diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig index be4caadbb0dc9..d83299c431cce 100644 --- a/eng/CodeAnalysis.src.globalconfig +++ b/eng/CodeAnalysis.src.globalconfig @@ -348,7 +348,7 @@ dotnet_diagnostic.CA1816.severity = none dotnet_diagnostic.CA1819.severity = none # CA1820: Test for empty strings using string length -dotnet_diagnostic.CA1820.severity = none +dotnet_diagnostic.CA1820.severity = suggestion # CA1821: Remove empty Finalizers dotnet_diagnostic.CA1821.severity = warning @@ -468,7 +468,7 @@ dotnet_diagnostic.CA1858.severity = warning # CA1859: Use concrete types when possible for improved performance dotnet_diagnostic.CA1859.severity = warning -# CA1860: Prefer Length/Count/IsEmpty property check over Any() +# CA1860: Avoid using 'Enumerable.Any()' extension method dotnet_diagnostic.CA1860.severity = warning # CA2000: Dispose objects before losing scope @@ -513,7 +513,7 @@ dotnet_diagnostic.CA2018.severity = warning # CA2019: Improper 'ThreadStatic' field initialization dotnet_diagnostic.CA2019.severity = warning -# CA2020: Prevent behavioral changes +# CA2020: Prevent behavioral change dotnet_diagnostic.CA2020.severity = warning # CA2021: Do not call Enumerable.Cast or Enumerable.OfType with incompatible types @@ -769,7 +769,7 @@ dotnet_diagnostic.CA3061.severity = warning # CA3075: Insecure DTD processing in XML dotnet_diagnostic.CA3075.severity = warning -# CA3076: Insecure XSLT script processing. +# CA3076: Insecure XSLT script processing dotnet_diagnostic.CA3076.severity = warning # CA3077: Insecure Processing in API Design, XmlDocument and XmlTextReader @@ -1659,6 +1659,15 @@ dotnet_diagnostic.IDE0241.severity = suggestion # IDE0250: Make struct readonly dotnet_diagnostic.IDE0250.severity = suggestion +# IDE0260: Use pattern matching +dotnet_diagnostic.IDE0260.severity = suggestion + +# IDE0270: Use coalesce expression +dotnet_diagnostic.IDE0270.severity = suggestion + +# IDE0280: Use 'nameof' +dotnet_diagnostic.IDE0280.severity = warning + # IDE1005: Delegate invocation can be simplified. dotnet_diagnostic.IDE1005.severity = warning diff --git a/eng/CodeAnalysis.test.globalconfig b/eng/CodeAnalysis.test.globalconfig index b64207eeaf669..84c7837a7e536 100644 --- a/eng/CodeAnalysis.test.globalconfig +++ b/eng/CodeAnalysis.test.globalconfig @@ -465,7 +465,7 @@ dotnet_diagnostic.CA1858.severity = none # CA1859: Use concrete types when possible for improved performance dotnet_diagnostic.CA1859.severity = none -# CA1860: Prefer Length/Count/IsEmpty property check over Any() +# CA1860: Avoid using 'Enumerable.Any()' extension method dotnet_diagnostic.CA1860.severity = none # CA2000: Dispose objects before losing scope @@ -510,7 +510,7 @@ dotnet_diagnostic.CA2018.severity = none # CA2019: Improper 'ThreadStatic' field initialization dotnet_diagnostic.CA2019.severity = none -# CA2020: Prevent behavioral changes +# CA2020: Prevent behavioral change dotnet_diagnostic.CA2020.severity = none # CA2021: Do not call Enumerable.Cast or Enumerable.OfType with incompatible types @@ -765,7 +765,7 @@ dotnet_diagnostic.CA3061.severity = none # CA3075: Insecure DTD processing in XML dotnet_diagnostic.CA3075.severity = none -# CA3076: Insecure XSLT script processing. +# CA3076: Insecure XSLT script processing dotnet_diagnostic.CA3076.severity = none # CA3077: Insecure Processing in API Design, XmlDocument and XmlTextReader @@ -1653,6 +1653,15 @@ dotnet_diagnostic.IDE0241.severity = silent # IDE0250: Make struct readonly dotnet_diagnostic.IDE0250.severity = silent +# IDE0260: Use pattern matching +dotnet_diagnostic.IDE0260.severity = silent + +# IDE0270: Use coalesce expression +dotnet_diagnostic.IDE0270.severity = silent + +# IDE0280: Use 'nameof' +dotnet_diagnostic.IDE0280.severity = silent + # IDE1005: Delegate invocation can be simplified. dotnet_diagnostic.IDE1005.severity = silent diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3fb11084dea6d..29e53e5552079 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,6 +1,6 @@ - + https://github.com/dotnet/icu 389d19d09d3cf16ec0143dba065fcd704ab8e48c @@ -85,9 +85,9 @@ 9a7551fa7ba8218affbc1148eabc4b5c9f4e1151 - + https://github.com/dotnet/emsdk - 07ca08d31022f545d37fbc8d1254d3441645fce2 + e4089ed2abe29bdc25bab2c261940175d0846824 diff --git a/eng/Versions.props b/eng/Versions.props index 7578f8e4bf072..1158e28fa9758 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -217,7 +217,7 @@ 0.11.4-alpha.23178.1 - 8.0.0-preview.4.23203.1 + 8.0.0-preview.4.23177.3 2.1.7 8.0.0-alpha.1.23180.2 @@ -236,7 +236,7 @@ Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-8_0_100_Transport --> - 8.0.0-preview.4.23205.3 + 8.0.0-preview.4.23177.1 $(MicrosoftNETWorkloadEmscriptenCurrentManifest80100TransportVersion) 1.1.87-gba258badda diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index e92ae5f615753..4d6f8a22c6cc4 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -70,10 +70,10 @@ resources: image: mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7 - container: browser_wasm - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-webassembly-net8-20230322221728-80fdceb + image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-webassembly-net8-20230327150025-4404b5c - container: wasi_wasm - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-webassembly-net8-20230322221804-80fdceb + image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-webassembly-net8-20230327150037-4404b5c - container: freebsd_x64 image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-freebsd-12 diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 32681c5466b01..6c6837a74938a 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -201,6 +201,6 @@ jobs: # Browser WebAssembly windows - ${{ if in(parameters.platform, 'browser_wasm_win', 'wasi_wasm_win') }}: - - (Windows.Amd64.Server2022.Open)windows.amd64.server2022.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2022-helix-webassembly-net8-20230319084205-80fdceb + - (Windows.Amd64.Server2022.Open)windows.amd64.server2022.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2022-helix-webassembly-net8-20230327150108-4404b5c ${{ insert }}: ${{ parameters.jobParameters }} diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml index 29b227a272729..c6d1624603fe1 100644 --- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml +++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml @@ -2,7 +2,7 @@ parameters: dependsOn: [] PublishRidAgnosticPackagesFromPlatform: '' isOfficialBuild: false - logArtifactName: 'Logs-PrepareSignedArtifacts' + logArtifactName: 'Logs-PrepareSignedArtifacts_Attempt$(System.JobAttempt)' jobs: - job: PrepareSignedArtifacts diff --git a/eng/testing/tests.singlefile.targets b/eng/testing/tests.singlefile.targets index 821e8f93750b4..6b869bd02c60a 100644 --- a/eng/testing/tests.singlefile.targets +++ b/eng/testing/tests.singlefile.targets @@ -23,7 +23,7 @@ $(CoreCLRILCompilerDir) - $(CoreCLRCrossILCompilerDir) + $(CoreCLRCrossILCompilerDir) $(ROOTFS_DIR) $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll $(CoreCLRAotSdkDir) @@ -36,6 +36,34 @@ true + + + + + $(RuntimeIdentifier) + + + x86_64 + aarch64 + arm64 + + + $(CrossCompileArch)-linux-gnu + $(CrossCompileArch)-alpine-linux-musl + $(CrossCompileArch)-unknown-freebsd12 + + + + + + + + + + + $(DefineConstants);SINGLE_FILE_TEST_RUNNER diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 3a0ceb80e6057..88003b8893500 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -7654,7 +7654,6 @@ void DacHandleWalker::WalkHandles() { if (mask & 1) { - dac_handle_table *pTable = hTable; PTR_AppDomain pDomain = AppDomain::GetCurrentDomain(); param.AppDomain = TO_CDADDR(pDomain.GetAddr()); param.Type = handleType; @@ -8285,3 +8284,234 @@ HRESULT DacStackReferenceErrorEnum::Next(unsigned int count, SOSStackRefError re *pFetched = i; return i < count ? S_FALSE : S_OK; } + + +HRESULT DacMemoryEnumerator::Skip(unsigned int count) +{ + mIteratorIndex += count; + return S_OK; +} + +HRESULT DacMemoryEnumerator::Reset() +{ + mIteratorIndex = 0; + return S_OK; +} + +HRESULT DacMemoryEnumerator::GetCount(unsigned int* pCount) +{ + if (!pCount) + return E_POINTER; + + mRegions.GetCount(); + return S_OK; +} + +HRESULT DacMemoryEnumerator::Next(unsigned int count, SOSMemoryRegion regions[], unsigned int* pFetched) +{ + if (!pFetched) + return E_POINTER; + + if (!regions) + return E_POINTER; + + unsigned int i = 0; + while (i < count && mIteratorIndex < mRegions.GetCount()) + { + regions[i++] = mRegions.Get(mIteratorIndex++); + } + + *pFetched = i; + return i < count ? S_FALSE : S_OK; +} + + +HRESULT DacGCBookkeepingEnumerator::Init() +{ + if (g_gcDacGlobals->bookkeeping_start == nullptr) + return E_FAIL; + + TADDR ctiAddr = TO_TADDR(*g_gcDacGlobals->bookkeeping_start); + if (ctiAddr == 0) + return E_FAIL; + + DPTR(dac_card_table_info) card_table_info(ctiAddr); + + SOSMemoryRegion mem = {0}; + if (card_table_info->recount && card_table_info->size) + { + mem.Start = card_table_info.GetAddr(); + mem.Size = card_table_info->size; + mRegions.Add(mem); + } + + size_t card_table_info_size = g_gcDacGlobals->card_table_info_size; + TADDR next = card_table_info->next_card_table; + + // Cap the number of regions we will walk in case we have run into some kind of + // memory corruption. We shouldn't have more than a few linked card tables anyway. + int maxRegions = 32; + + // This loop is effectively "while (next != 0)" but with an added check to make + // sure we don't underflow next when subtracting card_table_info_size if we encounter + // a bad pointer. + while (next > card_table_info_size) + { + DPTR(dac_card_table_info) ct(next - card_table_info_size); + + if (ct->recount && ct->size) + { + mem = {0}; + mem.Start = ct.GetAddr(); + mem.Size = ct->size; + mRegions.Add(mem); + } + + next = ct->next_card_table; + if (next == card_table_info->next_card_table) + break; + + if (--maxRegions <= 0) + break; + } + + return S_OK; +} + + +HRESULT DacHandleTableMemoryEnumerator::Init() +{ + int max_slots = 1; + +#ifdef FEATURE_SVR_GC + if (GCHeapUtilities::IsServerHeap()) + max_slots = GCHeapCount(); +#endif // FEATURE_SVR_GC + + // Cap the number of regions we will walk in case we hit an infinite loop due + // to memory corruption + int maxRegions = 8192; + + for (dac_handle_table_map *map = g_gcDacGlobals->handle_table_map; map && maxRegions >= 0; map = map->pNext, maxRegions--) + { + for (int i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE; ++i) + { + if (map->pBuckets[i] != NULL) + { + for (int j = 0; j < max_slots ; ++j) + { + DPTR(dac_handle_table) pTable = map->pBuckets[i]->pTable[j]; + DPTR(dac_handle_table_segment) pFirstSegment = pTable->pSegmentList; + DPTR(dac_handle_table_segment) curr = pFirstSegment; + + do + { + SOSMemoryRegion mem = {0}; + mem.Start = curr.GetAddr(); + mem.Size = HANDLE_SEGMENT_SIZE; + mem.Heap = j; // heap number + + mRegions.Add(mem); + + curr = curr->pNextSegment; + } while (curr != nullptr && curr != pFirstSegment); + } + } + } + } + + return S_OK; +} + +void DacFreeRegionEnumerator::AddSingleSegment(const dac_heap_segment &curr, FreeRegionKind kind, int heap) +{ + SOSMemoryRegion mem = {0}; + mem.Start = TO_CDADDR(curr.mem); + mem.ExtraData = (CLRDATA_ADDRESS)kind; + mem.Heap = heap; + + if (curr.mem < curr.committed) + mem.Size = TO_CDADDR(curr.committed) - mem.Start; + + if (mem.Start) + mRegions.Add(mem); +} + +void DacFreeRegionEnumerator::AddSegmentList(DPTR(dac_heap_segment) start, FreeRegionKind kind, int heap) +{ + int iterationMax = 2048; + + DPTR(dac_heap_segment) curr = start; + while (curr != nullptr) + { + AddSingleSegment(*curr, kind, heap); + + curr = curr->next; + if (curr == start) + break; + + if (iterationMax-- <= 0) + break; + } +} + +void DacFreeRegionEnumerator::AddFreeList(DPTR(dac_region_free_list) free_list, FreeRegionKind kind) +{ + if (free_list != nullptr) + { + AddSegmentList(free_list->head_free_region, kind); + } +} + +HRESULT DacFreeRegionEnumerator::Init() +{ + // Cap the number of free regions we will walk at a sensible number. This is to protect against + // memory corruption, un-initialized data, or just a bug. + int count_free_region_kinds = g_gcDacGlobals->count_free_region_kinds; + count_free_region_kinds = min(count_free_region_kinds, 16); + + unsigned int index = 0; + if (g_gcDacGlobals->global_free_huge_regions != nullptr) + { + DPTR(dac_region_free_list) global_free_huge_regions(g_gcDacGlobals->global_free_huge_regions); + AddFreeList(global_free_huge_regions, FreeRegionKind::FreeGlobalHugeRegion); + } + + if (g_gcDacGlobals->global_regions_to_decommit != nullptr) + { + DPTR(dac_region_free_list) regionList(g_gcDacGlobals->global_regions_to_decommit); + if (regionList != nullptr) + for (int i = 0; i < count_free_region_kinds; i++, regionList++) + AddFreeList(regionList, FreeRegionKind::FreeGlobalRegion); + } + +#if defined(FEATURE_SVR_GC) + if (GCHeapUtilities::IsServerHeap()) + { + AddServerRegions(); + } + else +#endif //FEATURE_SVR_GC + { + DPTR(dac_region_free_list) regionList(g_gcDacGlobals->free_regions); + if (regionList != nullptr) + for (int i = 0; i < count_free_region_kinds; i++, regionList++) + AddFreeList(regionList, FreeRegionKind::FreeRegion); + + if (g_gcDacGlobals->freeable_soh_segment != nullptr) + { + DPTR(DPTR(dac_heap_segment)) freeable_soh_segment_ptr(g_gcDacGlobals->freeable_soh_segment); + if (freeable_soh_segment_ptr != nullptr) + AddSegmentList(*freeable_soh_segment_ptr, FreeRegionKind::FreeSohSegment); + } + + if (g_gcDacGlobals->freeable_uoh_segment != nullptr) + { + DPTR(DPTR(dac_heap_segment)) freeable_uoh_segment_ptr(g_gcDacGlobals->freeable_uoh_segment); + if (freeable_uoh_segment_ptr != nullptr) + AddSegmentList(*freeable_uoh_segment_ptr, FreeRegionKind::FreeUohSegment); + } + } + + return S_OK; +} diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 52ef9cf5979d9..ddf61370f416e 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -1211,6 +1211,10 @@ class ClrDataAccess virtual HRESULT STDMETHODCALLTYPE GetDomainLoaderAllocator(CLRDATA_ADDRESS domainAddress, CLRDATA_ADDRESS *pLoaderAllocator); virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocatorHeapNames(int count, const char **ppNames, int *pNeeded); virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocatorHeaps(CLRDATA_ADDRESS loaderAllocator, int count, CLRDATA_ADDRESS *pLoaderHeaps, LoaderHeapKind *pKinds, int *pNeeded); + virtual HRESULT STDMETHODCALLTYPE GetHandleTableMemoryRegions(ISOSMemoryEnum **ppEnum); + virtual HRESULT STDMETHODCALLTYPE GetGCBookkeepingMemoryRegions(ISOSMemoryEnum **ppEnum); + virtual HRESULT STDMETHODCALLTYPE GetGCFreeRegions(ISOSMemoryEnum **ppEnum); + virtual HRESULT STDMETHODCALLTYPE LockedFlush(); // // ClrDataAccess. @@ -1954,6 +1958,56 @@ class DacReferenceList unsigned int _capacity; }; + +class DacMemoryEnumerator : public DefaultCOMImpl +{ +public: + DacMemoryEnumerator() + : mIteratorIndex(0) + { + } + + virtual ~DacMemoryEnumerator() {} + virtual HRESULT Init() = 0; + + HRESULT STDMETHODCALLTYPE Skip(unsigned int count); + HRESULT STDMETHODCALLTYPE Reset(); + HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount); + HRESULT STDMETHODCALLTYPE Next(unsigned int count, + SOSMemoryRegion regions[], + unsigned int *pFetched); + +protected: + DacReferenceList mRegions; + +private: + unsigned int mIteratorIndex; +}; + +class DacHandleTableMemoryEnumerator : public DacMemoryEnumerator +{ +public: + virtual HRESULT Init(); +}; + +class DacGCBookkeepingEnumerator : public DacMemoryEnumerator +{ +public: + virtual HRESULT Init(); +}; + +class DacFreeRegionEnumerator : public DacMemoryEnumerator +{ +public: + virtual HRESULT Init(); + +private: + void AddSingleSegment(const dac_heap_segment &seg, FreeRegionKind kind, int heap); + void AddSegmentList(DPTR(dac_heap_segment) seg, FreeRegionKind kind, int heap = 0); + void AddFreeList(DPTR(dac_region_free_list) freeList, FreeRegionKind kind); + void AddServerRegions(); +}; + struct DacGcReference; /* DacStackReferenceWalker. */ diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index b5a0aa1986bd2..9ccb7d6272442 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -5295,3 +5295,95 @@ HRESULT ClrDataAccess::GetGlobalAllocationContext( SOSDacLeave(); return hr; } + +HRESULT ClrDataAccess::GetHandleTableMemoryRegions(ISOSMemoryEnum** ppEnum) +{ + if (!ppEnum) + return E_POINTER; + + SOSDacEnter(); + + DacHandleTableMemoryEnumerator* htEnum = new (nothrow) DacHandleTableMemoryEnumerator(); + if (htEnum) + { + hr = htEnum->Init(); + + if (SUCCEEDED(hr)) + hr = htEnum->QueryInterface(__uuidof(ISOSMemoryEnum), (void**)ppEnum); + + if (FAILED(hr)) + delete htEnum; + } + else + { + hr = E_OUTOFMEMORY; + } + + SOSDacLeave(); + return hr; +} + +HRESULT ClrDataAccess::GetGCBookkeepingMemoryRegions(ISOSMemoryEnum** ppEnum) +{ + if (!ppEnum) + return E_POINTER; + + SOSDacEnter(); + + DacGCBookkeepingEnumerator* bkEnum = new (nothrow) DacGCBookkeepingEnumerator(); + if (bkEnum) + { + hr = bkEnum->Init(); + + if (SUCCEEDED(hr)) + hr = bkEnum->QueryInterface(__uuidof(ISOSMemoryEnum), (void**)ppEnum); + + if (FAILED(hr)) + delete bkEnum; + } + else + { + hr = E_OUTOFMEMORY; + } + + SOSDacLeave(); + return hr; +} + + +HRESULT ClrDataAccess::GetGCFreeRegions(ISOSMemoryEnum **ppEnum) +{ + if (!ppEnum) + return E_POINTER; + + SOSDacEnter(); + + DacFreeRegionEnumerator* frEnum = new (nothrow) DacFreeRegionEnumerator(); + if (frEnum) + { + hr = frEnum->Init(); + + if (SUCCEEDED(hr)) + hr = frEnum->QueryInterface(__uuidof(ISOSMemoryEnum), (void**)ppEnum); + + if (FAILED(hr)) + delete frEnum; + } + else + { + hr = E_OUTOFMEMORY; + } + + SOSDacLeave(); + return hr; +} + +HRESULT ClrDataAccess::LockedFlush() +{ + SOSDacEnter(); + + Flush(); + + SOSDacLeave(); + return hr; +} diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index e59255a4e5a68..3955d8f05db5c 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -459,4 +459,26 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) return S_OK; } +void DacFreeRegionEnumerator::AddServerRegions() +{ + // Cap the number of free regions we will walk at a sensible number. This is to protect against + // memory corruption, un-initialized data, or just a bug. + int count_free_region_kinds = g_gcDacGlobals->count_free_region_kinds; + count_free_region_kinds = min(count_free_region_kinds, 16); + + for (int i = 0; i < GCHeapCount(); i++) + { + TADDR heapAddress = (TADDR)HeapTableIndex(g_gcDacGlobals->g_heaps, i); + if (heapAddress == 0) + continue; + + dac_gc_heap heap = LoadGcHeapData(heapAddress); + for (int i = 0; i < count_free_region_kinds; i++) + AddSegmentList(heap.free_regions[i].head_free_region, FreeRegionKind::FreeRegion, i); + + AddSegmentList(heap.freeable_soh_segment, FreeRegionKind::FreeSohSegment, i); + AddSegmentList(heap.freeable_uoh_segment, FreeRegionKind::FreeUohSegment, i); + } +} + #endif // defined(FEATURE_SVR_GC) diff --git a/src/coreclr/debug/inc/dbgtargetcontext.h b/src/coreclr/debug/inc/dbgtargetcontext.h index fa6c7b92cb884..7f035463361d1 100644 --- a/src/coreclr/debug/inc/dbgtargetcontext.h +++ b/src/coreclr/debug/inc/dbgtargetcontext.h @@ -560,6 +560,7 @@ typedef DECLSPEC_ALIGN(16) struct { // /* +0x000 */ DWORD ContextFlags; + /* +0x004 */ DWORD Fcsr; // // Integer registers diff --git a/src/coreclr/gc/dac_gcheap_fields.h b/src/coreclr/gc/dac_gcheap_fields.h index 104157261635a..37b6389ff1ea1 100644 --- a/src/coreclr/gc/dac_gcheap_fields.h +++ b/src/coreclr/gc/dac_gcheap_fields.h @@ -10,23 +10,34 @@ DEFINE_FIELD (internal_root_array, uint8_t*) DEFINE_FIELD (internal_root_array_index, size_t) DEFINE_FIELD (heap_analyze_success, BOOL) DEFINE_FIELD (card_table, uint32_t*) + #if defined(ALL_FIELDS) || defined(BACKGROUND_GC) DEFINE_FIELD (mark_array, uint32_t*) DEFINE_FIELD (next_sweep_obj, uint8_t*) DEFINE_FIELD (background_saved_lowest_address, uint8_t*) DEFINE_FIELD (background_saved_highest_address, uint8_t*) +DEFINE_DPTR_FIELD (freeable_soh_segment, dac_heap_segment) +DEFINE_DPTR_FIELD (freeable_uoh_segment, dac_heap_segment) #if defined(ALL_FIELDS) || !defined(USE_REGIONS) DEFINE_DPTR_FIELD (saved_sweep_ephemeral_seg, dac_heap_segment) DEFINE_FIELD (saved_sweep_ephemeral_start, uint8_t*) #else DEFINE_MISSING_FIELD(saved_sweep_ephemeral_seg) DEFINE_MISSING_FIELD(saved_sweep_ephemeral_start) -#endif +#endif // defined(ALL_FIELDS) || !defined(USE_REGIONS) #else DEFINE_MISSING_FIELD(mark_array) DEFINE_MISSING_FIELD(next_sweep_obj) DEFINE_MISSING_FIELD(background_saved_lowest_address) DEFINE_MISSING_FIELD(background_saved_highest_address) +DEFINE_MISSING_FIELD(freeable_soh_segment) +DEFINE_MISSING_FIELD(freeable_uoh_segment) DEFINE_MISSING_FIELD(saved_sweep_ephemeral_seg) DEFINE_MISSING_FIELD(saved_sweep_ephemeral_start) -#endif +#endif // defined(ALL_FIELDS) || defined(BACKGROUND_GC) + +#if defined(ALL_FIELDS) || defined(USE_REGIONS) +DEFINE_ARRAY_FIELD (free_regions, dac_region_free_list, FREE_REGION_KINDS) +#else +DEFINE_MISSING_FIELD(free_regions) +#endif // ALL_FIELDS diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 474e041974cf9..358f803887e35 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -2228,8 +2228,8 @@ size_t gc_heap::g_bpromoted; #endif //MULTIPLE_HEAPS size_t gc_heap::card_table_element_layout[total_bookkeeping_elements + 1]; +uint8_t* gc_heap::bookkeeping_start = nullptr; #ifdef USE_REGIONS -uint8_t* gc_heap::bookkeeping_covered_start = nullptr; uint8_t* gc_heap::bookkeeping_covered_committed = nullptr; size_t gc_heap::bookkeeping_sizes[total_bookkeeping_elements]; #endif //USE_REGIONS @@ -8378,6 +8378,9 @@ class card_table_info { public: unsigned recount; + size_t size; + uint32_t* next_card_table; + uint8_t* lowest_address; uint8_t* highest_address; short* brick_table; @@ -8391,11 +8394,11 @@ class card_table_info #ifdef BACKGROUND_GC uint32_t* mark_array; #endif //BACKGROUND_GC - - size_t size; - uint32_t* next_card_table; }; +static_assert(offsetof(dac_card_table_info, size) == offsetof(card_table_info, size), "DAC card_table_info layout mismatch"); +static_assert(offsetof(dac_card_table_info, next_card_table) == offsetof(card_table_info, next_card_table), "DAC card_table_info layout mismatch"); + //These are accessors on untranslated cardtable inline unsigned& card_table_refcount (uint32_t* c_table) @@ -8623,6 +8626,9 @@ void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end) inline uint32_t*& card_table_next (uint32_t* c_table) { + // NOTE: The dac takes a dependency on card_table_info being right before c_table. + // It's 100% ok to change this implementation detail as long as a matching change + // is made to DacGCBookkeepingEnumerator::Init in daccess.cpp. return ((card_table_info*)((uint8_t*)c_table - sizeof (card_table_info)))->next_card_table; } @@ -8907,21 +8913,21 @@ bool gc_heap::inplace_commit_card_table (uint8_t* from, uint8_t* to) uint8_t* commit_end = nullptr; if (initial_commit) { - required_begin = bookkeeping_covered_start + ((i == card_table_element) ? 0 : card_table_element_layout[i]); - required_end = bookkeeping_covered_start + card_table_element_layout[i] + new_sizes[i]; + required_begin = bookkeeping_start + ((i == card_table_element) ? 0 : card_table_element_layout[i]); + required_end = bookkeeping_start + card_table_element_layout[i] + new_sizes[i]; commit_begin = align_lower_page(required_begin); } else { assert (additional_commit); - required_begin = bookkeeping_covered_start + card_table_element_layout[i] + bookkeeping_sizes[i]; + required_begin = bookkeeping_start + card_table_element_layout[i] + bookkeeping_sizes[i]; required_end = required_begin + new_sizes[i] - bookkeeping_sizes[i]; commit_begin = align_on_page(required_begin); } assert (required_begin <= required_end); commit_end = align_on_page(required_end); - commit_end = min (commit_end, align_lower_page(bookkeeping_covered_start + card_table_element_layout[i + 1])); + commit_end = min (commit_end, align_lower_page(bookkeeping_start + card_table_element_layout[i + 1])); commit_begin = min (commit_begin, commit_end); assert (commit_begin <= commit_end); @@ -8996,9 +9002,7 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) size_t alloc_size = card_table_element_layout[total_bookkeeping_elements]; uint8_t* mem = (uint8_t*)GCToOSInterface::VirtualReserve (alloc_size, 0, virtual_reserve_flags); -#ifdef USE_REGIONS - bookkeeping_covered_start = mem; -#endif //USE_REGIONS + bookkeeping_start = mem; if (!mem) return 0; @@ -9495,6 +9499,8 @@ void gc_heap::copy_brick_card_table() uint32_t* ct = &g_gc_card_table[card_word (gcard_of (g_gc_lowest_address))]; own_card_table (ct); card_table = translate_card_table (ct); + bookkeeping_start = (uint8_t*)ct - sizeof(card_table_info); + card_table_size(ct) = card_table_element_layout[total_bookkeeping_elements]; /* End of global lock */ highest_address = card_table_highest_address (ct); lowest_address = card_table_lowest_address (ct); @@ -13728,8 +13734,6 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, &g_gc_lowest_address, &g_gc_highest_address)) return E_OUTOFMEMORY; - bookkeeping_covered_start = global_region_allocator.get_start(); - if (!allocate_initial_regions(number_of_heaps)) return E_OUTOFMEMORY; } @@ -49291,13 +49295,20 @@ void PopulateDacVars(GcDacVars *gcDacVars) assert(gcDacVars != nullptr); *gcDacVars = {}; - // Note: these version numbers are not actually checked by SOS, so if you change - // the GC in a way that makes it incompatible with SOS, please change - // SOS_BREAKING_CHANGE_VERSION in both the runtime and the diagnostics repo - gcDacVars->major_version_number = 1; + // Note: These version numbers do not need to be checked in the .Net dac/SOS because + // we always match the compiled dac and GC to the version used. NativeAOT's SOS may + // work differently than .Net SOS. When making breaking changes here you may need to + // find NativeAOT's equivalent of SOS_BREAKING_CHANGE_VERSION and increment it. + gcDacVars->major_version_number = 2; gcDacVars->minor_version_number = 0; + gcDacVars->total_bookkeeping_elements = total_bookkeeping_elements; + gcDacVars->card_table_info_size = sizeof(card_table_info); + #ifdef USE_REGIONS gcDacVars->minor_version_number |= 1; + gcDacVars->count_free_region_kinds = count_free_region_kinds; + gcDacVars->global_regions_to_decommit = reinterpret_cast(&gc_heap::global_regions_to_decommit); + gcDacVars->global_free_huge_regions = reinterpret_cast(&gc_heap::global_free_huge_regions); #endif //USE_REGIONS #ifndef BACKGROUND_GC gcDacVars->minor_version_number |= 2; @@ -49315,10 +49326,15 @@ void PopulateDacVars(GcDacVars *gcDacVars) #endif //BACKGROUND_GC #ifndef MULTIPLE_HEAPS gcDacVars->ephemeral_heap_segment = reinterpret_cast(&gc_heap::ephemeral_heap_segment); +#ifdef USE_REGIONS + gcDacVars->free_regions = reinterpret_cast(&gc_heap::free_regions); +#endif #ifdef BACKGROUND_GC gcDacVars->mark_array = &gc_heap::mark_array; gcDacVars->background_saved_lowest_address = &gc_heap::background_saved_lowest_address; gcDacVars->background_saved_highest_address = &gc_heap::background_saved_highest_address; + gcDacVars->freeable_soh_segment = reinterpret_cast(&gc_heap::freeable_soh_segment); + gcDacVars->freeable_uoh_segment = reinterpret_cast(&gc_heap::freeable_uoh_segment); gcDacVars->next_sweep_obj = &gc_heap::next_sweep_obj; #ifdef USE_REGIONS gcDacVars->saved_sweep_ephemeral_seg = 0; @@ -49331,6 +49347,8 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->mark_array = 0; gcDacVars->background_saved_lowest_address = 0; gcDacVars->background_saved_highest_address = 0; + gcDacVars->freeable_soh_segment = 0; + gcDacVars->freeable_uoh_segment = 0; gcDacVars->next_sweep_obj = 0; gcDacVars->saved_sweep_ephemeral_seg = 0; gcDacVars->saved_sweep_ephemeral_start = 0; @@ -49357,4 +49375,5 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->gc_heap_field_offsets = reinterpret_cast(&gc_heap_field_offsets); #endif // MULTIPLE_HEAPS gcDacVars->generation_field_offsets = reinterpret_cast(&generation_field_offsets); + gcDacVars->bookkeeping_start = &gc_heap::bookkeeping_start; } diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index cfe968b74624b..3eb66a61a003a 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -16,16 +16,17 @@ #define MAX_EXPAND_MECHANISMS_COUNT 6 #define MAX_GC_MECHANISM_BITS_COUNT 2 #define MAX_GLOBAL_GC_MECHANISMS_COUNT 6 +#define FREE_REGION_KINDS 3 // The number of generations is hardcoded in to the dac APIS (DacpGcHeapDetails hard codes the size of its arrays) // The number of generations is hardcoded into some older dac APIS (for example DacpGcHeapDetails hard codes the size of its arrays) // This value cannot change and should not be used in new DAC APIs. New APIs can query GcDacVars.total_generation_count // variable which is dynamically initialized at runtime - #define NUMBERGENERATIONS 4 -#define INITIAL_HANDLE_TABLE_ARRAY_SIZE 10 -#define HANDLE_MAX_INTERNAL_TYPES 12 + + +#include "handletableconstants.h" // Analogue for the GC heap_segment class, containing information regarding a single // heap segment. @@ -42,6 +43,17 @@ class dac_heap_segment { class dac_gc_heap* heap; }; +class dac_region_free_list { +public: + size_t num_free_regions; + size_t size_free_regions; + size_t size_committed_in_free_regions; + size_t num_free_regions_added; + size_t num_free_regions_removed; + DPTR(dac_heap_segment) head_free_region; + DPTR(dac_heap_segment) tail_free_region; +}; + // Analogue for the GC generation class, containing information about the start segment // of a generation and its allocation context. class dac_generation { @@ -49,12 +61,14 @@ class dac_generation { #define ALL_FIELDS #define DEFINE_FIELD(field_name, field_type) field_type field_name; #define DEFINE_DPTR_FIELD(field_name, field_type) DPTR(field_type) field_name; +#define DEFINE_MISSING_FIELD(field_name) #include "dac_generation_fields.h" #undef DEFINE_DPTR_FIELD #undef DEFINE_FIELD #undef ALL_FIELDS +#undef DEFINE_MISSING_FIELD }; // Analogue for the GC CFinalize class, containing information about the finalize queue. @@ -64,6 +78,21 @@ class dac_finalize_queue { uint8_t** m_FillPointers[NUMBERGENERATIONS + ExtraSegCount]; }; +class dac_handle_table_segment { +public: + uint8_t rgGeneration[HANDLE_BLOCKS_PER_SEGMENT * sizeof(uint32_t) / sizeof(uint8_t)]; + uint8_t rgAllocation[HANDLE_BLOCKS_PER_SEGMENT]; + uint32_t rgFreeMask[HANDLE_MASKS_PER_SEGMENT]; + uint8_t rgBlockType[HANDLE_BLOCKS_PER_SEGMENT]; + uint8_t rgUserData[HANDLE_BLOCKS_PER_SEGMENT]; + uint8_t rgLocks[HANDLE_BLOCKS_PER_SEGMENT]; + uint8_t rgTail[HANDLE_MAX_INTERNAL_TYPES]; + uint8_t rgHint[HANDLE_MAX_INTERNAL_TYPES]; + uint32_t rgFreeCount[HANDLE_MAX_INTERNAL_TYPES]; + DPTR(dac_handle_table_segment) pNextSegment; + }; + + class dac_handle_table { public: // We do try to keep everything that the DAC knows about as close to the @@ -71,6 +100,7 @@ class dac_handle_table { // HandleTable has rgTypeFlags at offset 0 for performance reasons and // we don't want to disrupt that. uint32_t padding[HANDLE_MAX_INTERNAL_TYPES]; + DPTR(dac_handle_table_segment) pSegmentList; }; class dac_handle_table_bucket { @@ -86,6 +116,13 @@ class dac_handle_table_map { uint32_t dwMaxIndex; }; +class dac_card_table_info { +public: + unsigned recount; + size_t size; + TADDR next_card_table; +}; + // Possible values of the current_c_gc_state dacvar, indicating the state of // a background GC. enum c_gc_state @@ -111,7 +148,7 @@ enum oom_reason /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ /* If you modify failure_get_memory and */ /* oom_reason be sure to make the corresponding */ -/* changes in tools\sos\strike\strike.cpp. */ +/* changes in ClrMD. */ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ enum failure_get_memory { @@ -168,7 +205,7 @@ class dac_gc_heap { dac_generation generation_table[1]; }; -#define GENERATION_TABLE_FIELD_INDEX 18 +#define GENERATION_TABLE_FIELD_INDEX 21 // Unlike other DACized structures, these types are loaded manually in the debugger. // To avoid misuse, pointers to them are explicitly casted to these unused type. @@ -209,6 +246,9 @@ struct GcDacVars { uint8_t minor_version_number; size_t generation_size; size_t total_generation_count; + int total_bookkeeping_elements; + int count_free_region_kinds; + size_t card_table_info_size; #ifdef DACCESS_COMPILE #define GC_DAC_VAR(type, name) DPTR(type) name; #define GC_DAC_PTR_VAR(type, name) DPTR(type*) name; diff --git a/src/coreclr/gc/gcinterface.dacvars.def b/src/coreclr/gc/gcinterface.dacvars.def index a78852a09a220..f9e0eb4be7e3b 100644 --- a/src/coreclr/gc/gcinterface.dacvars.def +++ b/src/coreclr/gc/gcinterface.dacvars.def @@ -42,6 +42,8 @@ GC_DAC_PTR_VAR (uint32_t, mark_array) GC_DAC_VAR (c_gc_state, current_c_gc_state) GC_DAC_PTR_VAR (dac_heap_segment, ephemeral_heap_segment) GC_DAC_PTR_VAR (dac_heap_segment, saved_sweep_ephemeral_seg) +GC_DAC_PTR_VAR (dac_heap_segment, freeable_soh_segment) +GC_DAC_PTR_VAR (dac_heap_segment, freeable_uoh_segment) GC_DAC_PTR_VAR (uint8_t, saved_sweep_ephemeral_start) GC_DAC_PTR_VAR (uint8_t, background_saved_lowest_address) GC_DAC_PTR_VAR (uint8_t, background_saved_highest_address) @@ -62,6 +64,10 @@ GC_DAC_ARRAY_VAR (size_t, interesting_mechanism_bits_per_heap) GC_DAC_VAR (dac_handle_table_map, handle_table_map) GC_DAC_ARRAY_VAR (int, gc_heap_field_offsets) GC_DAC_ARRAY_VAR (int, generation_field_offsets) +GC_DAC_PTR_VAR (uint8_t, bookkeeping_start) +GC_DAC_ARRAY_VAR (dac_region_free_list, global_regions_to_decommit) +GC_DAC_PTR_VAR (dac_region_free_list, global_free_huge_regions) +GC_DAC_ARRAY_VAR (dac_region_free_list, free_regions) #undef GC_DAC_VAR #undef GC_DAC_ARRAY_VAR diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 3ca72125148d2..d72c9495dd8ea 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -1343,6 +1343,8 @@ enum free_region_kind count_free_region_kinds, }; +static_assert(count_free_region_kinds == FREE_REGION_KINDS, "Keep count_free_region_kinds in sync with FREE_REGION_KINDS, changing this is not a version breaking change."); + class region_free_list { size_t num_free_regions; @@ -1379,6 +1381,8 @@ class region_free_list void sort_by_committed_and_age(); static bool is_on_free_list (heap_segment* region, region_free_list free_list[count_free_region_kinds]); }; + +static_assert(sizeof(region_free_list) == sizeof(dac_region_free_list), "The DAC relies on the size of these two types matching for pointer arithmetic."); #endif enum bookkeeping_element @@ -4192,10 +4196,10 @@ class gc_heap #endif //BGC_SERVO_TUNING #endif //BACKGROUND_GC + PER_HEAP_ISOLATED_FIELD_INIT_ONLY uint8_t* bookkeeping_start; #ifdef USE_REGIONS PER_HEAP_ISOLATED_FIELD_INIT_ONLY size_t regions_range; PER_HEAP_ISOLATED_FIELD_INIT_ONLY bool enable_special_regions_p; - PER_HEAP_ISOLATED_FIELD_INIT_ONLY uint8_t* bookkeeping_covered_start; #else //USE_REGIONS PER_HEAP_ISOLATED_FIELD_INIT_ONLY size_t eph_gen_starts_size; PER_HEAP_ISOLATED_FIELD_INIT_ONLY size_t min_segment_size; diff --git a/src/coreclr/gc/handletableconstants.h b/src/coreclr/gc/handletableconstants.h new file mode 100644 index 0000000000000..0d6e678f2aebc --- /dev/null +++ b/src/coreclr/gc/handletableconstants.h @@ -0,0 +1,117 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +#ifndef __HANDLETABLECONSTANTS_H__ +#define __HANDLETABLECONSTANTS_H__ + + // Build support for async pinned handles into standalone GC to make it usable with older runtimes +#if defined(BUILD_AS_STANDALONE) && !defined(FEATURE_NATIVEAOT) +#define FEATURE_ASYNC_PINNED_HANDLES +#endif + +#define INITIAL_HANDLE_TABLE_ARRAY_SIZE 10 +#define HANDLE_MAX_INTERNAL_TYPES 12 + +/*--------------------------------------------------------------------------*/ + +//@TODO: find a home for this in a project-level header file +#ifndef BITS_PER_BYTE +#define BITS_PER_BYTE (8) +#endif +/*--------------------------------------------------------------------------*/ + + + +/**************************************************************************** + * + * MAJOR TABLE DEFINITIONS THAT CHANGE DEPENDING ON THE WEATHER + * + ****************************************************************************/ + +// 64k reserved per segment with 4k as header. +#define HANDLE_SEGMENT_SIZE (0x10000) // MUST be a power of 2 (and currently must be 64K due to VirtualAlloc semantics) +#define HANDLE_HEADER_SIZE (0x1000) // SHOULD be <= OS page size + +#define HANDLE_SEGMENT_ALIGNMENT HANDLE_SEGMENT_SIZE + + +#if !BIGENDIAN + + // little-endian write barrier mask manipulation + #define GEN_CLUMP_0_MASK (0x000000FF) + #define NEXT_CLUMP_IN_MASK(dw) ((dw) >> BITS_PER_BYTE) + +#else + + // big-endian write barrier mask manipulation + #define GEN_CLUMP_0_MASK (0xFF000000) + #define NEXT_CLUMP_IN_MASK(dw) ((dw) << BITS_PER_BYTE) + +#endif + + +// if the above numbers change than these will likely change as well +#define HANDLE_HANDLES_PER_CLUMP (16) // segment write-barrier granularity +#define HANDLE_HANDLES_PER_BLOCK (64) // segment suballocation granularity +#define HANDLE_OPTIMIZE_FOR_64_HANDLE_BLOCKS // flag for certain optimizations + +// number of types allowed for public callers +#define HANDLE_MAX_PUBLIC_TYPES (HANDLE_MAX_INTERNAL_TYPES - 1) // reserve one internal type + +// internal block types +#define HNDTYPE_INTERNAL_DATABLOCK (HANDLE_MAX_INTERNAL_TYPES - 1) // reserve last type for data blocks + +// max number of generations to support statistics on +#define MAXSTATGEN (5) + +/*--------------------------------------------------------------------------*/ + + + +/**************************************************************************** + * + * MORE DEFINITIONS + * + ****************************************************************************/ + +// fast handle-to-segment mapping +#define HANDLE_SEGMENT_CONTENT_MASK (HANDLE_SEGMENT_SIZE - 1) +#define HANDLE_SEGMENT_ALIGN_MASK (~HANDLE_SEGMENT_CONTENT_MASK) + +// table layout metrics +#define HANDLE_SIZE sizeof(_UNCHECKED_OBJECTREF) +#define HANDLE_HANDLES_PER_SEGMENT ((HANDLE_SEGMENT_SIZE - HANDLE_HEADER_SIZE) / HANDLE_SIZE) +#define HANDLE_BLOCKS_PER_SEGMENT (HANDLE_HANDLES_PER_SEGMENT / HANDLE_HANDLES_PER_BLOCK) +#define HANDLE_CLUMPS_PER_SEGMENT (HANDLE_HANDLES_PER_SEGMENT / HANDLE_HANDLES_PER_CLUMP) +#define HANDLE_CLUMPS_PER_BLOCK (HANDLE_HANDLES_PER_BLOCK / HANDLE_HANDLES_PER_CLUMP) +#define HANDLE_BYTES_PER_BLOCK (HANDLE_HANDLES_PER_BLOCK * HANDLE_SIZE) +#define HANDLE_HANDLES_PER_MASK (sizeof(uint32_t) * BITS_PER_BYTE) +#define HANDLE_MASKS_PER_SEGMENT (HANDLE_HANDLES_PER_SEGMENT / HANDLE_HANDLES_PER_MASK) +#define HANDLE_MASKS_PER_BLOCK (HANDLE_HANDLES_PER_BLOCK / HANDLE_HANDLES_PER_MASK) +#define HANDLE_CLUMPS_PER_MASK (HANDLE_HANDLES_PER_MASK / HANDLE_HANDLES_PER_CLUMP) + +// We use this relation to check for free mask per block. +C_ASSERT (HANDLE_HANDLES_PER_MASK * 2 == HANDLE_HANDLES_PER_BLOCK); + + +// cache layout metrics +#define HANDLE_CACHE_TYPE_SIZE 128 // 128 == 63 handles per bank +#define HANDLES_PER_CACHE_BANK ((HANDLE_CACHE_TYPE_SIZE / 2) - 1) + +// cache policy defines +#define REBALANCE_TOLERANCE (HANDLES_PER_CACHE_BANK / 3) +#define REBALANCE_LOWATER_MARK (HANDLES_PER_CACHE_BANK - REBALANCE_TOLERANCE) +#define REBALANCE_HIWATER_MARK (HANDLES_PER_CACHE_BANK + REBALANCE_TOLERANCE) + +// bulk alloc policy defines +#define SMALL_ALLOC_COUNT (HANDLES_PER_CACHE_BANK / 10) + +// misc constants +#define MASK_FULL (0) +#define MASK_EMPTY (0xFFFFFFFF) +#define MASK_LOBYTE (0x000000FF) +#define TYPE_INVALID ((uint8_t)0xFF) +#define BLOCK_INVALID ((uint8_t)0xFF) + +/*--------------------------------------------------------------------------*/ + +#endif // __HANDLETABLECONSTANTS_H__ diff --git a/src/coreclr/gc/handletablepriv.h b/src/coreclr/gc/handletablepriv.h index 4c05538996343..086ef2e018b6f 100644 --- a/src/coreclr/gc/handletablepriv.h +++ b/src/coreclr/gc/handletablepriv.h @@ -14,113 +14,7 @@ #include "handletable.h" - - // Build support for async pinned handles into standalone GC to make it usable with older runtimes -#if defined(BUILD_AS_STANDALONE) && !defined(FEATURE_NATIVEAOT) -#define FEATURE_ASYNC_PINNED_HANDLES -#endif - - -/*--------------------------------------------------------------------------*/ - -//@TODO: find a home for this in a project-level header file -#define BITS_PER_BYTE (8) -/*--------------------------------------------------------------------------*/ - - - -/**************************************************************************** - * - * MAJOR TABLE DEFINITIONS THAT CHANGE DEPENDING ON THE WEATHER - * - ****************************************************************************/ - -// 64k reserved per segment with 4k as header. -#define HANDLE_SEGMENT_SIZE (0x10000) // MUST be a power of 2 (and currently must be 64K due to VirtualAlloc semantics) -#define HANDLE_HEADER_SIZE (0x1000) // SHOULD be <= OS page size - -#define HANDLE_SEGMENT_ALIGNMENT HANDLE_SEGMENT_SIZE - - -#if !BIGENDIAN - - // little-endian write barrier mask manipulation - #define GEN_CLUMP_0_MASK (0x000000FF) - #define NEXT_CLUMP_IN_MASK(dw) ((dw) >> BITS_PER_BYTE) - -#else - - // big-endian write barrier mask manipulation - #define GEN_CLUMP_0_MASK (0xFF000000) - #define NEXT_CLUMP_IN_MASK(dw) ((dw) << BITS_PER_BYTE) - -#endif - - -// if the above numbers change than these will likely change as well -#define HANDLE_HANDLES_PER_CLUMP (16) // segment write-barrier granularity -#define HANDLE_HANDLES_PER_BLOCK (64) // segment suballocation granularity -#define HANDLE_OPTIMIZE_FOR_64_HANDLE_BLOCKS // flag for certain optimizations - -// number of types allowed for public callers -#define HANDLE_MAX_PUBLIC_TYPES (HANDLE_MAX_INTERNAL_TYPES - 1) // reserve one internal type - -// internal block types -#define HNDTYPE_INTERNAL_DATABLOCK (HANDLE_MAX_INTERNAL_TYPES - 1) // reserve last type for data blocks - -// max number of generations to support statistics on -#define MAXSTATGEN (5) - -/*--------------------------------------------------------------------------*/ - - - -/**************************************************************************** - * - * MORE DEFINITIONS - * - ****************************************************************************/ - -// fast handle-to-segment mapping -#define HANDLE_SEGMENT_CONTENT_MASK (HANDLE_SEGMENT_SIZE - 1) -#define HANDLE_SEGMENT_ALIGN_MASK (~HANDLE_SEGMENT_CONTENT_MASK) - -// table layout metrics -#define HANDLE_SIZE sizeof(_UNCHECKED_OBJECTREF) -#define HANDLE_HANDLES_PER_SEGMENT ((HANDLE_SEGMENT_SIZE - HANDLE_HEADER_SIZE) / HANDLE_SIZE) -#define HANDLE_BLOCKS_PER_SEGMENT (HANDLE_HANDLES_PER_SEGMENT / HANDLE_HANDLES_PER_BLOCK) -#define HANDLE_CLUMPS_PER_SEGMENT (HANDLE_HANDLES_PER_SEGMENT / HANDLE_HANDLES_PER_CLUMP) -#define HANDLE_CLUMPS_PER_BLOCK (HANDLE_HANDLES_PER_BLOCK / HANDLE_HANDLES_PER_CLUMP) -#define HANDLE_BYTES_PER_BLOCK (HANDLE_HANDLES_PER_BLOCK * HANDLE_SIZE) -#define HANDLE_HANDLES_PER_MASK (sizeof(uint32_t) * BITS_PER_BYTE) -#define HANDLE_MASKS_PER_SEGMENT (HANDLE_HANDLES_PER_SEGMENT / HANDLE_HANDLES_PER_MASK) -#define HANDLE_MASKS_PER_BLOCK (HANDLE_HANDLES_PER_BLOCK / HANDLE_HANDLES_PER_MASK) -#define HANDLE_CLUMPS_PER_MASK (HANDLE_HANDLES_PER_MASK / HANDLE_HANDLES_PER_CLUMP) - -// We use this relation to check for free mask per block. -C_ASSERT (HANDLE_HANDLES_PER_MASK * 2 == HANDLE_HANDLES_PER_BLOCK); - - -// cache layout metrics -#define HANDLE_CACHE_TYPE_SIZE 128 // 128 == 63 handles per bank -#define HANDLES_PER_CACHE_BANK ((HANDLE_CACHE_TYPE_SIZE / 2) - 1) - -// cache policy defines -#define REBALANCE_TOLERANCE (HANDLES_PER_CACHE_BANK / 3) -#define REBALANCE_LOWATER_MARK (HANDLES_PER_CACHE_BANK - REBALANCE_TOLERANCE) -#define REBALANCE_HIWATER_MARK (HANDLES_PER_CACHE_BANK + REBALANCE_TOLERANCE) - -// bulk alloc policy defines -#define SMALL_ALLOC_COUNT (HANDLES_PER_CACHE_BANK / 10) - -// misc constants -#define MASK_FULL (0) -#define MASK_EMPTY (0xFFFFFFFF) -#define MASK_LOBYTE (0x000000FF) -#define TYPE_INVALID ((uint8_t)0xFF) -#define BLOCK_INVALID ((uint8_t)0xFF) - -/*--------------------------------------------------------------------------*/ +#include "handletableconstants.h" @@ -483,6 +377,11 @@ struct HandleTable */ uint32_t rgTypeFlags[HANDLE_MAX_INTERNAL_TYPES]; + /* + * head of segment list for this table + */ + PTR_TableSegment pSegmentList; + /* * lock for this table */ @@ -499,11 +398,6 @@ struct HandleTable */ uint32_t dwCount; - /* - * head of segment list for this table - */ - PTR_TableSegment pSegmentList; - /* * information on current async scan (if any) */ diff --git a/src/coreclr/gc/objecthandle.cpp b/src/coreclr/gc/objecthandle.cpp index 52b25b88adf51..43e09789bab81 100644 --- a/src/coreclr/gc/objecthandle.cpp +++ b/src/coreclr/gc/objecthandle.cpp @@ -1811,6 +1811,8 @@ void PopulateHandleTableDacVars(GcDacVars* gcDacVars) static_assert(offsetof(HandleTableMap, dwMaxIndex) == offsetof(dac_handle_table_map, dwMaxIndex), "handle table map DAC layout mismatch"); static_assert(offsetof(HandleTableBucket, pTable) == offsetof(dac_handle_table_bucket, pTable), "handle table bucket DAC layout mismatch"); static_assert(offsetof(HandleTableBucket, HandleTableIndex) == offsetof(dac_handle_table_bucket, HandleTableIndex), "handle table bucket DAC layout mismatch"); + static_assert(offsetof(HandleTable, pSegmentList) == offsetof(dac_handle_table, pSegmentList), "handle table bucket DAC layout mismatch"); + static_assert(offsetof(_TableSegmentHeader, pNextSegment) == offsetof(dac_handle_table_segment, pNextSegment), "handle table bucket DAC layout mismatch"); #ifndef DACCESS_COMPILE gcDacVars->handle_table_map = reinterpret_cast(&g_HandleTableMap); diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index 12adb32cc409d..bc208595be770 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -525,8 +525,7 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { // // Specify the number of breakpoints and watchpoints that the OS -// will track. Architecturally, LOONGARCH64 supports up to 16. In practice, -// however, almost no one implements more than 4 of each. +// will track. // #define RISCV64_MAX_BREAKPOINTS 8 @@ -541,6 +540,7 @@ typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { // /* +0x000 */ DWORD ContextFlags; + /* +0x004 */ DWORD Fcsr; // // Integer registers @@ -584,7 +584,6 @@ typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { // //TODO-RISCV64: support the SIMD. ULONGLONG F[32]; - DWORD Fcsr; } T_CONTEXT, *PT_CONTEXT; // _IMAGE_RISCV64_RUNTIME_FUNCTION_ENTRY (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) diff --git a/src/coreclr/inc/sospriv.idl b/src/coreclr/inc/sospriv.idl index b1a3b18e06b8b..ac7b93a9a7bc1 100644 --- a/src/coreclr/inc/sospriv.idl +++ b/src/coreclr/inc/sospriv.idl @@ -49,6 +49,7 @@ cpp_quote("#endif") cpp_quote("typedef enum { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE } ModuleMapType;") cpp_quote("typedef enum {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap, VtableHeap} VCSHeapType;") cpp_quote("typedef enum {LoaderHeapKindNormal = 0, LoaderHeapKindExplicitControl = 1} LoaderHeapKind;") +cpp_quote("typedef enum {FreeUnknownRegion = 0, FreeGlobalHugeRegion = 1, FreeGlobalRegion = 2, FreeRegion = 3, FreeSohSegment = 4, FreeUohSegment = 5 } FreeRegionKind;") typedef void (*MODULEMAPTRAVERSE)(UINT index, CLRDATA_ADDRESS methodTable,LPVOID token); typedef void (*VISITHEAP)(CLRDATA_ADDRESS blockData,size_t blockSize,BOOL blockIsCurrentBlock); @@ -172,6 +173,32 @@ interface ISOSStackRefEnum : ISOSEnum } +cpp_quote("#ifndef _SOS_MemoryRegion_") +cpp_quote("#define _SOS_MemoryRegion_") + +typedef struct _SOSMemoryRegion +{ + CLRDATA_ADDRESS Start; + CLRDATA_ADDRESS Size; + CLRDATA_ADDRESS ExtraData; + int Heap; +} SOSMemoryRegion; + +cpp_quote("#endif // _SOS_MemoryRegion_") + +[ + object, + local, + uuid(E4B860EC-337A-40C0-A591-F09A9680690F) +] +interface ISOSMemoryEnum : ISOSEnum +{ + HRESULT Next([in] unsigned int count, + [out, size_is(count), length_is(*pNeeded)] SOSMemoryRegion memRegion[], + [out] unsigned int *pNeeded); +} + + [ object, local, @@ -465,7 +492,7 @@ interface ISOSDacInterface12 : IUnknown [ object, local, - uuid(3176a8ed-597b-4f54-a71f-83695c6a8c5d) + uuid(3176a8ed-597b-4f54-a71f-83695c6a8c5e) ] interface ISOSDacInterface13 : IUnknown { @@ -473,4 +500,8 @@ interface ISOSDacInterface13 : IUnknown HRESULT GetDomainLoaderAllocator(CLRDATA_ADDRESS domainAddress, CLRDATA_ADDRESS *pLoaderAllocator); HRESULT GetLoaderAllocatorHeapNames(int count, const char **ppNames, int *pNeeded); HRESULT GetLoaderAllocatorHeaps(CLRDATA_ADDRESS loaderAllocator, int count, CLRDATA_ADDRESS *pLoaderHeaps, LoaderHeapKind *pKinds, int *pNeeded); + HRESULT GetHandleTableMemoryRegions(ISOSMemoryEnum **ppEnum); + HRESULT GetGCBookkeepingMemoryRegions(ISOSMemoryEnum **ppEnum); + HRESULT GetGCFreeRegions(ISOSMemoryEnum **ppEnum); + HRESULT LockedFlush(); } diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index 1b39056d057fd..bbfac6e210e92 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -872,8 +872,6 @@ inline int CountBits(int iNum) return (iBits); } -#include "bitposition.h" - // Convert the currency to a decimal and canonicalize. inline void VarDecFromCyCanonicalize(CY cyIn, DECIMAL* dec) { diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 8b5957dfb8aa9..da92e4cd66013 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1573,6 +1573,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #if defined(TARGET_ARM64) static insCond JumpKindToInsCond(emitJumpKind condition); + static insOpts ShiftOpToInsOpts(genTreeOps op); #elif defined(TARGET_XARCH) static instruction JumpKindToCmov(emitJumpKind condition); #endif diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index b177186cedeca..6ecfb818a4daf 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -2626,31 +2626,7 @@ void CodeGen::genCodeForBinary(GenTreeOp* tree) } } - switch (op2->gtOper) - { - case GT_LSH: - { - opt = INS_OPTS_LSL; - break; - } - - case GT_RSH: - { - opt = INS_OPTS_ASR; - break; - } - - case GT_RSZ: - { - opt = INS_OPTS_LSR; - break; - } - - default: - { - unreached(); - } - } + opt = ShiftOpToInsOpts(op2->gtOper); emit->emitIns_R_R_R_I(ins, emitActualTypeSize(tree), targetReg, a->GetRegNum(), b->GetRegNum(), c->AsIntConCommon()->IconValue(), opt); @@ -4546,6 +4522,15 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) emit->emitIns_R_I(ins, cmpSize, op1Reg, intConst->IconValue()); } + else if (op2->isContained()) + { + assert(op2->OperIs(GT_LSH, GT_RSH, GT_RSZ)); + assert(op2->gtGetOp2()->IsCnsIntOrI()); + assert(op2->gtGetOp2()->isContained()); + + emit->emitIns_R_R_I(ins, cmpSize, op1->GetRegNum(), op2->gtGetOp1()->GetRegNum(), + op2->gtGetOp2()->AsIntConCommon()->IntegralValue(), ShiftOpToInsOpts(op2->gtOper)); + } else { emit->emitIns_R_R(ins, cmpSize, op1->GetRegNum(), op2->GetRegNum()); @@ -10389,4 +10374,29 @@ insCond CodeGen::JumpKindToInsCond(emitJumpKind condition) } } +//------------------------------------------------------------------------ +// ShiftOpToInsOpts: Convert a shift-op to a insOpts. +// +// Arguments: +// shiftOp - the shift-op +// +insOpts CodeGen::ShiftOpToInsOpts(genTreeOps shiftOp) +{ + switch (shiftOp) + { + case GT_LSH: + return INS_OPTS_LSL; + + case GT_RSH: + return INS_OPTS_ASR; + + case GT_RSZ: + return INS_OPTS_LSR; + + default: + NO_WAY("expected a shift-op"); + return INS_OPTS_NONE; + } +} + #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 09b2d3e7f292f..8215b4e1b56a8 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -26,14 +26,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX extern ICorJitHost* g_jitHost; -#if defined(DEBUG) -// Column settings for DOTNET_JitDumpIR. We could(should) make these programmable. -#define COLUMN_OPCODE 30 -#define COLUMN_OPERANDS (COLUMN_OPCODE + 25) -#define COLUMN_KINDS 110 -#define COLUMN_FLAGS (COLUMN_KINDS + 32) -#endif - unsigned Compiler::jitTotalMethodCompiled = 0; #if defined(DEBUG) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 4957a1c30e65e..7e4eb4c14d895 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -97,53 +97,9 @@ inline T genFindLowestBit(T value) return (value & (0 - value)); } -//------------------------------------------------------------------------ -// genFindHighestBit: Return the highest bit that is set (that is, a mask that includes just the -// highest bit). -// -// Return Value: -// The highest position (0 is LSB) of bit that is set in the 'value'. -// -// Note: -// It performs the "LeadingZeroCount " operation using intrinsics and then mask out everything -// but the highest bit. -inline unsigned int genFindHighestBit(unsigned int mask) -{ - assert(mask != 0); -#if defined(_MSC_VER) - unsigned long index; -#else - unsigned int index; -#endif - BitScanReverse(&index, mask); - return 1L << index; -} - -//------------------------------------------------------------------------ -// genFindHighestBit: Return the highest bit that is set (that is, a mask that includes just the -// highest bit). -// -// Return Value: -// The highest position (0 is LSB) of bit that is set in the 'value'. -// -// Note: -// It performs the "LeadingZeroCount " operation using intrinsics and then mask out everything -// but the highest bit. -inline unsigned __int64 genFindHighestBit(unsigned __int64 mask) -{ - assert(mask != 0); -#if defined(_MSC_VER) - unsigned long index; -#else - unsigned int index; -#endif - BitScanReverse64(&index, mask); - return 1LL << index; -} - /***************************************************************************** * -* Return true if the given 64-bit value has exactly zero or one bits set. +* Return true if the given value has exactly zero or one bits set. */ template @@ -154,17 +110,7 @@ inline bool genMaxOneBit(T value) /***************************************************************************** * -* Return true if the given 32-bit value has exactly zero or one bits set. -*/ - -inline bool genMaxOneBit(unsigned value) -{ - return (value & (value - 1)) == 0; -} - -/***************************************************************************** -* -* Return true if the given 64-bit value has exactly one bit set. +* Return true if the given value has exactly one bit set. */ template @@ -173,16 +119,6 @@ inline bool genExactlyOneBit(T value) return ((value != 0) && genMaxOneBit(value)); } -/***************************************************************************** -* -* Return true if the given 32-bit value has exactly zero or one bits set. -*/ - -inline bool genExactlyOneBit(unsigned value) -{ - return ((value != 0) && genMaxOneBit(value)); -} - /***************************************************************************** * * Given a value that has exactly one bit set, return the position of that @@ -190,47 +126,14 @@ inline bool genExactlyOneBit(unsigned value) */ inline unsigned genLog2(unsigned value) { - return BitPosition(value); -} - -// Given an unsigned 64-bit value, returns the lower 32-bits in unsigned format -// -inline unsigned ulo32(unsigned __int64 value) -{ - return static_cast(value); -} - -// Given an unsigned 64-bit value, returns the upper 32-bits in unsigned format -// -inline unsigned uhi32(unsigned __int64 value) -{ - return static_cast(value >> 32); + assert(genExactlyOneBit(value)); + return BitOperations::BitScanForward(value); } -/***************************************************************************** - * - * Given a value that has exactly one bit set, return the position of that - * bit, in other words return the logarithm in base 2 of the given value. - */ - inline unsigned genLog2(unsigned __int64 value) { -#ifdef HOST_64BIT - return BitPosition(value); -#else // HOST_32BIT - unsigned lo32 = ulo32(value); - unsigned hi32 = uhi32(value); - - if (lo32 != 0) - { - assert(hi32 == 0); - return genLog2(lo32); - } - else - { - return genLog2(hi32) + 32; - } -#endif + assert(genExactlyOneBit(value)); + return BitOperations::BitScanForward(value); } #ifdef __APPLE__ @@ -240,14 +143,18 @@ inline unsigned genLog2(size_t value) } #endif // __APPLE__ -/***************************************************************************** - * - * Return the lowest bit that is set in the given register mask. - */ +// Given an unsigned 64-bit value, returns the lower 32-bits in unsigned format +// +inline unsigned ulo32(unsigned __int64 value) +{ + return static_cast(value); +} -inline regMaskTP genFindLowestReg(regMaskTP value) +// Given an unsigned 64-bit value, returns the upper 32-bits in unsigned format +// +inline unsigned uhi32(unsigned __int64 value) { - return (regMaskTP)genFindLowestBit(value); + return static_cast(value >> 32); } /***************************************************************************** diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 04eca4b9aadf2..97de8d503606c 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -6164,7 +6164,7 @@ unsigned emitter::emitCalculatePaddingForLoopAlignment(insGroup* loopHeadIG, if (emitComp->opts.compJitAlignLoopAdaptive) { // For adaptive, adjust the loop size depending on the alignment boundary - maxLoopBlocksAllowed = genLog2((unsigned)alignmentBoundary) - 1; + maxLoopBlocksAllowed = genLog2(alignmentBoundary) - 1; maxLoopSize = alignmentBoundary * maxLoopBlocksAllowed; } else @@ -7145,129 +7145,141 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, emitCurIG = ig; - for (unsigned cnt = ig->igInsCnt; cnt > 0; cnt--) + // Fast loop without any JitDisasm/JitDump TP overhead + if (!emitComp->opts.disAsm INDEBUG(&&!emitComp->verbose)) { -#ifdef DEBUG - if ((emitComp->opts.disAsm || emitComp->verbose) && (JitConfig.JitDisasmWithDebugInfo() != 0) && - (id->idCodeSize() > 0)) + for (unsigned cnt = ig->igInsCnt; cnt > 0; cnt--) { - UNATIVE_OFFSET curCodeOffs = emitCurCodeOffs(cp); - while (nextMapping != emitComp->genRichIPmappings.end()) - { - UNATIVE_OFFSET mappingOffs = nextMapping->nativeLoc.CodeOffset(this); - - if (mappingOffs > curCodeOffs) - { - // Still haven't reached instruction that next mapping belongs to. - break; - } - - // We reached the mapping or went past it. - if (mappingOffs == curCodeOffs) - { - emitDispInsIndent(); - printf("; "); - nextMapping->debugInfo.Dump(true); - printf("\n"); - } - - ++nextMapping; - } + size_t curInstrAddr = (size_t)cp; + instrDesc* curInstrDesc = id; + size_t insSize = emitIssue1Instr(ig, id, &cp); + emitAdvanceInstrDesc(&id, insSize); } -#endif - size_t insSize = emitIssue1Instr(ig, id, &cp); - emitAdvanceInstrDesc(&id, insSize); } - - // Print the alignment boundary - if ((emitComp->opts.disAsm INDEBUG(|| emitComp->verbose)) && - (INDEBUG(emitComp->opts.disAddr ||) emitComp->opts.disAlignment)) + else { for (unsigned cnt = ig->igInsCnt; cnt > 0; cnt--) { size_t curInstrAddr = (size_t)cp; instrDesc* curInstrDesc = id; +#ifdef DEBUG + if ((emitComp->opts.disAsm || emitComp->verbose) && (JitConfig.JitDisasmWithDebugInfo() != 0) && + (id->idCodeSize() > 0)) + { + UNATIVE_OFFSET curCodeOffs = emitCurCodeOffs(cp); + while (nextMapping != emitComp->genRichIPmappings.end()) + { + UNATIVE_OFFSET mappingOffs = nextMapping->nativeLoc.CodeOffset(this); - size_t afterInstrAddr = (size_t)cp; - instruction curIns = curInstrDesc->idIns(); - bool isJccAffectedIns = false; - -#if defined(TARGET_XARCH) + if (mappingOffs > curCodeOffs) + { + // Still haven't reached instruction that next mapping belongs to. + break; + } - // Determine if this instruction is part of a set that matches the Intel jcc erratum characteristic - // described here: - // https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf - // This is the case when a jump instruction crosses a 32-byte boundary, or ends on a 32-byte boundary. - // "Jump instruction" in this case includes conditional jump (jcc), macro-fused op-jcc (where 'op' is - // one of cmp, test, add, sub, and, inc, or dec), direct unconditional jump, indirect jump, - // direct/indirect call, and return. + // We reached the mapping or went past it. + if (mappingOffs == curCodeOffs) + { + emitDispInsIndent(); + printf("; "); + nextMapping->debugInfo.Dump(true); + printf("\n"); + } - size_t jccAlignBoundary = 32; - size_t jccAlignBoundaryMask = jccAlignBoundary - 1; - size_t jccLastBoundaryAddr = afterInstrAddr & ~jccAlignBoundaryMask; + ++nextMapping; + } + } +#endif + size_t insSize = emitIssue1Instr(ig, id, &cp); + emitAdvanceInstrDesc(&id, insSize); - if (curInstrAddr < jccLastBoundaryAddr) + // Print the alignment boundary + if ((emitComp->opts.disAsm INDEBUG(|| emitComp->verbose)) && + (INDEBUG(emitComp->opts.disAddr ||) emitComp->opts.disAlignment)) { - isJccAffectedIns = IsJccInstruction(curIns) || IsJmpInstruction(curIns) || (curIns == INS_call) || - (curIns == INS_ret); + size_t afterInstrAddr = (size_t)cp; + instruction curIns = curInstrDesc->idIns(); + bool isJccAffectedIns = false; - // For op-Jcc there are two cases: (1) curIns is the jcc, in which case the above condition - // already covers us. (2) curIns is the `op` and the next instruction is the `jcc`. Note that - // we will never have a `jcc` as the first instruction of a group, so we don't need to worry - // about looking ahead to the next group after a an `op` of `op-Jcc`. +#if defined(TARGET_XARCH) - if (!isJccAffectedIns && (cnt > 1)) + // Determine if this instruction is part of a set that matches the Intel jcc erratum characteristic + // described here: + // https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf + // This is the case when a jump instruction crosses a 32-byte boundary, or ends on a 32-byte + // boundary. + // "Jump instruction" in this case includes conditional jump (jcc), macro-fused op-jcc (where 'op' + // is + // one of cmp, test, add, sub, and, inc, or dec), direct unconditional jump, indirect jump, + // direct/indirect call, and return. + + size_t jccAlignBoundary = 32; + size_t jccAlignBoundaryMask = jccAlignBoundary - 1; + size_t jccLastBoundaryAddr = afterInstrAddr & ~jccAlignBoundaryMask; + + if (curInstrAddr < jccLastBoundaryAddr) { - // The current `id` is valid, namely, there is another instruction in this group. - instruction nextIns = id->idIns(); - if (((curIns == INS_cmp) || (curIns == INS_test) || (curIns == INS_add) || - (curIns == INS_sub) || (curIns == INS_and) || (curIns == INS_inc) || - (curIns == INS_dec)) && - IsJccInstruction(nextIns)) + isJccAffectedIns = IsJccInstruction(curIns) || IsJmpInstruction(curIns) || + (curIns == INS_call) || (curIns == INS_ret); + + // For op-Jcc there are two cases: (1) curIns is the jcc, in which case the above condition + // already covers us. (2) curIns is the `op` and the next instruction is the `jcc`. Note that + // we will never have a `jcc` as the first instruction of a group, so we don't need to worry + // about looking ahead to the next group after a an `op` of `op-Jcc`. + + if (!isJccAffectedIns && (cnt > 1)) { - isJccAffectedIns = true; + // The current `id` is valid, namely, there is another instruction in this group. + instruction nextIns = id->idIns(); + if (((curIns == INS_cmp) || (curIns == INS_test) || (curIns == INS_add) || + (curIns == INS_sub) || (curIns == INS_and) || (curIns == INS_inc) || + (curIns == INS_dec)) && + IsJccInstruction(nextIns)) + { + isJccAffectedIns = true; + } } - } - if (isJccAffectedIns) - { - unsigned bytesCrossedBoundary = (unsigned)(afterInstrAddr & jccAlignBoundaryMask); - printf("; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (%s: %d ; jcc erratum) %dB boundary " - "...............................\n", - codeGen->genInsDisplayName(curInstrDesc), bytesCrossedBoundary, jccAlignBoundary); + if (isJccAffectedIns) + { + unsigned bytesCrossedBoundary = (unsigned)(afterInstrAddr & jccAlignBoundaryMask); + printf("; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (%s: %d ; jcc erratum) %dB boundary " + "...............................\n", + codeGen->genInsDisplayName(curInstrDesc), bytesCrossedBoundary, jccAlignBoundary); + } } - } #elif defined(TARGET_LOONGARCH64) - isJccAffectedIns = true; + isJccAffectedIns = true; #elif defined(TARGET_RISCV64) - isJccAffectedIns = true; + isJccAffectedIns = true; #endif // TARGET_RISCV64 - // Jcc affected instruction boundaries were printed above; handle other cases here. - if (!isJccAffectedIns) - { - size_t alignBoundaryMask = (size_t)emitComp->opts.compJitAlignLoopBoundary - 1; - size_t lastBoundaryAddr = afterInstrAddr & ~alignBoundaryMask; - - // draw boundary if beforeAddr was before the lastBoundary. - if (curInstrAddr < lastBoundaryAddr) + // Jcc affected instruction boundaries were printed above; handle other cases here. + if (!isJccAffectedIns) { - // Indicate if instruction is at the alignment boundary or is split - unsigned bytesCrossedBoundary = (unsigned)(afterInstrAddr & alignBoundaryMask); - if (bytesCrossedBoundary != 0) - { - printf("; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (%s: %d)", - codeGen->genInsDisplayName(curInstrDesc), bytesCrossedBoundary); - } - else + size_t alignBoundaryMask = (size_t)emitComp->opts.compJitAlignLoopBoundary - 1; + size_t lastBoundaryAddr = afterInstrAddr & ~alignBoundaryMask; + + // draw boundary if beforeAddr was before the lastBoundary. + if (curInstrAddr < lastBoundaryAddr) { - printf("; ..............................."); + // Indicate if instruction is at the alignment boundary or is split + unsigned bytesCrossedBoundary = (unsigned)(afterInstrAddr & alignBoundaryMask); + if (bytesCrossedBoundary != 0) + { + printf("; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (%s: %d)", + codeGen->genInsDisplayName(curInstrDesc), bytesCrossedBoundary); + } + else + { + printf("; ..............................."); + } + printf(" %dB boundary ...............................\n", + emitComp->opts.compJitAlignLoopBoundary); } - printf(" %dB boundary ...............................\n", - emitComp->opts.compJitAlignLoopBoundary); } } } diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index 81eb8ed27c26f..a82f37421d0dc 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -4190,7 +4190,7 @@ void emitter::emitIns_R_ARX( assert(!"Please use ins_Load() to select the correct instruction"); } - unsigned shift = genLog2((unsigned)mul); + unsigned shift = genLog2(mul); if ((ins == INS_lea) || emitInsIsLoad(ins)) { diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index eb0605667a0ee..526cea6443d4b 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -2776,15 +2776,6 @@ bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBloc optimizeJump = true; } - // If we are optimizing using real profile weights - // then don't optimize a conditional jump to an unconditional jump - // until after we have computed the edge weights - // - if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed) - { - optimizeJump = false; - } - if (optimizeJump) { #ifdef DEBUG @@ -3156,15 +3147,6 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) optimizeJump = false; } - // If we are optimize using real profile weights - // then don't optimize a switch jump to an unconditional jump - // until after we have computed the edge weights - // - if (fgIsUsingProfileWeights() && !fgEdgeWeightsComputed) - { - optimizeJump = false; - } - if (optimizeJump) { bNewDest = bDest->bbJumpDest; diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index dcbfd1d7064b0..eaa5a584261a3 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -2645,7 +2645,7 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un /* Get hold of the next register bit */ - tmpMask = genFindLowestReg(regMask); + tmpMask = genFindLowestBit(regMask); assert(tmpMask); /* Remember the new state of this register */ @@ -2694,7 +2694,7 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un /* Get hold of the next register bit */ - tmpMask = genFindLowestReg(regMask); + tmpMask = genFindLowestBit(regMask); assert(tmpMask); /* Remember the new state of this register */ @@ -4627,7 +4627,7 @@ void GCInfo::gcInfoRecordGCRegStateChange(GcInfoEncoder* gcInfoEncoder, while (regMask) { // Get hold of the next register bit. - regMaskTP tmpMask = genFindLowestReg(regMask); + regMaskTP tmpMask = genFindLowestBit(regMask); assert(tmpMask); // Remember the new state of this register. diff --git a/src/coreclr/jit/hashbv.h b/src/coreclr/jit/hashbv.h index 1c5e4310dcfa8..7ad95998add8e 100644 --- a/src/coreclr/jit/hashbv.h +++ b/src/coreclr/jit/hashbv.h @@ -323,12 +323,10 @@ HbvWalk ForEachHbvBitSet(const hashBv& bv, TFunctor func) indexType base = node->baseIndex; for (int el = 0; el < node->numElements(); el++) { - elemType i = 0; elemType e = node->elements[el]; while (e) { - int result = BitScanForwardPtr((DWORD*)&i, e); - assert(result); + unsigned i = BitOperations::BitScanForward(e); indexType index = base + (el * BITS_PER_ELEMENT) + i; e ^= (elemType(1) << i); diff --git a/src/coreclr/jit/importervectorization.cpp b/src/coreclr/jit/importervectorization.cpp index 9f7c6f3cefab2..da313d5e339bd 100644 --- a/src/coreclr/jit/importervectorization.cpp +++ b/src/coreclr/jit/importervectorization.cpp @@ -6,8 +6,8 @@ #pragma hdrstop #endif -// For now the max possible size is Vector256.Count * 2 -#define MaxPossibleUnrollSize 32 +// For now the max possible size is Vector512.Count * 2 +#define MaxPossibleUnrollSize 64 //------------------------------------------------------------------------ // importer_vectorization.cpp @@ -71,7 +71,7 @@ static bool ConvertToLowerCase(WCHAR* input, WCHAR* mask, int length) #if defined(FEATURE_HW_INTRINSICS) //------------------------------------------------------------------------ // impExpandHalfConstEqualsSIMD: Attempts to unroll and vectorize -// Equals against a constant WCHAR data for Length in [8..32] range +// Equals against a constant WCHAR data for Length in [8..64] range // using SIMD instructions. C# equivalent of what this function emits: // // bool IsTestString(ReadOnlySpan span) @@ -108,31 +108,20 @@ GenTree* Compiler::impExpandHalfConstEqualsSIMD( { assert(len >= 8 && len <= MaxPossibleUnrollSize); - if (!IsBaselineSimdIsaSupported()) + const int byteLen = len * sizeof(WCHAR); + const int simdSize = (int)roundDownSIMDSize(byteLen); + if (byteLen > (simdSize * 2)) { - // We need baseline SIMD support at least + // Data is too big to be processed via two SIMD loads + // or baseline has no SIMD support return nullptr; } - - CorInfoType baseType = CORINFO_TYPE_NATIVEUINT; - - int simdSize; - var_types simdType; - - NamedIntrinsic niEquals; - - GenTreeVecCon* cnsVec1 = nullptr; - GenTreeVecCon* cnsVec2 = nullptr; - GenTree* toLowerVec1 = nullptr; - GenTree* toLowerVec2 = nullptr; - - // Optimization: don't use two vectors for Length == 8 or 16 - bool useSingleVector = false; + assert((byteLen >= simdSize) && (simdSize >= 16)); WCHAR cnsValue[MaxPossibleUnrollSize] = {}; WCHAR toLowerMask[MaxPossibleUnrollSize] = {}; - memcpy((UINT8*)cnsValue, (UINT8*)cns, len * sizeof(WCHAR)); + memcpy(cnsValue, cns, byteLen); if ((cmpMode == OrdinalIgnoreCase) && !ConvertToLowerCase(cnsValue, toLowerMask, len)) { @@ -140,89 +129,23 @@ GenTree* Compiler::impExpandHalfConstEqualsSIMD( return nullptr; } -#if defined(TARGET_XARCH) - if (compOpportunisticallyDependsOn(InstructionSet_Vector256) && len >= 16) - { - // Handle [16..32] inputs via two Vector256 - assert(len >= 16 && len <= 32); - - simdSize = 32; - simdType = TYP_SIMD32; - - niEquals = NI_Vector256_op_Equality; - - // Special case: use a single vector for Length == 16 - useSingleVector = len == 16; - - cnsVec1 = gtNewVconNode(simdType, cnsValue); - cnsVec2 = gtNewVconNode(simdType, cnsValue + len - 16); - - if (cmpMode == OrdinalIgnoreCase) - { - toLowerVec1 = gtNewVconNode(simdType, toLowerMask); - toLowerVec2 = gtNewVconNode(simdType, toLowerMask + len - 16); - } - } - else -#endif // TARGET_XARCH - if (len <= 16) - { - // Handle [8..16] inputs via two Vector128 - assert(len >= 8 && len <= 16); - - simdSize = 16; - simdType = TYP_SIMD16; + const var_types simdType = getSIMDTypeForSize(simdSize); + const CorInfoType baseType = CORINFO_TYPE_NATIVEUINT; - niEquals = NI_Vector128_op_Equality; + GenTreeVecCon* cnsVec1 = gtNewVconNode(simdType, cnsValue); + GenTreeVecCon* cnsVec2 = gtNewVconNode(simdType, (BYTE*)cnsValue + byteLen - simdSize); - // Special case: use a single vector for Length == 8 - useSingleVector = len == 8; - - cnsVec1 = gtNewVconNode(simdType, cnsValue); - cnsVec2 = gtNewVconNode(simdType, cnsValue + len - 8); - - if (cmpMode == OrdinalIgnoreCase) - { - toLowerVec1 = gtNewVconNode(simdType, toLowerMask); - toLowerVec2 = gtNewVconNode(simdType, toLowerMask + len - 8); - } - } - else - { - JITDUMP("impExpandHalfConstEqualsSIMD: No V256 support and data is too big for V128\n"); - // NOTE: We might consider using four V128 for ARM64 - return nullptr; - } - - GenTree* zero = gtNewZeroConNode(simdType); - - GenTree* offset1 = gtNewIconNode(dataOffset, TYP_I_IMPL); - GenTree* offset2 = gtNewIconNode(dataOffset + len * sizeof(USHORT) - simdSize, TYP_I_IMPL); - GenTree* dataPtr1 = gtNewOperNode(GT_ADD, TYP_BYREF, data, offset1); - GenTree* dataPtr2 = gtNewOperNode(GT_ADD, TYP_BYREF, gtClone(data), offset2); - - GenTree* vec1 = gtNewIndir(simdType, dataPtr1); - GenTree* vec2 = gtNewIndir(simdType, dataPtr2); - - // TODO-Unroll-CQ: Spill vec1 and vec2 for better pipelining, currently we end up emitting: - // - // vmovdqu xmm0, xmmword ptr [rcx+12] - // vpxor xmm0, xmm0, xmmword ptr[reloc @RWD00] - // vmovdqu xmm1, xmmword ptr [rcx+20] - // vpxor xmm1, xmm1, xmmword ptr[reloc @RWD16] - // - // While we should re-order them to be: - // - // vmovdqu xmm0, xmmword ptr [rcx+12] - // vmovdqu xmm1, xmmword ptr [rcx+20] - // vpxor xmm0, xmm0, xmmword ptr[reloc @RWD00] - // vpxor xmm1, xmm1, xmmword ptr[reloc @RWD16] - // + GenTree* offset1 = gtNewIconNode(dataOffset, TYP_I_IMPL); + GenTree* offset2 = gtNewIconNode(dataOffset + byteLen - simdSize, TYP_I_IMPL); + GenTree* vec1 = gtNewIndir(simdType, gtNewOperNode(GT_ADD, TYP_BYREF, data, offset1)); + GenTree* vec2 = gtNewIndir(simdType, gtNewOperNode(GT_ADD, TYP_BYREF, gtClone(data), offset2)); if (cmpMode == OrdinalIgnoreCase) { // Apply ASCII-only ToLowerCase mask (bitwise OR 0x20 for all a-Z chars) - assert((toLowerVec1 != nullptr) && (toLowerVec2 != nullptr)); + GenTreeVecCon* toLowerVec1 = gtNewVconNode(simdType, toLowerMask); + GenTreeVecCon* toLowerVec2 = gtNewVconNode(simdType, (BYTE*)toLowerMask + byteLen - simdSize); + vec1 = gtNewSimdBinOpNode(GT_OR, simdType, vec1, toLowerVec1, baseType, simdSize); vec2 = gtNewSimdBinOpNode(GT_OR, simdType, vec2, toLowerVec2, baseType, simdSize); } @@ -231,7 +154,25 @@ GenTree* Compiler::impExpandHalfConstEqualsSIMD( GenTree* xor1 = gtNewSimdBinOpNode(GT_XOR, simdType, vec1, cnsVec1, baseType, simdSize); GenTree* xor2 = gtNewSimdBinOpNode(GT_XOR, simdType, vec2, cnsVec2, baseType, simdSize); GenTree* orr = gtNewSimdBinOpNode(GT_OR, simdType, xor1, xor2, baseType, simdSize); - return gtNewSimdHWIntrinsicNode(TYP_BOOL, useSingleVector ? xor1 : orr, zero, niEquals, baseType, simdSize); + + // Optimization: use a single load when byteLen equals simdSize. + // For code simplicity we always create nodes for two vectors case. + const bool useSingleVector = simdSize == byteLen; + return gtNewSimdCmpOpAllNode(GT_EQ, TYP_BOOL, useSingleVector ? xor1 : orr, gtNewZeroConNode(simdType), baseType, + simdSize); + + // Codegen example for byteLen=40 and OrdinalIgnoreCase mode with AVX: + // + // vmovups ymm0, ymmword ptr [rcx+0CH] + // vpor ymm0, ymm0, ymmword ptr [reloc @RWD00] + // vpxor ymm0, ymm0, ymmword ptr [reloc @RWD32] + // vmovups ymm1, ymmword ptr [rcx+28H] + // vpor ymm1, ymm1, ymmword ptr [reloc @RWD64] + // vpxor ymm1, ymm1, ymmword ptr [reloc @RWD96] + // vpor ymm0, ymm0, ymm1 + // vptest ymm0, ymm0 + // sete al + // movzx rax, al } #endif // defined(FEATURE_HW_INTRINSICS) @@ -491,7 +432,7 @@ GenTree* Compiler::impExpandHalfConstEquals(GenTreeLclVar* data, indirCmp = impExpandHalfConstEqualsSWAR(gtClone(data)->AsLclVar(), cnsData, len, dataOffset, cmpMode); } #if defined(FEATURE_HW_INTRINSICS) - else if (len <= 32) + else if (IsBaselineSimdIsaSupported()) { indirCmp = impExpandHalfConstEqualsSIMD(gtClone(data)->AsLclVar(), cnsData, len, dataOffset, cmpMode); } diff --git a/src/coreclr/jit/jitpch.h b/src/coreclr/jit/jitpch.h index e99ecd6c9f330..63f12133f61bf 100644 --- a/src/coreclr/jit/jitpch.h +++ b/src/coreclr/jit/jitpch.h @@ -13,6 +13,22 @@ #include #include +// Don't allow using the windows.h #defines for the BitScan* APIs. Using the #defines means our +// `BitOperations::BitScan*` functions have their name mapped, which is confusing and messes up +// Visual Studio source browsing. +#ifdef BitScanForward +#undef BitScanForward +#endif +#ifdef BitScanReverse +#undef BitScanReverse +#endif +#ifdef BitScanForward64 +#undef BitScanForward64 +#endif +#ifdef BitScanReverse64 +#undef BitScanReverse64 +#endif + #include "jitconfig.h" #include "jit.h" #include "iallocator.h" diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index e082d3c4d1eb0..23b57ef894963 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -269,7 +269,7 @@ bool Lowering::IsContainableBinaryOp(GenTree* parentNode, GenTree* childNode) co return false; } - if (parentNode->OperIs(GT_CMP, GT_OR, GT_XOR)) + if (parentNode->OperIs(GT_CMP, GT_OR, GT_XOR) || parentNode->OperIsCompare()) { if (IsInvariantInRange(childNode, parentNode)) { @@ -2268,7 +2268,37 @@ void Lowering::ContainCheckCast(GenTreeCast* node) // void Lowering::ContainCheckCompare(GenTreeOp* cmp) { - CheckImmedAndMakeContained(cmp, cmp->gtOp2); + GenTree* op1 = cmp->gtGetOp1(); + GenTree* op2 = cmp->gtGetOp2(); + + if (CheckImmedAndMakeContained(cmp, op2)) + return; + + if (cmp->OperIsCompare() && CheckImmedAndMakeContained(cmp, op1)) + { + std::swap(cmp->gtOp1, cmp->gtOp2); + cmp->ChangeOper(cmp->SwapRelop(cmp->gtOper)); + return; + } + +#ifdef TARGET_ARM64 + if (comp->opts.OptimizationEnabled() && cmp->OperIsCompare()) + { + if (IsContainableBinaryOp(cmp, op2)) + { + MakeSrcContained(cmp, op2); + return; + } + + if (IsContainableBinaryOp(cmp, op1)) + { + MakeSrcContained(cmp, op1); + std::swap(cmp->gtOp1, cmp->gtOp2); + cmp->ChangeOper(cmp->SwapRelop(cmp->gtOper)); + return; + } + } +#endif } #ifdef TARGET_ARM64 diff --git a/src/coreclr/jit/utils.h b/src/coreclr/jit/utils.h index d78000bfb7d26..7fd3e7d10f884 100644 --- a/src/coreclr/jit/utils.h +++ b/src/coreclr/jit/utils.h @@ -25,11 +25,34 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Needed for unreached() #include "error.h" -#ifdef TARGET_64BIT -#define BitScanForwardPtr BitScanForward64 -#else -#define BitScanForwardPtr BitScanForward -#endif +#if defined(_MSC_VER) + +// Define wrappers over the non-underscore versions of the BitScan* APIs. The PAL defines these already. +// We've #undef'ed the definitions in winnt.h for these names to avoid confusion. + +inline BOOLEAN BitScanForward(DWORD* Index, DWORD Mask) +{ + return ::_BitScanForward(Index, Mask); +} + +inline BOOLEAN BitScanReverse(DWORD* Index, DWORD Mask) +{ + return ::_BitScanReverse(Index, Mask); +} + +#if defined(HOST_64BIT) +inline BOOLEAN BitScanForward64(DWORD* Index, DWORD64 Mask) +{ + return ::_BitScanForward64(Index, Mask); +} + +inline BOOLEAN BitScanReverse64(DWORD* Index, DWORD64 Mask) +{ + return ::_BitScanReverse64(Index, Mask); +} +#endif // defined(HOST_64BIT) + +#endif // _MSC_VER template inline constexpr unsigned ArrLen(T (&)[size]) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index 2c1edf7ab0ecd..27955fd6bc22c 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -181,6 +181,15 @@ The .NET Foundation licenses this file to you under the MIT license. + + + + + + + <_LinkerVersion>$([System.Text.RegularExpressions.Regex]::Match($(_LinkerVersionString), '[1-9]\d*')) + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 44703efeb45cd..a0c5cbae672eb 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -318,7 +318,8 @@ The .NET Foundation licenses this file to you under the MIT license. - + + @@ -335,6 +336,9 @@ The .NET Foundation licenses this file to you under the MIT license. -x + + + diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs index 74cf978e2dedb..ccf4cd6399b36 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs @@ -357,10 +357,25 @@ internal ushort ExtendedFlags #endif } + internal uint RawBaseSize + { + get + { + return _uBaseSize; + } +#if TYPE_LOADER_IMPLEMENTATION + set + { + _uBaseSize = value; + } +#endif + } + internal uint BaseSize { get { + Debug.Assert(IsCanonical || IsArray); return _uBaseSize; } #if TYPE_LOADER_IMPLEMENTATION @@ -503,7 +518,8 @@ internal bool IsSzArray { get { - return ElementType == EETypeElementType.SzArray; + Debug.Assert(IsArray); + return BaseSize == SZARRAY_BASE_SIZE; } } @@ -713,6 +729,7 @@ internal uint ParameterizedTypeShape { get { + Debug.Assert(IsParameterizedType); return _uBaseSize; } #if TYPE_LOADER_IMPLEMENTATION @@ -833,22 +850,6 @@ internal uint ValueTypeSize } } - internal uint FieldByteCountNonGCAligned - { - get - { - // This api is designed to return correct results for EETypes which can be derived from - // And results indistinguishable from correct for DefTypes which cannot be derived from (sealed classes) - // (For sealed classes, this should always return BaseSize-((uint)sizeof(ObjHeader)); - Debug.Assert(!IsInterface && !IsParameterizedType); - - // get_BaseSize returns the GC size including space for the sync block index field, the MethodTable* and - // padding for GC heap alignment. Must subtract all of these to get the size used for the fields of - // the type (where the fields of the type includes the MethodTable*) - return BaseSize - ((uint)sizeof(ObjHeader) + ValueTypeFieldPadding); - } - } - internal EEInterfaceInfo* InterfaceMap { get @@ -1337,7 +1338,8 @@ internal EETypeElementType ElementType { get { - return (EETypeElementType)((_uFlags & (uint)EETypeFlags.ElementTypeMask) >> (byte)EETypeFlags.ElementTypeShift); + return (EETypeElementType)((_uFlags >> (byte)EETypeFlags.ElementTypeShift) & + ((uint)EETypeFlags.ElementTypeMask >> (byte)EETypeFlags.ElementTypeShift)); } #if TYPE_LOADER_IMPLEMENTATION set diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/EETypePtr.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/EETypePtr.cs index 4252397ed0811..8dc8889325743 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/EETypePtr.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/EETypePtr.cs @@ -44,13 +44,5 @@ internal static EETypePtr EETypePtrOf() { throw new NotImplementedException(); } - - internal unsafe uint BaseSize - { - get - { - return ToPointer()->BaseSize; - } - } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs index 5db1d3e9134a7..1c594aa928132 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs @@ -32,14 +32,6 @@ public abstract partial class Array : ICollection, IEnumerable, IList, IStructur private int _numComponents; #pragma warning restore -#if TARGET_64BIT - private const int POINTER_SIZE = 8; -#else - private const int POINTER_SIZE = 4; -#endif - // Header + m_pEEType + _numComponents (with an optional padding) - private const int SZARRAY_BASE_SIZE = POINTER_SIZE + POINTER_SIZE + POINTER_SIZE; - public int Length => checked((int)Unsafe.As(this).Length); // This could return a length greater than int.MaxValue @@ -47,11 +39,11 @@ public abstract partial class Array : ICollection, IEnumerable, IList, IStructur public long LongLength => (long)NativeLength; - internal bool IsSzArray + internal unsafe bool IsSzArray { get { - return this.GetEETypePtr().BaseSize == SZARRAY_BASE_SIZE; + return this.GetMethodTable()->IsSzArray; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EETypePtr.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EETypePtr.cs index 70b85c6a0416c..8771fd0a30e71 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EETypePtr.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/EETypePtr.cs @@ -310,14 +310,6 @@ internal EETypePtr BaseType } } - internal uint BaseSize - { - get - { - return _value->BaseSize; - } - } - internal IntPtr DispatchMap { get @@ -347,34 +339,47 @@ internal CorElementType CorElementType { get { - Debug.Assert((int)CorElementType.ELEMENT_TYPE_BOOLEAN == (int)EETypeElementType.Boolean); - Debug.Assert((int)CorElementType.ELEMENT_TYPE_I1 == (int)EETypeElementType.SByte); - Debug.Assert((int)CorElementType.ELEMENT_TYPE_I8 == (int)EETypeElementType.Int64); - EETypeElementType elementType = ElementType; - - if (elementType <= EETypeElementType.UInt64) - return (CorElementType)elementType; - else if (elementType == EETypeElementType.Single) - return CorElementType.ELEMENT_TYPE_R4; - else if (elementType == EETypeElementType.Double) - return CorElementType.ELEMENT_TYPE_R8; - else if (elementType == EETypeElementType.IntPtr) - return CorElementType.ELEMENT_TYPE_I; - else if (elementType == EETypeElementType.UIntPtr) - return CorElementType.ELEMENT_TYPE_U; - else if (IsValueType) - return CorElementType.ELEMENT_TYPE_VALUETYPE; - else if (IsByRef) - return CorElementType.ELEMENT_TYPE_BYREF; - else if (IsPointer) - return CorElementType.ELEMENT_TYPE_PTR; - else if (IsSzArray) - return CorElementType.ELEMENT_TYPE_SZARRAY; - else if (IsArray) - return CorElementType.ELEMENT_TYPE_ARRAY; - else - return CorElementType.ELEMENT_TYPE_CLASS; - + ReadOnlySpan map = new byte[] + { + default, + (byte)CorElementType.ELEMENT_TYPE_VOID, // EETypeElementType.Void + (byte)CorElementType.ELEMENT_TYPE_BOOLEAN, // EETypeElementType.Boolean + (byte)CorElementType.ELEMENT_TYPE_CHAR, // EETypeElementType.Char + (byte)CorElementType.ELEMENT_TYPE_I1, // EETypeElementType.SByte + (byte)CorElementType.ELEMENT_TYPE_U1, // EETypeElementType.Byte + (byte)CorElementType.ELEMENT_TYPE_I2, // EETypeElementType.Int16 + (byte)CorElementType.ELEMENT_TYPE_U2, // EETypeElementType.UInt16 + (byte)CorElementType.ELEMENT_TYPE_I4, // EETypeElementType.Int32 + (byte)CorElementType.ELEMENT_TYPE_U4, // EETypeElementType.UInt32 + (byte)CorElementType.ELEMENT_TYPE_I8, // EETypeElementType.Int64 + (byte)CorElementType.ELEMENT_TYPE_U8, // EETypeElementType.UInt64 + (byte)CorElementType.ELEMENT_TYPE_I, // EETypeElementType.IntPtr + (byte)CorElementType.ELEMENT_TYPE_U, // EETypeElementType.UIntPtr + (byte)CorElementType.ELEMENT_TYPE_R4, // EETypeElementType.Single + (byte)CorElementType.ELEMENT_TYPE_R8, // EETypeElementType.Double + + (byte)CorElementType.ELEMENT_TYPE_VALUETYPE, // EETypeElementType.ValueType + (byte)CorElementType.ELEMENT_TYPE_VALUETYPE, + (byte)CorElementType.ELEMENT_TYPE_VALUETYPE, // EETypeElementType.Nullable + (byte)CorElementType.ELEMENT_TYPE_VALUETYPE, + (byte)CorElementType.ELEMENT_TYPE_CLASS, // EETypeElementType.Class + (byte)CorElementType.ELEMENT_TYPE_CLASS, // EETypeElementType.Interface + (byte)CorElementType.ELEMENT_TYPE_CLASS, // EETypeElementType.SystemArray + (byte)CorElementType.ELEMENT_TYPE_ARRAY, // EETypeElementType.Array + (byte)CorElementType.ELEMENT_TYPE_SZARRAY, // EETypeElementType.SzArray + (byte)CorElementType.ELEMENT_TYPE_BYREF, // EETypeElementType.ByRef + (byte)CorElementType.ELEMENT_TYPE_PTR, // EETypeElementType.Pointer + default, // Pad the map to 32 elements to enable range check elimination + default, + default, + default, + default + }; + + // Verify last element of the map + Debug.Assert((byte)CorElementType.ELEMENT_TYPE_PTR == map[(int)EETypeElementType.Pointer]); + + return (CorElementType)map[(int)ElementType]; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.NativeAot.cs index 5d97217a13c8b..19e4a2a663619 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.NativeAot.cs @@ -41,7 +41,7 @@ public static ref byte GetArrayDataReference(Array array) // to special-case arrays of known type and dimension. // See comment on RawArrayData (in RuntimeHelpers.CoreCLR.cs) for details - return ref Unsafe.AddByteOffset(ref Unsafe.As(array).Data, (nuint)array.GetEETypePtr().BaseSize - (nuint)(2 * sizeof(IntPtr))); + return ref Unsafe.AddByteOffset(ref Unsafe.As(array).Data, (nuint)array.GetMethodTable()->BaseSize - (nuint)(2 * sizeof(IntPtr))); } } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs index 73aac9a149817..0f7ec21048475 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs @@ -177,7 +177,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo runtimeInterfacesLength = checked((ushort)state.RuntimeInterfaces.Length); } - baseSize = (int)pTemplateEEType->BaseSize; + baseSize = (int)pTemplateEEType->RawBaseSize; isValueType = pTemplateEEType->IsValueType; hasFinalizer = pTemplateEEType->IsFinalizable; isNullable = pTemplateEEType->IsNullable; @@ -269,7 +269,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo // Set basic MethodTable fields pEEType->Flags = flags; - pEEType->BaseSize = (uint)baseSize; + pEEType->RawBaseSize = (uint)baseSize; pEEType->NumVtableSlots = numVtableSlots; pEEType->NumInterfaces = runtimeInterfacesLength; pEEType->HashCode = hashCodeOfNewType; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index f6674fb35624e..627f9f95b1038 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -597,7 +597,7 @@ private unsafe void AllocateRuntimeType(TypeDesc type) if (state.ThreadDataSize != 0) TypeLoaderEnvironment.Instance.RegisterDynamicThreadStaticsInfo(state.HalfBakedRuntimeTypeHandle, state.ThreadStaticOffset, state.ThreadStaticDesc); - TypeLoaderLogger.WriteLine("Allocated new type " + type.ToString() + " with hashcode value = 0x" + type.GetHashCode().LowLevelToString() + " with MethodTable = " + rtt.ToIntPtr().LowLevelToString() + " of size " + rtt.ToEETypePtr()->BaseSize.LowLevelToString()); + TypeLoaderLogger.WriteLine("Allocated new type " + type.ToString() + " with hashcode value = 0x" + type.GetHashCode().LowLevelToString() + " with MethodTable = " + rtt.ToIntPtr().LowLevelToString() + " of size " + rtt.ToEETypePtr()->RawBaseSize.LowLevelToString()); } private static void AllocateRuntimeMethodDictionary(InstantiatedMethod method) diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index f96c671165c6f..82c5429493013 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2280,6 +2280,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { // /* +0x000 */ DWORD ContextFlags; + /* +0x004 */ DWORD Fcsr; // // Integer registers. @@ -2323,7 +2324,6 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { // // TODO-RISCV64: support the SIMD. ULONGLONG F[32]; - DWORD Fcsr; } CONTEXT, *PCONTEXT, *LPCONTEXT; // diff --git a/src/coreclr/pal/prebuilt/idl/sospriv_i.cpp b/src/coreclr/pal/prebuilt/idl/sospriv_i.cpp index 07f02d061e86c..141ec62612e48 100644 --- a/src/coreclr/pal/prebuilt/idl/sospriv_i.cpp +++ b/src/coreclr/pal/prebuilt/idl/sospriv_i.cpp @@ -5,9 +5,11 @@ /* link this file in with the server and any clients */ - /* File created by MIDL compiler version 8.01.0626 */ + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ /* Compiler settings for sospriv.idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0626 + Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: @@ -77,6 +79,9 @@ MIDL_DEFINE_GUID(IID, IID_ISOSStackRefErrorEnum,0x774F4E1B,0xFB7B,0x491B,0x97,0x MIDL_DEFINE_GUID(IID, IID_ISOSStackRefEnum,0x8FA642BD,0x9F10,0x4799,0x9A,0xA3,0x51,0x2A,0xE7,0x8C,0x77,0xEE); +MIDL_DEFINE_GUID(IID, IID_ISOSMemoryEnum,0xE4B860EC,0x337A,0x40C0,0xA5,0x91,0xF0,0x9A,0x96,0x80,0x69,0x0F); + + MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface,0x436f00f2,0xb42a,0x4b9f,0x87,0x0c,0xe7,0x3d,0xb6,0x6a,0xe9,0x30); @@ -113,7 +118,7 @@ MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface11,0x96BA1DB9,0x14CD,0x4492,0x80,0x65, MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface12,0x1b93bacc,0x8ca4,0x432d,0x94,0x3a,0x3e,0x6e,0x7e,0xc0,0xb0,0xa3); -MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface13,0x3176a8ed,0x597b,0x4f54,0xa7,0x1f,0x83,0x69,0x5c,0x6a,0x8c,0x5d); +MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface13,0x3176a8ed,0x597b,0x4f54,0xa7,0x1f,0x83,0x69,0x5c,0x6a,0x8c,0x5e); #undef MIDL_DEFINE_GUID diff --git a/src/coreclr/pal/prebuilt/inc/sospriv.h b/src/coreclr/pal/prebuilt/inc/sospriv.h index cc34480996560..e6f2b7b4f049e 100644 --- a/src/coreclr/pal/prebuilt/inc/sospriv.h +++ b/src/coreclr/pal/prebuilt/inc/sospriv.h @@ -73,6 +73,13 @@ typedef interface ISOSStackRefEnum ISOSStackRefEnum; #endif /* __ISOSStackRefEnum_FWD_DEFINED__ */ +#ifndef __ISOSMemoryEnum_FWD_DEFINED__ +#define __ISOSMemoryEnum_FWD_DEFINED__ +typedef interface ISOSMemoryEnum ISOSMemoryEnum; + +#endif /* __ISOSMemoryEnum_FWD_DEFINED__ */ + + #ifndef __ISOSDacInterface_FWD_DEFINED__ #define __ISOSDacInterface_FWD_DEFINED__ typedef interface ISOSDacInterface ISOSDacInterface; @@ -198,6 +205,7 @@ typedef int VCSHeapType; typedef enum { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE } ModuleMapType; typedef enum {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap, VtableHeap} VCSHeapType; typedef enum {LoaderHeapKindNormal = 0, LoaderHeapKindExplicitControl = 1} LoaderHeapKind; +typedef enum {FreeUnknownRegion = 0, FreeGlobalHugeRegion = 1, FreeGlobalRegion = 2, FreeRegion = 3, FreeSohSegment = 4, FreeUohSegment = 5 } FreeRegionKind; typedef void ( *MODULEMAPTRAVERSE )( UINT index, CLRDATA_ADDRESS methodTable, @@ -489,6 +497,17 @@ typedef struct _SOS_StackRefError extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0002_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0002_v0_0_s_ifspec; +#ifndef _SOS_MemoryRegion_ +#define _SOS_MemoryRegion_ +typedef struct _SOSMemoryRegion + { + CLRDATA_ADDRESS Start; + CLRDATA_ADDRESS Size; + CLRDATA_ADDRESS ExtraData; + int Heap; + } SOSMemoryRegion; +#endif // _SOS_MemoryRegion_ + #ifndef __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ #define __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ @@ -594,6 +613,112 @@ EXTERN_C const IID IID_ISOSStackRefErrorEnum; #endif /* __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ */ + +#ifndef __ISOSMemoryEnum_INTERFACE_DEFINED__ +#define __ISOSMemoryEnum_INTERFACE_DEFINED__ + +/* interface ISOSMemoryEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSMemoryEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E4B860EC-337A-40C0-A591-F09A9680690F") + ISOSMemoryEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSMemoryRegion memRegion[ ], + /* [out] */ unsigned int *pNeeded) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSMemoryEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSMemoryEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSMemoryEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSMemoryEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSMemoryEnum * This, + /* [in] */ unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSMemoryEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSMemoryEnum * This, + /* [out] */ unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSMemoryEnum * This, + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSMemoryRegion memRegion[ ], + /* [out] */ unsigned int *pNeeded); + + END_INTERFACE + } ISOSMemoryEnumVtbl; + + interface ISOSMemoryEnum + { + CONST_VTBL struct ISOSMemoryEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSMemoryEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSMemoryEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSMemoryEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSMemoryEnum_Skip(This,count) \ + ( (This)->lpVtbl -> Skip(This,count) ) + +#define ISOSMemoryEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ISOSMemoryEnum_GetCount(This,pCount) \ + ( (This)->lpVtbl -> GetCount(This,pCount) ) + + +#define ISOSMemoryEnum_Next(This,count,memRegion,pNeeded) \ + ( (This)->lpVtbl -> Next(This,count,memRegion,pNeeded) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSMemoryEnum_INTERFACE_DEFINED__ */ + + #ifndef __ISOSStackRefEnum_INTERFACE_DEFINED__ #define __ISOSStackRefEnum_INTERFACE_DEFINED__ @@ -3084,7 +3209,7 @@ EXTERN_C const IID IID_ISOSDacInterface13; #if defined(__cplusplus) && !defined(CINTERFACE) - MIDL_INTERFACE("3176a8ed-597b-4f54-a71f-83695c6a8c5d") + MIDL_INTERFACE("3176a8ed-597b-4f54-a71f-83695c6a8c5e") ISOSDacInterface13 : public IUnknown { public: @@ -3108,37 +3233,79 @@ EXTERN_C const IID IID_ISOSDacInterface13; CLRDATA_ADDRESS *pLoaderHeaps, LoaderHeapKind *pKinds, int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandleTableMemoryRegions( + ISOSMemoryEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCBookkeepingMemoryRegions( + ISOSMemoryEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCFreeRegions( + ISOSMemoryEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE LockedFlush( void) = 0; }; #else /* C style interface */ + typedef struct ISOSDacInterface13Vtbl { BEGIN_INTERFACE - DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface13 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface13 * This); - DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface13 * This); - DECLSPEC_XFGVIRT(ISOSDacInterface13, TraverseLoaderHeap) HRESULT ( STDMETHODCALLTYPE *TraverseLoaderHeap )( ISOSDacInterface13 * This, CLRDATA_ADDRESS loaderHeapAddr, LoaderHeapKind kind, VISITHEAP pCallback); + HRESULT ( STDMETHODCALLTYPE *GetDomainLoaderAllocator )( + ISOSDacInterface13 * This, + CLRDATA_ADDRESS domainAddress, + CLRDATA_ADDRESS *pLoaderAllocator); + + HRESULT ( STDMETHODCALLTYPE *GetLoaderAllocatorHeapNames )( + ISOSDacInterface13 * This, + int count, + const unsigned char **ppNames, + int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetLoaderAllocatorHeaps )( + ISOSDacInterface13 * This, + CLRDATA_ADDRESS loaderAllocator, + int count, + CLRDATA_ADDRESS *pLoaderHeaps, + LoaderHeapKind *pKinds, + int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetHandleTableMemoryRegions )( + ISOSDacInterface13 * This, + ISOSMemoryEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetGCBookkeepingMemoryRegions )( + ISOSDacInterface13 * This, + ISOSMemoryEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetGCFreeRegions )( + ISOSDacInterface13 * This, + ISOSMemoryEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *LockedFlush )( + ISOSDacInterface13 * This); + END_INTERFACE } ISOSDacInterface13Vtbl; diff --git a/src/coreclr/vm/decodemd.cpp b/src/coreclr/vm/decodemd.cpp index 6def9757c9b26..e1f7e8e3877a7 100644 --- a/src/coreclr/vm/decodemd.cpp +++ b/src/coreclr/vm/decodemd.cpp @@ -73,7 +73,6 @@ const BYTE decoded_10[2] = {10, END_DECODED }; #define DECODING_ERROR ((unsigned) -1) #define MASK(len) (~(~0u <<(len))) #define MASK64(len) ((~((~((unsigned __int64)0))<<(len)))) -#define BITS_PER_BYTE (sizeof(BYTE)*8) const Decoder::Decode emptyDecode = {decoded_end, DECODING_HEADER(0)}; diff --git a/src/coreclr/vm/riscv64/asmconstants.h b/src/coreclr/vm/riscv64/asmconstants.h index 12aedda2db5f8..e61abe2ea57e7 100644 --- a/src/coreclr/vm/riscv64/asmconstants.h +++ b/src/coreclr/vm/riscv64/asmconstants.h @@ -141,7 +141,7 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__GSCookie == sizeof(GSCookie)); #define SIZEOF__Frame 0x10 ASMCONSTANTS_C_ASSERT(SIZEOF__Frame == sizeof(Frame)); -#define SIZEOF__CONTEXT 0x220 +#define SIZEOF__CONTEXT 0x210 ASMCONSTANTS_C_ASSERT(SIZEOF__CONTEXT == sizeof(T_CONTEXT)); diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp index 26d55c4c07d6d..32a963787e02e 100644 --- a/src/coreclr/vm/virtualcallstub.cpp +++ b/src/coreclr/vm/virtualcallstub.cpp @@ -863,6 +863,7 @@ VirtualCallStubManager *VirtualCallStubManager::FindStubManager(PCODE stubAddres NOTHROW; GC_NOTRIGGER; FORBID_FAULT; + SUPPORTS_DAC; } CONTRACTL_END StubCodeBlockKind unusedStubKind; @@ -3696,56 +3697,7 @@ VirtualCallStubManager *VirtualCallStubManagerManager::FindVirtualCallStubManage SUPPORTS_DAC; -#ifndef DACCESS_COMPILE - // Check the cached element - { - VirtualCallStubManager *pMgr = m_pCacheElem; - if (pMgr != NULL && pMgr->CheckIsStub_Internal(stubAddress)) - { - return pMgr; - } - } - - // Check the current and shared domains. - { - Thread *pThread = GetThreadNULLOk(); - if (pThread != NULL) - { - // Check the current domain - { - BaseDomain *pDom = pThread->GetDomain(); - VirtualCallStubManager *pMgr = pDom->GetLoaderAllocator()->GetVirtualCallStubManager(); - if (pMgr->CheckIsStub_Internal(stubAddress)) - { - m_pCacheElem = pMgr; - return pMgr; - } - } - } - } -#endif - - // If both previous attempts fail, run through the list. This is likely - // because the thread is a debugger thread running outside of the domain - // that owns the target stub. - { - VirtualCallStubManagerIterator it = - VirtualCallStubManagerManager::GlobalManager()->IterateVirtualCallStubManagers(); - - while (it.Next()) - { - if (it.Current()->CheckIsStub_Internal(stubAddress)) - { -#ifndef DACCESS_COMPILE - m_pCacheElem = it.Current(); -#endif - return it.Current(); - } - } - } - - // No VirtualCallStubManager owns this address. - return NULL; + return VirtualCallStubManager::FindStubManager(stubAddress); } static VirtualCallStubManager * const IT_START = (VirtualCallStubManager *)(-1); @@ -3818,8 +3770,8 @@ BOOL VirtualCallStubManagerManager::CheckIsStub_Internal( WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - VirtualCallStubManager *pMgr = FindVirtualCallStubManager(stubStartAddress); - return (pMgr != NULL); + // Forwarded to from RangeSectionStubManager + return FALSE; } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs b/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs index 52882346b6322..0f7b1763d5850 100644 --- a/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs +++ b/src/libraries/Common/src/Interop/Interop.Locale.OSX.cs @@ -8,9 +8,21 @@ internal static partial class Interop internal static partial class Globalization { [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)] - internal static unsafe partial string GetLocaleNameNative(string localeName); + internal static partial string GetLocaleNameNative(string localeName); [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoStringNative", StringMarshalling = StringMarshalling.Utf8)] - internal static unsafe partial string GetLocaleInfoStringNative(string localeName, uint localeStringData); + internal static partial string GetLocaleInfoStringNative(string localeName, uint localeStringData); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoIntNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial int GetLocaleInfoIntNative(string localeName, uint localeNumberData); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial int GetLocaleInfoPrimaryGroupingSizeNative(string localeName, uint localeGroupingData); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial int GetLocaleInfoSecondaryGroupingSizeNative(string localeName, uint localeGroupingData); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleTimeFormatNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial string GetLocaleTimeFormatNative(string localeName, [MarshalAs(UnmanagedType.Bool)] bool shortFormat); } } diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj b/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj index 5920905308d2f..987e8547b27f0 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft.Win32.Registry.csproj @@ -9,6 +9,7 @@ $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) SR.PlatformNotSupported_Registry + $(NoWarn);IDE0280 Fields { get; } /// - /// Injects the trace values stroed in the object into a carrier. For example, into the headers of an HTTP request. + /// Injects the trace values stored in the object into a carrier. For example, into the headers of an HTTP request. /// /// The Activity object has the distributed context to inject to the carrier. /// Carrier is the medium in which the distributed context will be stored. diff --git a/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj b/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj index b2622d1a6afb9..b9887c1021aaf 100644 --- a/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj +++ b/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj @@ -1,10 +1,36 @@ - $(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst;$(NetCoreAppCurrent)-osx + $(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst true true + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs index 5c96ddaa896bb..822090c0819e1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs @@ -227,7 +227,7 @@ private async Task GetStringAsyncCore(HttpRequestMessage request, Cancel } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } @@ -306,7 +306,7 @@ private async Task GetByteArrayAsyncCore(HttpRequestMessage request, Can } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } @@ -352,7 +352,7 @@ private async Task GetStreamAsyncCore(HttpRequestMessage request, Cancel } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted: false); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted: false); } } @@ -496,7 +496,7 @@ public HttpResponseMessage Send(HttpRequestMessage request, HttpCompletionOption } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } @@ -551,7 +551,7 @@ async Task Core( } finally { - FinishSend(cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); + FinishSend(response, cts, disposeCts, telemetryStarted, responseContentTelemetryStarted); } } } @@ -583,8 +583,6 @@ private static bool ShouldBufferResponse(HttpCompletionOption completionOption, private void HandleFailure(Exception e, bool telemetryStarted, HttpResponseMessage? response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts) { - LogRequestFailed(telemetryStarted); - response?.Dispose(); Exception? toThrow = null; @@ -623,6 +621,8 @@ private void HandleFailure(Exception e, bool telemetryStarted, HttpResponseMessa e = toThrow = CancellationHelper.CreateOperationCanceledException(e, cancellationToken.IsCancellationRequested ? cancellationToken : cts.Token); } + LogRequestFailed(e, telemetryStarted); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, e); if (toThrow != null) @@ -642,7 +642,7 @@ private static bool StartSend(HttpRequestMessage request) return false; } - private static void FinishSend(CancellationTokenSource cts, bool disposeCts, bool telemetryStarted, bool responseContentTelemetryStarted) + private static void FinishSend(HttpResponseMessage? response, CancellationTokenSource cts, bool disposeCts, bool telemetryStarted, bool responseContentTelemetryStarted) { // Log completion. if (HttpTelemetry.Log.IsEnabled() && telemetryStarted) @@ -652,7 +652,7 @@ private static void FinishSend(CancellationTokenSource cts, bool disposeCts, boo HttpTelemetry.Log.ResponseContentStop(); } - HttpTelemetry.Log.RequestStop(); + HttpTelemetry.Log.RequestStop(response); } // Dispose of the CancellationTokenSource if it was created specially for this request diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs index a06da5b9ed5a2..ceb93c06a2aae 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs @@ -41,18 +41,20 @@ public virtual HttpResponseMessage Send(HttpRequestMessage request, Cancellation { HttpTelemetry.Log.RequestStart(request); + HttpResponseMessage? response = null; try { - return _handler.Send(request, cancellationToken); + response = _handler.Send(request, cancellationToken); + return response; } - catch when (LogRequestFailed(telemetryStarted: true)) + catch (Exception ex) when (LogRequestFailed(ex, telemetryStarted: true)) { // Unreachable as LogRequestFailed will return false throw; } finally { - HttpTelemetry.Log.RequestStop(); + HttpTelemetry.Log.RequestStop(response); } } else @@ -78,18 +80,20 @@ static async Task SendAsyncWithTelemetry(HttpMessageHandler { HttpTelemetry.Log.RequestStart(request); + HttpResponseMessage? response = null; try { - return await handler.SendAsync(request, cancellationToken).ConfigureAwait(false); + response = await handler.SendAsync(request, cancellationToken).ConfigureAwait(false); + return response; } - catch when (LogRequestFailed(telemetryStarted: true)) + catch (Exception ex) when (LogRequestFailed(ex, telemetryStarted: true)) { // Unreachable as LogRequestFailed will return false throw; } finally { - HttpTelemetry.Log.RequestStop(); + HttpTelemetry.Log.RequestStop(response); } } } @@ -100,11 +104,11 @@ private static bool ShouldSendWithTelemetry(HttpRequestMessage request) => request.RequestUri is Uri requestUri && requestUri.IsAbsoluteUri; - internal static bool LogRequestFailed(bool telemetryStarted) + internal static bool LogRequestFailed(Exception exception, bool telemetryStarted) { if (HttpTelemetry.Log.IsEnabled() && telemetryStarted) { - HttpTelemetry.Log.RequestFailed(); + HttpTelemetry.Log.RequestFailed(exception); } return false; } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs index 131748bddf5a8..8126bda265a33 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs @@ -13,6 +13,11 @@ internal sealed partial class HttpTelemetry : EventSource { public static readonly HttpTelemetry Log = new HttpTelemetry(); + public static class Keywords + { + public const EventKeywords RequestFailedDetailed = (EventKeywords)1; + } + private long _startedRequests; private long _stoppedRequests; private long _failedRequests; @@ -50,18 +55,39 @@ public void RequestStart(HttpRequestMessage request) request.VersionPolicy); } - [Event(2, Level = EventLevel.Informational)] - public void RequestStop() + [NonEvent] + public void RequestStop(HttpResponseMessage? response) + { + RequestStop(response is null ? -1 : (int)response.StatusCode); + } + + [Event(2, Level = EventLevel.Informational, Version = 1)] + private void RequestStop(int statusCode) { Interlocked.Increment(ref _stoppedRequests); - WriteEvent(eventId: 2); + WriteEvent(eventId: 2, statusCode); } - [Event(3, Level = EventLevel.Error)] - public void RequestFailed() + [NonEvent] + public void RequestFailed(Exception exception) { Interlocked.Increment(ref _failedRequests); - WriteEvent(eventId: 3); + + if (IsEnabled(EventLevel.Error, EventKeywords.None)) + { + RequestFailed(exceptionMessage: exception.Message); + + if (IsEnabled(EventLevel.Error, Keywords.RequestFailedDetailed)) + { + RequestFailedDetailed(exception: exception.ToString()); + } + } + } + + [Event(3, Level = EventLevel.Error, Version = 1)] + private void RequestFailed(string exceptionMessage) + { + WriteEvent(eventId: 3, exceptionMessage); } [Event(4, Level = EventLevel.Informational)] @@ -112,10 +138,10 @@ public void ResponseHeadersStart() WriteEvent(eventId: 11); } - [Event(12, Level = EventLevel.Informational)] - public void ResponseHeadersStop() + [Event(12, Level = EventLevel.Informational, Version = 1)] + public void ResponseHeadersStop(int statusCode) { - WriteEvent(eventId: 12); + WriteEvent(eventId: 12, statusCode); } [Event(13, Level = EventLevel.Informational)] @@ -130,6 +156,12 @@ public void ResponseContentStop() WriteEvent(eventId: 14); } + [Event(15, Level = EventLevel.Error, Keywords = Keywords.RequestFailedDetailed)] + private void RequestFailedDetailed(string exception) + { + WriteEvent(eventId: 15, exception); + } + [NonEvent] public void Http11ConnectionEstablished() { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index d5199afc6deb5..81aeaa63a9e29 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -1024,7 +1024,8 @@ public async Task ReadResponseHeadersAsync(CancellationToken cancellationToken) Debug.Assert(!wait); } - if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop(); + Debug.Assert(_response is not null); + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop((int)_response.StatusCode); } catch { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index 70b1690707ccb..5bb3a2941cd6f 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -352,7 +352,7 @@ private async Task ReadResponseAsync(CancellationToken cancellationToken) _headerState = HeaderState.TrailingHeaders; - if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop(); + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop((int)_response.StatusCode); } private async Task SendContentAsync(HttpContent content, CancellationToken cancellationToken) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index fbfa024a647cb..ba3b895b65e23 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -696,7 +696,7 @@ public async Task SendAsync(HttpRequestMessage request, boo await FillForHeadersAsync(async).ConfigureAwait(false); } - if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop(); + if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.ResponseHeadersStop((int)response.StatusCode); if (allowExpect100ToContinue != null) { diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs index b6bee89d36db7..9ac7d79660035 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs @@ -6,7 +6,6 @@ using System.Diagnostics.Tracing; using System.IO; using System.Linq; -using System.Net.Quic; using System.Net.Test.Common; using System.Text; using System.Threading; @@ -412,19 +411,40 @@ private static void ValidateStartFailedStopEvents(ConcurrentQueue<(EventWrittenE Assert.Equal(count, starts.Length); (EventWrittenEventArgs Event, Guid ActivityId)[] stops = events.Where(e => e.Event.EventName == "RequestStop").ToArray(); - Assert.All(stops, stopEvent => Assert.Empty(stopEvent.Event.Payload)); + foreach (EventWrittenEventArgs stopEvent in stops.Select(e => e.Event)) + { + object payload = Assert.Single(stopEvent.Payload); + int statusCode = Assert.IsType(payload); + Assert.Equal(shouldHaveFailures ? -1 : 200, statusCode); + } ValidateSameActivityIds(starts, stops); (EventWrittenEventArgs Event, Guid ActivityId)[] failures = events.Where(e => e.Event.EventName == "RequestFailed").ToArray(); - Assert.All(failures, failedEvent => Assert.Empty(failedEvent.Event.Payload)); + (EventWrittenEventArgs Event, Guid ActivityId)[] detailedFailures = events.Where(e => e.Event.EventName == "RequestFailedDetailed").ToArray(); if (shouldHaveFailures) { + foreach (EventWrittenEventArgs failedEvent in failures.Select(e => e.Event)) + { + object payload = Assert.Single(failedEvent.Payload); + string exceptionMessage = Assert.IsType(payload); + Assert.Equal(new OperationCanceledException().Message, exceptionMessage); + } + + foreach (EventWrittenEventArgs failedEvent in detailedFailures.Select(e => e.Event)) + { + object payload = Assert.Single(failedEvent.Payload); + string exception = Assert.IsType(payload); + Assert.StartsWith("System.Threading.Tasks.TaskCanceledException", exception); + } + ValidateSameActivityIds(starts, failures); + ValidateSameActivityIds(starts, detailedFailures); } else { Assert.Empty(failures); + Assert.Empty(detailedFailures); } } @@ -470,8 +490,8 @@ private static void ValidateRequestResponseStartStopEvents(ConcurrentQueue<(Even foreach (EventWrittenEventArgs requestContentStop in requestContentStops.Select(e => e.Event)) { object payload = Assert.Single(requestContentStop.Payload); - Assert.True(payload is long); - Assert.Equal(requestContentLength.Value, (long)payload); + long contentLength = Assert.IsType(payload); + Assert.Equal(requestContentLength.Value, contentLength); } ValidateSameActivityIds(requestContentStarts, requestContentStops); @@ -482,7 +502,12 @@ private static void ValidateRequestResponseStartStopEvents(ConcurrentQueue<(Even (EventWrittenEventArgs Event, Guid ActivityId)[] responseHeadersStops = events.Where(e => e.Event.EventName == "ResponseHeadersStop").ToArray(); Assert.Equal(count, responseHeadersStops.Length); - Assert.All(responseHeadersStops, r => Assert.Empty(r.Event.Payload)); + foreach (EventWrittenEventArgs responseHeadersStop in responseHeadersStops.Select(e => e.Event)) + { + object payload = Assert.Single(responseHeadersStop.Payload); + int statusCode = Assert.IsType(payload); + Assert.Equal(200, statusCode); + } ValidateSameActivityIds(responseHeadersStarts, responseHeadersStops); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs b/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs index 5667687e632e2..26ac057e31bd8 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Fakes/HttpTelemetry.cs @@ -11,9 +11,9 @@ public class HttpTelemetry public void RequestStart(HttpRequestMessage request) { } - public void RequestStop() { } + public void RequestStop(HttpResponseMessage response) { } - public void RequestFailed() { } + public void RequestFailed(Exception exception) { } public void ResponseContentStart() { } diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 56bf536c440c1..54f8c9feeb4d6 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -122,17 +122,17 @@ - + True True - TlsCipherSuiteData.Lookup.tt + SslConnectionInfo.Unix.tt - + True True - TlsCipherSuiteData.Lookup.tt + SslConnectionInfo.Unix.tt @@ -140,14 +140,14 @@ TextTemplatingFileGenerator TlsCipherSuite.cs - + TextTemplatingFileGenerator - TlsCipherSuiteData.Lookup.cs + SslConnectionInfo.Unix.cs - + @@ -285,8 +285,6 @@ Link="Common\System\Net\Security\Unix\SecChannelBindings.cs" /> - - keyExchangeAlgs = + new[] { (int)ExchangeAlgorithmType.None, (int)ExchangeAlgorithmType.RsaSign, (int)ExchangeAlgorithmType.RsaKeyX, (int)ExchangeAlgorithmType.DiffieHellman, }; + ReadOnlySpan dataCipherAlgs = + new[] { (int)CipherAlgorithmType.None, (int)CipherAlgorithmType.Null, (int)CipherAlgorithmType.Des, (int)CipherAlgorithmType.Rc2, (int)CipherAlgorithmType.TripleDes, (int)CipherAlgorithmType.Aes128, (int)CipherAlgorithmType.Aes192, (int)CipherAlgorithmType.Aes256, (int)CipherAlgorithmType.Aes, (int)CipherAlgorithmType.Rc4, }; + ReadOnlySpan dataKeySizes = + new[] { 0, 40, 56, 128, 168, 256 }; + ReadOnlySpan dataHashAlgs = + new[] { (int)HashAlgorithmType.None, (int)HashAlgorithmType.Md5, (int)HashAlgorithmType.Sha1, (int)HashAlgorithmType.Sha256, (int)HashAlgorithmType.Sha384, (int)HashAlgorithmType.Sha512, }; + ReadOnlySpan dataHashKeySizes = + new[] { 0, 128, 160, 256, 384, 512 }; + + int data = GetPackedData(cipherSuite); + Debug.Assert(data != 0, $"No mapping found for cipherSuite {cipherSuite}"); + + KeyExchangeAlg = keyExchangeAlgs[(data >> 12) & 0xF]; + DataCipherAlg = dataCipherAlgs[(data >> 8) & 0xF]; + DataKeySize = dataKeySizes[(data >> 4) & 0xF]; + DataHashAlg = dataHashAlgs[data & 0xF]; + DataHashKeySize = dataHashKeySizes[data & 0xF]; + + static int GetPackedData(TlsCipherSuite cipherSuite) + { + switch (cipherSuite) + { + case TlsCipherSuite.TLS_NULL_WITH_NULL_NULL: return 0 << 12 | 1 << 8 | 0 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_NULL_MD5: return 2 << 12 | 1 << 8 | 0 << 4 | 1; + case TlsCipherSuite.TLS_RSA_WITH_NULL_SHA: return 2 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5: return 2 << 12 | 9 << 8 | 1 << 4 | 1; + case TlsCipherSuite.TLS_RSA_WITH_RC4_128_MD5: return 2 << 12 | 9 << 8 | 3 << 4 | 1; + case TlsCipherSuite.TLS_RSA_WITH_RC4_128_SHA: return 2 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5: return 2 << 12 | 3 << 8 | 1 << 4 | 1; + case TlsCipherSuite.TLS_RSA_WITH_IDEA_CBC_SHA: return 2 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA: return 2 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_DES_CBC_SHA: return 2 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: return 2 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: return 3 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA: return 3 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: return 3 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA: return 3 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: return 3 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA: return 3 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: return 3 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA: return 3 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_EXPORT_WITH_RC4_40_MD5: return 3 << 12 | 9 << 8 | 1 << 4 | 1; + case TlsCipherSuite.TLS_DH_anon_WITH_RC4_128_MD5: return 3 << 12 | 9 << 8 | 3 << 4 | 1; + case TlsCipherSuite.TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA: return 3 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_DES_CBC_SHA: return 3 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_WITH_DES_CBC_SHA: return 0 << 12 | 2 << 8 | 2 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_WITH_3DES_EDE_CBC_SHA: return 0 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_WITH_RC4_128_SHA: return 0 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_WITH_IDEA_CBC_SHA: return 0 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_WITH_DES_CBC_MD5: return 0 << 12 | 2 << 8 | 2 << 4 | 1; + case TlsCipherSuite.TLS_KRB5_WITH_3DES_EDE_CBC_MD5: return 0 << 12 | 4 << 8 | 4 << 4 | 1; + case TlsCipherSuite.TLS_KRB5_WITH_RC4_128_MD5: return 0 << 12 | 9 << 8 | 3 << 4 | 1; + case TlsCipherSuite.TLS_KRB5_WITH_IDEA_CBC_MD5: return 0 << 12 | 0 << 8 | 3 << 4 | 1; + case TlsCipherSuite.TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA: return 0 << 12 | 2 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA: return 0 << 12 | 3 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC4_40_SHA: return 0 << 12 | 9 << 8 | 1 << 4 | 2; + case TlsCipherSuite.TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5: return 0 << 12 | 2 << 8 | 1 << 4 | 1; + case TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5: return 0 << 12 | 3 << 8 | 1 << 4 | 1; + case TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC4_40_MD5: return 0 << 12 | 9 << 8 | 1 << 4 | 1; + case TlsCipherSuite.TLS_PSK_WITH_NULL_SHA: return 0 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: return 2 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: return 2 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: return 2 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_NULL_SHA256: return 2 << 12 | 1 << 8 | 0 << 4 | 3; + case TlsCipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: return 2 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: return 2 << 12 | 7 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: return 2 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: return 3 << 12 | 7 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: return 3 << 12 | 7 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: return 3 << 12 | 7 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: return 3 << 12 | 7 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DH_anon_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA256: return 3 << 12 | 7 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: return 2 << 12 | 0 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: return 3 << 12 | 0 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: return 3 << 12 | 0 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: return 3 << 12 | 0 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: return 3 << 12 | 0 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA: return 3 << 12 | 0 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_PSK_WITH_RC4_128_SHA: return 0 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: return 0 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: return 0 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: return 0 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: return 2 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: return 2 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: return 2 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: return 2 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: return 2 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_DH_anon_WITH_SEED_CBC_SHA: return 3 << 12 | 0 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: return 2 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: return 2 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_anon_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_anon_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: return 0 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: return 2 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: return 2 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: return 0 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_PSK_WITH_NULL_SHA256: return 0 << 12 | 1 << 8 | 0 << 4 | 3; + case TlsCipherSuite.TLS_PSK_WITH_NULL_SHA384: return 0 << 12 | 1 << 8 | 0 << 4 | 4; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: return 3 << 12 | 1 << 8 | 0 << 4 | 3; + case TlsCipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: return 3 << 12 | 1 << 8 | 0 << 4 | 4; + case TlsCipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: return 2 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: return 2 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: return 2 << 12 | 1 << 8 | 0 << 4 | 3; + case TlsCipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: return 2 << 12 | 1 << 8 | 0 << 4 | 4; + case TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: return 2 << 12 | 0 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 3; + case TlsCipherSuite.TLS_AES_128_GCM_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_AES_256_GCM_SHA384: return 0 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256: return 0 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_AES_128_CCM_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_AES_128_CCM_8_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_anon_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_anon_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDH_anon_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: return 0 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: return 0 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: return 0 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: return 0 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: return 0 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: return 0 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: return 0 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: return 0 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: return 0 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: return 3 << 12 | 9 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: return 3 << 12 | 4 << 8 | 4 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: return 3 << 12 | 5 << 8 | 3 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: return 3 << 12 | 7 << 8 | 5 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: return 3 << 12 | 1 << 8 | 0 << 4 | 2; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: return 3 << 12 | 1 << 8 | 0 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: return 3 << 12 | 1 << 8 | 0 << 4 | 4; + case TlsCipherSuite.TLS_RSA_WITH_ARIA_128_CBC_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_WITH_ARIA_256_CBC_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DH_anon_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DH_anon_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_RSA_WITH_ARIA_128_GCM_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_ARIA_256_GCM_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_anon_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_anon_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_ARIA_128_CBC_SHA256: return 0 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_PSK_WITH_ARIA_256_CBC_SHA384: return 0 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_PSK_WITH_ARIA_128_GCM_SHA256: return 0 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_ARIA_256_GCM_SHA384: return 0 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: return 0 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: return 0 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: return 0 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: return 0 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: return 2 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: return 2 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: return 3 << 12 | 0 << 8 | 3 << 4 | 3; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: return 3 << 12 | 0 << 8 | 5 << 4 | 4; + case TlsCipherSuite.TLS_RSA_WITH_AES_128_CCM: return 2 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_AES_256_CCM: return 2 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_AES_128_CCM_8: return 2 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_RSA_WITH_AES_256_CCM_8: return 2 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_128_CCM: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_256_CCM: return 0 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_128_CCM_8: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_AES_256_CCM_8: return 0 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECCPWD_WITH_AES_128_GCM_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECCPWD_WITH_AES_256_GCM_SHA384: return 0 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECCPWD_WITH_AES_128_CCM_SHA256: return 0 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECCPWD_WITH_AES_256_CCM_SHA384: return 0 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: return 0 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: return 3 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256: return 2 << 12 | 0 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384: return 3 << 12 | 7 << 8 | 5 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + case TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256: return 3 << 12 | 5 << 8 | 3 << 4 | 0; + default: return 0; + } + } } } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslConnectionInfo.Unix.tt b/src/libraries/System.Net.Security/src/System/Net/Security/SslConnectionInfo.Unix.tt new file mode 100644 index 0000000000000..6d853177e69c4 --- /dev/null +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslConnectionInfo.Unix.tt @@ -0,0 +1,91 @@ +๏ปฟ<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ import namespace="System" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="System.Net.Primitives" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<#@ include file="TlsCipherSuiteNameParser.ttinclude" #><#@ + include file="TlsCipherSuite.cs" #> +<# Array tlsEnumValues = typeof(TlsCipherSuite).GetEnumValues(); #> +<# Array exchangeEnumValues = typeof(ExchangeAlgorithmTypeIndex).GetEnumValues(); #> +<# Array dataCipherAlgs = typeof(CipherAlgorithmTypeIndex).GetEnumValues(); #> +<# Array dataHashAlgs = typeof(HashAlgorithmTypeIndex).GetEnumValues(); #> + + +using System.Diagnostics; +using System.Security.Authentication; + +namespace System.Net.Security +{ + internal partial struct SslConnectionInfo + { + private void MapCipherSuite(TlsCipherSuite cipherSuite) + { + TlsCipherSuite = cipherSuite; + KeyExchKeySize = 0; + ReadOnlySpan keyExchangeAlgs = + new[] { <# +foreach (ExchangeAlgorithmTypeIndex val in exchangeEnumValues) +{ + #>(int)ExchangeAlgorithmType.<#= val #>, <# +} + #>}; + ReadOnlySpan dataCipherAlgs = + new[] { <# +foreach (CipherAlgorithmTypeIndex val in dataCipherAlgs) +{ + #>(int)CipherAlgorithmType.<#= val #>, <# +} + #>}; +<# +ReadOnlySpan strengths = new[] { 0, 40, 56, 128, 168, 256 }; +#> + ReadOnlySpan dataKeySizes = + new[] { <#= string.Join(", ", strengths.ToArray()) #> }; + ReadOnlySpan dataHashAlgs = + new[] { <# +foreach (HashAlgorithmTypeIndex val in dataHashAlgs) +{ + #>(int)HashAlgorithmType.<#= val #>, <# +} + #>}; + ReadOnlySpan dataHashKeySizes = + new[] { 0, 128, 160, 256, 384, 512 }; + + int data = GetPackedData(cipherSuite); + Debug.Assert(data != 0, $"No mapping found for cipherSuite {cipherSuite}"); + + KeyExchangeAlg = keyExchangeAlgs[(data >> 12) & 0xF]; + DataCipherAlg = dataCipherAlgs[(data >> 8) & 0xF]; + DataKeySize = dataKeySizes[(data >> 4) & 0xF]; + DataHashAlg = dataHashAlgs[data & 0xF]; + DataHashKeySize = dataHashKeySizes[data & 0xF]; + + static int GetPackedData(TlsCipherSuite cipherSuite) + { + switch (cipherSuite) + { +<# +foreach (TlsCipherSuite val in tlsEnumValues) +{ + TlsCipherSuiteData data = new CipherSuiteNameData(val.ToString()).Data; + int exchangeAlgorithmType = (int)Enum.Parse(EnumHelpers.ToFrameworkName(data.KeyExchangeAlgorithm)); + int cipherAlgorithmType = (int)Enum.Parse(EnumHelpers.ToFrameworkName(data.CipherAlgorithm)); + int cipherAlgorithmStrength = (int)strengths.IndexOf(data.CipherAlgorithmStrength); + int hashAlgorithmType = (int)Enum.Parse(EnumHelpers.ToFrameworkName(data.MACAlgorithm)); + + if (cipherAlgorithmStrength == -1) + throw new Exception($"Value '{data.CipherAlgorithmStrength}' is not found in 'strengths' array."); +#> + case TlsCipherSuite.<#= val #>: return <#= exchangeAlgorithmType #> << 12 | <#= cipherAlgorithmType #> << 8 | <#= cipherAlgorithmStrength #> << 4 | <#= hashAlgorithmType #>; +<# +} +#> + default: return 0; + } + } + } + } +} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.Lookup.cs b/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.Lookup.cs deleted file mode 100644 index 9a97c04b1b634..0000000000000 --- a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.Lookup.cs +++ /dev/null @@ -1,3394 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// This file has been auto-generated. Do not edit by hand. -// Instead open Developer Command prompt and run: TextTransform FileName.tt -// Or set AllowTlsCipherSuiteGeneration=true and open VS and edit there directly - -// This line is needed so that file compiles both as a T4 template and C# file - -using System.Collections.Generic; -using System.Security.Authentication; - -namespace System.Net.Security -{ - internal partial struct TlsCipherSuiteData - { - private const int LookupCount = 337; - - private static readonly Dictionary s_tlsLookup = - new Dictionary(LookupCount) - { - { - TlsCipherSuite.TLS_NULL_WITH_NULL_NULL, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_NULL_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_RC4_128_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Rc2, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_IDEA_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_RC4_128_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_DES_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_IDEA_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_DES_CBC_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 56, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_3DES_EDE_CBC_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_RC4_128_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_KRB5_WITH_IDEA_CBC_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc2, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC4_40_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Des, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc2, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_KRB5_EXPORT_WITH_RC4_40_MD5, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 40, - MACAlgorithm = HashAlgorithmType.Md5, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_NULL_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_SEED_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_SEED_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_NULL_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_NULL_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_AES_128_CCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_AES_128_CCM_8_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_anon_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_anon_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDH_anon_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Rc4, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.TripleDes, - CipherAlgorithmStrength = 168, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha1, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Null, - CipherAlgorithmStrength = 0, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.Sha256, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.Sha384, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_128_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_256_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_128_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_WITH_AES_256_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_128_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_256_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_128_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_AES_256_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECCPWD_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECCPWD_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECCPWD_WITH_AES_128_CCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECCPWD_WITH_AES_256_CCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.None, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.RsaKeyX, - CipherAlgorithm = CipherAlgorithmType.None, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes256, - CipherAlgorithmStrength = 256, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - { - TlsCipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.DiffieHellman, - CipherAlgorithm = CipherAlgorithmType.Aes128, - CipherAlgorithmStrength = 128, - MACAlgorithm = HashAlgorithmType.None, - } - }, - }; - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.Lookup.tt b/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.Lookup.tt deleted file mode 100644 index a36c425ccb0a8..0000000000000 --- a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.Lookup.tt +++ /dev/null @@ -1,45 +0,0 @@ -๏ปฟ<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ import namespace="System" #> -<#@ assembly name="System.Core" #> -<#@ assembly name="System.Net.Primitives" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ output extension=".cs" #> -<#@ include file="TlsCipherSuiteNameParser.ttinclude" #><#@ - include file="TlsCipherSuite.cs" #> -<# Array enumValues = typeof(TlsCipherSuite).GetEnumValues(); #> - -using System.Collections.Generic; -using System.Security.Authentication; - -namespace System.Net.Security -{ - internal partial struct TlsCipherSuiteData - { - private const int LookupCount = <#= enumValues.Length #>; - - private static readonly Dictionary s_tlsLookup = - new Dictionary(LookupCount) - { -<# -foreach (TlsCipherSuite val in enumValues) -{ - TlsCipherSuiteData data = new CipherSuiteNameData(val.ToString()).Data; -#> - { - TlsCipherSuite.<#= val #>, - new TlsCipherSuiteData() - { - KeyExchangeAlgorithm = ExchangeAlgorithmType.<#= EnumHelpers.ToFrameworkName(data.KeyExchangeAlgorithm) #>, - CipherAlgorithm = CipherAlgorithmType.<#= EnumHelpers.ToFrameworkName(data.CipherAlgorithm) #>, - CipherAlgorithmStrength = <#= data.CipherAlgorithmStrength #>, - MACAlgorithm = HashAlgorithmType.<#= EnumHelpers.ToFrameworkName(data.MACAlgorithm) #>, - } - }, -<# -} -#> - }; - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.cs b/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.cs deleted file mode 100644 index c422b9a7528cb..0000000000000 --- a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteData.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics; -using System.Security.Authentication; - -namespace System.Net.Security -{ - internal partial struct TlsCipherSuiteData - { - internal ExchangeAlgorithmType KeyExchangeAlgorithm; - // The Key Exchange size isn't part of the CipherSuite - internal CipherAlgorithmType CipherAlgorithm; - internal int CipherAlgorithmStrength; - internal HashAlgorithmType MACAlgorithm; - internal int MACAlgorithmStrength => GetHashSize(MACAlgorithm); - -#if DEBUG - static TlsCipherSuiteData() - { - Debug.Assert( - s_tlsLookup.Count == LookupCount, - $"Lookup dictionary was of size {s_tlsLookup.Count} instead of {LookupCount}"); - - foreach (TlsCipherSuite value in Enum.GetValues()) - { - Debug.Assert(s_tlsLookup.ContainsKey(value), $"No mapping found for {value} ({value:X})"); - } - } - - public override string ToString() - { - return $"Kx={KeyExchangeAlgorithm} Enc={CipherAlgorithm} [{CipherAlgorithmStrength}] Mac={MACAlgorithm} [{MACAlgorithmStrength}]"; - } -#endif - - public static TlsCipherSuiteData GetCipherSuiteData(TlsCipherSuite cipherSuite) - { - if (s_tlsLookup.TryGetValue(cipherSuite, out TlsCipherSuiteData mapping)) - { - return mapping; - } - - Debug.Fail($"No mapping found for cipherSuite {cipherSuite}"); - return default(TlsCipherSuiteData); - } - - private static int GetHashSize(HashAlgorithmType hash) - { - switch (hash) - { - case HashAlgorithmType.None: - return 0; - case HashAlgorithmType.Md5: - return 128; - case HashAlgorithmType.Sha1: - return 160; - case HashAlgorithmType.Sha256: - return 256; - case HashAlgorithmType.Sha384: - return 384; - case HashAlgorithmType.Sha512: - return 512; - default: - throw new ArgumentOutOfRangeException(nameof(hash)); - } - } - } -} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteNameParser.ttinclude b/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteNameParser.ttinclude index 7a3dee3296d80..a24c8a5b5d119 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteNameParser.ttinclude +++ b/src/libraries/System.Net.Security/src/System/Net/Security/TlsCipherSuiteNameParser.ttinclude @@ -70,6 +70,38 @@ public enum HashAlgorithmType Aead, } +public enum CipherAlgorithmTypeIndex +{ + None, + Null, + Des, + Rc2, + TripleDes, + Aes128, + Aes192, + Aes256, + Aes, + Rc4, +} + +public enum ExchangeAlgorithmTypeIndex +{ + None, + RsaSign, + RsaKeyX, + DiffieHellman, +} + +public enum HashAlgorithmTypeIndex +{ + None, + Md5, + Sha1, + Sha256, + Sha384, + Sha512 +} + internal static class EnumHelpers { public static string ToFrameworkName(ExchangeAlgorithmType val) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Guid.cs index 8effbc24857b0..3e64fbd3ec754 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Guid.cs @@ -1,83 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.Arm; -using System.Runtime.Intrinsics.X86; - namespace System.Buffers.Text { public static partial class Utf8Formatter { - #region Constants - - private const byte OpenBrace = (byte)'{'; - private const byte CloseBrace = (byte)'}'; - - private const byte OpenParen = (byte)'('; - private const byte CloseParen = (byte)')'; - - private const byte Dash = (byte)'-'; - - #endregion Constants - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static (Vector128, Vector128, Vector128) FormatGuidVector128Utf8(Guid value, bool useDashes) - { - Debug.Assert((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian); - // Vectorized implementation for D, N, P and B formats: - // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] - - Vector128 hexMap = Vector128.Create( - (byte)'0', (byte)'1', (byte)'2', (byte)'3', - (byte)'4', (byte)'5', (byte)'6', (byte)'7', - (byte)'8', (byte)'9', (byte)'a', (byte)'b', - (byte)'c', (byte)'d', (byte)'e', (byte)'f'); - - Vector128 srcVec = Unsafe.As>(ref value); - (Vector128 hexLow, Vector128 hexHigh) = - HexConverter.AsciiToHexVector128(srcVec, hexMap); - - // because of Guid's layout (int _a, short _b, _c, <8 byte fields>) - // we have to shuffle some bytes for _a, _b and _c - hexLow = Vector128.Shuffle(hexLow.AsInt16(), Vector128.Create(3, 2, 1, 0, 5, 4, 7, 6)).AsByte(); - - if (useDashes) - { - // We divide 16 bytes into 3 x Vector128: - // - // ________-____-____-____-____________ - // xxxxxxxxxxxxxxxx - // yyyyyyyyyyyyyyyy - // zzzzzzzzzzzzzzzz - // - // Vector "x" - just one dash, shift all elements after it. - Vector128 vecX = Vector128.Shuffle(hexLow, - Vector128.Create(0x706050403020100, 0xD0CFF0B0A0908FF).AsByte()); - - // Vector "y" - same here. - Vector128 vecY = Vector128.Shuffle(hexHigh, - Vector128.Create(0x7060504FF030201, 0xF0E0D0C0B0A0908).AsByte()); - - // Vector "z" - we need to merge some elements of hexLow with hexHigh and add 4 dashes. - Vector128 mid1 = Vector128.Shuffle(hexLow, - Vector128.Create(0x0D0CFF0B0A0908FF, 0xFFFFFFFFFFFF0F0E).AsByte()); - Vector128 mid2 = Vector128.Shuffle(hexHigh, - Vector128.Create(0xFFFFFFFFFFFFFFFF, 0xFF03020100FFFFFF).AsByte()); - Vector128 dashesMask = Vector128.Shuffle(Vector128.CreateScalarUnsafe((byte)'-'), - Vector128.Create(0xFFFF00FFFFFFFF00, 0x00FFFFFFFF00FFFF).AsByte()); - - Vector128 vecZ = (mid1 | mid2 | dashesMask); - return (vecX, vecY, vecZ); - } - - // N format - no dashes. - return (hexLow, hexHigh, default); - } - /// /// Formats a Guid as a UTF8 string. /// @@ -101,41 +28,24 @@ internal static (Vector128, Vector128, Vector128) FormatGuidVe /// public static bool TryFormat(Guid value, Span destination, out int bytesWritten, StandardFormat format = default) { - const int INSERT_DASHES = unchecked((int)0x80000000); - const int NO_DASHES = 0; - const int INSERT_CURLY_BRACES = (CloseBrace << 16) | (OpenBrace << 8); - const int INSERT_ROUND_BRACES = (CloseParen << 16) | (OpenParen << 8); - const int NO_BRACES = 0; - const int LEN_GUID_BASE = 32; - const int LEN_ADD_DASHES = 4; - const int LEN_ADD_BRACES = 2; - - // This is a 32-bit value whose contents (where 0 is the low byte) are: - // 0th byte: minimum required length of the output buffer, - // 1st byte: the ASCII byte to insert for the opening brace position (or 0 if no braces), - // 2nd byte: the ASCII byte to insert for the closing brace position (or 0 if no braces), - // 3rd byte: high bit set if dashes are to be inserted. - // - // The reason for keeping a single flag instead of separate vars is that we can avoid register spillage - // as we build up the output value. int flags; switch (FormattingHelpers.GetSymbolOrDefault(format, 'D')) { case 'D': // nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn - flags = INSERT_DASHES + NO_BRACES + LEN_GUID_BASE + LEN_ADD_DASHES; + flags = 36 + Guid.TryFormatFlags_UseDashes; break; case 'B': // {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn} - flags = INSERT_DASHES + INSERT_CURLY_BRACES + LEN_GUID_BASE + LEN_ADD_DASHES + LEN_ADD_BRACES; + flags = 38 + Guid.TryFormatFlags_UseDashes + Guid.TryFormatFlags_CurlyBraces; break; case 'P': // (nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn) - flags = INSERT_DASHES + INSERT_ROUND_BRACES + LEN_GUID_BASE + LEN_ADD_DASHES + LEN_ADD_BRACES; + flags = 38 + Guid.TryFormatFlags_UseDashes + Guid.TryFormatFlags_Parens; break; case 'N': // nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn - flags = NO_BRACES + NO_DASHES + LEN_GUID_BASE; + flags = 32; break; default: @@ -143,191 +53,7 @@ public static bool TryFormat(Guid value, Span destination, out int bytesWr goto case 'D'; // unreachable } - // At this point, the low byte of flags contains the minimum required length - - if ((byte)flags > destination.Length) - { - bytesWritten = 0; - return false; - } - - bytesWritten = (byte)flags; - flags >>= 8; - - // At this point, the low byte of flags contains the opening brace char (if any) - - if ((byte)flags != 0) - { - destination[0] = (byte)flags; - destination = destination.Slice(1); - } - flags >>= 8; - - if ((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian) - { - // Vectorized implementation for D, N, P and B formats: - // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] - (Vector128 vecX, Vector128 vecY, Vector128 vecZ) = - FormatGuidVector128Utf8(value, flags < 0 /*dash*/); - - ref byte dest = ref MemoryMarshal.GetReference(destination); - if (flags < 0) - { - // We need to merge these vectors in this order: - // xxxxxxxxxxxxxxxx - // yyyyyyyyyyyyyyyy - // zzzzzzzzzzzzzzzz - vecX.StoreUnsafe(ref dest, 0); - vecY.StoreUnsafe(ref dest, 20); - vecZ.StoreUnsafe(ref dest, 8); - } - else - { - // xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyy - vecX.StoreUnsafe(ref dest, 0); - vecY.StoreUnsafe(ref dest, 16); - } - if ((byte)flags != 0) - Unsafe.Add(ref dest, flags < 0 ? 36 : 32) = (byte)flags; - return true; - } - - // At this point, the low byte of flags contains the closing brace char (if any) - // And since we're performing arithmetic shifting the high bit of flags is set (flags is negative) if dashes are required - - DecomposedGuid guidAsBytes = default; - guidAsBytes.Guid = value; - - // When a GUID is blitted, the first three components are native-endian, and the last component is big-endian. - - // The line below forces the JIT to hoist the bounds check for the following segment. - // The JIT will optimize away the read, but it cannot optimize away the bounds check - // because it may have an observable side effect (throwing). - // We use 8 instead of 7 so that we also capture the dash if we're asked to insert one. - - { _ = destination[8]; } - if (BitConverter.IsLittleEndian) - { - HexConverter.ToBytesBuffer(guidAsBytes.Byte03, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte02, destination, 2, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte01, destination, 4, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte00, destination, 6, HexConverter.Casing.Lower); - } - else - { - HexConverter.ToBytesBuffer(guidAsBytes.Byte00, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte01, destination, 2, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte02, destination, 4, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte03, destination, 6, HexConverter.Casing.Lower); - } - - if (flags < 0 /* use dash? */) - { - destination[8] = Dash; - destination = destination.Slice(9); - } - else - { - destination = destination.Slice(8); - } - - { _ = destination[4]; } - if (BitConverter.IsLittleEndian) - { - HexConverter.ToBytesBuffer(guidAsBytes.Byte05, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte04, destination, 2, HexConverter.Casing.Lower); - } - else - { - HexConverter.ToBytesBuffer(guidAsBytes.Byte04, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte05, destination, 2, HexConverter.Casing.Lower); - } - - if (flags < 0 /* use dash? */) - { - destination[4] = Dash; - destination = destination.Slice(5); - } - else - { - destination = destination.Slice(4); - } - - { _ = destination[4]; } - if (BitConverter.IsLittleEndian) - { - HexConverter.ToBytesBuffer(guidAsBytes.Byte07, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte06, destination, 2, HexConverter.Casing.Lower); - } - else - { - HexConverter.ToBytesBuffer(guidAsBytes.Byte06, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte07, destination, 2, HexConverter.Casing.Lower); - } - - if (flags < 0 /* use dash? */) - { - destination[4] = Dash; - destination = destination.Slice(5); - } - else - { - destination = destination.Slice(4); - } - - { _ = destination[4]; } - HexConverter.ToBytesBuffer(guidAsBytes.Byte08, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte09, destination, 2, HexConverter.Casing.Lower); - - if (flags < 0 /* use dash? */) - { - destination[4] = Dash; - destination = destination.Slice(5); - } - else - { - destination = destination.Slice(4); - } - - { _ = destination[11]; } // can't hoist bounds check on the final brace (if exists) - HexConverter.ToBytesBuffer(guidAsBytes.Byte10, destination, 0, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte11, destination, 2, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte12, destination, 4, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte13, destination, 6, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte14, destination, 8, HexConverter.Casing.Lower); - HexConverter.ToBytesBuffer(guidAsBytes.Byte15, destination, 10, HexConverter.Casing.Lower); - - if ((byte)flags != 0) - { - destination[12] = (byte)flags; - } - - return true; - } - - /// - /// Used to provide access to the individual bytes of a GUID. - /// - [StructLayout(LayoutKind.Explicit)] - private struct DecomposedGuid - { - [FieldOffset(00)] public Guid Guid; - [FieldOffset(00)] public byte Byte00; - [FieldOffset(01)] public byte Byte01; - [FieldOffset(02)] public byte Byte02; - [FieldOffset(03)] public byte Byte03; - [FieldOffset(04)] public byte Byte04; - [FieldOffset(05)] public byte Byte05; - [FieldOffset(06)] public byte Byte06; - [FieldOffset(07)] public byte Byte07; - [FieldOffset(08)] public byte Byte08; - [FieldOffset(09)] public byte Byte09; - [FieldOffset(10)] public byte Byte10; - [FieldOffset(11)] public byte Byte11; - [FieldOffset(12)] public byte Byte12; - [FieldOffset(13)] public byte Byte13; - [FieldOffset(14)] public byte Byte14; - [FieldOffset(15)] public byte Byte15; + return value.TryFormatCore(destination, out bytesWritten, flags); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs index e90fb025a1b67..6716614028f66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs @@ -23,7 +23,8 @@ public readonly struct Byte IMinMaxValue, IUnsignedNumber, IUtf8SpanFormattable, - IUtfChar + IUtfChar, + IBinaryIntegerParseAndFormatInfo { private readonly byte m_value; // Do not rename (binary serialization) @@ -92,98 +93,44 @@ public override int GetHashCode() return m_value; } - public static byte Parse(string s) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static byte Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static byte Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.CurrentInfo); - } + public static byte Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static byte Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static byte Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - // 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) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static byte Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Parse(s, style, NumberFormatInfo.GetInstance(provider)); - } - - private static byte Parse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info) - { - Number.ParsingStatus status = Number.TryParseUInt32(s, style, info, out uint i); - if (status != Number.ParsingStatus.OK) - { - Number.ThrowOverflowOrFormatException(status, s, TypeCode.Byte); - } - - if (i > MaxValue) Number.ThrowOverflowException(TypeCode.Byte); - return (byte)i; + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out byte result) - { - if (s == null) - { - result = 0; - return false; - } + public static bool TryParse([NotNullWhen(true)] string? s, out byte result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - return TryParse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } - - public static bool TryParse(ReadOnlySpan s, out byte result) - { - return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } + public static bool TryParse(ReadOnlySpan s, out byte result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out byte result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return TryParse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider), out result); + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out byte result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result); - } - - private static bool TryParse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info, out byte result) - { - if (Number.TryParseUInt32(s, style, info, out uint i) != Number.ParsingStatus.OK - || i > MaxValue) - { - result = 0; - return false; - } - result = (byte)i; - return true; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public override string ToString() @@ -1213,5 +1160,25 @@ static bool INumberBase.TryConvertToTruncating(byte value, [MaybeN static byte IUtfChar.CastFrom(int value) => (byte)value; static byte IUtfChar.CastFrom(uint value) => (byte)value; static byte IUtfChar.CastFrom(ulong value) => (byte)value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => false; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 3; // 255 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 2; // 0xFF + + static byte IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_Byte; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(byte left, byte right) => left > right; + + static byte IBinaryIntegerParseAndFormatInfo.MultiplyBy10(byte value) => (byte)(value * 10); + + static byte IBinaryIntegerParseAndFormatInfo.MultiplyBy16(byte value) => (byte)(value * 16); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index 7d0c8dc2e7d3e..bac465382d004 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -36,7 +36,8 @@ public readonly struct Char IMinMaxValue, IUnsignedNumber, IUtf8SpanFormattable, - IUtfChar + IUtfChar, + IBinaryIntegerParseAndFormatInfo { // // Member Variables @@ -201,29 +202,37 @@ bool IUtf8SpanFormattable.TryFormat(Span utf8Destination, out int bytesWri public static char Parse(string s) { - if (s == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - } + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan()); + } + internal static char Parse(ReadOnlySpan s) + { if (s.Length != 1) { - throw new FormatException(SR.Format_NeedSingleChar); + ThrowHelper.ThrowFormatException_NeedSingleChar(); } return s[0]; } public static bool TryParse([NotNullWhen(true)] string? s, out char result) { - result = '\0'; - if (s == null) + if (s is null) { + result = '\0'; return false; } + return TryParse(s.AsSpan(), out result); + } + + internal static bool TryParse(ReadOnlySpan s, out char result) + { if (s.Length != 1) { + result = '\0'; return false; } + result = s[0]; return true; } @@ -1509,14 +1518,7 @@ bool IBinaryInteger.TryWriteLittleEndian(Span destination, out int b static char INumberBase.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s); - static char INumberBase.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) - { - if (s.Length != 1) - { - throw new FormatException(SR.Format_NeedSingleChar); - } - return s[0]; - } + static char INumberBase.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1930,16 +1932,7 @@ static bool INumberBase.TryConvertToTruncating(char value, [MaybeN static bool INumberBase.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out char result) => TryParse(s, out result); - static bool INumberBase.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out char result) - { - if (s.Length != 1) - { - result = default; - return false; - } - result = s[0]; - return true; - } + static bool INumberBase.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out char result) => TryParse(s, out result); // // IParsable @@ -1966,25 +1959,9 @@ static bool INumberBase.TryParse(ReadOnlySpan s, NumberStyles style, // ISpanParsable // - static char ISpanParsable.Parse(ReadOnlySpan s, IFormatProvider? provider) - { - if (s.Length != 1) - { - throw new FormatException(SR.Format_NeedSingleChar); - } - return s[0]; - } + static char ISpanParsable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s); - static bool ISpanParsable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out char result) - { - if (s.Length != 1) - { - result = default; - return false; - } - result = s[0]; - return true; - } + static bool ISpanParsable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out char result) => TryParse(s, out result); // // ISubtractionOperators @@ -2022,5 +1999,25 @@ static bool ISpanParsable.TryParse(ReadOnlySpan s, IFormatProvider? static char IUtfChar.CastFrom(int value) => (char)value; static char IUtfChar.CastFrom(uint value) => (char)value; static char IUtfChar.CastFrom(ulong value) => (char)value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => false; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 5; // 65_535 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 4; // 0xFFFF + + static char IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => (char)(MaxValue / 10); + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_Char; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(char left, char right) => left > right; + + static char IBinaryIntegerParseAndFormatInfo.MultiplyBy10(char value) => (char)(value * 10); + + static char IBinaryIntegerParseAndFormatInfo.MultiplyBy16(char value) => (char)(value * 16); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs index 33a5beae402de..bb7fbaa73fffa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs @@ -781,35 +781,35 @@ static bool TryParseRareTypes(RuntimeType rt, ReadOnlySpan value, bool ign { case CorElementType.ELEMENT_TYPE_R4: { - parsed = TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out float localResult); + parsed = TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out float localResult); result = BitConverter.SingleToInt32Bits(localResult); } break; case CorElementType.ELEMENT_TYPE_R8: { - parsed = TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out double localResult); + parsed = TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out double localResult); result = BitConverter.DoubleToInt64Bits(localResult); } break; case CorElementType.ELEMENT_TYPE_I: { - parsed = TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out nint localResult); + parsed = TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out nint localResult); result = localResult; } break; case CorElementType.ELEMENT_TYPE_U: { - parsed = TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out nuint localResult); + parsed = TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out nuint localResult); result = (long)localResult; } break; case CorElementType.ELEMENT_TYPE_CHAR: { - parsed = TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out char localResult); + parsed = TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out char localResult); result = localResult; } break; @@ -901,11 +901,11 @@ private static bool TryParse(ReadOnlySpan value, bool ignoreCase, b if (underlyingType == typeof(long)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); if (underlyingType == typeof(ulong)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); #if RARE_ENUMS - if (underlyingType == typeof(nint)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); - if (underlyingType == typeof(nuint)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); - if (underlyingType == typeof(float)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); - if (underlyingType == typeof(double)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); - if (underlyingType == typeof(char)) return TryParseByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); + if (underlyingType == typeof(nint)) return TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); + if (underlyingType == typeof(nuint)) return TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); + if (underlyingType == typeof(float)) return TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); + if (underlyingType == typeof(double)) return TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); + if (underlyingType == typeof(char)) return TryParseRareTypeByValueOrName(rt, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); #endif throw CreateUnknownEnumTypeException(); @@ -914,8 +914,8 @@ private static bool TryParse(ReadOnlySpan value, bool ignoreCase, b /// Core implementation for all {Try}Parse methods, both generic and non-generic, parsing either by value or by name. private static unsafe bool TryParseByValueOrName( RuntimeType enumType, ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out TUnderlying result) - where TUnderlying : struct, INumber, IBitwiseOperators, IMinMaxValue - where TStorage : struct, INumber, IBitwiseOperators, IMinMaxValue + where TUnderlying : unmanaged, IBinaryIntegerParseAndFormatInfo + where TStorage : unmanaged, IBinaryIntegerParseAndFormatInfo { AssertValidGenerics(); @@ -942,89 +942,77 @@ private static unsafe bool TryParseByValueOrName( NumberFormatInfo numberFormat = CultureInfo.InvariantCulture.NumberFormat; const NumberStyles NumberStyle = NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingWhite; - Number.ParsingStatus status; - if (typeof(TUnderlying) == typeof(int)) + Number.ParsingStatus status = Number.TryParseBinaryIntegerStyle(value, NumberStyle, numberFormat, out result); + if (status == Number.ParsingStatus.OK) { - Unsafe.SkipInit(out result); - status = Number.TryParseInt32IntegerStyle(value, NumberStyle, numberFormat, out Unsafe.As(ref result)); - if (status == Number.ParsingStatus.OK) - { - return true; - } + return true; } - else if (typeof(TUnderlying) == typeof(uint)) + + if (status != Number.ParsingStatus.Overflow) { Unsafe.SkipInit(out result); - status = Number.TryParseUInt32IntegerStyle(value, NumberStyle, numberFormat, out Unsafe.As(ref result)); - if (status == Number.ParsingStatus.OK) - { - return true; - } + return TryParseByName(enumType, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); } - else if (typeof(TUnderlying) == typeof(long)) + + if (throwOnFailure) { - Unsafe.SkipInit(out result); - status = Number.TryParseInt64IntegerStyle(value, NumberStyle, numberFormat, out Unsafe.As(ref result)); - if (status == Number.ParsingStatus.OK) + Number.ThrowOverflowException(Type.GetTypeCode(typeof(TUnderlying))); + } + } + + ParseFailure: + if (throwOnFailure) + { + ThrowInvalidEmptyParseArgument(); + } + + result = default; + return false; + } + + private static unsafe bool TryParseRareTypeByValueOrName( + RuntimeType enumType, ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out TUnderlying result) + where TUnderlying : struct, INumber, IBitwiseOperators, IMinMaxValue + where TStorage : struct, INumber, IBitwiseOperators, IMinMaxValue + { + AssertValidGenerics(); + + if (!value.IsEmpty) + { + char c = value[0]; + if (char.IsWhiteSpace(c)) + { + value = value.TrimStart(); + if (value.IsEmpty) { - return true; + goto ParseFailure; } + + c = value[0]; } - else if (typeof(TUnderlying) == typeof(ulong)) + + if (!char.IsAsciiDigit(c) && c != '-' && c != '+') { Unsafe.SkipInit(out result); - status = Number.TryParseUInt64IntegerStyle(value, NumberStyle, numberFormat, out Unsafe.As(ref result)); - if (status == Number.ParsingStatus.OK) - { - return true; - } + return TryParseByName(enumType, value, ignoreCase, throwOnFailure, out Unsafe.As(ref result)); } - else if (typeof(TUnderlying) == typeof(byte) || typeof(TUnderlying) == typeof(ushort)) + +#if RARE_ENUMS + Number.ParsingStatus status; + Type underlyingType = GetUnderlyingType(enumType); + + try { - status = Number.TryParseUInt32IntegerStyle(value, NumberStyle, numberFormat, out uint uint32result); - if (status == Number.ParsingStatus.OK) - { - if (uint32result <= uint.CreateTruncating(TUnderlying.MaxValue)) - { - result = TUnderlying.CreateTruncating(uint32result); - return true; - } - status = Number.ParsingStatus.Overflow; - } + result = (TUnderlying)ToObject(enumType, Convert.ChangeType(value.ToString(), underlyingType, CultureInfo.InvariantCulture)!); + return true; } - else if (typeof(TUnderlying) == typeof(sbyte) || typeof(TUnderlying) == typeof(short)) + catch (FormatException) { - status = Number.TryParseInt32IntegerStyle(value, NumberStyle, numberFormat, out int int32result); - if (status == Number.ParsingStatus.OK) - { - if (int32result >= int.CreateTruncating(TUnderlying.MinValue) && int32result <= int.CreateTruncating(TUnderlying.MaxValue)) - { - result = TUnderlying.CreateTruncating(int32result); - return true; - } - status = Number.ParsingStatus.Overflow; - } + status = Number.ParsingStatus.Failed; // e.g. tlbimp enums that can have values of the form "3D" } - else + catch when (!throwOnFailure) { -#if RARE_ENUMS - Type underlyingType = GetUnderlyingType(enumType); - try - { - result = (TUnderlying)ToObject(enumType, Convert.ChangeType(value.ToString(), underlyingType, CultureInfo.InvariantCulture)!); - return true; - } - catch (FormatException) - { - status = Number.ParsingStatus.Failed; // e.g. tlbimp enums that can have values of the form "3D" - } - catch when (!throwOnFailure) - { - status = Number.ParsingStatus.Overflow; // fall through to returning failure - } -#else - throw CreateUnknownEnumTypeException(); -#endif + status = Number.ParsingStatus.Overflow; // fall through to returning failure } if (status != Number.ParsingStatus.Overflow) @@ -1037,6 +1025,9 @@ private static unsafe bool TryParseByValueOrName( { Number.ThrowOverflowException(Type.GetTypeCode(typeof(TUnderlying))); } +#else + throw CreateUnknownEnumTypeException(); +#endif } ParseFailure: @@ -1049,7 +1040,7 @@ private static unsafe bool TryParseByValueOrName( return false; } - /// Handles just the name parsing portion of . + /// Handles just the name parsing portion of . private static bool TryParseByName(RuntimeType enumType, ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out TStorage result) where TStorage : struct, INumber, IBitwiseOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs index 870d8504fb967..cdbdd65a81426 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.OSX.cs @@ -7,21 +7,23 @@ namespace System.Globalization { internal sealed partial class CultureData { + private const int LOC_FULLNAME_CAPACITY = 157; // max size of locale name + /// /// This method uses the sRealName field (which is initialized by the constructor before this is called) to /// initialize the rest of the state of CultureData based on the underlying OS globalization library. /// - private bool InitNativeCultureDataCore() + private bool InitAppleCultureDataCore() { Debug.Assert(_sRealName != null); Debug.Assert(!GlobalizationMode.Invariant); string realNameBuffer = _sRealName; - _sWindowsName = GetLocaleNameNative(realNameBuffer); + _sWindowsName = _sName = _sRealName = GetLocaleNameNative(realNameBuffer); return true; } - internal static unsafe string GetLocaleNameNative(string localeName) + internal static string GetLocaleNameNative(string localeName) { return Interop.Globalization.GetLocaleNameNative(localeName); } @@ -36,11 +38,111 @@ private string GetLocaleInfoNative(LocaleStringData type) // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the // "windows" name, which can be specific for downlevel (< windows 7) os's. - private static unsafe string GetLocaleInfoNative(string localeName, LocaleStringData type) + private static string GetLocaleInfoNative(string localeName, LocaleStringData type) { Debug.Assert(localeName != null, "[CultureData.GetLocaleInfoNative] Expected localeName to be not be null"); return Interop.Globalization.GetLocaleInfoStringNative(localeName, (uint)type); } + + private int GetLocaleInfoNative(LocaleNumberData type) + { + Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfoNative(LocaleNumberData)] Expected _sWindowsName to be populated already"); + + // returning 0 will cause the first supported calendar to be returned, which is the preferred calendar + if (type == LocaleNumberData.CalendarType) + return 0; + + int value = Interop.Globalization.GetLocaleInfoIntNative(_sWindowsName, (uint)type); + const int DEFAULT_VALUE = 0; + if (value < 0) + { + Debug.Fail("[CultureData.GetLocaleInfoNative(LocaleNumberData)] failed"); + return DEFAULT_VALUE; + } + + return value; + } + + private int[] GetLocaleInfoNative(LocaleGroupingData type) + { + Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfoNative(LocaleGroupingData)] Expected _sWindowsName to be populated already"); + + int primaryGroupingSize = Interop.Globalization.GetLocaleInfoPrimaryGroupingSizeNative(_sWindowsName, (uint)type); + int secondaryGroupingSize = Interop.Globalization.GetLocaleInfoSecondaryGroupingSizeNative(_sWindowsName, (uint)type); + + if (secondaryGroupingSize == 0) + { + return new int[] { primaryGroupingSize }; + } + + return new int[] { primaryGroupingSize, secondaryGroupingSize }; + } + + private string GetTimeFormatStringNative() => GetTimeFormatStringNative(shortFormat: false); + + private string GetTimeFormatStringNative(bool shortFormat) + { + Debug.Assert(_sWindowsName != null, "[CultureData.GetTimeFormatStringNative(bool shortFormat)] Expected _sWindowsName to be populated already"); + + string result = Interop.Globalization.GetLocaleTimeFormatNative(_sWindowsName, shortFormat); + + return ConvertNativeTimeFormatString(result); + } + + private static string ConvertNativeTimeFormatString(string nativeFormatString) + { + Span result = stackalloc char[LOC_FULLNAME_CAPACITY]; + + bool amPmAdded = false; + int resultPos = 0; + + for (int i = 0; i < nativeFormatString.Length; i++) + { + switch (nativeFormatString[i]) + { + case '\'': + result[resultPos++] = nativeFormatString[i++]; + while (i < nativeFormatString.Length) + { + char current = nativeFormatString[i]; + result[resultPos++] = current; + if (current == '\'') + { + break; + } + i++; + } + break; + + case ':': + case '.': + case 'H': + case 'h': + case 'm': + case 's': + result[resultPos++] = nativeFormatString[i]; + break; + + case ' ': + case '\u00A0': + // Convert nonbreaking spaces into regular spaces + result[resultPos++] = ' '; + break; + + case 'a': // AM/PM + if (!amPmAdded) + { + amPmAdded = true; + result[resultPos++] = 't'; + result[resultPos++] = 't'; + } + break; + + } + } + + return result.Slice(0, resultPos).ToString(); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs index 2a253d5367be3..76c009beb6466 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs @@ -7,7 +7,12 @@ namespace System.Globalization { internal sealed partial class CultureData { - private bool InitCultureDataCore() => InitIcuCultureDataCore(); + private bool InitCultureDataCore() => +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + GlobalizationMode.Hybrid ? InitAppleCultureDataCore() : InitIcuCultureDataCore(); +#else + InitIcuCultureDataCore(); +#endif // Unix doesn't support user overrides partial void InitUserOverride(bool useUserOverride); @@ -20,7 +25,11 @@ internal sealed partial class CultureData private string[]? GetTimeFormatsCore(bool shortFormat) { +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + string format = GlobalizationMode.Hybrid ? GetTimeFormatStringNative(shortFormat) : IcuGetTimeFormatString(shortFormat); +#else string format = IcuGetTimeFormatString(shortFormat); +#endif return new string[] { format }; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index 92037366b6389..12ea4ded8beed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -1541,7 +1541,11 @@ internal int FirstDayOfWeek { if (_iFirstDayOfWeek == undef && !GlobalizationMode.Invariant) { +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + _iFirstDayOfWeek = GlobalizationMode.Hybrid ? GetLocaleInfoNative(LocaleNumberData.FirstDayOfWeek) : IcuGetLocaleInfo(LocaleNumberData.FirstDayOfWeek); +#else _iFirstDayOfWeek = ShouldUseUserOverrideNlsData ? NlsGetFirstDayOfWeek() : IcuGetLocaleInfo(LocaleNumberData.FirstDayOfWeek); +#endif } return _iFirstDayOfWeek; } @@ -1949,7 +1953,11 @@ internal string TimeSeparator } else { +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + string? longTimeFormat = GlobalizationMode.Hybrid ? GetTimeFormatStringNative() : IcuGetTimeFormatString(); +#else string? longTimeFormat = ShouldUseUserOverrideNlsData ? NlsGetTimeFormatString() : IcuGetTimeFormatString(); +#endif if (string.IsNullOrEmpty(longTimeFormat)) { longTimeFormat = LongTimes[0]; @@ -2285,8 +2293,11 @@ private int GetLocaleInfoCore(LocaleNumberData type) // This is never reached but helps illinker statically remove dependencies if (GlobalizationMode.Invariant) return 0; - +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + return GlobalizationMode.Hybrid ? GetLocaleInfoNative(type) : IcuGetLocaleInfo(type); +#else return GlobalizationMode.UseNls ? NlsGetLocaleInfo(type) : IcuGetLocaleInfo(type); +#endif } private int GetLocaleInfoCoreUserOverride(LocaleNumberData type) @@ -2294,8 +2305,11 @@ private int GetLocaleInfoCoreUserOverride(LocaleNumberData type) // This is never reached but helps illinker statically remove dependencies if (GlobalizationMode.Invariant) return 0; - +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + return GlobalizationMode.Hybrid ? GetLocaleInfoNative(type) : IcuGetLocaleInfo(type); +#else return ShouldUseUserOverrideNlsData ? NlsGetLocaleInfo(type) : IcuGetLocaleInfo(type); +#endif } private string GetLocaleInfoCoreUserOverride(LocaleStringData type) @@ -2343,7 +2357,11 @@ private int[] GetLocaleInfoCoreUserOverride(LocaleGroupingData type) if (GlobalizationMode.Invariant) return null!; +#if TARGET_OSX || TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + return GlobalizationMode.Hybrid ? GetLocaleInfoNative(type) : IcuGetLocaleInfo(type); +#else return ShouldUseUserOverrideNlsData ? NlsGetLocaleInfo(type) : IcuGetLocaleInfo(type); +#endif } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index 5af77c998154a..03a4ba17f78c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -830,6 +830,7 @@ public static NumberFormatInfo ReadOnly(NumberFormatInfo nfi) | NumberStyles.AllowThousands | NumberStyles.AllowExponent | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier); + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void ValidateParseStyleInteger(NumberStyles style) { // Check for undefined flags or invalid hex number flags diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 4a1ede42b511a..12f2f11ce6f02 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -25,7 +25,8 @@ public readonly partial struct Guid IComparable, IComparable, IEquatable, - ISpanParsable + ISpanParsable, + IUtf8SpanFormattable { public static readonly Guid Empty; @@ -306,7 +307,7 @@ public static Guid ParseExact(ReadOnlySpan input, [StringSyntax(StringSynt if (format.Length != 1) { // all acceptable format strings are of length 1 - throw new FormatException(SR.Format_InvalidGuidFormatSpecification); + ThrowBadGuidFormatSpecification(); } input = input.Trim(); @@ -490,7 +491,7 @@ static bool TryCompatParsing(ReadOnlySpan guidString, ref GuidResult resul result._fg = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness((ushort)uintTmp) : (ushort)uintTmp; // Unlike the other components, this one never allowed 0x or +, so we can parse it as straight hex. - if (Number.TryParseUInt32HexNumberStyle(guidString.Slice(28, 8), NumberStyles.AllowHexSpecifier, out uintTmp) == Number.ParsingStatus.OK) // _h, _i, _j, _k + if (Number.TryParseBinaryIntegerHexNumberStyle(guidString.Slice(28, 8), NumberStyles.AllowHexSpecifier, out uintTmp) == Number.ParsingStatus.OK) // _h, _i, _j, _k { result._hijk = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(uintTmp) : uintTmp; return true; @@ -883,9 +884,6 @@ public bool TryWriteBytes(Span destination) return true; } - // Returns the guid in "registry" format. - public override string ToString() => ToString("D", null); - public override int GetHashCode() { // Simply XOR all the bits of the GUID 32 bits at a time. @@ -1054,192 +1052,221 @@ public int CompareTo(Guid value) public static bool operator !=(Guid a, Guid b) => !EqualsCore(a, b); - public string ToString([StringSyntax(StringSyntaxAttribute.GuidFormat)] string? format) - { - return ToString(format, null); - } - - private static unsafe int HexsToChars(char* guidChars, int a, int b) + private static unsafe int HexsToChars(TChar* guidChars, int a, int b) where TChar : unmanaged, IUtfChar { - guidChars[0] = HexConverter.ToCharLower(a >> 4); - guidChars[1] = HexConverter.ToCharLower(a); + guidChars[0] = TChar.CastFrom(HexConverter.ToCharLower(a >> 4)); + guidChars[1] = TChar.CastFrom(HexConverter.ToCharLower(a)); - guidChars[2] = HexConverter.ToCharLower(b >> 4); - guidChars[3] = HexConverter.ToCharLower(b); + guidChars[2] = TChar.CastFrom(HexConverter.ToCharLower(b >> 4)); + guidChars[3] = TChar.CastFrom(HexConverter.ToCharLower(b)); return 4; } - private static unsafe int HexsToCharsHexOutput(char* guidChars, int a, int b) + private static unsafe int HexsToCharsHexOutput(TChar* guidChars, int a, int b) where TChar : unmanaged, IUtfChar { - guidChars[0] = '0'; - guidChars[1] = 'x'; + guidChars[0] = TChar.CastFrom('0'); + guidChars[1] = TChar.CastFrom('x'); - guidChars[2] = HexConverter.ToCharLower(a >> 4); - guidChars[3] = HexConverter.ToCharLower(a); + guidChars[2] = TChar.CastFrom(HexConverter.ToCharLower(a >> 4)); + guidChars[3] = TChar.CastFrom(HexConverter.ToCharLower(a)); - guidChars[4] = ','; - guidChars[5] = '0'; - guidChars[6] = 'x'; + guidChars[4] = TChar.CastFrom(','); + guidChars[5] = TChar.CastFrom('0'); + guidChars[6] = TChar.CastFrom('x'); - guidChars[7] = HexConverter.ToCharLower(b >> 4); - guidChars[8] = HexConverter.ToCharLower(b); + guidChars[7] = TChar.CastFrom(HexConverter.ToCharLower(b >> 4)); + guidChars[8] = TChar.CastFrom(HexConverter.ToCharLower(b)); return 9; } + // Returns the guid in "registry" format. + public override string ToString() => ToString("d", null); + + public string ToString([StringSyntax(StringSyntaxAttribute.GuidFormat)] string? format) + { + return ToString(format, null); + } + // IFormattable interface // We currently ignore provider public string ToString([StringSyntax(StringSyntaxAttribute.GuidFormat)] string? format, IFormatProvider? provider) { + int guidSize; if (string.IsNullOrEmpty(format)) { - format = "D"; + guidSize = 36; } - - // all acceptable format strings are of length 1 - if (format.Length != 1) + else { - throw new FormatException(SR.Format_InvalidGuidFormatSpecification); - } + // all acceptable format strings are of length 1 + if (format.Length != 1) + { + ThrowBadGuidFormatSpecification(); + } - int guidSize; - switch (format[0]) - { - case 'D': - case 'd': - guidSize = 36; - break; - case 'N': - case 'n': - guidSize = 32; - break; - case 'B': - case 'b': - case 'P': - case 'p': - guidSize = 38; - break; - case 'X': - case 'x': - guidSize = 68; - break; - default: - throw new FormatException(SR.Format_InvalidGuidFormatSpecification); + switch (format[0] | 0x20) + { + case 'd': + guidSize = 36; + break; + + case 'n': + guidSize = 32; + break; + + case 'b' or 'p': + guidSize = 38; + break; + + case 'x': + guidSize = 68; + break; + + default: + guidSize = 0; + ThrowBadGuidFormatSpecification(); + break; + }; } string guidString = string.FastAllocateString(guidSize); - bool result = TryFormat(new Span(ref guidString.GetRawStringData(), guidString.Length), out int bytesWritten, format); + bool result = TryFormatCore(new Span(ref guidString.GetRawStringData(), guidString.Length), out int bytesWritten, format); Debug.Assert(result && bytesWritten == guidString.Length, "Formatting guid should have succeeded."); return guidString; } - // Returns whether the guid is successfully formatted as a span. - public bool TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.GuidFormat)] ReadOnlySpan format = default) + public bool TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.GuidFormat)] ReadOnlySpan format = default) => + TryFormatCore(destination, out charsWritten, format); + + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.GuidFormat)] ReadOnlySpan format, IFormatProvider? provider) => + // Provider is ignored. + TryFormatCore(destination, out charsWritten, format); + + public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringSyntax(StringSyntaxAttribute.GuidFormat)] ReadOnlySpan format = default) => + TryFormatCore(utf8Destination, out bytesWritten, format); + + bool IUtf8SpanFormattable.TryFormat(Span utf8Destination, out int bytesWritten, [StringSyntax(StringSyntaxAttribute.GuidFormat)] ReadOnlySpan format, IFormatProvider? provider) => + // Provider is ignored. + TryFormatCore(utf8Destination, out bytesWritten, format); + + // TryFormatCore accepts an `int flags` composed of: + // - Lowest byte: required length + // - Second byte: opening brace char, or 0 if no braces + // - Third byte: closing brace char, or 0 if no braces + // - Highest bit: 1 if use dashes, else 0 + internal const int TryFormatFlags_UseDashes = unchecked((int)0x80000000); + internal const int TryFormatFlags_CurlyBraces = ('}' << 16) | ('{' << 8); + internal const int TryFormatFlags_Parens = (')' << 16) | ('(' << 8); + + private bool TryFormatCore(Span destination, out int charsWritten, ReadOnlySpan format) where TChar : unmanaged, IUtfChar { + int flags; + if (format.Length == 0) { - format = "D"; + flags = 36 + TryFormatFlags_UseDashes; } - // all acceptable format strings are of length 1 - if (format.Length != 1) + else { - throw new FormatException(SR.Format_InvalidGuidFormatSpecification); - } + if (format.Length != 1) + { + ThrowBadGuidFormatSpecification(); + } - bool dash = true; - bool hex = false; - int braces = 0; + switch (format[0] | 0x20) + { + case 'd': + flags = 36 + TryFormatFlags_UseDashes; + break; - int guidSize; + case 'p': + flags = 38 + TryFormatFlags_UseDashes + TryFormatFlags_Parens; + break; - switch (format[0]) - { - case 'D': - case 'd': - guidSize = 36; - break; - case 'N': - case 'n': - dash = false; - guidSize = 32; - break; - case 'B': - case 'b': - braces = '{' + ('}' << 16); - guidSize = 38; - break; - case 'P': - case 'p': - braces = '(' + (')' << 16); - guidSize = 38; - break; - case 'X': - case 'x': - braces = '{' + ('}' << 16); - dash = false; - hex = true; - guidSize = 68; - break; - default: - throw new FormatException(SR.Format_InvalidGuidFormatSpecification); + case 'b': + flags = 38 + TryFormatFlags_UseDashes + TryFormatFlags_CurlyBraces; + break; + + case 'n': + flags = 32; + break; + + case 'x': + return TryFormatX(destination, out charsWritten); + + default: + flags = 0; + ThrowBadGuidFormatSpecification(); + break; + } } - if (destination.Length < guidSize) + return TryFormatCore(destination, out charsWritten, flags); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // only used from two callers + internal unsafe bool TryFormatCore(Span destination, out int charsWritten, int flags) where TChar : unmanaged, IUtfChar + { + // The low byte of flags contains the required length. + if ((byte)flags > destination.Length) { charsWritten = 0; return false; } - unsafe + charsWritten = (byte)flags; + flags >>= 8; + + fixed (TChar* guidChars = &MemoryMarshal.GetReference(destination)) { - fixed (char* guidChars = &MemoryMarshal.GetReference(destination)) + TChar* p = guidChars; + + // The low byte of flags now contains the opening brace char (if any) + if ((byte)flags != 0) { - char* p = guidChars; + *p++ = TChar.CastFrom((byte)flags); + } + flags >>= 8; - if (braces != 0) - *p++ = (char)braces; + if ((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian) + { + // Vectorized implementation for D, N, P and B formats: + // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] + (Vector128 vecX, Vector128 vecY, Vector128 vecZ) = FormatGuidVector128Utf8(this, flags < 0 /* dash */); - if (hex) + if (typeof(TChar) == typeof(byte)) { - // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} - *p++ = '0'; - *p++ = 'x'; - p += HexsToChars(p, _a >> 24, _a >> 16); - p += HexsToChars(p, _a >> 8, _a); - *p++ = ','; - *p++ = '0'; - *p++ = 'x'; - p += HexsToChars(p, _b >> 8, _b); - *p++ = ','; - *p++ = '0'; - *p++ = 'x'; - p += HexsToChars(p, _c >> 8, _c); - *p++ = ','; - *p++ = '{'; - p += HexsToCharsHexOutput(p, _d, _e); - *p++ = ','; - p += HexsToCharsHexOutput(p, _f, _g); - *p++ = ','; - p += HexsToCharsHexOutput(p, _h, _i); - *p++ = ','; - p += HexsToCharsHexOutput(p, _j, _k); - *p++ = '}'; + byte* pChar = (byte*)p; + if (flags < 0 /* dash */) + { + // We need to merge these vectors in this order: + // xxxxxxxxxxxxxxxx + // yyyyyyyyyyyyyyyy + // zzzzzzzzzzzzzzzz + vecX.Store(pChar); + vecY.Store(pChar + 20); + vecZ.Store(pChar + 8); + p += 36; + } + else + { + // xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyy + vecX.Store(pChar); + vecY.Store(pChar + 16); + p += 32; + } } - else if ((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian) + else { - // Vectorized implementation for D, N, P and B formats: - // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] - (Vector128 vecX, Vector128 vecY, Vector128 vecZ) = - Buffers.Text.Utf8Formatter.FormatGuidVector128Utf8(this, dash); - // Expand to UTF-16 (Vector128 x0, Vector128 x1) = Vector128.Widen(vecX); (Vector128 y0, Vector128 y1) = Vector128.Widen(vecY); ushort* pChar = (ushort*)p; - if (dash) + if (flags < 0 /* dash */) { (Vector128 z0, Vector128 z1) = Vector128.Widen(vecZ); @@ -1247,7 +1274,7 @@ public bool TryFormat(Span destination, out int charsWritten, [StringSynta // xxxxxxxxxxxxxxxx // yyyyyyyyyyyyyyyy // zzzzzzzzzzzzzzzz - x0.Store(pChar + 0); + x0.Store(pChar); y0.Store(pChar + 20); y1.Store(pChar + 28); z0.Store(pChar + 8); // overlaps x1 @@ -1257,54 +1284,153 @@ public bool TryFormat(Span destination, out int charsWritten, [StringSynta else { // xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyy - x0.Store(pChar + 0); + x0.Store(pChar); x1.Store(pChar + 8); y0.Store(pChar + 16); y1.Store(pChar + 24); p += 32; } - if (braces != 0) - *p = (char)(braces >> 16); - charsWritten = guidSize; - return true; } - else + } + else + { + // Non-vectorized fallback for D, N, P and B formats: + // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] + p += HexsToChars(p, _a >> 24, _a >> 16); + p += HexsToChars(p, _a >> 8, _a); + if (flags < 0 /* dash */) { - // Non-vectorized fallback for D, N, P and B formats: - // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] - p += HexsToChars(p, _a >> 24, _a >> 16); - p += HexsToChars(p, _a >> 8, _a); - if (dash) - *p++ = '-'; - p += HexsToChars(p, _b >> 8, _b); - if (dash) - *p++ = '-'; - p += HexsToChars(p, _c >> 8, _c); - if (dash) - *p++ = '-'; - p += HexsToChars(p, _d, _e); - if (dash) - *p++ = '-'; - p += HexsToChars(p, _f, _g); - p += HexsToChars(p, _h, _i); - p += HexsToChars(p, _j, _k); + *p++ = TChar.CastFrom('-'); } + p += HexsToChars(p, _b >> 8, _b); + if (flags < 0 /* dash */) + { + *p++ = TChar.CastFrom('-'); + } + p += HexsToChars(p, _c >> 8, _c); + if (flags < 0 /* dash */) + { + *p++ = TChar.CastFrom('-'); + } + p += HexsToChars(p, _d, _e); + if (flags < 0 /* dash */) + { + *p++ = TChar.CastFrom('-'); + } + p += HexsToChars(p, _f, _g); + p += HexsToChars(p, _h, _i); + p += HexsToChars(p, _j, _k); + } - if (braces != 0) - *p++ = (char)(braces >> 16); - - Debug.Assert(p - guidChars == guidSize); + // The low byte of flags now contains the closing brace char (if any) + if ((byte)flags != 0) + { + *p = TChar.CastFrom((byte)flags); } + + Debug.Assert(p == guidChars + charsWritten - ((byte)flags != 0 ? 1 : 0)); + } + + return true; + } + + private unsafe bool TryFormatX(Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar + { + if (destination.Length < 68) + { + charsWritten = 0; + return false; + } + charsWritten = 68; + + fixed (TChar* guidChars = &MemoryMarshal.GetReference(destination)) + { + TChar* p = guidChars; + + // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} + *p++ = TChar.CastFrom('{'); + *p++ = TChar.CastFrom('0'); + *p++ = TChar.CastFrom('x'); + p += HexsToChars(p, _a >> 24, _a >> 16); + p += HexsToChars(p, _a >> 8, _a); + *p++ = TChar.CastFrom(','); + *p++ = TChar.CastFrom('0'); + *p++ = TChar.CastFrom('x'); + p += HexsToChars(p, _b >> 8, _b); + *p++ = TChar.CastFrom(','); + *p++ = TChar.CastFrom('0'); + *p++ = TChar.CastFrom('x'); + p += HexsToChars(p, _c >> 8, _c); + *p++ = TChar.CastFrom(','); + *p++ = TChar.CastFrom('{'); + p += HexsToCharsHexOutput(p, _d, _e); + *p++ = TChar.CastFrom(','); + p += HexsToCharsHexOutput(p, _f, _g); + *p++ = TChar.CastFrom(','); + p += HexsToCharsHexOutput(p, _h, _i); + *p++ = TChar.CastFrom(','); + p += HexsToCharsHexOutput(p, _j, _k); + *p++ = TChar.CastFrom('}'); + *p = TChar.CastFrom('}'); + + Debug.Assert(p == guidChars + charsWritten - 1); } - charsWritten = guidSize; return true; } - bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.GuidFormat)] ReadOnlySpan format, IFormatProvider? provider) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static (Vector128, Vector128, Vector128) FormatGuidVector128Utf8(Guid value, bool useDashes) { - // Like with the IFormattable implementation, provider is ignored. - return TryFormat(destination, out charsWritten, format); + Debug.Assert((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian); + // Vectorized implementation for D, N, P and B formats: + // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] + + Vector128 hexMap = Vector128.Create( + (byte)'0', (byte)'1', (byte)'2', (byte)'3', + (byte)'4', (byte)'5', (byte)'6', (byte)'7', + (byte)'8', (byte)'9', (byte)'a', (byte)'b', + (byte)'c', (byte)'d', (byte)'e', (byte)'f'); + + Vector128 srcVec = Unsafe.As>(ref value); + (Vector128 hexLow, Vector128 hexHigh) = + HexConverter.AsciiToHexVector128(srcVec, hexMap); + + // because of Guid's layout (int _a, short _b, _c, <8 byte fields>) + // we have to shuffle some bytes for _a, _b and _c + hexLow = Vector128.Shuffle(hexLow.AsInt16(), Vector128.Create(3, 2, 1, 0, 5, 4, 7, 6)).AsByte(); + + if (useDashes) + { + // We divide 16 bytes into 3 x Vector128: + // + // ________-____-____-____-____________ + // xxxxxxxxxxxxxxxx + // yyyyyyyyyyyyyyyy + // zzzzzzzzzzzzzzzz + // + // Vector "x" - just one dash, shift all elements after it. + Vector128 vecX = Vector128.Shuffle(hexLow, + Vector128.Create(0x706050403020100, 0xD0CFF0B0A0908FF).AsByte()); + + // Vector "y" - same here. + Vector128 vecY = Vector128.Shuffle(hexHigh, + Vector128.Create(0x7060504FF030201, 0xF0E0D0C0B0A0908).AsByte()); + + // Vector "z" - we need to merge some elements of hexLow with hexHigh and add 4 dashes. + Vector128 mid1 = Vector128.Shuffle(hexLow, + Vector128.Create(0x0D0CFF0B0A0908FF, 0xFFFFFFFFFFFF0F0E).AsByte()); + Vector128 mid2 = Vector128.Shuffle(hexHigh, + Vector128.Create(0xFFFFFFFFFFFFFFFF, 0xFF03020100FFFFFF).AsByte()); + Vector128 dashesMask = Vector128.Shuffle(Vector128.CreateScalarUnsafe((byte)'-'), + Vector128.Create(0xFFFF00FFFFFFFF00, 0x00FFFFFFFF00FFFF).AsByte()); + + Vector128 vecZ = (mid1 | mid2 | dashesMask); + return (vecX, vecY, vecZ); + } + + // N format - no dashes. + return (hexLow, hexHigh, default); } // @@ -1574,5 +1700,9 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, [S /// public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, out Guid result) => TryParse(s, out result); + + [DoesNotReturn] + private static void ThrowBadGuidFormatSpecification() => + throw new FormatException(SR.Format_InvalidGuidFormatSpecification); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int128.cs b/src/libraries/System.Private.CoreLib/src/System/Int128.cs index d4f7c6a2c1928..c6b98d28526c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int128.cs @@ -18,7 +18,8 @@ public readonly struct Int128 : IBinaryInteger, IMinMaxValue, ISignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { internal const int Size = 16; @@ -125,75 +126,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatInt128(this, format, provider, utf8Destination, out bytesWritten); } - public static Int128 Parse(string s) - { - ArgumentNullException.ThrowIfNull(s); - return Number.ParseInt128(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static Int128 Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static Int128 Parse(string s, NumberStyles style) - { - ArgumentNullException.ThrowIfNull(s); - NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseInt128(s, style, NumberFormatInfo.CurrentInfo); - } + public static Int128 Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static Int128 Parse(string s, IFormatProvider? provider) - { - ArgumentNullException.ThrowIfNull(s); - return Number.ParseInt128(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static Int128 Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); public static Int128 Parse(string s, NumberStyles style, IFormatProvider? provider) { - ArgumentNullException.ThrowIfNull(s); - NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseInt128(s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static Int128 Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseInt128(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out Int128 result) - { - if (s is not null) - { - return Number.TryParseInt128IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } - else - { - result = default; - return false; - } - } + public static bool TryParse([NotNullWhen(true)] string? s, out Int128 result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - public static bool TryParse(ReadOnlySpan s, out Int128 result) - { - return Number.TryParseInt128IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse(ReadOnlySpan s, out Int128 result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out Int128 result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s is not null) - { - return Number.TryParseInt128(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; - } - else + if (s is null) { - result = default; + result = 0; return false; } + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out Int128 result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.TryParseInt128(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -2199,5 +2169,25 @@ static bool INumberBase.TryConvertToTruncating(Int128 value, [Ma /// public static Int128 operator +(Int128 value) => value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => true; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 39; // 170_141_183_460_469_231_731_687_303_715_884_105_727 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 32; // 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF + + static Int128 IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => new Int128(0x0CCC_CCCC_CCCC_CCCC, 0xCCCC_CCCC_CCCC_CCCC); + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_Int128; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(Int128 left, Int128 right) => (UInt128)(left) > (UInt128)(right); + + static Int128 IBinaryIntegerParseAndFormatInfo.MultiplyBy10(Int128 value) => value * 10; + + static Int128 IBinaryIntegerParseAndFormatInfo.MultiplyBy16(Int128 value) => value * 16; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int16.cs b/src/libraries/System.Private.CoreLib/src/System/Int16.cs index 2b3d0bf60d324..02d896f981fb3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int16.cs @@ -24,7 +24,8 @@ public readonly struct Int16 IBinaryInteger, IMinMaxValue, ISignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly short m_value; // Do not rename (binary serialization) @@ -125,102 +126,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatInt32(m_value, 0x0000FFFF, format, provider, utf8Destination, out bytesWritten); } - public static short Parse(string s) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static short Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static short Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.CurrentInfo); - } + public static short Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static short Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static short Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); public static short Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static short Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Parse(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - private static short Parse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info) - { - Number.ParsingStatus status = Number.TryParseInt32(s, style, info, out int i); - if (status != Number.ParsingStatus.OK) - { - Number.ThrowOverflowOrFormatException(status, s, TypeCode.Int16); - } + public static bool TryParse([NotNullWhen(true)] string? s, out short result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - // For hex number styles AllowHexSpecifier << 6 == 0x8000 and cancels out MinValue so the check is effectively: (uint)i > ushort.MaxValue - // For integer styles it's zero and the effective check is (uint)(i - MinValue) > ushort.MaxValue - if ((uint)(i - MinValue - ((int)(style & NumberStyles.AllowHexSpecifier) << 6)) > ushort.MaxValue) - { - Number.ThrowOverflowException(TypeCode.Int16); - } - return (short)i; - } - - public static bool TryParse([NotNullWhen(true)] string? s, out short result) - { - if (s == null) - { - result = 0; - return false; - } - - return TryParse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } - - public static bool TryParse(ReadOnlySpan s, out short result) - { - return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } + public static bool TryParse(ReadOnlySpan s, out short result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out short result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return TryParse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider), out result); + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out short result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result); - } - - private static bool TryParse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info, out short result) - { - // For hex number styles AllowHexSpecifier << 6 == 0x8000 and cancels out MinValue so the check is effectively: (uint)i > ushort.MaxValue - // For integer styles it's zero and the effective check is (uint)(i - MinValue) > ushort.MaxValue - if (Number.TryParseInt32(s, style, info, out int i) != Number.ParsingStatus.OK - || (uint)(i - MinValue - ((int)(style & NumberStyles.AllowHexSpecifier) << 6)) > ushort.MaxValue) - { - result = 0; - return false; - } - result = (short)i; - return true; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1421,5 +1364,25 @@ static bool INumberBase.TryConvertToTruncating(short value, [Mayb /// static short IUnaryPlusOperators.operator +(short value) => (short)(+value); + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => true; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 5; // 32_767 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 4; // 0x7FFF + + static short IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_Int16; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(short left, short right) => (ushort)(left) > (ushort)(right); + + static short IBinaryIntegerParseAndFormatInfo.MultiplyBy10(short value) => (short)(value * 10); + + static short IBinaryIntegerParseAndFormatInfo.MultiplyBy16(short value) => (short)(value * 16); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int32.cs b/src/libraries/System.Private.CoreLib/src/System/Int32.cs index dc1986c0098fa..a0c055cd21a34 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int32.cs @@ -24,7 +24,8 @@ public readonly struct Int32 IBinaryInteger, IMinMaxValue, ISignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly int m_value; // Do not rename (binary serialization) @@ -135,85 +136,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatInt32(m_value, ~0, format, provider, utf8Destination, out bytesWritten); } - 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) => Parse(s, NumberStyles.Integer, provider: null); - public static int Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseInt32(s, style, NumberFormatInfo.CurrentInfo); - } + public static int Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - // Parses an integer from a String in the given style. If - // a NumberFormatInfo isn't specified, the current culture's - // NumberFormatInfo is assumed. - // - public static int Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static int Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - // Parses an integer from a String in the given style. If - // a NumberFormatInfo isn't specified, the current culture's - // NumberFormatInfo is assumed. - // public static int Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseInt32(s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static int Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseInt32(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - // Parses an integer from a String. Returns false rather - // than throwing an exception if input is invalid. - // - public static bool TryParse([NotNullWhen(true)] string? s, out int result) - { - if (s == null) - { - result = 0; - return false; - } + public static bool TryParse([NotNullWhen(true)] string? s, out int result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - return Number.TryParseInt32IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse(ReadOnlySpan s, out int result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - public static bool TryParse(ReadOnlySpan s, out int result) - { - return Number.TryParseInt32IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } - - // Parses an integer from a String in the given style. Returns false rather - // than throwing an exception if input is invalid. - // public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out int result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return Number.TryParseInt32(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out int result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.TryParseInt32(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1440,5 +1400,25 @@ static bool INumberBase.TryConvertToTruncating(int value, [MaybeNul /// static int IUnaryPlusOperators.operator +(int value) => +value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => true; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 10; // 2_147_483_647 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 8; // 0x7FFF_FFFF + + static int IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_Int32; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(int left, int right) => (uint)(left) > (uint)(right); + + static int IBinaryIntegerParseAndFormatInfo.MultiplyBy10(int value) => value * 10; + + static int IBinaryIntegerParseAndFormatInfo.MultiplyBy16(int value) => value * 16; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Int64.cs b/src/libraries/System.Private.CoreLib/src/System/Int64.cs index d8a3787917e16..7f4ace2b1c725 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int64.cs @@ -24,7 +24,8 @@ public readonly struct Int64 IBinaryInteger, IMinMaxValue, ISignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly long m_value; // Do not rename (binary serialization) @@ -132,75 +133,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatInt64(m_value, format, provider, utf8Destination, out bytesWritten); } - 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) => Parse(s, NumberStyles.Integer, provider: null); - 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, NumberStyles style) => Parse(s, style, provider: null); - public static long Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static long Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - // Parses a long from a String in the given style. If - // a NumberFormatInfo isn't specified, the current culture's - // NumberFormatInfo is assumed. - // public static long Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static long Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out long result) - { - if (s == null) - { - result = 0; - return false; - } - - return Number.TryParseInt64IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse([NotNullWhen(true)] string? s, out long result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - public static bool TryParse(ReadOnlySpan s, out long result) - { - return Number.TryParseInt64IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse(ReadOnlySpan s, out long result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out long result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return Number.TryParseInt64(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out long result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.TryParseInt64(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1433,5 +1403,25 @@ static bool INumberBase.TryConvertToTruncating(long value, [MaybeN /// static long IUnaryPlusOperators.operator +(long value) => +value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => true; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 19; // 9_223_372_036_854_775_807 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 16; // 0x7FFF_FFFF_FFFF_FFFF + + static long IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_Int64; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(long left, long right) => (ulong)(left) > (ulong)(right); + + static long IBinaryIntegerParseAndFormatInfo.MultiplyBy10(long value) => value * 10; + + static long IBinaryIntegerParseAndFormatInfo.MultiplyBy16(long value) => value * 16; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index bdeebbf560b7c..d12bf4f4fae0e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -1426,17 +1426,18 @@ private static void ThrowNullLowHighInclusive(T? lowInclusive, T? highInclusi public static unsafe bool SequenceEqual(this Span span, ReadOnlySpan other) where T : IEquatable? { int length = span.Length; + int otherLength = other.Length; if (RuntimeHelpers.IsBitwiseEquatable()) { - return length == other.Length && + return length == otherLength && SpanHelpers.SequenceEqual( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(other)), - ((uint)length) * (nuint)sizeof(T)); // 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. + ((uint)otherLength) * (nuint)sizeof(T)); // 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); + return length == otherLength && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } /// @@ -2161,16 +2162,18 @@ public static int LastIndexOfAny(this ReadOnlySpan span, IndexOfAnyValues< public static unsafe bool SequenceEqual(this ReadOnlySpan span, ReadOnlySpan other) where T : IEquatable? { int length = span.Length; + int otherLength = other.Length; + if (RuntimeHelpers.IsBitwiseEquatable()) { - return length == other.Length && + return length == otherLength && SpanHelpers.SequenceEqual( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(other)), - ((uint)length) * (nuint)sizeof(T)); // 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. + ((uint)otherLength) * (nuint)sizeof(T)); // 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); + return length == otherLength && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs index b738f5058d08a..fd89703d9d96f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -24,6 +25,26 @@ namespace System // specified. Note, however, that the Parse methods do not accept // NaNs or Infinities. + internal interface IBinaryIntegerParseAndFormatInfo : IBinaryInteger, IMinMaxValue + where TSelf : unmanaged, IBinaryIntegerParseAndFormatInfo + { + static abstract bool IsSigned { get; } + + static abstract int MaxDigitCount { get; } + + static abstract int MaxHexDigitCount { get; } + + static abstract TSelf MaxValueDiv10 { get; } + + static abstract string OverflowMessage { get; } + + static abstract bool IsGreaterThanAsUnsigned(TSelf left, TSelf right); + + static abstract TSelf MultiplyBy10(TSelf value); + + static abstract TSelf MultiplyBy16(TSelf value); + } + internal static partial class Number { private const int Int32Precision = 10; @@ -45,300 +66,75 @@ internal static partial class Number private const int HalfMaxExponent = 5; private const int HalfMinExponent = -8; - private static unsafe bool TryNumberToInt32(ref NumberBuffer number, ref int value) + private static unsafe bool TryNumberBufferToBinaryInteger(ref NumberBuffer number, ref TInteger value) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo { number.CheckConsistency(); int i = number.Scale; - if (i > Int32Precision || i < number.DigitsCount) - { - return false; - } - byte* p = number.GetDigitsPointer(); - Debug.Assert(p != null); - int n = 0; - while (--i >= 0) - { - if ((uint)n > (0x7FFFFFFF / 10)) - { - return false; - } - n *= 10; - if (*p != '\0') - { - n += (*p++ - '0'); - } - } - if (number.IsNegative) - { - n = -n; - if (n > 0) - { - return false; - } - } - else - { - if (n < 0) - { - return false; - } - } - value = n; - return true; - } - - private static unsafe bool TryNumberToInt64(ref NumberBuffer number, ref long value) - { - number.CheckConsistency(); - int i = number.Scale; - if (i > Int64Precision || i < number.DigitsCount) + if ((i > TInteger.MaxDigitCount) || (i < number.DigitsCount) || (!TInteger.IsSigned && number.IsNegative)) { return false; } - byte* p = number.GetDigitsPointer(); - Debug.Assert(p != null); - long n = 0; - while (--i >= 0) - { - if ((ulong)n > (0x7FFFFFFFFFFFFFFF / 10)) - { - return false; - } - n *= 10; - if (*p != '\0') - { - n += (*p++ - '0'); - } - } - if (number.IsNegative) - { - n = -n; - if (n > 0) - { - return false; - } - } - else - { - if (n < 0) - { - return false; - } - } - value = n; - return true; - } - - private static unsafe bool TryNumberToInt128(ref NumberBuffer number, ref Int128 value) - { - number.CheckConsistency(); - int i = number.Scale; - if ((i > Int128Precision) || (i < number.DigitsCount)) - { - return false; - } byte* p = number.GetDigitsPointer(); + Debug.Assert(p != null); - Int128 n = 0; + TInteger n = TInteger.Zero; + while (--i >= 0) { - if ((UInt128)n > new UInt128(0x0CCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC)) // Int128.MaxValue / 10 - { - return false; - } - n *= 10; - if (*p != '\0') - { - n += (*p++ - '0'); - } - } - if (number.IsNegative) - { - n = -n; - if (n > 0) - { - return false; - } - } - else - { - if (n < 0) + if (TInteger.IsGreaterThanAsUnsigned(n, TInteger.MaxValueDiv10)) { return false; } - } - value = n; - return true; - } - private static unsafe bool TryNumberToUInt32(ref NumberBuffer number, ref uint value) - { - number.CheckConsistency(); + n = TInteger.MultiplyBy10(n); - int i = number.Scale; - if (i > UInt32Precision || i < number.DigitsCount || number.IsNegative) - { - return false; - } - byte* p = number.GetDigitsPointer(); - Debug.Assert(p != null); - uint n = 0; - while (--i >= 0) - { - if (n > (0xFFFFFFFF / 10)) - { - return false; - } - n *= 10; if (*p != '\0') { - uint newN = n + (uint)(*p++ - '0'); - // Detect an overflow here... - if (newN < n) + TInteger newN = n + TInteger.CreateTruncating(*p++ - '0'); + + if (!TInteger.IsSigned && (newN < n)) { return false; } + n = newN; } } - value = n; - return true; - } - private static unsafe bool TryNumberToUInt64(ref NumberBuffer number, ref ulong value) - { - number.CheckConsistency(); - - int i = number.Scale; - if (i > UInt64Precision || i < number.DigitsCount || number.IsNegative) - { - return false; - } - byte* p = number.GetDigitsPointer(); - Debug.Assert(p != null); - ulong n = 0; - while (--i >= 0) + if (TInteger.IsSigned) { - if (n > (0xFFFFFFFFFFFFFFFF / 10)) - { - return false; - } - n *= 10; - if (*p != '\0') + if (number.IsNegative) { - ulong newN = n + (ulong)(*p++ - '0'); - // Detect an overflow here... - if (newN < n) + n = -n; + + if (n > TInteger.Zero) { return false; } - n = newN; } - } - value = n; - return true; - } - - private static unsafe bool TryNumberToUInt128(ref NumberBuffer number, ref UInt128 value) - { - number.CheckConsistency(); - - int i = number.Scale; - if (i > UInt128Precision || (i < number.DigitsCount) || number.IsNegative) - { - return false; - } - byte* p = number.GetDigitsPointer(); - Debug.Assert(p != null); - UInt128 n = 0U; - while (--i >= 0) - { - if (n > new UInt128(0x1999999999999999, 0x9999999999999999)) // UInt128.MaxValue / 10 + else if (n < TInteger.Zero) { return false; } - n *= 10U; - if (*p != '\0') - { - UInt128 newN = n + (UInt128)(*p++ - '0'); - // Detect an overflow here... - if (newN < n) - { - return false; - } - n = newN; - } } + value = n; return true; } - internal static int ParseInt32(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) - { - ParsingStatus status = TryParseInt32(value, styles, info, out int result); - if (status != ParsingStatus.OK) - { - ThrowOverflowOrFormatException(status, value, TypeCode.Int32); - } - - return result; - } - - internal static long ParseInt64(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) + internal static TInteger ParseBinaryInteger(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo { - ParsingStatus status = TryParseInt64(value, styles, info, out long result); - if (status != ParsingStatus.OK) - { - ThrowOverflowOrFormatException(status, value, TypeCode.Int64); - } - - return result; - } - - internal static Int128 ParseInt128(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) - { - ParsingStatus status = TryParseInt128(value, styles, info, out Int128 result); - if (status != ParsingStatus.OK) - { - ThrowOverflowOrFormatExceptionInt128(status); - } - - return result; - } - - internal static uint ParseUInt32(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) - { - ParsingStatus status = TryParseUInt32(value, styles, info, out uint result); - if (status != ParsingStatus.OK) - { - ThrowOverflowOrFormatException(status, value, TypeCode.UInt32); - } - - return result; - } - - internal static ulong ParseUInt64(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) - { - ParsingStatus status = TryParseUInt64(value, styles, info, out ulong result); - if (status != ParsingStatus.OK) - { - ThrowOverflowOrFormatException(status, value, TypeCode.UInt64); - } - - return result; - } + ParsingStatus status = TryParseBinaryInteger(value, styles, info, out TInteger result); - internal static UInt128 ParseUInt128(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info) - { - ParsingStatus status = TryParseUInt128(value, styles, info, out UInt128 result); if (status != ParsingStatus.OK) { - ThrowOverflowOrFormatExceptionUInt128(status); + ThrowOverflowOrFormatException(status, value); } - return result; } @@ -478,1473 +274,159 @@ private static unsafe bool TryParseNumber(scoped ref char* str, char* strEnd, Nu { number.Scale--; } - } - 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 (((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; - } - else - { - break; - } - ch = ++p < strEnd ? *p : '\0'; - } - - bool negExp = false; - number.DigitsCount = digEnd; - number.Digits[digEnd] = (byte)('\0'); - if ((state & StateDigits) != 0) - { - if ((ch == 'E' || ch == 'e') && ((styles & NumberStyles.AllowExponent) != 0)) - { - char* temp = p; - ch = ++p < strEnd ? *p : '\0'; - if ((next = MatchChars(p, strEnd, info._positiveSign)) != null) - { - ch = (p = next) < strEnd ? *p : '\0'; - } - else if ((next = MatchNegativeSignChars(p, strEnd, info)) != null) - { - ch = (p = next) < strEnd ? *p : '\0'; - negExp = true; - } - if (IsDigit(ch)) - { - int exp = 0; - do - { - exp = exp * 10 + (ch - '0'); - ch = ++p < strEnd ? *p : '\0'; - if (exp > 1000) - { - exp = 9999; - while (IsDigit(ch)) - { - ch = ++p < strEnd ? *p : '\0'; - } - } - } while (IsDigit(ch)); - if (negExp) - { - exp = -exp; - } - number.Scale += exp; - } - else - { - p = temp; - ch = p < strEnd ? *p : '\0'; - } - } - - if (number.Kind == NumberBufferKind.FloatingPoint && !number.HasNonZeroTail) - { - // Adjust the number buffer for trailing zeros - int numberOfFractionalDigits = digEnd - number.Scale; - if (numberOfFractionalDigits > 0) - { - numberOfTrailingZeros = Math.Min(numberOfTrailingZeros, numberOfFractionalDigits); - Debug.Assert(numberOfTrailingZeros >= 0); - number.DigitsCount = digEnd - numberOfTrailingZeros; - number.Digits[number.DigitsCount] = (byte)('\0'); - } - } - - while (true) - { - if (!IsWhite(ch) || (styles & NumberStyles.AllowTrailingWhite) == 0) - { - if ((styles & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || (((next = MatchNegativeSignChars(p, strEnd, info)) != null) && (number.IsNegative = true)))) - { - state |= StateSign; - p = next - 1; - } - else if (ch == ')' && ((state & StateParens) != 0)) - { - state &= ~StateParens; - } - else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null) - { - currSymbol = null; - p = next - 1; - } - else - { - break; - } - } - ch = ++p < strEnd ? *p : '\0'; - } - if ((state & StateParens) == 0) - { - if ((state & StateNonZero) == 0) - { - if (number.Kind != NumberBufferKind.Decimal) - { - number.Scale = 0; - } - if ((number.Kind == NumberBufferKind.Integer) && (state & StateDecimal) == 0) - { - number.IsNegative = false; - } - } - str = p; - return true; - } - } - str = p; - return false; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ParsingStatus TryParseInt32(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out int result) - { - if ((styles & ~NumberStyles.Integer) == 0) - { - // Optimized path for the common case of anything that's allowed for integer style. - return TryParseInt32IntegerStyle(value, styles, info, out result); - } - - if ((styles & NumberStyles.AllowHexSpecifier) != 0) - { - result = 0; - return TryParseUInt32HexNumberStyle(value, styles, out Unsafe.As(ref result)); - } - - return TryParseInt32Number(value, styles, info, out result); - } - - private static unsafe ParsingStatus TryParseInt32Number(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out int result) - { - result = 0; - NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[Int32NumberBufferLength]); - - if (!TryStringToNumber(value, styles, ref number, info)) - { - return ParsingStatus.Failed; - } - - if (!TryNumberToInt32(ref number, ref result)) - { - return ParsingStatus.Overflow; - } - - return ParsingStatus.OK; - } - - /// Parses int limited to styles that make up NumberStyles.Integer. - internal static ParsingStatus TryParseInt32IntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out int result) - { - Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[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)); - } - - // Parse leading sign. - int sign = 1; - if ((styles & NumberStyles.AllowLeadingSign) != 0) - { - if (info.HasInvariantNumberSigns) - { - 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 if (info.AllowHyphenDuringParsing && num == '-') - { - sign = -1; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else - { - value = value.Slice(index); - index = 0; - string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign; - 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]; - } - } - } - - bool overflow = false; - int answer = 0; - - if (IsDigit(num)) - { - // Skip past leading zeros. - if (num == '0') - { - do - { - index++; - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - 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 DoneAtEnd; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - answer = 10 * answer + num - '0'; - } - - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - // Potential overflow now processing the 10th digit. - overflow = answer > int.MaxValue / 10; - answer = answer * 10 + num - '0'; - overflow |= (uint)answer > int.MaxValue + (((uint)sign) >> 31); - 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 OverflowExit; - num = value[index]; - } - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = answer * sign; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - 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; - } - - /// Parses long inputs limited to styles that make up NumberStyles.Integer. - internal static ParsingStatus TryParseInt64IntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out long result) - { - Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[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)); - } - - // Parse leading sign. - int sign = 1; - if ((styles & NumberStyles.AllowLeadingSign) != 0) - { - if (info.HasInvariantNumberSigns) - { - 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 if (info.AllowHyphenDuringParsing && num == '-') - { - sign = -1; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else - { - value = value.Slice(index); - index = 0; - string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign; - 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]; - } - } - } - - bool overflow = false; - long answer = 0; - - if (IsDigit(num)) - { - // Skip past leading zeros. - if (num == '0') - { - do - { - index++; - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - 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 DoneAtEnd; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - answer = 10 * answer + num - '0'; - } - - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - // Potential overflow now processing the 19th digit. - overflow = answer > long.MaxValue / 10; - answer = answer * 10 + num - '0'; - overflow |= (ulong)answer > (ulong)long.MaxValue + (((uint)sign) >> 31); - 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 OverflowExit; - num = value[index]; - } - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = answer * sign; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - 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; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ParsingStatus TryParseInt64(ReadOnlySpan 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. - return TryParseInt64IntegerStyle(value, styles, info, out result); - } - - if ((styles & NumberStyles.AllowHexSpecifier) != 0) - { - result = 0; - return TryParseUInt64HexNumberStyle(value, styles, out Unsafe.As(ref result)); - } - - return TryParseInt64Number(value, styles, info, out result); - } - - private static unsafe ParsingStatus TryParseInt64Number(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out long result) - { - result = 0; - NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[Int64NumberBufferLength]); - - if (!TryStringToNumber(value, styles, ref number, info)) - { - return ParsingStatus.Failed; - } - - if (!TryNumberToInt64(ref number, ref result)) - { - return ParsingStatus.Overflow; - } - - return ParsingStatus.OK; - } - - /// Parses Int128 inputs limited to styles that make up NumberStyles.Integer. - internal static ParsingStatus TryParseInt128IntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out Int128 result) - { - Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[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)); - } - - // Parse leading sign. - int sign = 1; - if ((styles & NumberStyles.AllowLeadingSign) != 0) - { - if (info.HasInvariantNumberSigns) - { - 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 if (info.AllowHyphenDuringParsing && num == '-') - { - sign = -1; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else - { - value = value.Slice(index); - index = 0; - string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign; - 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]; - } - } - } - - bool overflow = false; - Int128 answer = 0; - - if (IsDigit(num)) - { - // Skip past leading zeros. - if (num == '0') - { - do - { - index++; - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - 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 < 37; i++) // next 37 digits can't overflow - { - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - answer = 10 * answer + num - '0'; - } - - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - // Potential overflow now processing the 39th digit. - overflow = answer > new Int128(0x0CCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC); // Int128.MaxValue / 10 - answer = answer * 10 + num - '0'; - overflow |= (UInt128)answer > new UInt128(0x7FFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF) + (((uint)sign) >> 31); - 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 OverflowExit; - num = value[index]; - } - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = answer * sign; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - 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; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ParsingStatus TryParseInt128(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out Int128 result) - { - if ((styles & ~NumberStyles.Integer) == 0) - { - // Optimized path for the common case of anything that's allowed for integer style. - return TryParseInt128IntegerStyle(value, styles, info, out result); - } - - if ((styles & NumberStyles.AllowHexSpecifier) != 0) - { - ParsingStatus status = TryParseUInt128HexNumberStyle(value, styles, out UInt128 unsignedResult); - result = new Int128(unsignedResult.Upper, unsignedResult.Lower); - return status; - } - - return TryParseInt128Number(value, styles, info, out result); - } - - private static unsafe ParsingStatus TryParseInt128Number(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out Int128 result) - { - result = 0; - NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[Int128NumberBufferLength]); - - if (!TryStringToNumber(value, styles, ref number, info)) - { - return ParsingStatus.Failed; - } - - if (!TryNumberToInt128(ref number, ref result)) - { - return ParsingStatus.Overflow; - } - - return ParsingStatus.OK; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ParsingStatus TryParseUInt32(ReadOnlySpan 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. - return TryParseUInt32IntegerStyle(value, styles, info, out result); - } - - if ((styles & NumberStyles.AllowHexSpecifier) != 0) - { - return TryParseUInt32HexNumberStyle(value, styles, out result); - } - - return TryParseUInt32Number(value, styles, info, out result); - } - - private static unsafe ParsingStatus TryParseUInt32Number(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out uint result) - { - result = 0; - NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[UInt32NumberBufferLength]); - - if (!TryStringToNumber(value, styles, ref number, info)) - { - return ParsingStatus.Failed; - } - - if (!TryNumberToUInt32(ref number, ref result)) - { - return ParsingStatus.Overflow; - } - - return ParsingStatus.OK; - } - - /// Parses uint limited to styles that make up NumberStyles.Integer. - internal static ParsingStatus TryParseUInt32IntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out uint result) - { - Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[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)); - } - - // Parse leading sign. - bool overflow = false; - if ((styles & NumberStyles.AllowLeadingSign) != 0) - { - if (info.HasInvariantNumberSigns) - { - if (num == '+') - { - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else if (num == '-') - { - overflow = true; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - } - else if (info.AllowHyphenDuringParsing && num == '-') - { - overflow = true; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else - { - value = value.Slice(index); - index = 0; - string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign; - 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)) - { - overflow = true; - 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 DoneAtEnd; - num = value[index]; - } while (num == '0'); - if (!IsDigit(num)) - goto HasTrailingCharsZero; - } - - // 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'; - } - - if ((uint)index >= (uint)value.Length) - goto DoneAtEndButPotentialOverflow; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - // Potential overflow now processing the 10th digit. - overflow |= (uint)answer > uint.MaxValue / 10 || ((uint)answer == uint.MaxValue / 10 && num > '5'); - 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 OverflowExit; - num = value[index]; - } - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = (uint)answer; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - HasTrailingCharsZero: - overflow = false; - 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; - } - - /// Parses uint limited to styles that make up NumberStyles.HexNumber. - internal static ParsingStatus TryParseUInt32HexNumberStyle(ReadOnlySpan value, NumberStyles styles, out uint result) - { - Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[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)); - } - - bool overflow = false; - uint answer = 0; - - if (HexConverter.IsHexChar(num)) - { - // Skip past leading zeros. - if (num == '0') - { - do - { - index++; - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - } while (num == '0'); - if (!HexConverter.IsHexChar(num)) - goto HasTrailingChars; - } - - // Parse up through 8 digits, as no overflow is possible - answer = (uint)HexConverter.FromChar(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]; - - uint numValue = (uint)HexConverter.FromChar(num); - if (numValue == 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 (!HexConverter.IsHexChar(num)) - goto HasTrailingChars; - - // At this point, we're either overflowing or hitting a formatting error. - // Format errors take precedence for compatibility. Read through any remaining digits. - do - { - index++; - if ((uint)index >= (uint)value.Length) - goto OverflowExit; - num = value[index]; - } while (HexConverter.IsHexChar(num)); - overflow = true; - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = answer; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - 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; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ParsingStatus TryParseUInt64(ReadOnlySpan 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. - return TryParseUInt64IntegerStyle(value, styles, info, out result); - } - - if ((styles & NumberStyles.AllowHexSpecifier) != 0) - { - return TryParseUInt64HexNumberStyle(value, styles, out result); - } - - return TryParseUInt64Number(value, styles, info, out result); - } - - private static unsafe ParsingStatus TryParseUInt64Number(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out ulong result) - { - result = 0; - NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[UInt64NumberBufferLength]); - - if (!TryStringToNumber(value, styles, ref number, info)) - { - return ParsingStatus.Failed; - } - - if (!TryNumberToUInt64(ref number, ref result)) - { - return ParsingStatus.Overflow; - } - - return ParsingStatus.OK; - } - - /// Parses ulong limited to styles that make up NumberStyles.Integer. - internal static ParsingStatus TryParseUInt64IntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out ulong result) - { - Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[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)); - } - - // Parse leading sign. - bool overflow = false; - if ((styles & NumberStyles.AllowLeadingSign) != 0) - { - if (info.HasInvariantNumberSigns) - { - if (num == '+') - { - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else if (num == '-') - { - overflow = true; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - } - else if (info.AllowHyphenDuringParsing && num == '-') - { - overflow = true; - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - else - { - value = value.Slice(index); - index = 0; - string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign; - 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)) - { - overflow = true; - index += negativeSign.Length; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; - } - } - } - - long answer = 0; - - if (IsDigit(num)) - { - // Skip past leading zeros. - if (num == '0') - { - do - { - index++; - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - } while (num == '0'); - if (!IsDigit(num)) - goto HasTrailingCharsZero; - } - - // 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'; - } - - if ((uint)index >= (uint)value.Length) - goto DoneAtEndButPotentialOverflow; - num = value[index]; - if (!IsDigit(num)) - goto HasTrailingChars; - index++; - // Potential overflow now processing the 20th digit. - overflow |= (ulong)answer > ulong.MaxValue / 10 || ((ulong)answer == ulong.MaxValue / 10 && num > '5'); - 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 OverflowExit; - num = value[index]; - } - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = (ulong)answer; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - HasTrailingCharsZero: - overflow = false; - 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++) + } + 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)) { - if (!IsWhite(value[index])) - break; + state |= StateDecimal; + p = next - 1; } - if ((uint)index >= (uint)value.Length) - goto DoneAtEndButPotentialOverflow; - } - - if (!TrailingZeros(value, index)) - goto FalseExit; - - goto DoneAtEndButPotentialOverflow; - } - - /// Parses ulong limited to styles that make up NumberStyles.HexNumber. - private static ParsingStatus TryParseUInt64HexNumberStyle(ReadOnlySpan value, NumberStyles styles, out ulong result) - { - Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format"); - - if (value.IsEmpty) - goto FalseExit; - - int index = 0; - int num = value[0]; - - // Skip past any whitespace at the beginning. - if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num)) - { - do + 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)) { - index++; - if ((uint)index >= (uint)value.Length) - goto FalseExit; - num = value[index]; + p = next - 1; } - while (IsWhite(num)); + else + { + break; + } + ch = ++p < strEnd ? *p : '\0'; } - bool overflow = false; - ulong answer = 0; - - if (HexConverter.IsHexChar(num)) + bool negExp = false; + number.DigitsCount = digEnd; + number.Digits[digEnd] = (byte)('\0'); + if ((state & StateDigits) != 0) { - // Skip past leading zeros. - if (num == '0') + if ((ch == 'E' || ch == 'e') && ((styles & NumberStyles.AllowExponent) != 0)) { - do + char* temp = p; + ch = ++p < strEnd ? *p : '\0'; + if ((next = MatchChars(p, strEnd, info._positiveSign)) != null) { - index++; - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - } while (num == '0'); - if (!HexConverter.IsHexChar(num)) - goto HasTrailingChars; + ch = (p = next) < strEnd ? *p : '\0'; + } + else if ((next = MatchNegativeSignChars(p, strEnd, info)) != null) + { + ch = (p = next) < strEnd ? *p : '\0'; + negExp = true; + } + if (IsDigit(ch)) + { + int exp = 0; + do + { + exp = exp * 10 + (ch - '0'); + ch = ++p < strEnd ? *p : '\0'; + if (exp > 1000) + { + exp = 9999; + while (IsDigit(ch)) + { + ch = ++p < strEnd ? *p : '\0'; + } + } + } while (IsDigit(ch)); + if (negExp) + { + exp = -exp; + } + number.Scale += exp; + } + else + { + p = temp; + ch = p < strEnd ? *p : '\0'; + } } - // Parse up through 16 digits, as no overflow is possible - answer = (uint)HexConverter.FromChar(num); // first digit - index++; - for (int i = 0; i < 15; i++) // next 15 digits can't overflow + if (number.Kind == NumberBufferKind.FloatingPoint && !number.HasNonZeroTail) { - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - - uint numValue = (uint)HexConverter.FromChar(num); - if (numValue == 0xFF) - goto HasTrailingChars; - index++; - answer = 16 * answer + numValue; + // Adjust the number buffer for trailing zeros + int numberOfFractionalDigits = digEnd - number.Scale; + if (numberOfFractionalDigits > 0) + { + numberOfTrailingZeros = Math.Min(numberOfTrailingZeros, numberOfFractionalDigits); + Debug.Assert(numberOfTrailingZeros >= 0); + number.DigitsCount = digEnd - numberOfTrailingZeros; + number.Digits[number.DigitsCount] = (byte)('\0'); + } } - // If there's another digit, it's an overflow. - if ((uint)index >= (uint)value.Length) - goto DoneAtEnd; - num = value[index]; - if (!HexConverter.IsHexChar(num)) - goto HasTrailingChars; - - // At this point, we're either overflowing or hitting a formatting error. - // Format errors take precedence for compatibility. Read through any remaining digits. - do + while (true) { - index++; - if ((uint)index >= (uint)value.Length) - goto OverflowExit; - num = value[index]; - } while (HexConverter.IsHexChar(num)); - overflow = true; - goto HasTrailingChars; - } - goto FalseExit; - - DoneAtEndButPotentialOverflow: - if (overflow) - { - goto OverflowExit; - } - DoneAtEnd: - result = answer; - ParsingStatus status = ParsingStatus.OK; - Exit: - return status; - - FalseExit: // parsing failed - result = 0; - status = ParsingStatus.Failed; - goto Exit; - OverflowExit: - result = 0; - status = ParsingStatus.Overflow; - goto Exit; - - 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(ch) || (styles & NumberStyles.AllowTrailingWhite) == 0) + { + if ((styles & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || (((next = MatchNegativeSignChars(p, strEnd, info)) != null) && (number.IsNegative = true)))) + { + state |= StateSign; + p = next - 1; + } + else if (ch == ')' && ((state & StateParens) != 0)) + { + state &= ~StateParens; + } + else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null) + { + currSymbol = null; + p = next - 1; + } + else + { + break; + } + } + ch = ++p < strEnd ? *p : '\0'; + } + if ((state & StateParens) == 0) { - if (!IsWhite(value[index])) - break; + if ((state & StateNonZero) == 0) + { + if (number.Kind != NumberBufferKind.Decimal) + { + number.Scale = 0; + } + if ((number.Kind == NumberBufferKind.Integer) && (state & StateDecimal) == 0) + { + number.IsNegative = false; + } + } + str = p; + return true; } - if ((uint)index >= (uint)value.Length) - goto DoneAtEndButPotentialOverflow; } - - if (!TrailingZeros(value, index)) - goto FalseExit; - - goto DoneAtEndButPotentialOverflow; + str = p; + return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ParsingStatus TryParseUInt128(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out UInt128 result) + internal static ParsingStatus TryParseBinaryInteger(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out TInteger result) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo { if ((styles & ~NumberStyles.Integer) == 0) { // Optimized path for the common case of anything that's allowed for integer style. - return TryParseUInt128IntegerStyle(value, styles, info, out result); + return TryParseBinaryIntegerStyle(value, styles, info, out result); } if ((styles & NumberStyles.AllowHexSpecifier) != 0) { - return TryParseUInt128HexNumberStyle(value, styles, out result); + return TryParseBinaryIntegerHexNumberStyle(value, styles, out result); } - return TryParseUInt128Number(value, styles, info, out result); + return TryParseBinaryIntegerNumber(value, styles, info, out result); } - private static unsafe ParsingStatus TryParseUInt128Number(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out UInt128 result) + private static unsafe ParsingStatus TryParseBinaryIntegerNumber(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out TInteger result) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo { - result = 0U; - NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[UInt128NumberBufferLength]); + result = TInteger.Zero; + NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, stackalloc byte[TInteger.MaxDigitCount + 1]); if (!TryStringToNumber(value, styles, ref number, info)) { return ParsingStatus.Failed; } - if (!TryNumberToUInt128(ref number, ref result)) + if (!TryNumberBufferToBinaryInteger(ref number, ref result)) { return ParsingStatus.Overflow; } @@ -1952,8 +434,9 @@ private static unsafe ParsingStatus TryParseUInt128Number(ReadOnlySpan val return ParsingStatus.OK; } - /// Parses UInt128 limited to styles that make up NumberStyles.Integer. - internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out UInt128 result) + /// Parses int limited to styles that make up NumberStyles.Integer. + internal static ParsingStatus TryParseBinaryIntegerStyle(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out TInteger result) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo { Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format"); @@ -1977,21 +460,21 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val } // Parse leading sign. - bool overflow = false; + bool isNegative = false; if ((styles & NumberStyles.AllowLeadingSign) != 0) { if (info.HasInvariantNumberSigns) { - if (num == '+') + if (num == '-') { + isNegative = true; index++; if ((uint)index >= (uint)value.Length) goto FalseExit; num = value[index]; } - else if (num == '-') + else if (num == '+') { - overflow = true; index++; if ((uint)index >= (uint)value.Length) goto FalseExit; @@ -2000,7 +483,7 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val } else if (info.AllowHyphenDuringParsing && num == '-') { - overflow = true; + isNegative = true; index++; if ((uint)index >= (uint)value.Length) goto FalseExit; @@ -2020,7 +503,7 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val } else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign)) { - overflow = true; + isNegative = true; index += negativeSign.Length; if ((uint)index >= (uint)value.Length) goto FalseExit; @@ -2029,7 +512,8 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val } } - Int128 answer = 0; + bool overflow = !TInteger.IsSigned && isNegative; + TInteger answer = TInteger.Zero; if (IsDigit(num)) { @@ -2043,35 +527,63 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val goto DoneAtEnd; num = value[index]; } while (num == '0'); + if (!IsDigit(num)) - goto HasTrailingCharsZero; + { + if (!TInteger.IsSigned) + { + overflow = false; + } + goto HasTrailingChars; + } } - // Parse most digits, up to the potential for overflow, which can't happen until after 38 digits. - answer = num - '0'; // first digit + // Parse most digits, up to the potential for overflow, which can't happen until after MaxDigitCount - 1 digits. + answer = TInteger.CreateTruncating(num - '0'); // first digit index++; - for (int i = 0; i < 37; i++) // next 37 digits can't overflow + for (int i = 0; i < TInteger.MaxDigitCount - 2; i++) // next MaxDigitCount - 2 digits can't overflow { if ((uint)index >= (uint)value.Length) - goto DoneAtEndButPotentialOverflow; + { + if (!TInteger.IsSigned) + goto DoneAtEndButPotentialOverflow; + else + goto DoneAtEnd; + } num = value[index]; if (!IsDigit(num)) goto HasTrailingChars; index++; - answer = 10 * answer + num - '0'; + answer = TInteger.MultiplyBy10(answer); + answer += TInteger.CreateTruncating(num - '0'); } if ((uint)index >= (uint)value.Length) - goto DoneAtEndButPotentialOverflow; + { + if (!TInteger.IsSigned) + goto DoneAtEndButPotentialOverflow; + else + goto DoneAtEnd; + } num = value[index]; if (!IsDigit(num)) goto HasTrailingChars; index++; - // Potential overflow now processing the 39th digit. - UInt128 maxValueDiv10 = new UInt128(0x1999999999999999, 0x9999999999999999); // UInt128.MaxValue / 10 - overflow |= (UInt128)answer > maxValueDiv10; - overflow |= ((UInt128)answer == maxValueDiv10 && num > '5'); - answer = answer * 10 + num - '0'; + // Potential overflow now processing the MaxDigitCount digit. + if (!TInteger.IsSigned) + { + overflow |= (answer > TInteger.MaxValueDiv10) || (answer == TInteger.MaxValueDiv10) && (num > '5'); + } + else + { + overflow = answer > TInteger.MaxValueDiv10; + } + answer = TInteger.MultiplyBy10(answer); + answer += TInteger.CreateTruncating(num - '0'); + if (TInteger.IsSigned) + { + overflow |= TInteger.IsGreaterThanAsUnsigned(answer, TInteger.MaxValue + (isNegative ? TInteger.One : TInteger.Zero)); + } if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow; @@ -2096,22 +608,27 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val goto OverflowExit; } DoneAtEnd: - result = (UInt128)answer; + if (!TInteger.IsSigned) + { + result = answer; + } + else + { + result = isNegative ? -answer : answer; + } ParsingStatus status = ParsingStatus.OK; Exit: return status; FalseExit: // parsing failed - result = 0U; + result = TInteger.Zero; status = ParsingStatus.Failed; goto Exit; OverflowExit: - result = 0U; + result = TInteger.Zero; status = ParsingStatus.Overflow; goto Exit; - HasTrailingCharsZero: - overflow = false; 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)) @@ -2133,8 +650,9 @@ internal static ParsingStatus TryParseUInt128IntegerStyle(ReadOnlySpan val goto DoneAtEndButPotentialOverflow; } - /// Parses UInt128 limited to styles that make up NumberStyles.HexNumber. - private static ParsingStatus TryParseUInt128HexNumberStyle(ReadOnlySpan value, NumberStyles styles, out UInt128 result) + /// Parses uint limited to styles that make up NumberStyles.HexNumber. + internal static ParsingStatus TryParseBinaryIntegerHexNumberStyle(ReadOnlySpan value, NumberStyles styles, out TInteger result) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo { Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format"); @@ -2158,7 +676,7 @@ private static ParsingStatus TryParseUInt128HexNumberStyle(ReadOnlySpan va } bool overflow = false; - UInt128 answer = 0U; + TInteger answer = TInteger.Zero; if (HexConverter.IsHexChar(num)) { @@ -2176,10 +694,10 @@ private static ParsingStatus TryParseUInt128HexNumberStyle(ReadOnlySpan va goto HasTrailingChars; } - // Parse up through 32 digits, as no overflow is possible - answer = (uint)HexConverter.FromChar(num); // first digit + // Parse up through MaxHexDigitCount digits, as no overflow is possible + answer = TInteger.CreateTruncating((uint)HexConverter.FromChar(num)); // first digit index++; - for (int i = 0; i < 31; i++) // next 31 digits can't overflow + for (int i = 0; i < TInteger.MaxHexDigitCount - 1; i++) // next MaxHexDigitCount - 1 digits can't overflow { if ((uint)index >= (uint)value.Length) goto DoneAtEnd; @@ -2189,7 +707,8 @@ private static ParsingStatus TryParseUInt128HexNumberStyle(ReadOnlySpan va if (numValue == 0xFF) goto HasTrailingChars; index++; - answer = 16U * answer + numValue; + answer = TInteger.MultiplyBy16(answer); + answer += TInteger.CreateTruncating(numValue); } // If there's another digit, it's an overflow. @@ -2225,11 +744,11 @@ private static ParsingStatus TryParseUInt128HexNumberStyle(ReadOnlySpan va return status; FalseExit: // parsing failed - result = 0U; + result = TInteger.Zero; status = ParsingStatus.Failed; goto Exit; OverflowExit: - result = 0U; + result = TInteger.Zero; status = ParsingStatus.Overflow; goto Exit; @@ -2719,6 +1238,13 @@ internal enum ParsingStatus [DoesNotReturn] internal static void ThrowOverflowOrFormatException(ParsingStatus status, ReadOnlySpan value, TypeCode type = 0) => throw GetException(status, value, type); + [DoesNotReturn] + internal static void ThrowOverflowOrFormatException(ParsingStatus status, ReadOnlySpan value) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo + { + throw GetException(status, value); + } + [DoesNotReturn] internal static void ThrowOverflowException(TypeCode type) => throw GetOverflowException(type); @@ -2736,6 +1262,15 @@ private static Exception GetException(ParsingStatus status, ReadOnlySpan v return GetOverflowException(type); } + private static Exception GetException(ParsingStatus status, ReadOnlySpan value) + where TInteger : unmanaged, IBinaryIntegerParseAndFormatInfo + { + if (status == ParsingStatus.Failed) + return new FormatException(SR.Format(SR.Format_InvalidStringWithValue, value.ToString())); + + return new OverflowException(TInteger.OverflowMessage); + } + private static OverflowException GetOverflowException(TypeCode type) { string s; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs index 4c7a813829a2b..d284f4221334d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.PlatformNotSupported.cs @@ -102,6 +102,27 @@ public abstract class PackedSimd public static Vector128 Negate(Vector128 value) { throw new PlatformNotSupportedException(); } public static Vector128 Negate(Vector128 value) { throw new PlatformNotSupportedException(); } + // Extended integer arithmetic + + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + + public static Vector128 AddPairwiseWidening(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw new PlatformNotSupportedException(); } + // Bit shifts public static Vector128 ShiftLeft(Vector128 value, int count) { throw new PlatformNotSupportedException(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs index 3fb4a1f32b947..d17d6164ef859 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Wasm/PackedSimd.cs @@ -430,6 +430,91 @@ public abstract class PackedSimd [Intrinsic] public static Vector128 Negate(Vector128 value) => Negate(value); + // Extended integer arithmetic + + /// + /// i16x8.extmul_low_i8x16_s + /// + [Intrinsic] + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); + /// + /// i16x8.extmul_low_i8x16_u + /// + [Intrinsic] + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); + /// + /// i32x4.extmul_low_i16x8_s + /// + [Intrinsic] + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); + /// + /// i32x4.extmul_low_i16x8_u + /// + [Intrinsic] + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); + /// + /// i64x2.extmul_low_i32x4_s + /// + [Intrinsic] + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); + /// + /// i64x2.extmul_low_i32x4_u + /// + [Intrinsic] + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) => MultiplyWideningLower(left, right); + + /// + /// i16x8.extmul_high_i8x16_s + /// + [Intrinsic] + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); + /// + /// i16x8.extmul_high_i8x16_u + /// + [Intrinsic] + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); + /// + /// i32x4.extmul_high_i16x8_s + /// + [Intrinsic] + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); + /// + /// i32x4.extmul_high_i16x8_u + /// + [Intrinsic] + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); + /// + /// i64x2.extmul_high_i32x4_s + /// + [Intrinsic] + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); + /// + /// i64x2.extmul_high_i32x4_u + /// + [Intrinsic] + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) => MultiplyWideningUpper(left, right); + + /// + /// i16x8.extadd_pairwise_i8x16_s + /// + [Intrinsic] + public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); + /// + /// i16x8.extadd_pairwise_i8x16_u + /// + [Intrinsic] + public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); + /// + /// i32x4.extadd_pairwise_i16x8_s + /// + [Intrinsic] + public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); + /// + /// i32x4.extadd_pairwise_i16x8_u + /// + [Intrinsic] + public static Vector128 AddPairwiseWidening(Vector128 value) => AddPairwiseWidening(value); + // Bit shifts /// diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index 610c5f5c6dd4e..9f09ec5318ad6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -24,7 +24,8 @@ public readonly struct SByte IBinaryInteger, IMinMaxValue, ISignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly sbyte m_value; // Do not rename (binary serialization) @@ -128,106 +129,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatInt32(m_value, 0x000000FF, format, provider, utf8Destination, out bytesWritten); } - public static sbyte Parse(string s) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static sbyte Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static sbyte Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.CurrentInfo); - } + public static sbyte Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static sbyte Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static sbyte Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - // Parses a signed byte from a String in the given style. If - // a NumberFormatInfo isn't specified, the current culture's - // NumberFormatInfo is assumed. - // public static sbyte Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static sbyte Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Parse(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - private static sbyte Parse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info) - { - Number.ParsingStatus status = Number.TryParseInt32(s, style, info, out int i); - if (status != Number.ParsingStatus.OK) - { - Number.ThrowOverflowOrFormatException(status, s, TypeCode.SByte); - } - - // For hex number styles AllowHexSpecifier >> 2 == 0x80 and cancels out MinValue so the check is effectively: (uint)i > byte.MaxValue - // For integer styles it's zero and the effective check is (uint)(i - MinValue) > byte.MaxValue - if ((uint)(i - MinValue - ((int)(style & NumberStyles.AllowHexSpecifier) >> 2)) > byte.MaxValue) - { - Number.ThrowOverflowException(TypeCode.SByte); - } - return (sbyte)i; - } - - public static bool TryParse([NotNullWhen(true)] string? s, out sbyte result) - { - if (s == null) - { - result = 0; - return false; - } - - return TryParse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } + public static bool TryParse([NotNullWhen(true)] string? s, out sbyte result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - public static bool TryParse(ReadOnlySpan s, out sbyte result) - { - return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } + public static bool TryParse(ReadOnlySpan s, out sbyte result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out sbyte result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return TryParse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider), out result); + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out sbyte result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result); - } - - private static bool TryParse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info, out sbyte result) - { - // For hex number styles AllowHexSpecifier >> 2 == 0x80 and cancels out MinValue so the check is effectively: (uint)i > byte.MaxValue - // For integer styles it's zero and the effective check is (uint)(i - MinValue) > byte.MaxValue - if (Number.TryParseInt32(s, style, info, out int i) != Number.ParsingStatus.OK - || (uint)(i - MinValue - ((int)(style & NumberStyles.AllowHexSpecifier) >> 2)) > byte.MaxValue) - { - result = 0; - return false; - } - result = (sbyte)i; - return true; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1386,5 +1325,25 @@ static bool INumberBase.TryConvertToTruncating(sbyte value, [Mayb /// static sbyte IUnaryPlusOperators.operator +(sbyte value) => (sbyte)(+value); + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => true; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 3; // 127 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 2; // 0x7F + + static sbyte IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_SByte; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(sbyte left, sbyte right) => (byte)(left) > (byte)(right); + + static sbyte IBinaryIntegerParseAndFormatInfo.MultiplyBy10(sbyte value) => (sbyte)(value * 10); + + static sbyte IBinaryIntegerParseAndFormatInfo.MultiplyBy16(sbyte value) => (sbyte)(value * 16); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs index 6edff0f0eb414..24fa9f8f8e034 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -490,7 +490,7 @@ internal TimerQueueTimer(TimerCallback timerCallback, object? state, TimeSpan du { } - private static uint GetMilliseconds(TimeSpan time, [CallerArgumentExpression("time")] string? parameter = null) + private static uint GetMilliseconds(TimeSpan time, [CallerArgumentExpression(nameof(time))] string? parameter = null) { long tm = (long)time.TotalMilliseconds; ArgumentOutOfRangeException.ThrowIfLessThan(tm, -1, parameter); diff --git a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs index e8b9232e48901..142b94d84a545 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -521,6 +521,12 @@ internal static void ThrowFormatException_BadFormatSpecifier() throw new FormatException(SR.Argument_BadFormatSpecifier); } + [DoesNotReturn] + internal static void ThrowFormatException_NeedSingleChar() + { + throw new FormatException(SR.Format_NeedSingleChar); + } + [DoesNotReturn] internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge() { diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs index c420c268fe018..85ff1a912a4c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs @@ -19,7 +19,8 @@ public readonly struct UInt128 : IBinaryInteger, IMinMaxValue, IUnsignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { internal const int Size = 16; @@ -126,75 +127,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatUInt128(this, format, provider, utf8Destination, out bytesWritten); } - public static UInt128 Parse(string s) - { - ArgumentNullException.ThrowIfNull(s); - return Number.ParseUInt128(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static UInt128 Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static UInt128 Parse(string s, NumberStyles style) - { - ArgumentNullException.ThrowIfNull(s); - NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseUInt128(s, style, NumberFormatInfo.CurrentInfo); - } + public static UInt128 Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static UInt128 Parse(string s, IFormatProvider? provider) - { - ArgumentNullException.ThrowIfNull(s); - return Number.ParseUInt128(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static UInt128 Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); public static UInt128 Parse(string s, NumberStyles style, IFormatProvider? provider) { - ArgumentNullException.ThrowIfNull(s); - NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseUInt128(s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static UInt128 Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseUInt128(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out UInt128 result) - { - if (s is not null) - { - return Number.TryParseUInt128IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } - else - { - result = default; - return false; - } - } + public static bool TryParse([NotNullWhen(true)] string? s, out UInt128 result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - public static bool TryParse(ReadOnlySpan s, out UInt128 result) - { - return Number.TryParseUInt128IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse(ReadOnlySpan s, out UInt128 result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out UInt128 result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s is not null) - { - return Number.TryParseUInt128(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; - } - else + if (s is null) { - result = default; + result = 0; return false; } + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out UInt128 result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.TryParseUInt128(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -2162,5 +2132,25 @@ static bool INumberBase.TryConvertToTruncating(UInt128 value, [ /// public static UInt128 operator +(UInt128 value) => value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => false; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 39; // 340_282_366_920_938_463_463_374_607_431_768_211_455 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 32; // 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF + + static UInt128 IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => new UInt128(0x1999_9999_9999_9999, 0x9999_9999_9999_9999); + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_UInt128; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(UInt128 left, UInt128 right) => left > right; + + static UInt128 IBinaryIntegerParseAndFormatInfo.MultiplyBy10(UInt128 value) => value * 10; + + static UInt128 IBinaryIntegerParseAndFormatInfo.MultiplyBy16(UInt128 value) => value * 16; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs index d43bd48fe68b0..54f87f1264cea 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs @@ -24,7 +24,8 @@ public readonly struct UInt16 IBinaryInteger, IMinMaxValue, IUnsignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly ushort m_value; // Do not rename (binary serialization) @@ -120,95 +121,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatUInt32(m_value, format, provider, utf8Destination, out bytesWritten); } - public static ushort Parse(string s) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static ushort Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static ushort Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.CurrentInfo); - } + public static ushort Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static ushort Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static ushort Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); public static ushort Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Parse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static ushort Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Parse(s, style, NumberFormatInfo.GetInstance(provider)); - } - - private static ushort Parse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info) - { - Number.ParsingStatus status = Number.TryParseUInt32(s, style, info, out uint i); - if (status != Number.ParsingStatus.OK) - { - Number.ThrowOverflowOrFormatException(status, s, TypeCode.UInt16); - } - - if (i > MaxValue) Number.ThrowOverflowException(TypeCode.UInt16); - return (ushort)i; + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out ushort result) - { - if (s == null) - { - result = 0; - return false; - } + public static bool TryParse([NotNullWhen(true)] string? s, out ushort result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - return TryParse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } - - public static bool TryParse(ReadOnlySpan s, out ushort result) - { - return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result); - } + public static bool TryParse(ReadOnlySpan s, out ushort result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ushort result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return TryParse((ReadOnlySpan)s, style, NumberFormatInfo.GetInstance(provider), out result); + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out ushort result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result); - } - - private static bool TryParse(ReadOnlySpan s, NumberStyles style, NumberFormatInfo info, out ushort result) - { - if (Number.TryParseUInt32(s, style, info, out uint i) != Number.ParsingStatus.OK - || i > MaxValue) - { - result = 0; - return false; - } - result = (ushort)i; - return true; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1229,5 +1179,25 @@ static bool INumberBase.TryConvertToTruncating(ushort value, [Ma /// static ushort IUnaryPlusOperators.operator +(ushort value) => (ushort)(+value); + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => false; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 5; // 65_535 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 4; // 0xFFFF + + static ushort IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_UInt16; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(ushort left, ushort right) => left > right; + + static ushort IBinaryIntegerParseAndFormatInfo.MultiplyBy10(ushort value) => (ushort)(value * 10); + + static ushort IBinaryIntegerParseAndFormatInfo.MultiplyBy16(ushort value) => (ushort)(value * 16); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs index 0a9f9c0aea125..dcec51866930d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs @@ -24,7 +24,8 @@ public readonly struct UInt32 IBinaryInteger, IMinMaxValue, IUnsignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly uint m_value; // Do not rename (binary serialization) @@ -130,71 +131,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatUInt32(m_value, format, provider, utf8Destination, out bytesWritten); } - public static uint Parse(string s) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static uint Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static uint Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt32(s, style, NumberFormatInfo.CurrentInfo); - } + public static uint Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static uint Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static uint Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); public static uint Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt32(s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static uint Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseUInt32(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out uint result) - { - if (s == null) - { - result = 0; - return false; - } + public static bool TryParse([NotNullWhen(true)] string? s, out uint result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - return Number.TryParseUInt32IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } - - public static bool TryParse(ReadOnlySpan s, out uint result) - { - return Number.TryParseUInt32IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse(ReadOnlySpan s, out uint result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out uint result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return Number.TryParseUInt32(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out uint result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.TryParseUInt32(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1244,5 +1218,25 @@ static bool INumberBase.TryConvertToTruncating(uint value, [MaybeN /// static uint IUnaryPlusOperators.operator +(uint value) => +value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => false; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 10; // 4_294_967_295 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 8; // 0xFFFF_FFFF + + static uint IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_UInt32; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(uint left, uint right) => left > right; + + static uint IBinaryIntegerParseAndFormatInfo.MultiplyBy10(uint value) => value * 10; + + static uint IBinaryIntegerParseAndFormatInfo.MultiplyBy16(uint value) => value * 16; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs index 962064b83c310..c9b2e057480d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs @@ -24,7 +24,8 @@ public readonly struct UInt64 IBinaryInteger, IMinMaxValue, IUnsignedNumber, - IUtf8SpanFormattable + IUtf8SpanFormattable, + IBinaryIntegerParseAndFormatInfo { private readonly ulong m_value; // Do not rename (binary serialization) @@ -129,71 +130,44 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS return Number.TryFormatUInt64(m_value, format, provider, utf8Destination, out bytesWritten); } - public static ulong Parse(string s) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); - } + public static ulong Parse(string s) => Parse(s, NumberStyles.Integer, provider: null); - public static ulong Parse(string s, NumberStyles style) - { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt64(s, style, NumberFormatInfo.CurrentInfo); - } + public static ulong Parse(string s, NumberStyles style) => Parse(s, style, provider: null); - public static ulong Parse(string s, IFormatProvider? provider) - { - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); - } + public static ulong Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); public static ulong Parse(string s, NumberStyles style, IFormatProvider? provider) { - NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseUInt64(s, style, NumberFormatInfo.GetInstance(provider)); + if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); } + return Parse(s.AsSpan(), style, provider); } public static ulong Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.ParseUInt64(s, style, NumberFormatInfo.GetInstance(provider)); + return Number.ParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse([NotNullWhen(true)] string? s, out ulong result) - { - if (s == null) - { - result = 0; - return false; - } + public static bool TryParse([NotNullWhen(true)] string? s, out ulong result) => TryParse(s, NumberStyles.Integer, provider: null, out result); - return Number.TryParseUInt64IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } - - public static bool TryParse(ReadOnlySpan s, out ulong result) - { - return Number.TryParseUInt64IntegerStyle(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; - } + public static bool TryParse(ReadOnlySpan s, out ulong result) => TryParse(s, NumberStyles.Integer, provider: null, out result); public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ulong result) { NumberFormatInfo.ValidateParseStyleInteger(style); - if (s == null) + if (s is null) { result = 0; return false; } - - return Number.TryParseUInt64(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out ulong result) { NumberFormatInfo.ValidateParseStyleInteger(style); - return Number.TryParseUInt64(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; + return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } // @@ -1237,5 +1211,25 @@ static bool INumberBase.TryConvertToTruncating(ulong value, [Mayb /// static ulong IUnaryPlusOperators.operator +(ulong value) => +value; + + // + // IBinaryIntegerParseAndFormatInfo + // + + static bool IBinaryIntegerParseAndFormatInfo.IsSigned => false; + + static int IBinaryIntegerParseAndFormatInfo.MaxDigitCount => 20; // 18_446_744_073_709_551_615 + + static int IBinaryIntegerParseAndFormatInfo.MaxHexDigitCount => 16; // 0xFFFF_FFFF_FFFF_FFFF + + static ulong IBinaryIntegerParseAndFormatInfo.MaxValueDiv10 => MaxValue / 10; + + static string IBinaryIntegerParseAndFormatInfo.OverflowMessage => SR.Overflow_UInt64; + + static bool IBinaryIntegerParseAndFormatInfo.IsGreaterThanAsUnsigned(ulong left, ulong right) => left > right; + + static ulong IBinaryIntegerParseAndFormatInfo.MultiplyBy10(ulong value) => value * 10; + + static ulong IBinaryIntegerParseAndFormatInfo.MultiplyBy16(ulong value) => value * 16; } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaImporter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaImporter.cs index 01ff1b823140a..2696c5dbe5425 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaImporter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SchemaImporter.cs @@ -43,7 +43,7 @@ internal SchemaImporter(XmlSchemaSet schemas, IEnumerable? typ [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - internal void Import([NotNullIfNotNull("_elements")] out List? elementTypeNames) + internal void Import([NotNullIfNotNull(nameof(_elements))] out List? elementTypeNames) { elementTypeNames = null!; diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 4b98633ea73d8..26affa796b3a1 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -5729,6 +5729,22 @@ public abstract partial class PackedSimd public static Vector128 Negate(Vector128 value) { throw null; } public static Vector128 Negate(Vector128 value) { throw null; } public static Vector128 Negate(Vector128 value) { throw null; } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningLower(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw null; } + public static Vector128 MultiplyWideningUpper(Vector128 left, Vector128 right) { throw null; } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw null; } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw null; } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw null; } + public static Vector128 AddPairwiseWidening(Vector128 value) { throw null; } public static Vector128 ShiftLeft(Vector128 value, int count) { throw null; } public static Vector128 ShiftLeft(Vector128 value, int count) { throw null; } public static Vector128 ShiftLeft(Vector128 value, int count) { throw null; } diff --git a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs index 0d371c4d7886c..eb870ed17e3d5 100644 --- a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs +++ b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs @@ -240,7 +240,7 @@ namespace System.Numerics public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? value, out System.Numerics.BigInteger result) { throw null; } public bool TryWriteBytes(System.Span destination, out int bytesWritten, bool isUnsigned = false, bool isBigEndian = false) { throw null; } } - public readonly partial struct Complex : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators + public readonly partial struct Complex : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.IUtf8SpanFormattable { private readonly int _dummyPrimitive; public static readonly System.Numerics.Complex ImaginaryOne; @@ -376,7 +376,8 @@ namespace System.Numerics public string ToString(System.IFormatProvider? provider) { throw null; } public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format) { throw null; } public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format, System.IFormatProvider? provider) { throw null; } - public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider? provider) { throw null; } + public bool TryFormat(System.Span destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] System.ReadOnlySpan format = default, System.IFormatProvider? provider = null) { throw null; } + public bool TryFormat(System.Span utf8Destination, out int bytesWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] System.ReadOnlySpan format = default, System.IFormatProvider? provider = null) { throw null; } public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Numerics.Complex result) { throw null; } public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.Numerics.Complex result) { throw null; } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Numerics.Complex result) { throw null; } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 0e73eb3b94960..88f8ef25fe205 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -19,7 +19,8 @@ public readonly struct Complex : IEquatable, IFormattable, INumberBase, - ISignedNumber + ISignedNumber, + IUtf8SpanFormattable { private const NumberStyles DefaultNumberStyle = NumberStyles.Float | NumberStyles.AllowThousands; @@ -393,14 +394,23 @@ public bool Equals(Complex value) public override int GetHashCode() => HashCode.Combine(m_real, m_imaginary); - public override string ToString() => $"<{m_real}; {m_imaginary}>"; + public override string ToString() => ToString(null, null); public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format) => ToString(format, null); public string ToString(IFormatProvider? provider) => ToString(null, provider); - public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider) => - $"<{m_real.ToString(format, provider)}; {m_imaginary.ToString(format, provider)}>"; + public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider) + { + // $"<{m_real.ToString(format, provider)}; {m_imaginary.ToString(format, provider)}>"; + var handler = new DefaultInterpolatedStringHandler(4, 2, provider, stackalloc char[512]); + handler.AppendLiteral("<"); + handler.AppendFormatted(m_real, format); + handler.AppendLiteral("; "); + handler.AppendFormatted(m_imaginary, format); + handler.AppendLiteral(">"); + return handler.ToStringAndClear(); + } public static Complex Sin(Complex value) { @@ -2199,46 +2209,52 @@ public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, I // /// - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) - { - int charsWrittenSoFar = 0; - - // We have at least 6 more characters for: <0; 0> - if (destination.Length < 6) - { - charsWritten = charsWrittenSoFar; - return false; - } + public bool TryFormat(Span destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.NumericFormat)] ReadOnlySpan format = default, IFormatProvider? provider = null) => + TryFormatCore(destination, out charsWritten, format, provider); - destination[charsWrittenSoFar++] = '<'; + public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringSyntax(StringSyntaxAttribute.NumericFormat)] ReadOnlySpan format = default, IFormatProvider? provider = null) => + TryFormatCore(utf8Destination, out bytesWritten, format, provider); - bool tryFormatSucceeded = m_real.TryFormat(destination.Slice(charsWrittenSoFar), out int tryFormatCharsWritten, format, provider); - charsWrittenSoFar += tryFormatCharsWritten; + private bool TryFormatCore(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) where TChar : unmanaged, IBinaryInteger + { + Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); - // We have at least 4 more characters for: ; 0> - if (!tryFormatSucceeded || (destination.Length < (charsWrittenSoFar + 4))) + // We have at least 6 more characters for: <0; 0> + if (destination.Length >= 6) { - charsWritten = charsWrittenSoFar; - return false; - } - - destination[charsWrittenSoFar++] = ';'; - destination[charsWrittenSoFar++] = ' '; - - tryFormatSucceeded = m_imaginary.TryFormat(destination.Slice(charsWrittenSoFar), out tryFormatCharsWritten, format, provider); - charsWrittenSoFar += tryFormatCharsWritten; + int realChars; + if (typeof(TChar) == typeof(char) ? + m_real.TryFormat(MemoryMarshal.Cast(destination.Slice(1)), out realChars, format, provider) : + m_real.TryFormat(MemoryMarshal.Cast(destination.Slice(1)), out realChars, format, provider)) + { + destination[0] = TChar.CreateTruncating('<'); + destination = destination.Slice(1 + realChars); // + 1 for < - // We have at least 1 more character for: > - if (!tryFormatSucceeded || (destination.Length < (charsWrittenSoFar + 1))) - { - charsWritten = charsWrittenSoFar; - return false; + // We have at least 4 more characters for: ; 0> + if (destination.Length >= 4) + { + int imaginaryChars; + if (typeof(TChar) == typeof(char) ? + m_imaginary.TryFormat(MemoryMarshal.Cast(destination.Slice(2)), out imaginaryChars, format, provider) : + m_imaginary.TryFormat(MemoryMarshal.Cast(destination.Slice(2)), out imaginaryChars, format, provider)) + { + // We have 1 more character for: > + if ((uint)(2 + imaginaryChars) < (uint)destination.Length) + { + destination[0] = TChar.CreateTruncating(';'); + destination[1] = TChar.CreateTruncating(' '); + destination[2 + imaginaryChars] = TChar.CreateTruncating('>'); + + charsWritten = realChars + imaginaryChars + 4; + return true; + } + } + } + } } - destination[charsWrittenSoFar++] = '>'; - - charsWritten = charsWrittenSoFar; - return true; + charsWritten = 0; + return false; } // diff --git a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs index c5f0f4fefaa81..ea37fb5dc4614 100644 --- a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs +++ b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Runtime.CompilerServices; - +using System.Text; using Xunit; namespace System.Numerics.Tests @@ -1730,25 +1731,79 @@ public static void Tanh_Advanced(double real, double imaginary, double expectedR public static void ToStringTest(double real, double imaginary) { var complex = new Complex(real, imaginary); + NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat; - string expected = "<" + real.ToString() + "; " + imaginary.ToString() + ">"; - string actual = complex.ToString(); - Assert.Equal(expected, actual); + Assert.Equal($"<{real}; {imaginary}>", complex.ToString()); - NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat; - expected = "<" + real.ToString(numberFormatInfo) + "; " + imaginary.ToString(numberFormatInfo) + ">"; - actual = complex.ToString(numberFormatInfo); - Assert.Equal(expected, complex.ToString(numberFormatInfo)); + Assert.Equal($"<{real.ToString(numberFormatInfo)}; {imaginary.ToString(numberFormatInfo)}>", complex.ToString(numberFormatInfo)); + Assert.Equal($"<{real.ToString((string)null)}; {imaginary.ToString((string)null)}>", complex.ToString((string)null)); + Assert.Equal($"<{real.ToString((string)null, numberFormatInfo)}; {imaginary.ToString((string)null, numberFormatInfo)}>", complex.ToString((string)null, numberFormatInfo)); foreach (string format in s_supportedStandardNumericFormats) { - expected = "<" + real.ToString(format) + "; " + imaginary.ToString(format) + ">"; - actual = complex.ToString(format); - Assert.Equal(expected, actual); + Assert.Equal($"<{real.ToString(format)}; {imaginary.ToString(format)}>", complex.ToString(format)); + Assert.Equal($"<{real.ToString(format, numberFormatInfo)}; {imaginary.ToString(format, numberFormatInfo)}>", complex.ToString(format, numberFormatInfo)); + } + } + + [Theory] + [MemberData(nameof(Boundaries_2_TestData))] + [MemberData(nameof(Primitives_2_TestData))] + [MemberData(nameof(Random_2_TestData))] + [MemberData(nameof(SmallRandom_2_TestData))] + [MemberData(nameof(Invalid_2_TestData))] + public static void TryFormatTest(double real, double imaginary) + { + var complex = new Complex(real, imaginary); + + // UTF16 + { + foreach (NumberFormatInfo numberFormatInfo in new[] { CultureInfo.CurrentCulture.NumberFormat, null }) + { + foreach (string format in s_supportedStandardNumericFormats.Append(null)) + { + string expected = $"<{real.ToString(format, numberFormatInfo)}; {imaginary.ToString(format, numberFormatInfo)}>"; + int charsWritten; + + // Just right or larger than required storage + for (int additional = 0; additional < 2; additional++) + { + char[] chars = new char[expected.Length + additional]; + Assert.True(complex.TryFormat(chars, out charsWritten, format, numberFormatInfo)); + Assert.Equal(expected.Length, charsWritten); + Assert.Equal(expected, new string(expected.AsSpan(0, expected.Length))); + } + + // Too small storage + Assert.False(complex.TryFormat(new char[expected.Length - 1], out charsWritten, format, numberFormatInfo)); + Assert.Equal(0, charsWritten); + } + } + } - expected = "<" + real.ToString(format, numberFormatInfo) + "; " + imaginary.ToString(format, numberFormatInfo) + ">"; - actual = complex.ToString(format, numberFormatInfo); - Assert.Equal(expected, actual); + // UTF8 + { + foreach (NumberFormatInfo numberFormatInfo in new[] { CultureInfo.CurrentCulture.NumberFormat, null }) + { + foreach (string format in s_supportedStandardNumericFormats.Append(null)) + { + byte[] expected = Encoding.UTF8.GetBytes($"<{real.ToString(format, numberFormatInfo)}; {imaginary.ToString(format, numberFormatInfo)}>"); + int bytesWritten; + + // Just right or larger than required storage + for (int additional = 0; additional < 2; additional++) + { + byte[] bytes = new byte[expected.Length + additional]; + Assert.True(complex.TryFormat(bytes, out bytesWritten, format, numberFormatInfo)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, bytes.AsSpan(0, expected.Length).ToArray()); + } + + // Too small storage + Assert.False(complex.TryFormat(new byte[expected.Length - 1], out bytesWritten, format, numberFormatInfo)); + Assert.Equal(0, bytesWritten); + } + } } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a9fd59e5af115..251edf1a3687b 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -2758,7 +2758,7 @@ public enum GCNotificationStatus Timeout = 3, NotApplicable = 4, } - public readonly partial struct Guid : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable + public readonly partial struct Guid : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.IUtf8SpanFormattable { private readonly int _dummyPrimitive; public static readonly System.Guid Empty; @@ -2788,11 +2788,13 @@ public enum GCNotificationStatus public static System.Guid ParseExact(System.ReadOnlySpan input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] System.ReadOnlySpan format) { throw null; } public static System.Guid ParseExact(string input, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] string format) { throw null; } bool System.ISpanFormattable.TryFormat(System.Span destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] System.ReadOnlySpan format, System.IFormatProvider? provider) { throw null; } + bool System.IUtf8SpanFormattable.TryFormat(System.Span utf8Destination, out int bytesWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] System.ReadOnlySpan format, System.IFormatProvider? provider) { throw null; } public byte[] ToByteArray() { throw null; } public override string ToString() { throw null; } public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] string? format) { throw null; } public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] string? format, System.IFormatProvider? provider) { throw null; } public bool TryFormat(System.Span destination, out int charsWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] System.ReadOnlySpan format = default(System.ReadOnlySpan)) { throw null; } + public bool TryFormat(System.Span utf8Destination, out int bytesWritten, [System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("GuidFormat")] System.ReadOnlySpan format = default(System.ReadOnlySpan)) { throw null; } public static bool TryParse(System.ReadOnlySpan input, out System.Guid result) { throw null; } public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.Guid result) { throw null; } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, out System.Guid result) { throw null; } diff --git a/src/libraries/System.Runtime/tests/System/GuidTests.cs b/src/libraries/System.Runtime/tests/System/GuidTests.cs index 12742ad5df1f1..f71efb5d0e8df 100644 --- a/src/libraries/System.Runtime/tests/System/GuidTests.cs +++ b/src/libraries/System.Runtime/tests/System/GuidTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Text; using Xunit; namespace System.Tests @@ -847,6 +848,12 @@ public static void TryFormat_InvalidFormat_ThrowsFormatException(string format) { Assert.Throws(() => s_testGuid.TryFormat(new Span(), out int charsWritten, format)); Assert.Throws(() => s_testGuid.TryFormat(new Span(), out int charsWritten, format.ToUpperInvariant())); + + Assert.Throws(() => ((ISpanFormattable)s_testGuid).TryFormat(new Span(), out int charsWritten, format, null)); + Assert.Throws(() => ((ISpanFormattable)s_testGuid).TryFormat(new Span(), out int charsWritten, format.ToUpperInvariant(), null)); + + Assert.Throws(() => s_testGuid.TryFormat(new Span(), out int bytesWritten, format)); + Assert.Throws(() => s_testGuid.TryFormat(new Span(), out int bytesWritten, format.ToUpperInvariant())); } [Theory] @@ -854,8 +861,18 @@ public static void TryFormat_InvalidFormat_ThrowsFormatException(string format) public static void TryFormat_LengthTooSmall_ReturnsFalse(Guid guid, string format, string expected) { _ = expected; + Assert.False(guid.TryFormat(new Span(new char[guid.ToString(format).Length - 1]), out int charsWritten, format)); Assert.Equal(0, charsWritten); + + Assert.False(((ISpanFormattable)guid).TryFormat(new Span(new char[guid.ToString(format).Length - 1]), out charsWritten, format, null)); + Assert.Equal(0, charsWritten); + + Assert.False(guid.TryFormat(new Span(new byte[guid.ToString(format).Length - 1]), out int bytesWritten, format)); + Assert.Equal(0, bytesWritten); + + Assert.False(((IUtf8SpanFormattable)guid).TryFormat(new Span(new byte[guid.ToString(format).Length - 1]), out bytesWritten, format, null)); + Assert.Equal(0, bytesWritten); } [Theory] @@ -863,17 +880,45 @@ public static void TryFormat_LengthTooSmall_ReturnsFalse(Guid guid, string forma public static void TryFormat_CharsWritten_EqualsZero_WhenSpanTooSmall(Guid guid, string format, string expected) { _ = expected; + Assert.False(guid.TryFormat(new Span(new char[guid.ToString(format).Length - 1]), out int charsWritten, format)); Assert.Equal(0, charsWritten); + + Assert.False(((ISpanFormattable)guid).TryFormat(new Span(new char[guid.ToString(format).Length - 1]), out charsWritten, format, null)); + Assert.Equal(0, charsWritten); + + Assert.False(guid.TryFormat(new Span(new byte[guid.ToString(format).Length - 1]), out int bytesWritten, format)); + Assert.Equal(0, bytesWritten); + + Assert.False(((IUtf8SpanFormattable)guid).TryFormat(new Span(new byte[guid.ToString(format).Length - 1]), out bytesWritten, format, null)); + Assert.Equal(0, bytesWritten); } [Theory] [MemberData(nameof(ToString_TestData))] public static void TryFormat_ValidLength_ReturnsTrue(Guid guid, string format, string expected) { - char[] chars = new char[guid.ToString(format).Length]; - Assert.True(guid.TryFormat(new Span(chars), out int charsWritten, format)); - Assert.Equal(chars, expected.ToCharArray()); + for (int additionalSpace = 0; additionalSpace < 2; additionalSpace++) + { + char[] chars = new char[expected.Length + additionalSpace]; + byte[] bytes = new byte[expected.Length + additionalSpace]; + + Assert.True(guid.TryFormat(new Span(chars), out int charsWritten, format)); + Assert.Equal(expected.Length, charsWritten); + Assert.Equal(expected, chars.AsSpan(0, charsWritten).ToString()); + + Assert.True(((ISpanFormattable)guid).TryFormat(new Span(chars), out charsWritten, format, null)); + Assert.Equal(expected.Length, charsWritten); + Assert.Equal(expected, chars.AsSpan(0, charsWritten).ToString()); + + Assert.True(guid.TryFormat(new Span(bytes), out int bytesWritten, format)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, Encoding.UTF8.GetString(bytes.AsSpan(0, bytesWritten))); + + Assert.True(((IUtf8SpanFormattable)guid).TryFormat(new Span(bytes), out bytesWritten, format, null)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, Encoding.UTF8.GetString(bytes.AsSpan(0, bytesWritten))); + } } } } diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs index ae73934b34358..64268c03726a8 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs @@ -572,7 +572,7 @@ internal static void LogNamespacePropagation(SignedXml signedXml, XmlNodeList? n /// The reference being processed /// Stream containing the output of the reference /// Stream containing the output of the reference - [return: NotNullIfNotNull("data")] + [return: NotNullIfNotNull(nameof(data))] internal static Stream? LogReferenceData(Reference reference, Stream? data) { if (VerboseLoggingEnabled) diff --git a/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs b/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs index 7add066f09380..3964d53ab4f48 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs @@ -10,7 +10,7 @@ namespace System.Text.Json.Reflection { internal static class RoslynExtensions { - [return: NotNullIfNotNull("typeSymbol")] + [return: NotNullIfNotNull(nameof(typeSymbol))] public static Type? AsType(this ITypeSymbol? typeSymbol, MetadataLoadContextInternal metadataLoadContext) { if (typeSymbol == null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonCollectionConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonCollectionConverter.cs index d7153aeb94427..e87b7f1c651c1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonCollectionConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonCollectionConverter.cs @@ -161,7 +161,7 @@ internal override bool OnTryRead( } // Dispatch to any polymorphic converters: should always be entered regardless of ObjectState progress - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Type) != 0 && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted && ResolvePolymorphicConverter(jsonTypeInfo, ref state) is JsonConverter polymorphicConverter) { @@ -181,7 +181,7 @@ internal override bool OnTryRead( CreateCollection(ref reader, ref state, options); - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Id)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Id) != 0) { Debug.Assert(state.ReferenceId != null); Debug.Assert(options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve); @@ -245,7 +245,7 @@ internal override bool OnTryRead( state.Current.ObjectState = StackFrameObjectState.EndToken; // Array payload is nested inside a $values metadata property. - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Values)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Values) != 0) { if (!reader.Read()) { @@ -258,7 +258,7 @@ internal override bool OnTryRead( if (state.Current.ObjectState < StackFrameObjectState.EndTokenValidation) { // Array payload is nested inside a $values metadata property. - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Values)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Values) != 0) { if (reader.TokenType != JsonTokenType.EndObject) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonDictionaryConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonDictionaryConverter.cs index e1dbc744f2180..d6375439d8df5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonDictionaryConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/JsonDictionaryConverter.cs @@ -185,7 +185,7 @@ internal sealed override bool OnTryRead( } // Dispatch to any polymorphic converters: should always be entered regardless of ObjectState progress - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Type) != 0 && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted && ResolvePolymorphicConverter(jsonTypeInfo, ref state) is JsonConverter polymorphicConverter) { @@ -206,7 +206,7 @@ internal sealed override bool OnTryRead( CreateCollection(ref reader, ref state); - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Id)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Id) != 0) { Debug.Assert(state.ReferenceId != null); Debug.Assert(options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs index 2568f58560b0c..1a3ddf380b49c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs @@ -102,7 +102,7 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, } // Dispatch to any polymorphic converters: should always be entered regardless of ObjectState progress - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Type) != 0 && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted && ResolvePolymorphicConverter(jsonTypeInfo, ref state) is JsonConverter polymorphicConverter) { @@ -133,7 +133,7 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, obj = jsonTypeInfo.CreateObject()!; - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Id)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Id) != 0) { Debug.Assert(state.ReferenceId != null); Debug.Assert(options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs index 064a9a6d5ba5a..0edf2d220d8fc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.cs @@ -132,7 +132,7 @@ internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToCo } // Dispatch to any polymorphic converters: should always be entered regardless of ObjectState progress - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Type) != 0 && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted && ResolvePolymorphicConverter(jsonTypeInfo, ref state) is JsonConverter polymorphicConverter) { @@ -170,7 +170,7 @@ internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToCo obj = (T)CreateObject(ref state.Current); - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Id)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Id) != 0) { Debug.Assert(state.ReferenceId != null); Debug.Assert(options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index 4a5edd193f6ca..08d3e37e975d5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Diagnostics; using System.Globalization; +using System.Runtime.CompilerServices; using System.Text.Encodings.Web; namespace System.Text.Json.Serialization.Converters @@ -93,14 +94,13 @@ public EnumConverter(EnumConverterOptions converterOptions, JsonNamingPolicy? na } } -#pragma warning disable 8500 // address of managed types - public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { JsonTokenType token = reader.TokenType; if (token == JsonTokenType.String) { - if (!_converterOptions.HasFlag(EnumConverterOptions.AllowStrings)) + if ((_converterOptions & EnumConverterOptions.AllowStrings) == 0) { ThrowHelper.ThrowJsonException(); return default; @@ -122,7 +122,7 @@ public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso #endif } - if (token != JsonTokenType.Number || !_converterOptions.HasFlag(EnumConverterOptions.AllowNumbers)) + if (token != JsonTokenType.Number || (_converterOptions & EnumConverterOptions.AllowNumbers) == 0) { ThrowHelper.ThrowJsonException(); return default; @@ -135,49 +135,51 @@ public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso case TypeCode.Int32: if (reader.TryGetInt32(out int int32)) { - return *(T*)&int32; + // Use Unsafe.As instead of raw pointers for .NET Standard support. + // https://github.com/dotnet/runtime/issues/84895 + return Unsafe.As(ref int32); } break; case TypeCode.UInt32: if (reader.TryGetUInt32(out uint uint32)) { - return *(T*)&uint32; + return Unsafe.As(ref uint32); } break; case TypeCode.UInt64: if (reader.TryGetUInt64(out ulong uint64)) { - return *(T*)&uint64; + return Unsafe.As(ref uint64); } break; case TypeCode.Int64: if (reader.TryGetInt64(out long int64)) { - return *(T*)&int64; + return Unsafe.As(ref int64); } break; case TypeCode.SByte: if (reader.TryGetSByte(out sbyte byte8)) { - return *(T*)&byte8; + return Unsafe.As(ref byte8); } break; case TypeCode.Byte: if (reader.TryGetByte(out byte ubyte8)) { - return *(T*)&ubyte8; + return Unsafe.As(ref ubyte8); } break; case TypeCode.Int16: if (reader.TryGetInt16(out short int16)) { - return *(T*)&int16; + return Unsafe.As(ref int16); } break; case TypeCode.UInt16: if (reader.TryGetUInt16(out ushort uint16)) { - return *(T*)&uint16; + return Unsafe.As(ref uint16); } break; } @@ -186,10 +188,10 @@ public override unsafe T Read(ref Utf8JsonReader reader, Type typeToConvert, Jso return default; } - public override unsafe void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // If strings are allowed, attempt to write it out as a string value - if (_converterOptions.HasFlag(EnumConverterOptions.AllowStrings)) + if ((_converterOptions & EnumConverterOptions.AllowStrings) != 0) { ulong key = ConvertToUInt64(value); @@ -226,7 +228,7 @@ public override unsafe void Write(Utf8JsonWriter writer, T value, JsonSerializer } } - if (!_converterOptions.HasFlag(EnumConverterOptions.AllowNumbers)) + if ((_converterOptions & EnumConverterOptions.AllowNumbers) == 0) { ThrowHelper.ThrowJsonException(); } @@ -234,35 +236,36 @@ public override unsafe void Write(Utf8JsonWriter writer, T value, JsonSerializer switch (s_enumTypeCode) { case TypeCode.Int32: - writer.WriteNumberValue(*(int*)&value); + // Use Unsafe.As instead of raw pointers for .NET Standard support. + // https://github.com/dotnet/runtime/issues/84895 + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.UInt32: - writer.WriteNumberValue(*(uint*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.UInt64: - writer.WriteNumberValue(*(ulong*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.Int64: - writer.WriteNumberValue(*(long*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.Int16: - writer.WriteNumberValue(*(short*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.UInt16: - writer.WriteNumberValue(*(ushort*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.Byte: - writer.WriteNumberValue(*(byte*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; case TypeCode.SByte: - writer.WriteNumberValue(*(sbyte*)&value); + writer.WriteNumberValue(Unsafe.As(ref value)); break; default: ThrowHelper.ThrowJsonException(); break; } } -#pragma warning restore 8500 internal override T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs index 74345fa12ccb7..6a3de620ae1d0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.MetadataHandling.cs @@ -15,7 +15,7 @@ public partial class JsonConverter { Debug.Assert(!IsValueType); Debug.Assert(CanHaveMetadata); - Debug.Assert(state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type)); + Debug.Assert((state.Current.MetadataPropertyNames & MetadataPropertyName.Type) != 0); Debug.Assert(state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted); Debug.Assert(jsonTypeInfo.PolymorphicTypeResolver?.UsesTypeDiscriminators == true); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleMetadata.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleMetadata.cs index 4326af6da116a..c9a9e6015fe19 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleMetadata.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleMetadata.cs @@ -50,7 +50,7 @@ internal static bool TryReadMetadata(JsonConverter converter, JsonTypeInfo jsonT // We just read a property. The only valid next tokens are EndObject and PropertyName. Debug.Assert(reader.TokenType == JsonTokenType.PropertyName); - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Ref)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Ref) != 0) { // No properties whatsoever should follow a $ref property. ThrowHelper.ThrowJsonException_MetadataReferenceObjectCannotContainOtherProperties(reader.GetSpan(), ref state); @@ -427,7 +427,7 @@ static string ReadAsStringMetadataValue(JsonNode? jsonNode) internal static void ValidateMetadataForObjectConverter(ref ReadStack state) { - if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Values)) + if ((state.Current.MetadataPropertyNames & MetadataPropertyName.Values) != 0) { // Object converters do not support $values metadata. ThrowHelper.ThrowJsonException_MetadataUnexpectedProperty(s_valuesPropertyName, ref state); diff --git a/src/mono/mono/arch/arm64/arm64-codegen.h b/src/mono/mono/arch/arm64/arm64-codegen.h index 2687b9fe0e903..8593d3f35cf0e 100644 --- a/src/mono/mono/arch/arm64/arm64-codegen.h +++ b/src/mono/mono/arch/arm64/arm64-codegen.h @@ -1208,6 +1208,8 @@ arm_encode_arith_imm (int imm, guint32 *shift) // type - data type of vector elements, one of {TYPE_I8, TYPE_I16, TYPE_I32, TYPE_I64} #define arm_neon_abs(p, width, type, rd, rn) arm_neon_2mvec_opcode ((p), (width), 0b0, (type), 0b01011, (rd), (rn)) #define arm_neon_neg(p, width, type, rd, rn) arm_neon_2mvec_opcode ((p), (width), 0b1, (type), 0b01011, (rd), (rn)) +#define arm_neon_xtn(p, type, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, (type), 0b10010, (rd), (rn)) +#define arm_neon_xtn2(p, type, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, (type), 0b10010, (rd), (rn)) // Parametrized variants of the float opcodes // width - determines if full register or its lower half is used one of {VREG_LOW, VREG_FULL} @@ -1215,6 +1217,11 @@ arm_encode_arith_imm (int imm, guint32 *shift) #define arm_neon_fabs(p, width, type, rd, rn) arm_neon_2mvec_opcode ((p), (width), 0b0, 0b10 | (type), 0b01111, (rd), (rn)) #define arm_neon_fneg(p, width, type, rd, rn) arm_neon_2mvec_opcode ((p), (width), 0b1, 0b10 | (type), 0b01111, (rd), (rn)) #define arm_neon_fsqrt(p, width, type, rd, rn) arm_neon_2mvec_opcode ((p), (width), 0b1, 0b10 | (type), 0b11111, (rd), (rn)) +#define arm_neon_fcvtn(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10110, (rd), (rn)) +#define arm_neon_fcvtn2(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b10110, (rd), (rn)) +#define arm_neon_fcvtl(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10111, (rd), (rn)) +#define arm_neon_fcvtl2(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b10111, (rd), (rn)) + // Parametrized variants of the bitwise opcodes // width - determines if full register or its lower half is used, one of {VREG_LOW, VREG_FULL} @@ -1304,13 +1311,6 @@ arm_encode_arith_imm (int imm, guint32 *shift) #define arm_neon_abs_4s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_4, 0b01011, (rd), (rn)) #define arm_neon_abs_2d(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_8, 0b01011, (rd), (rn)) -#define arm_neon_xtn_8b(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b10010, (rd), (rn)) -#define arm_neon_xtn2_8b(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b10010, (rd), (rn)) -#define arm_neon_xtn_4h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10010, (rd), (rn)) -#define arm_neon_xtn2_8h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b10010, (rd), (rn)) -#define arm_neon_xtn_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_4, 0b10010, (rd), (rn)) -#define arm_neon_xtn2_4s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_4, 0b10010, (rd), (rn)) - #define arm_neon_sqxtn_8b(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b10100, (rd), (rn)) #define arm_neon_sqxtn2_8b(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b10100, (rd), (rn)) #define arm_neon_sqxtn_4h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10100, (rd), (rn)) @@ -1318,16 +1318,6 @@ arm_encode_arith_imm (int imm, guint32 *shift) #define arm_neon_sqxtn_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_4, 0b10100, (rd), (rn)) #define arm_neon_sqxtn2_4s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_4, 0b10100, (rd), (rn)) -#define arm_neon_fcvtn_4h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b10110, (rd), (rn)) -#define arm_neon_fcvtn2_4h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b10110, (rd), (rn)) -#define arm_neon_fcvtn_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10110, (rd), (rn)) -#define arm_neon_fcvtn2_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b10110, (rd), (rn)) - -#define arm_neon_fcvtl_4h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b10111, (rd), (rn)) -#define arm_neon_fcvtl2_4h(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b10111, (rd), (rn)) -#define arm_neon_fcvtl_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10111, (rd), (rn)) -#define arm_neon_fcvtl2_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b10111, (rd), (rn)) - #define arm_neon_frintn_2s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b11000, (rd), (rn)) #define arm_neon_frintn_4s(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b11000, (rd), (rn)) #define arm_neon_frintn_2d(p, rd, rn) arm_neon_2mvec_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b11000, (rd), (rn)) @@ -2284,18 +2274,26 @@ arm_encode_arith_imm (int imm, guint32 *shift) #define arm_neon_shimm_opcode(p, q, u, immh, immb, opcode, rd, rn) arm_neon_opcode_2reg ((p), (q), 0b00001111000000000000010000000000 | (u) << 29 | (immh) << 19 | (immb) << 16 | (opcode) << 11, (rd), (rn)) #define arm_neon_shimm_shr_immh_immb(size, shift) (((shift) - (16 << (size))) & 0b01111111) #define arm_neon_shimm_shr_opcode(p, q, u, size, opcode, rd, rn, shift) do { \ - int32_t ___temp_emit0 = arm_neon_shimm_shr_immh_immb ((size), (shift)); \ - arm_neon_shimm_opcode ((p), (q), (u), (__temp_emit0 >> 3) & 0b1111, __temp_emit0 & 0b111, (opcode), (rd), (rn)) \ + int32_t __temp_emit0 = arm_neon_shimm_shr_immh_immb ((size), (shift)); \ + arm_neon_shimm_opcode ((p), (q), (u), (__temp_emit0 >> 3) & 0b1111, __temp_emit0 & 0b111, (opcode), (rd), (rn)); \ } while (0) #define arm_neon_shimm_shl_immh_immb(size, shift) (((shift) + (8 << (size))) & 0b01111111) #define arm_neon_shimm_shl_opcode(p, q, u, size, opcode, rd, rn, shift) do { \ - int32_t ___temp_emit0 = arm_neon_shimm_shl_immh_immb ((size), (shift)); \ - arm_neon_shimm_opcode ((p), (q), (u), (__temp_emit0 >> 3) & 0b1111, __temp_emit0 & 0b111, (opcode), (rd), (rn)) \ + int32_t __temp_emit0 = arm_neon_shimm_shl_immh_immb ((size), (shift)); \ + arm_neon_shimm_opcode ((p), (q), (u), (__temp_emit0 >> 3) & 0b1111, __temp_emit0 & 0b111, (opcode), (rd), (rn)); \ } while (0) #define arm_neon_sli(p, width, type, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), (width), 0b1, (type), 0b01010, (rd), (rn), (shift)) #define arm_neon_shrn(p, type, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b0, (type), 0b10000, (rd), (rn), (shift)) +#define arm_neon_sshll(p, type, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b0, (type), 0b10100, (rd), (rn), (shift)) +#define arm_neon_sshll2(p, type, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b0, (type), 0b10100, (rd), (rn), (shift)) +#define arm_neon_sxtl(p, type, rd, rn) arm_neon_sshll ((p), (type), (rd), (rn), 0) +#define arm_neon_sxtl2(p, type, rd, rn) arm_neon_sshll2 ((p), (type), (rd), (rn), 0) +#define arm_neon_ushll(p, type, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b1, (type), 0b10100, (rd), (rn), (shift)) +#define arm_neon_ushll2(p, type, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b1, (type), 0b10100, (rd), (rn), (shift)) +#define arm_neon_uxtl(p, type, rd, rn) arm_neon_ushll ((p), (type), (rd), (rn), 0) +#define arm_neon_uxtl2(p, type, rd, rn) arm_neon_ushll2 ((p), (type), (rd), (rn), 0) #define arm_neon_sshr_8b(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b00000, (rd), (rn), (shift)) #define arm_neon_sshr_16b(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b00000, (rd), (rn), (shift)) @@ -2373,13 +2371,6 @@ arm_encode_arith_imm (int imm, guint32 *shift) #define arm_neon_sqrshrn_2s(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b0, SIZE_4, 0b10011, (rd), (rn), (shift)) #define arm_neon_sqrshrn2_2s(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_FULL, 0b0, SIZE_4, 0b10011, (rd), (rn), (shift)) -#define arm_neon_shll_i_8b(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b0, SIZE_1, 0b10100, (rd), (rn), (shift)) -#define arm_neon_shll2_i_8b(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b0, SIZE_1, 0b10100, (rd), (rn), (shift)) -#define arm_neon_shll_i_4h(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b10100, (rd), (rn), (shift)) -#define arm_neon_shll2_i_4h(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b10100, (rd), (rn), (shift)) -#define arm_neon_shll_i_2s(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b0, SIZE_4, 0b10100, (rd), (rn), (shift)) -#define arm_neon_shll2_i_2s(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b0, SIZE_4, 0b10100, (rd), (rn), (shift)) - #define arm_neon_scvtf_i_4h(p, rd, rn, fbits) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b0, SIZE_2, 0b11100, (rd), (rn), (fbits)) #define arm_neon_scvtf_i_8h(p, rd, rn, fbits) arm_neon_shimm_shr_opcode ((p), VREG_FULL, 0b0, SIZE_2, 0b11100, (rd), (rn), (fbits)) #define arm_neon_scvtf_i_2s(p, rd, rn, fbits) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b0, SIZE_4, 0b11100, (rd), (rn), (fbits)) @@ -2476,13 +2467,6 @@ arm_encode_arith_imm (int imm, guint32 *shift) #define arm_neon_uqrshrn_2s(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b1, SIZE_4, 0b10011, (rd), (rn), (shift)) #define arm_neon_uqrshrn2_2s(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_FULL, 0b1, SIZE_4, 0b10011, (rd), (rn), (shift)) -#define arm_neon_ushll_8b(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b1, SIZE_1, 0b10100, (rd), (rn), (shift)) -#define arm_neon_ushll2_8b(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b1, SIZE_1, 0b10100, (rd), (rn), (shift)) -#define arm_neon_ushll_4h(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b1, SIZE_2, 0b10100, (rd), (rn), (shift)) -#define arm_neon_ushll2_4h(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b1, SIZE_2, 0b10100, (rd), (rn), (shift)) -#define arm_neon_ushll_2s(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_LOW, 0b1, SIZE_4, 0b10100, (rd), (rn), (shift)) -#define arm_neon_ushll2_2s(p, rd, rn, shift) arm_neon_shimm_shl_opcode ((p), VREG_FULL, 0b1, SIZE_4, 0b10100, (rd), (rn), (shift)) - #define arm_neon_ucvtf_i_4h(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b1, SIZE_2, 0b11100, (rd), (rn), (shift)) #define arm_neon_ucvtf_i_8h(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_FULL, 0b1, SIZE_2, 0b11100, (rd), (rn), (shift)) #define arm_neon_ucvtf_i_2s(p, rd, rn, shift) arm_neon_shimm_shr_opcode ((p), VREG_LOW, 0b1, SIZE_4, 0b11100, (rd), (rn), (shift)) diff --git a/src/mono/mono/mini/cpu-arm64.mdesc b/src/mono/mono/mini/cpu-arm64.mdesc index 8640097829724..a2af821a08171 100644 --- a/src/mono/mono/mini/cpu-arm64.mdesc +++ b/src/mono/mono/mini/cpu-arm64.mdesc @@ -533,6 +533,11 @@ create_scalar_unsafe_int: dest:x src1:i len:4 create_scalar_unsafe_float: dest:x src1:f len:4 arm64_bic: dest:x src1:x src2:x len:4 bitwise_select: dest:x src1:x src2:x src3:x len:12 +arm64_xtn: dest:x src1:x len:4 +arm64_xtn2: dest:x src1:x src2:x len:4 clob:1 +arm64_fcvtn: dest:x src1:x len:4 +arm64_fcvtn2: dest:x src1:x src2:x len:4 clob:1 +xunop: dest:x src1:x len:4 arm64_ushl: dest:x src1:x src2:x len:4 arm64_ext_imm: dest:x src1:x src2:x len:4 diff --git a/src/mono/mono/mini/llvm-intrinsics.h b/src/mono/mono/mini/llvm-intrinsics.h index dad8452029721..df1ec108d59f0 100644 --- a/src/mono/mono/mini/llvm-intrinsics.h +++ b/src/mono/mono/mini/llvm-intrinsics.h @@ -253,6 +253,10 @@ INTRINS_OVR(SSE_SSUB_SATI16, ssub_sat, Generic, v128_i2_t) INTRINS_OVR(SSE_USUB_SATI16, usub_sat, Generic, v128_i2_t) #endif #if defined(TARGET_WASM) +INTRINS_OVR(WASM_EXTADD_PAIRWISE_SIGNED_V16, wasm_extadd_pairwise_signed, Wasm, sse_i2_t) +INTRINS_OVR(WASM_EXTADD_PAIRWISE_SIGNED_V8, wasm_extadd_pairwise_signed, Wasm, sse_i4_t) +INTRINS_OVR(WASM_EXTADD_PAIRWISE_UNSIGNED_V16, wasm_extadd_pairwise_unsigned, Wasm, sse_i2_t) +INTRINS_OVR(WASM_EXTADD_PAIRWISE_UNSIGNED_V8, wasm_extadd_pairwise_unsigned, Wasm, sse_i4_t) INTRINS_OVR(WASM_ALLTRUE_V16, wasm_alltrue, Wasm, sse_i1_t) INTRINS_OVR(WASM_ALLTRUE_V8, wasm_alltrue, Wasm, sse_i2_t) INTRINS_OVR(WASM_ALLTRUE_V4, wasm_alltrue, Wasm, sse_i4_t) diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index b4dfb333ddfed..062eeb7dd76cc 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -35,6 +35,8 @@ #define EXPAND(x) x #define PARENTHESIZE(...) (__VA_ARGS__) #define EXPAND_FUN(m, ...) EXPAND(m PARENTHESIZE(__VA_ARGS__)) +#define OPFMT_DS dreg, sreg1 +#define OPFMT_TDS _t, dreg, sreg1 #define OPFMT_WDSS _w, dreg, sreg1, sreg2 #define OPFMT_WTDS _w, _t, dreg, sreg1 #define OPFMT_WTDSS _w, _t, dreg, sreg1, sreg2 @@ -3774,7 +3776,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_ldrfpq (code, dreg, sreg1, ins->inst_offset); break; case OP_XMOVE: - arm_neon_mov (code, dreg, sreg1); + if(dreg != sreg1) + arm_neon_mov (code, dreg, sreg1); break; case OP_XCONST: { if (cfg->compile_aot && cfg->code_exec_only) { @@ -3848,6 +3851,29 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) arm_neon_ins_e(code, t, dreg, sreg1, ins->inst_c0, 0); break; } + case OP_ARM64_XTN: + // The '-1' here and in XTN2 is to account for the arm_neon_xtn macro defining + // its type as the type of the destination. Here inst_c1 is the type of the + // source data. Since XTN(2) steps down the type by one; e.g. I4 to I2, we + // subtract unity. + arm_neon_xtn (code, get_type_size_macro (ins->inst_c1) - 1, dreg, sreg1); + break; + + case OP_ARM64_XTN2: + g_assert (dreg == sreg1); + arm_neon_xtn2 (code, get_type_size_macro (ins->inst_c1) - 1, dreg, sreg2); + break; + + case OP_ARM64_FCVTN: + // Only double->float is supported here, while arm64 can also do float->half. + arm_neon_fcvtn (code, dreg, sreg1); + break; + + case OP_ARM64_FCVTN2: + g_assert (dreg == sreg1); + arm_neon_fcvtn2 (code, dreg, sreg2); + break; + case OP_ARM64_XADDV: { switch (ins->inst_c0) { case INTRINS_AARCH64_ADV_SIMD_FADDV: diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index 56935279a18bd..c75c124b7d400 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -754,7 +754,7 @@ unwinder_init (Unwinder *unwinder) memset (unwinder, 0, sizeof (Unwinder)); } -#if defined(__GNUC__) && defined(TARGET_ARM64) +#if defined(__GNUC__) && defined(TARGET_ARM64) && !defined(__clang__) /* gcc 4.9.2 seems to miscompile this on arm64 */ static __attribute__((optimize("O0"))) gboolean #else diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index e9adc6f69bbbf..d4e3e3754966b 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -5178,15 +5178,28 @@ bitcast_to_integral (EmitContext *ctx, LLVMValueRef vec) } static LLVMValueRef -extract_high_elements (EmitContext *ctx, LLVMValueRef src_vec) +extract_half_elements (EmitContext *ctx, LLVMValueRef src_vec, gboolean high) { LLVMTypeRef src_t = LLVMTypeOf (src_vec); unsigned int src_elems = LLVMGetVectorSize (src_t); unsigned int dst_elems = src_elems / 2; + unsigned int offset = high ? dst_elems : 0; int mask [MAX_VECTOR_ELEMS] = { 0 }; for (guint i = 0; i < dst_elems; ++i) - mask [i] = dst_elems + i; - return LLVMBuildShuffleVector (ctx->builder, src_vec, LLVMGetUndef (src_t), create_const_vector_i32 (mask, dst_elems), "extract_high"); + mask [i] = offset + i; + return LLVMBuildShuffleVector (ctx->builder, src_vec, LLVMGetUndef (src_t), create_const_vector_i32 (mask, dst_elems), high ? "extract_high" : "extract_low"); +} + +static LLVMValueRef +extract_high_elements (EmitContext *ctx, LLVMValueRef src_vec) +{ + return extract_half_elements (ctx, src_vec, TRUE); +} + +static LLVMValueRef +extract_low_elements (EmitContext *ctx, LLVMValueRef src_vec) +{ + return extract_half_elements (ctx, src_vec, FALSE); } static LLVMValueRef @@ -9974,6 +9987,25 @@ MONO_RESTORE_WARNING values [ins->dreg] = LLVMBuildBitCast (builder, shuffle, LLVMVectorType (itype, nelems * 2), ""); break; } + case OP_WASM_EXTMUL_LOWER_U: + case OP_WASM_EXTMUL_UPPER_U: + case OP_WASM_EXTMUL_LOWER: + case OP_WASM_EXTMUL_UPPER: { + LLVMTypeRef src_t = LLVMTypeOf (lhs); + int nelems = LLVMGetVectorSize (src_t) / 2; + unsigned int width = mono_llvm_get_prim_size_bits (LLVMGetElementType(src_t)); + LLVMTypeRef int_t = LLVMIntType (width * 2); + LLVMTypeRef ret_t = LLVMVectorType (int_t, nelems); + int lower = ins->opcode == OP_WASM_EXTMUL_LOWER || ins->opcode == OP_WASM_EXTMUL_LOWER_U; + gboolean is_unsigned = ins->opcode == OP_WASM_EXTMUL_LOWER_U || ins->opcode == OP_WASM_EXTMUL_UPPER_U; + LLVMValueRef part1 = lower ? extract_low_elements (ctx, lhs) : extract_high_elements(ctx, lhs); + LLVMValueRef part2 = lower ? extract_low_elements (ctx, rhs) : extract_high_elements(ctx, rhs); + LLVMValueRef ext1 = is_unsigned ? LLVMBuildZExt (builder, part1, ret_t, "") : LLVMBuildSExt (builder, part1, ret_t, ""); + LLVMValueRef ext2 = is_unsigned ? LLVMBuildZExt (builder, part2, ret_t, "") : LLVMBuildSExt (builder, part2, ret_t, ""); + values [ins->dreg] = LLVMBuildMul (builder, ext1, ext2, ""); + + break; + } #endif #if defined(TARGET_ARM64) || defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_WASM) case OP_XEQUAL: { diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index 9b70bdc1c7cd1..29c6809e24335 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -855,6 +855,10 @@ MINI_OP3(OP_WASM_SIMD_SHUFFLE, "wasm_shuffle", XREG, XREG, XREG, XREG) MINI_OP(OP_WASM_SIMD_SUM, "wasm_sum", XREG, XREG, NONE) MINI_OP(OP_WASM_SIMD_SWIZZLE, "wasm_swizzle", XREG, XREG, XREG) MINI_OP(OP_WASM_EXTRACT_NARROW, "wasm_extract_narrow", XREG, XREG, XREG) +MINI_OP(OP_WASM_EXTMUL_LOWER, "wasm_extmul_lower", XREG, XREG, XREG) +MINI_OP(OP_WASM_EXTMUL_UPPER, "wasm_extmul_upper", XREG, XREG, XREG) +MINI_OP(OP_WASM_EXTMUL_LOWER_U, "wasm_extmul_lower_u", XREG, XREG, XREG) +MINI_OP(OP_WASM_EXTMUL_UPPER_U, "wasm_extmul_upper_u", XREG, XREG, XREG) #endif #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_WASM) @@ -1498,6 +1502,7 @@ MINI_OP(OP_XEXTRACT, "xextract", IREG, XREG, NONE) /* * Generic SIMD operations, the rest of the JIT doesn't care about the exact operation. */ +MINI_OP(OP_XUNOP, "xunop", XREG, XREG, NONE) MINI_OP(OP_XBINOP, "xbinop", XREG, XREG, XREG) MINI_OP(OP_XBINOP_FORCEINT, "xbinop_forceint", XREG, XREG, XREG) MINI_OP(OP_XBINOP_SCALAR, "xbinop_scalar", XREG, XREG, XREG) diff --git a/src/mono/mono/mini/simd-arm64.h b/src/mono/mono/mini/simd-arm64.h index 1f10471b708e6..b9c0b7507236f 100644 --- a/src/mono/mono/mini/simd-arm64.h +++ b/src/mono/mono/mini/simd-arm64.h @@ -49,6 +49,12 @@ SIMD_OP (128, OP_XCOMPARE_FP, CMP_GE, WTDSS, _UNDEF, SIMD_OP (128, OP_XCOMPARE_FP, CMP_LT, WTDSS_REV, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fcmgt, arm_neon_fcmgt) SIMD_OP (128, OP_XCOMPARE_FP, CMP_LE, WTDSS_REV, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fcmge, arm_neon_fcmge) +SIMD_OP (128, OP_XUNOP, OP_SIMD_FCVTL, DS, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fcvtl, _UNDEF) +SIMD_OP (128, OP_XUNOP, OP_SIMD_FCVTL2, DS, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fcvtl2, _UNDEF) +SIMD_OP (128, OP_XUNOP, OP_ARM64_SXTL, TDS, arm_neon_sxtl, arm_neon_sxtl, arm_neon_sxtl, _UNDEF, _UNDEF, _UNDEF) +SIMD_OP (128, OP_XUNOP, OP_ARM64_SXTL2, TDS, arm_neon_sxtl2, arm_neon_sxtl2, arm_neon_sxtl2, _UNDEF, _UNDEF, _UNDEF) +SIMD_OP (128, OP_XUNOP, OP_ARM64_UXTL, TDS, arm_neon_uxtl, arm_neon_uxtl, arm_neon_uxtl, _UNDEF, _UNDEF, _UNDEF) +SIMD_OP (128, OP_XUNOP, OP_ARM64_UXTL2, TDS, arm_neon_uxtl2, arm_neon_uxtl2, arm_neon_uxtl2, _UNDEF, _UNDEF, _UNDEF) SIMD_OP (128, OP_XBINOP, OP_IADD, WTDSS, arm_neon_add, arm_neon_add, arm_neon_add, arm_neon_add, _UNDEF, _UNDEF) SIMD_OP (128, OP_XBINOP, OP_FADD, WTDSS, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fadd, arm_neon_fadd) SIMD_OP (128, OP_XBINOP, OP_ISUB, WTDSS, arm_neon_sub, arm_neon_sub, arm_neon_sub, arm_neon_sub, _UNDEF, _UNDEF) @@ -59,7 +65,7 @@ SIMD_OP (128, OP_XBINOP, OP_FMAX, WTDSS, _UNDEF, SIMD_OP (128, OP_XBINOP, OP_IMIN, WTDSS, arm_neon_smin, arm_neon_smin, arm_neon_smin, _SKIP, _UNDEF, _UNDEF) SIMD_OP (128, OP_XBINOP, OP_IMIN_UN, WTDSS, arm_neon_umin, arm_neon_umin, arm_neon_umin, _SKIP, _UNDEF, _UNDEF) SIMD_OP (128, OP_XBINOP, OP_FMIN, WTDSS, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fmin, arm_neon_fmin) -SIMD_OP (128, OP_XBINOP, OP_IMUL, WTDSS, arm_neon_mul, arm_neon_mul, arm_neon_mul, arm_neon_mul, _UNDEF, _UNDEF) +SIMD_OP (128, OP_XBINOP, OP_IMUL, WTDSS, arm_neon_mul, arm_neon_mul, arm_neon_mul, _UNDEF, _UNDEF, _UNDEF) SIMD_OP (128, OP_XBINOP, OP_FMUL, WTDSS, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fmul, arm_neon_fmul) SIMD_OP (128, OP_XBINOP, OP_FDIV, WTDSS, _UNDEF, _UNDEF, _UNDEF, _UNDEF, arm_neon_fdiv, arm_neon_fdiv) SIMD_OP (128, OP_XBINOP_FORCEINT, XBINOP_FORCEINT_AND, WDSS, arm_neon_and, arm_neon_and, arm_neon_and, arm_neon_and, arm_neon_and, arm_neon_and) diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index f88c861f90882..a01b2a7a2c095 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1324,16 +1324,12 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_ConvertToUInt32: case SN_ConvertToUInt64: case SN_Create: - case SN_Dot: case SN_GetElement: case SN_GetLower: case SN_GetUpper: - case SN_Narrow: case SN_Shuffle: case SN_ToVector128: case SN_ToVector128Unsafe: - case SN_WidenLower: - case SN_WidenUpper: case SN_WithElement: return NULL; default: @@ -1342,7 +1338,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi } #endif - MonoClass *klass = cmethod->klass; + MonoClass* klass = fsig->param_count > 0 ? args[0]->klass : cmethod->klass; MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; if (cfg->verbose_level > 1) { @@ -1557,10 +1553,17 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_Dot: { if (!is_element_type_primitive (fsig->params [0])) return NULL; +#if defined(TARGET_WASM) + if (!COMPILE_LLVM (cfg) && (arg0_type == MONO_TYPE_I8 || arg0_type == MONO_TYPE_U8)) + return NULL; +#elif defined(TARGET_ARM64) + if (!COMPILE_LLVM (cfg) && (arg0_type == MONO_TYPE_I8 || arg0_type == MONO_TYPE_U8 || arg0_type == MONO_TYPE_I || arg0_type == MONO_TYPE_U)) + return NULL; +#endif + #if defined(TARGET_ARM64) || defined(TARGET_WASM) int instc0 = type_enum_is_float (arg0_type) ? OP_FMUL : OP_IMUL; MonoInst *pairwise_multiply = emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, instc0, arg0_type, fsig, args); - return emit_sum_vector (cfg, fsig->params [0], arg0_type, pairwise_multiply); #elif defined(TARGET_AMD64) int instc =-1; @@ -1782,8 +1785,11 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi if (size == 16) { switch (arg0_type) { case MONO_TYPE_R8: { - MonoInst *ins = emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN, args [0]->dreg, -1); - return emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN2, ins->dreg, args [1]->dreg); + MonoInst* ins = emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN, args [0]->dreg, -1); + ins->inst_c1 = arg0_type; + MonoInst* ret = emit_simd_ins (cfg, arg_class, OP_ARM64_FCVTN2, ins->dreg, args [1]->dreg); + ret->inst_c1 = arg0_type; + return ret; } case MONO_TYPE_I2: case MONO_TYPE_I4: @@ -1791,13 +1797,19 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case MONO_TYPE_U2: case MONO_TYPE_U4: case MONO_TYPE_U8: { - MonoInst *ins = emit_simd_ins (cfg, arg_class, OP_ARM64_XTN, args [0]->dreg, -1); - return emit_simd_ins (cfg, arg_class, OP_ARM64_XTN2, ins->dreg, args [1]->dreg); + MonoInst* ins = emit_simd_ins (cfg, arg_class, OP_ARM64_XTN, args [0]->dreg, -1); + ins->inst_c1 = arg0_type; + MonoInst* ret = emit_simd_ins (cfg, arg_class, OP_ARM64_XTN2, ins->dreg, args [1]->dreg); + ret->inst_c1 = arg0_type; + return ret; } default: return NULL; } } else { + if (!COMPILE_LLVM (cfg)) + return NULL; + switch (arg0_type) { case MONO_TYPE_R8: { //Widen arg0 @@ -1971,20 +1983,36 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi } case SN_WidenLower: case SN_WidenUpper: { -#if defined(TARGET_ARM64) || defined(TARGET_WASM) if (!is_element_type_primitive (fsig->params [0])) return NULL; - - int op = id == SN_WidenLower ? OP_XLOWER : OP_XUPPER; - MonoInst *lower_or_upper_half = emit_simd_ins_for_sig (cfg, klass, op, 0, arg0_type, fsig, args); - if (type_enum_is_float (arg0_type)) { - return emit_simd_ins (cfg, klass, OP_SIMD_FCVTL, lower_or_upper_half->dreg, -1); - } else { - int zero = alloc_ireg (cfg); - MONO_EMIT_NEW_ICONST (cfg, zero, 0); - op = type_enum_is_unsigned (arg0_type) ? OP_SIMD_USHLL : OP_SIMD_SSHLL; - return emit_simd_ins (cfg, klass, op, lower_or_upper_half->dreg, zero); +#if defined(TARGET_ARM64) + if (!COMPILE_LLVM (cfg)) { + int subop = 0; + gboolean is_upper = (id == SN_WidenUpper); + if (type_enum_is_float (arg0_type)) + subop = is_upper ? OP_SIMD_FCVTL2 : OP_SIMD_FCVTL; + else if (type_enum_is_unsigned (arg0_type)) + subop = is_upper ? OP_ARM64_UXTL2 : OP_ARM64_UXTL; + else + subop = is_upper ? OP_ARM64_SXTL2 : OP_ARM64_SXTL; + + MonoInst* ins = emit_simd_ins (cfg, klass, OP_XUNOP, args [0]->dreg, -1); + ins->inst_c0 = subop; + ins->inst_c1 = arg0_type; + return ins; } +#endif +#if defined(TARGET_ARM64) || defined(TARGET_WASM) + int op = id == SN_WidenLower ? OP_XLOWER : OP_XUPPER; + MonoInst *lower_or_upper_half = emit_simd_ins_for_sig (cfg, klass, op, 0, arg0_type, fsig, args); + if (type_enum_is_float (arg0_type)) { + return emit_simd_ins (cfg, klass, OP_SIMD_FCVTL, lower_or_upper_half->dreg, -1); + } else { + int zero = alloc_ireg (cfg); + MONO_EMIT_NEW_ICONST (cfg, zero, 0); + op = type_enum_is_unsigned (arg0_type) ? OP_SIMD_USHLL : OP_SIMD_SSHLL; + return emit_simd_ins (cfg, klass, op, lower_or_upper_half->dreg, zero); + } #else return NULL; #endif @@ -4864,6 +4892,7 @@ static SimdIntrinsic wasmbase_methods [] = { static SimdIntrinsic packedsimd_methods [] = { {SN_Add}, + {SN_AddPairwiseWidening}, {SN_And, OP_XBINOP_FORCEINT, XBINOP_FORCEINT_AND}, {SN_Bitmask, OP_WASM_SIMD_BITMASK}, {SN_CompareEqual}, @@ -4873,6 +4902,8 @@ static SimdIntrinsic packedsimd_methods [] = { {SN_Dot, OP_XOP_X_X_X, INTRINS_WASM_DOT}, {SN_ExtractLane}, {SN_Multiply}, + {SN_MultiplyWideningLower, OP_WASM_EXTMUL_LOWER, 0, OP_WASM_EXTMUL_LOWER_U}, + {SN_MultiplyWideningUpper, OP_WASM_EXTMUL_UPPER, 0, OP_WASM_EXTMUL_UPPER_U}, {SN_Negate}, {SN_ReplaceLane}, {SN_ShiftLeft, OP_SIMD_SHL}, @@ -4963,6 +4994,30 @@ emit_wasm_supported_intrinsics ( return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id); case SN_Negate: return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id); + case SN_AddPairwiseWidening: { + op = OP_XOP_X_X; + + switch (arg0_type) { + case MONO_TYPE_I1: + c0 = INTRINS_WASM_EXTADD_PAIRWISE_SIGNED_V16; + break; + case MONO_TYPE_I2: + c0 = INTRINS_WASM_EXTADD_PAIRWISE_SIGNED_V8; + break; + case MONO_TYPE_U1: + c0 = INTRINS_WASM_EXTADD_PAIRWISE_UNSIGNED_V16; + break; + case MONO_TYPE_U2: + c0 = INTRINS_WASM_EXTADD_PAIRWISE_UNSIGNED_V8; + break; + } + + // continue with default emit + if (c0 != 0) + break; + + return NULL; + } case SN_CompareEqual: return emit_simd_ins_for_sig (cfg, klass, type_enum_is_float (arg0_type) ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_EQ, arg0_type, fsig, args); case SN_CompareNotEqual: diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index 25d9d66a17e0f..0e38696380cc5 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -635,10 +635,10 @@ METHOD(MultiplyRoundedDoublingScalarBySelectedScalarAndSubtractSaturateHigh) METHOD(DotProductBySelectedQuadruplet) // Wasm METHOD(Bitmask) -METHOD(Splat) -METHOD(ExtractLane) -METHOD(ReplaceLane) -METHOD(Swizzle) METHOD(ConvertNarrowingSignedSaturate) METHOD(ConvertNarrowingUnsignedSaturate) +METHOD(ExtractLane) +METHOD(ReplaceLane) METHOD(ShiftLeft) +METHOD(Splat) +METHOD(Swizzle) diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index 74cc69825f29f..96e5446388a43 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -403,7 +403,7 @@ mono_threads_wasm_browser_thread_tid (void) #ifdef DISABLE_THREADS return (MonoNativeThreadId)1; #else - return (MonoNativeThreadId)emscripten_main_browser_thread_id (); + return (MonoNativeThreadId)emscripten_main_runtime_thread_id (); #endif } diff --git a/src/mono/mono/utils/valgrind.h b/src/mono/mono/utils/valgrind.h index 03058c1fc840f..3d802e5d4a7e5 100644 --- a/src/mono/mono/utils/valgrind.h +++ b/src/mono/mono/utils/valgrind.h @@ -769,12 +769,14 @@ typedef __extension__ \ ({volatile unsigned long long int _zzq_args[6]; \ volatile unsigned long long int _zzq_result; \ + volatile unsigned long long int _zzq_default_ll; \ _zzq_args[0] = (unsigned long long int)(_zzq_request); \ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ + _zzq_default_ll = (unsigned long long int)(_zzq_default); \ __asm__ volatile("mov x3, %1\n\t" /*default*/ \ "mov x4, %2\n\t" /*ptr*/ \ __SPECIAL_INSTRUCTION_PREAMBLE \ @@ -782,7 +784,7 @@ typedef "orr x10, x10, x10\n\t" \ "mov %0, x3" /*result*/ \ : "=r" (_zzq_result) \ - : "r" (_zzq_default), "r" (&_zzq_args[0]) \ + : "r" (_zzq_default_ll), "r" (&_zzq_args[0]) \ : "cc","memory", "x3", "x4"); \ _zzq_result; \ }) diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index 3fe69f51c2e0e..c610f34c1b689 100644 --- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -31,6 +31,10 @@ Copyright (c) .NET Foundation. All rights reserved. <_WebAssemblySdkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">net8.0 <_WebAssemblySdkTasksTFM Condition=" '$(MSBuildRuntimeType)' != 'Core'">net472 <_WebAssemblySdkTasksAssembly>$(WebAssemblySdkDirectoryRoot)tools\$(_WebAssemblySdkTasksTFM)\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.dll + + + $(CompressionIncludePatterns);_framework\** + true @@ -77,28 +81,48 @@ Copyright (c) .NET Foundation. All rights reserved. + $(ResolveStaticWebAssetsInputsDependsOn); _AddWasmStaticWebAssets; - _GenerateBuildWasmBootJson; $(StaticWebAssetsPrepareForRunDependsOn) - $(ResolvePublishStaticWebAssetsDependsOn); ProcessPublishFilesForWasm; ComputeWasmExtensions; _AddPublishWasmBootJsonToStaticWebAssets; - $(GenerateStaticWebAssetsPublishManifestDependsOn); GeneratePublishWasmBootJson; + + + $(ResolveCompressedFilesDependsOn); + ResolveWasmOutputs; + _AddWasmStaticWebAssets; + + + $(ResolveCompressedFilesForPublishDependsOn); + ProcessPublishFilesForWasm; + ComputeWasmExtensions; + _AddPublishWasmBootJsonToStaticWebAssets; + + + $(CompressFilesDependsOn) + _GenerateBuildWasmBootJson; + + + $(CompressFilesForPublishDependsOn); + GeneratePublishWasmBootJson; + + + $(AddWasmStaticWebAssetsDependsOn); ResolveWasmOutputs; @@ -381,6 +405,7 @@ Copyright (c) .NET Foundation. All rights reserved. + diff --git a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js index bac3f856160c5..3b32add2f39e5 100644 --- a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js +++ b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js @@ -23,6 +23,16 @@ if (is_node && process.versions.node.split(".")[0] < 14) { throw new Error(`NodeJS at '${process.execPath}' has too low version '${process.versions.node}'`); } +if (is_node) { + // the emscripten 3.1.34 stopped handling these when MODULARIZE is enabled + process.on('uncaughtException', function(ex) { + // ignore UnhandledPromiseRejection exceptions with exit status + if (ex !== 'unwind' && (ex.name !== "UnhandledPromiseRejection" || !ex.message.includes('"#"'))) { + throw ex; + } + }); +} + if (typeof globalThis.crypto === 'undefined') { // **NOTE** this is a simple insecure polyfill for testing purposes only // /dev/random doesn't work on js shells, so define our own diff --git a/src/mono/wasm/emscripten-version.txt b/src/mono/wasm/emscripten-version.txt index f4e47c2e5e20a..45dd392530866 100644 --- a/src/mono/wasm/emscripten-version.txt +++ b/src/mono/wasm/emscripten-version.txt @@ -1 +1 @@ -3.1.30 \ No newline at end of file +3.1.34 \ No newline at end of file diff --git a/src/mono/wasm/runtime/pthreads/shared/index.ts b/src/mono/wasm/runtime/pthreads/shared/index.ts index c71a27f5f3967..774dbc76ec8af 100644 --- a/src/mono/wasm/runtime/pthreads/shared/index.ts +++ b/src/mono/wasm/runtime/pthreads/shared/index.ts @@ -20,7 +20,7 @@ export const MainThread: PThreadInfo = { let browser_thread_id_lazy: pthread_ptr | undefined; export function getBrowserThreadID(): pthread_ptr { if (browser_thread_id_lazy === undefined) { - browser_thread_id_lazy = (Module)["_emscripten_main_browser_thread_id"]() as pthread_ptr; + browser_thread_id_lazy = (Module)["_emscripten_main_runtime_thread_id"]() as pthread_ptr; } return browser_thread_id_lazy; } diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 60c5473492962..3d835c0bb6140 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -23,6 +23,16 @@ if (is_node && process.versions.node.split(".")[0] < 14) { throw new Error(`NodeJS at '${process.execPath}' has too low version '${process.versions.node}'`); } +if (is_node) { + // the emscripten 3.1.34 stopped handling these when MODULARIZE is enabled + process.on('uncaughtException', function(ex) { + // ignore UnhandledPromiseRejection exceptions with exit status + if (ex !== 'unwind' && (ex.name !== "UnhandledPromiseRejection" || !ex.message.includes('"#"'))) { + throw ex; + } + }); +} + if (!is_node && !is_browser && typeof globalThis.crypto === 'undefined') { // **NOTE** this is a simple insecure polyfill for testing purposes only // /dev/random doesn't work on js shells, so define our own diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 9755e405afed4..8342ee12786eb 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -293,7 +293,6 @@ <_EmccLinkFlags Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" /> <_EmccLinkFlags Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" /> <_EmccLinkFlags Include="--source-map-base http://example.com" /> - <_EmccLinkFlags Include="-s STRICT_JS=1" /> <_EmccLinkFlags Include="-s WASM_BIGINT=1" /> <_EmccLinkFlags Include="-s EXPORT_NAME="'createDotnetRuntime'"" /> <_EmccLinkFlags Include="-s MODULARIZE=1"/> diff --git a/src/native/libs/System.Globalization.Native/entrypoints.c b/src/native/libs/System.Globalization.Native/entrypoints.c index 10254d6256db4..c3c65b2196cde 100644 --- a/src/native/libs/System.Globalization.Native/entrypoints.c +++ b/src/native/libs/System.Globalization.Native/entrypoints.c @@ -61,6 +61,10 @@ static const Entry s_globalizationNative[] = #ifdef __APPLE__ DllImportEntry(GlobalizationNative_GetLocaleNameNative) DllImportEntry(GlobalizationNative_GetLocaleInfoStringNative) + DllImportEntry(GlobalizationNative_GetLocaleInfoIntNative) + DllImportEntry(GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative) + DllImportEntry(GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative) + DllImportEntry(GlobalizationNative_GetLocaleTimeFormatNative) #endif }; diff --git a/src/native/libs/System.Globalization.Native/pal_locale.c b/src/native/libs/System.Globalization.Native/pal_locale.c index eada9f12ddd39..ccae3e0c6d989 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.c +++ b/src/native/libs/System.Globalization.Native/pal_locale.c @@ -277,3 +277,25 @@ int32_t GlobalizationNative_IsPredefinedLocale(const UChar* localeName) return err == U_ZERO_ERROR; } + +/* +PAL Function: +GetLocaleTimeFormat + +Obtains time format information (in ICU format, it needs to be converted to .NET's format). +Returns 1 for success, 0 otherwise +*/ +int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, + int shortFormat, + UChar* value, + int32_t valueLength) +{ + UErrorCode err = U_ZERO_ERROR; + char locale[ULOC_FULLNAME_CAPACITY]; + GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); + UDateFormatStyle style = (shortFormat != 0) ? UDAT_SHORT : UDAT_MEDIUM; + UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, NULL, 0, NULL, 0, &err); + udat_toPattern(pFormat, false, value, valueLength, &err); + udat_close(pFormat); + return UErrorCodeToBool(err); +} diff --git a/src/native/libs/System.Globalization.Native/pal_locale.h b/src/native/libs/System.Globalization.Native/pal_locale.h index 7ee6d1e7ee56e..7fe89f667f213 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.h +++ b/src/native/libs/System.Globalization.Native/pal_locale.h @@ -9,10 +9,16 @@ PALEXPORT int32_t GlobalizationNative_GetLocales(UChar *value, int32_t valueLeng PALEXPORT int32_t GlobalizationNative_GetLocaleName(const UChar* localeName, UChar* value, int32_t valueLength); -#ifdef __APPLE__ -PALEXPORT const char* GlobalizationNative_GetLocaleNameNative(const char* localeName); -#endif - PALEXPORT int32_t GlobalizationNative_GetDefaultLocaleName(UChar* value, int32_t valueLength); PALEXPORT int32_t GlobalizationNative_IsPredefinedLocale(const UChar* localeName); + +PALEXPORT int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, + int shortFormat, UChar* value, + int32_t valueLength); + +#ifdef __APPLE__ +PALEXPORT const char* GlobalizationNative_GetLocaleNameNative(const char* localeName); + +PALEXPORT const char* GlobalizationNative_GetLocaleTimeFormatNative(const char* localeName, int shortFormat); +#endif diff --git a/src/native/libs/System.Globalization.Native/pal_locale.m b/src/native/libs/System.Globalization.Native/pal_locale.m index 7400c48b1c9ba..66b951db76125 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.m +++ b/src/native/libs/System.Globalization.Native/pal_locale.m @@ -4,6 +4,7 @@ #include #include "pal_locale_internal.h" #include "pal_localeStringData.h" +#include "pal_localeNumberData.h" #import #import @@ -34,10 +35,10 @@ const char* GlobalizationNative_GetLocaleNameNative(const char* localeName) { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; - NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; - const char* value = [currentLocale.localeIdentifier UTF8String]; - return strdup(value); + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + const char* value = [currentLocale.localeIdentifier UTF8String]; + return strdup(value); } const char* GlobalizationNative_GetLocaleInfoStringNative(const char* localeName, LocaleStringData localeStringData) @@ -51,7 +52,6 @@ [dateFormatter setLocale:currentLocale]; NSLocale *gbLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"]; - switch (localeStringData) { ///// localized name of locale, eg "German (Germany)" in UI language (corresponds to LOCALE_SLOCALIZEDDISPLAYNAME) @@ -148,9 +148,426 @@ value = ""; break; } - return strdup(value); } + +// invariant character definitions +#define CHAR_CURRENCY ((char)0x00A4) // international currency +#define CHAR_SPACE ((char)0x0020) // space +#define CHAR_NBSPACE ((char)0x00A0) // no-break space +#define CHAR_DIGIT ((char)0x0023) // '#' +#define CHAR_MINUS ((char)0x002D) // '-' +#define CHAR_PERCENT ((char)0x0025) // '%' +#define CHAR_OPENPAREN ((char)0x0028) // '(' +#define CHAR_CLOSEPAREN ((char)0x0029) // ')' +#define CHAR_ZERO ((char)0x0030) // '0' + +/* +Function: +NormalizeNumericPattern + +Returns a numeric string pattern in a format that we can match against the +appropriate managed pattern. Examples: +For PositiveMonetaryNumberFormat "ยค#,##0.00" becomes "Cn" +For NegativeNumberFormat "#,##0.00;(#,##0.00)" becomes "(n)" +*/ +static char* NormalizeNumericPattern(const char* srcPattern, int isNegative) +{ + int iStart = 0; + int iEnd = strlen(srcPattern); + + // ';' separates positive and negative subpatterns. + // When there is no explicit negative subpattern, + // an implicit negative subpattern is formed from the positive pattern with a prefixed '-'. + char * ptrNegativePattern = strrchr(srcPattern,';'); + if (ptrNegativePattern) + { + int32_t iNegativePatternStart = ptrNegativePattern - srcPattern; + if (isNegative) + { + iStart = iNegativePatternStart + 1; + } + else + { + iEnd = iNegativePatternStart - 1; + } + } + + int minusAdded = false; + + for (int i = iStart; i <= iEnd; i++) + { + switch (srcPattern[i]) + { + case CHAR_MINUS: + case CHAR_OPENPAREN: + case CHAR_CLOSEPAREN: + minusAdded = true; + break; + } + + if (minusAdded) + break; + } + + // international currency symbol (CHAR_CURRENCY) + // The positive pattern comes first, then an optional negative pattern + // separated by a semicolon + // A destPattern example: "(C n)" where C represents the currency symbol, and + // n is the number + char* destPattern; + int index = 0; + + // if there is no negative subpattern, prefix the minus sign + if (isNegative && !minusAdded) + { + int length = (iEnd - iStart) + 2; + destPattern = (char*)calloc((size_t)length, sizeof(char)); + if (!destPattern) + { + return NULL; + } + destPattern[index++] = '-'; + } + else + { + int length = (iEnd - iStart) + 1; + destPattern = (char*)calloc((size_t)length, sizeof(char)); + if (!destPattern) + { + return NULL; + } + } + + int digitAdded = false; + int currencyAdded = false; + int spaceAdded = false; + + for (int i = iStart; i <= iEnd; i++) + { + char ch = srcPattern[i]; + switch (ch) + { + case CHAR_DIGIT: + case CHAR_ZERO: + if (!digitAdded) + { + digitAdded = true; + destPattern[index++] = 'n'; + } + break; + + case CHAR_CURRENCY: + if (!currencyAdded) + { + currencyAdded = true; + destPattern[index++] = 'C'; + } + break; + + case CHAR_SPACE: + case CHAR_NBSPACE: + if (!spaceAdded) + { + spaceAdded = true; + destPattern[index++] = ' '; + } + break; + + case CHAR_MINUS: + case CHAR_OPENPAREN: + case CHAR_CLOSEPAREN: + case CHAR_PERCENT: + destPattern[index++] = ch; + break; + } + } + + const int MAX_DOTNET_NUMERIC_PATTERN_LENGTH = 6; // example: "(C n)" plus terminator + + if (destPattern[0] == '\0' || strlen (destPattern) >= MAX_DOTNET_NUMERIC_PATTERN_LENGTH) + { + free (destPattern); + return NULL; + } + + return destPattern; +} + +/* +Function: +GetNumericPattern + +Determines the pattern from the decimalFormat and returns the matching pattern's +index from patterns[]. +Returns index -1 if no pattern is found. +*/ +static int GetPatternIndex(char* normalizedPattern,const char* patterns[], int patternsCount) +{ + const int INVALID_FORMAT = -1; + + if (!normalizedPattern) + { + return INVALID_FORMAT; + } + + for (int i = 0; i < patternsCount; i++) + { + if (strcmp(normalizedPattern, patterns[i]) == 0) + { + free(normalizedPattern); + return i; + } + } + + assert(false); // should have found a valid pattern + + free(normalizedPattern); + return INVALID_FORMAT; +} + +static int32_t GetValueForNumberFormat(NSLocale *currentLocale, LocaleNumberData localeNumberData) +{ + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.locale = currentLocale; + const char *pFormat; + int32_t value; + + switch(localeNumberData) + { + case LocaleNumber_PositiveMonetaryNumberFormat: + { + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + static const char* Patterns[] = {"Cn", "nC", "C n", "n C"}; + pFormat = [[numberFormatter positiveFormat] UTF8String]; + char* normalizedPattern = NormalizeNumericPattern(pFormat, false); + value = GetPatternIndex(normalizedPattern, Patterns, sizeof(Patterns)/sizeof(Patterns[0])); + break; + } + case LocaleNumber_NegativeMonetaryNumberFormat: + { + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + static const char* Patterns[] = {"(Cn)", "-Cn", "C-n", "Cn-", "(nC)", "-nC", "n-C", "nC-", "-n C", + "-C n", "n C-", "C n-", "C -n", "n- C", "(C n)", "(n C)", "C- n" }; + pFormat = [[numberFormatter negativeFormat] UTF8String]; + char* normalizedPattern = NormalizeNumericPattern(pFormat, true); + value = GetPatternIndex(normalizedPattern, Patterns, sizeof(Patterns)/sizeof(Patterns[0])); + break; + } + case LocaleNumber_NegativeNumberFormat: + { + numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + static const char* Patterns[] = {"(n)", "-n", "- n", "n-", "n -"}; + pFormat = [[numberFormatter negativeFormat] UTF8String]; + char* normalizedPattern = NormalizeNumericPattern(pFormat, true); + value = GetPatternIndex(normalizedPattern, Patterns, sizeof(Patterns)/sizeof(Patterns[0])); + break; + } + case LocaleNumber_NegativePercentFormat: + { + numberFormatter.numberStyle = NSNumberFormatterPercentStyle; + static const char* Patterns[] = {"-n %", "-n%", "-%n", "%-n", "%n-", "n-%", "n%-", "-% n", "n %-", "% n-", "% -n", "n- %"}; + pFormat = [[numberFormatter negativeFormat] UTF8String]; + char* normalizedPattern = NormalizeNumericPattern(pFormat, true); + value = GetPatternIndex(normalizedPattern, Patterns, sizeof(Patterns)/sizeof(Patterns[0])); + break; + } + case LocaleNumber_PositivePercentFormat: + { + numberFormatter.numberStyle = NSNumberFormatterPercentStyle; + static const char* Patterns[] = {"n %", "n%", "%n", "% n"}; + pFormat = [[numberFormatter positiveFormat] UTF8String]; + char* normalizedPattern = NormalizeNumericPattern(pFormat, false); + value = GetPatternIndex(normalizedPattern, Patterns, sizeof(Patterns)/sizeof(Patterns[0])); + break; + } + default: + return -1; + } + + return value; +} + +int32_t GlobalizationNative_GetLocaleInfoIntNative(const char* localeName, LocaleNumberData localeNumberData) +{ + bool isSuccess = true; + int32_t value; + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + + switch (localeNumberData) + { + case LocaleNumber_MeasurementSystem: + { + const char *measurementSystem = [[currentLocale objectForKey:NSLocaleMeasurementSystem] UTF8String]; + NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + const char *us_measurementSystem = [[usLocale objectForKey:NSLocaleMeasurementSystem] UTF8String]; + value = (measurementSystem == us_measurementSystem) ? 1 : 0; + break; + } + case LocaleNumber_FractionalDigitsCount: + { + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.locale = currentLocale; + numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + value = (int32_t)numberFormatter.maximumFractionDigits; + break; + } + case LocaleNumber_MonetaryFractionalDigitsCount: + { + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.locale = currentLocale; + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + value = (int32_t)numberFormatter.maximumFractionDigits; + break; + } + case LocaleNumber_PositiveMonetaryNumberFormat: + case LocaleNumber_NegativeMonetaryNumberFormat: + case LocaleNumber_NegativeNumberFormat: + case LocaleNumber_NegativePercentFormat: + case LocaleNumber_PositivePercentFormat: + { + value = GetValueForNumberFormat(currentLocale, localeNumberData); + if (value < 0) + { + isSuccess = false; + } + break; + } + case LocaleNumber_FirstWeekOfYear: + { + NSCalendar *calendar = [currentLocale objectForKey:NSLocaleCalendar]; + int minDaysInWeek = (int32_t)[calendar minimumDaysInFirstWeek]; + if (minDaysInWeek == 1) + { + value = WeekRule_FirstDay; + } + else if (minDaysInWeek == 7) + { + value = WeekRule_FirstFullWeek; + } + else if (minDaysInWeek >= 4) + { + value = WeekRule_FirstFourDayWeek; + } + else + { + value = -1; + isSuccess = false; + } + break; + } + case LocaleNumber_ReadingLayout: + { + NSLocaleLanguageDirection langDir = [NSLocale characterDirectionForLanguage:[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]]; + // 0 - Left to right (such as en-US) + // 1 - Right to left (such as arabic locales) + value = NSLocaleLanguageDirectionRightToLeft == langDir ? 1 : 0; + break; + } + case LocaleNumber_FirstDayofWeek: + { + NSCalendar *calendar = [currentLocale objectForKey:NSLocaleCalendar]; + value = [calendar firstWeekday] - 1; // .NET is 0-based and in Apple is 1-based; + break; + } + default: + value = -1; + isSuccess = false; + break; + } + + assert(isSuccess); + + return value; +} + +/* +PAL Function: +GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative + +Returns primary grouping size for decimal and currency +*/ +int32_t GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative(const char* localeName, LocaleNumberData localeGroupingData) +{ + bool isSuccess = true; + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.locale = currentLocale; + + switch (localeGroupingData) + { + case LocaleNumber_Digit: + numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + break; + case LocaleNumber_Monetary: + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + break; + default: + isSuccess = false; + assert(isSuccess); + break; + } + return [numberFormatter groupingSize]; +} + +/* +PAL Function: +GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative + +Returns secondary grouping size for decimal and currency +*/ +int32_t GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative(const char* localeName, LocaleNumberData localeGroupingData) +{ + bool isSuccess = true; + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.locale = currentLocale; + + switch (localeGroupingData) + { + case LocaleNumber_Digit: + numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + break; + case LocaleNumber_Monetary: + numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle; + break; + default: + isSuccess = false; + assert(isSuccess); + break; + } + + return [numberFormatter secondaryGroupingSize]; +} + +/* +PAL Function: +GlobalizationNative_GetLocaleTimeFormatNative + +Returns time format information (in native format, it needs to be converted to .NET's format). +*/ +const char* GlobalizationNative_GetLocaleTimeFormatNative(const char* localeName, int shortFormat) +{ + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSLocale *currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:currentLocale]; + + if (shortFormat != 0) + { + [dateFormatter setTimeStyle:NSDateFormatterShortStyle]; + } + else + { + [dateFormatter setTimeStyle:NSDateFormatterMediumStyle]; + } + + return strdup([[dateFormatter dateFormat] UTF8String]); +} + #endif #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) diff --git a/src/native/libs/System.Globalization.Native/pal_localeNumberData.h b/src/native/libs/System.Globalization.Native/pal_localeNumberData.h index db5c401b8b7b6..a68f1e32e334a 100644 --- a/src/native/libs/System.Globalization.Native/pal_localeNumberData.h +++ b/src/native/libs/System.Globalization.Native/pal_localeNumberData.h @@ -43,3 +43,14 @@ PALEXPORT int32_t GlobalizationNative_GetLocaleInfoGroupingSizes(const UChar* lo LocaleNumberData localeGroupingData, int32_t* primaryGroupSize, int32_t* secondaryGroupSize); + +#ifdef __APPLE__ +PALEXPORT int32_t GlobalizationNative_GetLocaleInfoIntNative(const char* localeName, + LocaleNumberData localeNumberData); + +PALEXPORT int32_t GlobalizationNative_GetLocaleInfoPrimaryGroupingSizeNative(const char* localeName, + LocaleNumberData localeGroupingData); + +PALEXPORT int32_t GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative(const char* localeName, + LocaleNumberData localeGroupingData); +#endif diff --git a/src/native/libs/System.Globalization.Native/pal_localeStringData.c b/src/native/libs/System.Globalization.Native/pal_localeStringData.c index 9120b89bd329b..488cbc8cb35f2 100644 --- a/src/native/libs/System.Globalization.Native/pal_localeStringData.c +++ b/src/native/libs/System.Globalization.Native/pal_localeStringData.c @@ -401,24 +401,3 @@ int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeName, return UErrorCodeToBool(status); } -/* -PAL Function: -GetLocaleTimeFormat - -Obtains time format information (in ICU format, it needs to be converted to .NET's format). -Returns 1 for success, 0 otherwise -*/ -int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, - int shortFormat, - UChar* value, - int32_t valueLength) -{ - UErrorCode err = U_ZERO_ERROR; - char locale[ULOC_FULLNAME_CAPACITY]; - GetLocale(localeName, locale, ULOC_FULLNAME_CAPACITY, false, &err); - UDateFormatStyle style = (shortFormat != 0) ? UDAT_SHORT : UDAT_MEDIUM; - UDateFormat* pFormat = udat_open(style, UDAT_NONE, locale, NULL, 0, NULL, 0, &err); - udat_toPattern(pFormat, false, value, valueLength, &err); - udat_close(pFormat); - return UErrorCodeToBool(err); -} diff --git a/src/native/libs/System.Globalization.Native/pal_localeStringData.h b/src/native/libs/System.Globalization.Native/pal_localeStringData.h index e6030d8a4cf86..a6961c39761bf 100644 --- a/src/native/libs/System.Globalization.Native/pal_localeStringData.h +++ b/src/native/libs/System.Globalization.Native/pal_localeStringData.h @@ -52,9 +52,5 @@ PALEXPORT int32_t GlobalizationNative_GetLocaleInfoString(const UChar* localeNam #ifdef __APPLE__ PALEXPORT const char* GlobalizationNative_GetLocaleInfoStringNative(const char* localeName, LocaleStringData localeStringData); -#endif - -PALEXPORT int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeName, - int shortFormat, UChar* value, - int32_t valueLength); +#endif diff --git a/src/native/libs/System.Globalization.Native/pal_locale_internal.h b/src/native/libs/System.Globalization.Native/pal_locale_internal.h index 1f9edb7640cbf..c754554bbfdd5 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale_internal.h +++ b/src/native/libs/System.Globalization.Native/pal_locale_internal.h @@ -4,7 +4,6 @@ #pragma once #include "pal_icushim_internal.h" -#include "pal_localeStringData.h" /* Function: @@ -61,21 +60,4 @@ DetectDefaultSystemLocaleName Detects the default locale string for Apple platforms */ char* DetectDefaultAppleLocaleName(void); - -/* -Function: -GlobalizationNative_GetLocaleNameNative - -Returns native locale name for Apple platforms -*/ -const char* GlobalizationNative_GetLocaleNameNative(const char* localeName); - -/* -Function: -GlobalizationNative_GetLocaleInfoStringNative - -Returns string locale information if found for the specified locale name for Apple platforms. -Returns empty string if not found. -*/ -const char* GlobalizationNative_GetLocaleInfoStringNative(const char* localeName, LocaleStringData localeStringData); #endif diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.props b/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.props new file mode 100644 index 0000000000000..23625a46fc4ce --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + + + true + + + diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.targets b/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.targets index d72d49174ce0d..eca47c9c796ad 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.targets +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Directory.Build.targets @@ -3,12 +3,6 @@ - - - 1 - 0 - - $(IntermediateOutputPath)$(MSBuildProjectName)/gen/ $(GeneratedHWIntrinsicTestDirectory)GeneratedHWIntrinsicTestList.txt diff --git a/src/tests/JIT/HardwareIntrinsics/Directory.Build.props b/src/tests/JIT/HardwareIntrinsics/Directory.Build.props index 81ddb5af5a309..8df9869fb8699 100644 --- a/src/tests/JIT/HardwareIntrinsics/Directory.Build.props +++ b/src/tests/JIT/HardwareIntrinsics/Directory.Build.props @@ -1,3 +1,4 @@ + diff --git a/src/tests/JIT/HardwareIntrinsics/Directory.Build.targets b/src/tests/JIT/HardwareIntrinsics/Directory.Build.targets new file mode 100644 index 0000000000000..e10bfde46063a --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/Directory.Build.targets @@ -0,0 +1,20 @@ + + + + + + + + + true + + + + + + true + true + true + + + diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_r.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_r.csproj index 09b38909db712..b525dacf167c4 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_r.csproj @@ -1,17 +1,12 @@ true + true Embedded - - - 1 - 0 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_ro.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_ro.csproj index b76e7ea9ee3b3..9194d3a9763a5 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256/Vector256_ro.csproj @@ -1,17 +1,12 @@ true + true Embedded True - - - 1 - 0 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_r.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_r.csproj index 688c23b52914f..24486d9d9555c 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_r.csproj @@ -1,7 +1,7 @@ true - + true true true @@ -10,12 +10,6 @@ Embedded - - - 1 - 0 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_ro.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_ro.csproj index 10a0920bb9153..32ce1332e61a0 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector256_1/Vector256_1_ro.csproj @@ -1,7 +1,7 @@ true - + true true true @@ -10,12 +10,6 @@ Embedded True - - - 1 - 0 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_r.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_r.csproj index 5bd89c674d2a8..681f7971f5f5c 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_r.csproj @@ -1,16 +1,12 @@ true + true Embedded - - - - 1 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_ro.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_ro.csproj index 097a1aef36503..d458d5bf48614 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector512/Vector512_ro.csproj @@ -1,16 +1,12 @@ true + true Embedded True - - - - 1 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_r.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_r.csproj index 2529fc56bf863..ee8b16107dc8f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_r.csproj @@ -1,16 +1,12 @@ true + true Embedded - - - - 1 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_ro.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_ro.csproj index 66c501a722e2d..4b8799ae937ab 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector512_1/Vector512_1_ro.csproj @@ -1,16 +1,12 @@ true + true Embedded True - - - - 1 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_r.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_r.csproj index bb555014d8ff3..7e05ced6512f1 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_r.csproj @@ -1,16 +1,12 @@ true + true Embedded - - - 1 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_ro.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_ro.csproj index f41eecd53c7f4..1713e65402227 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64/Vector64_ro.csproj @@ -1,16 +1,12 @@ true + true Embedded True - - - 1 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_r.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_r.csproj index 676fb4cfe89b1..aeeaf5a1738fe 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_r.csproj @@ -1,16 +1,12 @@ true + true Embedded - - - 1 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_ro.csproj b/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_ro.csproj index dce5b934909f1..2310470cc212f 100644 --- a/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/General/Vector64_1/Vector64_1_ro.csproj @@ -1,16 +1,12 @@ true + true Embedded True - - - 1 - 0 - diff --git a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj index 2c8f90272ce3d..a44c0bfb5145d 100644 --- a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj +++ b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_r.csproj @@ -1,9 +1,10 @@ - 20 + 32 true true + diff --git a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj index e10ee544a203e..44c6f2f9f679f 100644 --- a/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj +++ b/src/tests/JIT/HardwareIntrinsics/HardwareIntrinsics_ro.csproj @@ -1,6 +1,6 @@ - 20 + 32 true true diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.props b/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.props new file mode 100644 index 0000000000000..e3e1bac79c32c --- /dev/null +++ b/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + + + true + + + diff --git a/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.targets b/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.targets index 77fd5e210fc55..933c13be21e6a 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.targets +++ b/src/tests/JIT/HardwareIntrinsics/X86/Directory.Build.targets @@ -3,13 +3,6 @@ - - - 1 - 0 - 0 - - $(IntermediateOutputPath)$(MSBuildProjectName)/gen/ $(GeneratedHWIntrinsicTestDirectory)GeneratedHWIntrinsicTestList.txt diff --git a/src/tests/issues.targets b/src/tests/issues.targets index b7214078e9c60..d362b4c04fc3c 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -293,6 +293,9 @@ + + https://github.com/dotnet/runtime/issues/84818 + https://github.com/dotnet/runtime/issues/49184 @@ -509,6 +512,21 @@ https://github.com/dotnet/runtime/issues/66745 + + https://github.com/dotnet/runtime/issues/84818 + + + https://github.com/dotnet/runtime/issues/84750 + + + https://github.com/dotnet/runtime/issues/84750 + + + https://github.com/dotnet/runtime/issues/84818 + + + https://github.com/dotnet/runtime/issues/84818 + https://github.com/dotnet/runtime/issues/81241 @@ -3698,6 +3716,12 @@ https://github.com/dotnet/runtime/issues/41472 + + https://github.com/dotnet/runtime/issues/84786 + + + https://github.com/dotnet/runtime/issues/84786 + needs triage diff --git a/src/tests/nativeaot/SmokeTests/DwarfDump/Program.cs b/src/tests/nativeaot/SmokeTests/DwarfDump/Program.cs index 0096a28c92f1e..39e6c815c0dda 100644 --- a/src/tests/nativeaot/SmokeTests/DwarfDump/Program.cs +++ b/src/tests/nativeaot/SmokeTests/DwarfDump/Program.cs @@ -54,8 +54,8 @@ public static int Main(string[] args) const int MinWarnings = 16500; const int MaxWarnings = 18500; #else - const int MinWarnings = 9500; - const int MaxWarnings = 10500; + const int MinWarnings = 12000; + const int MaxWarnings = 13000; #endif int count = 0; string line; diff --git a/src/tests/run.cmd b/src/tests/run.cmd index 113deb87cbef1..0c79426b6c437 100644 --- a/src/tests/run.cmd +++ b/src/tests/run.cmd @@ -24,6 +24,7 @@ set __ToolsDir=%__ProjectDir%\..\Tools set "DotNetCli=%__RepoRootDir%\dotnet.cmd" set __Sequential= +set __ParallelType= set __msbuildExtraArgs= set __LongGCTests= set __GCSimulatorTests= @@ -53,13 +54,11 @@ if /i "%1" == "checked" (set __BuildType=Checked if /i "%1" == "TestEnv" (set __TestEnv=%2&shift&shift&goto Arg_Loop) if /i "%1" == "sequential" (set __Sequential=1&shift&goto Arg_Loop) -if /i "%1" == "longgc" (set __LongGCTests=1&shift&goto Arg_Loop) -if /i "%1" == "gcsimulator" (set __GCSimulatorTests=1&shift&goto Arg_Loop) +if /i "%1" == "parallel" (set __ParallelType=%2&shift&shift&goto Arg_Loop) if /i "%1" == "jitstress" (set DOTNET_JitStress=%2&shift&shift&goto Arg_Loop) if /i "%1" == "jitstressregs" (set DOTNET_JitStressRegs=%2&shift&shift&goto Arg_Loop) if /i "%1" == "jitminopts" (set DOTNET_JITMinOpts=1&shift&goto Arg_Loop) if /i "%1" == "jitforcerelocs" (set DOTNET_ForceRelocs=1&shift&goto Arg_Loop) -if /i "%1" == "ilasmroundtrip" (set __IlasmRoundTrip=1&shift&goto Arg_Loop) if /i "%1" == "printlastresultsonly" (set __PrintLastResultsOnly=1&shift&goto Arg_Loop) if /i "%1" == "runcrossgen2tests" (set RunCrossGen2=1&shift&goto Arg_Loop) @@ -68,11 +67,11 @@ if /i "%1" == "runlargeversionbubblecrossgen2tests" (set RunCrossGen2=1&set if /i "%1" == "synthesizepgo" (set CrossGen2SynthesizePgo=1&shift&goto Arg_Loop) if /i "%1" == "link" (set DoLink=true&set ILLINK=%2&shift&shift&goto Arg_Loop) if /i "%1" == "gcname" (set DOTNET_GCName=%2&shift&shift&goto Arg_Loop) -if /i "%1" == "timeout" (set __TestTimeout=%2&shift&shift&goto Arg_Loop) - -REM change it to DOTNET_GCStress when we stop using xunit harness if /i "%1" == "gcstresslevel" (set DOTNET_GCStress=%2&set __TestTimeout=1800000&shift&shift&goto Arg_Loop) - +if /i "%1" == "gcsimulator" (set __GCSimulatorTests=1&shift&goto Arg_Loop) +if /i "%1" == "longgc" (set __LongGCTests=1&shift&goto Arg_Loop) +if /i "%1" == "ilasmroundtrip" (set __IlasmRoundTrip=1&shift&goto Arg_Loop) +if /i "%1" == "timeout" (set __TestTimeout=%2&shift&shift&goto Arg_Loop) if /i "%1" == "runincontext" (set RunInUnloadableContext=1&shift&goto Arg_Loop) if /i "%1" == "tieringtest" (set TieringTest=1&shift&goto Arg_Loop) if /i "%1" == "runnativeaottests" (set RunNativeAot=1&shift&goto Arg_Loop) @@ -107,7 +106,7 @@ set "__TestWorkingDir=%__RootBinDir%\tests\coreclr\%__TargetOS%.%__BuildArch%.%_ if not defined XunitTestBinBase set XunitTestBinBase=%__TestWorkingDir%\ if not defined XunitTestReportDirBase set XunitTestReportDirBase=%XunitTestBinBase%\Reports\ -REM We are not running in the official build scenario, call run.py +REM Set up arguments to call run.py set __RuntestPyArgs=-arch %__BuildArch% -build_type %__BuildType% @@ -135,6 +134,10 @@ if defined __Sequential ( set __RuntestPyArgs=%__RuntestPyArgs% --sequential ) +if defined __ParallelType ( + set __RuntestPyArgs=%__RuntestPyArgs% -parallel %__ParallelType% +) + if defined RunCrossGen2 ( set __RuntestPyArgs=%__RuntestPyArgs% --run_crossgen2_tests ) @@ -180,201 +183,6 @@ echo %NEXTCMD% exit /b %ERRORLEVEL% -:SetupMSBuildAndCallRuntestProj - -:: Note: We've disabled node reuse because it causes file locking issues. -:: The issue is that we extend the build with our own targets which -:: means that rebuilding cannot successfully delete the task -:: assembly. -set __msbuildCommonArgs=/nologo /nodeReuse:false %__msbuildExtraArgs% /p:Platform=%__MSBuildBuildArch% - -if not defined __Sequential ( - set __msbuildCommonArgs=%__msbuildCommonArgs% /maxcpucount -) else ( - set __msbuildCommonArgs=%__msbuildCommonArgs% /p:ParallelRun=false -) - -if defined DoLink ( - set __msbuildCommonArgs=%__msbuildCommonArgs% /p:RunTestsViaIllink=true -) - -if not exist "%__LogsDir%" md "%__LogsDir%" -if not exist "%__MsbuildDebugLogsDir%" md "%__MsbuildDebugLogsDir%" - -REM Set up the directory for MSBuild debug logs. -set MSBUILDDEBUGPATH=%__MsbuildDebugLogsDir% - -REM These log files are created automatically by the test run process. Q: what do they depend on being set? -set __TestRunHtmlLog=%__LogsDir%\TestRun_%__TargetOS%__%__BuildArch%__%__BuildType%.html -set __TestRunXmlLog=%__LogsDir%\TestRun_%__TargetOS%__%__BuildArch%__%__BuildType%.xml - -REM Prepare the Test Drop - -echo %__MsgPrefix%Removing 'ni' files and 'lock' folders from %__TestWorkingDir% -REM Cleans any NI from the last run -powershell -NoProfile "Get-ChildItem -path %__TestWorkingDir% -Include '*.ni.*' -Recurse -Force | Remove-Item -force" -REM Cleans up any lock folder used for synchronization from last run -powershell -NoProfile "Get-ChildItem -path %__TestWorkingDir% -Include 'lock' -Recurse -Force | where {$_.Attributes -eq 'Directory'}| Remove-Item -force -Recurse" - -if defined CORE_ROOT goto SkipCoreRootSetup - -set "CORE_ROOT=%XunitTestBinBase%\Tests\Core_Root" -echo %__MsgPrefix%Using Default CORE_ROOT as %CORE_ROOT% -echo %__MsgPrefix%Copying Built binaries from %__BinDir% to %CORE_ROOT% -if exist "%CORE_ROOT%" rd /s /q "%CORE_ROOT%" -md "%CORE_ROOT%" -xcopy "%__BinDir%" "%CORE_ROOT%" - -:SkipCoreRootSetup - -if not exist %CORE_ROOT%\coreclr.dll ( - echo %__MsgPrefix%Error: Ensure you have done a successful build of the Product and %CORE_ROOT% contains runtime binaries. - exit /b 1 -) - -REM ========================================================================================= -REM === -REM === Run normal (non-perf) tests -REM === -REM ========================================================================================= - -call :SetTestEnvironment - -call :ResolveDependencies -if errorlevel 1 exit /b 1 - -::Check if the test Binaries are built -if not exist %XunitTestBinBase% ( - echo %__MsgPrefix%Error: Ensure the Test Binaries are built and are present at %XunitTestBinBase%. - echo %__MsgPrefix%Run "buildtest.cmd %__BuildArch% %__BuildType%" to build the tests first. - exit /b 1 -) - -echo %__MsgPrefix%CORE_ROOT that will be used is: %CORE_ROOT% -echo %__MsgPrefix%Starting test run at %TIME% - -set __BuildLogRootName=TestRunResults -call :msbuild "%__ProjectFilesDir%\src\runtest.proj" /p:Runtests=true /clp:showcommandline -set __errorlevel=%errorlevel% - - -if %__errorlevel% GEQ 1 ( - echo %__MsgPrefix%Test Run failed. Refer to the following: - echo Html report: %__TestRunHtmlLog% - exit /b 1 -) - -goto TestsDone - -REM ========================================================================================= -REM === -REM === All tests complete! -REM === -REM ========================================================================================= - -:TestsDone - -echo %__MsgPrefix%Test run successful. Finished at %TIME%. Refer to the log files for details: -echo %__TestRunHtmlLog% -echo %__TestRunXmlLog% -exit /b 0 - -REM ========================================================================================= -REM === -REM === Subroutine to invoke msbuild. -REM === -REM === All arguments are passed to msbuild. The first argument should be the .proj file to invoke. -REM === -REM === On entry, environment variable __BuildLogRootName must be set to a file name prefix for the generated log files. -REM === All the "standard" environment variables that aren't expected to change per invocation must also be set, -REM === like __msbuildCommonArgs. -REM === -REM === The build log files will be overwritten, not appended to. -REM === -REM ========================================================================================= - -:msbuild - -echo %__MsgPrefix%Invoking msbuild - -set "__BuildLog=%__LogsDir%\%__BuildLogRootName%_%__TargetOS%__%__BuildArch%__%__BuildType%.log" -set "__BuildWrn=%__LogsDir%\%__BuildLogRootName%_%__TargetOS%__%__BuildArch%__%__BuildType%.wrn" -set "__BuildErr=%__LogsDir%\%__BuildLogRootName%_%__TargetOS%__%__BuildArch%__%__BuildType%.err" - -set __msbuildLogArgs=^ -/fileloggerparameters:Verbosity=normal;LogFile="%__BuildLog%";Append ^ -/fileloggerparameters1:WarningsOnly;LogFile="%__BuildWrn%" ^ -/fileloggerparameters2:ErrorsOnly;LogFile="%__BuildErr%" ^ -/consoleloggerparameters:Summary ^ -/verbosity:minimal - -set __msbuildArgs=%* %__msbuildCommonArgs% %__msbuildLogArgs% - -@REM The next line will overwrite the existing log file, if any. -echo %__MsgPrefix%"%DotNetCli%" msbuild %__msbuildArgs% -echo Invoking: "%DotNetCli%" msbuild %__msbuildArgs% > "%__BuildLog%" - -call "%DotNetCli%" msbuild %__msbuildArgs% -if errorlevel 1 ( - echo %__MsgPrefix%Error: msbuild failed. Refer to the log files for details: - echo %__BuildLog% - echo %__BuildWrn% - echo %__BuildErr% - exit /b 1 -) - -exit /b 0 - -REM ========================================================================================= -REM === -REM === Set various environment variables, based on arguments to this script, before invoking the tests. -REM === -REM ========================================================================================= - -:SetTestEnvironment - -:: Long GC tests take about 10 minutes per test on average, so -:: they often bump up against the default 10 minute timeout. -:: 20 minutes is more than enough time for a test to complete successfully. -if defined __LongGCTests ( - echo %__MsgPrefix%Running Long GC tests, extending timeout to 20 minutes - set __TestTimeout=1200000 - set RunningLongGCTests=1 -) - -:: GCSimulator tests can take up to an hour to complete. They are run twice a week in the -:: CI, so it's fine if they take a long time. -if defined __GCSimulatorTests ( - echo %__MsgPrefix%Running GCSimulator tests, extending timeout to one hour - set __TestTimeout=3600000 - set RunningGCSimulatorTests=1 -) - -if defined __IlasmRoundTrip ( - echo %__MsgPrefix%Running Ilasm round trip - set RunningIlasmRoundTrip=1 -) - -exit /b 0 - -REM ========================================================================================= -REM === -REM === Generate the "layout" directory in CORE_ROOT; download dependencies. -REM === -REM ========================================================================================= - -:ResolveDependencies - -set __BuildLogRootName=Tests_GenerateRuntimeLayout -call :msbuild "%__ProjectFilesDir%\src\runtest.proj" /p:GenerateRuntimeLayout=true -if errorlevel 1 ( - echo %__MsgPrefix%Test Dependency Resolution Failed - exit /b 1 -) -echo %__MsgPrefix%Created the runtime layout with all dependencies in %CORE_ROOT% - -exit /b 0 - REM ========================================================================================= REM === REM === Display a help message describing how to use this script. @@ -395,7 +203,8 @@ echo./? -? /h -h /help -help - View this message. echo ^ - Specifies build architecture: x64, x86, arm, or arm64 ^(default: x64^). echo ^ - Specifies build type: Debug, Release, or Checked ^(default: Debug^). echo TestEnv ^ - Run a custom script before every test to set custom test environment settings. -echo sequential - Run tests sequentially (no parallelism). +echo sequential - Run tests sequentially ^(no parallelism^). +echo parallel ^ - Run tests with given level of parallelism: none, collections, assemblies, all. Default: collections. echo RunCrossgen2Tests - Runs ReadytoRun tests compiled with Crossgen2 echo synthesizepgo - Enabled synthesizing PGO data in CrossGen2 echo jitstress ^ - Runs the tests with DOTNET_JitStress=n @@ -409,6 +218,7 @@ echo 2: GC on transitions to preemptive GC echo 4: GC on every allowable JITed instruction echo 8: GC on every allowable NGEN instruction echo 16: GC only on a unique stack trace +echo (Note that the value must be expresed in hex.) echo gcsimulator - Run the GC Simulator tests echo longgc - Run the long-running GC tests echo ilasmroundtrip - Runs ilasm round trip on the tests diff --git a/src/tests/run.py b/src/tests/run.py index 0680248f63b12..5e9f94a160459 100755 --- a/src/tests/run.py +++ b/src/tests/run.py @@ -75,6 +75,11 @@ prone to failure; however, copying into the Core_Root directory may create naming conflicts.""") +parallel_help = """ +Specify the level of parallelism: none, collections, assemblies, all. Default: collections. +`-parallel none` is a synonym for `--sequential`. +""" + parser = argparse.ArgumentParser(description=description) parser.add_argument("-os", dest="host_os", nargs='?', default=None) @@ -84,6 +89,7 @@ parser.add_argument("-core_root", dest="core_root", nargs='?', default=None) parser.add_argument("-runtime_repo_location", dest="runtime_repo_location", default=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) parser.add_argument("-test_env", dest="test_env", default=None) +parser.add_argument("-parallel", dest="parallel", default=None, help=parallel_help) # Optional arguments which change execution. @@ -567,6 +573,9 @@ def call_msbuild(args): common_msbuild_arguments = [] + if args.parallel: + common_msbuild_arguments += ["/p:ParallelRun={}".format(args.parallel)] + if args.sequential: common_msbuild_arguments += ["/p:ParallelRun=none"] @@ -956,11 +965,19 @@ def setup_args(args): print("Error, msbuild currently expects tests in {} (got test_location {})".format(normal_location, coreclr_setup_args.test_location)) raise Exception("Error, msbuild currently expects tests in artifacts/tests/...") + # valid_parallel_args is the same list as that allowed by the xunit.console.dll "-parallel" argument. + valid_parallel_args = ["none", "collections", "assemblies", "all"] + coreclr_setup_args.verify(args, "test_env", lambda arg: True, "Error setting test_env") + coreclr_setup_args.verify(args, + "parallel", + lambda arg: arg is None or arg in valid_parallel_args, + "Parallel argument '{}' unknown".format) + coreclr_setup_args.verify(args, "analyze_results_only", lambda arg: True, @@ -1041,6 +1058,9 @@ def setup_args(args): lambda arg: True, "Error setting run_nativeaot_tests") + if coreclr_setup_args.sequential and coreclr_setup_args.parallel: + print("Error: don't specify both --sequential and -parallel") + sys.exit(1) print("host_os : %s" % coreclr_setup_args.host_os) print("arch : %s" % coreclr_setup_args.arch) diff --git a/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs b/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs index 2d9097f975df4..3612aaa3d3cb8 100644 --- a/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs +++ b/src/tools/illink/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs @@ -571,8 +571,8 @@ public BodyReducer (MethodBody body, LinkContext context) Collection? FoldedInstructions { get; set; } - [MemberNotNull ("FoldedInstructions")] - [MemberNotNull ("mapping")] + [MemberNotNull (nameof(FoldedInstructions))] + [MemberNotNull (nameof(mapping))] void InitializeFoldedInstruction () { FoldedInstructions = new Collection (Instructions); @@ -1475,7 +1475,7 @@ public ConstantExpressionMethodAnalyzer (UnreachableBlocksOptimizer optimizer) // public bool SideEffectFreeResult { get; private set; } - [MemberNotNullWhen (true, "Result")] + [MemberNotNullWhen (true, nameof(Result))] public bool Analyze (in CalleePayload callee, Stack callStack) { MethodDefinition method = callee.Method; @@ -1852,7 +1852,7 @@ bool EvaluateConditionalJump (Instruction instr, out Instruction? target) return false; } - [MemberNotNullWhen (true, "Result")] + [MemberNotNullWhen (true, nameof(Result))] bool ConvertStackToResult () { if (stack_instr == null) diff --git a/src/tools/illink/src/linker/Linker/Tracer.cs b/src/tools/illink/src/linker/Linker/Tracer.cs index 15bd8a4b342e1..854f2ecdced04 100644 --- a/src/tools/illink/src/linker/Linker/Tracer.cs +++ b/src/tools/illink/src/linker/Linker/Tracer.cs @@ -66,7 +66,7 @@ public void AddRecorder (IDependencyRecorder recorder) recorders.Add (recorder); } - [MemberNotNullWhen (true, "recorders")] + [MemberNotNullWhen (true, nameof(recorders))] bool IsRecordingEnabled () { return recorders != null;