diff --git a/BuildToolsVersion.txt b/BuildToolsVersion.txt index 457b5383dead..433db8972e5b 100644 --- a/BuildToolsVersion.txt +++ b/BuildToolsVersion.txt @@ -1 +1 @@ -3.0.0-preview4-03906-01 +3.0.0-preview4-03913-01 diff --git a/Documentation/Profiling/Profiler Loading.md b/Documentation/Profiling/Profiler Loading.md index 73286298daa2..acc0bab9c584 100644 --- a/Documentation/Profiling/Profiler Loading.md +++ b/Documentation/Profiling/Profiler Loading.md @@ -16,7 +16,7 @@ If any of these environment variable are present, we skip the registry look up a A couple things to note about this: - If you specify `CORECLR_PROFILER_PATH` _and_ register your profiler, then `CORECLR_PROFILER_PATH` always wins. Even if `CORECLR_PROFILER_PATH` points to an invalid path, we will still use `CORECLR_PROFILER_PATH`, and just fail to load your profiler. -- `CORECLR_R_PROFILER` is _always required_. If you specify `CORECLR_PROFILER_PATH`, we skip the registry look up. We still need to know your profiler's CLSID, so we can pass it to your class factory's CreateInstance call. +- `CORECLR_PROFILER` is _always required_. If you specify `CORECLR_PROFILER_PATH`, we skip the registry look up. We still need to know your profiler's CLSID, so we can pass it to your class factory's CreateInstance call. ## Through the registry (Windows Only) diff --git a/Documentation/Profiling/davbr-blog-archive/samples/PlugInToYourProfiler.cpp b/Documentation/Profiling/davbr-blog-archive/samples/PlugInToYourProfiler.cpp index 81471bb1b31d..561f5916635f 100644 --- a/Documentation/Profiling/davbr-blog-archive/samples/PlugInToYourProfiler.cpp +++ b/Documentation/Profiling/davbr-blog-archive/samples/PlugInToYourProfiler.cpp @@ -1 +1,477 @@ -// This blog post originally appeared on David Broman's blog on 10/13/2005 #include "SigFormat.cpp" // --------------------------------------------------------------------- // --------------------------------------------------------------------- // This file does not compile on its own. It contains snippets of code you can add // to a working profiler, so that your profiler will invoke instances of the SigFormat // object to parse and pretty-print all the types in all modules as they're loaded. // // The functions are ordered from callees to callers (so no forward declarations are // necessary). If you prefer a top-down approach to learning code, then start // at the bottom of the file. // --------------------------------------------------------------------- // --------------------------------------------------------------------- // **************************************************************** // HELPERS TO READ THROUGH METADATA, FIND SIGNATURES, AND INVOKE THE PARSER // **************************************************************** // Simple wrapper to create an instance of SigFormat and invoke it HRESULT DoParse(sig_byte * sig, ULONG cbSig) { SigFormat sf; HRESULT hr; bool fRet = sf.Parse(sig, cbSig); if (!fRet) { hr = E_FAIL; goto Error; } hr = S_OK; Cleanup: return hr; Error: goto Cleanup; } // Takes an mdProperty, prints an intro line, then invokes the parser / printer HRESULT PrintProperty(ModuleID moduleID, IMetaDataImport* pMDImport, LPCWSTR wszClassName, mdProperty md) { HRESULT hr; mdTypeDef td; WCHAR wszName[500]; ULONG cchName; PCCOR_SIGNATURE sigMember; ULONG cbSigMember; DWORD dwAttr; DWORD dwCPlusTypeFlag; UVCP_CONSTANT pValue; ULONG cchValue; mdMethodDef mdSetter; mdMethodDef mdGetter; mdMethodDef aOtherMethods[100]; ULONG cOtherMethods; hr = pMDImport->GetPropertyProps(md, // The member for which to get props. &td, // Put member's class here. wszName, // Put member's name here. dimensionof(wszName), // Size of szMember buffer in wide chars. &cchName, // Put actual size here &dwAttr, // Put flags here. &sigMember, // [OUT] point to the blob value of meta data &cbSigMember, // [OUT] actual size of signature blob &dwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* &pValue, // [OUT] constant value &cchValue, &mdSetter, // [OUT] setter method of the property &mdGetter, // [OUT] getter method of the property aOtherMethods, // [OUT] other method of the property dimensionof(aOtherMethods), // [IN] size of rmdOtherMethod &cOtherMethods); // [OUT] total number of other method of this property if (FAILED(hr)) { goto Error; } printf("\n%S.%S (0x%x)\n", wszClassName, wszName, md); DoParse((sig_byte *) sigMember, cbSigMember); hr = S_OK; Cleanup: return hr; Error: goto Cleanup; } // Takes a field token, prints an intro line, then invokes the parser / printer HRESULT PrintField(ModuleID moduleID, IMetaDataImport* pMDImport, LPCWSTR wszClassName, mdToken md) { HRESULT hr; mdTypeDef td; WCHAR wszName[500]; ULONG cchName; PCCOR_SIGNATURE sigMember; ULONG cbSigMember; DWORD dwAttr; DWORD dwCPlusTypeFlag; UVCP_CONSTANT pValue; ULONG cchValue; hr = pMDImport->GetFieldProps(md, // The member for which to get props. &td, // Put member's class here. wszName, // Put member's name here. dimensionof(wszName), // Size of szMember buffer in wide chars. &cchName, // Put actual size here &dwAttr, // Put flags here. &sigMember, // [OUT] point to the blob value of meta data &cbSigMember, // [OUT] actual size of signature blob &dwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* &pValue, // [OUT] constant value &cchValue); // [OUT] size of constant string in chars, 0 for non-strings. if (FAILED(hr)) { goto Error; } printf("\n%S.%S (0x%x)\n", wszClassName, wszName, md); DoParse((sig_byte *) sigMember, cbSigMember); hr = S_OK; Cleanup: return hr; Error: goto Cleanup; } // Takes an mdMethodDef, prints an intro line, then invokes the parser / printer on its signature and its locals HRESULT PrintMethodDef(ModuleID moduleID, IMetaDataImport* pMDImport, LPCWSTR wszClassName, mdMethodDef md) { HRESULT hr; mdTypeDef td; WCHAR wszMethod[500]; ULONG cchMethod; DWORD dwAttr; PCCOR_SIGNATURE sigParam; PCCOR_SIGNATURE sigLocal; ULONG cbSigParam; ULONG cbSigLocal; ULONG ulCodeRVA; DWORD dwImplFlags; BOOL fMore; LPCBYTE pMethodHeader = NULL; ULONG cbMethodSize; IMAGE_COR_ILMETHOD_TINY* pimt = NULL; IMAGE_COR_ILMETHOD_FAT* pimf = NULL; hr = pMDImport->GetMethodProps(md, // The method for which to get props. &td, // Put method's class here. wszMethod, // Put method's name here. dimensionof(wszMethod), // Size of szMethod buffer in wide chars. &cchMethod, // Put actual size here &dwAttr, // Put flags here. &sigParam, // [OUT] point to the blob value of meta data &cbSigParam, // [OUT] actual size of signature blob &ulCodeRVA, // [OUT] codeRVA &dwImplFlags); // [OUT] Impl. Flags if (FAILED(hr)) { goto Error; } printf("\n%S.%S (0x%x)\n", wszClassName, wszMethod, md); // Method prototype signature parse DoParse((sig_byte *) sigParam, cbSigParam); // Method locals signature parse hr = g_pProfilerInfo->GetILFunctionBody(moduleID, md, &pMethodHeader, &cbMethodSize); if (FAILED(hr)) { goto EndLocal; } // The following odd-looking lines of code decode the method header, ensure // it is in a format that contains local variables, and then grabs the local // variable signature out of the header. pimt = (IMAGE_COR_ILMETHOD_TINY*) pMethodHeader; if ((pimt->Flags_CodeSize & (CorILMethod_FormatMask >> 1)) != CorILMethod_FatFormat) { goto EndLocal; } pimf = (IMAGE_COR_ILMETHOD_FAT*) pMethodHeader; if (pimf->LocalVarSigTok == 0) { goto EndLocal; } hr = pMDImport->GetSigFromToken(pimf->LocalVarSigTok, &sigLocal, &cbSigLocal); DoParse((sig_byte *) sigLocal, cbSigLocal); EndLocal: hr = S_OK; Cleanup: return hr; Error: goto Cleanup; } // Simple helper to print an intro line for a class void PrintHeader(LPCWSTR wszClassName, mdTypeDef td, LPCSTR szCategory) { printf("\n--------------------------------------------\n"); printf("%S (0x%x):\t%s\n", wszClassName, td, szCategory); printf("--------------------------------------------\n\n"); } // Combines above functions to print the methods, properties, and fields of a class HRESULT PrintTypedef(ModuleID moduleID, IMetaDataImport* pMDImport, mdTypeDef td) { HRESULT hr; HCORENUM hEnum = NULL; mdMethodDef aMethods[100]; mdFieldDef aFields[100]; mdFieldDef aProperties[100]; ULONG cMethodDefs; ULONG cFields; ULONG cProperties; ULONG i; WCHAR wszTdName[200]; ULONG cchTdName; DWORD dwTypeDefFlags; mdToken tkExtends; BOOL fMore; hr = pMDImport->GetTypeDefProps(td, // [IN] TypeDef token for inquiry. wszTdName, // [OUT] Put name here. dimensionof(wszTdName), // [IN] size of name buffer in wide chars. &cchTdName, // [OUT] put size of name (wide chars) here. &dwTypeDefFlags, // [OUT] Put flags here. &tkExtends); // [OUT] Put base class TypeDef/TypeRef here. if (FAILED(hr)) { goto Error; } PrintHeader(wszTdName, td, "METHODDEFS"); fMore = TRUE; while (fMore) { hr = pMDImport->EnumMethods(&hEnum, td, // [IN] TypeDef to scope the enumeration. aMethods, // [OUT] Put MethodDefs here. dimensionof(aMethods), // [IN] Max MethodDefs to put. &cMethodDefs); // [OUT] Put # put here. if (FAILED(hr)) { goto Error; } if (hr == S_FALSE) { fMore = FALSE; } for (i=0; i < cMethodDefs; i++) { hr = PrintMethodDef(moduleID, pMDImport, wszTdName, aMethods[i]); if (FAILED(hr)) { // do you care? If so, do something about this. } } } pMDImport->CloseEnum(hEnum); hEnum = NULL; PrintHeader(wszTdName, td, "FIELDS"); fMore = TRUE; while (fMore) { hr = pMDImport->EnumFields(&hEnum, td, Fields, dimensionof(aFields), &cFields); if (FAILED(hr)) { goto Error; } if (hr == S_FALSE) { fMore = FALSE; } for (i=0; i < cFields; i++) { hr = PrintField(moduleID, pMDImport, wszTdName, aFields[i]); if (FAILED(hr)) { // do you care? If so, do something about this. } } } pMDImport->CloseEnum(hEnum); hEnum = NULL; PrintHeader(wszTdName, td, "PROPERTIES"); fMore = TRUE; while (fMore) { hr = pMDImport->EnumProperties(&hEnum, td, aProperties, dimensionof(aProperties), &cProperties); if (FAILED(hr)) { goto Error; } if (hr == S_FALSE) { fMore = FALSE; } for (i=0; i < cProperties; i++) { hr = PrintProperty(moduleID, pMDImport, wszTdName, aProperties[i]); if (FAILED(hr)) { // do you care? If so, do something about this. } } } pMDImport->CloseEnum(hEnum); hEnum = NULL; hr = S_OK; Cleanup: if (hEnum != NULL) { pMDImport->CloseEnum(hEnum); } return hr; Error: goto Cleanup; } // Enumerates the typedefs in a module via the metadata interface, and calls PrintTypedef // on each one HRESULT PrintMetadata(ModuleID moduleID, IMetaDataImport* pMDImport) { HRESULT hr; HCORENUM hEnum = NULL; mdTypeDef aTypeDefs[100]; ULONG cTypeDefs; ULONG i; BOOL fMoreTypeDefs = TRUE; while (fMoreTypeDefs) { hr = pMDImport->EnumTypeDefs(&hEnum, aTypeDefs, dimensionof(aTypeDefs), &cTypeDefs); if (FAILED(hr)) { goto Error; } if (hr == S_FALSE) { fMoreTypeDefs = FALSE; } for (i=0; i < cTypeDefs; i++) { hr = PrintTypedef(moduleID, pMDImport, aTypeDefs[i]); if (FAILED(hr)) { // do you care? If so, do something about this. } } } hr = S_OK; Cleanup: if (hEnum != NULL) { pMDImport->CloseEnum(hEnum); } return hr; Error: goto Cleanup; } // **************************************************************** // Add this to your profiler's ICorProfilerCallback2::ModuleLoadFinished implementation. // It is assumed your copy of the ICorProfilerInfo2 interface may be accessed via // g_pProfilerInfo. Change the code to fit your profiler as appropriate. // **************************************************************** // // As a module gets loaded, this callback implementation initiates the pretty-printer to // log all the types to stdout. HRESULT CYourProfImpl::ModuleLoadFinished( ModuleID moduleID, HRESULT hrStatus ) { HRESULT hr; LPCBYTE pbBaseLoadAddr; WCHAR wszName[300]; ULONG cchNameIn = dimensionof(wszName); ULONG cchNameOut; AssemblyID assemblyID; hr = g_pProfilerInfo->GetModuleInfo(moduleID, &pbBaseLoadAddr, cchNameIn, &cchNameOut, wszName, &assemblyID); if (FAILED(hr)) { return hr; } printf("MODULE LOAD FINISHED: %S\n", wszName); IMetaDataImport *pMDImport = NULL; hr = g_pProfilerInfo->GetModuleMetaData(moduleID, ofRead, IID_IMetaDataImport, (IUnknown **)&pMDImport ); if (FAILED(hr)) { return hr; } hr = PrintMetadata(moduleID, pMDImport); if (FAILED(hr)) { // Do any error handling as appropriate } hr = S_OK; Cleanup: return hr; Error: goto Cleanup; } \ No newline at end of file +// This blog post originally appeared on David Broman's blog on 10/13/2005 + +#include "SigFormat.cpp" + + + // --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // This file does not compile on its own. It contains snippets of code you can add + // to a working profiler, so that your profiler will invoke instances of the SigFormat + // object to parse and pretty-print all the types in all modules as they're loaded. + // + // The functions are ordered from callees to callers (so no forward declarations are + // necessary). If you prefer a top-down approach to learning code, then start + // at the bottom of the file. + // --------------------------------------------------------------------- + // --------------------------------------------------------------------- + + + // **************************************************************** + // HELPERS TO READ THROUGH METADATA, FIND SIGNATURES, AND INVOKE THE PARSER + // **************************************************************** + + // Simple wrapper to create an instance of SigFormat and invoke it +HRESULT DoParse(sig_byte * sig, ULONG cbSig) +{ + SigFormat sf; + HRESULT hr; + bool fRet = sf.Parse(sig, cbSig); + if (!fRet) + { + hr = E_FAIL; + goto Error; + } + + hr = S_OK; + + Cleanup: + return hr; + + Error: + goto Cleanup; +} + + // Takes an mdProperty, prints an intro line, then invokes the parser / printer +HRESULT PrintProperty(ModuleID moduleID, IMetaDataImport* pMDImport, LPCWSTR wszClassName, mdProperty md) +{ + HRESULT hr; + mdTypeDef td; + WCHAR wszName[500]; + ULONG cchName; + PCCOR_SIGNATURE sigMember; + ULONG cbSigMember; + DWORD dwAttr; + DWORD dwCPlusTypeFlag; + UVCP_CONSTANT pValue; + ULONG cchValue; + mdMethodDef mdSetter; + mdMethodDef mdGetter; + mdMethodDef aOtherMethods[100]; + ULONG cOtherMethods; + + hr = pMDImport->GetPropertyProps(md, // The member for which to get props. + &td, // Put member's class here. + wszName, // Put member's name here. + dimensionof(wszName), // Size of szMember buffer in wide chars. + &cchName, // Put actual size here + &dwAttr, // Put flags here. + &sigMember, // [OUT] point to the blob value of meta data + &cbSigMember, // [OUT] actual size of signature blob + &dwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + &pValue, // [OUT] constant value + &cchValue, + &mdSetter, // [OUT] setter method of the property + &mdGetter, // [OUT] getter method of the property + aOtherMethods, // [OUT] other method of the property + dimensionof(aOtherMethods), // [IN] size of rmdOtherMethod + &cOtherMethods); // [OUT] total number of other method of this property + if (FAILED(hr)) + { + goto Error; + } + + printf("\n%S.%S (0x%x)\n", wszClassName, wszName, md); + DoParse((sig_byte *) sigMember, cbSigMember); + + hr = S_OK; + + Cleanup: + return hr; + + Error: + goto Cleanup; + +} + + + // Takes a field token, prints an intro line, then invokes the parser / printer +HRESULT PrintField(ModuleID moduleID, IMetaDataImport* pMDImport, LPCWSTR wszClassName, mdToken md) +{ + HRESULT hr; + mdTypeDef td; + WCHAR wszName[500]; + ULONG cchName; + PCCOR_SIGNATURE sigMember; + ULONG cbSigMember; + DWORD dwAttr; + DWORD dwCPlusTypeFlag; + UVCP_CONSTANT pValue; + ULONG cchValue; + + hr = pMDImport->GetFieldProps(md, // The member for which to get props. + &td, // Put member's class here. + wszName, // Put member's name here. + dimensionof(wszName), // Size of szMember buffer in wide chars. + &cchName, // Put actual size here + &dwAttr, // Put flags here. + &sigMember, // [OUT] point to the blob value of meta data + &cbSigMember, // [OUT] actual size of signature blob + &dwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + &pValue, // [OUT] constant value + &cchValue); // [OUT] size of constant string in chars, 0 for non-strings. + if (FAILED(hr)) + { + goto Error; + } + + printf("\n%S.%S (0x%x)\n", wszClassName, wszName, md); + DoParse((sig_byte *) sigMember, cbSigMember); + + hr = S_OK; + + Cleanup: + return hr; + + Error: + goto Cleanup; + +} + + // Takes an mdMethodDef, prints an intro line, then invokes the parser / printer on its signature and its locals +HRESULT PrintMethodDef(ModuleID moduleID, IMetaDataImport* pMDImport, LPCWSTR wszClassName, mdMethodDef md) +{ + HRESULT hr; + mdTypeDef td; + WCHAR wszMethod[500]; + ULONG cchMethod; + DWORD dwAttr; + PCCOR_SIGNATURE sigParam; + PCCOR_SIGNATURE sigLocal; + ULONG cbSigParam; + ULONG cbSigLocal; + ULONG ulCodeRVA; + DWORD dwImplFlags; + BOOL fMore; + LPCBYTE pMethodHeader = NULL; + ULONG cbMethodSize; + IMAGE_COR_ILMETHOD_TINY* pimt = NULL; + IMAGE_COR_ILMETHOD_FAT* pimf = NULL; + + hr = pMDImport->GetMethodProps(md, // The method for which to get props. + &td, // Put method's class here. + wszMethod, // Put method's name here. + dimensionof(wszMethod), // Size of szMethod buffer in wide chars. + &cchMethod, // Put actual size here + &dwAttr, // Put flags here. + &sigParam, // [OUT] point to the blob value of meta data + &cbSigParam, // [OUT] actual size of signature blob + &ulCodeRVA, // [OUT] codeRVA + &dwImplFlags); // [OUT] Impl. Flags + if (FAILED(hr)) + { + goto Error; + } + + printf("\n%S.%S (0x%x)\n", wszClassName, wszMethod, md); + + // Method prototype signature parse + DoParse((sig_byte *) sigParam, cbSigParam); + + // Method locals signature parse + hr = g_pProfilerInfo->GetILFunctionBody(moduleID, + md, + &pMethodHeader, + &cbMethodSize); + if (FAILED(hr)) + { + goto EndLocal; + } + + // The following odd-looking lines of code decode the method header, ensure + // it is in a format that contains local variables, and then grabs the local + // variable signature out of the header. + + pimt = (IMAGE_COR_ILMETHOD_TINY*) pMethodHeader; + if ((pimt->Flags_CodeSize & (CorILMethod_FormatMask >> 1)) != CorILMethod_FatFormat) + { + goto EndLocal; + } + + pimf = (IMAGE_COR_ILMETHOD_FAT*) pMethodHeader; + if (pimf->LocalVarSigTok == 0) + { + goto EndLocal; + } + + hr = pMDImport->GetSigFromToken(pimf->LocalVarSigTok, + &sigLocal, + &cbSigLocal); + + DoParse((sig_byte *) sigLocal, cbSigLocal); + + EndLocal: + + hr = S_OK; + + Cleanup: + return hr; + + Error: + goto Cleanup; +} + + + // Simple helper to print an intro line for a class +void PrintHeader(LPCWSTR wszClassName, mdTypeDef td, LPCSTR szCategory) +{ + printf("\n--------------------------------------------\n"); + printf("%S (0x%x):\t%s\n", wszClassName, td, szCategory); + printf("--------------------------------------------\n\n"); +} + + + // Combines above functions to print the methods, properties, and fields of a class +HRESULT PrintTypedef(ModuleID moduleID, IMetaDataImport* pMDImport, mdTypeDef td) +{ + HRESULT hr; + HCORENUM hEnum = NULL; + mdMethodDef aMethods[100]; + mdFieldDef aFields[100]; + mdFieldDef aProperties[100]; + ULONG cMethodDefs; + ULONG cFields; + ULONG cProperties; + ULONG i; + WCHAR wszTdName[200]; + ULONG cchTdName; + DWORD dwTypeDefFlags; + mdToken tkExtends; + BOOL fMore; + + hr = pMDImport->GetTypeDefProps(td, // [IN] TypeDef token for inquiry. + wszTdName, // [OUT] Put name here. + dimensionof(wszTdName), // [IN] size of name buffer in wide chars. + &cchTdName, // [OUT] put size of name (wide chars) here. + &dwTypeDefFlags, // [OUT] Put flags here. + &tkExtends); // [OUT] Put base class TypeDef/TypeRef here. + if (FAILED(hr)) + { + goto Error; + } + + PrintHeader(wszTdName, td, "METHODDEFS"); + fMore = TRUE; + while (fMore) + { + hr = pMDImport->EnumMethods(&hEnum, + td, // [IN] TypeDef to scope the enumeration. + aMethods, // [OUT] Put MethodDefs here. + dimensionof(aMethods), // [IN] Max MethodDefs to put. + &cMethodDefs); // [OUT] Put # put here. + if (FAILED(hr)) + { + goto Error; + } + + if (hr == S_FALSE) + { + fMore = FALSE; + } + + for (i=0; i < cMethodDefs; i++) + { + hr = PrintMethodDef(moduleID, pMDImport, wszTdName, aMethods[i]); + if (FAILED(hr)) + { + // do you care? If so, do something about this. + } + } + } + + pMDImport->CloseEnum(hEnum); + hEnum = NULL; + + PrintHeader(wszTdName, td, "FIELDS"); + fMore = TRUE; + while (fMore) + { + hr = pMDImport->EnumFields(&hEnum, + td, + Fields, + dimensionof(aFields), + &cFields); + + if (FAILED(hr)) + { + goto Error; + } + + if (hr == S_FALSE) + { + fMore = FALSE; + } + + for (i=0; i < cFields; i++) + { + hr = PrintField(moduleID, pMDImport, wszTdName, aFields[i]); + if (FAILED(hr)) + { + // do you care? If so, do something about this. + } + } + } + + pMDImport->CloseEnum(hEnum); + hEnum = NULL; + + PrintHeader(wszTdName, td, "PROPERTIES"); + fMore = TRUE; + while (fMore) + { + hr = pMDImport->EnumProperties(&hEnum, + td, + aProperties, + dimensionof(aProperties), + &cProperties); + if (FAILED(hr)) + { + goto Error; + } + + if (hr == S_FALSE) + { + fMore = FALSE; + } + + for (i=0; i < cProperties; i++) + { + hr = PrintProperty(moduleID, pMDImport, wszTdName, aProperties[i]); + if (FAILED(hr)) + { + // do you care? If so, do something about this. + } + } + } + + pMDImport->CloseEnum(hEnum); + hEnum = NULL; + + hr = S_OK; + + Cleanup: + if (hEnum != NULL) + { + pMDImport->CloseEnum(hEnum); + } + return hr; + + Error: + goto Cleanup; +} + + + // Enumerates the typedefs in a module via the metadata interface, and calls PrintTypedef + // on each one +HRESULT PrintMetadata(ModuleID moduleID, IMetaDataImport* pMDImport) +{ + HRESULT hr; + HCORENUM hEnum = NULL; + mdTypeDef aTypeDefs[100]; + ULONG cTypeDefs; + ULONG i; + BOOL fMoreTypeDefs = TRUE; + + while (fMoreTypeDefs) + { + hr = pMDImport->EnumTypeDefs(&hEnum, + aTypeDefs, + dimensionof(aTypeDefs), + &cTypeDefs); + if (FAILED(hr)) + { + goto Error; + } + + if (hr == S_FALSE) + { + fMoreTypeDefs = FALSE; + } + + for (i=0; i < cTypeDefs; i++) + { + hr = PrintTypedef(moduleID, pMDImport, aTypeDefs[i]); + if (FAILED(hr)) + { + // do you care? If so, do something about this. + } + } + } + + hr = S_OK; + + Cleanup: + if (hEnum != NULL) + { + pMDImport->CloseEnum(hEnum); + } + return hr; + + Error: + goto Cleanup; +} + + + // **************************************************************** + // Add this to your profiler's ICorProfilerCallback2::ModuleLoadFinished implementation. + // It is assumed your copy of the ICorProfilerInfo2 interface may be accessed via + // g_pProfilerInfo. Change the code to fit your profiler as appropriate. + // **************************************************************** + // + // As a module gets loaded, this callback implementation initiates the pretty-printer to + // log all the types to stdout. +HRESULT CYourProfImpl::ModuleLoadFinished( ModuleID moduleID, HRESULT hrStatus ) +{ + HRESULT hr; + LPCBYTE pbBaseLoadAddr; + WCHAR wszName[300]; + ULONG cchNameIn = dimensionof(wszName); + ULONG cchNameOut; + AssemblyID assemblyID; + + hr = g_pProfilerInfo->GetModuleInfo(moduleID, + &pbBaseLoadAddr, + cchNameIn, + &cchNameOut, + wszName, + &assemblyID); + if (FAILED(hr)) + { + return hr; + } + + printf("MODULE LOAD FINISHED: %S\n", wszName); + + IMetaDataImport *pMDImport = NULL; + hr = g_pProfilerInfo->GetModuleMetaData(moduleID, + ofRead, + IID_IMetaDataImport, + (IUnknown **)&pMDImport ); + if (FAILED(hr)) + { + return hr; + } + + hr = PrintMetadata(moduleID, pMDImport); + if (FAILED(hr)) + { + // Do any error handling as appropriate + } + + hr = S_OK; + + Cleanup: + return hr; + + Error: + goto Cleanup; +} diff --git a/Documentation/Profiling/davbr-blog-archive/samples/sigparse.cpp b/Documentation/Profiling/davbr-blog-archive/samples/sigparse.cpp index 0a273a044c18..e62bb0021f3d 100644 --- a/Documentation/Profiling/davbr-blog-archive/samples/sigparse.cpp +++ b/Documentation/Profiling/davbr-blog-archive/samples/sigparse.cpp @@ -1 +1,1051 @@ -// This blog post originally appeared on David Broman's blog on 10/13/2005 // Sig ::= MethodDefSig | MethodRefSig | StandAloneMethodSig | FieldSig | PropertySig | LocalVarSig // MethodDefSig ::= [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|GENERIC GenParamCount) ParamCount RetType Param* // MethodRefSig ::= [[HASTHIS] [EXPLICITTHIS]] VARARG ParamCount RetType Param* [SENTINEL Param+] // StandAloneMethodSig ::= [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|C|STDCALL|THISCALL|FASTCALL) // ParamCount RetType Param* [SENTINEL Param+] // FieldSig ::= FIELD CustomMod* Type // PropertySig ::= PROPERTY [HASTHIS] ParamCount CustomMod* Type Param* // LocalVarSig ::= LOCAL_SIG Count (TYPEDBYREF | ([CustomMod] [Constraint])* [BYREF] Type)+ // ------------- // CustomMod ::= ( CMOD_OPT | CMOD_REQD ) ( TypeDefEncoded | TypeRefEncoded ) // Constraint ::= #define ELEMENT_TYPE_PINNED // Param ::= CustomMod* ( TYPEDBYREF | [BYREF] Type ) // RetType ::= CustomMod* ( VOID | TYPEDBYREF | [BYREF] Type ) // Type ::= ( BOOLEAN | CHAR | I1 | U1 | U2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U | // | VALUETYPE TypeDefOrRefEncoded // | CLASS TypeDefOrRefEncoded // | STRING // | OBJECT // | PTR CustomMod* VOID // | PTR CustomMod* Type // | FNPTR MethodDefSig // | FNPTR MethodRefSig // | ARRAY Type ArrayShape // | SZARRAY CustomMod* Type // | GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type* // | VAR Number // | MVAR Number // ArrayShape ::= Rank NumSizes Size* NumLoBounds LoBound* // TypeDefOrRefEncoded ::= TypeDefEncoded | TypeRefEncoded // TypeDefEncoded ::= 32-bit-3-part-encoding-for-typedefs-and-typerefs // TypeRefEncoded ::= 32-bit-3-part-encoding-for-typedefs-and-typerefs // ParamCount ::= 29-bit-encoded-integer // GenArgCount ::= 29-bit-encoded-integer // Count ::= 29-bit-encoded-integer // Rank ::= 29-bit-encoded-integer // NumSizes ::= 29-bit-encoded-integer // Size ::= 29-bit-encoded-integer // NumLoBounds ::= 29-bit-encoded-integer // LoBounds ::= 29-bit-encoded-integer // Number ::= 29-bit-encoded-integer #define ELEMENT_TYPE_END 0x00 //Marks end of a list #define ELEMENT_TYPE_VOID 0x01 #define ELEMENT_TYPE_BOOLEAN 0x02 #define ELEMENT_TYPE_CHAR 0x03 #define ELEMENT_TYPE_I1 0x04 #define ELEMENT_TYPE_U1 0x05 #define ELEMENT_TYPE_I2 0x06 #define ELEMENT_TYPE_U2 0x07 #define ELEMENT_TYPE_I4 0x08 #define ELEMENT_TYPE_U4 0x09 #define ELEMENT_TYPE_I8 0x0a #define ELEMENT_TYPE_U8 0x0b #define ELEMENT_TYPE_R4 0x0c #define ELEMENT_TYPE_R8 0x0d #define ELEMENT_TYPE_STRING 0x0e #define ELEMENT_TYPE_PTR 0x0f // Followed by type #define ELEMENT_TYPE_BYREF 0x10 // Followed by type #define ELEMENT_TYPE_VALUETYPE 0x11 // Followed by TypeDef or TypeRef token #define ELEMENT_TYPE_CLASS 0x12 // Followed by TypeDef or TypeRef token #define ELEMENT_TYPE_VAR 0x13 // Generic parameter in a generic type definition, represented as number #define ELEMENT_TYPE_ARRAY 0x14 // type rank boundsCount bound1 … loCount lo1 … #define ELEMENT_TYPE_GENERICINST 0x15 // Generic type instantiation. Followed by type type-arg-count type-1 ... type-n #define ELEMENT_TYPE_TYPEDBYREF 0x16 #define ELEMENT_TYPE_I 0x18 // System.IntPtr #define ELEMENT_TYPE_U 0x19 // System.UIntPtr #define ELEMENT_TYPE_FNPTR 0x1b // Followed by full method signature #define ELEMENT_TYPE_OBJECT 0x1c // System.Object #define ELEMENT_TYPE_SZARRAY 0x1d // Single-dim array with 0 lower bound #define ELEMENT_TYPE_MVAR 0x1e // Generic parameter in a generic method definition,represented as number #define ELEMENT_TYPE_CMOD_REQD 0x1f // Required modifier : followed by a TypeDef or TypeRef token #define ELEMENT_TYPE_CMOD_OPT 0x20 // Optional modifier : followed by a TypeDef or TypeRef token #define ELEMENT_TYPE_INTERNAL 0x21 // Implemented within the CLI #define ELEMENT_TYPE_MODIFIER 0x40 // Or’d with following element types #define ELEMENT_TYPE_SENTINEL 0x41 // Sentinel for vararg method signature #define ELEMENT_TYPE_PINNED 0x45 // Denotes a local variable that points at a pinned object #define SIG_METHOD_DEFAULT 0x0 // default calling convention #define SIG_METHOD_C 0x1 // C calling convention #define SIG_METHOD_STDCALL 0x2 // Stdcall calling convention #define SIG_METHOD_THISCALL 0x3 // thiscall calling convention #define SIG_METHOD_FASTCALL 0x4 // fastcall calling convention #define SIG_METHOD_VARARG 0x5 // vararg calling convention #define SIG_FIELD 0x6 // encodes a field #define SIG_LOCAL_SIG 0x7 // used for the .locals directive #define SIG_PROPERTY 0x8 // used to encode a property #define SIG_GENERIC 0x10 // used to indicate that the method has one or more generic parameters. #define SIG_HASTHIS 0x20 // used to encode the keyword instance in the calling convention #define SIG_EXPLICITTHIS 0x40 // used to encode the keyword explicit in the calling convention #define SIG_INDEX_TYPE_TYPEDEF 0 // ParseTypeDefOrRefEncoded returns this as the out index type for typedefs #define SIG_INDEX_TYPE_TYPEREF 1 // ParseTypeDefOrRefEncoded returns this as the out index type for typerefs #define SIG_INDEX_TYPE_TYPESPEC 2 // ParseTypeDefOrRefEncoded returns this as the out index type for typespecs typedef unsigned char sig_byte; typedef unsigned char sig_elem_type; typedef unsigned char sig_index_type; typedef unsigned int sig_index; typedef unsigned int sig_count; typedef unsigned int sig_mem_number; class SigParser { private: sig_byte *pbBase; sig_byte *pbCur; sig_byte *pbEnd; public: bool Parse(sig_byte *blob, sig_count len); private: bool ParseByte(sig_byte *pbOut); bool ParseNumber(sig_count *pOut); bool ParseTypeDefOrRefEncoded(sig_index_type *pOutIndexType, sig_index *pOutIndex); bool ParseMethod(sig_elem_type); bool ParseField(sig_elem_type); bool ParseProperty(sig_elem_type); bool ParseLocals(sig_elem_type); bool ParseLocal(); bool ParseOptionalCustomMods(); bool ParseOptionalCustomModsOrConstraint(); bool ParseCustomMod(); bool ParseRetType(); bool ParseType(); bool ParseParam(); bool ParseArrayShape(); protected: // subtype these methods to create your parser side-effects //---------------------------------------------------- // a method with given elem_type virtual void NotifyBeginMethod(sig_elem_type elem_type) {} virtual void NotifyEndMethod() {} // total parameters for the method virtual void NotifyParamCount(sig_count) {} // starting a return type virtual void NotifyBeginRetType() {} virtual void NotifyEndRetType() {} // starting a parameter virtual void NotifyBeginParam() {} virtual void NotifyEndParam() {} // sentinel indication the location of the "..." in the method signature virtual void NotifySentinal() {} // number of generic parameters in this method signature (if any) virtual void NotifyGenericParamCount(sig_count) {} //---------------------------------------------------- // a field with given elem_type virtual void NotifyBeginField(sig_elem_type elem_type) {} virtual void NotifyEndField() {} //---------------------------------------------------- // a block of locals with given elem_type (always just LOCAL_SIG for now) virtual void NotifyBeginLocals(sig_elem_type elem_type) {} virtual void NotifyEndLocals() {} // count of locals with a block virtual void NotifyLocalsCount(sig_count) {} // starting a new local within a local block virtual void NotifyBeginLocal() {} virtual void NotifyEndLocal() {} // the only constraint available to locals at the moment is ELEMENT_TYPE_PINNED virtual void NotifyConstraint(sig_elem_type elem_type) {} //---------------------------------------------------- // a property with given element type virtual void NotifyBeginProperty(sig_elem_type elem_type) {} virtual void NotifyEndProperty() {} //---------------------------------------------------- // starting array shape information for array types virtual void NotifyBeginArrayShape() {} virtual void NotifyEndArrayShape() {} // array rank (total number of dimensions) virtual void NotifyRank(sig_count) {} // number of dimensions with specified sizes followed by the size of each virtual void NotifyNumSizes(sig_count) {} virtual void NotifySize(sig_count) {} // BUG BUG lower bounds can be negative, how can this be encoded? // number of dimensions with specified lower bounds followed by lower bound of each virtual void NotifyNumLoBounds(sig_count) {} virtual void NotifyLoBound(sig_count) {} //---------------------------------------------------- // starting a normal type (occurs in many contexts such as param, field, local, etc) virtual void NotifyBeginType() {}; virtual void NotifyEndType() {}; virtual void NotifyTypedByref() {} // the type has the 'byref' modifier on it -- this normally proceeds the type definition in the context // the type is used, so for instance a parameter might have the byref modifier on it // so this happens before the BeginType in that context virtual void NotifyByref() {} // the type is "VOID" (this has limited uses, function returns and void pointer) virtual void NotifyVoid() {} // the type has the indicated custom modifiers (which can be optional or required) virtual void NotifyCustomMod(sig_elem_type cmod, sig_index_type indexType, sig_index index) {} // the type is a simple type, the elem_type defines it fully virtual void NotifyTypeSimple(sig_elem_type elem_type) {} // the type is specified by the given index of the given index type (normally a type index in the type metadata) // this callback is normally qualified by other ones such as NotifyTypeClass or NotifyTypeValueType virtual void NotifyTypeDefOrRef(sig_index_type indexType, int index) {} // the type is an instance of a generic // elem_type indicates value_type or class // indexType and index indicate the metadata for the type in question // number indicates the number of type specifications for the generic types that will follow virtual void NotifyTypeGenericInst(sig_elem_type elem_type, sig_index_type indexType, sig_index index, sig_mem_number number) {} // the type is the type of the nth generic type parameter for the class virtual void NotifyTypeGenericTypeVariable(sig_mem_number number) {} // the type is the type of the nth generic type parameter for the member virtual void NotifyTypeGenericMemberVariable(sig_mem_number number) {} // the type will be a value type virtual void NotifyTypeValueType() {} // the type will be a class virtual void NotifyTypeClass() {} // the type is a pointer to a type (nested type notifications follow) virtual void NotifyTypePointer() {} // the type is a function pointer, followed by the type of the function virtual void NotifyTypeFunctionPointer() {} // the type is an array, this is followed by the array shape, see above, as well as modifiers and element type virtual void NotifyTypeArray() {} // the type is a simple zero-based array, this has no shape but does have custom modifiers and element type virtual void NotifyTypeSzArray() {} }; //---------------------------------------------------- bool SigParser::Parse(sig_byte *pb, sig_count cbBuffer) { pbBase = pb; pbCur = pb; pbEnd = pbBase + cbBuffer; sig_elem_type elem_type; if (!ParseByte(&elem_type)) return false; switch (elem_type & 0xf) { case SIG_METHOD_DEFAULT: // default calling convention case SIG_METHOD_C: // C calling convention case SIG_METHOD_STDCALL: // Stdcall calling convention case SIG_METHOD_THISCALL: // thiscall calling convention case SIG_METHOD_FASTCALL: // fastcall calling convention case SIG_METHOD_VARARG: // vararg calling convention return ParseMethod(elem_type); break; case SIG_FIELD: // encodes a field return ParseField(elem_type); break; case SIG_LOCAL_SIG: // used for the .locals directive return ParseLocals(elem_type); break; case SIG_PROPERTY: // used to encode a property return ParseProperty(elem_type); break; default: // unknown signature break; } return false; } bool SigParser::ParseByte(sig_byte *pbOut) { if (pbCur < pbEnd) { *pbOut = *pbCur; pbCur++; return true; } return false; } bool SigParser::ParseMethod(sig_elem_type elem_type) { // MethodDefSig ::= [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|GENERIC GenParamCount) // ParamCount RetType Param* [SENTINEL Param+] NotifyBeginMethod(elem_type); sig_count gen_param_count; sig_count param_count; if (elem_type & SIG_GENERIC) { if (!ParseNumber(&gen_param_count)) { return false; } NotifyGenericParamCount(gen_param_count); } if (!ParseNumber(¶m_count)) { return false; } NotifyParamCount(param_count); if (!ParseRetType()) { return false; } bool fEncounteredSentinal = false; for (sig_count i = 0; i < param_count; i++) { if (pbCur >= pbEnd) { return false; } if (*pbCur == ELEMENT_TYPE_SENTINEL) { if (fEncounteredSentinal) { return false; } fEncounteredSentinal = true; NotifySentinal(); pbCur++; } if (!ParseParam()) { return false; } } NotifyEndMethod(); return true; } bool SigParser::ParseField(sig_elem_type elem_type) { // FieldSig ::= FIELD CustomMod* Type NotifyBeginField(elem_type); if (!ParseOptionalCustomMods()) { return false; } if (!ParseType()) { return false; } NotifyEndField(); return true; } bool SigParser::ParseProperty(sig_elem_type elem_type) { // PropertySig ::= PROPERTY [HASTHIS] ParamCount CustomMod* Type Param* NotifyBeginProperty(elem_type); sig_count param_count; if (!ParseNumber(¶m_count)) { return false; } NotifyParamCount(param_count); if (!ParseOptionalCustomMods()) { return false; } if (!ParseType()) { return false; } for (sig_count i = 0; i < param_count; i++) { if (!ParseParam()) { return false; } } NotifyEndProperty(); return true; } bool SigParser::ParseLocals(sig_elem_type elem_type) { // LocalVarSig ::= LOCAL_SIG Count (TYPEDBYREF | ([CustomMod] [Constraint])* [BYREF] Type)+ NotifyBeginLocals(elem_type); sig_count local_count; if (!ParseNumber(&local_count)) { return false; } NotifyLocalsCount(local_count); for (sig_count i = 0; i < local_count; i++) { if (!ParseLocal()) { return false; } } NotifyEndLocals(); return true; } bool SigParser::ParseLocal() { //TYPEDBYREF | ([CustomMod] [Constraint])* [BYREF] Type NotifyBeginLocal(); if (pbCur >= pbEnd) { return false; } if (*pbCur == ELEMENT_TYPE_TYPEDBYREF) { NotifyTypedByref(); pbCur++; goto Success; } if (!ParseOptionalCustomModsOrConstraint()) { return false; } if (pbCur >= pbEnd) { return false; } if (*pbCur == ELEMENT_TYPE_BYREF) { NotifyByref(); pbCur++; } if (!ParseType()) { return false; } Success: NotifyEndLocal(); return true; } bool SigParser::ParseOptionalCustomModsOrConstraint() { for (;;) { if (pbCur >= pbEnd) { return true; } switch (*pbCur) { case ELEMENT_TYPE_CMOD_OPT: case ELEMENT_TYPE_CMOD_REQD: if (!ParseCustomMod()) { return false; } break; case ELEMENT_TYPE_PINNED: NotifyConstraint(*pbCur); pbCur++; break; default: return true; } } return false; } bool SigParser::ParseOptionalCustomMods() { for (;;) { if (pbCur >= pbEnd) { return true; } switch (*pbCur) { case ELEMENT_TYPE_CMOD_OPT: case ELEMENT_TYPE_CMOD_REQD: if (!ParseCustomMod()) { return false; } break; default: return true; } } return false; } bool SigParser::ParseCustomMod() { sig_elem_type cmod = 0; sig_index index; sig_index_type indexType; if (!ParseByte(&cmod)) { return false; } if (cmod == ELEMENT_TYPE_CMOD_OPT || cmod == ELEMENT_TYPE_CMOD_REQD) { if (!ParseTypeDefOrRefEncoded(&indexType, &index)) { return false; } NotifyCustomMod(cmod, indexType, index); return true; } return false; } bool SigParser::ParseParam() { // Param ::= CustomMod* ( TYPEDBYREF | [BYREF] Type ) NotifyBeginParam(); if (!ParseOptionalCustomMods()) { return false; } if (pbCur >= pbEnd) { return false; } if (*pbCur == ELEMENT_TYPE_TYPEDBYREF) { NotifyTypedByref(); pbCur++; goto Success; } if (*pbCur == ELEMENT_TYPE_BYREF) { NotifyByref(); pbCur++; } if (!ParseType()) { return false; } Success: NotifyEndParam(); return true; } bool SigParser::ParseRetType() { // RetType ::= CustomMod* ( VOID | TYPEDBYREF | [BYREF] Type ) NotifyBeginRetType(); if (!ParseOptionalCustomMods()) { return false; } if (pbCur >= pbEnd) { return false; } if (*pbCur == ELEMENT_TYPE_TYPEDBYREF) { NotifyTypedByref(); pbCur++; goto Success; } if (*pbCur == ELEMENT_TYPE_VOID) { NotifyVoid(); pbCur++; goto Success; } if (*pbCur == ELEMENT_TYPE_BYREF) { NotifyByref(); pbCur++; } if (!ParseType()) { return false; } Success: NotifyEndRetType(); return true; } bool SigParser::ParseArrayShape() { sig_count rank; sig_count numsizes; sig_count size; // ArrayShape ::= Rank NumSizes Size* NumLoBounds LoBound* NotifyBeginArrayShape(); if (!ParseNumber(&rank)) { return false; } NotifyRank(rank); if (!ParseNumber(&numsizes)) { return false; } NotifyNumSizes(numsizes); for (sig_count i = 0; i < numsizes; i++) { if (!ParseNumber(&size)) { return false; } NotifySize(size); } if (!ParseNumber(&numsizes)) { return false; } NotifyNumLoBounds(numsizes); for (sig_count i = 0; i < numsizes; i++) { if (!ParseNumber(&size)) { return false; } NotifyLoBound(size); } NotifyEndArrayShape(); return true; } bool SigParser::ParseType() { // Type ::= ( BOOLEAN | CHAR | I1 | U1 | U2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U | // | VALUETYPE TypeDefOrRefEncoded // | CLASS TypeDefOrRefEncoded // | STRING // | OBJECT // | PTR CustomMod* VOID // | PTR CustomMod* Type // | FNPTR MethodDefSig // | FNPTR MethodRefSig // | ARRAY Type ArrayShape // | SZARRAY CustomMod* Type // | GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * // | VAR Number // | MVAR Number NotifyBeginType(); sig_elem_type elem_type; sig_index index; sig_mem_number number; sig_index_type indexType; if (!ParseByte(&elem_type)) return false; switch (elem_type) { case ELEMENT_TYPE_BOOLEAN: case ELEMENT_TYPE_CHAR: case ELEMENT_TYPE_I1: case ELEMENT_TYPE_U1: case ELEMENT_TYPE_U2: case ELEMENT_TYPE_I2: case ELEMENT_TYPE_I4: case ELEMENT_TYPE_U4: case ELEMENT_TYPE_I8: case ELEMENT_TYPE_U8: case ELEMENT_TYPE_R4: case ELEMENT_TYPE_R8: case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: case ELEMENT_TYPE_STRING: case ELEMENT_TYPE_OBJECT: // simple types NotifyTypeSimple(elem_type); break; case ELEMENT_TYPE_PTR: // PTR CustomMod* VOID // PTR CustomMod* Type NotifyTypePointer(); if (!ParseOptionalCustomMods()) { return false; } if (pbCur >= pbEnd) { return false; } if (*pbCur == ELEMENT_TYPE_VOID) { pbCur++; NotifyVoid(); break; } if (!ParseType()) { return false; } break; case ELEMENT_TYPE_CLASS: // CLASS TypeDefOrRefEncoded NotifyTypeClass(); if (!ParseTypeDefOrRefEncoded(&indexType, &index)) { return false; } NotifyTypeDefOrRef(indexType, index); break; case ELEMENT_TYPE_VALUETYPE: //VALUETYPE TypeDefOrRefEncoded NotifyTypeValueType(); if (!ParseTypeDefOrRefEncoded(&indexType, &index)) { return false; } NotifyTypeDefOrRef(indexType, index); break; case ELEMENT_TYPE_FNPTR: // FNPTR MethodDefSig // FNPTR MethodRefSig NotifyTypeFunctionPointer(); if (!ParseByte(&elem_type)) { return false; } if (!ParseMethod(elem_type)) { return false; } break; case ELEMENT_TYPE_ARRAY: // ARRAY Type ArrayShape NotifyTypeArray(); if (!ParseType()) { return false; } if (!ParseArrayShape()) { return false; } break; case ELEMENT_TYPE_SZARRAY: // SZARRAY CustomMod* Type NotifyTypeSzArray(); if (!ParseOptionalCustomMods()) { return false; } if (!ParseType()) { return false; } break; case ELEMENT_TYPE_GENERICINST: // GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * if (!ParseByte(&elem_type)) { return false; } if (elem_type != ELEMENT_TYPE_CLASS && elem_type != ELEMENT_TYPE_VALUETYPE) { return false; } if (!ParseTypeDefOrRefEncoded(&indexType, &index)) { return false; } if (!ParseNumber(&number)) { return false; } NotifyTypeGenericInst(elem_type, indexType, index, number); { for (sig_mem_number i=0; i < number; i++) { if (!ParseType()) { return false; } } } break; case ELEMENT_TYPE_VAR: // VAR Number if (!ParseNumber(&number)) { return false; } NotifyTypeGenericTypeVariable(number); break; case ELEMENT_TYPE_MVAR: // MVAR Number if (!ParseNumber(&number)) { return false; } NotifyTypeGenericMemberVariable(number); break; } NotifyEndType(); return true; } bool SigParser::ParseTypeDefOrRefEncoded(sig_index_type *pIndexTypeOut, sig_index *pIndexOut) { // parse an encoded typedef or typeref sig_count encoded = 0; if (!ParseNumber(&encoded)) { return false; } *pIndexTypeOut = (sig_index_type) (encoded & 0x3); *pIndexOut = (encoded >> 2); return true; } bool SigParser::ParseNumber(sig_count *pOut) { // parse the variable length number format (0-4 bytes) sig_byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; // at least one byte in the encoding, read that if (!ParseByte(&b1)) { return false; } if (b1 == 0xff) { // special encoding of 'NULL' // not sure what this means as a number, don't expect to see it except for string lengths // which we don't encounter anyway so calling it an error return false; } // early out on 1 byte encoding if ( (b1 & 0x80) == 0) { *pOut = (int)b1; return true; } // now at least 2 bytes in the encoding, read 2nd byte if (!ParseByte(&b2)) { return false; } // early out on 2 byte encoding if ( (b1 & 0x40) == 0) { *pOut = (((b1 & 0x3f) << 8) | b2); return true; } // must be a 4 byte encoding if ( (b1 & 0x20) != 0) { // 4 byte encoding has this bit clear -- error if not return false; } if (!ParseByte(&b3)) { return false; } if (!ParseByte(&b4)) { return false; } *pOut = ((b1 & 0x1f) << 24) | (b2 << 16) | (b3 << 8) | b4; return true; } \ No newline at end of file +// This blog post originally appeared on David Broman's blog on 10/13/2005 + +// Sig ::= MethodDefSig | MethodRefSig | StandAloneMethodSig | FieldSig | PropertySig | LocalVarSig +// MethodDefSig ::= [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|GENERIC GenParamCount) ParamCount RetType Param* +// MethodRefSig ::= [[HASTHIS] [EXPLICITTHIS]] VARARG ParamCount RetType Param* [SENTINEL Param+] +// StandAloneMethodSig ::= [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|C|STDCALL|THISCALL|FASTCALL) +// ParamCount RetType Param* [SENTINEL Param+] +// FieldSig ::= FIELD CustomMod* Type +// PropertySig ::= PROPERTY [HASTHIS] ParamCount CustomMod* Type Param* +// LocalVarSig ::= LOCAL_SIG Count (TYPEDBYREF | ([CustomMod] [Constraint])* [BYREF] Type)+ + +// ------------- + +// CustomMod ::= ( CMOD_OPT | CMOD_REQD ) ( TypeDefEncoded | TypeRefEncoded ) +// Constraint ::= #define ELEMENT_TYPE_PINNED +// Param ::= CustomMod* ( TYPEDBYREF | [BYREF] Type ) +// RetType ::= CustomMod* ( VOID | TYPEDBYREF | [BYREF] Type ) +// Type ::= ( BOOLEAN | CHAR | I1 | U1 | U2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U | +// | VALUETYPE TypeDefOrRefEncoded +// | CLASS TypeDefOrRefEncoded +// | STRING +// | OBJECT +// | PTR CustomMod* VOID +// | PTR CustomMod* Type +// | FNPTR MethodDefSig +// | FNPTR MethodRefSig +// | ARRAY Type ArrayShape +// | SZARRAY CustomMod* Type +// | GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type* +// | VAR Number +// | MVAR Number + +// ArrayShape ::= Rank NumSizes Size* NumLoBounds LoBound* + +// TypeDefOrRefEncoded ::= TypeDefEncoded | TypeRefEncoded +// TypeDefEncoded ::= 32-bit-3-part-encoding-for-typedefs-and-typerefs +// TypeRefEncoded ::= 32-bit-3-part-encoding-for-typedefs-and-typerefs + +// ParamCount ::= 29-bit-encoded-integer +// GenArgCount ::= 29-bit-encoded-integer +// Count ::= 29-bit-encoded-integer +// Rank ::= 29-bit-encoded-integer +// NumSizes ::= 29-bit-encoded-integer +// Size ::= 29-bit-encoded-integer +// NumLoBounds ::= 29-bit-encoded-integer +// LoBounds ::= 29-bit-encoded-integer +// Number ::= 29-bit-encoded-integer + + + #define ELEMENT_TYPE_END 0x00 //Marks end of a list + #define ELEMENT_TYPE_VOID 0x01 + #define ELEMENT_TYPE_BOOLEAN 0x02 + #define ELEMENT_TYPE_CHAR 0x03 + #define ELEMENT_TYPE_I1 0x04 + #define ELEMENT_TYPE_U1 0x05 + #define ELEMENT_TYPE_I2 0x06 + #define ELEMENT_TYPE_U2 0x07 + #define ELEMENT_TYPE_I4 0x08 + #define ELEMENT_TYPE_U4 0x09 + #define ELEMENT_TYPE_I8 0x0a + #define ELEMENT_TYPE_U8 0x0b + #define ELEMENT_TYPE_R4 0x0c + #define ELEMENT_TYPE_R8 0x0d + #define ELEMENT_TYPE_STRING 0x0e + #define ELEMENT_TYPE_PTR 0x0f // Followed by type + #define ELEMENT_TYPE_BYREF 0x10 // Followed by type + #define ELEMENT_TYPE_VALUETYPE 0x11 // Followed by TypeDef or TypeRef token + #define ELEMENT_TYPE_CLASS 0x12 // Followed by TypeDef or TypeRef token + #define ELEMENT_TYPE_VAR 0x13 // Generic parameter in a generic type definition, represented as number + #define ELEMENT_TYPE_ARRAY 0x14 // type rank boundsCount bound1 … loCount lo1 … + #define ELEMENT_TYPE_GENERICINST 0x15 // Generic type instantiation. Followed by type type-arg-count type-1 ... type-n + #define ELEMENT_TYPE_TYPEDBYREF 0x16 + #define ELEMENT_TYPE_I 0x18 // System.IntPtr + #define ELEMENT_TYPE_U 0x19 // System.UIntPtr + #define ELEMENT_TYPE_FNPTR 0x1b // Followed by full method signature + #define ELEMENT_TYPE_OBJECT 0x1c // System.Object + #define ELEMENT_TYPE_SZARRAY 0x1d // Single-dim array with 0 lower bound + + #define ELEMENT_TYPE_MVAR 0x1e // Generic parameter in a generic method definition,represented as number + #define ELEMENT_TYPE_CMOD_REQD 0x1f // Required modifier : followed by a TypeDef or TypeRef token + #define ELEMENT_TYPE_CMOD_OPT 0x20 // Optional modifier : followed by a TypeDef or TypeRef token + #define ELEMENT_TYPE_INTERNAL 0x21 // Implemented within the CLI + #define ELEMENT_TYPE_MODIFIER 0x40 // Or’d with following element types + #define ELEMENT_TYPE_SENTINEL 0x41 // Sentinel for vararg method signature + #define ELEMENT_TYPE_PINNED 0x45 // Denotes a local variable that points at a pinned object + + #define SIG_METHOD_DEFAULT 0x0 // default calling convention + #define SIG_METHOD_C 0x1 // C calling convention + #define SIG_METHOD_STDCALL 0x2 // Stdcall calling convention + #define SIG_METHOD_THISCALL 0x3 // thiscall calling convention + #define SIG_METHOD_FASTCALL 0x4 // fastcall calling convention + #define SIG_METHOD_VARARG 0x5 // vararg calling convention + #define SIG_FIELD 0x6 // encodes a field + #define SIG_LOCAL_SIG 0x7 // used for the .locals directive + #define SIG_PROPERTY 0x8 // used to encode a property + + + #define SIG_GENERIC 0x10 // used to indicate that the method has one or more generic parameters. + #define SIG_HASTHIS 0x20 // used to encode the keyword instance in the calling convention + #define SIG_EXPLICITTHIS 0x40 // used to encode the keyword explicit in the calling convention + + #define SIG_INDEX_TYPE_TYPEDEF 0 // ParseTypeDefOrRefEncoded returns this as the out index type for typedefs + #define SIG_INDEX_TYPE_TYPEREF 1 // ParseTypeDefOrRefEncoded returns this as the out index type for typerefs + #define SIG_INDEX_TYPE_TYPESPEC 2 // ParseTypeDefOrRefEncoded returns this as the out index type for typespecs + + +typedef unsigned char sig_byte; +typedef unsigned char sig_elem_type; +typedef unsigned char sig_index_type; +typedef unsigned int sig_index; +typedef unsigned int sig_count; +typedef unsigned int sig_mem_number; + +class SigParser +{ +private: + sig_byte *pbBase; + sig_byte *pbCur; + sig_byte *pbEnd; + +public: + bool Parse(sig_byte *blob, sig_count len); + +private: + bool ParseByte(sig_byte *pbOut); + bool ParseNumber(sig_count *pOut); + bool ParseTypeDefOrRefEncoded(sig_index_type *pOutIndexType, sig_index *pOutIndex); + + bool ParseMethod(sig_elem_type); + bool ParseField(sig_elem_type); + bool ParseProperty(sig_elem_type); + bool ParseLocals(sig_elem_type); + bool ParseLocal(); + bool ParseOptionalCustomMods(); + bool ParseOptionalCustomModsOrConstraint(); + bool ParseCustomMod(); + bool ParseRetType(); + bool ParseType(); + bool ParseParam(); + bool ParseArrayShape(); + +protected: + + // subtype these methods to create your parser side-effects + + //---------------------------------------------------- + + // a method with given elem_type + virtual void NotifyBeginMethod(sig_elem_type elem_type) {} + virtual void NotifyEndMethod() {} + + // total parameters for the method + virtual void NotifyParamCount(sig_count) {} + + // starting a return type + virtual void NotifyBeginRetType() {} + virtual void NotifyEndRetType() {} + + // starting a parameter + virtual void NotifyBeginParam() {} + virtual void NotifyEndParam() {} + + // sentinel indication the location of the "..." in the method signature + virtual void NotifySentinal() {} + + // number of generic parameters in this method signature (if any) + virtual void NotifyGenericParamCount(sig_count) {} + + //---------------------------------------------------- + + // a field with given elem_type + virtual void NotifyBeginField(sig_elem_type elem_type) {} + virtual void NotifyEndField() {} + + //---------------------------------------------------- + + // a block of locals with given elem_type (always just LOCAL_SIG for now) + virtual void NotifyBeginLocals(sig_elem_type elem_type) {} + virtual void NotifyEndLocals() {} + + // count of locals with a block + virtual void NotifyLocalsCount(sig_count) {} + + // starting a new local within a local block + virtual void NotifyBeginLocal() {} + virtual void NotifyEndLocal() {} + + // the only constraint available to locals at the moment is ELEMENT_TYPE_PINNED + virtual void NotifyConstraint(sig_elem_type elem_type) {} + + + //---------------------------------------------------- + + // a property with given element type + virtual void NotifyBeginProperty(sig_elem_type elem_type) {} + virtual void NotifyEndProperty() {} + + //---------------------------------------------------- + + // starting array shape information for array types + virtual void NotifyBeginArrayShape() {} + virtual void NotifyEndArrayShape() {} + + // array rank (total number of dimensions) + virtual void NotifyRank(sig_count) {} + + // number of dimensions with specified sizes followed by the size of each + virtual void NotifyNumSizes(sig_count) {} + virtual void NotifySize(sig_count) {} + + // BUG BUG lower bounds can be negative, how can this be encoded? + // number of dimensions with specified lower bounds followed by lower bound of each + virtual void NotifyNumLoBounds(sig_count) {} + virtual void NotifyLoBound(sig_count) {} + + //---------------------------------------------------- + + + // starting a normal type (occurs in many contexts such as param, field, local, etc) + virtual void NotifyBeginType() {}; + virtual void NotifyEndType() {}; + + virtual void NotifyTypedByref() {} + + // the type has the 'byref' modifier on it -- this normally proceeds the type definition in the context + // the type is used, so for instance a parameter might have the byref modifier on it + // so this happens before the BeginType in that context + virtual void NotifyByref() {} + + // the type is "VOID" (this has limited uses, function returns and void pointer) + virtual void NotifyVoid() {} + + // the type has the indicated custom modifiers (which can be optional or required) + virtual void NotifyCustomMod(sig_elem_type cmod, sig_index_type indexType, sig_index index) {} + + // the type is a simple type, the elem_type defines it fully + virtual void NotifyTypeSimple(sig_elem_type elem_type) {} + + // the type is specified by the given index of the given index type (normally a type index in the type metadata) + // this callback is normally qualified by other ones such as NotifyTypeClass or NotifyTypeValueType + virtual void NotifyTypeDefOrRef(sig_index_type indexType, int index) {} + + // the type is an instance of a generic + // elem_type indicates value_type or class + // indexType and index indicate the metadata for the type in question + // number indicates the number of type specifications for the generic types that will follow + virtual void NotifyTypeGenericInst(sig_elem_type elem_type, sig_index_type indexType, sig_index index, sig_mem_number number) {} + + // the type is the type of the nth generic type parameter for the class + virtual void NotifyTypeGenericTypeVariable(sig_mem_number number) {} + + // the type is the type of the nth generic type parameter for the member + virtual void NotifyTypeGenericMemberVariable(sig_mem_number number) {} + + // the type will be a value type + virtual void NotifyTypeValueType() {} + + // the type will be a class + virtual void NotifyTypeClass() {} + + // the type is a pointer to a type (nested type notifications follow) + virtual void NotifyTypePointer() {} + + // the type is a function pointer, followed by the type of the function + virtual void NotifyTypeFunctionPointer() {} + + // the type is an array, this is followed by the array shape, see above, as well as modifiers and element type + virtual void NotifyTypeArray() {} + + // the type is a simple zero-based array, this has no shape but does have custom modifiers and element type + virtual void NotifyTypeSzArray() {} +}; + + //---------------------------------------------------- + + +bool SigParser::Parse(sig_byte *pb, sig_count cbBuffer) +{ + pbBase = pb; + pbCur = pb; + pbEnd = pbBase + cbBuffer; + + sig_elem_type elem_type; + + if (!ParseByte(&elem_type)) + return false; + + switch (elem_type & 0xf) + { + case SIG_METHOD_DEFAULT: // default calling convention + case SIG_METHOD_C: // C calling convention + case SIG_METHOD_STDCALL: // Stdcall calling convention + case SIG_METHOD_THISCALL: // thiscall calling convention + case SIG_METHOD_FASTCALL: // fastcall calling convention + case SIG_METHOD_VARARG: // vararg calling convention + return ParseMethod(elem_type); + break; + + case SIG_FIELD: // encodes a field + return ParseField(elem_type); + break; + + case SIG_LOCAL_SIG: // used for the .locals directive + return ParseLocals(elem_type); + break; + + case SIG_PROPERTY: // used to encode a property + return ParseProperty(elem_type); + break; + + default: + // unknown signature + break; + } + + return false; +} + + +bool SigParser::ParseByte(sig_byte *pbOut) +{ + if (pbCur < pbEnd) + { + *pbOut = *pbCur; + pbCur++; + return true; + } + + return false; +} + + +bool SigParser::ParseMethod(sig_elem_type elem_type) +{ + // MethodDefSig ::= [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|GENERIC GenParamCount) + // ParamCount RetType Param* [SENTINEL Param+] + + NotifyBeginMethod(elem_type); + + sig_count gen_param_count; + sig_count param_count; + + if (elem_type & SIG_GENERIC) + { + if (!ParseNumber(&gen_param_count)) + { + return false; + } + + NotifyGenericParamCount(gen_param_count); + } + + if (!ParseNumber(¶m_count)) + { + return false; + } + + NotifyParamCount(param_count); + + if (!ParseRetType()) + { + return false; + } + + bool fEncounteredSentinal = false; + + for (sig_count i = 0; i < param_count; i++) + { + if (pbCur >= pbEnd) + { + return false; + } + + if (*pbCur == ELEMENT_TYPE_SENTINEL) + { + if (fEncounteredSentinal) + { + return false; + } + + fEncounteredSentinal = true; + NotifySentinal(); + pbCur++; + } + + if (!ParseParam()) + { + return false; + } + } + + NotifyEndMethod(); + + return true; +} + + +bool SigParser::ParseField(sig_elem_type elem_type) +{ + // FieldSig ::= FIELD CustomMod* Type + + NotifyBeginField(elem_type); + + if (!ParseOptionalCustomMods()) + { + return false; + } + + if (!ParseType()) + { + return false; + } + + NotifyEndField(); + + return true; +} + + +bool SigParser::ParseProperty(sig_elem_type elem_type) +{ + // PropertySig ::= PROPERTY [HASTHIS] ParamCount CustomMod* Type Param* + + NotifyBeginProperty(elem_type); + + sig_count param_count; + + if (!ParseNumber(¶m_count)) + { + return false; + } + + NotifyParamCount(param_count); + + if (!ParseOptionalCustomMods()) + { + return false; + } + + if (!ParseType()) + { + return false; + } + + for (sig_count i = 0; i < param_count; i++) + { + if (!ParseParam()) + { + return false; + } + } + + NotifyEndProperty(); + + return true; +} + + +bool SigParser::ParseLocals(sig_elem_type elem_type) +{ + // LocalVarSig ::= LOCAL_SIG Count (TYPEDBYREF | ([CustomMod] [Constraint])* [BYREF] Type)+ + + NotifyBeginLocals(elem_type); + + sig_count local_count; + + if (!ParseNumber(&local_count)) + { + return false; + } + + NotifyLocalsCount(local_count); + + for (sig_count i = 0; i < local_count; i++) + { + if (!ParseLocal()) + { + return false; + } + } + + NotifyEndLocals(); + + return true; +} + + +bool SigParser::ParseLocal() +{ + //TYPEDBYREF | ([CustomMod] [Constraint])* [BYREF] Type + NotifyBeginLocal(); + + if (pbCur >= pbEnd) + { + return false; + } + + if (*pbCur == ELEMENT_TYPE_TYPEDBYREF) + { + NotifyTypedByref(); + pbCur++; + goto Success; + } + + if (!ParseOptionalCustomModsOrConstraint()) + { + return false; + } + + if (pbCur >= pbEnd) + { + return false; + } + + if (*pbCur == ELEMENT_TYPE_BYREF) + { + NotifyByref(); + pbCur++; + } + + if (!ParseType()) + { + return false; + } + + Success: + NotifyEndLocal(); + return true; +} + + +bool SigParser::ParseOptionalCustomModsOrConstraint() +{ + for (;;) + { + if (pbCur >= pbEnd) + { + return true; + } + + switch (*pbCur) + { + case ELEMENT_TYPE_CMOD_OPT: + case ELEMENT_TYPE_CMOD_REQD: + if (!ParseCustomMod()) + { + return false; + } + break; + + case ELEMENT_TYPE_PINNED: + NotifyConstraint(*pbCur); + pbCur++; + break; + + default: + return true; + } + } + + return false; +} + + +bool SigParser::ParseOptionalCustomMods() +{ + for (;;) + { + if (pbCur >= pbEnd) + { + return true; + } + + switch (*pbCur) + { + case ELEMENT_TYPE_CMOD_OPT: + case ELEMENT_TYPE_CMOD_REQD: + if (!ParseCustomMod()) + { + return false; + } + break; + + default: + return true; + } + } + + return false; +} + + + +bool SigParser::ParseCustomMod() +{ + sig_elem_type cmod = 0; + sig_index index; + sig_index_type indexType; + + if (!ParseByte(&cmod)) + { + return false; + } + + if (cmod == ELEMENT_TYPE_CMOD_OPT || cmod == ELEMENT_TYPE_CMOD_REQD) + { + if (!ParseTypeDefOrRefEncoded(&indexType, &index)) + { + return false; + } + + NotifyCustomMod(cmod, indexType, index); + return true; + } + + return false; +} + + +bool SigParser::ParseParam() +{ + // Param ::= CustomMod* ( TYPEDBYREF | [BYREF] Type ) + + NotifyBeginParam(); + + if (!ParseOptionalCustomMods()) + { + return false; + } + + if (pbCur >= pbEnd) + { + return false; + } + + if (*pbCur == ELEMENT_TYPE_TYPEDBYREF) + { + NotifyTypedByref(); + pbCur++; + goto Success; + } + + if (*pbCur == ELEMENT_TYPE_BYREF) + { + NotifyByref(); + pbCur++; + } + + if (!ParseType()) + { + return false; + } + + Success: + NotifyEndParam(); + return true; +} + + +bool SigParser::ParseRetType() +{ + // RetType ::= CustomMod* ( VOID | TYPEDBYREF | [BYREF] Type ) + + NotifyBeginRetType(); + + if (!ParseOptionalCustomMods()) + { + return false; + } + + if (pbCur >= pbEnd) + { + return false; + } + + if (*pbCur == ELEMENT_TYPE_TYPEDBYREF) + { + NotifyTypedByref(); + pbCur++; + goto Success; + } + + if (*pbCur == ELEMENT_TYPE_VOID) + { + NotifyVoid(); + pbCur++; + goto Success; + } + + if (*pbCur == ELEMENT_TYPE_BYREF) + { + NotifyByref(); + pbCur++; + } + + if (!ParseType()) + { + return false; + } + + Success: + NotifyEndRetType(); + return true; +} + +bool SigParser::ParseArrayShape() +{ + sig_count rank; + sig_count numsizes; + sig_count size; + + // ArrayShape ::= Rank NumSizes Size* NumLoBounds LoBound* + NotifyBeginArrayShape(); + if (!ParseNumber(&rank)) + { + return false; + } + + NotifyRank(rank); + + if (!ParseNumber(&numsizes)) + { + return false; + } + + NotifyNumSizes(numsizes); + + for (sig_count i = 0; i < numsizes; i++) + { + if (!ParseNumber(&size)) + { + return false; + } + + NotifySize(size); + } + + if (!ParseNumber(&numsizes)) + { + return false; + } + + NotifyNumLoBounds(numsizes); + + for (sig_count i = 0; i < numsizes; i++) + { + if (!ParseNumber(&size)) + { + return false; + } + + NotifyLoBound(size); + } + + NotifyEndArrayShape(); + return true; +} + +bool SigParser::ParseType() +{ + // Type ::= ( BOOLEAN | CHAR | I1 | U1 | U2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U | + // | VALUETYPE TypeDefOrRefEncoded + // | CLASS TypeDefOrRefEncoded + // | STRING + // | OBJECT + // | PTR CustomMod* VOID + // | PTR CustomMod* Type + // | FNPTR MethodDefSig + // | FNPTR MethodRefSig + // | ARRAY Type ArrayShape + // | SZARRAY CustomMod* Type + // | GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * + // | VAR Number + // | MVAR Number + + NotifyBeginType(); + + sig_elem_type elem_type; + sig_index index; + sig_mem_number number; + sig_index_type indexType; + + if (!ParseByte(&elem_type)) + return false; + + switch (elem_type) + { + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_R8: + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + case ELEMENT_TYPE_STRING: + case ELEMENT_TYPE_OBJECT: + // simple types + NotifyTypeSimple(elem_type); + break; + + case ELEMENT_TYPE_PTR: + // PTR CustomMod* VOID + // PTR CustomMod* Type + + NotifyTypePointer(); + + if (!ParseOptionalCustomMods()) + { + return false; + } + + if (pbCur >= pbEnd) + { + return false; + } + + if (*pbCur == ELEMENT_TYPE_VOID) + { + pbCur++; + NotifyVoid(); + break; + } + + if (!ParseType()) + { + return false; + } + + break; + + case ELEMENT_TYPE_CLASS: + // CLASS TypeDefOrRefEncoded + NotifyTypeClass(); + + if (!ParseTypeDefOrRefEncoded(&indexType, &index)) + { + return false; + } + + NotifyTypeDefOrRef(indexType, index); + break; + + case ELEMENT_TYPE_VALUETYPE: + //VALUETYPE TypeDefOrRefEncoded + NotifyTypeValueType(); + + if (!ParseTypeDefOrRefEncoded(&indexType, &index)) + { + return false; + } + + NotifyTypeDefOrRef(indexType, index); + break; + + case ELEMENT_TYPE_FNPTR: + // FNPTR MethodDefSig + // FNPTR MethodRefSig + NotifyTypeFunctionPointer(); + + if (!ParseByte(&elem_type)) + { + return false; + } + + if (!ParseMethod(elem_type)) + { + return false; + } + + break; + + case ELEMENT_TYPE_ARRAY: + // ARRAY Type ArrayShape + NotifyTypeArray(); + + if (!ParseType()) + { + return false; + } + + if (!ParseArrayShape()) + { + return false; + } + break; + + case ELEMENT_TYPE_SZARRAY: + // SZARRAY CustomMod* Type + + NotifyTypeSzArray(); + + if (!ParseOptionalCustomMods()) + { + return false; + } + + if (!ParseType()) + { + return false; + } + + break; + + case ELEMENT_TYPE_GENERICINST: + // GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * + + if (!ParseByte(&elem_type)) + { + return false; + } + + if (elem_type != ELEMENT_TYPE_CLASS && elem_type != ELEMENT_TYPE_VALUETYPE) + { + return false; + } + + if (!ParseTypeDefOrRefEncoded(&indexType, &index)) + { + return false; + } + + if (!ParseNumber(&number)) + { + return false; + } + + NotifyTypeGenericInst(elem_type, indexType, index, number); + + { + for (sig_mem_number i=0; i < number; i++) + { + if (!ParseType()) + { + return false; + } + } + } + + break; + + case ELEMENT_TYPE_VAR: + // VAR Number + if (!ParseNumber(&number)) + { + return false; + } + + NotifyTypeGenericTypeVariable(number); + break; + + case ELEMENT_TYPE_MVAR: + // MVAR Number + if (!ParseNumber(&number)) + { + return false; + } + + NotifyTypeGenericMemberVariable(number); + break; + } + + NotifyEndType(); + + return true; +} + +bool SigParser::ParseTypeDefOrRefEncoded(sig_index_type *pIndexTypeOut, sig_index *pIndexOut) +{ + // parse an encoded typedef or typeref + + sig_count encoded = 0; + + if (!ParseNumber(&encoded)) + { + return false; + } + + *pIndexTypeOut = (sig_index_type) (encoded & 0x3); + *pIndexOut = (encoded >> 2); + return true; +} + +bool SigParser::ParseNumber(sig_count *pOut) +{ + // parse the variable length number format (0-4 bytes) + + sig_byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; + + // at least one byte in the encoding, read that + + if (!ParseByte(&b1)) + { + return false; + } + + if (b1 == 0xff) + { + // special encoding of 'NULL' + // not sure what this means as a number, don't expect to see it except for string lengths + // which we don't encounter anyway so calling it an error + return false; + } + + // early out on 1 byte encoding + if ( (b1 & 0x80) == 0) + { + *pOut = (int)b1; + return true; + } + + // now at least 2 bytes in the encoding, read 2nd byte + if (!ParseByte(&b2)) + { + return false; + } + + // early out on 2 byte encoding + if ( (b1 & 0x40) == 0) + { + *pOut = (((b1 & 0x3f) << 8) | b2); + return true; + } + + // must be a 4 byte encoding + + if ( (b1 & 0x20) != 0) + { + // 4 byte encoding has this bit clear -- error if not + return false; + } + + if (!ParseByte(&b3)) + { + return false; + } + + if (!ParseByte(&b4)) + { + return false; + } + + *pOut = ((b1 & 0x1f) << 24) | (b2 << 16) | (b3 << 8) | b4; + return true; +} diff --git a/Documentation/building/windows-instructions.md b/Documentation/building/windows-instructions.md index afb216fccb5b..bb241408291a 100644 --- a/Documentation/building/windows-instructions.md +++ b/Documentation/building/windows-instructions.md @@ -50,7 +50,7 @@ Visual Studio Express is not supported. ## CMake -The CoreCLR repo build has been validated using CMake 3.9.3. +The CoreCLR repo build has been validated using CMake 3.9.3. When using Visual Studio 2019 at least version 3.14.1 is required. - Install [CMake](http://www.cmake.org/download) for Windows. - Add its location (e.g. C:\Program Files (x86)\CMake\bin) to the PATH environment variable. @@ -60,7 +60,7 @@ The CoreCLR repo build has been validated using CMake 3.9.3. ## Python -Python is used in the build system. We are currently using python 2.7.9, although +Python is used in the build system. We are currently using Python 2.7.9, although any recent (2.4+) version of Python should work, including Python 3. - Install [Python](https://www.python.org/downloads/) for Windows. - Add its location (e.g. C:\Python*\) to the PATH environment variable. diff --git a/Documentation/deep-dive-blog-posts.md b/Documentation/deep-dive-blog-posts.md index cb567f331c9d..bbc3cb9202ae 100644 --- a/Documentation/deep-dive-blog-posts.md +++ b/Documentation/deep-dive-blog-posts.md @@ -3,6 +3,8 @@ ### Posts that take a high-level overview of releases - [Corestart 2.0: What's new for performance in .NET Core 2.0](https://www.ageofascent.com/2017/11/05/perfromance-dotnet-core-2-corestart-conference/) +- [Performance improvements in .NET Core 2.0](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core/) +- [Performance improvements in .NET Core 2.1](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-2-1/) ### Posts that take a high-level look at the entire source: diff --git a/Documentation/design-docs/AssemblyLoadContext.ContextualReflection.md b/Documentation/design-docs/AssemblyLoadContext.ContextualReflection.md index 65297ced78de..b2c7cb15d2a9 100644 --- a/Documentation/design-docs/AssemblyLoadContext.ContextualReflection.md +++ b/Documentation/design-docs/AssemblyLoadContext.ContextualReflection.md @@ -51,6 +51,7 @@ namespace System.Reflection { public static Assembly Load(string assemblyString); public static Assembly Load(AssemblyName assemblyRef); + public static Assembly LoadWithPartialName (string partialName); } } ``` @@ -65,8 +66,18 @@ namespace System public static Type GetType(string typeName); } } + +namespace System.Reflection +{ + public abstract partial class Assembly : ICustomAttributeProvider, ISerializable + { + public Type GetType(string typeName, bool throwOnError, bool ignoreCase); + public Type GetType(string typeName, bool throwOnError); + public Type GetType(string typeName); + } +} ``` -#### Unamiguous APIs related to affected APIs +#### Normally unamiguous APIs related to affected APIs ```C# namespace System { @@ -78,9 +89,9 @@ namespace System } } ``` -In this case, `assemblyResolver` functionally specifies the explicit mechanism to load. This indicates the current assembly's `AssmblyLoadContext` is not being used. If the `assemblyResolver` is only serving as a first or last chance resolver, then these would also be in the set of affected APIs. -#### Should be affected APIs -Issue https://github.com/dotnet/coreclr/issues/22213, discusses scenarios in which various flavors of the API `GetType()` is not functioning correctly. As part of the analysis and fix of that issue, the set of affected APIs may increase. +In this case, `assemblyResolver` functionally specifies the explicit mechanism to load. + +If the `assemblyResolver` is `null`, assembly loads for these occur when `typeName` includes a assembly-qualified type reference. ### Root cause analysis In .NET Framework, plugin isolation was provided by creating multiple `AppDomain` instances. .NET Core dropped support for multiple `AppDomain` instances. Instead we introduced `AssemblyLoadContext`. @@ -112,10 +123,10 @@ namespace System.Runtime.Loader { public partial class AssemblyLoadContext { - private static readonly AsyncLocal asyncLocalActiveContext = new AsyncLocal(null); + private static readonly AsyncLocal _asyncLocalActiveContext; public static AssemblyLoadContext CurrentContextualReflectionContext { - get { return _asyncLocalCurrentContextualReflectionContext.Value; } + get { return _asyncLocalCurrentContextualReflectionContext?.Value; } } } } @@ -203,7 +214,7 @@ namespace System.Runtime.Loader { public partial class AssemblyLoadContext { - public static AssemblyLoadContext CurrentContextualReflectionContext { get { return _asyncLocalCurrentContextualReflectionContext.Value; }} + public static AssemblyLoadContext CurrentContextualReflectionContext { get { return _asyncLocalCurrentContextualReflectionContext?.Value; }} public ContextualReflectionScope EnterContextualReflection(); @@ -218,62 +229,93 @@ namespace System.Runtime.Loader ``` ## Design doc -Mostly TBD. - -### Performance Consideration -#### Avoiding native / managed transitions +### Affected runtime native calls -My natural inclination would be to replace most native calls taking a `StackCrawlMark` with callS taking the `CurrentContextualReflectionContext`. When `CurrentContextualReflectionContext` is `null`, resolve the `StackCrawlMark` first, passing the result as the inferred context. +The affected runtime native calls correspond to the runtime's mechanism to load an assembly, and to get a type. Each affected native call is passed a managed reference to the CurrentContextualReflectionContext. This prevents GC holes, while running the native code. The `CurrentContextualReflectionContext` acts as the mechanism for resolving assembly names to assemblies. -However this may require mutiple native/managed transitions. Performance considerations may require Native calls which currently take a `StackCrawlMark` will need to be modified to also take `CurrentContextualReflectionContext`. +### Unloadability -### Hypothetical Advanced/Problematic use cases +`CurrentContextualReflectionContext` will hold an `AssemblyLoadContext` reference. This will prevent the context from being unloaded while it could be used. As an `AsyncLocal`, the setting will propagate to child threads and asynchronous tasks. +After a thread or asynchronous task completes, the `AsyncLocal` will eventually be cleared, this will unblock the `AssemblyLoadContext` unload. The timing of this unload depends on the ThreadPool implementation. -One could imagine complicated scenarios in which we need to handle ALCs on event callback boundaries. These are expected to be rare. The following are representative patterns that demonstrate the possibility to be support these more complicated usages. +### ContextualReflectionScope -#### An incoming event handler into an AssemblyLoadContext ```C# -void OnEvent() +/// Opaque disposable struct used to restore CurrentContextualReflectionContext +/// +/// This is an implmentation detail of the AssemblyLoadContext.EnterContextualReflection APIs. +/// It is a struct, to avoid heap allocation. +/// It is required to be public to avoid boxing. +/// +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public struct ContextualReflectionScope : IDisposable { - using (alc.Activate()) - { - ... - } -} -``` -#### An incoming event handler into a collectible AssemblyLoadContext -```C# -class WeakAssemblyLoadContextEventHandler -{ - WeakReference weakAlc; + private readonly AssemblyLoadContext _activated; + private readonly AssemblyLoadContext _predecessor; + private readonly bool _initialized; - void OnEvent() - { - AssemblyLoadContext alc; - if(weakAlc.TryGetTarget(out alc)) + internal ContextualReflectionScope(AssemblyLoadContext activating) { - using (alc.Activate()) - { - ... - } + _predecessor = AssemblyLoadContext.CurrentContextualReflectionContext; + AssemblyLoadContext.SetCurrentContextualReflectionContext(activating); + _activated = activating; + _initialized = true; + } + + public void Dispose() + { + if (_initialized) + { + // Do not clear initialized. Always restore the _predecessor in Dispose() + // _initialized = false; + AssemblyLoadContext.SetCurrentContextualReflectionContext(_predecessor); + } } - } } ``` -#### A outgoing callback + +`_initialized` is included to prevent useful default construction. It prevents the `default(ContextualReflectionScope).Dispose()` case. + +`_predecessor` represents the previous value of `CurrentContextualReflectionContext`. It is used by `Dispose()` to restore the previous state. + +`_activated` is included as a potential aid to debugging. It serves no other useful purpose. + +This struct is implemented as a readonly struct. No state is modified after construction. This means `Dispose()` can be called multiple times. This means `using` blocks will always restore the previous `CurrentContextualReflectionContext` as exiting. + +### Unusual usage patterns + +There are some unusual usage patterns which are not recommended, but not prohibited. They all have reasonable behaviors. + +* Clear but never restore the CurrentContextualReflectionContext +```C# +myAssemblyLoadContext.EnterContextualReflection(null); +``` + +* Set but never clear the CurrentContextualReflectionContext ```C# -using (AssemblyLoadContext.Activate(null)) -{ - Callback(); -} +myAssemblyLoadContext.EnterContextualReflection(); ``` -#### An outgoing event handler + +* Manual dispose ```C# -void OnEvent() +myAssemblyLoadContext.EnterContextualReflection(); + +scope.Dispose(); +``` + +* Multiple dispose +```C# +ContextualReflectionScope scope = myAssemblyLoadContext.EnterContextualReflection(); + +scope.Dispose(); // Will restore the context as set during `EnterContextualReflection()` +scope.Dispose(); // Will restore the context as set during `EnterContextualReflection()` (again) +``` + +* Early dispose +```C# +using (ContextualReflectionScope scope = myAssemblyLoadContext.EnterContextualReflection()) { - using (AssemblyLoadContext.Activate(null)) - { - ... - } -} + scope.Dispose(); // Will restore the context as set during `EnterContextualReflection()` +} // `using` will restore the context as set during `EnterContextualReflection()` (again) ``` diff --git a/Documentation/project-docs/clr-configuration-knobs.csx b/Documentation/project-docs/clr-configuration-knobs.csx index d14e1b2a9d82..739431f808a5 100644 --- a/Documentation/project-docs/clr-configuration-knobs.csx +++ b/Documentation/project-docs/clr-configuration-knobs.csx @@ -350,13 +350,13 @@ public static class ConfigKnobsDoc "## Environment/Registry Configuration Knobs\n"; public static string ClrConfigSectionInfo = - "This table was machine-generated using `clr-configuration-knobs.csx` script from repository commit [GIT_SHORT_HASH](https://github.com/dotnet/coreclr/commit/GIT_LONG_HASH) on DATE_CREATED. It might be out of date. To generate latest documentation run `{dotnet} csi clr-configuration-knobs.csx` from this file directory.\n"; + "This table was machine-generated using `clr-configuration-knobs.csx` script from repository commit [GIT_SHORT_HASH](https://github.com/dotnet/coreclr/commit/GIT_LONG_HASH) on DATE_CREATED. It might be out of date. To generate latest documentation run `dotnet-script clr-configuration-knobs.csx` from this file directory.\n"; public static string ClrConfigSectionUsage = "When using these configurations from environment variables, the variables need to have the `COMPlus_` prefix in their names. e.g. To set DumpJittedMethods to 1, add the environment variable `COMPlus_DumpJittedMethods=1`.\n\nSee also [Setting configuration variables](../building/viewing-jit-dumps.md#setting-configuration-variables) for more information.\n"; public static string ClrConfigTableHeader = - "\nName | Description | Type | Class | Default Value | Flags \n" + + "\nName | Description | Type | Class | Default Value | Flags\n" + "-----|-------------|------|-------|---------------|-------\n"; public static string PalConfigurationKnobs = @@ -421,10 +421,10 @@ public static class ConfigKnobsDoc foreach (string key in catKnobs.Keys) { var knob = catKnobs[key]; - writer.Write($"`{knob.Name}` | {knob.Description} | `{knob.Type}` | "); - writer.Write(knob.Class.Length > 0 ? $"`{knob.Class}` | " : " | "); - writer.Write(knob.DefaultValue.Length > 0 ? $"`{knob.DefaultValue}` | " : " | "); - writer.WriteLine($"{ knob.Flags}"); + writer.Write($"`{knob.Name}` | {knob.Description} | `{knob.Type}` |"); + writer.Write(knob.Class.Length > 0 ? $" `{knob.Class}` |" : " |"); + writer.Write(knob.DefaultValue.Length > 0 ? $" `{knob.DefaultValue}` |" : " |"); + writer.WriteLine(knob.Flags.Length > 0 ? $" {knob.Flags}" : string.Empty); count++; } diff --git a/Documentation/project-docs/clr-configuration-knobs.md b/Documentation/project-docs/clr-configuration-knobs.md index 328fdaafb54d..8eddfa76409c 100644 --- a/Documentation/project-docs/clr-configuration-knobs.md +++ b/Documentation/project-docs/clr-configuration-knobs.md @@ -17,7 +17,7 @@ Name | Description | Type ## Environment/Registry Configuration Knobs -This table was machine-generated using `clr-configuration-knobs.csx` script from repository commit [79aadb8](https://github.com/dotnet/coreclr/commit/79aadb8c6455e30065cbd817e3ec5b52d17f3dce) on 6/12/2018. It might be out of date. To generate latest documentation run `{dotnet} csi clr-configuration-knobs.csx` from this file directory. +This table was machine-generated using `clr-configuration-knobs.csx` script from repository commit [d064ffb](https://github.com/dotnet/coreclr/commit/d064ffb6b05c4f7fa44c7ee389e9694e64a76c08) on 15/04/2019. It might be out of date. To generate latest documentation run `{dotnet-script} clr-configuration-knobs.csx` from this file directory. When using these configurations from environment variables, the variables need to have the `COMPlus_` prefix in their names. e.g. To set DumpJittedMethods to 1, add the environment variable `COMPlus_DumpJittedMethods=1`. @@ -30,98 +30,93 @@ See also [Setting configuration variables](../building/viewing-jit-dumps.md#sett 4. [Conditional breakpoints Configuration Knobs](#conditional-breakpoints-configuration-knobs) 5. [Debugger Configuration Knobs](#debugger-configuration-knobs) 6. [Diagnostics (internal general-purpose) Configuration Knobs](#diagnostics-internal-general-purpose-configuration-knobs) -7. [Exception Handling Configuration Knobs](#exception-handling-configuration-knobs) -8. [Garbage collector Configuration Knobs](#garbage-collector-configuration-knobs) -9. [GDBJIT Configuration Knobs](#gdbjit-configuration-knobs) -10. [IBC Configuration Knobs](#ibc-configuration-knobs) -11. [Interop Configuration Knobs](#interop-configuration-knobs) -12. [Interpreter Configuration Knobs](#interpreter-configuration-knobs) -13. [JIT Configuration Knobs](#jit-configuration-knobs) -14. [JIT Hardware Intrinsics Configuration Knobs](#jit-hardware-intrinsics-configuration-knobs) -15. [Jit Pitching Configuration Knobs](#jit-pitching-configuration-knobs) -16. [Loader Configuration Knobs](#loader-configuration-knobs) -17. [Loader heap Configuration Knobs](#loader-heap-configuration-knobs) -18. [Log Configuration Knobs](#log-configuration-knobs) -19. [MetaData Configuration Knobs](#metadata-configuration-knobs) -20. [Native Binder Configuration Knobs](#native-binder-configuration-knobs) -21. [NGEN Configuration Knobs](#ngen-configuration-knobs) -22. [Performance Configuration Knobs](#performance-configuration-knobs) -23. [Profiling API / ETW Configuration Knobs](#profiling-api--etw-configuration-knobs) -24. [Spinning heuristics Configuration Knobs](#spinning-heuristics-configuration-knobs) -25. [Stress Configuration Knobs](#stress-configuration-knobs) -26. [Thread (miscellaneous) Configuration Knobs](#thread-miscellaneous-configuration-knobs) -27. [Thread Suspend Configuration Knobs](#thread-suspend-configuration-knobs) -28. [Threadpool Configuration Knobs](#threadpool-configuration-knobs) -29. [Tiered Compilation Configuration Knobs](#tiered-compilation-configuration-knobs) -30. [TypeLoader Configuration Knobs](#typeloader-configuration-knobs) -31. [Uncategorized Configuration Knobs](#uncategorized-configuration-knobs) -32. [Virtual call stubs Configuration Knobs](#virtual-call-stubs-configuration-knobs) -33. [Watson Configuration Knobs](#watson-configuration-knobs) -34. [Zap Configuration Knobs](#zap-configuration-knobs) +7. [Entry point slot backpatch Configuration Knobs](#entry-point-slot-backpatch-configuration-knobs) +8. [Exception Handling Configuration Knobs](#exception-handling-configuration-knobs) +9. [Garbage collector Configuration Knobs](#garbage-collector-configuration-knobs) +10. [GDBJIT Configuration Knobs](#gdbjit-configuration-knobs) +11. [IBC Configuration Knobs](#ibc-configuration-knobs) +12. [Interop Configuration Knobs](#interop-configuration-knobs) +13. [Interpreter Configuration Knobs](#interpreter-configuration-knobs) +14. [JIT Configuration Knobs](#jit-configuration-knobs) +15. [JIT Hardware Intrinsics Configuration Knobs](#jit-hardware-intrinsics-configuration-knobs) +16. [Jit Pitching Configuration Knobs](#jit-pitching-configuration-knobs) +17. [Loader Configuration Knobs](#loader-configuration-knobs) +18. [Loader heap Configuration Knobs](#loader-heap-configuration-knobs) +19. [Log Configuration Knobs](#log-configuration-knobs) +20. [MetaData Configuration Knobs](#metadata-configuration-knobs) +21. [Native Binder Configuration Knobs](#native-binder-configuration-knobs) +22. [NGEN Configuration Knobs](#ngen-configuration-knobs) +23. [Performance Configuration Knobs](#performance-configuration-knobs) +24. [Profiling API / ETW Configuration Knobs](#profiling-api--etw-configuration-knobs) +25. [Spinning heuristics Configuration Knobs](#spinning-heuristics-configuration-knobs) +26. [Stress Configuration Knobs](#stress-configuration-knobs) +27. [Thread (miscellaneous) Configuration Knobs](#thread-miscellaneous-configuration-knobs) +28. [Thread Suspend Configuration Knobs](#thread-suspend-configuration-knobs) +29. [Threadpool Configuration Knobs](#threadpool-configuration-knobs) +30. [Tiered Compilation Configuration Knobs](#tiered-compilation-configuration-knobs) +31. [TypeLoader Configuration Knobs](#typeloader-configuration-knobs) +32. [Uncategorized Configuration Knobs](#uncategorized-configuration-knobs) +33. [Virtual call stubs Configuration Knobs](#virtual-call-stubs-configuration-knobs) +34. [Watson Configuration Knobs](#watson-configuration-knobs) +35. [Zap Configuration Knobs](#zap-configuration-knobs) #### AppDomain Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`ADBreakOnCannotUnload` | Used to troubleshoot failures to unload appdomain (e.g. someone sitting in unmanged code). In some cases by the time we throw the appropriate exception the thread has moved from the offending call. This setting allows in an instrumented build to stop exactly at the right moment. | `DWORD` | `INTERNAL` | `0` | -`AddRejitNops` | Control for the profiler rejit feature infrastructure | `DWORD` | `UNSUPPORTED` | | -`ADDumpSB` | Not used | `DWORD` | `INTERNAL` | `0` | -`ADForceSB` | Forces sync block creation for all objects | `DWORD` | `INTERNAL` | `0` | -`ADLogMemory` | Superseded by test hooks | `DWORD` | `INTERNAL` | `0` | -`ADTakeDHSnapShot` | Superseded by test hooks | `DWORD` | `INTERNAL` | `0` | -`ADTakeSnapShot` | Superseded by test hooks | `DWORD` | `INTERNAL` | `0` | -`ADULazyMemoryRelease` | On by default. Turned off in cases when people try to catch memory leaks, in which case AD unload should be immediately followed by GC) | `DWORD` | `EXTERNAL` | `1` | -`ADURetryCount` | Controls timeout of AD unload. Used for workarounds when machine is too slow, there are network issues etc. | `DWORD` | `EXTERNAL` | | -`EnableFullDebug` | Heavy-weight checking for AD boundary violations (AD leaks) | `DWORD` | `INTERNAL` | | -`FinalizeOnShutdown` | When enabled, on shutdown, blocks all user threads and calls finalizers for all finalizable objects, including live objects | `DWORD` | `EXTERNAL` | `DEFAULT_FinalizeOnShutdown` | +`AddRejitNops` | Control for the profiler rejit feature infrastructure | `DWORD` | `UNSUPPORTED` | | +`ADDumpSB` | Not used | `DWORD` | `INTERNAL` | `0` | +`ADForceSB` | Forces sync block creation for all objects | `DWORD` | `INTERNAL` | `0` | +`ADLogMemory` | Superseded by test hooks | `DWORD` | `INTERNAL` | `0` | +`ADTakeDHSnapShot` | Superseded by test hooks | `DWORD` | `INTERNAL` | `0` | +`ADTakeSnapShot` | Superseded by test hooks | `DWORD` | `INTERNAL` | `0` | +`EnableFullDebug` | Heavy-weight checking for AD boundary violations (AD leaks) | `DWORD` | `INTERNAL` | | #### ARM Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `ARMEnabled` | AppDomain Resource Monitoring. Set to 1 to enable it | `DWORD` | `UNSUPPORTED` | `(DWORD)0` | #### Assembly Loader Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `designerNamespaceResolution` | Set it to 1 to enable DesignerNamespaceResolve event for WinRT types | `DWORD` | `EXTERNAL` | `FALSE` | IgnoreEnv \| IgnoreHKLM \| IgnoreHKCU \| FavorConfigFile `GetAssemblyIfLoadedIgnoreRidMap` | Used to force loader to ignore assemblies cached in the rid-map | `DWORD` | `INTERNAL` | `0` | REGUTIL_default #### Conditional breakpoints Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `BreakOnBadExit` | | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default -`BreakOnClassBuild` | Very useful for debugging class layout code. | `STRING` | `INTERNAL` | | -`BreakOnClassLoad` | Very useful for debugging class loading code. | `STRING` | `INTERNAL` | | -`BreakOnComToClrNativeInfoInit` | Throws an assert when native information about a COM -> CLR call are about to be gathered. | `STRING` | `INTERNAL` | | +`BreakOnClassBuild` | Very useful for debugging class layout code. | `STRING` | `INTERNAL` | | +`BreakOnClassLoad` | Very useful for debugging class loading code. | `STRING` | `INTERNAL` | | +`BreakOnComToClrNativeInfoInit` | Throws an assert when native information about a COM -> CLR call are about to be gathered. | `STRING` | `INTERNAL` | | `BreakOnDebugBreak` | Allows an assert in debug builds when a user break is hit | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnDILoad` | Allows an assert when the DI is loaded | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnDumpToken` | Breaks when using internal logging on a particular token value. | `DWORD` | `INTERNAL` | `0xffffffff` | REGUTIL_default `BreakOnEELoad` | | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default -`BreakOnEEShutdown` | | `DWORD` | `INTERNAL` | `0` | +`BreakOnEEShutdown` | | `DWORD` | `INTERNAL` | `0` | `BreakOnExceptionInGetThrowable` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`BreakOnFinalizeTimeOut` | Triggers a debug break on the finalizer thread when it has exceeded the maximum wait time | `DWORD` | `UNSUPPORTED` | `0` | -`BreakOnFindMethod` | Breaks in findMethodInternal when it searches for the specified token. | `DWORD` | `INTERNAL` | `0` | +`BreakOnFindMethod` | Breaks in findMethodInternal when it searches for the specified token. | `DWORD` | `INTERNAL` | `0` | `BreakOnFirstPass` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnHR` | Debug.cpp, IfFailxxx use this macro to stop if hr matches | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`BreakOnInstantiation` | Very useful for debugging generic class instantiation. | `STRING` | `INTERNAL` | | -`BreakOnInteropStubSetup` | Throws an assert when marshaling stub for the given method is about to be built. | `STRING` | `INTERNAL` | | -`BreakOnInteropVTableBuild` | Specifies a type name for which an assert should be thrown when building interop v-table. | `STRING` | `INTERNAL` | | REGUTIL_default -`BreakOnMethodName` | Very useful for debugging method override placement code. | `STRING` | `INTERNAL` | | -`BreakOnNGenRegistryAccessCount` | Breaks on the Nth' root store write | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default +`BreakOnInstantiation` | Very useful for debugging generic class instantiation. | `STRING` | `INTERNAL` | | +`BreakOnInteropStubSetup` | Throws an assert when marshaling stub for the given method is about to be built. | `STRING` | `INTERNAL` | | +`BreakOnInteropVTableBuild` | Specifies a type name for which an assert should be thrown when building interop v-table. | `STRING` | `INTERNAL` | | REGUTIL_default +`BreakOnMethodName` | Very useful for debugging method override placement code. | `STRING` | `INTERNAL` | | `BreakOnNotify` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnRetailAssert` | Used for debugging \"retail\" asserts (fatal errors) | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnSecondPass` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnSO` | | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default -`BreakOnStructMarshalSetup` | Throws an assert when field marshalers for the given type with layout are about to be created. | `STRING` | `INTERNAL` | | +`BreakOnStructMarshalSetup` | Throws an assert when field marshalers for the given type with layout are about to be created. | `STRING` | `INTERNAL` | | `BreakOnUEF` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `BreakOnUncaughtException` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default #### Debugger Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `D::FCE` | Allows an assert when crawling the managed stack for an exception handler | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgAssertOnDebuggeeDebugBreak` | If non-zero causes the managed-only debugger to assert on unhandled breakpoints in the debuggee | `DWORD` | `INTERNAL` | `0` | REGUTIL_default @@ -132,13 +127,13 @@ Name | Description | Type | Class | Default Value | Flags `DbgBreakOnSendBreakpoint` | Allows an assert when sending a breakpoint to the right side | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgBreakOnSetIP` | Allows an assert when setting the IP | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgCheckInt3` | Asserts if the debugger explicitly writes int3 instead of calling SetUnmanagedBreakpoint | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`DbgDACAssertOnMismatch` | Allows an assert when the mscordacwks and mscorwks dll versions don't match | `DWORD` | `INTERNAL` | | +`DbgDACAssertOnMismatch` | Allows an assert when the mscordacwks and mscorwks dll versions don't match | `DWORD` | `INTERNAL` | | `DbgDACEnableAssert` | Enables extra validity checking in DAC - assumes target isn't corrupt | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgDACSkipVerifyDlls` | Allows disabling the check to ensure mscordacwks and mscorwks dll versions match | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgDelayHelper` | Varies the wait in the helper thread startup for testing race between threads | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgDisableDynamicSymsCompat` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgDisableTargetConsistencyAsserts` | Allows explicitly testing with corrupt targets | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`DbgDontResumeThreadsOnUnhandledException` | If non-zero, then don't try to unsuspend threads after continuing a 2nd-chance native exception | `DWORD` | `UNSUPPORTED` | `0` | +`DbgDontResumeThreadsOnUnhandledException` | If non-zero, then don't try to unsuspend threads after continuing a 2nd-chance native exception | `DWORD` | `UNSUPPORTED` | `0` | `DbgEnableMixedModeDebuggingInternalOnly` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgExtraThreads` | Allows extra unmanaged threads to run and throw debug events for stress testing | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgExtraThreadsCantStop` | Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing | `DWORD` | `INTERNAL` | `0` | REGUTIL_default @@ -152,457 +147,496 @@ Name | Description | Type | Class | Default Value | Flags `DbgNoDebugger` | Allows breaking if we don't want to lazily initialize the debugger | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgNoForceContinue` | Used to force a continue on longhorn | `DWORD` | `UNSUPPORTED` | `1` | REGUTIL_default `DbgNoOpenMDByFile` | Allows opening MD by memory for perf testing | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`DbgOOBinFEEE` | Allows forcing oob breakpoints when a fatal error occurs | `DWORD` | `INTERNAL` | `0` | -`DbgPackShimPath` | CoreCLR path to dbgshim.dll - we are trying to figure out if we can remove this | `STRING` | `EXTERNAL` | | +`DbgOOBinFEEE` | Allows forcing oob breakpoints when a fatal error occurs | `DWORD` | `INTERNAL` | `0` | +`DbgPackShimPath` | CoreCLR path to dbgshim.dll - we are trying to figure out if we can remove this | `STRING` | `EXTERNAL` | | `DbgPingInterop` | Allows checking for deadlocks in interop debugging | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgRace` | Allows pausing for native debug events to get hijicked | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgRedirect` | Allows for redirecting the event pipeline | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default -`DbgRedirectApplication` | Specifies the auxiliary debugger application to launch. | `STRING` | `EXTERNAL` | | -`DbgRedirectAttachCmd` | Specifies command parameters for attaching the auxiliary debugger. | `STRING` | `EXTERNAL` | | -`DbgRedirectCommonCmd` | Specifies a command line format string for the auxiliary debugger. | `STRING` | `EXTERNAL` | | -`DbgRedirectCreateCmd` | Specifies command parameters when creating the auxiliary debugger. | `STRING` | `EXTERNAL` | | +`DbgRedirectApplication` | Specifies the auxiliary debugger application to launch. | `STRING` | `EXTERNAL` | | +`DbgRedirectAttachCmd` | Specifies command parameters for attaching the auxiliary debugger. | `STRING` | `EXTERNAL` | | +`DbgRedirectCommonCmd` | Specifies a command line format string for the auxiliary debugger. | `STRING` | `EXTERNAL` | | +`DbgRedirectCreateCmd` | Specifies command parameters when creating the auxiliary debugger. | `STRING` | `EXTERNAL` | | `DbgShortcutCanary` | Allows a way to force canary to fail to be able to test failure paths | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgSkipMEOnStep` | Turns off MethodEnter checks | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgSkipStackCheck` | Skip the stack pointer check during stackwalking | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default `DbgSkipVerCheck` | Allows different RS and LS versions (for servicing work) | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgTC` | Allows checking boundary compression for offset mappings | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgTransportFaultInject` | Allows injecting a fault for testing the debug transport | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`DbgTransportLog` | Turns on logging for the debug transport | `DWORD` | `INTERNAL` | | -`DbgTransportLogClass` | Mask to control what is logged in DbgTransportLog | `DWORD` | `INTERNAL` | | -`DbgTransportProxyAddress` | Allows specifying the transport proxy address | `STRING` | `UNSUPPORTED` | | REGUTIL_default +`DbgTransportLog` | Turns on logging for the debug transport | `DWORD` | `INTERNAL` | | +`DbgTransportLogClass` | Mask to control what is logged in DbgTransportLog | `DWORD` | `INTERNAL` | | +`DbgTransportProxyAddress` | Allows specifying the transport proxy address | `STRING` | `UNSUPPORTED` | | REGUTIL_default `DbgTrapOnSkip` | Allows breaking when we skip a breakpoint | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DbgWaitTimeout` | Specifies the timeout value for waits | `DWORD` | `INTERNAL` | `1` | REGUTIL_default `DbgWFDETimeout` | Specifies the timeout value for wait when waiting for a debug event | `DWORD` | `UNSUPPORTED` | `25` | REGUTIL_default `DebugBreakOnAssert` | If DACCESS_COMPILE is defined, break on asserts. | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `DebugBreakOnVerificationFailure` | Halts the jit on verification failure | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`DebuggerBreakPoint` | Allows counting various debug events | `STRING` | `INTERNAL` | | REGUTIL_default -`Debugging_RequiredVersion` | The lowest ICorDebug version we should attempt to emulate, or 0 for default policy. Use 2 for CLRv2, 4 for CLRv4, etc. | `DWORD` | `UNSUPPORTED` | `0` | -`DebugVerify` | Control for tracing in peverify | `STRING` | `INTERNAL` | | REGUTIL_default +`DebuggerBreakPoint` | Allows counting various debug events | `STRING` | `INTERNAL` | | REGUTIL_default +`Debugging_RequiredVersion` | The lowest ICorDebug version we should attempt to emulate, or 0 for default policy. Use 2 for CLRv2, 4 for CLRv4, etc. | `DWORD` | `UNSUPPORTED` | `0` | +`DebugVerify` | Control for tracing in peverify | `STRING` | `INTERNAL` | | REGUTIL_default `EnableDiagnostics` | Allows the debugger and profiler diagnostics to be disabled | `DWORD` | `EXTERNAL` | `1` | REGUTIL_default -`EncApplyChanges` | Allows breaking when ApplyEditAndContinue is called | `DWORD` | `INTERNAL` | `0` | +`EncApplyChanges` | Allows breaking when ApplyEditAndContinue is called | `DWORD` | `INTERNAL` | `0` | `EnCBreakOnRemapComplete` | Allows breaking after N RemapCompletes | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `EnCBreakOnRemapOpportunity` | Allows breaking after N RemapOpportunities | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`EncDumpApplyChanges` | Allows dumping edits in delta metadata and il files | `DWORD` | `INTERNAL` | `0` | -`EncFixupFieldBreak` | Unlikely that this is used anymore. | `DWORD` | `INTERNAL` | `0` | -`EncJitUpdatedFunction` | Allows breaking when an updated function is jitted | `DWORD` | `INTERNAL` | `0` | -`EnCResolveField` | Allows breaking when computing the address of an EnC-added field | `DWORD` | `INTERNAL` | `0` | -`EncResumeInUpdatedFunction` | Allows breaking when execution resumes in a new EnC version of a function | `DWORD` | `INTERNAL` | `0` | -`IntentionallyCorruptDataFromTarget` | Intentionally fakes bad data retrieved from target to try and break dump generation. | `DWORD` | `INTERNAL` | `0` | -`MiniMdBufferCapacity` | The max size of the buffer to store mini metadata information for triage- and mini-dumps. | `DWORD` | `INTERNAL` | `64 * 1024` | +`EncDumpApplyChanges` | Allows dumping edits in delta metadata and il files | `DWORD` | `INTERNAL` | `0` | +`EncFixupFieldBreak` | Unlikely that this is used anymore. | `DWORD` | `INTERNAL` | `0` | +`EncJitUpdatedFunction` | Allows breaking when an updated function is jitted | `DWORD` | `INTERNAL` | `0` | +`EnCResolveField` | Allows breaking when computing the address of an EnC-added field | `DWORD` | `INTERNAL` | `0` | +`EncResumeInUpdatedFunction` | Allows breaking when execution resumes in a new EnC version of a function | `DWORD` | `INTERNAL` | `0` | +`IntentionallyCorruptDataFromTarget` | Intentionally fakes bad data retrieved from target to try and break dump generation. | `DWORD` | `INTERNAL` | `0` | +`MiniMdBufferCapacity` | The max size of the buffer to store mini metadata information for triage- and mini-dumps. | `DWORD` | `INTERNAL` | `64 * 1024` | `RaiseExceptionOnAssert` | Raise a first chance (if set to 1) or second chance (if set to 2) exception on asserts. | `DWORD` | `INTERNAL` | `0` | REGUTIL_default #### Diagnostics (internal general-purpose) Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`ConditionalContracts` | If ENABLE_CONTRACTS_IMPL is defined, sets whether contracts are conditional. (?) | `DWORD` | `INTERNAL` | | -`ConsistencyCheck` | | `DWORD` | `INTERNAL` | `0` | +`ConditionalContracts` | If ENABLE_CONTRACTS_IMPL is defined, sets whether contracts are conditional. (?) | `DWORD` | `INTERNAL` | | +`ConsistencyCheck` | | `DWORD` | `INTERNAL` | `0` | `ContinueOnAssert` | If set, doesn't break on asserts. | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `disableStackOverflowProbing` | | `DWORD` | `UNSUPPORTED` | `0` | FavorConfigFile -`InjectFatalError` | | `DWORD` | `INTERNAL` | | +`InjectFatalError` | | `DWORD` | `INTERNAL` | | `InjectFault` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`SuppressChecks` | | `DWORD` | `INTERNAL` | | -`SuppressLockViolationsOnReentryFromOS` | 64 bit OOM tests re-enter the CLR via RtlVirtualUnwind. This indicates whether to suppress resulting locking violations. | `DWORD` | `INTERNAL` | `0` | -`TestHooks` | Used by tests to get test an insight on various CLR workings | `STRING` | `INTERNAL` | | +`SuppressChecks` | | `DWORD` | `INTERNAL` | | +`SuppressLockViolationsOnReentryFromOS` | 64 bit OOM tests re-enter the CLR via RtlVirtualUnwind. This indicates whether to suppress resulting locking violations. | `DWORD` | `INTERNAL` | `0` | +`TestHooks` | Used by tests to get test an insight on various CLR workings | `STRING` | `INTERNAL` | | + +#### Entry point slot backpatch Configuration Knobs + +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`BackpatchEntryPointSlots` | Indicates whether to enable entry point slot backpatching, for instance to avoid making virtual calls through a precode and instead to patch virtual slots for a method when its entry point changes. | `DWORD` | `UNSUPPORTED` | `1` | #### Exception Handling Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`AssertOnFailFast` | | `DWORD` | `INTERNAL` | | +`AssertOnFailFast` | | `DWORD` | `INTERNAL` | | +`Corhost_Swallow_Uncaught_Exceptions` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `FailFastOnCorruptedStateException` | Failfast if a CSE is encountered | `DWORD` | `UNSUPPORTED` | `0` | FavorConfigFile `legacyCorruptedStateExceptionsPolicy` | Enabled Pre-V4 CSE behavior | `DWORD` | `UNSUPPORTED` | `0` | FavorConfigFile `SuppressLostExceptionTypeAssert` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default +`UseEntryPointFilter` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default #### Garbage collector Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`BGCSpin` | Specifies the bgc spin time | `DWORD` | `UNSUPPORTED` | `2` | -`BGCSpinCount` | Specifies the bgc spin count | `DWORD` | `UNSUPPORTED` | `140` | -`FastGCCheckStack` | | `DWORD` | `INTERNAL` | `0` | -`FastGCStress` | Reduce the number of GCs done by enabling GCStress | `DWORD` | `INTERNAL` | | -`gcAllowVeryLargeObjects` | Allow allocation of 2GB+ objects on GC heap | `DWORD` | `EXTERNAL` | `1` | -`GCBreakOnOOM` | Does a DebugBreak at the soonest time we detect an OOM | `DWORD` | `UNSUPPORTED` | | -`GCCompactRatio` | Specifies the ratio compacting GCs vs sweeping | `DWORD` | `UNSUPPORTED` | `0` | -`gcConcurrent` | Enables/Disables concurrent GC | `DWORD` | `UNSUPPORTED` | `(DWORD)-1` | -`GCConfigLogEnabled` | Specifies if you want to turn on config logging in GC | `DWORD` | `UNSUPPORTED` | `0` | -`GCConfigLogFile` | Specifies the name of the GC config log file | `STRING` | `UNSUPPORTED` | | -`gcConservative` | Enables/Disables conservative GC | `DWORD` | `UNSUPPORTED` | `0` | -`GcCoverage` | Specify a method or regular expression of method names to run with GCStress | `STRING` | `INTERNAL` | | -`GCCpuGroup` | Specifies if to enable GC to support CPU groups | `DWORD` | `EXTERNAL` | `0` | -`gcForceCompact` | When set to true, always do compacting GC | `DWORD` | `UNSUPPORTED` | | -`GCgen0size` | Specifies the smallest gen0 size | `DWORD` | `UNSUPPORTED` | | -`GCHeapCount` | | `DWORD` | `UNSUPPORTED` | `0` | -`GCLatencyLevel` | Specifies the GC latency level that you want to optimize for | `DWORD` | `EXTERNAL` | `1` | -`GCLatencyMode` | Specifies the GC latency mode - batch, interactive or low latency (note that the same thing can be specified via API which is the supported way) | `DWORD` | `INTERNAL` | | -`GCLogEnabled` | Specifies if you want to turn on logging in GC | `DWORD` | `UNSUPPORTED` | `0` | -`GCLogFile` | Specifies the name of the GC log file | `STRING` | `UNSUPPORTED` | | -`GCLogFileSize` | Specifies the GC log file size | `DWORD` | `UNSUPPORTED` | `0` | -`GCLOHCompact` | Specifies the LOH compaction mode | `DWORD` | `UNSUPPORTED` | | -`GCMixLog` | Specifies the name of the log file for GC mix statistics | `STRING` | `UNSUPPORTED` | | -`GCName` | | `STRING` | `EXTERNAL` | | -`GCNoAffinitize` | | `DWORD` | `UNSUPPORTED` | `0` | -`GCNumaAware` | Specifies if to enable GC NUMA aware | `DWORD` | `UNSUPPORTED` | `1` | -`GCPollType` | | `DWORD` | `EXTERNAL` | | -`GCRetainVM` | When set we put the segments that should be deleted on a standby list (instead of releasing them back to the OS) which will be considered to satisfy new segment requests (note that the same thing can be specified via API which is the supported way) | `DWORD` | `UNSUPPORTED` | `0` | -`GCSegmentSize` | Specifies the managed heap segment size | `DWORD` | `UNSUPPORTED` | | -`gcServer` | Enables server GC | `DWORD` | `UNSUPPORTED` | `0` | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`BGCSpin` | Specifies the bgc spin time | `DWORD` | `UNSUPPORTED` | `2` | +`BGCSpinCount` | Specifies the bgc spin count | `DWORD` | `UNSUPPORTED` | `140` | +`FastGCCheckStack` | | `DWORD` | `INTERNAL` | `0` | +`FastGCStress` | Reduce the number of GCs done by enabling GCStress | `DWORD` | `INTERNAL` | | +`gcAllowVeryLargeObjects` | Allow allocation of 2GB+ objects on GC heap | `DWORD` | `EXTERNAL` | `1` | +`GCBreakOnOOM` | Does a DebugBreak at the soonest time we detect an OOM | `DWORD` | `UNSUPPORTED` | | +`GCCompactRatio` | Specifies the ratio compacting GCs vs sweeping | `DWORD` | `UNSUPPORTED` | `0` | +`gcConcurrent` | Enables/Disables concurrent GC | `DWORD` | `UNSUPPORTED` | `(DWORD)-1` | +`GCConfigLogEnabled` | Specifies if you want to turn on config logging in GC | `DWORD` | `UNSUPPORTED` | `0` | +`GCConfigLogFile` | Specifies the name of the GC config log file | `STRING` | `UNSUPPORTED` | | +`gcConservative` | Enables/Disables conservative GC | `DWORD` | `UNSUPPORTED` | `0` | +`GcCoverage` | Specify a method or regular expression of method names to run with GCStress | `STRING` | `INTERNAL` | | +`GCCpuGroup` | Specifies if to enable GC to support CPU groups | `DWORD` | `EXTERNAL` | `0` | +`gcForceCompact` | When set to true, always do compacting GC | `DWORD` | `UNSUPPORTED` | | +`GCGen0MaxBudget` | Specifies the largest gen0 allocation budget | `DWORD` | `UNSUPPORTED` | | +`GCgen0size` | Specifies the smallest gen0 size | `DWORD` | `UNSUPPORTED` | | +`GCHeapAffinitizeMask` | Specifies processor mask for Server GC threads | `DWORD` | `EXTERNAL` | | +`GCHeapAffinitizeRanges` | Specifies list of processors for Server GC threads. The format is a comma separated list of processor numbers or ranges of processor numbers. Example: 1,3,5,7-9,12 | `STRING` | `EXTERNAL` | | +`GCHeapCount` | | `DWORD` | `EXTERNAL` | `0` | +`GCHeapHardLimit` | Specifies the maximum commit size for the GC heap | `DWORD` | `EXTERNAL` | | +`GCHeapHardLimitPercent` | Specifies the GC heap usage as a percentage of the total memory | `DWORD` | `EXTERNAL` | | +`GCHighMemPercent` | Specifies the percent for GC to consider as high memory | `DWORD` | `EXTERNAL` | `0` | +`GCLargePages` | Specifies whether large pages should be used when a heap hard limit is set | `DWORD` | `EXTERNAL` | | +`GCLatencyLevel` | Specifies the GC latency level that you want to optimize for | `DWORD` | `EXTERNAL` | `1` | +`GCLatencyMode` | Specifies the GC latency mode - batch, interactive or low latency (note that the same thing can be specified via API which is the supported way) | `DWORD` | `INTERNAL` | | +`GCLogEnabled` | Specifies if you want to turn on logging in GC | `DWORD` | `UNSUPPORTED` | `0` | +`GCLogFile` | Specifies the name of the GC log file | `STRING` | `UNSUPPORTED` | | +`GCLogFileSize` | Specifies the GC log file size | `DWORD` | `UNSUPPORTED` | `0` | +`GCLOHCompact` | Specifies the LOH compaction mode | `DWORD` | `UNSUPPORTED` | | +`GCLOHThreshold` | Specifies the size that will make objects go on LOH | `DWORD` | `EXTERNAL` | `0` | +`GCMixLog` | Specifies the name of the log file for GC mix statistics | `STRING` | `UNSUPPORTED` | | +`GCName` | | `STRING` | `EXTERNAL` | | +`GCNoAffinitize` | | `DWORD` | `EXTERNAL` | `0` | +`GCNumaAware` | Specifies if to enable GC NUMA aware | `DWORD` | `UNSUPPORTED` | `1` | +`GCPollType` | | `DWORD` | `EXTERNAL` | | +`GCProvModeStress` | Stress the provisional modes | `DWORD` | `UNSUPPORTED` | `0` | +`GCRetainVM` | When set we put the segments that should be deleted on a standby list (instead of releasing them back to the OS) which will be considered to satisfy new segment requests (note that the same thing can be specified via API which is the supported way) | `DWORD` | `UNSUPPORTED` | `0` | +`GCSegmentSize` | Specifies the managed heap segment size | `DWORD` | `UNSUPPORTED` | | +`gcServer` | Enables server GC | `DWORD` | `UNSUPPORTED` | `0` | `GCStress` | Trigger GCs at regular intervals | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default -`GCStressMaxFGCsPerBGC` | Specifies how many FGCs will occur during one BGC in GCStressMix mode | `DWORD` | `INTERNAL` | `~0U` | -`GCStressMix` | Specifies whether the GC mix mode is enabled or not | `DWORD` | `INTERNAL` | `0` | +`GCStressMaxFGCsPerBGC` | Specifies how many FGCs will occur during one BGC in GCStressMix mode | `DWORD` | `INTERNAL` | `~0U` | +`GCStressMix` | Specifies whether the GC mix mode is enabled or not | `DWORD` | `INTERNAL` | `0` | `GcStressOnDirectCalls` | Whether to trigger a GC on direct calls | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`GCStressStart` | Start GCStress after N stress GCs have been attempted | `DWORD` | `EXTERNAL` | `0` | -`GCStressStartAtJit` | Start GCStress after N items are jitted | `DWORD` | `INTERNAL` | `0` | -`GCStressStep` | Specifies how often StressHeap will actually do a GC in GCStressMix mode | `DWORD` | `INTERNAL` | `1` | -`gcTrimCommitOnLowMemory` | When set we trim the committed space more aggressively for the ephemeral seg. This is used for running many instances of server processes where they want to keep as little memory committed as possible | `DWORD` | `EXTERNAL` | | -`HeapVerify` | When set verifies the integrity of the managed heap on entry and exit of each GC | `DWORD` | `UNSUPPORTED` | | -`SetupGcCoverage` | This doesn't appear to be a config flag | `STRING` | `EXTERNAL` | | REGUTIL_default -`SkipGcCoverage` | Specify a list of assembly names to skip with GC Coverage | `STRING` | `INTERNAL` | | -`StatsUpdatePeriod` | Specifies the interval, in seconds, at which to update the statistics | `DWORD` | `UNSUPPORTED` | `60` | -`SuspendTimeLog` | Specifies the name of the log file for suspension statistics | `STRING` | `UNSUPPORTED` | | +`GCStressStart` | Start GCStress after N stress GCs have been attempted | `DWORD` | `EXTERNAL` | `0` | +`GCStressStartAtJit` | Start GCStress after N items are jitted | `DWORD` | `INTERNAL` | `0` | +`GCStressStep` | Specifies how often StressHeap will actually do a GC in GCStressMix mode | `DWORD` | `INTERNAL` | `1` | +`gcTrimCommitOnLowMemory` | When set we trim the committed space more aggressively for the ephemeral seg. This is used for running many instances of server processes where they want to keep as little memory committed as possible | `DWORD` | `EXTERNAL` | | +`HeapVerify` | When set verifies the integrity of the managed heap on entry and exit of each GC | `DWORD` | `UNSUPPORTED` | | +`SetupGcCoverage` | This doesn't appear to be a config flag | `STRING` | `EXTERNAL` | | REGUTIL_default +`SkipGcCoverage` | Specify a list of assembly names to skip with GC Coverage | `STRING` | `INTERNAL` | | +`StatsUpdatePeriod` | Specifies the interval, in seconds, at which to update the statistics | `DWORD` | `UNSUPPORTED` | `60` | +`SuspendTimeLog` | Specifies the name of the log file for suspension statistics | `STRING` | `UNSUPPORTED` | | #### GDBJIT Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`GDBJitElfDump` | Dump ELF for specified method | `STRING` | `INTERNAL` | | -`GDBJitEmitDebugFrame` | Enable .debug_frame generation | `DWORD` | `INTERNAL` | `TRUE` | +`GDBJitElfDump` | Dump ELF for specified method | `STRING` | `INTERNAL` | | +`GDBJitEmitDebugFrame` | Enable .debug_frame generation | `DWORD` | `INTERNAL` | `TRUE` | #### IBC Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `ConvertIbcData` | Converts between v1 and v2 IBC data | `DWORD` | `UNSUPPORTED` | `1` | REGUTIL_default -`DisableHotCold` | Master hot/cold splitting switch in Jit64 | `DWORD` | `UNSUPPORTED` | | +`DisableHotCold` | Master hot/cold splitting switch in Jit64 | `DWORD` | `UNSUPPORTED` | | `DisableIBC` | Disables the use of IBC data | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default `UseIBCFile` | | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default #### Interop Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`AllowDComReflection` | Allows out of process DCOM clients to marshal blocked reflection types. | `DWORD` | `EXTERNAL` | `0` | -`EnableEventPipe` | Enable/disable event pipe. Non-zero values enable tracing. | `DWORD` | `INTERNAL` | `0` | -`EnableRCWCleanupOnSTAShutdown` | Performs RCW cleanup when STA shutdown is detected using IInitializeSpy in classic processes. | `DWORD` | `INTERNAL` | `0` | -`EventPipeConfig` | Configuration for EventPipe. | `STRING` | `INTERNAL` | | -`EventPipeOutputFile` | The full path including file name for the trace file that will be written when COMPlus_EnableEventPipe&=1 | `STRING` | `INTERNAL` | | -`EventPipeRundown` | Enable/disable eventpipe rundown. | `DWORD` | `INTERNAL` | `1` | -`ExposeExceptionsInCOM` | | `DWORD` | `INTERNAL` | | -`InteropLogArguments` | Log all pinned arguments passed to an interop call | `DWORD` | `EXTERNAL` | `0` | -`InteropValidatePinnedObjects` | After returning from a managed-to-unmanaged interop call, validate GC heap around objects pinned by IL stubs. | `DWORD` | `UNSUPPORTED` | `0` | -`legacyComHierarchyVisibility` | | `DWORD` | `EXTERNAL` | | -`legacyComVTableLayout` | | `DWORD` | `EXTERNAL` | | -`LocalWinMDPath` | Additional path to probe for WinMD files in if a WinRT type is not resolved using the standard paths. | `STRING` | `INTERNAL` | | -`LogCCWRefCountChange` | Outputs debug information and calls LogCCWRefCountChange_BREAKPOINT when AddRef or Release is called on a CCW. | `STRING` | `UNSUPPORTED` | | -`newComVTableLayout` | | `DWORD` | `EXTERNAL` | | -`PInvokeInline` | | `STRING` | `EXTERNAL` | | REGUTIL_default -`PreferComInsteadOfManagedRemoting` | When communicating with a cross app domain CCW, use COM instead of managed remoting. | `DWORD` | `EXTERNAL` | `0` | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`AllowDComReflection` | Allows out of process DCOM clients to marshal blocked reflection types. | `DWORD` | `EXTERNAL` | `0` | +`EnableEventPipe` | Enable/disable event pipe. Non-zero values enable tracing. | `DWORD` | `INTERNAL` | `0` | +`EnableRCWCleanupOnSTAShutdown` | Performs RCW cleanup when STA shutdown is detected using IInitializeSpy in classic processes. | `DWORD` | `INTERNAL` | `0` | +`EventPipeCircularMB` | The EventPipe circular buffer size in megabytes. | `DWORD` | `INTERNAL` | `1024` | +`EventPipeConfig` | Configuration for EventPipe. | `STRING` | `INTERNAL` | | +`EventPipeOutputPath` | The full path excluding file name for the trace file that will be written when COMPlus_EnableEventPipe=1 | `STRING` | `INTERNAL` | | +`EventPipeRundown` | Enable/disable eventpipe rundown. | `DWORD` | `INTERNAL` | `1` | +`ExposeExceptionsInCOM` | | `DWORD` | `INTERNAL` | | +`InteropLogArguments` | Log all pinned arguments passed to an interop call | `DWORD` | `EXTERNAL` | `0` | +`InteropValidatePinnedObjects` | After returning from a managed-to-unmanaged interop call, validate GC heap around objects pinned by IL stubs. | `DWORD` | `UNSUPPORTED` | `0` | +`LocalWinMDPath` | Additional path to probe for WinMD files in if a WinRT type is not resolved using the standard paths. | `STRING` | `INTERNAL` | | +`LogCCWRefCountChange` | Outputs debug information and calls LogCCWRefCountChange_BREAKPOINT when AddRef or Release is called on a CCW. | `STRING` | `UNSUPPORTED` | | +`PInvokeInline` | | `STRING` | `EXTERNAL` | | REGUTIL_default #### Interpreter Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`DumpInterpreterStubs` | Prints all interpreter stubs that are created to the console | `DWORD` | `INTERNAL` | `0` | -`Interpret` | Selectively uses the interpreter to execute the specified methods | `STRING` | `INTERNAL` | | REGUTIL_default -`InterpreterDoLoopMethods` | If set, don't check for loops, start by interpreting *all* methods | `DWORD` | `INTERNAL` | `0` | -`InterpreterFallback` | Fallback to the interpreter when the JIT compiler fails | `DWORD` | `INTERNAL` | `0` | -`InterpreterJITThreshold` | The number of times a method should be interpreted before being JITted | `DWORD` | `INTERNAL` | `10` | -`InterpreterLogFile` | If non-null, append interpreter logging to this file, else use stdout | `STRING` | `INTERNAL` | | REGUTIL_default +`DumpInterpreterStubs` | Prints all interpreter stubs that are created to the console | `DWORD` | `INTERNAL` | `0` | +`Interpret` | Selectively uses the interpreter to execute the specified methods | `STRING` | `INTERNAL` | | REGUTIL_default +`InterpreterDoLoopMethods` | If set, don't check for loops, start by interpreting *all* methods | `DWORD` | `INTERNAL` | `0` | +`InterpreterFallback` | Fallback to the interpreter when the JIT compiler fails | `DWORD` | `INTERNAL` | `0` | +`InterpreterJITThreshold` | The number of times a method should be interpreted before being JITted | `DWORD` | `INTERNAL` | `10` | +`InterpreterLogFile` | If non-null, append interpreter logging to this file, else use stdout | `STRING` | `INTERNAL` | | REGUTIL_default `InterpreterLooseRules` | If non-zero, allow ECMA spec violations required by managed C++. | `DWORD` | `INTERNAL` | `1` | REGUTIL_default -`InterpreterMethHashMax` | If non-zero, only interpret methods selected by 'Interpret' whose hash is at most this value | `DWORD` | `INTERNAL` | `UINT32_MAX` | -`InterpreterMethHashMin` | Only interpret methods selected by 'Interpret' whose hash is at least this value. or after nth | `DWORD` | `INTERNAL` | `0` | -`InterpreterPrintPostMortem` | Prints summary information about the execution to the console | `DWORD` | `INTERNAL` | `0` | -`InterpreterStubMax` | If non-zero, only interpret methods selected by 'Interpret' whose stub number is at most this value. | `DWORD` | `INTERNAL` | `UINT32_MAX` | -`InterpreterStubMin` | Only interpret methods selected by 'Interpret' whose stub num is at least this value. | `DWORD` | `INTERNAL` | `0` | +`InterpreterMethHashMax` | If non-zero, only interpret methods selected by 'Interpret' whose hash is at most this value | `DWORD` | `INTERNAL` | `UINT32_MAX` | +`InterpreterMethHashMin` | Only interpret methods selected by 'Interpret' whose hash is at least this value. or after nth | `DWORD` | `INTERNAL` | `0` | +`InterpreterPrintPostMortem` | Prints summary information about the execution to the console | `DWORD` | `INTERNAL` | `0` | +`InterpreterStubMax` | If non-zero, only interpret methods selected by 'Interpret' whose stub number is at most this value. | `DWORD` | `INTERNAL` | `UINT32_MAX` | +`InterpreterStubMin` | Only interpret methods selected by 'Interpret' whose stub num is at least this value. | `DWORD` | `INTERNAL` | `0` | `InterpreterUseCaching` | If non-zero, use the caching mechanism. | `DWORD` | `INTERNAL` | `1` | REGUTIL_default -`InterpretExclude` | Excludes the specified methods from the set selected by 'Interpret' | `STRING` | `INTERNAL` | | REGUTIL_default -`TraceInterpreterEntries` | Logs entries to interpreted methods to the console | `DWORD` | `INTERNAL` | `0` | -`TraceInterpreterIL` | Logs individual instructions of interpreted methods to the console | `DWORD` | `INTERNAL` | `0` | -`TraceInterpreterJITTransition` | Logs when the interpreter determines a method should be JITted | `DWORD` | `INTERNAL` | `0` | -`TraceInterpreterOstack` | Logs operand stack after each IL instruction of interpreted methods to the console | `DWORD` | `INTERNAL` | `0` | -`TraceInterpreterVerbose` | Logs interpreter progress with detailed messages to the console | `DWORD` | `INTERNAL` | `0` | +`InterpretExclude` | Excludes the specified methods from the set selected by 'Interpret' | `STRING` | `INTERNAL` | | REGUTIL_default +`TraceInterpreterEntries` | Logs entries to interpreted methods to the console | `DWORD` | `INTERNAL` | `0` | +`TraceInterpreterIL` | Logs individual instructions of interpreted methods to the console | `DWORD` | `INTERNAL` | `0` | +`TraceInterpreterJITTransition` | Logs when the interpreter determines a method should be JITted | `DWORD` | `INTERNAL` | `0` | +`TraceInterpreterOstack` | Logs operand stack after each IL instruction of interpreted methods to the console | `DWORD` | `INTERNAL` | `0` | +`TraceInterpreterVerbose` | Logs interpreter progress with detailed messages to the console | `DWORD` | `INTERNAL` | `0` | #### JIT Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`` | | `STRING` | `JitMeasureNowayAssertFile` | | -`AltJit` | Enables AltJit and selectively limits it to the specified methods. | `STRING` | `EXTERNAL` | | REGUTIL_default -`AltJitAssertOnNYI` | Controls the AltJit behavior of NYI stuff | `DWORD` | `INTERNAL` | `0` | -`AltJitExcludeAssemblies` | Do not use AltJit on this semicolon-delimited list of assemblies. | `STRING` | `EXTERNAL` | | REGUTIL_default -`AltJitLimit` | Max number of functions to use altjit for (decimal) | `DWORD` | | `0` | -`AltJitName` | Alternative Jit to use, will fall back to primary jit. | `STRING` | `EXTERNAL` | | REGUTIL_default -`AltJitNgen` | Enables AltJit for NGEN and selectively limits it to the specified methods. | `STRING` | `INTERNAL` | | REGUTIL_default -`AltJitSkipOnAssert` | If AltJit hits an assert, fall back to the fallback JIT. Useful in conjunction with COMPlus_ContinueOnAssert=1 | `DWORD` | | `0` | -`BreakOnDumpToken` | Breaks when using internal logging on a particular token value. | `DWORD` | | `0xffffffff` | -`DebugBreakOnVerificationFailure` | Halts the jit on verification failure | `DWORD` | | `0` | -`DumpJittedMethods` | Prints all jitted methods to the console | `DWORD` | | `0` | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`` | | `STRING` | `JitMeasureNowayAssertFile` | | +`AltJit` | Enables AltJit and selectively limits it to the specified methods. | `STRING` | `EXTERNAL` | | REGUTIL_default +`AltJitAssertOnNYI` | Controls the AltJit behavior of NYI stuff | `DWORD` | `INTERNAL` | `0` | +`AltJitExcludeAssemblies` | Do not use AltJit on this semicolon-delimited list of assemblies. | `STRING` | `EXTERNAL` | | REGUTIL_default +`AltJitLimit` | Max number of functions to use altjit for (decimal) | `DWORD` | | `0` | +`AltJitName` | Alternative Jit to use, will fall back to primary jit. | `STRING` | `EXTERNAL` | | REGUTIL_default +`AltJitNgen` | Enables AltJit for NGEN and selectively limits it to the specified methods. | `STRING` | `INTERNAL` | | REGUTIL_default +`AltJitSkipOnAssert` | If AltJit hits an assert, fall back to the fallback JIT. Useful in conjunction with COMPlus_ContinueOnAssert=1 | `DWORD` | | `0` | +`BreakOnDumpToken` | Breaks when using internal logging on a particular token value. | `DWORD` | | `0xffffffff` | +`DebugBreakOnVerificationFailure` | Halts the jit on verification failure | `DWORD` | | `0` | +`DumpJittedMethods` | Prints all jitted methods to the console | `DWORD` | | `0` | `EnableAVX` | Enable AVX instruction set for wide operations as default | `DWORD` | `EXTERNAL` | `EXTERNAL_JitEnableAVX_Default` | REGUTIL_default `FeatureSIMD` | Enable SIMD intrinsics recognition in System.Numerics.dll and/or System.Numerics.Vectors.dll | `DWORD` | `EXTERNAL` | `EXTERNAL_FeatureSIMD_Default` | REGUTIL_default -`InjectFault` | | `DWORD` | `Should` | `0` | -`InterpreterFallback` | Fallback to the interpreter when the JIT compiler fails | `DWORD` | | `0` | -`JitAggressiveInlining` | Aggressive inlining of all methods | `DWORD` | | `0` | -`JitAlignLoops` | Aligns loop targets to 8 byte boundaries | `DWORD` | `UNSUPPORTED` | | -`JitAssertOnMaxRAPasses` | | `DWORD` | | `0` | -`JitBreak` | Stops in the importer when compiling a specified method | `SSV` | | | +`InjectFault` | | `DWORD` | `Should` | `0` | +`JitAggressiveInlining` | Aggressive inlining of all methods | `DWORD` | | `0` | +`JitAlignLoops` | Aligns loop targets to 8 byte boundaries | `DWORD` | `UNSUPPORTED` | | +`JitAssertOnMaxRAPasses` | | `DWORD` | | `0` | +`JitBreak` | Stops in the importer when compiling a specified method | `SSV` | | | `JitBreakEmit` | | `DWORD` | `INTERNAL` | `(DWORD)-1` | REGUTIL_default -`JitBreakEmitOutputInstr` | | `DWORD` | | `-1` | -`JitBreakMorphTree` | | `DWORD` | | `0xffffffff` | -`JitBreakOnBadCode` | | `DWORD` | | `0` | -`JITBreakOnMinOpts` | Halt if jit switches to MinOpts | `DWORD` | `JitBreakOnMinOpts` | `0` | -`JitBreakOnUnsafeCode` | | `DWORD` | | `0` | -`JitCanUseSSE2` | | `DWORD` | | `-1` | -`JitCloneLoops` | If 0, don't clone. Otherwise clone loops for optimizations. | `DWORD` | | `1` | -`JitComponentUnitTests` | Run JIT component unit tests | `DWORD` | `RunComponentUnitTests` | `0` | -`JitDebugBreak` | | `SSV` | | | -`JitDebuggable` | | `DWORD` | `INTERNAL` | | -`JitDebugLogLoopCloning` | In debug builds log places where loop cloning optimizations are performed on the fast path. | `DWORD` | | `0` | -`JitDefaultFill` | In debug builds, initialize the memory allocated by the nra with this byte. | `DWORD` | | `0xdd` | -`JitDiffableDasm` | Make the disassembly diff-able | `DWORD` | `DiffableDasm` | `0` | -`JitDirectAlloc` | | `DWORD` | | `0` | -`JitDisasm` | Dumps disassembly for specified method | `SSV` | | | -`JitDoAssertionProp` | Perform assertion propagation optimization | `DWORD` | | `1` | -`JitDoCopyProp` | Perform copy propagation on variables that appear redundant | `DWORD` | | `1` | -`JitDoEarlyProp` | Perform Early Value Propagation | `DWORD` | | `1` | -`JitDoLoopHoisting` | Perform loop hoisting on loop invariant values | `DWORD` | | `1` | -`JitDoRangeAnalysis` | Perform range check analysis | `DWORD` | | `1` | -`JitDoSsa` | Perform Static Single Assignment (SSA) numbering on the variables | `DWORD` | | `1` | -`JitDoubleAlign` | | `DWORD` | | `1` | -`JitDoValueNumber` | Perform value numbering on method expressions | `DWORD` | | `1` | -`JitDump` | Dumps trees for specified method | `SSV` | | | -`JitDumpASCII` | Uses only ASCII characters in tree dumps | `DWORD` | | `1` | -`JitDumpBeforeAfterMorph` | If 1, display each tree before/after morphing | `DWORD` | `TreesBeforeAfterMorph` | `0` | -`JitDumpFg` | Dumps Xml/Dot Flowgraph for specified method | `STRING` | | | -`JitDumpFgDir` | Directory for Xml/Dot flowgraph dump(s) | `STRING` | | | -`JitDumpFgDot` | Set to non-zero to emit Dot instead of Xml Flowgraph dump | `DWORD` | | `0` | -`JitDumpFgFile` | Filename for Xml/Dot flowgraph dump(s) | `STRING` | | | -`JitDumpFgPhase` | Phase-based Xml/Dot flowgraph support. Set to the short name of a phase to see the flowgraph after that phase. Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all phases | `STRING` | | | -`JitDumpIR` | Dumps trees (in linear IR form) for specified method | `SSV` | | | -`JitDumpIRFormat` | Comma separated format control for JitDumpIR, values = {types \| locals \| ssa \| valnums \| kinds \| flags \| nodes \| nolists \| nostmts \| noleafs \| trees \| dataflow} | `STRING` | | | -`JitDumpIRPhase` | Phase control for JitDumpIR, values = {* \| phasename} | `STRING` | | | -`JitDumpTerseLsra` | Produce terse dump output for LSRA | `DWORD` | | `1` | -`JitDumpToDebugger` | Output JitDump output to the debugger | `DWORD` | | `0` | -`JitDumpVerboseSsa` | Produce especially verbose dump output for SSA | `DWORD` | | `0` | -`JitDumpVerboseTrees` | Enable more verbose tree dumps | `DWORD` | | `0` | -`JitEECallTimingInfo` | | `DWORD` | | `0` | -`JitEHDump` | Dump the EH table for the method, as reported to the VM | `SSV` | | | -`JitELTHookEnabled` | On ARM, setting this will emit Enter/Leave/TailCall callbacks | `DWORD` | `INTERNAL` | `0` | -`JitEmitPrintRefRegs` | | `DWORD` | | `0` | -`JitEnableDevirtualization` | Enable devirtualization in importer | `DWORD` | | `1` | -`JitEnableFinallyCloning` | | `DWORD` | | `1` | -`JitEnableLateDevirtualization` | Enable devirtualization after inlining | `DWORD` | | `1` | +`JitBreakEmitOutputInstr` | | `DWORD` | | `-1` | +`JitBreakMorphTree` | | `DWORD` | | `0xffffffff` | +`JitBreakOnBadCode` | | `DWORD` | | `0` | +`JITBreakOnMinOpts` | Halt if jit switches to MinOpts | `DWORD` | `JitBreakOnMinOpts` | `0` | +`JitBreakOnUnsafeCode` | | `DWORD` | | `0` | +`JitCanUseSSE2` | | `DWORD` | | `-1` | +`JitCloneLoops` | If 0, don't clone. Otherwise clone loops for optimizations. | `DWORD` | | `1` | +`JitComponentUnitTests` | Run JIT component unit tests | `DWORD` | `RunComponentUnitTests` | `0` | +`JitDebugBreak` | | `SSV` | | | +`JitDebugDump` | | `SSV` | | | +`JitDebuggable` | | `DWORD` | `INTERNAL` | | +`JitDebugLogLoopCloning` | In debug builds log places where loop cloning optimizations are performed on the fast path. | `DWORD` | | `0` | +`JitDefaultFill` | In debug builds, initialize the memory allocated by the nra with this byte. | `DWORD` | | `0xdd` | +`JitDiffableDasm` | Make the disassembly diff-able | `DWORD` | `DiffableDasm` | `0` | +`JitDirectAlloc` | | `DWORD` | | `0` | +`JitDisasm` | Dumps disassembly for specified method | `SSV` | | | +`JitDisasmAssemblies` | Only show JitDisasm and related info for methods from this semicolon-delimited list of assemblies. | `STRING` | | | +`JitDoAssertionProp` | Perform assertion propagation optimization | `DWORD` | | `1` | +`JitDoCopyProp` | Perform copy propagation on variables that appear redundant | `DWORD` | | `1` | +`JitDoEarlyProp` | Perform Early Value Propagation | `DWORD` | | `1` | +`JitDoLoopHoisting` | Perform loop hoisting on loop invariant values | `DWORD` | | `1` | +`JitDoRangeAnalysis` | Perform range check analysis | `DWORD` | | `1` | +`JitDoSsa` | Perform Static Single Assignment (SSA) numbering on the variables | `DWORD` | | `1` | +`JitDoubleAlign` | | `DWORD` | | `1` | +`JitDoValueNumber` | Perform value numbering on method expressions | `DWORD` | | `1` | +`JitDump` | Dumps trees for specified method | `SSV` | | | +`JitDumpASCII` | Uses only ASCII characters in tree dumps | `DWORD` | | `1` | +`JitDumpBeforeAfterMorph` | If 1, display each tree before/after morphing | `DWORD` | `TreesBeforeAfterMorph` | `0` | +`JitDumpFg` | Dumps Xml/Dot Flowgraph for specified method | `STRING` | | | +`JitDumpFgDir` | Directory for Xml/Dot flowgraph dump(s) | `STRING` | | | +`JitDumpFgDot` | Set to non-zero to emit Dot instead of Xml Flowgraph dump | `DWORD` | | `0` | +`JitDumpFgFile` | Filename for Xml/Dot flowgraph dump(s) | `STRING` | | | +`JitDumpFgPhase` | Phase-based Xml/Dot flowgraph support. Set to the short name of a phase to see the flowgraph after that phase. Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all phases | `STRING` | | | +`JitDumpIR` | Dumps trees (in linear IR form) for specified method | `SSV` | | | +`JitDumpIRFormat` | Comma separated format control for JitDumpIR, values = {types \| locals \| ssa \| valnums \| kinds \| flags \| nodes \| nolists \| nostmts \| noleafs \| trees \| dataflow} | `STRING` | | | +`JitDumpIRPhase` | Phase control for JitDumpIR, values = {* \| phasename} | `STRING` | | | +`JitDumpTerseLsra` | Produce terse dump output for LSRA | `DWORD` | | `1` | +`JitDumpToDebugger` | Output JitDump output to the debugger | `DWORD` | | `0` | +`JitDumpVerboseSsa` | Produce especially verbose dump output for SSA | `DWORD` | | `0` | +`JitDumpVerboseTrees` | Enable more verbose tree dumps | `DWORD` | | `0` | +`JitEECallTimingInfo` | | `DWORD` | | `0` | +`JitEHDump` | Dump the EH table for the method, as reported to the VM | `SSV` | | | +`JitELTHookEnabled` | On ARM, setting this will emit Enter/Leave/TailCall callbacks | `DWORD` | `INTERNAL` | `0` | +`JitEmitPrintRefRegs` | | `DWORD` | | `0` | +`JitEnableDevirtualization` | Enable devirtualization in importer | `DWORD` | | `1` | +`JitEnableFinallyCloning` | | `DWORD` | | `1` | +`JitEnableGuardedDevirtualization` | | `DWORD` | | `0` | +`JitEnableLateDevirtualization` | Enable devirtualization after inlining | `DWORD` | | `1` | `JitEnableNoWayAssert` | | `DWORD` | `INTERNAL` | `INTERNAL_JitEnableNoWayAssert_Default` | REGUTIL_default -`JitEnablePCRelAddr` | Whether absolute addr be encoded as PC-rel offset by RyuJIT where possible | `DWORD` | `EnablePCRelAddr` | `1` | -`JitEnableRemoveEmptyTry` | | `DWORD` | | `1` | -`JitExclude` | | `SSV` | | | -`JitExpensiveDebugCheckLevel` | Level indicates how much checking beyond the default to do in debug builds (currently 1-2) | `DWORD` | | `0` | -`JitForceFallback` | Set to non-zero to test NOWAY assert by forcing a retry | `DWORD` | | `0` | -`JitForceProcedureSplitting` | | `SSV` | | | -`JitForceVer` | | `DWORD` | | `0` | -`JitFramed` | Forces EBP frames | `DWORD` | `UNSUPPORTED` | | -`JitFullyInt` | Forces Fully interruptible code | `DWORD` | | `0` | -`JitFuncInfoLogFile` | If set, gather JIT function info and write to this file. | `STRING` | `INTERNAL` | | -`JitFunctionTrace` | If non-zero, print JIT start/end logging | `DWORD` | | `0` | -`JitGCChecks` | | `DWORD` | | `0` | -`JitGCDump` | | `SSV` | | | -`JitGCInfoLogging` | If true, prints GCInfo-related output to standard output. | `DWORD` | | `0` | +`JitEnablePCRelAddr` | Whether absolute addr be encoded as PC-rel offset by RyuJIT where possible | `DWORD` | `EnablePCRelAddr` | `1` | +`JitEnableRemoveEmptyTry` | | `DWORD` | | `1` | +`JitExclude` | | `SSV` | | | +`JitExpensiveDebugCheckLevel` | Level indicates how much checking beyond the default to do in debug builds (currently 1-2) | `DWORD` | | `0` | +`JitForceFallback` | Set to non-zero to test NOWAY assert by forcing a retry | `DWORD` | | `0` | +`JitForceProcedureSplitting` | | `SSV` | | | +`JitForceVer` | | `DWORD` | | `0` | +`JitFramed` | Forces EBP frames | `DWORD` | `UNSUPPORTED` | | +`JitFullyInt` | Forces Fully interruptible code | `DWORD` | | `0` | +`JitFuncInfoLogFile` | If set, gather JIT function info and write to this file. | `STRING` | `INTERNAL` | | +`JitFunctionFile` | | `STRING` | | | +`JitFunctionTrace` | If non-zero, print JIT start/end logging | `DWORD` | | `0` | +`JitGCChecks` | | `DWORD` | | `0` | +`JitGCDump` | | `SSV` | | | +`JitGCInfoLogging` | If true, prints GCInfo-related output to standard output. | `DWORD` | | `0` | `JitGCStress` | GC stress mode for jit | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`JitHalt` | Emits break instruction into jitted code | `SSV` | | | -`JitHashBreak` | Same as JitBreak, but for a method hash | `DWORD` | | `-1` | -`JitHashDump` | Same as JitDump, but for a method hash | `DWORD` | | `-1` | -`JitHashDumpIR` | Same as JitDumpIR, but for a method hash | `DWORD` | | `-1` | -`JitHashHalt` | Same as JitHalt, but for a method hash | `DWORD` | | `-1` | -`JitHeartbeat` | | `DWORD` | `INTERNAL` | `0` | -`JitHelperLogging` | | `DWORD` | `INTERNAL` | `0` | -`JitImportBreak` | | `SSV` | | | -`JitInclude` | | `SSV` | | | -`JitInlineAdditionalMultiplier` | | `DWORD` | | `0` | -`JITInlineDepth` | | `DWORD` | `JitInlineDepth` | `DEFAULT_MAX_INLINE_DEPTH` | -`JitInlineDumpData` | | `DWORD` | | `0` | -`JitInlineDumpXml` | 1 = full xml (+ failures in DEBUG) 2 = only methods with inlines (+ failures in DEBUG) 3 = only methods with inlines, no failures | `DWORD` | | `0` | -`JitInlineLimit` | | `DWORD` | | `-1` | -`JitInlinePolicyDiscretionary` | | `DWORD` | | `0` | -`JitInlinePolicyFull` | | `DWORD` | | `0` | -`JitInlinePolicyModel` | | `DWORD` | | `0` | -`JitInlinePolicyRandom` | nonzero enables; value is the external random seed | `DWORD` | | `0` | -`JitInlinePolicyReplay` | | `DWORD` | | `0` | -`JitInlinePolicySize` | | `DWORD` | | `0` | -`JitInlinePrintStats` | | `DWORD` | | `0` | -`JitInlineReplayFile` | | `STRING` | | | -`JitInlineSIMDMultiplier` | | `DWORD` | | `3` | -`JITInlineSize` | | `DWORD` | `JitInlineSize` | `DEFAULT_MAX_INLINE_SIZE` | +`JitGuardedDevirtualizationGuessBestClass` | | `DWORD` | | `1` | +`JitGuardedDevirtualizationGuessUniqueInterface` | | `DWORD` | | `1` | +`JitHalt` | Emits break instruction into jitted code | `SSV` | | | +`JitHashBreak` | Same as JitBreak, but for a method hash | `DWORD` | | `-1` | +`JitHashDump` | Same as JitDump, but for a method hash | `DWORD` | | `-1` | +`JitHashDumpIR` | Same as JitDumpIR, but for a method hash | `DWORD` | | `-1` | +`JitHashHalt` | Same as JitHalt, but for a method hash | `DWORD` | | `-1` | +`JitHeartbeat` | | `DWORD` | `INTERNAL` | `0` | +`JitHelperLogging` | | `DWORD` | `INTERNAL` | `0` | +`JitImportBreak` | | `SSV` | | | +`JitInclude` | | `SSV` | | | +`JitInlineAdditionalMultiplier` | | `DWORD` | | `0` | +`JITInlineDepth` | | `DWORD` | `JitInlineDepth` | `DEFAULT_MAX_INLINE_DEPTH` | +`JitInlineDumpData` | | `DWORD` | | `0` | +`JitInlineDumpXml` | 1 = full xml (+ failures in DEBUG) 2 = only methods with inlines (+ failures in DEBUG) 3 = only methods with inlines, no failures | `DWORD` | | `0` | +`JitInlineLimit` | | `DWORD` | | `-1` | +`JitInlinePolicyDiscretionary` | | `DWORD` | | `0` | +`JitInlinePolicyFull` | | `DWORD` | | `0` | +`JitInlinePolicyModel` | | `DWORD` | | `0` | +`JitInlinePolicyRandom` | nonzero enables; value is the external random seed | `DWORD` | | `0` | +`JitInlinePolicyReplay` | | `DWORD` | | `0` | +`JitInlinePolicySize` | | `DWORD` | | `0` | +`JitInlinePrintStats` | | `DWORD` | | `0` | +`JitInlineReplayFile` | | `STRING` | | | +`JitInlineSIMDMultiplier` | | `DWORD` | | `3` | +`JITInlineSize` | | `DWORD` | `JitInlineSize` | `DEFAULT_MAX_INLINE_SIZE` | `JitLargeBranches` | Force using the largest conditional branch format | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`JitLateDisasm` | | `SSV` | | | -`JITLateDisasmTo` | | `STRING` | `JitLateDisasmTo` | | -`JitLockWrite` | Force all volatile writes to be 'locked' | `DWORD` | `INTERNAL` | `0` | -`JitLongAddress` | Force using the large pseudo instruction form for long address | `DWORD` | | `0` | -`JitLoopHoistStats` | Display JIT loop hoisting statistics | `DWORD` | `DisplayLoopHoistStats` | `0` | -`JitLsraStats` | Display JIT Linear Scan Register Allocator statistics | `DWORD` | `DisplayLsraStats` | `0` | -`JITMaxTempAssert` | | `DWORD` | `JitMaxTempAssert` | `1` | -`JitMaxUncheckedOffset` | | `DWORD` | | `8` | -`JitMeasureIR` | If set, measure the IR size after some phases and report it in the time log. | `DWORD` | | `0` | -`JitMeasureNowayAssert` | Set to 1 to measure noway_assert usage. Only valid if MEASURE_NOWAY is defined. | `DWORD` | | `0` | +`JitLateDisasm` | | `SSV` | | | +`JITLateDisasmTo` | | `STRING` | `JitLateDisasmTo` | | +`JitLockWrite` | Force all volatile writes to be 'locked' | `DWORD` | `INTERNAL` | `0` | +`JitLongAddress` | Force using the large pseudo instruction form for long address | `DWORD` | | `0` | +`JitLoopHoistStats` | Display JIT loop hoisting statistics | `DWORD` | `DisplayLoopHoistStats` | `0` | +`JitLsraStats` | Display JIT Linear Scan Register Allocator statistics | `DWORD` | `DisplayLsraStats` | `0` | +`JITMaxTempAssert` | | `DWORD` | `JitMaxTempAssert` | `1` | +`JitMaxUncheckedOffset` | | `DWORD` | | `8` | +`JitMeasureIR` | If set, measure the IR size after some phases and report it in the time log. | `DWORD` | | `0` | +`JitMeasureNowayAssert` | Set to 1 to measure noway_assert usage. Only valid if MEASURE_NOWAY is defined. | `DWORD` | | `0` | `JitMemStats` | Display JIT memory usage statistics | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`JITMinOpts` | Forces MinOpts | `DWORD` | `UNSUPPORTED` | | -`JITMinOptsBbCount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsBbCount` | `DEFAULT_MIN_OPTS_BB_COUNT` | -`JITMinOptsCodeSize` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsCodeSize` | `DEFAULT_MIN_OPTS_CODE_SIZE` | -`JITMinOptsInstrCount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsInstrCount` | `DEFAULT_MIN_OPTS_INSTR_COUNT` | -`JITMinOptsLvNumcount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsLvNumCount` | `DEFAULT_MIN_OPTS_LV_NUM_COUNT` | -`JITMinOptsLvRefcount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsLvRefCount` | `DEFAULT_MIN_OPTS_LV_REF_COUNT` | -`JITMinOptsName` | Forces MinOpts for a named function | `SSV` | `JitMinOptsName` | | -`JitMinOptsTrackGCrefs` | Track GC roots | `DWORD` | | `JitMinOptsTrackGCrefs_Default` | -`JitName` | Primary Jit to use | `STRING` | `EXTERNAL` | | -`JitNoCMOV` | | `DWORD` | | `0` | -`JitNoCSE` | | `DWORD` | | `0` | -`JitNoCSE2` | | `DWORD` | | `0` | -`JitNoForceFallback` | Set to non-zero to prevent NOWAY assert testing. Overrides COMPlus_JitForceFallback and JIT stress flags. | `DWORD` | | `0` | -`JitNoHoist` | | `DWORD` | | `0` | -`JitNoInline` | Disables inlining of all methods | `DWORD` | | `0` | -`JitNoInlineRange` | | `STRING` | | | -`JitNoMemoryBarriers` | If 1, don't generate memory barriers | `DWORD` | | `0` | -`JitNoProcedureSplitting` | Disallow procedure splitting for specified methods | `SSV` | | | -`JitNoProcedureSplittingEH` | Disallow procedure splitting for specified methods if they contain exception handling | `SSV` | | | -`JitNoRegLoc` | | `DWORD` | | `0` | -`JitNoRngChks` | If 1, don't generate range checks | `DWORD` | `JitNoRangeChks` | `0` | -`JitNoStructPromotion` | Disables struct promotion in Jit32 | `DWORD` | | `0` | -`JitNoUnroll` | | `DWORD` | | `0` | -`JitOptimizeType` | | `DWORD` | `EXTERNAL` | | -`JitOptRepeat` | Runs optimizer multiple times on the method | `SSV` | | | -`JitOptRepeatCount` | Number of times to repeat opts when repeating | `DWORD` | | `2` | -`JitOrder` | | `DWORD` | | `0` | -`JITPInvokeCheckEnabled` | | `DWORD` | `JitPInvokeCheckEnabled` | `0` | -`JITPInvokeEnabled` | | `DWORD` | `JitPInvokeEnabled` | `1` | -`JitPrintDevirtualizedMethods` | | `DWORD` | | `0` | +`JITMinOpts` | Forces MinOpts | `DWORD` | `UNSUPPORTED` | | +`JITMinOptsBbCount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsBbCount` | `DEFAULT_MIN_OPTS_BB_COUNT` | +`JITMinOptsCodeSize` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsCodeSize` | `DEFAULT_MIN_OPTS_CODE_SIZE` | +`JITMinOptsInstrCount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsInstrCount` | `DEFAULT_MIN_OPTS_INSTR_COUNT` | +`JITMinOptsLvNumcount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsLvNumCount` | `DEFAULT_MIN_OPTS_LV_NUM_COUNT` | +`JITMinOptsLvRefcount` | Internal jit control of MinOpts | `DWORD` | `JitMinOptsLvRefCount` | `DEFAULT_MIN_OPTS_LV_REF_COUNT` | +`JITMinOptsName` | Forces MinOpts for a named function | `SSV` | `JitMinOptsName` | | +`JitMinOptsTrackGCrefs` | Track GC roots | `DWORD` | | `JitMinOptsTrackGCrefs_Default` | +`JitName` | Primary Jit to use | `STRING` | `EXTERNAL` | | +`JitNoCMOV` | | `DWORD` | | `0` | +`JitNoCSE` | | `DWORD` | | `0` | +`JitNoCSE2` | | `DWORD` | | `0` | +`JitNoForceFallback` | Set to non-zero to prevent NOWAY assert testing. Overrides COMPlus_JitForceFallback and JIT stress flags. | `DWORD` | | `0` | +`JitNoHoist` | | `DWORD` | | `0` | +`JitNoInline` | Disables inlining of all methods | `DWORD` | | `0` | +`JitNoInlineRange` | | `STRING` | | | +`JitNoMemoryBarriers` | If 1, don't generate memory barriers | `DWORD` | | `0` | +`JitNoProcedureSplitting` | Disallow procedure splitting for specified methods | `SSV` | | | +`JitNoProcedureSplittingEH` | Disallow procedure splitting for specified methods if they contain exception handling | `SSV` | | | +`JitNoRegLoc` | | `DWORD` | | `0` | +`JitNoRngChks` | If 1, don't generate range checks | `DWORD` | `JitNoRangeChks` | `0` | +`JitNoStructPromotion` | Disables struct promotion in Jit32 | `DWORD` | | `0` | +`JitNoUnroll` | | `DWORD` | | `0` | +`JitObjectStackAllocation` | | `DWORD` | | `0` | +`JitOptimizeType` | | `DWORD` | `EXTERNAL` | | +`JitOptRepeat` | Runs optimizer multiple times on the method | `SSV` | | | +`JitOptRepeatCount` | Number of times to repeat opts when repeating | `DWORD` | | `2` | +`JitOrder` | | `DWORD` | | `0` | +`JITPInvokeCheckEnabled` | | `DWORD` | `JitPInvokeCheckEnabled` | `0` | +`JITPInvokeEnabled` | | `DWORD` | `JitPInvokeEnabled` | `1` | +`JitPrintDevirtualizedMethods` | | `DWORD` | | `0` | `JitPrintInlinedMethods` | | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default -`JitRange` | | `STRING` | | | +`JitQueryCurrentStaticFieldClass` | | `DWORD` | | `1` | +`JitRange` | | `STRING` | | | `JitRegisterFP` | Control FP enregistration | `DWORD` | `EXTERNAL` | `3` | REGUTIL_default -`JitReportFastTailCallDecisions` | | `DWORD` | | `0` | -`JITRequired` | | `DWORD` | `JitRequired` | `-1` | -`JITRoundFloat` | | `DWORD` | `JitRoundFloat` | `DEFAULT_ROUND_LEVEL` | -`JitSkipArrayBoundCheck` | | `DWORD` | | `0` | -`JitSlowDebugChecksEnabled` | Turn on slow debug checks | `DWORD` | | `1` | -`JitSplitFunctionSize` | On ARM, use this as the maximum function/funclet size for creating function fragments (and creating multiple RUNTIME_FUNCTION entries) | `DWORD` | | `0` | -`JitSsaStress` | Perturb order of processing of blocks in SSA; 0 = no stress; 1 = use method hash; * = supplied value as random hash | `DWORD` | | `0` | -`JitStackAllocToLocalSize` | | `DWORD` | | `DEFAULT_MAX_LOCALLOC_TO_LOCAL_SIZE` | -`JitStackChecks` | | `DWORD` | | `0` | -`JitStackProbes` | | `DWORD` | `StackProbesOverride` | `0` | -`JitStress` | Internal Jit stress mode: 0 = no stress, 2 = all stress, other = vary stress based on a hash of the method and this value | `DWORD` | | `0` | -`JitStressBBProf` | Internal Jit stress mode | `DWORD` | | `0` | -`JitStressBiasedCSE` | Internal Jit stress mode: decimal bias value between (0,100) to perform CSE on a candidate. 100% = All CSEs. 0% = 0 CSE. (> 100) means no stress. | `DWORD` | | `0x101` | -`JitStressFP` | Internal Jit stress mode | `DWORD` | | `0` | -`JitStressModeNames` | Internal Jit stress mode: stress using the given set of stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL | `STRING` | | | -`JitStressModeNamesNot` | Internal Jit stress mode: do NOT stress using the given set of stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL | `STRING` | | | -`JitStressModeNamesOnly` | Internal Jit stress: if nonzero, only enable stress modes listed in JitStressModeNames | `DWORD` | | `0` | -`JitStressOnly` | Internal Jit stress mode: stress only the specified method(s) | `SSV` | | | -`JitStressRange` | Internal Jit stress mode | `STRING` | | | -`JitStressRegs` | | `DWORD` | | `0` | -`JitStrictCheckForNonVirtualCallToVirtualMethod` | | `DWORD` | | `1` | -`JitTelemetry` | If non-zero, gather JIT telemetry data | `DWORD` | `EXTERNAL` | `1` | -`JitTimeLogCsv` | If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds. | `STRING` | `INTERNAL` | | -`JitTimeLogFile` | If set, gather JIT throughput data and write to this file. | `STRING` | `INTERNAL` | | -`JitUnwindDump` | Dump the unwind codes for the method | `SSV` | | | -`JitVerificationDisable` | | `DWORD` | `INTERNAL` | | -`JitVNMapSelBudget` | Max # of MapSelect's considered for a particular top-level invocation. | `DWORD` | `INTERNAL` | `100` | -`JitVNMapSelLimit` | If non-zero, assert if # of VNF_MapSelect applications considered reaches this | `DWORD` | | `0` | -`MultiCoreJitProfile` | If set, use the file to store/control multi-core JIT. | `STRING` | `INTERNAL` | | -`MultiCoreJitProfileWriteDelay` | Set the delay after which the multi-core JIT profile will be written to disk. | `DWORD` | `INTERNAL` | `12` | -`NetFx40_PInvokeStackResilience` | Makes P/Invoke resilient against mismatched signature and calling convention (significant perf penalty). | `DWORD` | `EXTERNAL` | `(DWORD)-1` | -`NgenHashDump` | same as JitHashDump, but for ngen | `DWORD` | | `-1` | -`NgenHashDumpIR` | same as JitHashDumpIR, but for ngen | `DWORD` | | `-1` | -`NgenOrder` | | `DWORD` | | `0` | -`RunAltJitCode` | If non-zero, and the compilation succeeds for an AltJit, then use the code. If zero, then we always throw away the generated code and fall back to the default compiler. | `DWORD` | | `1` | -`SIMD16ByteOnly` | Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit) | `DWORD` | `INTERNAL` | `0` | -`StackSamplingAfter` | When to start sampling (for some sort of app steady state), i.e., initial delay for sampling start in milliseconds. | `DWORD` | `UNSUPPORTED` | `0` | -`StackSamplingEnabled` | Is stack sampling based tracking of evolving hot methods enabled. | `DWORD` | `UNSUPPORTED` | `0` | -`StackSamplingEvery` | How frequent should thread stacks be sampled in milliseconds. | `DWORD` | `UNSUPPORTED` | `100` | -`StackSamplingNumMethods` | Number of evolving methods to track as hot and JIT them in the background at a given point of execution. | `DWORD` | `UNSUPPORTED` | `32` | -`StressCOMCall` | | `DWORD` | | `0` | -`TailCallLoopOpt` | Convert recursive tail calls to loops | `DWORD` | `EXTERNAL` | `1` | -`TailCallMax` | | `STRING` | `INTERNAL` | | REGUTIL_default -`TailCallOpt` | | `STRING` | `EXTERNAL` | | REGUTIL_default -`TailcallStress` | | `DWORD` | | `0` | +`JitReportFastTailCallDecisions` | | `DWORD` | | `0` | +`JITRequired` | | `DWORD` | `JitRequired` | `-1` | +`JITRoundFloat` | | `DWORD` | `JitRoundFloat` | `DEFAULT_ROUND_LEVEL` | +`JitSaveFpLrWithCalleeSavedRegisters` | | `DWORD` | | `0` | +`JitSkipArrayBoundCheck` | | `DWORD` | | `0` | +`JitSlowDebugChecksEnabled` | Turn on slow debug checks | `DWORD` | | `1` | +`JitSplitFunctionSize` | On ARM, use this as the maximum function/funclet size for creating function fragments (and creating multiple RUNTIME_FUNCTION entries) | `DWORD` | | `0` | +`JitSsaStress` | Perturb order of processing of blocks in SSA; 0 = no stress; 1 = use method hash; * = supplied value as random hash | `DWORD` | | `0` | +`JitStackAllocToLocalSize` | | `DWORD` | | `DEFAULT_MAX_LOCALLOC_TO_LOCAL_SIZE` | +`JitStackChecks` | | `DWORD` | | `0` | +`JitStdOutFile` | If set, sends JIT's stdout output to this file. | `STRING` | | | +`JitStress` | Internal Jit stress mode: 0 = no stress, 2 = all stress, other = vary stress based on a hash of the method and this value | `DWORD` | | `0` | +`JitStressBBProf` | Internal Jit stress mode | `DWORD` | | `0` | +`JitStressBiasedCSE` | Internal Jit stress mode: decimal bias value between (0,100) to perform CSE on a candidate. 100% = All CSEs. 0% = 0 CSE. (> 100) means no stress. | `DWORD` | | `0x101` | +`JitStressFP` | Internal Jit stress mode | `DWORD` | | `0` | +`JitStressModeNames` | Internal Jit stress mode: stress using the given set of stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL | `STRING` | | | +`JitStressModeNamesNot` | Internal Jit stress mode: do NOT stress using the given set of stress mode names, e.g. STRESS_REGS, STRESS_TAILCALL | `STRING` | | | +`JitStressModeNamesOnly` | Internal Jit stress: if nonzero, only enable stress modes listed in JitStressModeNames | `DWORD` | | `0` | +`JitStressOnly` | Internal Jit stress mode: stress only the specified method(s) | `SSV` | | | +`JitStressRange` | Internal Jit stress mode | `STRING` | | | +`JitStressRegs` | | `DWORD` | | `0` | +`JitStrictCheckForNonVirtualCallToVirtualMethod` | | `DWORD` | | `1` | +`JitTelemetry` | If non-zero, gather JIT telemetry data | `DWORD` | `EXTERNAL` | `1` | +`JitTimeLogCsv` | If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds. | `STRING` | `INTERNAL` | | +`JitTimeLogFile` | If set, gather JIT throughput data and write to this file. | `STRING` | `INTERNAL` | | +`JitUnwindDump` | Dump the unwind codes for the method | `SSV` | | | +`JitVerificationDisable` | | `DWORD` | `INTERNAL` | | +`JitVNMapSelBudget` | Max # of MapSelect's considered for a particular top-level invocation. | `DWORD` | `INTERNAL` | `100` | +`JitVNMapSelLimit` | If non-zero, assert if # of VNF_MapSelect applications considered reaches this | `DWORD` | | `0` | +`MultiCoreJitProfile` | If set, use the file to store/control multi-core JIT. | `STRING` | `INTERNAL` | | +`MultiCoreJitProfileWriteDelay` | Set the delay after which the multi-core JIT profile will be written to disk. | `DWORD` | `INTERNAL` | `12` | +`NetFx40_PInvokeStackResilience` | Makes P/Invoke resilient against mismatched signature and calling convention (significant perf penalty). | `DWORD` | `EXTERNAL` | `(DWORD)-1` | +`NgenHashDump` | same as JitHashDump, but for ngen | `DWORD` | | `-1` | +`NgenHashDumpIR` | same as JitHashDumpIR, but for ngen | `DWORD` | | `-1` | +`NgenOrder` | | `DWORD` | | `0` | +`RunAltJitCode` | If non-zero, and the compilation succeeds for an AltJit, then use the code. If zero, then we always throw away the generated code and fall back to the default compiler. | `DWORD` | | `1` | +`SIMD16ByteOnly` | Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit) | `DWORD` | `INTERNAL` | `0` | +`StackSamplingAfter` | When to start sampling (for some sort of app steady state), i.e., initial delay for sampling start in milliseconds. | `DWORD` | `UNSUPPORTED` | `0` | +`StackSamplingEnabled` | Is stack sampling based tracking of evolving hot methods enabled. | `DWORD` | `UNSUPPORTED` | `0` | +`StackSamplingEvery` | How frequent should thread stacks be sampled in milliseconds. | `DWORD` | `UNSUPPORTED` | `100` | +`StackSamplingNumMethods` | Number of evolving methods to track as hot and JIT them in the background at a given point of execution. | `DWORD` | `UNSUPPORTED` | `32` | +`StressCOMCall` | | `DWORD` | | `0` | +`TailCallLoopOpt` | Convert recursive tail calls to loops | `DWORD` | `EXTERNAL` | `1` | +`TailCallMax` | | `STRING` | `INTERNAL` | | REGUTIL_default +`TailCallOpt` | | `STRING` | `EXTERNAL` | | REGUTIL_default +`TailcallStress` | | `DWORD` | | `0` | #### JIT Hardware Intrinsics Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`EnableAES` | Enable AES | `DWORD` | | `1` | -`EnableAVX` | | `DWORD` | | `1` | -`EnableAVX2` | Enable AVX2 | `DWORD` | | `1` | -`EnableBMI1` | Enable BMI1 | `DWORD` | | `1` | -`EnableBMI2` | Enable BMI2 | `DWORD` | | `1` | -`EnableFMA` | Enable FMA | `DWORD` | | `1` | -`EnableIncompleteISAClass` | Enable testing not-yet-implemented intrinsic classes | `DWORD` | | `0` | -`EnableLZCNT` | Enable AES | `DWORD` | | `1` | -`EnablePCLMULQDQ` | Enable PCLMULQDQ | `DWORD` | | `1` | -`EnablePOPCNT` | Enable POPCNT | `DWORD` | | `1` | -`EnableSSE` | Enable SSE | `DWORD` | | `1` | -`EnableSSE2` | Enable SSE2 | `DWORD` | | `1` | -`EnableSSE3` | Enable SSE3 | `DWORD` | | `1` | -`EnableSSE3_4` | Enable SSE3, SSSE3, SSE 4.1 and 4.2 instruction set as default | `DWORD` | | `1` | -`EnableSSE41` | Enable SSE41 | `DWORD` | | `1` | -`EnableSSE42` | Enable SSE42 EnableAVX is already defined for DEBUG and non-DEBUG mode both | `DWORD` | | `1` | -`EnableSSSE3` | Enable SSSE3 | `DWORD` | | `1` | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`EnableAES` | Enable AES | `DWORD` | | `1` | +`EnableArm64Aes` | | `DWORD` | ` ` | `1` | +`EnableArm64Atomics` | | `DWORD` | ` ` | `1` | +`EnableArm64Crc32` | | `DWORD` | ` ` | `1` | +`EnableArm64Dcpop` | | `DWORD` | ` ` | `1` | +`EnableArm64Dp` | | `DWORD` | ` ` | `1` | +`EnableArm64Fcma` | | `DWORD` | ` ` | `1` | +`EnableArm64Fp` | | `DWORD` | ` ` | `1` | +`EnableArm64Fp16` | | `DWORD` | ` ` | `1` | +`EnableArm64Jscvt` | | `DWORD` | ` ` | `1` | +`EnableArm64Lrcpc` | | `DWORD` | ` ` | `1` | +`EnableArm64Pmull` | | `DWORD` | ` ` | `1` | +`EnableArm64Sha1` | | `DWORD` | ` ` | `1` | +`EnableArm64Sha256` | | `DWORD` | ` ` | `1` | +`EnableArm64Sha3` | | `DWORD` | ` ` | `1` | +`EnableArm64Sha512` | | `DWORD` | ` ` | `1` | +`EnableArm64Simd` | | `DWORD` | ` ` | `1` | +`EnableArm64Simd_fp16` | | `DWORD` | | `1` | +`EnableArm64Simd_v81` | | `DWORD` | ` ` | `1` | +`EnableArm64Sm3` | | `DWORD` | ` ` | `1` | +`EnableArm64Sm4` | | `DWORD` | ` ` | `1` | +`EnableArm64Sve` | | `DWORD` | ` ` | `1` | +`EnableAVX` | Enable AVX | `DWORD` | | `1` | +`EnableAVX2` | Enable AVX2 | `DWORD` | | `1` | +`EnableBMI1` | Enable BMI1 | `DWORD` | | `1` | +`EnableBMI2` | Enable BMI2 | `DWORD` | | `1` | +`EnableFMA` | Enable FMA | `DWORD` | | `1` | +`EnableHWIntrinsic` | Enable Base | `DWORD` | | `1` | +`EnableIncompleteISAClass` | Enable testing not-yet-implemented intrinsic classes | `DWORD` | | `0` | +`EnableLZCNT` | Enable AES | `DWORD` | | `1` | +`EnablePCLMULQDQ` | Enable PCLMULQDQ | `DWORD` | | `1` | +`EnablePOPCNT` | Enable POPCNT | `DWORD` | | `1` | +`EnableSSE` | Enable SSE | `DWORD` | | `1` | +`EnableSSE2` | Enable SSE2 | `DWORD` | | `1` | +`EnableSSE3` | Enable SSE3 | `DWORD` | | `1` | +`EnableSSE3_4` | Enable SSE3, SSSE3, SSE 4.1 and 4.2 instruction set as default | `DWORD` | | `1` | +`EnableSSE41` | Enable SSE41 | `DWORD` | | `1` | +`EnableSSE42` | Enable SSE42 | `DWORD` | | `1` | +`EnableSSSE3` | Enable SSSE3 | `DWORD` | | `1` | #### Jit Pitching Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`JitPitchEnabled` | Set it to 1 to enable Jit Pitching | `DWORD` | `INTERNAL` | `(DWORD)0` | -`JitPitchMaxVal` | Do Jit Pitching the value of the inner counter less then this value (for debuggin purpose only) | `DWORD` | `INTERNAL` | `(DWORD)0xffffffff` | -`JitPitchMemThreshold` | Do Jit Pitching when code heap usage is larger than this (in bytes) | `DWORD` | `INTERNAL` | `(DWORD)0` | -`JitPitchMethodSizeThreshold` | Do Jit Pitching for methods whose native code size larger than this (in bytes) | `DWORD` | `INTERNAL` | `(DWORD)0` | -`JitPitchMinVal` | Do Jit Pitching if the value of the inner counter greater than this value (for debugging purpose only) | `DWORD` | `INTERNAL` | `(DWORD)0` | -`JitPitchPrintStat` | Print statistics about Jit Pitching | `DWORD` | `INTERNAL` | `(DWORD)0` | -`JitPitchTimeInterval` | Time interval between Jit Pitchings in ms | `DWORD` | `INTERNAL` | `(DWORD)0` | +`JitPitchEnabled` | Set it to 1 to enable Jit Pitching | `DWORD` | `INTERNAL` | `(DWORD)0` | +`JitPitchMaxVal` | Do Jit Pitching the value of the inner counter less then this value (for debuggin purpose only) | `DWORD` | `INTERNAL` | `(DWORD)0xffffffff` | +`JitPitchMemThreshold` | Do Jit Pitching when code heap usage is larger than this (in bytes) | `DWORD` | `INTERNAL` | `(DWORD)0` | +`JitPitchMethodSizeThreshold` | Do Jit Pitching for methods whose native code size larger than this (in bytes) | `DWORD` | `INTERNAL` | `(DWORD)0` | +`JitPitchMinVal` | Do Jit Pitching if the value of the inner counter greater than this value (for debugging purpose only) | `DWORD` | `INTERNAL` | `(DWORD)0` | +`JitPitchPrintStat` | Print statistics about Jit Pitching | `DWORD` | `INTERNAL` | `(DWORD)0` | +`JitPitchTimeInterval` | Time interval between Jit Pitchings in ms | `DWORD` | `INTERNAL` | `(DWORD)0` | #### Loader Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`APIThreadStress` | Used to test Loader for race conditions | `DWORD` | `INTERNAL` | | -`CoreClrBinderLog` | Debug flag that enabled detailed log for new binder (similar to stress logging). | `STRING` | `INTERNAL` | | -`DisableFXClosureWalk` | Disable full closure walks even in the presence of FX binding redirects | `DWORD` | `INTERNAL` | `0` | -`DisableIJWVersionCheck` | Don't perform the new version check that prevents unsupported IJW in-proc SxS. | `DWORD` | `EXTERNAL` | `0` | -`EnableFastBindClosure` | If set to >0 the binder uses CFastAssemblyBindingClosure instances | `DWORD` | `UNSUPPORTED` | `0` | -`ForceLog` | Fusion flag to enforce assembly binding log. Heavily used and documented in MSDN and BLOGS. | `DWORD` | `EXTERNAL` | | -`LoaderOptimization` | Controls code sharing behavior | `DWORD` | `EXTERNAL` | | -`TagAssemblyNames` | Enable CAssemblyName::_tag field for more convenient debugging. | `DWORD` | `INTERNAL` | `0` | -`WinMDPath` | Path for Windows WinMD files | `STRING` | `INTERNAL` | | +`APIThreadStress` | Used to test Loader for race conditions | `DWORD` | `INTERNAL` | | +`CoreClrBinderLog` | Debug flag that enabled detailed log for new binder (similar to stress logging). | `STRING` | `INTERNAL` | | +`ForceLog` | Fusion flag to enforce assembly binding log. Heavily used and documented in MSDN and BLOGS. | `DWORD` | `EXTERNAL` | | +`WinMDPath` | Path for Windows WinMD files | `STRING` | `INTERNAL` | | #### Loader heap Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`BreakOnOutOfMemoryWithinRange` | Break before out of memory within range exception is thrown | `DWORD` | `INTERNAL` | `0` | -`CodeHeapReserveForJumpStubs` | Percentage of code heap to reserve for jump stubs | `DWORD` | `INTERNAL` | `1` | +`BreakOnOutOfMemoryWithinRange` | Break before out of memory within range exception is thrown | `DWORD` | `INTERNAL` | `0` | +`CodeHeapReserveForJumpStubs` | Percentage of code heap to reserve for jump stubs | `DWORD` | `INTERNAL` | `1` | `LoaderHeapCallTracing` | Loader heap troubleshooting | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`NGenReserveForJumpStubs` | Percentage of ngen image size to reserve for jump stubs | `DWORD` | `INTERNAL` | `0` | +`NGenReserveForJumpStubs` | Percentage of ngen image size to reserve for jump stubs | `DWORD` | `INTERNAL` | `0` | #### Log Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`LogEnable` | Turns on the traditional CLR log. | `DWORD` | `INTERNAL` | | -`LogFacility` | Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog. | `DWORD` | `INTERNAL` | | -`LogFacility2` | Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog. | `DWORD` | `INTERNAL` | | -`logFatalError` | Specifies whether EventReporter logs fatal errors in the Windows event log. | `DWORD` | `EXTERNAL` | `1` | -`LogFile` | Specifies a file name for the CLR log. | `STRING` | `INTERNAL` | | REGUTIL_default -`LogFileAppend` | Specifies whether to append to or replace the CLR log file. | `DWORD` | `INTERNAL` | | -`LogFlushFile` | Specifies whether to flush the CLR log file on each write. | `DWORD` | `INTERNAL` | | -`LogLevel` | 4=10 msgs, 9=1000000, 10=everything | `DWORD` | `EXTERNAL` | | -`LogPath` | ?Fusion debug log path. | `STRING` | `INTERNAL` | | -`LogToConsole` | Writes the CLR log to console. | `DWORD` | `INTERNAL` | | -`LogToDebugger` | Writes the CLR log to debugger (OutputDebugStringA). | `DWORD` | `INTERNAL` | | -`LogToFile` | Writes the CLR log to a file. | `DWORD` | `INTERNAL` | | -`LogWithPid` | Appends pid to filename for the CLR log. | `DWORD` | `INTERNAL` | | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`LogEnable` | Turns on the traditional CLR log. | `DWORD` | `INTERNAL` | | +`LogFacility` | Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog. | `DWORD` | `INTERNAL` | | +`LogFacility2` | Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog. | `DWORD` | `INTERNAL` | | +`logFatalError` | Specifies whether EventReporter logs fatal errors in the Windows event log. | `DWORD` | `EXTERNAL` | `1` | +`LogFile` | Specifies a file name for the CLR log. | `STRING` | `INTERNAL` | | REGUTIL_default +`LogFileAppend` | Specifies whether to append to or replace the CLR log file. | `DWORD` | `INTERNAL` | | +`LogFlushFile` | Specifies whether to flush the CLR log file on each write. | `DWORD` | `INTERNAL` | | +`LogLevel` | 4=10 msgs, 9=1000000, 10=everything | `DWORD` | `EXTERNAL` | | +`LogPath` | ?Fusion debug log path. | `STRING` | `INTERNAL` | | +`LogToConsole` | Writes the CLR log to console. | `DWORD` | `INTERNAL` | | +`LogToDebugger` | Writes the CLR log to debugger (OutputDebugStringA). | `DWORD` | `INTERNAL` | | +`LogToFile` | Writes the CLR log to a file. | `DWORD` | `INTERNAL` | | +`LogWithPid` | Appends pid to filename for the CLR log. | `DWORD` | `INTERNAL` | | #### MetaData Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`AssertOnBadImageFormat` | ASSERT when invalid MD read | `DWORD` | `INTERNAL` | | +`AssertOnBadImageFormat` | ASSERT when invalid MD read | `DWORD` | `INTERNAL` | | `MD_ApplyDeltaBreak` | ASSERT when applying EnC | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `MD_DeltaCheck` | Some checks of GUID when applying EnC (?) | `DWORD` | `INTERNAL` | `1` | REGUTIL_default `MD_EncDelta` | Forces EnC Delta format in MD (?) | `DWORD` | `INTERNAL` | `0` | REGUTIL_default @@ -618,89 +652,88 @@ Name | Description | Type | Class | Default Value | Flags #### Native Binder Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`NgenBind_ZapForbid` | Assert if an assembly succeeds in binding to a native image | `DWORD` | `INTERNAL` | `0` | -`NgenBind_ZapForbidExcludeList` | | `STRING` | `INTERNAL` | | -`NgenBind_ZapForbidList` | | `STRING` | `INTERNAL` | | +`NgenBind_ZapForbid` | Assert if an assembly succeeds in binding to a native image | `DWORD` | `INTERNAL` | `0` | +`NgenBind_ZapForbidExcludeList` | | `STRING` | `INTERNAL` | | +`NgenBind_ZapForbidList` | | `STRING` | `INTERNAL` | | `SymDiffDump` | Used to create the map file while binding the assembly. Used by SemanticDiffer | `DWORD` | `INTERNAL` | `0` | REGUTIL_default #### NGEN Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`CrossGenAssumeInputSigned` | CrossGen should assume that its input assemblies will be signed before deployment | `DWORD` | `INTERNAL` | `1` | -`EnableHardbinding` | Enables the use of hardbinding | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`HardPrejitEnabled` | | `DWORD` | `EXTERNAL` | | -`NGen_JitName` | | `STRING` | `EXTERNAL` | | REGUTIL_default -`NgenAllowMscorlibSoftbind` | Disable forced hard-binding to mscorlib | `DWORD` | `INTERNAL` | `0` | -`NgenDisasm` | Same as JitDisasm, but for ngen | `SSV` | | | -`NgenDump` | Same as JitDump, but for ngen | `SSV` | | | -`NgenDumpFg` | Ngen Xml Flowgraph support | `STRING` | | | -`NgenDumpFgDir` | Ngen Xml Flowgraph support | `STRING` | | | -`NgenDumpFgFile` | Ngen Xml Flowgraph support | `STRING` | | | -`NgenDumpIR` | Same as JitDumpIR, but for ngen | `SSV` | | | -`NgenDumpIRFormat` | Same as JitDumpIRFormat, but for ngen | `STRING` | | | -`NgenDumpIRPhase` | Same as JitDumpIRPhase, but for ngen | `STRING` | | | -`NgenEHDump` | Dump the EH table for the method, as reported to the VM | `SSV` | | | -`NGenEnableCreatePdb` | If set to >0 ngen.exe displays help on, recognizes createpdb in the command line | `DWORD` | `UNSUPPORTED` | `0` | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`CrossGenAssumeInputSigned` | CrossGen should assume that its input assemblies will be signed before deployment | `DWORD` | `INTERNAL` | `1` | +`NGen_JitName` | | `STRING` | `EXTERNAL` | | REGUTIL_default +`NgenDebugDump` | | `SSV` | | | +`NgenDisasm` | Same as JitDisasm, but for ngen | `SSV` | | | +`NgenDump` | Same as JitDump, but for ngen | `SSV` | | | +`NgenDumpFg` | Ngen Xml Flowgraph support | `STRING` | | | +`NgenDumpFgDir` | Ngen Xml Flowgraph support | `STRING` | | | +`NgenDumpFgFile` | Ngen Xml Flowgraph support | `STRING` | | | +`NgenDumpIR` | Same as JitDumpIR, but for ngen | `SSV` | | | +`NgenDumpIRFormat` | Same as JitDumpIRFormat, but for ngen | `STRING` | | | +`NgenDumpIRPhase` | Same as JitDumpIRPhase, but for ngen | `STRING` | | | +`NgenEHDump` | Dump the EH table for the method, as reported to the VM | `SSV` | | | +`NGenEnableCreatePdb` | If set to >0 ngen.exe displays help on, recognizes createpdb in the command line | `DWORD` | `UNSUPPORTED` | `0` | `NgenForceFailureCount` | If set to >0 and we have IBC data we will force a failure after we reference an IBC data item times | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `NgenForceFailureKind` | If set to 1, We will throw a TypeLoad exception; If set to 2, We will cause an A/V | `DWORD` | `INTERNAL` | `1` | REGUTIL_default -`NgenForceFailureMask` | Bitmask used to control which locations will check and raise the failure (defaults to bits: -1) | `DWORD` | `INTERNAL` | `-1` | REGUTIL_default -`NGenFramed` | Same as JitFramed, but for ngen | `DWORD` | `UNSUPPORTED` | `-1` | REGUTIL_default -`NgenGCDump` | | `SSV` | | | +`NgenForceFailureMask` | Bitmask used to control which locations will check and raise the failure (defaults to bits: -1) | `DWORD` | `INTERNAL` | `(DWORD)-1` | REGUTIL_default +`NGenFramed` | Same as JitFramed, but for ngen | `DWORD` | `UNSUPPORTED` | `(DWORD)-1` | REGUTIL_default +`NgenGCDump` | | `SSV` | | | `NGenOnlyOneMethod` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `NgenOrder` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`NGenSimulateDiskFull` | If set to 1, ngen will throw a Disk full exception in ZapWriter.cpp:Save() | `DWORD` | `INTERNAL` | `0` | -`NgenUnwindDump` | Dump the unwind codes for the method | `SSV` | | | -`NoASLRForNgen` | Turn off IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE bit in generated ngen images. Makes nidump output repeatable from run to run. | `DWORD` | `INTERNAL` | `0` | -`PartialNGen` | Generate partial NGen images | `DWORD` | `INTERNAL` | `-1` | +`NGenSimulateDiskFull` | If set to 1, ngen will throw a Disk full exception in ZapWriter.cpp:Save() | `DWORD` | `INTERNAL` | `0` | +`NgenUnwindDump` | Dump the unwind codes for the method | `SSV` | | | +`NoASLRForNgen` | Turn off IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE bit in generated ngen images. Makes nidump output repeatable from run to run. | `DWORD` | `INTERNAL` | `0` | +`PartialNGen` | Generate partial NGen images | `DWORD` | `INTERNAL` | `(DWORD)-1` | `partialNGenStress` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `ZapDoNothing` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default #### Performance Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`performanceScenario` | Activates a set of workload-specific default values for performance settings | `STRING` | `EXTERNAL` | | +`performanceScenario` | Activates a set of workload-specific default values for performance settings | `STRING` | `EXTERNAL` | | #### Profiling API / ETW Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`AttachThreadAlwaysOn` | Forces profapi attach thread to be created on startup, instead of on-demand. | `DWORD` | `EXTERNAL` | | +`AttachThreadAlwaysOn` | Forces profapi attach thread to be created on startup, instead of on-demand. | `DWORD` | `EXTERNAL` | | `COR_ENABLE_PROFILING` | Flag to indicate whether profiling should be enabled for the currently running process. | `DWORD` | `EXTERNAL` | `0` | DontPrependCOMPlus_ \| IgnoreConfigFiles -`COR_PROFILER` | Specifies GUID of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`COR_PROFILER_PATH` | Specifies the path to the DLL of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`COR_PROFILER_PATH_32` | Specifies the path to the DLL of profiler to load into currently running 32 bits process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`COR_PROFILER_PATH_64` | Specifies the path to the DLL of profiler to load into currently running 64 bits process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`COR_PROFILER` | Specifies GUID of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`COR_PROFILER_PATH` | Specifies the path to the DLL of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`COR_PROFILER_PATH_32` | Specifies the path to the DLL of profiler to load into currently running 32 bits process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`COR_PROFILER_PATH_64` | Specifies the path to the DLL of profiler to load into currently running 64 bits process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ `CORECLR_ENABLE_PROFILING` | CoreCLR only: Flag to indicate whether profiling should be enabled for the currently running process. | `DWORD` | `EXTERNAL` | `0` | DontPrependCOMPlus_ \| IgnoreConfigFiles -`CORECLR_PROFILER` | CoreCLR only: Specifies GUID of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`CORECLR_PROFILER_PATH` | CoreCLR only: Specifies the path to the DLL of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`CORECLR_PROFILER_PATH_32` | CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 32 process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`CORECLR_PROFILER_PATH_64` | CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ -`ETW_ObjectAllocationEventsPerTypePerSec` | Desired number of GCSampledObjectAllocation ETW events to be logged per type per second. If 0, then the default built in to the implementation for the enabled event (e.g., High, Low), will be used. | `STRING` | `UNSUPPORTED` | | REGUTIL_default +`CORECLR_PROFILER` | CoreCLR only: Specifies GUID of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`CORECLR_PROFILER_PATH` | CoreCLR only: Specifies the path to the DLL of profiler to load into currently running process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`CORECLR_PROFILER_PATH_32` | CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 32 process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`CORECLR_PROFILER_PATH_64` | CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process | `STRING` | `EXTERNAL` | | DontPrependCOMPlus_ +`ETW_ObjectAllocationEventsPerTypePerSec` | Desired number of GCSampledObjectAllocation ETW events to be logged per type per second. If 0, then the default built in to the implementation for the enabled event (e.g., High, Low), will be used. | `STRING` | `UNSUPPORTED` | | REGUTIL_default `ETWEnabled` | This flag is used on OSes < Vista to enable/disable ETW. It is disabled by default | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default -`MsBetweenAttachCheck` | | `DWORD` | `EXTERNAL` | `500` | +`MsBetweenAttachCheck` | | `DWORD` | `EXTERNAL` | `500` | `PerfMapEnabled` | This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default `PerfMapIgnoreSignal` | When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default -`ProfAPI_AttachProfilerMinTimeoutInMs` | Timeout in ms for the minimum time out value of AttachProfiler | `DWORD` | `EXTERNAL` | `10*1000` | -`ProfAPI_DetachMaxSleepMs` | The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded. | `DWORD` | `EXTERNAL` | `0` | -`ProfAPI_DetachMinSleepMs` | The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded. | `DWORD` | `EXTERNAL` | `0` | -`ProfAPI_EnableRejitDiagnostics` | Enable extra dumping to stdout of rejit structures | `DWORD` | `INTERNAL` | `0` | -`ProfAPI_ProfilerCompatibilitySetting` | Specifies the profiler loading policy (the default is not to load a V2 profiler in V4) | `STRING` | `EXTERNAL` | | REGUTIL_default \| TrimWhiteSpaceFromStringValue -`ProfAPI_TestOnlyEnableICorProfilerInfo` | Test-only flag to allow attaching profiler tests to call ICorProfilerInfo interface, which would otherwise be disallowed for attaching profilers | `DWORD` | `INTERNAL` | `0` | -`ProfAPI_ValidateNGENInstrumentation` | This flag enables additional validations when using the IMetaDataEmit APIs for NGEN'ed images to ensure only supported edits are made. | `DWORD` | `UNSUPPORTED` | `0` | -`ProfAPIFault` | Test-only bitmask to inject various types of faults in the profapi code | `DWORD` | `INTERNAL` | `0` | -`ProfAPIMaxWaitForTriggerMs` | Timeout in ms for profilee to wait for each blocking operation performed by trigger app. | `DWORD` | `EXTERNAL` | `5*60*1000` | -`StartupDelayMS` | | `STRING` | `EXTERNAL` | | -`TestOnlyAllowedEventMask` | Test-only bitmask to allow profiler tests to override CLR enforcement of COR_PRF_ALLOWABLE_AFTER_ATTACH and COR_PRF_MONITOR_IMMUTABLE | `DWORD` | `INTERNAL` | `0` | -`TestOnlyEnableObjectAllocatedHook` | Test-only flag that forces CLR to initialize on startup as if ObjectAllocated callback were requested, to enable post-attach ObjectAllocated functionality. | `DWORD` | `INTERNAL` | `0` | -`TestOnlyEnableSlowELTHooks` | Test-only flag that forces CLR to initialize on startup as if slow-ELT were requested, to enable post-attach ELT functionality. | `DWORD` | `INTERNAL` | `0` | +`ProfAPI_AttachProfilerMinTimeoutInMs` | Timeout in ms for the minimum time out value of AttachProfiler | `DWORD` | `EXTERNAL` | `10*1000` | +`ProfAPI_DetachMaxSleepMs` | The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded. | `DWORD` | `EXTERNAL` | `0` | +`ProfAPI_DetachMinSleepMs` | The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded. | `DWORD` | `EXTERNAL` | `0` | +`ProfAPI_EnableRejitDiagnostics` | Enable extra dumping to stdout of rejit structures | `DWORD` | `INTERNAL` | `0` | +`ProfAPI_ProfilerCompatibilitySetting` | Specifies the profiler loading policy (the default is not to load a V2 profiler in V4) | `STRING` | `EXTERNAL` | | REGUTIL_default \| TrimWhiteSpaceFromStringValue +`ProfApi_RejitOnAttach` | Enables the ability for profilers to rejit methods on attach. | `DWORD` | `EXTERNAL` | `1` | +`ProfAPI_TestOnlyEnableICorProfilerInfo` | Test-only flag to allow attaching profiler tests to call ICorProfilerInfo interface, which would otherwise be disallowed for attaching profilers | `DWORD` | `INTERNAL` | `0` | +`ProfAPI_ValidateNGENInstrumentation` | This flag enables additional validations when using the IMetaDataEmit APIs for NGEN'ed images to ensure only supported edits are made. | `DWORD` | `UNSUPPORTED` | `0` | +`ProfAPIFault` | Test-only bitmask to inject various types of faults in the profapi code | `DWORD` | `INTERNAL` | `0` | +`ProfAPIMaxWaitForTriggerMs` | Timeout in ms for profilee to wait for each blocking operation performed by trigger app. | `DWORD` | `EXTERNAL` | `5*60*1000` | +`StartupDelayMS` | | `STRING` | `EXTERNAL` | | +`TestOnlyAllowedEventMask` | Test-only bitmask to allow profiler tests to override CLR enforcement of COR_PRF_ALLOWABLE_AFTER_ATTACH and COR_PRF_MONITOR_IMMUTABLE | `DWORD` | `INTERNAL` | `0` | +`TestOnlyEnableObjectAllocatedHook` | Test-only flag that forces CLR to initialize on startup as if ObjectAllocated callback were requested, to enable post-attach ObjectAllocated functionality. | `DWORD` | `INTERNAL` | `0` | +`TestOnlyEnableSlowELTHooks` | Test-only flag that forces CLR to initialize on startup as if slow-ELT were requested, to enable post-attach ELT functionality. | `DWORD` | `INTERNAL` | `0` | #### Spinning heuristics Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `Monitor_SpinCount` | Hex value specifying the maximum number of spin iterations Monitor may perform upon contention on acquiring the lock before waiting. | `DWORD` | `INTERNAL` | `0x1e` | EEConfig_default `SpinBackoffFactor` | Hex value specifying the growth of each successive spin duration | `DWORD` | `EXTERNAL` | `0x3` | EEConfig_default @@ -712,150 +745,150 @@ Name | Description | Type | Class | Default Value | Flags #### Stress Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`ForceEnc` | Forces Edit and Continue to be on for all eligible modules. | `DWORD` | `UNSUPPORTED` | | +`ForceEnc` | Forces Edit and Continue to be on for all eligible modules. | `DWORD` | `UNSUPPORTED` | | `StressCOMCall` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`StressLog` | Turns on the stress log. | `DWORD` | `UNSUPPORTED` | | -`StressLogSize` | Stress log size in bytes per thread. | `DWORD` | `UNSUPPORTED` | | -`StressOn` | Enables the STRESS_ASSERT macro that stops runtime quickly (to prevent the clr state from changing significantly before breaking) | `DWORD` | `INTERNAL` | | +`StressLog` | Turns on the stress log. | `DWORD` | `UNSUPPORTED` | | +`StressLogSize` | Stress log size in bytes per thread. | `DWORD` | `UNSUPPORTED` | | +`StressOn` | Enables the STRESS_ASSERT macro that stops runtime quickly (to prevent the clr state from changing significantly before breaking) | `DWORD` | `INTERNAL` | | `stressSynchronized` | Unknown if or where this is used; unless a test is specifically depending on this, it can be removed. | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`StressThreadCount` | | `DWORD` | `EXTERNAL` | | +`StressThreadCount` | | `DWORD` | `EXTERNAL` | | #### Thread (miscellaneous) Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`Thread_DeadThreadCountThresholdForGCTrigger` | In the heuristics to clean up dead threads, this threshold must be reached before triggering a GC will be considered. Set to 0 to disable triggering a GC based on dead threads. | `DWORD` | `INTERNAL` | `75` | -`Thread_DeadThreadGCTriggerPeriodMilliseconds` | In the heuristics to clean up dead threads, this much time must have elapsed since the previous max-generation GC before triggering another GC will be considered | `DWORD` | `INTERNAL` | `1000 * 60 * 30` | +`Thread_DeadThreadCountThresholdForGCTrigger` | In the heuristics to clean up dead threads, this threshold must be reached before triggering a GC will be considered. Set to 0 to disable triggering a GC based on dead threads. | `DWORD` | `INTERNAL` | `75` | +`Thread_DeadThreadGCTriggerPeriodMilliseconds` | In the heuristics to clean up dead threads, this much time must have elapsed since the previous max-generation GC before triggering another GC will be considered | `DWORD` | `INTERNAL` | `1000 * 60 * 30` | #### Thread Suspend Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`DiagnosticSuspend` | | `DWORD` | `INTERNAL` | `0` | -`SuspendDeadlockTimeout` | | `DWORD` | `INTERNAL` | `40000` | -`SuspendThreadDeadlockTimeoutMs` | | `DWORD` | `INTERNAL` | `2000` | -`ThreadSuspendInjection` | Specifies whether to inject activations for thread suspension on Unix | `DWORD` | `INTERNAL` | `1` | +`DiagnosticSuspend` | | `DWORD` | `INTERNAL` | `0` | +`SuspendDeadlockTimeout` | | `DWORD` | `INTERNAL` | `40000` | +`SuspendThreadDeadlockTimeoutMs` | | `DWORD` | `INTERNAL` | `2000` | +`ThreadSuspendInjection` | Specifies whether to inject activations for thread suspension on Unix | `DWORD` | `INTERNAL` | `1` | #### Threadpool Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`HillClimbing_Bias` | The 'cost' of a thread. 0 means drive for increased throughput regardless of thread count; higher values bias more against higher thread counts. | `DWORD` | `INTERNAL` | `15` | -`HillClimbing_Disable` | Disables hill climbing for thread adjustments in the thread pool | `DWORD` | `INTERNAL` | `0` | -`HillClimbing_ErrorSmoothingFactor` | | `DWORD` | `INTERNAL` | `1` | -`HillClimbing_GainExponent` | The exponent to apply to the gain, times 100. 100 means to use linear gain, higher values will enhance large moves and damp small ones. | `DWORD` | `INTERNAL` | `200` | -`HillClimbing_MaxChangePerSample` | | `DWORD` | `INTERNAL` | `20` | -`HillClimbing_MaxChangePerSecond` | | `DWORD` | `INTERNAL` | `4` | -`HillClimbing_MaxSampleErrorPercent` | | `DWORD` | `INTERNAL` | `15` | -`HillClimbing_MaxWaveMagnitude` | | `DWORD` | `INTERNAL` | `20` | -`HillClimbing_SampleIntervalHigh` | | `DWORD` | `INTERNAL` | `200` | -`HillClimbing_SampleIntervalLow` | | `DWORD` | `INTERNAL` | `10` | -`HillClimbing_TargetSignalToNoiseRatio` | | `DWORD` | `INTERNAL` | `300` | -`HillClimbing_WaveHistorySize` | | `DWORD` | `INTERNAL` | `8` | -`HillClimbing_WaveMagnitudeMultiplier` | | `DWORD` | `INTERNAL` | `100` | -`HillClimbing_WavePeriod` | | `DWORD` | `INTERNAL` | `4` | -`Thread_UseAllCpuGroups` | Specifies if to automatically distribute thread across CPU Groups | `DWORD` | `EXTERNAL` | `0` | -`ThreadPool_DebugBreakOnWorkerStarvation` | Breaks into the debugger if the ThreadPool detects work queue starvation | `DWORD` | `INTERNAL` | `0` | -`ThreadPool_DisableStarvationDetection` | Disables the ThreadPool feature that forces new threads to be added when workitems run for too long | `DWORD` | `INTERNAL` | `0` | -`ThreadPool_EnableWorkerTracking` | Enables extra expensive tracking of how many workers threads are working simultaneously | `DWORD` | `INTERNAL` | `0` | -`ThreadPool_ForceMaxWorkerThreads` | Overrides the MaxThreads setting for the ThreadPool worker pool | `DWORD` | `INTERNAL` | `0` | -`ThreadPool_ForceMinWorkerThreads` | Overrides the MinThreads setting for the ThreadPool worker pool | `DWORD` | `INTERNAL` | `0` | -`ThreadPool_UnfairSemaphoreSpinLimit` | Maximum number of spins per processor a thread pool worker thread performs before waiting for work | `DWORD` | `INTERNAL` | `0x32` | -`ThreadpoolTickCountAdjustment` | | `DWORD` | `INTERNAL` | `0` | +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`HillClimbing_Bias` | The 'cost' of a thread. 0 means drive for increased throughput regardless of thread count; higher values bias more against higher thread counts. | `DWORD` | `INTERNAL` | `15` | +`HillClimbing_Disable` | Disables hill climbing for thread adjustments in the thread pool | `DWORD` | `INTERNAL` | `0` | +`HillClimbing_ErrorSmoothingFactor` | | `DWORD` | `INTERNAL` | `1` | +`HillClimbing_GainExponent` | The exponent to apply to the gain, times 100. 100 means to use linear gain, higher values will enhance large moves and damp small ones. | `DWORD` | `INTERNAL` | `200` | +`HillClimbing_MaxChangePerSample` | | `DWORD` | `INTERNAL` | `20` | +`HillClimbing_MaxChangePerSecond` | | `DWORD` | `INTERNAL` | `4` | +`HillClimbing_MaxSampleErrorPercent` | | `DWORD` | `INTERNAL` | `15` | +`HillClimbing_MaxWaveMagnitude` | | `DWORD` | `INTERNAL` | `20` | +`HillClimbing_SampleIntervalHigh` | | `DWORD` | `INTERNAL` | `200` | +`HillClimbing_SampleIntervalLow` | | `DWORD` | `INTERNAL` | `10` | +`HillClimbing_TargetSignalToNoiseRatio` | | `DWORD` | `INTERNAL` | `300` | +`HillClimbing_WaveHistorySize` | | `DWORD` | `INTERNAL` | `8` | +`HillClimbing_WaveMagnitudeMultiplier` | | `DWORD` | `INTERNAL` | `100` | +`HillClimbing_WavePeriod` | | `DWORD` | `INTERNAL` | `4` | +`Thread_UseAllCpuGroups` | Specifies if to automatically distribute thread across CPU Groups | `DWORD` | `EXTERNAL` | `0` | +`ThreadPool_DebugBreakOnWorkerStarvation` | Breaks into the debugger if the ThreadPool detects work queue starvation | `DWORD` | `INTERNAL` | `0` | +`ThreadPool_DisableStarvationDetection` | Disables the ThreadPool feature that forces new threads to be added when workitems run for too long | `DWORD` | `INTERNAL` | `0` | +`ThreadPool_EnableWorkerTracking` | Enables extra expensive tracking of how many workers threads are working simultaneously | `DWORD` | `INTERNAL` | `0` | +`ThreadPool_ForceMaxWorkerThreads` | Overrides the MaxThreads setting for the ThreadPool worker pool | `DWORD` | `INTERNAL` | `0` | +`ThreadPool_ForceMinWorkerThreads` | Overrides the MinThreads setting for the ThreadPool worker pool | `DWORD` | `INTERNAL` | `0` | +`ThreadPool_UnfairSemaphoreSpinLimit` | Maximum number of spins per processor a thread pool worker thread performs before waiting for work | `DWORD` | `INTERNAL` | `0x32` | +`ThreadpoolTickCountAdjustment` | | `DWORD` | `INTERNAL` | `0` | #### Tiered Compilation Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`TieredCompilation` | Enables tiered compilation | `DWORD` | `EXTERNAL` | `1` | -`TieredCompilation_Test_CallCounting` | Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any tier1 promotion | `DWORD` | `UNSUPPORTED` | `1` | -`TieredCompilation_Test_OptimizeTier0` | Use optimized codegen (normally used by tier1) in tier0 | `DWORD` | `UNSUPPORTED` | `0` | -`TieredCompilation_Tier1CallCountingDelayMs` | Delay in milliseconds since process startup or the last tier 0 JIT before call counting begins for tier 1 promotion. | `DWORD` | `UNSUPPORTED` | `100` | -`TieredCompilation_Tier1CallCountThreshold` | Number of times a method must be called after which it is promoted to tier 1. | `DWORD` | `UNSUPPORTED` | `30` | +`TC_QuickJit` | For methods that would be jitted, enable using quick JIT when appropriate. | `DWORD` | `UNSUPPORTED` | `0` | +`TC_StartupTier_CallCounting` | Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers | `DWORD` | `INTERNAL` | `1` | +`TC_StartupTier_CallCountingDelayMs` | A perpetual delay in milliseconds that is applied call counting in the startup tier and jitting at higher tiers, while there is startup-like activity. | `DWORD` | `UNSUPPORTED` | `100` | +`TC_StartupTier_CallCountThreshold` | Number of times a method must be called in the startup tier after which it is promoted to the next tier. | `DWORD` | `UNSUPPORTED` | `30` | +`TC_StartupTier_DelaySingleProcMultiplier` | Multiplier for TC_StartupTier_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor. | `DWORD` | `UNSUPPORTED` | `10` | +`TC_StartupTier_OptimizeCode` | Use optimized codegen (normally used by the optimized tier) in the startup tier | `DWORD` | `INTERNAL` | `0` | +`TieredCompilation` | Enables tiered compilation | `DWORD` | `EXTERNAL` | `1` | #### TypeLoader Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`TypeLoader_InjectInterfaceDuplicates` | Injects duplicates in interface map for all types. | `DWORD` | `INTERNAL` | `0` | +`TypeLoader_InjectInterfaceDuplicates` | Injects duplicates in interface map for all types. | `DWORD` | `INTERNAL` | `0` | #### Uncategorized Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `ActivatePatchSkip` | Allows an assert when ActivatePatchSkip is called | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`AlwaysUseMetadataInterfaceMapLayout` | Used for debugging generic interface map layout. | `DWORD` | `INTERNAL` | | -`AssertOnUnneededThis` | While the ConfigDWORD is unnecessary, the contained ASSERT should be kept. This may result in some work tracking down violating MethodDescCallSites. | `DWORD` | `INTERNAL` | `0` | +`AlwaysUseMetadataInterfaceMapLayout` | Used for debugging generic interface map layout. | `DWORD` | `INTERNAL` | | +`AssertOnUnneededThis` | While the ConfigDWORD is unnecessary, the contained ASSERT should be kept. This may result in some work tracking down violating MethodDescCallSites. | `DWORD` | `INTERNAL` | `0` | `AssertStacktrace` | | `DWORD` | `INTERNAL` | `1` | REGUTIL_default `clearNativeImageStress` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`CPUFamily` | | `DWORD` | `INTERNAL` | | -`CPUFeatures` | | `DWORD` | `INTERNAL` | | +`CPUFamily` | | `DWORD` | `INTERNAL` | | +`CPUFeatures` | | `DWORD` | `INTERNAL` | | `DisableConfigCache` | Used to disable the \"probabilistic\" config cache, which walks through the appropriate config registry keys on init and probabilistically keeps track of which exist. | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default -`DisableStackwalkCache` | | `DWORD` | `EXTERNAL` | | -`DoubleArrayToLargeObjectHeap` | Controls double[] placement | `DWORD` | `UNSUPPORTED` | | -`DumpConfiguration` | Dumps runtime properties of xml configuration files to the log. | `DWORD` | `INTERNAL` | `0` | -`DumpOnClassLoad` | Dumps information about loaded class to log. | `STRING` | `INTERNAL` | | -`ExpandAllOnLoad` | | `DWORD` | `INTERNAL` | | -`ForcedRuntime` | Verify version of CLR loaded | `STRING` | `INTERNAL` | | +`DisableStackwalkCache` | | `DWORD` | `EXTERNAL` | | +`DoubleArrayToLargeObjectHeap` | Controls double[] placement | `DWORD` | `UNSUPPORTED` | | +`DumpConfiguration` | Dumps runtime properties of xml configuration files to the log. | `DWORD` | `INTERNAL` | `0` | +`DumpOnClassLoad` | Dumps information about loaded class to log. | `STRING` | `INTERNAL` | | +`ExpandAllOnLoad` | | `DWORD` | `INTERNAL` | | +`ForcedRuntime` | Verify version of CLR loaded | `STRING` | `INTERNAL` | | `ForceRelocs` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`GenerateLongJumpDispatchStubRatio` | Useful for testing VSD on AMD64 | `DWORD` | `INTERNAL` | | +`GenerateLongJumpDispatchStubRatio` | Useful for testing VSD on AMD64 | `DWORD` | `INTERNAL` | | `HashStack` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default -`HostManagerConfig` | | `DWORD` | `INTERNAL` | `(DWORD)-1` | -`HostTestADUnload` | Allows setting Rude unload as default | `DWORD` | `INTERNAL` | `0` | -`HostTestThreadAbort` | | `DWORD` | `INTERNAL` | `0` | +`HostManagerConfig` | | `DWORD` | `INTERNAL` | `(DWORD)-1` | +`HostTestThreadAbort` | | `DWORD` | `INTERNAL` | `0` | `IgnoreDllMainReturn` | Don't check the return value of DllMain if this is set | `DWORD` | `UNSUPPORTED` | `0` | ConfigFile_ApplicationFirst -`InvokeHalt` | Throws an assert when the given method is invoked through reflection. | `STRING` | `INTERNAL` | | -`legacyNullReferenceExceptionPolicy` | | `DWORD` | `UNSUPPORTED` | | -`legacyUnhandledExceptionPolicy` | | `DWORD` | `UNSUPPORTED` | | -`MaxStackDepth` | | `DWORD` | `INTERNAL` | | -`MaxStubUnwindInfoSegmentSize` | | `DWORD` | `INTERNAL` | | -`MaxThreadRecord` | | `DWORD` | `INTERNAL` | | -`MessageDebugOut` | | `DWORD` | `INTERNAL` | `0` | +`InvokeHalt` | Throws an assert when the given method is invoked through reflection. | `STRING` | `INTERNAL` | | +`legacyNullReferenceExceptionPolicy` | | `DWORD` | `UNSUPPORTED` | | +`legacyUnhandledExceptionPolicy` | | `DWORD` | `UNSUPPORTED` | | +`MaxStackDepth` | | `DWORD` | `INTERNAL` | | +`MaxStubUnwindInfoSegmentSize` | | `DWORD` | `INTERNAL` | | +`MaxThreadRecord` | | `DWORD` | `INTERNAL` | | +`MessageDebugOut` | | `DWORD` | `INTERNAL` | `0` | `MscorsnLogging` | Enables strong name logging | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `NativeImageRequire` | | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default `NestedEhOom` | | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `NoGuiOnAssert` | | `DWORD` | `INTERNAL` | `INTERNAL_NoGuiOnAssert_Default` | REGUTIL_default `NoProcedureSplitting` | | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default `NoStringInterning` | Disallows string interning. I see no value in it anymore. | `DWORD` | `INTERNAL` | `1` | REGUTIL_default -`NotifyBadAppCfg` | Whether to show a message box for bad application config file. | `DWORD` | `EXTERNAL` | | -`PauseOnLoad` | Stops in SystemDomain::init. I think it can be removed. | `DWORD` | `INTERNAL` | | -`PerfAllocsSizeThreshold` | Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler. | `DWORD` | `INTERNAL` | `0x3FFFFFFF` | -`PerfNumAllocsThreshold` | Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler. | `DWORD` | `INTERNAL` | `0x3FFFFFFF` | -`PerfTypesToLog` | Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler. | `STRING` | `INTERNAL` | | -`Prepopulate1` | | `DWORD` | `EXTERNAL` | `1` | -`PrestubGC` | | `STRING` | `INTERNAL` | | -`PrestubHalt` | | `STRING` | `INTERNAL` | | -`RestrictedGCStressExe` | | `STRING` | `EXTERNAL` | | +`NotifyBadAppCfg` | Whether to show a message box for bad application config file. | `DWORD` | `EXTERNAL` | | +`PauseOnLoad` | Stops in SystemDomain::init. I think it can be removed. | `DWORD` | `INTERNAL` | | +`PerfAllocsSizeThreshold` | Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler. | `DWORD` | `INTERNAL` | `0x3FFFFFFF` | +`PerfNumAllocsThreshold` | Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler. | `DWORD` | `INTERNAL` | `0x3FFFFFFF` | +`PerfTypesToLog` | Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler. | `STRING` | `INTERNAL` | | +`Prepopulate1` | | `DWORD` | `EXTERNAL` | `1` | +`PrestubGC` | | `STRING` | `INTERNAL` | | +`PrestubHalt` | | `STRING` | `INTERNAL` | | +`RestrictedGCStressExe` | | `STRING` | `EXTERNAL` | | `ReturnSourceTypeForTesting` | Allows returning the (internal only) source type of an IL to Native mapping for debugging purposes | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `RSStressLog` | Allows turning on logging for RS startup | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default -`SaveThreadInfo` | | `DWORD` | `INTERNAL` | | -`SaveThreadInfoMask` | | `DWORD` | `INTERNAL` | | -`SBDumpOnNewIndex` | Used for Syncblock debugging. It's been a while since any of those have been used. | `DWORD` | `INTERNAL` | `0` | -`SBDumpOnResize` | Used for Syncblock debugging. It's been a while since any of those have been used. | `DWORD` | `INTERNAL` | `0` | -`SBDumpStyle` | Used for Syncblock debugging. It's been a while since any of those have been used. | `DWORD` | `INTERNAL` | `0` | -`ShimDatabaseVersion` | Force using shim database version in registry | `STRING` | `UNSUPPORTED` | | -`SleepOnExit` | Used for lrak detection. I'd say deprecated by umdh. | `DWORD` | `UNSUPPORTED` | `0` | -`StubLinkerUnwindInfoVerificationOn` | | `DWORD` | `INTERNAL` | | +`SaveThreadInfo` | | `DWORD` | `INTERNAL` | | +`SaveThreadInfoMask` | | `DWORD` | `INTERNAL` | | +`SBDumpOnNewIndex` | Used for Syncblock debugging. It's been a while since any of those have been used. | `DWORD` | `INTERNAL` | `0` | +`SBDumpOnResize` | Used for Syncblock debugging. It's been a while since any of those have been used. | `DWORD` | `INTERNAL` | `0` | +`SBDumpStyle` | Used for Syncblock debugging. It's been a while since any of those have been used. | `DWORD` | `INTERNAL` | `0` | +`ShimDatabaseVersion` | Force using shim database version in registry | `STRING` | `UNSUPPORTED` | | +`SleepOnExit` | Used for lrak detection. I'd say deprecated by umdh. | `DWORD` | `UNSUPPORTED` | `0` | +`StubLinkerUnwindInfoVerificationOn` | | `DWORD` | `INTERNAL` | | `SuccessExit` | | `DWORD` | `UNSUPPORTED` | `0` | REGUTIL_default -`SupressAllowUntrustedCallerChecks` | Disable APTCA | `DWORD` | `INTERNAL` | `0` | -`SymbolReadingPolicy` | Specifies when PDBs may be read | `DWORD` | `EXTERNAL` | | -`TestDataConsistency` | Allows ensuring the left side is not holding locks (and may thus be in an inconsistent state) when inspection occurs | `DWORD` | `UNSUPPORTED` | `FALSE` | +`SymbolReadingPolicy` | Specifies when PDBs may be read | `DWORD` | `EXTERNAL` | | +`TestDataConsistency` | Allows ensuring the left side is not holding locks (and may thus be in an inconsistent state) when inspection occurs | `DWORD` | `UNSUPPORTED` | `FALSE` | `ThreadGuardPages` | | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default `Timeline` | | `DWORD` | `EXTERNAL` | `0` | REGUTIL_default -`TotalStressLogSize` | Total stress log size in bytes. | `DWORD` | `UNSUPPORTED` | | -`TraceIUnknown` | | `DWORD` | `EXTERNAL` | | -`TraceWrap` | | `DWORD` | `EXTERNAL` | | -`TURNOFFDEBUGINFO` | | `DWORD` | `EXTERNAL` | | -`UseMethodDataCache` | Used during feature development; may now be removed. | `DWORD` | `EXTERNAL` | `FALSE` | -`UseParentMethodData` | Used during feature development; may now be removed. | `DWORD` | `EXTERNAL` | `TRUE` | -`VerifierOff` | | `DWORD` | `INTERNAL` | | -`VerifyAllOnLoad` | | `DWORD` | `EXTERNAL` | | +`TotalStressLogSize` | Total stress log size in bytes. | `DWORD` | `UNSUPPORTED` | | +`TraceIUnknown` | | `DWORD` | `EXTERNAL` | | +`TraceWrap` | | `DWORD` | `EXTERNAL` | | +`TURNOFFDEBUGINFO` | | `DWORD` | `EXTERNAL` | | +`UseMethodDataCache` | Used during feature development; may now be removed. | `DWORD` | `EXTERNAL` | `FALSE` | +`UseParentMethodData` | Used during feature development; may now be removed. | `DWORD` | `EXTERNAL` | `TRUE` | +`VerifierOff` | | `DWORD` | `INTERNAL` | | +`VerifyAllOnLoad` | | `DWORD` | `EXTERNAL` | | #### Virtual call stubs Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- `VirtualCallStubCollideMonoPct` | Used only when STUB_LOGGING is defined, which by default is not. | `DWORD` | `INTERNAL` | `0` | REGUTIL_default `VirtualCallStubCollideWritePct` | Used only when STUB_LOGGING is defined, which by default is not. | `DWORD` | `INTERNAL` | `100` | REGUTIL_default @@ -868,31 +901,31 @@ Name | Description | Type | Class | Default Value | Flags #### Watson Configuration Knobs -Name | Description | Type | Class | Default Value | Flags +Name | Description | Type | Class | Default Value | Flags -----|-------------|------|-------|---------------|------- -`DisableWatsonForManagedExceptions` | Disable Watson and debugger launching for managed exceptions | `DWORD` | `INTERNAL` | `0` | +`DisableWatsonForManagedExceptions` | Disable Watson and debugger launching for managed exceptions | `DWORD` | `INTERNAL` | `0` | #### Zap Configuration Knobs -Name | Description | Type | Class | Default Value | Flags ------|-------------|------|-------|---------------|------- -`DebugAssertOnMissedCOWPage` | | `DWORD` | `INTERNAL` | `1` | -`EnableEventLog` | Enable/disable use of EnableEventLogging mechanism | `DWORD` | `EXTERNAL` | `0` | -`EventNameFilter` | | `STRING` | `INTERNAL` | | -`EventSourceFilter` | | `STRING` | `INTERNAL` | | -`ReadyToRun` | Enable/disable use of ReadyToRun native code | `DWORD` | `EXTERNAL` | `1` | -`ReadyToRunExcludeList` | List of assemblies that cannot use Ready to Run images | `STRING` | `EXTERNAL` | | -`ReadyToRunLogFile` | Name of file to log success/failure of using Ready to Run images | `STRING` | `EXTERNAL` | | -`ZapBBInstr` | | `STRING` | `INTERNAL` | | REGUTIL_default -`ZapBBInstrDir` | | `STRING` | `EXTERNAL` | | -`ZapDisable` | | `DWORD` | `EXTERNAL` | `0` | -`ZapExclude` | | `STRING` | `INTERNAL` | | REGUTIL_default -`ZapLazyCOWPagesEnabled` | | `DWORD` | `INTERNAL` | `1` | -`ZapOnly` | | `STRING` | `INTERNAL` | | REGUTIL_default -`ZapRequire` | | `DWORD` | `EXTERNAL` | | -`ZapRequireExcludeList` | | `STRING` | `EXTERNAL` | | -`ZapRequireList` | | `STRING` | `EXTERNAL` | | -`ZapSet` | | `STRING` | `EXTERNAL` | | REGUTIL_default +Name | Description | Type | Class | Default Value | Flags +-----|-------------|------|-------|---------------|------- +`DebugAssertOnMissedCOWPage` | | `DWORD` | `INTERNAL` | `1` | +`EnableEventLog` | Enable/disable use of EnableEventLogging mechanism | `DWORD` | `EXTERNAL` | `0` | +`EventNameFilter` | | `STRING` | `INTERNAL` | | +`EventSourceFilter` | | `STRING` | `INTERNAL` | | +`ReadyToRun` | Enable/disable use of ReadyToRun native code | `DWORD` | `EXTERNAL` | `1` | +`ReadyToRunExcludeList` | List of assemblies that cannot use Ready to Run images | `STRING` | `EXTERNAL` | | +`ReadyToRunLogFile` | Name of file to log success/failure of using Ready to Run images | `STRING` | `EXTERNAL` | | +`ZapBBInstr` | | `STRING` | `INTERNAL` | | REGUTIL_default +`ZapBBInstrDir` | | `STRING` | `EXTERNAL` | | +`ZapDisable` | | `DWORD` | `EXTERNAL` | `0` | +`ZapExclude` | | `STRING` | `INTERNAL` | | REGUTIL_default +`ZapLazyCOWPagesEnabled` | | `DWORD` | `INTERNAL` | `1` | +`ZapOnly` | | `STRING` | `INTERNAL` | | REGUTIL_default +`ZapRequire` | | `DWORD` | `EXTERNAL` | | +`ZapRequireExcludeList` | | `STRING` | `EXTERNAL` | | +`ZapRequireList` | | `STRING` | `EXTERNAL` | | +`ZapSet` | | `STRING` | `EXTERNAL` | | REGUTIL_default ## PAL Configuration Knobs diff --git a/Documentation/project-docs/profiling-api-status.md b/Documentation/project-docs/profiling-api-status.md index 1cd9c7eb552f..98d486cd125b 100644 --- a/Documentation/project-docs/profiling-api-status.md +++ b/Documentation/project-docs/profiling-api-status.md @@ -18,6 +18,10 @@ The implementation of this API was making some questionable assumptions about Wi ReJIT feature is only available on x86/x64 for now. +### Profiler Attach/Detach + +We only support launch at the moment, see https://github.com/dotnet/coreclr/issues/16796 + ### Any issues we missed? -Please let us know and we will get it addressed. Thanks! \ No newline at end of file +Please let us know and we will get it addressed. Thanks! diff --git a/ILAsmVersion.txt b/ILAsmVersion.txt index c1808ce4b060..a23af0061bc5 100644 --- a/ILAsmVersion.txt +++ b/ILAsmVersion.txt @@ -1 +1 @@ -3.0.0-preview5-27607-72 +3.0.0-preview5-27616-71 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a268b056d616..179b8803407c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -225,6 +225,21 @@ jobs: ${{ if eq(variables['Build.DefinitionName'], 'coreclr-outerloop-gcstress0x3-gcstress0xc') }}: testGroup: outerloop-gcstress0x3-gcstress0xc +# The ReadyToRun test jobs that are triggered by default from a PR. +- ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.DefinitionName'], 'coreclr-ci')) }}: + - template: eng/platform-matrix.yml + parameters: + jobTemplate: test-job.yml + buildConfig: checked + platforms: + - Linux_x64 + - OSX_x64 + - Windows_NT_x64 + - Windows_NT_x86 + jobParameters: + readyToRun: true + testGroup: innerloop + # CI - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) }}: - template: eng/platform-matrix.yml @@ -238,6 +253,17 @@ jobs: parameters: jobTemplate: test-job.yml buildConfig: checked + platforms: + - Linux_arm64 + - Linux_musl_x64 + - Linux_musl_arm64 + - Linux_rhel6_x64 + - Linux_x64 + - OSX_x64 + - Windows_NT_x64 + - Windows_NT_x86 + - Windows_NT_arm + - Windows_NT_arm64 jobParameters: readyToRun: true testGroup: outerloop diff --git a/build-test.cmd b/build-test.cmd index ee2a4c1a41e7..424232ebf27f 100644 --- a/build-test.cmd +++ b/build-test.cmd @@ -358,7 +358,7 @@ if exist "%CORE_ROOT%" rd /s /q "%CORE_ROOT%" if exist "%CORE_ROOT_STAGE%" rd /s /q "%CORE_ROOT_STAGE%" md "%CORE_ROOT%" md "%CORE_ROOT_STAGE%" -xcopy "%__BinDir%" "%CORE_ROOT_STAGE%" +xcopy /s "%__BinDir%" "%CORE_ROOT_STAGE%" REM ========================================================================================= REM === @@ -557,7 +557,16 @@ if /I "%2" == "mscorlib.ni.dll" exit /b 0 REM don't precompile anything from CoreCLR if /I exist %CORE_ROOT_STAGE%\%2 exit /b 0 -"%CORE_ROOT_STAGE%\crossgen.exe" /Platform_Assemblies_Paths "%CORE_ROOT%" /in "%1" /out "%CORE_ROOT%/temp.ni.dll" >nul 2>nul +REM Don't precompile xunit.* files +echo "%2" | findstr /b "xunit." >nul && ( + exit /b 0 +) + +set __CrossgenExe="%CORE_ROOT_STAGE%\crossgen.exe" +if /i "%__BuildArch%" == "arm" ( set __CrossgenExe="%CORE_ROOT_STAGE%\x86\crossgen.exe" ) +if /i "%__BuildArch%" == "arm64" ( set __CrossgenExe="%CORE_ROOT_STAGE%\x64\crossgen.exe" ) + +"%__CrossgenExe%" /Platform_Assemblies_Paths "%CORE_ROOT%" /in "%1" /out "%CORE_ROOT%/temp.ni.dll" >nul 2>nul set /a __exitCode = %errorlevel% if "%__exitCode%" == "-2146230517" ( echo %2 is not a managed assembly. @@ -565,7 +574,7 @@ if "%__exitCode%" == "-2146230517" ( ) if %__exitCode% neq 0 ( - echo Unable to precompile %2 + echo Unable to precompile %2, Exit Code is %__exitCode% exit /b 0 ) diff --git a/build-test.sh b/build-test.sh index 2489e7eb5633..93a19800d3cb 100755 --- a/build-test.sh +++ b/build-test.sh @@ -150,7 +150,7 @@ generate_layout() build_MSBuild_projects "Tests_Overlay_Managed" "${__ProjectDir}/tests/runtest.proj" "Creating test overlay" "/t:CreateTestOverlay" chmod +x $__BinDir/corerun - chmod +x $__BinDir/crossgen + chmod +x $__CrossgenExe # Make sure to copy over the pulled down packages cp -r $__BinDir/* $CORE_ROOT/ > /dev/null @@ -176,7 +176,7 @@ precompile_coreroot_fx() local overlayDir=$CORE_ROOT - filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*.ni.dll -not -iname \*-ms-win-\* -type f ) + filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*.ni.dll -not -iname \*-ms-win-\* -not -iname xunit.\* -type f) for fileToPrecompile in ${filesToPrecompile} do local filename=${fileToPrecompile} @@ -184,7 +184,7 @@ precompile_coreroot_fx() continue fi echo Precompiling $filename - $overlayDir/crossgen /Platform_Assemblies_Paths $overlayDir $filename 1> $filename.stdout 2>$filename.stderr + $__CrossgenExe /Platform_Assemblies_Paths $overlayDir $filename 1> $filename.stdout 2>$filename.stderr local exitCode=$? if [[ $exitCode != 0 ]]; then if grep -q -e '0x80131018' $filename.stderr; then @@ -964,9 +964,6 @@ __CrossComponentBinDir="$__BinDir" __CrossCompIntermediatesDir="$__IntermediatesDir/crossgen" __CrossArch="$__HostArch" -if [[ "$__HostArch" == "x64" && "$__BuildArch" == "arm" ]]; then - __CrossArch="x86" -fi if [ $__CrossBuild == 1 ]; then __CrossComponentBinDir="$__CrossComponentBinDir/$__CrossArch" fi diff --git a/clrdefinitions.cmake b/clrdefinitions.cmake index 1a8089f243ca..155c77746916 100644 --- a/clrdefinitions.cmake +++ b/clrdefinitions.cmake @@ -211,9 +211,9 @@ if(CLR_CMAKE_PLATFORM_UNIX AND CLR_CMAKE_TARGET_ARCH_AMD64) add_definitions(-DUNIX_AMD64_ABI) endif(CLR_CMAKE_PLATFORM_UNIX AND CLR_CMAKE_TARGET_ARCH_AMD64) add_definitions(-DFEATURE_USE_ASM_GC_WRITE_BARRIERS) -if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR (CLR_CMAKE_PLATFORM_ARCH_ARM64 AND NOT WIN32)) +if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM64) add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) -endif(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR (CLR_CMAKE_PLATFORM_ARCH_ARM64 AND NOT WIN32)) +endif(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM64) if((CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM64) AND NOT WIN32) add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES) endif((CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM64) AND NOT WIN32) diff --git a/configurecompiler.cmake b/configurecompiler.cmake index c893e442823d..929dfe54afae 100644 --- a/configurecompiler.cmake +++ b/configurecompiler.cmake @@ -323,7 +323,6 @@ endif(WIN32) if(CLR_CMAKE_PLATFORM_UNIX) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}" ) - add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS}) endif(CLR_CMAKE_PLATFORM_UNIX) if(CLR_CMAKE_PLATFORM_LINUX) @@ -516,6 +515,10 @@ if(CLR_CMAKE_PLATFORM_UNIX_ARM) endif(ARM_SOFTFP) endif(CLR_CMAKE_PLATFORM_UNIX_ARM) +if(CLR_CMAKE_PLATFORM_UNIX) + add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS}) +endif(CLR_CMAKE_PLATFORM_UNIX) + if (WIN32) # Compile options for targeting windows diff --git a/dependencies.props b/dependencies.props index a76a39102fa3..69a75885f18e 100644 --- a/dependencies.props +++ b/dependencies.props @@ -26,16 +26,16 @@ - caa82199af6a08425d93d3ab3a4b1cb9750ed6b3 - 66f3bb05de8ac6063fbedff5816ef25cc6ecfa11 + 64388f5ec335146136dea340002316fed53df6a9 + c6a0e8080e10e8940af6b1d1809e79fdd8de55b7 - 3.0.0-preview5-27607-72 - 2.4.1 + 3.0.0-preview5-27616-71 + 2.4.1-pre.build.4059 1.0.0-beta-build0015 - 2.0.36 + 2.0.40 4.6.0-alpha-00001 2.2.0 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a525ca3fc4f5..e8f4f86e37a3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,25 +3,25 @@ - + https://github.com/dotnet/arcade - b1f9e12fe3ee71c48ea60b15968745850ac0a4a7 + 517bf671ea342965d007aa48f5bfd4926e58d582 - + https://github.com/dotnet/arcade - b1f9e12fe3ee71c48ea60b15968745850ac0a4a7 + 517bf671ea342965d007aa48f5bfd4926e58d582 - + https://github.com/dotnet/corefx - 87fdc75beacc76e02c8e572ae3b0613b418200eb + 071e6986b2a71e29cab3df4e2dd2cdf3fe3ce574 - + https://github.com/dotnet/corefx - 87fdc75beacc76e02c8e572ae3b0613b418200eb + 071e6986b2a71e29cab3df4e2dd2cdf3fe3ce574 - + https://github.com/dotnet/core-setup - 209213958004859a79ca586e7b278b5c7fe1f4b0 + 490010c3451a44e45f782a019efd736aa490f79c https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index bcfeaa36a041..7bdc598a0e7e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,15 +7,17 @@ false true + 2.5.1-beta.19179.4 1.0.0-alpha-004 - 4.6.0-preview5.19208.1 - 3.0.0-preview5.19208.1 - 3.0.0-preview4-27604-13 + 4.6.0-preview5.19215.16 + 3.0.0-preview5.19215.16 + 3.0.0-preview5-27618-16 99.99.99-master-20190313.3 99.99.99-master-20190313.3 + Microsoft.DotNet.XUnitConsoleRunner Microsoft.Private.CoreFx.NETCoreApp Microsoft.NETCore.Platforms Microsoft.NETCore.App diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1 new file mode 100644 index 000000000000..074b423245c8 --- /dev/null +++ b/eng/common/CheckSymbols.ps1 @@ -0,0 +1,134 @@ +param( + [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where NuGet packages to be checked are stored + [Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation + [Parameter(Mandatory=$true)][string] $SymbolToolPath # Full path to directory where dotnet symbol-tool was installed +) + +Add-Type -AssemblyName System.IO.Compression.FileSystem + +function FirstMatchingSymbolDescriptionOrDefault { + param( + [string] $FullPath, # Full path to the module that has to be checked + [string] $TargetServerParam # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols + ) + + $FileName = [System.IO.Path]::GetFileName($FullPath) + $Extension = [System.IO.Path]::GetExtension($FullPath) + + # Those below are potential symbol files that the `dotnet symbol` might + # return. Which one will be returned depend on the type of file we are + # checking and which type of file was uploaded. + + # The file itself is returned + $SymbolPath = $SymbolsPath + "\" + $FileName + + # PDB file for the module + $PdbPath = $SymbolPath.Replace($Extension, ".pdb") + + # PDB file for R2R module (created by crossgen) + $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb") + + # DBG file for a .so library + $SODbg = $SymbolPath.Replace($Extension, ".so.dbg") + + # DWARF file for a .dylib + $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf") + + .\dotnet-symbol.exe --symbols --modules $TargetServerParam $FullPath -o $SymbolsPath -d | Out-Null + + if (Test-Path $PdbPath) { + return "PDB" + } + elseif (Test-Path $NGenPdb) { + return "NGen PDB" + } + elseif (Test-Path $SODbg) { + return "DBG for SO" + } + elseif (Test-Path $DylibDwarf) { + return "Dwarf for Dylib" + } + elseif (Test-Path $SymbolPath) { + return "Module" + } + else { + return $null + } +} + +function CountMissingSymbols { + param( + [string] $PackagePath # Path to a NuGet package + ) + + # Ensure input file exist + if (!(Test-Path $PackagePath)) { + throw "Input file does not exist: $PackagePath" + } + + # Extensions for which we'll look for symbols + $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib") + + # How many files are missing symbol information + $MissingSymbols = 0 + + $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) + $ExtractPath = $ExtractPath + $PackageId; + $SymbolsPath = $ExtractPath + $PackageId + ".Symbols"; + + [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath) + + # Makes easier to reference `symbol tool` + Push-Location $SymbolToolPath + + Get-ChildItem -Recurse $ExtractPath | + Where-Object {$RelevantExtensions -contains $_.Extension} | + ForEach-Object { + Write-Host -NoNewLine "`t Checking file" $_.FullName "... " + + $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server" + $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server" + + if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) { + Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")" + } + else { + $MissingSymbols++ + + if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) { + Write-Host "No symbols found on MSDL or SymWeb!" + } + else { + if ($SymbolsOnMSDL -eq $null) { + Write-Host "No symbols found on MSDL!" + } + else { + Write-Host "No symbols found on SymWeb!" + } + } + } + } + + Pop-Location + + return $MissingSymbols +} + +function CheckSymbolsAvailable { + if (Test-Path $ExtractPath) { + Remove-Item -recurse $ExtractPath + } + + Get-ChildItem "$InputPath\*.nupkg" | + ForEach-Object { + $FileName = $_.Name + Write-Host "Validating $FileName " + $Status = CountMissingSymbols "$InputPath\$FileName" + + if ($Status -ne 0) { + Write-Error "Missing symbols for $Status modules in the package $FileName" + } + } +} + +CheckSymbolsAvailable diff --git a/eng/common/PublishToSymbolServers.proj b/eng/common/PublishToSymbolServers.proj index 36c08f0ea492..5d55e312b012 100644 --- a/eng/common/PublishToSymbolServers.proj +++ b/eng/common/PublishToSymbolServers.proj @@ -24,6 +24,14 @@ + + + + diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj index 1a81ff906f6e..1a39a7ef3f67 100644 --- a/eng/common/internal/Tools.csproj +++ b/eng/common/internal/Tools.csproj @@ -12,8 +12,12 @@ - - https://devdiv.pkgs.visualstudio.com/_packaging/8f470c7e-ac49-4afe-a6ee-cf784e438b93/nuget/v3/index.json; + + + https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json; + + + $(RestoreSources); https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json; diff --git a/eng/common/templates/phases/publish-build-assets.yml b/eng/common/templates/phases/publish-build-assets.yml index 211967debab5..a0a8074282aa 100644 --- a/eng/common/templates/phases/publish-build-assets.yml +++ b/eng/common/templates/phases/publish-build-assets.yml @@ -5,6 +5,7 @@ parameters: condition: succeeded() continueOnError: false runAsPublic: false + publishUsingPipelines: false phases: - phase: Asset_Registry_Publish displayName: Publish to Build Asset Registry @@ -36,6 +37,7 @@ phases: /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' /p:BuildAssetRegistryToken=$(MaestroAccessToken) /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com + /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }} /p:Configuration=$(_BuildConfig) condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} diff --git a/functions.cmake b/functions.cmake index d86844591078..d20a574373f5 100644 --- a/functions.cmake +++ b/functions.cmake @@ -86,11 +86,7 @@ function(preprocess_def_file inputFilename outputFilename) PROPERTIES GENERATED TRUE) endfunction() -function(generate_exports_file) - set(INPUT_LIST ${ARGN}) - list(GET INPUT_LIST -1 outputFilename) - list(REMOVE_AT INPUT_LIST -1) - +function(generate_exports_file inputFilename outputFilename) if(CMAKE_SYSTEM_NAME STREQUAL Darwin) set(AWK_SCRIPT generateexportedsymbols.awk) else() @@ -99,8 +95,8 @@ function(generate_exports_file) add_custom_command( OUTPUT ${outputFilename} - COMMAND ${AWK} -f ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} ${INPUT_LIST} >${outputFilename} - DEPENDS ${INPUT_LIST} ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} + COMMAND ${AWK} -f ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} ${inputFilename} >${outputFilename} + DEPENDS ${inputFilename} ${CMAKE_SOURCE_DIR}/${AWK_SCRIPT} COMMENT "Generating exports file ${outputFilename}" ) set_source_files_properties(${outputFilename} diff --git a/global.json b/global.json index e0882827c518..8172ac723f67 100644 --- a/global.json +++ b/global.json @@ -7,7 +7,7 @@ "python": "2.7.15" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19207.1", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19207.1" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19215.12", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19215.12" } } diff --git a/netci.groovy b/netci.groovy index 4a765c8c358c..22ee7ffed57b 100755 --- a/netci.groovy +++ b/netci.groovy @@ -1267,8 +1267,14 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def // Check scenario. switch (scenario) { case 'crossgen_comparison': - if (isFlowJob && ((os == 'Ubuntu' && architecture == 'arm') || (os == 'Ubuntu16.04' && architecture == 'arm64')) && (configuration == 'Checked' || configuration == 'Release')) { - addPeriodicTriggerHelper(job, '@daily') + if (isFlowJob && (configuration == 'Checked' || configuration == 'Release')) { + if (os == 'Ubuntu' && architecture == 'arm') { + // Not enough Linux/arm32 hardware for this. + // addPeriodicTriggerHelper(job, '@daily') + } + if (os == 'Ubuntu16.04' && architecture == 'arm64') { + addPeriodicTriggerHelper(job, '@daily') + } } break @@ -1316,7 +1322,9 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def if (isFlowJob) { // Currently no push triggers, with limited arm Linux hardware. // TODO: If we have enough machine capacity, add some arm Linux push triggers. - addPeriodicTriggerHelper(job, '@daily') + + // Duplicated by AzDO + // addPeriodicTriggerHelper(job, '@daily') } } break @@ -1353,7 +1361,10 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def // arm r2r jobs should only run weekly. else if (architecture == 'arm') { if (isFlowJob) { - addPeriodicTriggerHelper(job, '@weekly') + // Linux arm32 done in AzDO + if (os == 'Windows_NT') { + addPeriodicTriggerHelper(job, '@weekly') + } } } // arm64 r2r jobs should only run weekly. @@ -1402,7 +1413,10 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def } else if (architecture == 'arm') { if (isFlowJob) { - addPeriodicTriggerHelper(job, '@weekly') + // Linux arm32 duplicated by AzDO + if (os == 'Windows_NT') { + addPeriodicTriggerHelper(job, '@weekly') + } } } else if (architecture == 'arm64') { @@ -1512,6 +1526,10 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def if (os in bidailyCrossList) { break } + if ((os == 'Ubuntu') && (architecture == 'arm') && !isCoreFxScenario(scenario)) { + // Linux arm32 duplicated by AzDO + break + } // ARM corefx testing uses non-flow jobs to provide the configuration-specific // build for the flow job. We don't need cron jobs for these. Note that the // Windows ARM jobs depend on a Windows "build only" job that exits the trigger @@ -1546,6 +1564,10 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def if (os in bidailyCrossList) { break } + if ((os == 'Ubuntu') && (architecture == 'arm')) { + // Linux arm32 duplicated by AzDO + break + } addPeriodicTriggerHelper(job, '@weekly') break case 'gcstress0xc': @@ -1565,6 +1587,10 @@ def static addNonPRTriggers(def job, def branch, def isPR, def architecture, def if (os in bidailyCrossList) { break } + if ((os == 'Ubuntu') && (architecture == 'arm')) { + // Linux arm32 duplicated by AzDO + break + } addPeriodicTriggerHelper(job, '@weekly') break diff --git a/src/System.Private.CoreLib/Common/NotImplemented.cs b/src/System.Private.CoreLib/Common/NotImplemented.cs index 82f4e18ddc0e..9c8062872fc9 100644 --- a/src/System.Private.CoreLib/Common/NotImplemented.cs +++ b/src/System.Private.CoreLib/Common/NotImplemented.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { // @@ -17,18 +18,6 @@ namespace System // internal static class NotImplemented { - internal static Exception ByDesign - { - get - { - return new NotImplementedException(); - } - } - - internal static Exception ByDesignWithMessage(string message) - { - return new NotImplementedException(message); - } + internal static Exception ByDesign => new NotImplementedException(); } } - diff --git a/src/System.Private.CoreLib/Common/System/SR.cs b/src/System.Private.CoreLib/Common/System/SR.cs index eb0713fb9ed0..da03e59c175c 100644 --- a/src/System.Private.CoreLib/Common/System/SR.cs +++ b/src/System.Private.CoreLib/Common/System/SR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -13,7 +14,7 @@ namespace System { internal static partial class SR { - private static ResourceManager ResourceManager + private static ResourceManager? ResourceManager { get; set; @@ -28,14 +29,14 @@ private static bool UsingResourceKeys() } // Needed for debugger integration - internal static string GetResourceString(string resourceKey) + internal static string? GetResourceString(string resourceKey) { return GetResourceString(resourceKey, string.Empty); } - internal static string GetResourceString(string resourceKey, string defaultString) + internal static string GetResourceString(string resourceKey, string? defaultString) { - string resourceString = null; + string? resourceString = null; try { resourceString = InternalGetResourceString(resourceKey); } catch (MissingManifestResourceException) { } @@ -44,20 +45,20 @@ internal static string GetResourceString(string resourceKey, string defaultStrin return defaultString; } - return resourceString; + return resourceString!; // only null if missing resource } - private static object _lock = new object(); - private static List _currentlyLoading; + private static readonly object _lock = new object(); + private static List? _currentlyLoading; private static int _infinitelyRecursingCount; private static bool _resourceManagerInited = false; - private static string InternalGetResourceString(string key) + private static string? InternalGetResourceString(string? key) { if (key == null || key.Length == 0) { Debug.Fail("SR::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); - return key; + return key!; } // We have a somewhat common potential for infinite @@ -124,7 +125,7 @@ private static string InternalGetResourceString(string key) { ResourceManager = new ResourceManager(SR.ResourceType); } - string s = ResourceManager.GetString(key, null); + string? s = ResourceManager.GetString(key, null); _currentlyLoading.RemoveAt(_currentlyLoading.Count - 1); // Pop Debug.Assert(s != null, "Managed resource string lookup failed. Was your resource name misspelled? Did you rebuild mscorlib after adding a resource to resources.txt? Debug this w/ cordbg and bug whoever owns the code that called SR.GetResourceString. Resource name was: \"" + key + "\""); @@ -149,7 +150,7 @@ private static string InternalGetResourceString(string key) } } - internal static string Format(IFormatProvider provider, string resourceFormat, params object[] args) + internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { @@ -164,7 +165,7 @@ internal static string Format(IFormatProvider provider, string resourceFormat, p return resourceFormat; } - internal static string Format(string resourceFormat, params object[] args) + internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { @@ -179,7 +180,7 @@ internal static string Format(string resourceFormat, params object[] args) return resourceFormat; } - internal static string Format(string resourceFormat, object p1) + internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { @@ -189,7 +190,7 @@ internal static string Format(string resourceFormat, object p1) return string.Format(resourceFormat, p1); } - internal static string Format(string resourceFormat, object p1, object p2) + internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { @@ -199,7 +200,7 @@ internal static string Format(string resourceFormat, object p1, object p2) return string.Format(resourceFormat, p1, p2); } - internal static string Format(string resourceFormat, object p1, object p2, object p3) + internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { diff --git a/src/System.Private.CoreLib/ILLinkTrim.xml b/src/System.Private.CoreLib/ILLinkTrim.xml index 5820e2be13b1..b621468b61ba 100644 --- a/src/System.Private.CoreLib/ILLinkTrim.xml +++ b/src/System.Private.CoreLib/ILLinkTrim.xml @@ -15,6 +15,7 @@ + @@ -36,6 +37,7 @@ + diff --git a/src/System.Private.CoreLib/Resources/Strings.resx b/src/System.Private.CoreLib/Resources/Strings.resx index 9fed81d6bf34..9e2c84b4d1d0 100644 --- a/src/System.Private.CoreLib/Resources/Strings.resx +++ b/src/System.Private.CoreLib/Resources/Strings.resx @@ -541,6 +541,9 @@ Object must be an array of primitives. + + Object must be of type RuntimeAssembly. + Object must be of type SByte. @@ -3751,4 +3754,4 @@ Startup hook assembly '{0}' failed to load. See inner exception for details. - \ No newline at end of file + diff --git a/src/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/System.Private.CoreLib.csproj index 96b9584874d1..c012ba5caebc 100644 --- a/src/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -150,7 +150,6 @@ - @@ -175,7 +174,7 @@ - + @@ -276,9 +275,6 @@ - - - @@ -372,7 +368,7 @@ - + diff --git a/src/System.Private.CoreLib/shared/Internal/IO/File.Unix.cs b/src/System.Private.CoreLib/shared/Internal/IO/File.Unix.cs index 50fa0f0d0c4b..25d62003de8c 100644 --- a/src/System.Private.CoreLib/shared/Internal/IO/File.Unix.cs +++ b/src/System.Private.CoreLib/shared/Internal/IO/File.Unix.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace Internal.IO { internal static partial class File diff --git a/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs b/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs index 0acae3b4577d..28624bb95f32 100644 --- a/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs +++ b/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.IO; diff --git a/src/System.Private.CoreLib/shared/Internal/IO/File.cs b/src/System.Private.CoreLib/shared/Internal/IO/File.cs index 2fcc0f391f3e..a8439895b1bd 100644 --- a/src/System.Private.CoreLib/shared/Internal/IO/File.cs +++ b/src/System.Private.CoreLib/shared/Internal/IO/File.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.Security; @@ -19,7 +20,7 @@ internal static partial class File // given by the specified path exists; otherwise, the result is // false. Note that if path describes a directory, // Exists will return true. - public static bool Exists(string path) + public static bool Exists(string? path) { try { diff --git a/src/System.Private.CoreLib/shared/Internal/Padding.cs b/src/System.Private.CoreLib/shared/Internal/Padding.cs index 14bf998babaa..86050b7fb75c 100644 --- a/src/System.Private.CoreLib/shared/Internal/Padding.cs +++ b/src/System.Private.CoreLib/shared/Internal/Padding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace Internal diff --git a/src/System.Private.CoreLib/shared/Internal/Resources/WindowsRuntimeResourceManagerBase.cs b/src/System.Private.CoreLib/shared/Internal/Resources/WindowsRuntimeResourceManagerBase.cs index 6594ae6f055e..531b0fd4e602 100644 --- a/src/System.Private.CoreLib/shared/Internal/Resources/WindowsRuntimeResourceManagerBase.cs +++ b/src/System.Private.CoreLib/shared/Internal/Resources/WindowsRuntimeResourceManagerBase.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Globalization; namespace Internal.Resources @@ -11,11 +11,11 @@ namespace Internal.Resources // allowing us to ask for a WinRT-specific ResourceManager. public abstract class WindowsRuntimeResourceManagerBase { - public abstract bool Initialize(string libpath, string reswFilename, out PRIExceptionInfo exceptionInfo); + public abstract bool Initialize(string libpath, string reswFilename, out PRIExceptionInfo? exceptionInfo); - public abstract string GetString(string stringName, string startingCulture, string neutralResourcesCulture); + public abstract string GetString(string stringName, string? startingCulture, string? neutralResourcesCulture); - public abstract CultureInfo GlobalResourceContextBestFitCultureInfo + public abstract CultureInfo? GlobalResourceContextBestFitCultureInfo { get; } @@ -26,7 +26,7 @@ public abstract CultureInfo GlobalResourceContextBestFitCultureInfo /// Check whether CultureData exists for specified cultureName /// This API is used for WindowsRuntimeResourceManager in System.Runtime.WindowsRuntime /// - public static bool IsValidCulture(string cultureName) + public static bool IsValidCulture(string? cultureName) { return CultureData.GetCultureData(cultureName, /* useUserOverride */ true) != null; } diff --git a/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs b/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs index 03d3f8521176..02092af2094d 100644 --- a/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs +++ b/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.CompilerServices; using System.Runtime.Versioning; @@ -71,7 +72,7 @@ public static int SizeOf() [Intrinsic] [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T As(object value) where T : class + public static T As(object? value) where T : class? { throw new PlatformNotSupportedException(); diff --git a/src/System.Private.CoreLib/shared/Internal/Threading/Tasks/AsyncCausalitySupport.cs b/src/System.Private.CoreLib/shared/Internal/Threading/Tasks/AsyncCausalitySupport.cs index dcea41dbab22..54df96db664a 100644 --- a/src/System.Private.CoreLib/shared/Internal/Threading/Tasks/AsyncCausalitySupport.cs +++ b/src/System.Private.CoreLib/shared/Internal/Threading/Tasks/AsyncCausalitySupport.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Threading.Tasks; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/Internal/Win32/RegistryKey.cs b/src/System.Private.CoreLib/shared/Internal/Win32/RegistryKey.cs index a98eef902b9e..469d67866a17 100644 --- a/src/System.Private.CoreLib/shared/Internal/Win32/RegistryKey.cs +++ b/src/System.Private.CoreLib/shared/Internal/Win32/RegistryKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Buffers; using System.Collections.Generic; @@ -28,7 +29,7 @@ internal sealed class RegistryKey : IDisposable private const int MaxKeyLength = 255; private const int MaxValueLength = 16383; - private SafeRegistryHandle _hkey = null; + private SafeRegistryHandle _hkey; private RegistryKey(SafeRegistryHandle hkey) { @@ -75,12 +76,12 @@ internal static RegistryKey OpenBaseKey(IntPtr hKey) return new RegistryKey(new SafeRegistryHandle(hKey, false)); } - public RegistryKey OpenSubKey(string name) + public RegistryKey? OpenSubKey(string name) { return OpenSubKey(name, false); } - public RegistryKey OpenSubKey(string name, bool writable) + public RegistryKey? OpenSubKey(string name, bool writable) { // Make sure that the name does not contain double slahes Debug.Assert(name.IndexOf("\\\\") == -1); @@ -162,7 +163,7 @@ public unsafe string[] GetValueNames() // add up quickly- we'll try to keep the memory pressure low and grow the buffer // only if needed. - char[] name = ArrayPool.Shared.Rent(100); + char[]? name = ArrayPool.Shared.Rent(100); try { @@ -214,18 +215,18 @@ public unsafe string[] GetValueNames() return names.ToArray(); } - public object GetValue(string name) + public object? GetValue(string name) { return GetValue(name, null); } - public object GetValue(string name, object defaultValue) + public object? GetValue(string name, object? defaultValue) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { - object data = defaultValue; + object? data = defaultValue; int type = 0; int datasize = 0; - int ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize); + int ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, (byte[]?)null, ref datasize); if (ret != 0) { @@ -369,7 +370,7 @@ public object GetValue(string name, object defaultValue) // make sure the string is null terminated before processing the data if (blob.Length > 0 && blob[blob.Length - 1] != (char)0) { - Array.Resize(ref blob, blob.Length + 1); + Array.Resize(ref blob!, blob.Length + 1); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } string[] strings = Array.Empty(); @@ -386,7 +387,7 @@ public object GetValue(string name, object defaultValue) nextNull++; } - string toAdd = null; + string? toAdd = null; if (nextNull < len) { Debug.Assert(blob[nextNull] == (char)0, "blob[nextNull] should be 0"); @@ -414,13 +415,13 @@ public object GetValue(string name, object defaultValue) { if (strings.Length == stringsCount) { - Array.Resize(ref strings, stringsCount > 0 ? stringsCount * 2 : 4); + Array.Resize(ref strings!, stringsCount > 0 ? stringsCount * 2 : 4); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } - strings[stringsCount++] = toAdd; + strings![stringsCount++] = toAdd; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } - Array.Resize(ref strings, stringsCount); + Array.Resize(ref strings!, stringsCount); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 data = strings; } break; @@ -455,7 +456,7 @@ internal void SetValue(string name, string value) } } - internal void Win32Error(int errorCode, string str) + internal void Win32Error(int errorCode, string? str) { switch (errorCode) { diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs index 554d0659aed9..a4a7a4344aa3 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -145,7 +146,9 @@ internal string GetErrorMessage() return Interop.Sys.StrError(RawErrno); } +#pragma warning disable CS8609 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 public override string ToString() +#pragma warning restore CS8609 { return $"RawErrno: {RawErrno} Error: {Error} GetErrorMessage: {GetErrorMessage()}"; // No localization required; text is member names used for debugging purposes } @@ -179,7 +182,7 @@ internal static unsafe string StrError(int platformErrno) message = buffer; } - return Marshal.PtrToStringAnsi((IntPtr)message); + return Marshal.PtrToStringAnsi((IntPtr)message)!; } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPlatformToPal")] diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.IOErrors.cs b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.IOErrors.cs index b3f9a3fdc745..666220ea1947 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.IOErrors.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.IOErrors.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.IO; @@ -10,7 +11,7 @@ internal static partial class Interop { - private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string path, bool isDirectory, Func errorRewriter) + private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string? path, bool isDirectory, Func? errorRewriter) { Debug.Assert(errorInfo.Error != Error.SUCCESS); Debug.Assert(errorInfo.Error != Error.EINTR, "EINTR errors should be handled by the native shim and never bubble up to managed code"); @@ -23,7 +24,7 @@ private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string path, b throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory); } - internal static void CheckIo(Error error, string path = null, bool isDirectory = false, Func errorRewriter = null) + internal static void CheckIo(Error error, string? path = null, bool isDirectory = false, Func? errorRewriter = null) { if (error != Interop.Error.SUCCESS) { @@ -43,7 +44,7 @@ internal static void CheckIo(Error error, string path = null, bool isDirectory = /// /// On success, returns the non-negative result long that was validated. /// - internal static long CheckIo(long result, string path = null, bool isDirectory = false, Func errorRewriter = null) + internal static long CheckIo(long result, string? path = null, bool isDirectory = false, Func? errorRewriter = null) { if (result < 0) { @@ -61,7 +62,7 @@ internal static long CheckIo(long result, string path = null, bool isDirectory = /// /// On success, returns the non-negative result int that was validated. /// - internal static int CheckIo(int result, string path = null, bool isDirectory = false, Func errorRewriter = null) + internal static int CheckIo(int result, string? path = null, bool isDirectory = false, Func? errorRewriter = null) { CheckIo((long)result, path, isDirectory, errorRewriter); @@ -76,7 +77,7 @@ internal static int CheckIo(int result, string path = null, bool isDirectory = f /// /// On success, returns the non-negative result IntPtr that was validated. /// - internal static IntPtr CheckIo(IntPtr result, string path = null, bool isDirectory = false, Func errorRewriter = null) + internal static IntPtr CheckIo(IntPtr result, string? path = null, bool isDirectory = false, Func? errorRewriter = null) { CheckIo((long)result, path, isDirectory, errorRewriter); @@ -91,7 +92,7 @@ internal static IntPtr CheckIo(IntPtr result, string path = null, bool isDirecto /// /// On success, returns the valid SafeFileHandle that was validated. /// - internal static TSafeHandle CheckIo(TSafeHandle handle, string path = null, bool isDirectory = false, Func errorRewriter = null) + internal static TSafeHandle CheckIo(TSafeHandle handle, string? path = null, bool isDirectory = false, Func? errorRewriter = null) where TSafeHandle : SafeHandle { if (handle.IsInvalid) @@ -109,7 +110,7 @@ internal static TSafeHandle CheckIo(TSafeHandle handle, string path /// The path with which this error is associated. This may be null. /// true if the is known to be a directory; otherwise, false. /// - internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string path = null, bool isDirectory = false) + internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string? path = null, bool isDirectory = false) { // Translate the errno into a known set of exception types. For cases where multiple errnos map // to the same exception type, include an inner exception with the details. diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Libraries.cs b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Libraries.cs index 02d009244509..6c620bf03107 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Libraries.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Libraries.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal static partial class Interop { internal static partial class Libraries diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs index 764bdaf85afe..c5ec71a73d2f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Globalization; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs index 503a864d693c..2878161c9910 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; using System.Security; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs index aea7615e4e71..9d21d23acb08 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Globalization; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ICU.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ICU.cs index a16c813b2f5a..f122d519ba0d 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ICU.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ICU.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs index 89b6c3cebec0..9a0cd923be01 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs index 417b71e7f166..40de0991821a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -34,6 +35,6 @@ internal static partial class Globalization internal static extern bool GetLocaleInfoGroupingSizes(string localeName, uint localeGroupingData, ref int primaryGroupSize, ref int secondaryGroupSize); [DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocales")] - internal static extern int GetLocales([Out] char[] value, int valueLength); + internal static extern int GetLocales([Out] char[]? value, int valueLength); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs index d442da0ea137..2cfc3746ba4b 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; using System.Text; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs index 4a9933f9291f..d5261ac6ca32 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal static partial class Interop { internal static partial class Globalization diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs index 6c6926824621..583599fb1390 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; using System.Text; diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs index 9698be92e921..058f07efe1ae 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.Buffers; @@ -17,7 +18,7 @@ internal static partial class Interop internal static bool CallStringMethod( SpanFunc interopCall, TArg1 arg1, TArg2 arg2, TArg3 arg3, - out string result) + out string? result) { const int InitialSize = 256; // arbitrary stack allocation size const int MaxHeapSize = 1280; // max from previous version of the code, starting at 80 and doubling four times diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetHostName.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetHostName.cs index 6d2fdc58cc2d..34fa14f35256 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetHostName.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetHostName.cs @@ -35,7 +35,7 @@ internal static unsafe string GetHostName() // If the hostname is truncated, it is unspecified whether the returned buffer includes a terminating null byte. name[ArrLength - 1] = 0; - return Marshal.PtrToStringAnsi((IntPtr)name); + return Marshal.PtrToStringAnsi((IntPtr)name)!; } } } diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetUnixName.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetUnixName.cs index 6f3c3ff78d50..02e08fd447c1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetUnixName.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetUnixName.cs @@ -16,7 +16,7 @@ internal static partial class Sys internal static string GetUnixName() { IntPtr ptr = GetUnixNamePrivate(); - return Marshal.PtrToStringAnsi(ptr); + return Marshal.PtrToStringAnsi(ptr)!; } } } diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.MountPoints.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.MountPoints.cs index 913b7ebbb77c..c2d1b7946672 100644 --- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.MountPoints.cs +++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.MountPoints.cs @@ -28,13 +28,13 @@ internal static string[] GetAllMountPoints() { if (count == found.Length) { - Array.Resize(ref found, count * 2); + Array.Resize(ref found!, count * 2); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } - found[count++] = Marshal.PtrToStringAnsi((IntPtr)name); + found[count++] = Marshal.PtrToStringAnsi((IntPtr)name)!; }); } - Array.Resize(ref found, count); + Array.Resize(ref found!, count); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return found; } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.ActivityControl.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.ActivityControl.cs new file mode 100644 index 000000000000..34df748d39ab --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.ActivityControl.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + internal enum ActivityControl : uint + { + EVENT_ACTIVITY_CTRL_GET_ID = 1, + EVENT_ACTIVITY_CTRL_SET_ID = 2, + EVENT_ACTIVITY_CTRL_CREATE_ID = 3, + EVENT_ACTIVITY_CTRL_GET_SET_ID = 4, + EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5 + } + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EVENT_INFO_CLASS.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EVENT_INFO_CLASS.cs new file mode 100644 index 000000000000..a122002e9abe --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EVENT_INFO_CLASS.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + internal enum EVENT_INFO_CLASS + { + BinaryTrackInfo, + SetEnableAllKeywords, + SetTraits, + } + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EtwEnableCallback.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EtwEnableCallback.cs new file mode 100644 index 000000000000..6bb157520f35 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EtwEnableCallback.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0; + internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1; + internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2; + + [StructLayout(LayoutKind.Sequential)] + internal struct EVENT_FILTER_DESCRIPTOR + { + public long Ptr; + public int Size; + public int Type; + } + + internal unsafe delegate void EtwEnableCallback( + in Guid sourceId, + int isEnabled, + byte level, + long matchAnyKeywords, + long matchAllKeywords, + EVENT_FILTER_DESCRIPTOR* filterData, + void* callbackContext); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventActivityIdControl.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventActivityIdControl.cs new file mode 100644 index 000000000000..886ff37d19fe --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventActivityIdControl.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + [DllImport(Libraries.Advapi32, ExactSpelling = true)] + internal static extern int EventActivityIdControl(ActivityControl ControlCode, ref Guid ActivityId); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventRegister.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventRegister.cs new file mode 100644 index 000000000000..f5d245ec5d68 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventRegister.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + [DllImport(Libraries.Advapi32, ExactSpelling = true)] + internal static extern unsafe uint EventRegister( + in Guid providerId, + EtwEnableCallback enableCallback, + void* callbackContext, + ref long registrationHandle); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventSetInformation.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventSetInformation.cs new file mode 100644 index 000000000000..381cb661c37e --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventSetInformation.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + [DllImport(Libraries.Advapi32, ExactSpelling = true)] + internal static unsafe extern int EventSetInformation( + long registrationHandle, + EVENT_INFO_CLASS informationClass, + void* eventInformation, + int informationLength); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs new file mode 100644 index 000000000000..c5f6f3b18790 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + internal enum TRACE_QUERY_INFO_CLASS + { + TraceGuidQueryList, + TraceGuidQueryInfo, + TraceGuidQueryProcess, + TraceStackTracingInfo, + MaxTraceSetInfoClass + } + + [StructLayout(LayoutKind.Sequential)] + internal struct TRACE_GUID_INFO + { + public int InstanceCount; + public int Reserved; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct TRACE_PROVIDER_INSTANCE_INFO + { + public int NextOffset; + public int EnableCount; + public int Pid; + public int Flags; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct TRACE_ENABLE_INFO + { + public int IsEnabled; + public byte Level; + public byte Reserved1; + public ushort LoggerId; + public int EnableProperty; + public int Reserved2; + public long MatchAnyKeyword; + public long MatchAllKeyword; + } + + [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true)] + internal static unsafe extern int EnumerateTraceGuidsEx( + TRACE_QUERY_INFO_CLASS TraceQueryInfoClass, + void* InBuffer, + int InBufferSize, + void* OutBuffer, + int OutBufferSize, + out int ReturnLength); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventUnregister.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventUnregister.cs new file mode 100644 index 000000000000..f387b3a9ab5c --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventUnregister.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + [DllImport(Libraries.Advapi32, ExactSpelling = true)] + internal static extern uint EventUnregister(long registrationHandle); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventWriteString.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventWriteString.cs new file mode 100644 index 000000000000..a00a2f3a2c99 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventWriteString.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Advapi32 + { + [DllImport(Libraries.Advapi32, ExactSpelling = true)] + internal static extern int EventWriteString( + long registrationHandle, + byte level, + long keyword, + string msg); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs new file mode 100644 index 000000000000..2d3f45e839be --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +#if ES_BUILD_STANDALONE +using Microsoft.Diagnostics.Tracing; +#else +using System.Diagnostics.Tracing; +#endif + +internal partial class Interop +{ + internal partial class Advapi32 + { + /// + /// Call the ETW native API EventWriteTransfer and checks for invalid argument error. + /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId. + /// So, for these cases we will retry the call with an empty Guid. + /// + internal static unsafe int EventWriteTransfer( + long registrationHandle, + in EventDescriptor eventDescriptor, + Guid* activityId, + Guid* relatedActivityId, + int userDataCount, + EventProvider.EventData* userData) + { + int HResult = EventWriteTransfer_PInvoke(registrationHandle, in eventDescriptor, activityId, relatedActivityId, userDataCount, userData); + if (HResult == Errors.ERROR_INVALID_PARAMETER && relatedActivityId == null) + { + Guid emptyGuid = Guid.Empty; + HResult = EventWriteTransfer_PInvoke(registrationHandle, in eventDescriptor, activityId, &emptyGuid, userDataCount, userData); + } + + return HResult; + } + + [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteTransfer")] + private static unsafe extern int EventWriteTransfer_PInvoke( + long registrationHandle, + in EventDescriptor eventDescriptor, + Guid* activityId, + Guid* relatedActivityId, + int userDataCount, + EventProvider.EventData* userData); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.LookupAccountNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.LookupAccountNameW.cs index 3554665e5f94..bef8afa434bb 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.LookupAccountNameW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.LookupAccountNameW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop @@ -10,7 +11,7 @@ internal partial class Advapi32 { [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] internal static extern bool LookupAccountNameW( - string lpSystemName, + string? lpSystemName, ref char lpAccountName, ref byte Sid, ref uint cbSid, diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs index 375376d52a01..e27966978231 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs index b6c6d9809c64..7f3dcbea7689 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -21,7 +22,7 @@ internal static extern int RegCreateKeyEx( SafeRegistryHandle hKey, string lpSubKey, int Reserved, - string lpClass, + string? lpClass, int dwOptions, int samDesired, ref Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs, diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs index c949cc15ff1f..01c4cea4086a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs index 378666908ed5..4e0fdd9d40f5 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -15,6 +16,6 @@ internal partial class Interop internal partial class Advapi32 { [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW")] - internal static extern int RegDeleteValue(SafeRegistryHandle hKey, string lpValueName); + internal static extern int RegDeleteValue(SafeRegistryHandle hKey, string? lpValueName); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs index 8e37b8e74b1d..b2873fa8690b 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -21,9 +22,9 @@ internal static extern unsafe int RegEnumKeyEx( int dwIndex, char[] lpName, ref int lpcbName, - int[] lpReserved, - [Out] char[] lpClass, - int[] lpcbClass, - long[] lpftLastWriteTime); + int[]? lpReserved, + [Out] char[]? lpClass, + int[]? lpcbClass, + long[]? lpftLastWriteTime); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs index 28d24e208ab7..3d455d0ccdb1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -21,8 +22,8 @@ internal static extern unsafe int RegEnumValue( char[] lpValueName, ref int lpcbValueName, IntPtr lpReserved_MustBeZero, - int[] lpType, - byte[] lpData, - int[] lpcbData); + int[]? lpType, + byte[]? lpData, + int[]? lpcbData); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs index fa56f483990a..3a867a2e31be 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs index d186d98043f1..32cbbfc0bd65 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -17,7 +18,7 @@ internal partial class Advapi32 [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")] internal static extern int RegOpenKeyEx( SafeRegistryHandle hKey, - string lpSubKey, + string? lpSubKey, int ulOptions, int samDesired, out SafeRegistryHandle hkResult); @@ -26,7 +27,7 @@ internal static extern int RegOpenKeyEx( [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")] internal static extern int RegOpenKeyEx( IntPtr hKey, - string lpSubKey, + string? lpSubKey, int ulOptions, int samDesired, out SafeRegistryHandle hkResult); diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs index 2d220a1963bc..24eeb1fb9443 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -18,16 +19,16 @@ internal partial class Advapi32 [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryInfoKeyW")] internal static extern int RegQueryInfoKey( SafeRegistryHandle hKey, - [Out] char[] lpClass, - int[] lpcbClass, + [Out] char[]? lpClass, + int[]? lpcbClass, IntPtr lpReserved_MustBeZero, ref int lpcSubKeys, - int[] lpcbMaxSubKeyLen, - int[] lpcbMaxClassLen, + int[]? lpcbMaxSubKeyLen, + int[]? lpcbMaxClassLen, ref int lpcValues, - int[] lpcbMaxValueNameLen, - int[] lpcbMaxValueLen, - int[] lpcbSecurityDescriptor, - int[] lpftLastWriteTime); + int[]? lpcbMaxValueNameLen, + int[]? lpcbMaxValueLen, + int[]? lpcbSecurityDescriptor, + int[]? lpftLastWriteTime); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs index 989d0727c72e..0ed94b2157b4 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -18,17 +19,17 @@ internal partial class Advapi32 [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, - string lpValueName, - int[] lpReserved, + string? lpValueName, + int[]? lpReserved, ref int lpType, - [Out] byte[] lpData, + [Out] byte[]? lpData, ref int lpcbData); [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, - string lpValueName, - int[] lpReserved, + string? lpValueName, + int[]? lpReserved, ref int lpType, ref int lpData, ref int lpcbData); @@ -36,8 +37,8 @@ internal static extern int RegQueryValueEx( [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, - string lpValueName, - int[] lpReserved, + string? lpValueName, + int[]? lpReserved, ref int lpType, ref long lpData, ref int lpcbData); @@ -45,10 +46,10 @@ internal static extern int RegQueryValueEx( [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")] internal static extern int RegQueryValueEx( SafeRegistryHandle hKey, - string lpValueName, - int[] lpReserved, + string? lpValueName, + int[]? lpReserved, ref int lpType, - [Out] char[] lpData, + [Out] char[]? lpData, ref int lpcbData); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs index 7fb479ee0987..64a405695c79 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if REGISTRY_ASSEMBLY using Microsoft.Win32.SafeHandles; #else @@ -17,25 +18,25 @@ internal partial class Advapi32 [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, - string lpValueName, + string? lpValueName, int Reserved, int dwType, - byte[] lpData, + byte[]? lpData, int cbData); [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, - string lpValueName, + string? lpValueName, int Reserved, int dwType, - char[] lpData, + char[]? lpData, int cbData); [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, - string lpValueName, + string? lpValueName, int Reserved, int dwType, ref int lpData, @@ -44,7 +45,7 @@ internal static extern int RegSetValueEx( [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, - string lpValueName, + string? lpValueName, int Reserved, int dwType, ref long lpData, @@ -53,10 +54,10 @@ internal static extern int RegSetValueEx( [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")] internal static extern int RegSetValueEx( SafeRegistryHandle hKey, - string lpValueName, + string? lpValueName, int Reserved, int dwType, - string lpData, + string? lpData, int cbData); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs index bdb89702f8c3..b358f9fee081 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class Advapi32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs index 4d75163d4b41..50bc5281586c 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs index 9d072a3b01e6..d877dd255ce1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs index 29aaa2904bff..74079f8f80ad 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs index b10cb6a0410b..a60dc8eeecac 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Crypt32/Interop.CryptProtectMemory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; using System.Security; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOL.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOL.cs index 9f4dab8935d2..8a89556e59b0 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOL.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOL.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { /// diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOLEAN.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOLEAN.cs index 4874734534df..154ecbec7275 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOLEAN.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.BOOLEAN.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { /// diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Errors.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Errors.cs index 1a95db3c939b..ea9ce0b8a35a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Errors.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Errors.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { // As defined in winerror.h and https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx @@ -18,6 +19,7 @@ internal partial class Errors internal const int ERROR_NOT_READY = 0x15; internal const int ERROR_SHARING_VIOLATION = 0x20; internal const int ERROR_HANDLE_EOF = 0x26; + internal const int ERROR_NOT_SUPPORTED = 0x32; internal const int ERROR_FILE_EXISTS = 0x50; internal const int ERROR_INVALID_PARAMETER = 0x57; internal const int ERROR_BROKEN_PIPE = 0x6D; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs index 8cbc8bfb266b..80321fb07af8 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal static partial class Interop { internal static partial class Libraries diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs index 16365ee65119..3330d32f9a89 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.IO; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CancelIoEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CancelIoEx.cs index fc99e3052f6d..85809e1ed202 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CancelIoEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CancelIoEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.Threading; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs index ff41f939f1c6..fd194166709f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs index b13cdfd03fed..dc7dfef34e9e 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal static partial class Interop { internal static partial class Kernel32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile.cs index 9ee1e16fa666..99ef2b28d792 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -33,8 +35,9 @@ internal static SafeFileHandle CreateFile( int dwFlagsAndAttributes, IntPtr hTemplateFile) { - lpFileName = PathInternal.EnsureExtendedPrefixOverMaxPath(lpFileName); - return CreateFilePrivate(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + string? lpFileNameWithPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(lpFileName); + Debug.Assert(lpFileNameWithPrefix != null, "null not expected when non-null passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + return CreateFilePrivate(lpFileNameWithPrefix, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs index ddc18f6c42f8..fc9806132269 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CreateFile2.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.IO; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs index ce3db6f2b458..67804d4a737b 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FILE_INFO_BY_HANDLE_CLASS.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FILE_INFO_BY_HANDLE_CLASS.cs index e31a453ba943..c619115fdd49 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FILE_INFO_BY_HANDLE_CLASS.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FILE_INFO_BY_HANDLE_CLASS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileAttributes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileAttributes.cs index 725a25a7193a..8103870deae8 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileAttributes.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileAttributes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class Kernel32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs new file mode 100644 index 000000000000..f8c1be93f5b7 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32)] + internal static unsafe extern Interop.BOOL FileTimeToSystemTime(long* lpFileTime, Interop.Kernel32.SYSTEMTIME* lpSystemTime); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs index 9d52f1f4f42d..a4330f53389b 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class Kernel32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs index fcf9254acaae..de11958fe369 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs index dcb86ec9b6a4..80fb2e7189fc 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -19,10 +21,11 @@ internal partial class Kernel32 internal static SafeFindHandle FindFirstFile(string fileName, ref WIN32_FIND_DATA data) { - fileName = PathInternal.EnsureExtendedPrefixIfNeeded(fileName); + string? fileNameWithPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(fileName); + Debug.Assert(fileNameWithPrefix != null, "null not expected when non-null passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 // use FindExInfoBasic since we don't care about short name and it has better perf - return FindFirstFileExPrivate(fileName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0); + return FindFirstFileExPrivate(fileNameWithPrefix, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0); } internal enum FINDEX_INFO_LEVELS : uint diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs index e10a2279cff1..5d0f0dcea7cc 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs index 09001e81e064..bfa40819a1e0 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs index c372a8553ecb..7c317e2665a9 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeEnvironmentStrings.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs index c70865350aeb..b6b8ed670182 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FreeLibrary.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCPInfo.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCPInfo.cs index 8d523e41e9ac..98537ec330b8 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCPInfo.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCPInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetComputerName.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetComputerName.cs index 34a26c180f37..620fe8331534 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetComputerName.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetComputerName.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -15,7 +16,7 @@ internal partial class Kernel32 // maximum length of the NETBIOS name (not including NULL) private const int MAX_COMPUTERNAME_LENGTH = 15; - internal static unsafe string GetComputerName() + internal static unsafe string? GetComputerName() { Span buffer = stackalloc char[MAX_COMPUTERNAME_LENGTH + 1]; uint length = (uint)buffer.Length; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs index 611cc70d289d..2f2eb48bbd5e 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentDirectory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcessId.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcessId.cs index 3a1a353d8620..b71fb4e6f22f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcessId.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcessId.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcess_IntPtr.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcess_IntPtr.cs index c99351950a83..7b9ea6661897 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcess_IntPtr.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentProcess_IntPtr.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs index d456db752257..0599f4c59023 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs index 29a686026a27..9d25bed4800e 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentStrings.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs index 13adefc21634..d591219b12ae 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs index 181fb1010583..624404952f77 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -19,8 +21,9 @@ internal partial class Kernel32 internal static bool GetFileAttributesEx(string name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation) { - name = PathInternal.EnsureExtendedPrefixOverMaxPath(name); - return GetFileAttributesExPrivate(name, fileInfoLevel, ref lpFileInformation); + string? nameWithExtendedPrefix = PathInternal.EnsureExtendedPrefixIfNeeded(name); + Debug.Assert(nameWithExtendedPrefix != null, "null not expected when non-null is passed"); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + return GetFileAttributesExPrivate(nameWithExtendedPrefix, fileInfoLevel, ref lpFileInformation); } internal enum GET_FILEEX_INFO_LEVELS : uint @@ -69,9 +72,9 @@ internal unsafe struct WIN32_FIND_DATA internal uint dwReserved0; internal uint dwReserved1; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - internal string cFileName; + internal string? cFileName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - internal string cAlternateFileName; + internal string? cAlternateFileName; } internal struct FILE_TIME diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileInformationByHandleEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileInformationByHandleEx.cs index 1106cff1c58f..78c9e7071fe0 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileInformationByHandleEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileInformationByHandleEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs index faa57cc2f121..3f9e6271b5b5 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs index 197b0a9be523..38b7cdd2e63f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs index 657188f255e2..c69f7d30c204 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs index 81b4d096f564..dd497bf6d92c 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessInformation.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessInformation.cs new file mode 100644 index 000000000000..76027483f23a --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessInformation.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + internal const int ProcessLeapSecondInfo = 8; + + internal struct PROCESS_LEAP_SECOND_INFO + { + public uint Flags; + public uint Reserved; + } + + [DllImport(Libraries.Kernel32)] + internal static unsafe extern Interop.BOOL GetProcessInformation(IntPtr hProcess, int ProcessInformationClass, void* ProcessInformation, int ProcessInformationSize); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs index 22ec793c4907..7b72ca773207 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -12,4 +13,4 @@ internal partial class Kernel32 [DllImport(Libraries.Kernel32, SetLastError = true)] internal extern static bool GetProcessTimes(IntPtr handleProcess, out long creation, out long exit, out long kernel, out long user); } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetStdHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetStdHandle.cs index f2b54c9728a2..ae54f641d60d 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetStdHandle.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetStdHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs index 197f6f5eadcd..a7cd273098c3 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemDirectoryW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal static partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs index cbf07eae7ffa..56210558d2d1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTime.cs new file mode 100644 index 000000000000..b51cfa396e1a --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTime.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32)] + internal static unsafe extern void GetSystemTime(Interop.Kernel32.SYSTEMTIME* lpSystemTime); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimeAsFileTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimeAsFileTime.cs new file mode 100644 index 000000000000..70363ce6961f --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimeAsFileTime.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32)] + internal static unsafe extern void GetSystemTimeAsFileTime(long* lpSystemTimeAsFileTime); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimePreciseAsFileTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimePreciseAsFileTime.cs new file mode 100644 index 000000000000..8c86d952870b --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimePreciseAsFileTime.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32)] + internal static unsafe extern void GetSystemTimePreciseAsFileTime(long* lpSystemTimeAsFileTime); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimes.cs index ff2697804669..12d5a4aa57d4 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimes.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetSystemTimes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -12,4 +13,4 @@ internal partial class Kernel32 [DllImport(Libraries.Kernel32, SetLastError = true)] internal extern static bool GetSystemTimes(out long idle, out long kernel, out long user); } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs index 97e1d82847a6..0afc4481be75 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs index 7f7bb775c85a..68ff9aca40f8 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetVersionExW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetVersionExW.cs index 13a997a34400..ab79ed2ea4f7 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetVersionExW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetVersionExW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GlobalMemoryStatusEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GlobalMemoryStatusEx.cs index 6a87ec370b24..99dde8581597 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GlobalMemoryStatusEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GlobalMemoryStatusEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs index 80b52e6ab99a..1312454eabbd 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -40,7 +41,7 @@ internal static unsafe partial class Kernel32 [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] internal static extern unsafe int LCMapStringEx( - string lpLocaleName, + string? lpLocaleName, uint dwMapFlags, char* lpSrcStr, int cchSrc, @@ -102,7 +103,7 @@ internal static extern unsafe bool IsNLSDefinedString( #if !ENABLE_WINRT [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] - internal static extern bool GetUserPreferredUILanguages(uint dwFlags, out uint pulNumLanguages, char [] pwszLanguagesBuffer, ref uint pcchLanguagesBuffer); + internal static extern bool GetUserPreferredUILanguages(uint dwFlags, out uint pulNumLanguages, char[]? pwszLanguagesBuffer, ref uint pcchLanguagesBuffer); #endif //!ENABLE_WINRT [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] @@ -119,13 +120,13 @@ internal static extern unsafe bool IsNLSDefinedString( internal delegate BOOL EnumTimeFormatsProcEx(char* lpTimeFormatString, void* lParam); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, out int lpValue); + internal static extern int GetCalendarInfoEx(string? lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, out int lpValue); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, IntPtr lpValue); + internal static extern int GetCalendarInfoEx(string? lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, IntPtr lpValue); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern bool EnumCalendarInfoExEx(EnumCalendarInfoProcExEx pCalInfoEnumProcExEx, string lpLocaleName, uint Calendar, string lpReserved, uint CalType, void* lParam); + internal static extern bool EnumCalendarInfoExEx(EnumCalendarInfoProcExEx pCalInfoEnumProcExEx, string lpLocaleName, uint Calendar, string? lpReserved, uint CalType, void* lParam); internal delegate BOOL EnumCalendarInfoProcExEx(char* lpCalendarInfoString, uint Calendar, IntPtr lpReserved, void* lParam); diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.HandleTypes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.HandleTypes.cs index c2096aa62b75..51f7c92f024f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.HandleTypes.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.HandleTypes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class Kernel32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs index 7953da68daa5..5d064780bfec 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs index 4eef5852fe7e..c3c6fcc118d1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LoadLibraryEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LocalAlloc.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LocalAlloc.cs index 9c74adbe01a5..55f76b4403c5 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LocalAlloc.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LocalAlloc.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LockFile.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LockFile.cs index a21d00f4f665..7d0a55ce644f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LockFile.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.LockFile.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.IO; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MAX_PATH.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MAX_PATH.cs index f7fa32669bad..0a05230f1328 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MAX_PATH.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MAX_PATH.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class Kernel32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORYSTATUSEX.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORYSTATUSEX.cs index 45f57aa4d83b..8ddac8e64f48 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORYSTATUSEX.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORYSTATUSEX.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORY_BASIC_INFORMATION.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORY_BASIC_INFORMATION.cs index 0744d53f66c5..a14157fecc10 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORY_BASIC_INFORMATION.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MEMORY_BASIC_INFORMATION.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs index 509d9a241107..024dd1fba49c 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs index 158e4db3fd30..edabe9f9f6b9 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OSVERSIONINFOEX.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OSVERSIONINFOEX.cs index 1bfe00c57446..19c32e07c183 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OSVERSIONINFOEX.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OSVERSIONINFOEX.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OutputDebugString.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OutputDebugString.cs index 8da50ff8ab3a..bc7c1c83be5a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OutputDebugString.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.OutputDebugString.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceCounter.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceCounter.cs index ddc9797e5f2a..e0959f73daea 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceCounter.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceCounter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceFrequency.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceFrequency.cs index 72a48ba208be..71fd3db6cb70 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceFrequency.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryPerformanceFrequency.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryUnbiasedInterruptTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryUnbiasedInterruptTime.cs index 87ca7fd1d497..bdd77c180fb1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryUnbiasedInterruptTime.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.QueryUnbiasedInterruptTime.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs index 076f7f136fde..67e317adf060 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs index 3ae65a88069e..0687830057c1 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ResolveLocaleName.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ResolveLocaleName.cs index 2d6b6c3c729e..1a0e61317ceb 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ResolveLocaleName.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ResolveLocaleName.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs index 8d31f8622ff4..16e9fec77394 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SYSTEM_INFO.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SYSTEM_INFO.cs index 16e5bfd8da0c..ab793a390b55 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SYSTEM_INFO.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SYSTEM_INFO.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SecurityOptions.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SecurityOptions.cs index 4a4402484f2b..4e94e3e5a856 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SecurityOptions.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SecurityOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class Kernel32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs index b30e5d765643..5cf23a8d471e 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetCurrentDirectory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEndOfFile.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEndOfFile.cs index e5d60041a8ed..2233e1f83815 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEndOfFile.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEndOfFile.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs index cff406fca5bb..6a0fc1d4d96a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetEnvironmentVariable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop @@ -9,6 +10,6 @@ internal partial class Interop internal partial class Kernel32 { [DllImport(Libraries.Kernel32, EntryPoint = "SetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] - internal static extern bool SetEnvironmentVariable(string lpName, string lpValue); + internal static extern bool SetEnvironmentVariable(string lpName, string? lpValue); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetFilePointerEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetFilePointerEx.cs index c0e5247a5233..dbedf85cbead 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetFilePointerEx.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetFilePointerEx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs index 123eb75d7bee..b5bd94508608 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs new file mode 100644 index 000000000000..cf81e3d29524 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32)] + internal static unsafe extern Interop.BOOL SystemTimeToFileTime(Interop.Kernel32.SYSTEMTIME* lpSystemTime, long* lpFileTime); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.Registry.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.Registry.cs index 062d1caebacc..30299ae709dd 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.Registry.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.Registry.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs index 68d4583b54a2..dc89af488a8c 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs new file mode 100644 index 000000000000..e832e9341e6e --- /dev/null +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal partial class Kernel32 + { + [DllImport(Libraries.Kernel32)] + internal static unsafe extern Interop.BOOL TzSpecificLocalTimeToSystemTime( + IntPtr lpTimeZoneInformation, + Interop.Kernel32.SYSTEMTIME* lpLocalTime, + Interop.Kernel32.SYSTEMTIME* lpUniversalTime); + } +} diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerSetConditionMask.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerSetConditionMask.cs index 385e48a43907..931faf5705da 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerSetConditionMask.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerSetConditionMask.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerifyVersionExW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerifyVersionExW.cs index 5c2471cf4952..90f5bdbe103f 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerifyVersionExW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VerifyVersionExW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs index a97dc1aec7bb..944fb4e5eb62 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualFree.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualFree.cs index 574cd93a0a8f..2b940a4210cf 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualFree.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualFree.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualQuery.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualQuery.cs index faab1cc81a61..c7c02d687551 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualQuery.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.VirtualQuery.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WideCharToMultiByte.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WideCharToMultiByte.cs index a06c9153f470..6e523e5b7b44 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WideCharToMultiByte.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WideCharToMultiByte.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs index 69651ca1cab3..46948096ed72 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs index dc1e97555b89..6816d59028ef 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Idna.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Idna.cs index f49ce8dd6170..61b107bd5afc 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Idna.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Idna.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Normalization.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Normalization.cs index 3e49f1f64caf..d7f639b9653a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Normalization.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Normaliz/Interop.Normalization.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -18,7 +19,7 @@ internal static extern int NormalizeString( string source, int sourceLength, [System.Runtime.InteropServices.OutAttribute()] - char[] destination, + char[]? destination, int destinationLength); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs b/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQueryInformationFile.cs similarity index 98% rename from src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs rename to src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQueryInformationFile.cs index 4ba39a74e2b2..96bc2986afa4 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQueryInformationFile.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQuerySystemInformation.cs b/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQuerySystemInformation.cs index 16f05e338cd9..1115926bba43 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQuerySystemInformation.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/Interop.NtQuerySystemInformation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs index 57accbe7c008..db5c04aeff03 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoTaskMemAlloc.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoTaskMemAlloc.cs index 9119ee774e5f..335531d77a54 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoTaskMemAlloc.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoTaskMemAlloc.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringByteLen.cs b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringByteLen.cs index 52496893a069..6cec249eba59 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringByteLen.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringByteLen.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -10,6 +11,6 @@ internal partial class Interop internal partial class OleAut32 { [DllImport(Libraries.OleAut32)] - internal static extern IntPtr SysAllocStringByteLen(byte[] str, uint len); + internal static extern IntPtr SysAllocStringByteLen(byte[]? str, uint len); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs index be902b0c5820..67bd4f0bc05a 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; using System.Security; @@ -14,6 +15,6 @@ internal partial class OleAut32 internal static extern SafeBSTRHandle SysAllocStringLen(IntPtr src, uint len); [DllImport(Libraries.OleAut32, CharSet = CharSet.Unicode)] - internal static extern IntPtr SysAllocStringLen(string src, int len); + internal static extern IntPtr SysAllocStringLen(string? src, int len); } } diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysFreeString.cs b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysFreeString.cs index 8673cc672411..8e1c9d8f2e4c 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysFreeString.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysFreeString.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysStringLen.cs b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysStringLen.cs index cf65d6b086cf..7bd214ac6733 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysStringLen.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysStringLen.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; using System.Security; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Secur32/Interop.GetUserNameExW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Secur32/Interop.GetUserNameExW.cs index cf0dd5f698fb..e91506bf4e43 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Secur32/Interop.GetUserNameExW.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Secur32/Interop.GetUserNameExW.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; internal partial class Interop diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Shell32/Interop.SHGetKnownFolderPath.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Shell32/Interop.SHGetKnownFolderPath.cs index 1090805c0e04..c6bc10a95f81 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Shell32/Interop.SHGetKnownFolderPath.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Shell32/Interop.SHGetKnownFolderPath.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.Constants.cs b/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.Constants.cs index f1f09740e90f..2cc835fad951 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.Constants.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.Constants.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal partial class Interop { internal partial class User32 diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.LoadString.cs b/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.LoadString.cs index 078ebd481dd6..d7239a3c4ac0 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.LoadString.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.LoadString.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.SendMessageTimeout.cs b/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.SendMessageTimeout.cs index c8a97e6b9dbf..2c1bcc6c3222 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.SendMessageTimeout.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/User32/Interop.SendMessageTimeout.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleMinusOneIsInvalid.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleMinusOneIsInvalid.cs index a76c51d96660..8576dacc3d0c 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleMinusOneIsInvalid.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleMinusOneIsInvalid.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleZeroOrMinusOneIsInvalid.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleZeroOrMinusOneIsInvalid.cs index 28d021948962..2b61f6248ac0 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleZeroOrMinusOneIsInvalid.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/CriticalHandleZeroOrMinusOneIsInvalid.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs index 3b5347dba3be..ec99cbf17eb3 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.IO; @@ -52,7 +53,7 @@ internal static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, in bool isDirectory = (error.Error == Interop.Error.ENOENT) && ((flags & Interop.Sys.OpenFlags.O_CREAT) != 0 - || !DirectoryExists(Path.GetDirectoryName(PathInternal.TrimEndingDirectorySeparator(path)))); + || !DirectoryExists(Path.GetDirectoryName(PathInternal.TrimEndingDirectorySeparator(path!))!)); Interop.CheckIo( error.Error, diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs index 4eabe8f08c64..db8482ed712c 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Security; using System.Runtime.InteropServices; @@ -39,7 +40,7 @@ internal bool? IsAsync } } - internal ThreadPoolBoundHandle ThreadPoolBinding { get; set; } + internal ThreadPoolBoundHandle? ThreadPoolBinding { get; set; } override protected bool ReleaseHandle() { diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFindHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFindHandle.Windows.cs index 4ba05409fd92..192f523ff162 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFindHandle.Windows.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFindHandle.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Security; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleMinusOneIsInvalid.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleMinusOneIsInvalid.cs index 5415f2c35d31..b146b5a68713 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleMinusOneIsInvalid.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleMinusOneIsInvalid.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleZeroOrMinusOneIsInvalid.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleZeroOrMinusOneIsInvalid.cs index 8d0220bf905e..9a58aa29fed2 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleZeroOrMinusOneIsInvalid.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeHandleZeroOrMinusOneIsInvalid.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs index 3be2e354abf3..dea7978ee8ec 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace Microsoft.Win32.SafeHandles { sealed internal class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs index 249f5e9f7c24..011aaeae662f 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs index 37e350031b83..c3a7fcad885d 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs index 66f17f0af709..e87fedd724a0 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace Microsoft.Win32.SafeHandles { public sealed partial class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs index edb0cdfcafe7..f2e81eacd8c5 100644 --- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs +++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; namespace Microsoft.Win32.SafeHandles diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems index 0ba0bbb8d114..e51a210baea6 100644 --- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems +++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems @@ -233,6 +233,7 @@ + @@ -422,6 +423,7 @@ + @@ -767,6 +769,7 @@ + @@ -798,13 +801,17 @@ - + + + + + @@ -907,8 +914,11 @@ + + + - + @@ -987,6 +997,13 @@ + + + + + + + @@ -999,6 +1016,7 @@ + @@ -1017,6 +1035,9 @@ + + + @@ -1032,6 +1053,7 @@ + @@ -1041,8 +1063,10 @@ + + @@ -1050,7 +1074,6 @@ - @@ -1058,17 +1081,14 @@ + - - - - @@ -1084,6 +1104,7 @@ + @@ -1115,20 +1136,30 @@ - + + + + + + + + + + + diff --git a/src/System.Private.CoreLib/shared/System/Action.cs b/src/System.Private.CoreLib/shared/System/Action.cs index 54ca7aaf5323..4c840379c843 100644 --- a/src/System.Private.CoreLib/shared/System/Action.cs +++ b/src/System.Private.CoreLib/shared/System/Action.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public delegate void Action(); diff --git a/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs b/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs index f328b9c25114..cc4ef6f47137 100644 --- a/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs +++ b/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; using System.Globalization; +using System.Runtime.Loader; using System.Runtime.Remoting; using System.Threading; @@ -11,7 +13,7 @@ namespace System { public static partial class Activator { - public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) + public static object? CreateInstance(Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { if (type is null) throw new ArgumentNullException(nameof(type)); @@ -34,7 +36,7 @@ public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder } [System.Security.DynamicSecurityMethod] - public static ObjectHandle CreateInstance(string assemblyName, string typeName) + public static ObjectHandle? CreateInstance(string assemblyName, string typeName) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return CreateInstanceInternal(assemblyName, @@ -49,7 +51,7 @@ public static ObjectHandle CreateInstance(string assemblyName, string typeName) } [System.Security.DynamicSecurityMethod] - public static ObjectHandle CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) + public static ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return CreateInstanceInternal(assemblyName, @@ -64,7 +66,7 @@ public static ObjectHandle CreateInstance(string assemblyName, string typeName, } [System.Security.DynamicSecurityMethod] - public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttributes) + public static ObjectHandle? CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return CreateInstanceInternal(assemblyName, @@ -78,10 +80,10 @@ public static ObjectHandle CreateInstance(string assemblyName, string typeName, ref stackMark); } - public static object CreateInstance(Type type, bool nonPublic) => + public static object? CreateInstance(Type type, bool nonPublic) => CreateInstance(type, nonPublic, wrapExceptions: true); - internal static object CreateInstance(Type type, bool nonPublic, bool wrapExceptions) + internal static object? CreateInstance(Type type, bool nonPublic, bool wrapExceptions) { if (type is null) throw new ArgumentNullException(nameof(type)); @@ -92,25 +94,25 @@ internal static object CreateInstance(Type type, bool nonPublic, bool wrapExcept throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); } - private static ObjectHandle CreateInstanceInternal(string assemblyString, + private static ObjectHandle? CreateInstanceInternal(string assemblyString, string typeName, bool ignoreCase, BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes, + Binder? binder, + object?[]? args, + CultureInfo? culture, + object?[]? activationAttributes, ref StackCrawlMark stackMark) { - Type type = null; - Assembly assembly = null; + Type? type = null; + Assembly? assembly = null; if (assemblyString == null) { assembly = Assembly.GetExecutingAssembly(ref stackMark); } else { - RuntimeAssembly assemblyFromResolveEvent; + RuntimeAssembly? assemblyFromResolveEvent; AssemblyName assemblyName = RuntimeAssembly.CreateAssemblyName(assemblyString, out assemblyFromResolveEvent); if (assemblyFromResolveEvent != null) { @@ -126,16 +128,16 @@ private static ObjectHandle CreateInstanceInternal(string assemblyString, { // Classic managed type assembly = RuntimeAssembly.InternalLoadAssemblyName( - assemblyName, ref stackMark); + assemblyName, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } } if (type == null) { - type = assembly.GetType(typeName, throwOnError: true, ignoreCase); + type = assembly!.GetType(typeName, throwOnError: true, ignoreCase); } - object o = CreateInstance(type, bindingAttr, binder, args, culture, activationAttributes); + object? o = CreateInstance(type, bindingAttr, binder, args, culture, activationAttributes); return o != null ? new ObjectHandle(o) : null; } diff --git a/src/System.Private.CoreLib/shared/System/Activator.cs b/src/System.Private.CoreLib/shared/System/Activator.cs index 203eb234c648..b4e5ddfeea24 100644 --- a/src/System.Private.CoreLib/shared/System/Activator.cs +++ b/src/System.Private.CoreLib/shared/System/Activator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Globalization; using System.Reflection; @@ -18,36 +19,36 @@ public static partial class Activator [DebuggerHidden] [DebuggerStepThrough] - public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture) => + public static object? CreateInstance(Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture) => CreateInstance(type, bindingAttr, binder, args, culture, null); [DebuggerHidden] [DebuggerStepThrough] - public static object CreateInstance(Type type, params object[] args) => + public static object? CreateInstance(Type type, params object?[]? args) => CreateInstance(type, ConstructorDefault, null, args, null, null); [DebuggerHidden] [DebuggerStepThrough] - public static object CreateInstance(Type type, object[] args, object[] activationAttributes) => + public static object? CreateInstance(Type type, object?[]? args, object?[]? activationAttributes) => CreateInstance(type, ConstructorDefault, null, args, null, activationAttributes); [DebuggerHidden] [DebuggerStepThrough] - public static object CreateInstance(Type type) => + public static object? CreateInstance(Type type) => CreateInstance(type, nonPublic: false); - public static ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName) => + public static ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName) => CreateInstanceFrom(assemblyFile, typeName, false, ConstructorDefault, null, null, null, null); - public static ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, object[] activationAttributes) => + public static ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, object?[]? activationAttributes) => CreateInstanceFrom(assemblyFile, typeName, false, ConstructorDefault, null, null, null, activationAttributes); - public static ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) + public static ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { Assembly assembly = Assembly.LoadFrom(assemblyFile); Type t = assembly.GetType(typeName, true, ignoreCase); - object o = CreateInstance(t, bindingAttr, binder, args, culture, activationAttributes); + object? o = CreateInstance(t, bindingAttr, binder, args, culture, activationAttributes); return o != null ? new ObjectHandle(o) : null; } diff --git a/src/System.Private.CoreLib/shared/System/AppContext.cs b/src/System.Private.CoreLib/shared/System/AppContext.cs index c3994ea351ec..fcda485fa149 100644 --- a/src/System.Private.CoreLib/shared/System/AppContext.cs +++ b/src/System.Private.CoreLib/shared/System/AppContext.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Reflection; using System.Runtime.ExceptionServices; @@ -13,22 +14,22 @@ namespace System { public static partial class AppContext { - private static readonly Dictionary s_dataStore = new Dictionary(); - private static Dictionary s_switches; - private static string s_defaultBaseDirectory; + private static readonly Dictionary s_dataStore = new Dictionary(); + private static Dictionary? s_switches; + private static string? s_defaultBaseDirectory; - public static string BaseDirectory + public static string? BaseDirectory { get { // The value of APP_CONTEXT_BASE_DIRECTORY key has to be a string and it is not allowed to be any other type. // Otherwise the caller will get invalid cast exception - return (string)GetData("APP_CONTEXT_BASE_DIRECTORY") ?? + return (string?)GetData("APP_CONTEXT_BASE_DIRECTORY") ?? (s_defaultBaseDirectory ?? (s_defaultBaseDirectory = GetBaseDirectoryCore())); } } - public static string TargetFrameworkName + public static string? TargetFrameworkName { get { @@ -38,12 +39,12 @@ public static string TargetFrameworkName } } - public static object GetData(string name) + public static object? GetData(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); - object data; + object? data; lock (s_dataStore) { s_dataStore.TryGetValue(name, out data); @@ -51,7 +52,7 @@ public static object GetData(string name) return data; } - public static void SetData(string name, object data) + public static void SetData(string name, object? data) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -126,7 +127,7 @@ public static void SetSwitch(string switchName, bool isEnabled) Interlocked.CompareExchange(ref s_switches, new Dictionary(), null); } - lock (s_switches) + lock (s_switches!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { s_switches[switchName] = isEnabled; } diff --git a/src/System.Private.CoreLib/shared/System/AppDomain.cs b/src/System.Private.CoreLib/shared/System/AppDomain.cs index 707f8278a79f..b1a20551b5e9 100644 --- a/src/System.Private.CoreLib/shared/System/AppDomain.cs +++ b/src/System.Private.CoreLib/shared/System/AppDomain.cs @@ -4,6 +4,7 @@ #pragma warning disable CS0067 // events are declared but not used +#nullable enable using System.Diagnostics; using System.IO; using System.Reflection; @@ -24,18 +25,18 @@ public sealed partial class AppDomain : MarshalByRefObject { private static readonly AppDomain s_domain = new AppDomain(); private readonly object _forLock = new object(); - private IPrincipal _defaultPrincipal; + private IPrincipal? _defaultPrincipal; private PrincipalPolicy _principalPolicy = PrincipalPolicy.NoPrincipal; - private Func s_getWindowsPrincipal; - private Func s_getUnauthenticatedPrincipal; + private Func? s_getWindowsPrincipal; + private Func? s_getUnauthenticatedPrincipal; private AppDomain() { } public static AppDomain CurrentDomain => s_domain; - public string BaseDirectory => AppContext.BaseDirectory; + public string? BaseDirectory => AppContext.BaseDirectory; - public string RelativeSearchPath => null; + public string? RelativeSearchPath => null; public AppDomainSetup SetupInformation => new AppDomainSetup(); @@ -47,17 +48,17 @@ public event UnhandledExceptionEventHandler UnhandledException remove { AppContext.UnhandledException -= value; } } - public string DynamicDirectory => null; + public string? DynamicDirectory => null; [ObsoleteAttribute("AppDomain.SetDynamicBase has been deprecated. Please investigate the use of AppDomainSetup.DynamicBase instead. https://go.microsoft.com/fwlink/?linkid=14202")] - public void SetDynamicBase(string path) { } + public void SetDynamicBase(string? path) { } public string FriendlyName { get { - Assembly assembly = Assembly.GetEntryAssembly(); - return assembly != null ? assembly.GetName().Name : "DefaultDomain"; + Assembly? assembly = Assembly.GetEntryAssembly(); + return assembly != null ? assembly.GetName().Name! : "DefaultDomain"; } } @@ -103,7 +104,7 @@ public static AppDomain CreateDomain(string friendlyName) public int ExecuteAssembly(string assemblyFile) => ExecuteAssembly(assemblyFile, null); - public int ExecuteAssembly(string assemblyFile, string[] args) + public int ExecuteAssembly(string assemblyFile, string?[]? args) { if (assemblyFile == null) { @@ -114,41 +115,41 @@ public int ExecuteAssembly(string assemblyFile, string[] args) return ExecuteAssembly(assembly, args); } - public int ExecuteAssembly(string assemblyFile, string[] args, byte[] hashValue, Configuration.Assemblies.AssemblyHashAlgorithm hashAlgorithm) + public int ExecuteAssembly(string assemblyFile, string?[]? args, byte[]? hashValue, Configuration.Assemblies.AssemblyHashAlgorithm hashAlgorithm) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_CAS); // This api is only meaningful for very specific partial trust/CAS scenarios } - private int ExecuteAssembly(Assembly assembly, string[] args) + private int ExecuteAssembly(Assembly assembly, string?[]? args) { - MethodInfo entry = assembly.EntryPoint; + MethodInfo? entry = assembly.EntryPoint; if (entry == null) { throw new MissingMethodException(SR.Arg_EntryPointNotFoundException); } - object result = entry.Invoke( + object? result = entry.Invoke( obj: null, invokeAttr: BindingFlags.DoNotWrapExceptions, binder: null, - parameters: entry.GetParameters().Length > 0 ? new object[] { args } : null, + parameters: entry.GetParameters().Length > 0 ? new object?[] { args } : null, culture: null); return result != null ? (int)result : 0; } - public int ExecuteAssemblyByName(AssemblyName assemblyName, params string[] args) => + public int ExecuteAssemblyByName(AssemblyName assemblyName, params string?[]? args) => ExecuteAssembly(Assembly.Load(assemblyName), args); public int ExecuteAssemblyByName(string assemblyName) => ExecuteAssemblyByName(assemblyName, null); - public int ExecuteAssemblyByName(string assemblyName, params string[] args) => + public int ExecuteAssemblyByName(string assemblyName, params string?[]? args) => ExecuteAssembly(Assembly.Load(assemblyName), args); - public object GetData(string name) => AppContext.GetData(name); + public object? GetData(string name) => AppContext.GetData(name); - public void SetData(string name, object data) => AppContext.SetData(name, data); + public void SetData(string name, object? data) => AppContext.SetData(name, data); public bool? IsCompatibilitySwitchSet(string value) { @@ -174,7 +175,7 @@ public static void Unload(AppDomain domain) public Assembly Load(byte[] rawAssembly) => Assembly.Load(rawAssembly); - public Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore) => Assembly.Load(rawAssembly, rawSymbolStore); + public Assembly Load(byte[] rawAssembly, byte[]? rawSymbolStore) => Assembly.Load(rawAssembly, rawSymbolStore); public Assembly Load(AssemblyName assemblyRef) => Assembly.Load(assemblyRef); @@ -211,7 +212,7 @@ public static bool MonitoringIsEnabled public bool ShadowCopyFiles => false; [ObsoleteAttribute("AppDomain.AppendPrivatePath has been deprecated. Please investigate the use of AppDomainSetup.PrivateBinPath instead. https://go.microsoft.com/fwlink/?linkid=14202")] - public void AppendPrivatePath(string path) { } + public void AppendPrivatePath(string? path) { } [ObsoleteAttribute("AppDomain.ClearPrivatePath has been deprecated. Please investigate the use of AppDomainSetup.PrivateBinPath instead. https://go.microsoft.com/fwlink/?linkid=14202")] public void ClearPrivatePath() { } @@ -220,13 +221,13 @@ public void ClearPrivatePath() { } public void ClearShadowCopyPath() { } [ObsoleteAttribute("AppDomain.SetCachePath has been deprecated. Please investigate the use of AppDomainSetup.CachePath instead. https://go.microsoft.com/fwlink/?linkid=14202")] - public void SetCachePath(string path) { } + public void SetCachePath(string? path) { } [ObsoleteAttribute("AppDomain.SetShadowCopyFiles has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyFiles instead. https://go.microsoft.com/fwlink/?linkid=14202")] public void SetShadowCopyFiles() { } [ObsoleteAttribute("AppDomain.SetShadowCopyPath has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyDirectories instead. https://go.microsoft.com/fwlink/?linkid=14202")] - public void SetShadowCopyPath(string path) { } + public void SetShadowCopyPath(string? path) { } public Assembly[] GetAssemblies() => AssemblyLoadContext.GetLoadedAssemblies(); @@ -279,7 +280,7 @@ public void SetThreadPrincipal(IPrincipal principal) } } - public ObjectHandle CreateInstance(string assemblyName, string typeName) + public ObjectHandle? CreateInstance(string assemblyName, string typeName) { if (assemblyName == null) { @@ -289,7 +290,7 @@ public ObjectHandle CreateInstance(string assemblyName, string typeName) return Activator.CreateInstance(assemblyName, typeName); } - public ObjectHandle CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) + public ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { if (assemblyName == null) { @@ -306,7 +307,7 @@ public ObjectHandle CreateInstance(string assemblyName, string typeName, bool ig activationAttributes); } - public ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttributes) + public ObjectHandle? CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes) { if (assemblyName == null) { @@ -316,15 +317,15 @@ public ObjectHandle CreateInstance(string assemblyName, string typeName, object[ return Activator.CreateInstance(assemblyName, typeName, activationAttributes); } - public object CreateInstanceAndUnwrap(string assemblyName, string typeName) + public object? CreateInstanceAndUnwrap(string assemblyName, string typeName) { - ObjectHandle oh = CreateInstance(assemblyName, typeName); + ObjectHandle? oh = CreateInstance(assemblyName, typeName); return oh?.Unwrap(); } - public object CreateInstanceAndUnwrap(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) + public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { - ObjectHandle oh = CreateInstance(assemblyName, + ObjectHandle? oh = CreateInstance(assemblyName, typeName, ignoreCase, bindingAttr, @@ -335,18 +336,18 @@ public object CreateInstanceAndUnwrap(string assemblyName, string typeName, bool return oh?.Unwrap(); } - public object CreateInstanceAndUnwrap(string assemblyName, string typeName, object[] activationAttributes) + public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, object?[]? activationAttributes) { - ObjectHandle oh = CreateInstance(assemblyName, typeName, activationAttributes); + ObjectHandle? oh = CreateInstance(assemblyName, typeName, activationAttributes); return oh?.Unwrap(); } - public ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName) + public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName) { return Activator.CreateInstanceFrom(assemblyFile, typeName); } - public ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) + public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { return Activator.CreateInstanceFrom(assemblyFile, typeName, @@ -358,20 +359,20 @@ public ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, boo activationAttributes); } - public ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, object[] activationAttributes) + public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, object?[]? activationAttributes) { return Activator.CreateInstanceFrom(assemblyFile, typeName, activationAttributes); } - public object CreateInstanceFromAndUnwrap(string assemblyFile, string typeName) + public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName) { - ObjectHandle oh = CreateInstanceFrom(assemblyFile, typeName); - return oh?.Unwrap(); + ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName); + return oh?.Unwrap(); } - public object CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) + public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { - ObjectHandle oh = CreateInstanceFrom(assemblyFile, + ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName, ignoreCase, bindingAttr, @@ -382,15 +383,15 @@ public object CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, return oh?.Unwrap(); } - public object CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, object[] activationAttributes) + public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, object?[]? activationAttributes) { - ObjectHandle oh = CreateInstanceFrom(assemblyFile, typeName, activationAttributes); + ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName, activationAttributes); return oh?.Unwrap(); } - public IPrincipal GetThreadPrincipal() + public IPrincipal? GetThreadPrincipal() { - IPrincipal principal = _defaultPrincipal; + IPrincipal? principal = _defaultPrincipal; if (principal == null) { switch (_principalPolicy) @@ -407,7 +408,7 @@ public IPrincipal GetThreadPrincipal() (Func)mi.CreateDelegate(typeof(Func))); } - principal = s_getUnauthenticatedPrincipal(); + principal = s_getUnauthenticatedPrincipal!(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 break; case PrincipalPolicy.WindowsPrincipal: @@ -423,7 +424,7 @@ public IPrincipal GetThreadPrincipal() (Func)mi.CreateDelegate(typeof(Func))); } - principal = s_getWindowsPrincipal(); + principal = s_getWindowsPrincipal!(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 break; } } diff --git a/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs b/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs index c278e7278702..e8d0b9fff4f3 100644 --- a/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs +++ b/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { #if PROJECTN @@ -10,7 +11,7 @@ namespace System public sealed class AppDomainSetup { internal AppDomainSetup() { } - public string ApplicationBase => AppContext.BaseDirectory; - public string TargetFrameworkName => AppContext.TargetFrameworkName; + public string? ApplicationBase => AppContext.BaseDirectory; + public string? TargetFrameworkName => AppContext.TargetFrameworkName; } } diff --git a/src/System.Private.CoreLib/shared/System/Array.Enumerators.cs b/src/System.Private.CoreLib/shared/System/Array.Enumerators.cs index b9974ecfca61..4547af13dda5 100644 --- a/src/System.Private.CoreLib/shared/System/Array.Enumerators.cs +++ b/src/System.Private.CoreLib/shared/System/Array.Enumerators.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -81,7 +82,7 @@ public bool MoveNext() return !_complete; } - public object Current + public object? Current { get { @@ -136,7 +137,7 @@ public bool MoveNext() return false; } - public object Current + public object? Current { get { @@ -199,7 +200,7 @@ public T Current } } - object IEnumerator.Current => Current; + object? IEnumerator.Current => Current; void IEnumerator.Reset() => _index = -1; @@ -207,4 +208,4 @@ public void Dispose() { } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Array.cs b/src/System.Private.CoreLib/shared/System/Array.cs index 2de97dd68908..058f1ca8e214 100644 --- a/src/System.Private.CoreLib/shared/System/Array.cs +++ b/src/System.Private.CoreLib/shared/System/Array.cs @@ -9,6 +9,7 @@ using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; +#nullable enable namespace System { [Serializable] @@ -38,12 +39,12 @@ public static ReadOnlyCollection AsReadOnly(T[] array) return new ReadOnlyCollection(array); } - public static void Resize(ref T[] array, int newSize) + public static void Resize(ref T[]? array, int newSize) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (newSize < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.newSize, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - T[] larray = array; + T[]? larray = array; if (larray == null) { array = new T[newSize]; @@ -64,7 +65,7 @@ public static Array CreateInstance(Type elementType, params long[] lengths) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths); } - if (lengths.Length == 0) + if (lengths!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank); int[] intLengths = new int[lengths.Length]; @@ -106,7 +107,7 @@ public static void Copy(Array sourceArray, long sourceIndex, Array destinationAr Copy(sourceArray, isourceIndex, destinationArray, idestinationIndex, ilength); } - public object GetValue(long index) + public object? GetValue(long index) { int iindex = (int)index; if (index != iindex) @@ -115,7 +116,7 @@ public object GetValue(long index) return this.GetValue(iindex); } - public object GetValue(long index1, long index2) + public object? GetValue(long index1, long index2) { int iindex1 = (int)index1; int iindex2 = (int)index2; @@ -128,7 +129,7 @@ public object GetValue(long index1, long index2) return this.GetValue(iindex1, iindex2); } - public object GetValue(long index1, long index2, long index3) + public object? GetValue(long index1, long index2, long index3) { int iindex1 = (int)index1; int iindex2 = (int)index2; @@ -144,11 +145,11 @@ public object GetValue(long index1, long index2, long index3) return this.GetValue(iindex1, iindex2, iindex3); } - public object GetValue(params long[] indices) + public object? GetValue(params long[] indices) { if (indices == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices); - if (Rank != indices.Length) + if (Rank != indices!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices); int[] intIndices = new int[indices.Length]; @@ -165,7 +166,7 @@ public object GetValue(params long[] indices) return this.GetValue(intIndices); } - public void SetValue(object value, long index) + public void SetValue(object? value, long index) { int iindex = (int)index; @@ -175,7 +176,7 @@ public void SetValue(object value, long index) this.SetValue(value, iindex); } - public void SetValue(object value, long index1, long index2) + public void SetValue(object? value, long index1, long index2) { int iindex1 = (int)index1; int iindex2 = (int)index2; @@ -204,11 +205,11 @@ public void SetValue(object value, long index1, long index2, long index3) this.SetValue(value, iindex1, iindex2, iindex3); } - public void SetValue(object value, params long[] indices) + public void SetValue(object? value, params long[] indices) { if (indices == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices); - if (Rank != indices.Length) + if (Rank != indices!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices); int[] intIndices = new int[indices.Length]; @@ -240,45 +241,36 @@ public long GetLongLength(int dimension) } // Number of elements in the Array. - int ICollection.Count - { get { return Length; } } - + int ICollection.Count { get { return Length; } } // Returns an object appropriate for synchronizing access to this // Array. - public object SyncRoot - { get { return this; } } + public object SyncRoot { get { return this; } } // Is this Array read-only? - public bool IsReadOnly - { get { return false; } } + public bool IsReadOnly { get { return false; } } - public bool IsFixedSize - { - get { return true; } - } + public bool IsFixedSize { get { return true; } } // Is this Array synchronized (i.e., thread-safe)? If you want a synchronized // collection, you can use SyncRoot as an object to synchronize your // collection with. You could also call GetSynchronized() // to get a synchronized wrapper around the Array. - public bool IsSynchronized - { get { return false; } } + public bool IsSynchronized { get { return false; } } - - object IList.this[int index] + object? IList.this[int index] { get { return GetValue(index); } set { SetValue(value, index); } } - int IList.Add(object value) + int IList.Add(object? value) { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection); return default; } - bool IList.Contains(object value) + bool IList.Contains(object? value) { return Array.IndexOf(this, value) >= this.GetLowerBound(0); } @@ -288,17 +280,17 @@ void IList.Clear() Array.Clear(this, this.GetLowerBound(0), this.Length); } - int IList.IndexOf(object value) + int IList.IndexOf(object? value) { return Array.IndexOf(this, value); } - void IList.Insert(int index, object value) + void IList.Insert(int index, object? value) { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection); } - void IList.Remove(object value) + void IList.Remove(object? value) { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection); } @@ -315,14 +307,14 @@ public object Clone() return MemberwiseClone(); } - int IStructuralComparable.CompareTo(object other, IComparer comparer) + int IStructuralComparable.CompareTo(object? other, IComparer comparer) { if (other == null) { return 1; } - Array o = other as Array; + Array? o = other as Array; if (o == null || this.Length != o.Length) { @@ -332,10 +324,10 @@ int IStructuralComparable.CompareTo(object other, IComparer comparer) int i = 0; int c = 0; - while (i < o.Length && c == 0) + while (i < o!.Length && c == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - object left = GetValue(i); - object right = o.GetValue(i); + object? left = GetValue(i); + object? right = o.GetValue(i); c = comparer.Compare(left, right); i++; @@ -344,7 +336,7 @@ int IStructuralComparable.CompareTo(object other, IComparer comparer) return c; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) { @@ -364,8 +356,8 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) int i = 0; while (i < o.Length) { - object left = GetValue(i); - object right = o.GetValue(i); + object? left = GetValue(i); + object? right = o.GetValue(i); if (!comparer.Equals(left, right)) { @@ -391,7 +383,7 @@ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) { - ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i))); + ret = CombineHashCodes(ret, comparer!.GetHashCode(GetValue(i))); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } return ret; @@ -410,11 +402,11 @@ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) // negative result to produce the index of the first element (if any) that // is larger than the given search value. // - public static int BinarySearch(Array array, object value) + public static int BinarySearch(Array array, object? value) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return BinarySearch(array, array.GetLowerBound(0), array.Length, value, null); + return BinarySearch(array!, array!.GetLowerBound(0), array.Length, value, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Searches a section of an array for a given element using a binary search @@ -430,7 +422,7 @@ public static int BinarySearch(Array array, object value) // negative result to produce the index of the first element (if any) that // is larger than the given search value. // - public static int BinarySearch(Array array, int index, int length, object value) + public static int BinarySearch(Array array, int index, int length, object? value) { return BinarySearch(array, index, length, value, null); } @@ -449,11 +441,11 @@ public static int BinarySearch(Array array, int index, int length, object value) // negative result to produce the index of the first element (if any) that // is larger than the given search value. // - public static int BinarySearch(Array array, object value, IComparer comparer) + public static int BinarySearch(Array array, object? value, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return BinarySearch(array, array.GetLowerBound(0), array.Length, value, comparer); + return BinarySearch(array!, array!.GetLowerBound(0), array.Length, value, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Searches a section of an array for a given element using a binary search @@ -471,11 +463,11 @@ public static int BinarySearch(Array array, object value, IComparer comparer) // negative result to produce the index of the first element (if any) that // is larger than the given search value. // - public static int BinarySearch(Array array, int index, int length, object value, IComparer comparer) + public static int BinarySearch(Array array, int index, int length, object? value, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - int lb = array.GetLowerBound(0); + int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 if (index < lb) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) @@ -560,14 +552,14 @@ public static int BinarySearch(T[] array, T value) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return BinarySearch(array, 0, array.Length, value, null); + return BinarySearch(array!, 0, array!.Length, value, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } - public static int BinarySearch(T[] array, T value, System.Collections.Generic.IComparer comparer) + public static int BinarySearch(T[] array, T value, System.Collections.Generic.IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return BinarySearch(array, 0, array.Length, value, comparer); + return BinarySearch(array!, 0, array!.Length, value, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int BinarySearch(T[] array, int index, int length, T value) @@ -575,7 +567,7 @@ public static int BinarySearch(T[] array, int index, int length, T value) return BinarySearch(array, index, length, value, null); } - public static int BinarySearch(T[] array, int index, int length, T value, System.Collections.Generic.IComparer comparer) + public static int BinarySearch(T[] array, int index, int length, T value, System.Collections.Generic.IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -584,7 +576,7 @@ public static int BinarySearch(T[] array, int index, int length, T value, Sys if (length < 0) ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); - if (array.Length - index < length) + if (array!.Length - index < length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); return ArraySortHelper.Default.BinarySearch(array, index, length, value, comparer); @@ -602,10 +594,10 @@ public static TOutput[] ConvertAll(TInput[] array, Converter(T[] array, T value) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - for (int i = 0; i < array.Length; i++) + for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { array[i] = value; } @@ -669,19 +661,19 @@ public static void Fill(T[] array, T value, int startIndex, int count) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - if (startIndex < 0 || startIndex > array.Length) + if (startIndex < 0 || startIndex > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } - if (count < 0 || startIndex > array.Length - count) + if (count < 0 || startIndex > array!.Length - count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } for (int i = startIndex; i < startIndex + count; i++) { - array[i] = value; + array![i] = value; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } } @@ -697,14 +689,14 @@ public static T Find(T[] array, Predicate match) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } - for (int i = 0; i < array.Length; i++) + for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - if (match(array[i])) + if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { return array[i]; } } - return default; + return default!; // TODO-NULLABLE-GENERIC } public static T[] FindAll(T[] array, Predicate match) @@ -720,9 +712,9 @@ public static T[] FindAll(T[] array, Predicate match) } List list = new List(); - for (int i = 0; i < array.Length; i++) + for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - if (match(array[i])) + if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { list.Add(array[i]); } @@ -737,7 +729,7 @@ public static int FindIndex(T[] array, Predicate match) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return FindIndex(array, 0, array.Length, match); + return FindIndex(array!, 0, array!.Length, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int FindIndex(T[] array, int startIndex, Predicate match) @@ -747,7 +739,7 @@ public static int FindIndex(T[] array, int startIndex, Predicate match) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return FindIndex(array, startIndex, array.Length - startIndex, match); + return FindIndex(array!, startIndex, array!.Length - startIndex, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int FindIndex(T[] array, int startIndex, int count, Predicate match) @@ -757,12 +749,12 @@ public static int FindIndex(T[] array, int startIndex, int count, Predicate array.Length) + if (startIndex < 0 || startIndex > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } - if (count < 0 || startIndex > array.Length - count) + if (count < 0 || startIndex > array!.Length - count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } @@ -775,7 +767,7 @@ public static int FindIndex(T[] array, int startIndex, int count, Predicate(T[] array, Predicate match) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } - for (int i = array.Length - 1; i >= 0; i--) + for (int i = array!.Length - 1; i >= 0; i--) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - if (match(array[i])) + if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { return array[i]; } } - return default; + return default!; // TODO-NULLABLE-GENERIC } public static int FindLastIndex(T[] array, Predicate match) @@ -810,7 +802,7 @@ public static int FindLastIndex(T[] array, Predicate match) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return FindLastIndex(array, array.Length - 1, array.Length, match); + return FindLastIndex(array!, array!.Length - 1, array.Length, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int FindLastIndex(T[] array, int startIndex, Predicate match) @@ -820,7 +812,7 @@ public static int FindLastIndex(T[] array, int startIndex, Predicate match ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return FindLastIndex(array, startIndex, startIndex + 1, match); + return FindLastIndex(array!, startIndex, startIndex + 1, match); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int FindLastIndex(T[] array, int startIndex, int count, Predicate match) @@ -835,7 +827,7 @@ public static int FindLastIndex(T[] array, int startIndex, int count, Predica ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } - if (array.Length == 0) + if (array!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { // Special case for 0 length List if (startIndex != -1) @@ -861,7 +853,7 @@ public static int FindLastIndex(T[] array, int startIndex, int count, Predica int endIndex = startIndex - count; for (int i = startIndex; i > endIndex; i--) { - if (match(array[i])) + if (match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { return i; } @@ -881,9 +873,9 @@ public static void ForEach(T[] array, Action action) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action); } - for (int i = 0; i < array.Length; i++) + for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - action(array[i]); + action!(array[i]); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } } @@ -891,11 +883,11 @@ public static void ForEach(T[] array, Action action) // The array is searched forwards, and the elements of the array are // compared to the given value using the Object.Equals method. // - public static int IndexOf(Array array, object value) + public static int IndexOf(Array array, object? value) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return IndexOf(array, value, array.GetLowerBound(0), array.Length); + return IndexOf(array!, value, array!.GetLowerBound(0), array.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Returns the index of the first occurrence of a given value in a range of @@ -904,11 +896,11 @@ public static int IndexOf(Array array, object value) // elements of the array are compared to the given value using the // Object.Equals method. // - public static int IndexOf(Array array, object value, int startIndex) + public static int IndexOf(Array array, object? value, int startIndex) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - int lb = array.GetLowerBound(0); + int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 return IndexOf(array, value, startIndex, array.Length - startIndex + lb); } @@ -918,11 +910,11 @@ public static int IndexOf(Array array, object value, int startIndex) // elements of the array are compared to the given value using the // Object.Equals method. // - public static int IndexOf(Array array, object value, int startIndex, int count) + public static int IndexOf(Array array, object? value, int startIndex, int count) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - if (array.Rank != 1) + if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported); int lb = array.GetLowerBound(0); @@ -939,7 +931,7 @@ public static int IndexOf(Array array, object value, int startIndex, int count) return retVal; #endif - object[] objArray = array as object[]; + object[]? objArray = array as object[]; int endIndex = startIndex + count; if (objArray != null) { @@ -965,7 +957,7 @@ public static int IndexOf(Array array, object value, int startIndex, int count) { for (int i = startIndex; i < endIndex; i++) { - object obj = array.GetValue(i); + object? obj = array.GetValue(i); if (obj == null) { if (value == null) @@ -992,7 +984,7 @@ public static int IndexOf(T[] array, T value) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return IndexOf(array, value, 0, array.Length); + return IndexOf(array!, value, 0, array!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int IndexOf(T[] array, T value, int startIndex) @@ -1002,7 +994,7 @@ public static int IndexOf(T[] array, T value, int startIndex) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return IndexOf(array, value, startIndex, array.Length - startIndex); + return IndexOf(array!, value, startIndex, array!.Length - startIndex); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int IndexOf(T[] array, T value, int startIndex, int count) @@ -1012,7 +1004,7 @@ public static int IndexOf(T[] array, T value, int startIndex, int count) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - if ((uint)startIndex > (uint)array.Length) + if ((uint)startIndex > (uint)array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } @@ -1056,11 +1048,11 @@ ref Unsafe.Add(ref Unsafe.As(ref array.GetRawSzArrayData()), startIn // The array is searched backwards, and the elements of the array are // compared to the given value using the Object.Equals method. // - public static int LastIndexOf(Array array, object value) + public static int LastIndexOf(Array array, object? value) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - int lb = array.GetLowerBound(0); + int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 return LastIndexOf(array, value, array.Length - 1 + lb, array.Length); } @@ -1069,11 +1061,11 @@ public static int LastIndexOf(Array array, object value) // startIndex and ending at index 0. The elements of the array are // compared to the given value using the Object.Equals method. // - public static int LastIndexOf(Array array, object value, int startIndex) + public static int LastIndexOf(Array array, object? value, int startIndex) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - int lb = array.GetLowerBound(0); + int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 return LastIndexOf(array, value, startIndex, startIndex + 1 - lb); } @@ -1083,11 +1075,11 @@ public static int LastIndexOf(Array array, object value, int startIndex) // the array are compared to the given value using the Object.Equals // method. // - public static int LastIndexOf(Array array, object value, int startIndex, int count) + public static int LastIndexOf(Array array, object? value, int startIndex, int count) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - int lb = array.GetLowerBound(0); + int lb = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 if (array.Length == 0) { return lb - 1; @@ -1110,7 +1102,7 @@ public static int LastIndexOf(Array array, object value, int startIndex, int cou return retVal; #endif - object[] objArray = array as object[]; + object[]? objArray = array as object[]; int endIndex = startIndex - count + 1; if (objArray != null) { @@ -1136,7 +1128,7 @@ public static int LastIndexOf(Array array, object value, int startIndex, int cou { for (int i = startIndex; i >= endIndex; i--) { - object obj = array.GetValue(i); + object? obj = array.GetValue(i); if (obj == null) { if (value == null) @@ -1159,7 +1151,7 @@ public static int LastIndexOf(T[] array, T value) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - return LastIndexOf(array, value, array.Length - 1, array.Length); + return LastIndexOf(array!, value, array!.Length - 1, array.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int LastIndexOf(T[] array, T value, int startIndex) @@ -1169,7 +1161,7 @@ public static int LastIndexOf(T[] array, T value, int startIndex) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } // if array is empty and startIndex is 0, we need to pass 0 as count - return LastIndexOf(array, value, startIndex, (array.Length == 0) ? 0 : (startIndex + 1)); + return LastIndexOf(array!, value, startIndex, (array!.Length == 0) ? 0 : (startIndex + 1)); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static int LastIndexOf(T[] array, T value, int startIndex, int count) @@ -1179,7 +1171,7 @@ public static int LastIndexOf(T[] array, T value, int startIndex, int count) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - if (array.Length == 0) + if (array!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { // // Special case for 0 length List @@ -1251,7 +1243,7 @@ public static void Reverse(Array array) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Reverse(array, array.GetLowerBound(0), array.Length); + Reverse(array!, array!.GetLowerBound(0), array.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Reverses the elements in a range of an array. Following a call to this @@ -1264,7 +1256,7 @@ public static void Reverse(Array array, int index, int length) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - int lowerBound = array.GetLowerBound(0); + int lowerBound = array!.GetLowerBound(0); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 if (index < lowerBound) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) @@ -1294,7 +1286,7 @@ public static void Reverse(Array array, int index, int length) int j = index + length - 1; while (i < j) { - object temp = array.GetValue(i); + object? temp = array.GetValue(i); array.SetValue(array.GetValue(j), i); array.SetValue(temp, j); i++; @@ -1307,7 +1299,7 @@ public static void Reverse(T[] array) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Reverse(array, 0, array.Length); + Reverse(array!, 0, array!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static void Reverse(T[] array, int index, int length) @@ -1318,7 +1310,7 @@ public static void Reverse(T[] array, int index, int length) ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); - if (array.Length - index < length) + if (array!.Length - index < length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); if (length <= 1) @@ -1344,7 +1336,7 @@ public static void Sort(Array array) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Sort(array, null, array.GetLowerBound(0), array.Length, null); + Sort(array!, null, array!.GetLowerBound(0), array.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Sorts the elements of two arrays based on the keys in the first array. @@ -1353,11 +1345,11 @@ public static void Sort(Array array) // keys to each other using the IComparable interface, which must be // implemented by all elements of the keys array. // - public static void Sort(Array keys, Array items) + public static void Sort(Array keys, Array? items) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - Sort(keys, items, keys.GetLowerBound(0), keys.Length, null); + Sort(keys!, items, keys!.GetLowerBound(0), keys.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Sorts the elements in a section of an array. The sort compares the @@ -1375,7 +1367,7 @@ public static void Sort(Array array, int index, int length) // keys to each other using the IComparable interface, which must be // implemented by all elements of the keys array. // - public static void Sort(Array keys, Array items, int index, int length) + public static void Sort(Array keys, Array? items, int index, int length) { Sort(keys, items, index, length, null); } @@ -1386,11 +1378,11 @@ public static void Sort(Array keys, Array items, int index, int length) // IComparable interface, which in that case must be implemented by // all elements of the array. // - public static void Sort(Array array, IComparer comparer) + public static void Sort(Array array, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Sort(array, null, array.GetLowerBound(0), array.Length, comparer); + Sort(array!, null, array!.GetLowerBound(0), array.Length, comparer); } // Sorts the elements of two arrays based on the keys in the first array. @@ -1401,11 +1393,11 @@ public static void Sort(Array array, IComparer comparer) // the IComparable interface, which in that case must be implemented // by all elements of the keys array. // - public static void Sort(Array keys, Array items, IComparer comparer) + public static void Sort(Array keys, Array? items, IComparer? comparer) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - Sort(keys, items, keys.GetLowerBound(0), keys.Length, comparer); + Sort(keys!, items, keys!.GetLowerBound(0), keys.Length, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Sorts the elements in a section of an array. The sort compares the @@ -1414,7 +1406,7 @@ public static void Sort(Array keys, Array items, IComparer comparer) // the IComparable interface, which in that case must be implemented // by all elements in the given section of the array. // - public static void Sort(Array array, int index, int length, IComparer comparer) + public static void Sort(Array array, int index, int length, IComparer? comparer) { Sort(array, null, index, length, comparer); } @@ -1427,11 +1419,11 @@ public static void Sort(Array array, int index, int length, IComparer comparer) // the IComparable interface, which in that case must be implemented // by all elements of the given section of the keys array. // - public static void Sort(Array keys, Array items, int index, int length, IComparer comparer) + public static void Sort(Array keys, Array? items, int index, int length, IComparer? comparer) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - if (keys.Rank != 1 || (items != null && items.Rank != 1)) + if (keys!.Rank != 1 || (items != null && items.Rank != 1)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported); int keysLowerBound = keys.GetLowerBound(0); if (items != null && keysLowerBound != items.GetLowerBound(0)) @@ -1444,7 +1436,6 @@ public static void Sort(Array keys, Array items, int index, int length, ICompare if (keys.Length - (index - keysLowerBound) < length || (items != null && (index - keysLowerBound) > items.Length - length)) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); - if (length > 1) { SortImpl(keys, items, index, length, comparer ?? Comparer.Default); @@ -1455,14 +1446,14 @@ public static void Sort(T[] array) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Sort(array, 0, array.Length, null); + Sort(array!, 0, array!.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } - public static void Sort(TKey[] keys, TValue[] items) + public static void Sort(TKey[] keys, TValue[]? items) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - Sort(keys, items, 0, keys.Length, null); + Sort(keys!, items, 0, keys!.Length, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static void Sort(T[] array, int index, int length) @@ -1470,26 +1461,26 @@ public static void Sort(T[] array, int index, int length) Sort(array, index, length, null); } - public static void Sort(TKey[] keys, TValue[] items, int index, int length) + public static void Sort(TKey[] keys, TValue[]? items, int index, int length) { Sort(keys, items, index, length, null); } - public static void Sort(T[] array, System.Collections.Generic.IComparer comparer) + public static void Sort(T[] array, System.Collections.Generic.IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Sort(array, 0, array.Length, comparer); + Sort(array!, 0, array!.Length, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } - public static void Sort(TKey[] keys, TValue[] items, System.Collections.Generic.IComparer comparer) + public static void Sort(TKey[] keys, TValue[]? items, System.Collections.Generic.IComparer? comparer) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - Sort(keys, items, 0, keys.Length, comparer); + Sort(keys!, items, 0, keys!.Length, comparer); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } - public static void Sort(T[] array, int index, int length, System.Collections.Generic.IComparer comparer) + public static void Sort(T[] array, int index, int length, System.Collections.Generic.IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1497,7 +1488,7 @@ public static void Sort(T[] array, int index, int length, System.Collections. ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); - if (array.Length - index < length) + if (array!.Length - index < length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); if (length > 1) @@ -1516,7 +1507,7 @@ public static void Sort(T[] array, int index, int length, System.Collections. } } - public static void Sort(TKey[] keys, TValue[] items, int index, int length, System.Collections.Generic.IComparer comparer) + public static void Sort(TKey[] keys, TValue[]? items, int index, int length, System.Collections.Generic.IComparer? comparer) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -1524,7 +1515,7 @@ public static void Sort(TKey[] keys, TValue[] items, int index, in ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (length < 0) ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); - if (keys.Length - index < length || (items != null && index > items.Length - length)) + if (keys!.Length - index < length || (items != null && index > items.Length - length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); if (length > 1) @@ -1561,7 +1552,7 @@ public static void Sort(T[] array, Comparison comparison) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); } - ArraySortHelper.Sort(array, 0, array.Length, comparison); + ArraySortHelper.Sort(array!, 0, array!.Length, comparison); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static bool TrueForAll(T[] array, Predicate match) @@ -1576,9 +1567,9 @@ public static bool TrueForAll(T[] array, Predicate match) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } - for (int i = 0; i < array.Length; i++) + for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - if (!match(array[i])) + if (!match!(array[i])) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { return false; } @@ -1591,10 +1582,10 @@ public static bool TrueForAll(T[] array, Predicate match) private readonly struct SorterObjectArray { private readonly object[] keys; - private readonly object[] items; + private readonly object?[]? items; private readonly IComparer comparer; - internal SorterObjectArray(object[] keys, object[] items, IComparer comparer) + internal SorterObjectArray(object[] keys, object?[]? items, IComparer comparer) { this.keys = keys; this.items = items; @@ -1612,7 +1603,7 @@ internal void SwapIfGreaterWithItems(int a, int b) keys[b] = temp; if (items != null) { - object item = items[a]; + object? item = items[a]; items[a] = items[b]; items[b] = item; } @@ -1628,7 +1619,7 @@ private void Swap(int i, int j) if (items != null) { - object item = items[i]; + object? item = items[i]; items[i] = items[j]; items[j] = item; } @@ -1746,7 +1737,7 @@ private void Heapsort(int lo, int hi) private void DownHeap(int i, int n, int lo) { object d = keys[lo + i - 1]; - object dt = (items != null) ? items[lo + i - 1] : null; + object? dt = (items != null) ? items[lo + i - 1] : null; int child; while (i <= n / 2) { @@ -1770,7 +1761,8 @@ private void DownHeap(int i, int n, int lo) private void InsertionSort(int lo, int hi) { int i, j; - object t, ti; + object t; + object? ti; for (i = lo; i < hi; i++) { j = i; @@ -1796,10 +1788,10 @@ private void InsertionSort(int lo, int hi) private readonly struct SorterGenericArray { private readonly Array keys; - private readonly Array items; + private readonly Array? items; private readonly IComparer comparer; - internal SorterGenericArray(Array keys, Array items, IComparer comparer) + internal SorterGenericArray(Array keys, Array? items, IComparer comparer) { this.keys = keys; this.items = items; @@ -1812,12 +1804,12 @@ internal void SwapIfGreaterWithItems(int a, int b) { if (comparer.Compare(keys.GetValue(a), keys.GetValue(b)) > 0) { - object key = keys.GetValue(a); + object? key = keys.GetValue(a); keys.SetValue(keys.GetValue(b), a); keys.SetValue(key, b); if (items != null) { - object item = items.GetValue(a); + object? item = items.GetValue(a); items.SetValue(items.GetValue(b), a); items.SetValue(item, b); } @@ -1827,13 +1819,13 @@ internal void SwapIfGreaterWithItems(int a, int b) private void Swap(int i, int j) { - object t1 = keys.GetValue(i); + object? t1 = keys.GetValue(i); keys.SetValue(keys.GetValue(j), i); keys.SetValue(t1, j); if (items != null) { - object t2 = items.GetValue(i); + object? t2 = items.GetValue(i); items.SetValue(items.GetValue(j), i); items.SetValue(t2, j); } @@ -1913,7 +1905,7 @@ private int PickPivotAndPartition(int lo, int hi) SwapIfGreaterWithItems(lo, hi); SwapIfGreaterWithItems(mid, hi); - object pivot = keys.GetValue(mid); + object? pivot = keys.GetValue(mid); Swap(mid, hi - 1); int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below. @@ -1950,8 +1942,8 @@ private void Heapsort(int lo, int hi) private void DownHeap(int i, int n, int lo) { - object d = keys.GetValue(lo + i - 1); - object dt = (items != null) ? items.GetValue(lo + i - 1) : null; + object? d = keys.GetValue(lo + i - 1); + object? dt = (items != null) ? items.GetValue(lo + i - 1) : null; int child; while (i <= n / 2) { @@ -1977,7 +1969,8 @@ private void DownHeap(int i, int n, int lo) private void InsertionSort(int lo, int hi) { int i, j; - object t, dt; + object? t; + object? dt; for (i = lo; i < hi; i++) { j = i; diff --git a/src/System.Private.CoreLib/shared/System/ArraySegment.cs b/src/System.Private.CoreLib/shared/System/ArraySegment.cs index b2bd41780614..58eb506f67d6 100644 --- a/src/System.Private.CoreLib/shared/System/ArraySegment.cs +++ b/src/System.Private.CoreLib/shared/System/ArraySegment.cs @@ -13,6 +13,7 @@ ** ===========================================================*/ +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -32,7 +33,7 @@ namespace System // instantiating another generic type in addition to ArraySegment for new type parameters. public static ArraySegment Empty { get; } = new ArraySegment(new T[0]); - private readonly T[] _array; // Do not rename (binary serialization) + private readonly T[]? _array; // Do not rename (binary serialization) private readonly int _offset; // Do not rename (binary serialization) private readonly int _count; // Do not rename (binary serialization) @@ -43,7 +44,7 @@ public ArraySegment(T[] array) _array = array; _offset = 0; - _count = array.Length; + _count = array!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public ArraySegment(T[] array, int offset, int count) @@ -59,7 +60,7 @@ public ArraySegment(T[] array, int offset, int count) _count = count; } - public T[] Array => _array; + public T[]? Array => _array; public int Offset => _offset; @@ -74,7 +75,7 @@ public T this[int index] ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } - return _array[_offset + index]; + return _array![_offset + index]; } set { @@ -83,7 +84,7 @@ public T this[int index] ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } - _array[_offset + index] = value; + _array![_offset + index] = value; } } @@ -115,7 +116,7 @@ public override int GetHashCode() public void CopyTo(T[] destination, int destinationIndex) { ThrowInvalidOperationIfDefault(); - System.Array.Copy(_array, _offset, destination, destinationIndex, _count); + System.Array.Copy(_array!, _offset, destination, destinationIndex, _count); } public void CopyTo(ArraySegment destination) @@ -128,10 +129,10 @@ public void CopyTo(ArraySegment destination) ThrowHelper.ThrowArgumentException_DestinationTooShort(); } - System.Array.Copy(_array, _offset, destination._array, destination._offset, _count); + System.Array.Copy(_array!, _offset, destination._array!, destination._offset, _count); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is ArraySegment) return Equals((ArraySegment)obj); @@ -153,7 +154,7 @@ public ArraySegment Slice(int index) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } - return new ArraySegment(_array, _offset + index, _count - index); + return new ArraySegment(_array!, _offset + index, _count - index); } public ArraySegment Slice(int index, int count) @@ -165,7 +166,7 @@ public ArraySegment Slice(int index, int count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } - return new ArraySegment(_array, _offset + index, count); + return new ArraySegment(_array!, _offset + index, count); } public T[] ToArray() @@ -174,11 +175,11 @@ public T[] ToArray() if (_count == 0) { - return Empty._array; + return Empty._array!; } var array = new T[_count]; - System.Array.Copy(_array, _offset, array, 0, _count); + System.Array.Copy(_array!, _offset, array, 0, _count); return array; } @@ -203,7 +204,7 @@ T IList.this[int index] if (index < 0 || index >= _count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); - return _array[_offset + index]; + return _array![_offset + index]; } set @@ -212,7 +213,7 @@ T IList.this[int index] if (index < 0 || index >= _count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); - _array[_offset + index] = value; + _array![_offset + index] = value; } } @@ -220,7 +221,7 @@ int IList.IndexOf(T item) { ThrowInvalidOperationIfDefault(); - int index = System.Array.IndexOf(_array, item, _offset, _count); + int index = System.Array.IndexOf(_array!, item, _offset, _count); Debug.Assert(index == -1 || (index >= _offset && index < _offset + _count)); @@ -248,7 +249,7 @@ T IReadOnlyList.this[int index] if (index < 0 || index >= _count) ThrowHelper.ThrowArgumentOutOfRange_IndexException(); - return _array[_offset + index]; + return _array![_offset + index]; } } #endregion IReadOnlyList @@ -278,7 +279,7 @@ bool ICollection.Contains(T item) { ThrowInvalidOperationIfDefault(); - int index = System.Array.IndexOf(_array, item, _offset, _count); + int index = System.Array.IndexOf(_array!, item, _offset, _count); Debug.Assert(index == -1 || (index >= _offset && index < _offset + _count)); @@ -313,7 +314,7 @@ private void ThrowInvalidOperationIfDefault() public struct Enumerator : IEnumerator { - private readonly T[] _array; + private readonly T[]? _array; private readonly int _start; private readonly int _end; // cache Offset + Count, since it's a little slow private int _current; @@ -323,7 +324,7 @@ internal Enumerator(ArraySegment arraySegment) Debug.Assert(arraySegment.Array != null); Debug.Assert(arraySegment.Offset >= 0); Debug.Assert(arraySegment.Count >= 0); - Debug.Assert(arraySegment.Offset + arraySegment.Count <= arraySegment.Array.Length); + Debug.Assert(arraySegment.Offset + arraySegment.Count <= arraySegment.Array!.Length); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34792 _array = arraySegment.Array; _start = arraySegment.Offset; @@ -349,11 +350,11 @@ public T Current ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); if (_current >= _end) ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); - return _array[_current]; + return _array![_current]; } } - object IEnumerator.Current => Current; + object? IEnumerator.Current => Current; void IEnumerator.Reset() { diff --git a/src/System.Private.CoreLib/shared/System/AssemblyLoadEventArgs.cs b/src/System.Private.CoreLib/shared/System/AssemblyLoadEventArgs.cs index d7e524969330..43b32d74cfd5 100644 --- a/src/System.Private.CoreLib/shared/System/AssemblyLoadEventArgs.cs +++ b/src/System.Private.CoreLib/shared/System/AssemblyLoadEventArgs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; namespace System diff --git a/src/System.Private.CoreLib/shared/System/AssemblyLoadEventHandler.cs b/src/System.Private.CoreLib/shared/System/AssemblyLoadEventHandler.cs index 752379fdc780..af89e634b33a 100644 --- a/src/System.Private.CoreLib/shared/System/AssemblyLoadEventHandler.cs +++ b/src/System.Private.CoreLib/shared/System/AssemblyLoadEventHandler.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { - public delegate void AssemblyLoadEventHandler(object sender, AssemblyLoadEventArgs args); + public delegate void AssemblyLoadEventHandler(object? sender, AssemblyLoadEventArgs args); } diff --git a/src/System.Private.CoreLib/shared/System/AsyncCallback.cs b/src/System.Private.CoreLib/shared/System/AsyncCallback.cs index 036d44a4b97d..f06749f60b21 100644 --- a/src/System.Private.CoreLib/shared/System/AsyncCallback.cs +++ b/src/System.Private.CoreLib/shared/System/AsyncCallback.cs @@ -10,6 +10,7 @@ ** ===========================================================*/ +#nullable enable namespace System { public delegate void AsyncCallback(IAsyncResult ar); diff --git a/src/System.Private.CoreLib/shared/System/AttributeTargets.cs b/src/System.Private.CoreLib/shared/System/AttributeTargets.cs index c33d19e85ea3..dbbade3a600e 100644 --- a/src/System.Private.CoreLib/shared/System/AttributeTargets.cs +++ b/src/System.Private.CoreLib/shared/System/AttributeTargets.cs @@ -5,6 +5,7 @@ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// +#nullable enable namespace System { // Enum used to indicate all the elements of the diff --git a/src/System.Private.CoreLib/shared/System/AttributeUsageAttribute.cs b/src/System.Private.CoreLib/shared/System/AttributeUsageAttribute.cs index 8a4a0a661bf6..d96e4057cc36 100644 --- a/src/System.Private.CoreLib/shared/System/AttributeUsageAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/AttributeUsageAttribute.cs @@ -11,6 +11,7 @@ ** ===========================================================*/ +#nullable enable using System.Reflection; namespace System diff --git a/src/System.Private.CoreLib/shared/System/BitConverter.cs b/src/System.Private.CoreLib/shared/System/BitConverter.cs index eedd5afab1e5..196725ecebdb 100644 --- a/src/System.Private.CoreLib/shared/System/BitConverter.cs +++ b/src/System.Private.CoreLib/shared/System/BitConverter.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -237,7 +237,7 @@ public static short ToInt16(byte[] value, int startIndex) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); - if (unchecked((uint)startIndex) >= unchecked((uint)value.Length)) + if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); if (startIndex > value.Length - sizeof(short)) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value); @@ -258,7 +258,7 @@ public static int ToInt32(byte[] value, int startIndex) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); - if (unchecked((uint)startIndex) >= unchecked((uint)value.Length)) + if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); if (startIndex > value.Length - sizeof(int)) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value); @@ -279,7 +279,7 @@ public static long ToInt64(byte[] value, int startIndex) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); - if (unchecked((uint)startIndex) >= unchecked((uint)value.Length)) + if (unchecked((uint)startIndex) >= unchecked((uint)value!.Length)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); if (startIndex > value.Length - sizeof(long)) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value); @@ -364,11 +364,11 @@ public static string ToString(byte[] value, int startIndex, int length) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); - if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) + if (startIndex < 0 || startIndex >= value!.Length && startIndex > 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); if (length < 0) throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_GenericPositive); - if (startIndex > value.Length - length) + if (startIndex > value!.Length - length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value); if (length == 0) @@ -410,7 +410,7 @@ public static string ToString(byte[] value) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); - return ToString(value, 0, value.Length); + return ToString(value!, 0, value!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Converts an array of bytes into a String. @@ -418,7 +418,7 @@ public static string ToString(byte[] value, int startIndex) { if (value == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); - return ToString(value, startIndex, value.Length - startIndex); + return ToString(value!, startIndex, value!.Length - startIndex); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } /*==================================ToBoolean=================================== @@ -436,7 +436,7 @@ public static bool ToBoolean(byte[] value, int startIndex) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); if (startIndex < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); - if (startIndex > value.Length - 1) + if (startIndex > value!.Length - 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); // differs from other overloads, which throw base ArgumentException return value[startIndex] != 0; diff --git a/src/System.Private.CoreLib/shared/System/Buffer.Unix.cs b/src/System.Private.CoreLib/shared/System/Buffer.Unix.cs index fee3ccb9fe21..7de47fd6a21c 100644 --- a/src/System.Private.CoreLib/shared/System/Buffer.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Buffer.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if BIT64 using nuint = System.UInt64; #else @@ -23,4 +24,4 @@ public static partial class Buffer private const nuint MemmoveNativeThreshold = 2048; #endif } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Buffer.Windows.cs b/src/System.Private.CoreLib/shared/System/Buffer.Windows.cs index 4de884d68db9..2609e90ad997 100644 --- a/src/System.Private.CoreLib/shared/System/Buffer.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Buffer.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if BIT64 using nuint = System.UInt64; #else @@ -20,4 +21,4 @@ public static partial class Buffer private const nuint MemmoveNativeThreshold = 2048; #endif } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Buffer.cs b/src/System.Private.CoreLib/shared/System/Buffer.cs index f2ffaaea85dc..da62bc50b47b 100644 --- a/src/System.Private.CoreLib/shared/System/Buffer.cs +++ b/src/System.Private.CoreLib/shared/System/Buffer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if AMD64 || ARM64 || (BIT32 && !ARM) #define HAS_CUSTOM_BLOCKS #endif diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs b/src/System.Private.CoreLib/shared/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs index fdf79985ee12..4df370337d0a 100644 --- a/src/System.Private.CoreLib/shared/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs +++ b/src/System.Private.CoreLib/shared/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs @@ -83,12 +83,6 @@ private static bool TryParseDateTimeOffsetDefault(ReadOnlySpan source, out offsetMinutes = (int)(digit1 * 10 + digit2); } - TimeSpan offset = new TimeSpan(hours: offsetHours, minutes: offsetMinutes, seconds: 0); - if (sign == Utf8Constants.Minus) - { - offset = -offset; - } - if (!TryCreateDateTimeOffset(dateTime: dateTime, offsetNegative: sign == Utf8Constants.Minus, offsetHours: offsetHours, offsetMinutes: offsetMinutes, out value)) { bytesConsumed = 0; diff --git a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs index 5c5fd994edc0..59e109a0431c 100644 --- a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs +++ b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -301,12 +301,12 @@ private static MemoryPressure GetMemoryPressure() const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high" const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium" - GC.GetMemoryInfo(out uint threshold, out _, out uint lastLoad, out _, out _); - if (lastLoad >= threshold * HighPressureThreshold) + GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo(); + if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * HighPressureThreshold) { return MemoryPressure.High; } - else if (lastLoad >= threshold * MediumPressureThreshold) + else if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * MediumPressureThreshold) { return MemoryPressure.Medium; } diff --git a/src/System.Private.CoreLib/shared/System/ByReference.cs b/src/System.Private.CoreLib/shared/System/ByReference.cs index 5da3c99f41b1..bb75753f5be4 100644 --- a/src/System.Private.CoreLib/shared/System/ByReference.cs +++ b/src/System.Private.CoreLib/shared/System/ByReference.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.Versioning; diff --git a/src/System.Private.CoreLib/shared/System/CLSCompliantAttribute.cs b/src/System.Private.CoreLib/shared/System/CLSCompliantAttribute.cs index d895b5ac7166..9790e935f34e 100644 --- a/src/System.Private.CoreLib/shared/System/CLSCompliantAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/CLSCompliantAttribute.cs @@ -11,6 +11,7 @@ ** =============================================================================*/ +#nullable enable namespace System { [AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/CharEnumerator.cs b/src/System.Private.CoreLib/shared/System/CharEnumerator.cs index ca60705d9912..0b2caefdfa32 100644 --- a/src/System.Private.CoreLib/shared/System/CharEnumerator.cs +++ b/src/System.Private.CoreLib/shared/System/CharEnumerator.cs @@ -12,6 +12,7 @@ ** ============================================================*/ +#nullable enable using System.Collections; using System.Collections.Generic; @@ -19,7 +20,7 @@ namespace System { public sealed class CharEnumerator : IEnumerator, IEnumerator, IDisposable, ICloneable { - private string _str; + private string? _str; private int _index; private char _currentElement; @@ -36,7 +37,7 @@ public object Clone() public bool MoveNext() { - if (_index < (_str.Length - 1)) + if (_index < (_str!.Length - 1)) { _index++; _currentElement = _str[_index]; @@ -54,7 +55,7 @@ public void Dispose() _str = null; } - object IEnumerator.Current + object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { get { return Current; } } @@ -65,7 +66,7 @@ public char Current { if (_index == -1) throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); - if (_index >= _str.Length) + if (_index >= _str!.Length) throw new InvalidOperationException(SR.InvalidOperation_EnumEnded); return _currentElement; } diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs index 17e7fd5b77fc..593e3a724aa2 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; using System.Threading; namespace System.Collections.Concurrent @@ -52,7 +52,7 @@ public class ConcurrentQueue : IProducerConsumerCollection, IReadOnlyColle /// Lock used to protect cross-segment operations, including any updates to or /// and any operations that need to get a consistent view of them. /// - private object _crossSegmentLock; + private readonly object _crossSegmentLock; /// The current tail segment. private volatile ConcurrentQueueSegment _tail; /// The current head segment. @@ -68,11 +68,20 @@ public ConcurrentQueue() } /// - /// Initializes the contents of the queue from an existing collection. + /// Initializes a new instance of the class that contains elements copied + /// from the specified collection. /// - /// A collection from which to copy elements. - private void InitializeFromCollection(IEnumerable collection) + /// + /// The collection whose elements are copied to the new . + /// + /// The argument is null. + public ConcurrentQueue(IEnumerable collection) { + if (collection == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); + } + _crossSegmentLock = new object(); // Determine the initial segment size. We'll use the default, @@ -91,30 +100,12 @@ private void InitializeFromCollection(IEnumerable collection) // Initialize the segment and add all of the data to it. _tail = _head = new ConcurrentQueueSegment(length); - foreach (T item in collection) + foreach (T item in collection!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { Enqueue(item); } } - /// - /// Initializes a new instance of the class that contains elements copied - /// from the specified collection. - /// - /// - /// The collection whose elements are copied to the new . - /// - /// The argument is null. - public ConcurrentQueue(IEnumerable collection) - { - if (collection == null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); - } - - InitializeFromCollection(collection); - } - /// /// Copies the elements of the to an , starting at a particular index. @@ -156,7 +147,7 @@ void ICollection.CopyTo(Array array, int index) // Otherwise, fall back to the slower path that first copies the contents // to an array, and then uses that array's non-generic CopyTo to do the copy. - ToArray().CopyTo(array, index); + ToArray().CopyTo(array!, index); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } /// @@ -173,7 +164,7 @@ void ICollection.CopyTo(Array array, int index) /// cref="ICollection"/>. This property is not supported. /// /// The SyncRoot property is not supported. - object ICollection.SyncRoot { get { ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); return default; } } + object ICollection.SyncRoot { get { ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); return default!; } } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 /// Returns an enumerator that iterates through a collection. /// An that can be used to iterate through the collection. @@ -347,7 +338,7 @@ public int Count // With the cross-segment lock held, we're guaranteed that all of these internal segments are // consistent, as the head and tail segment can't be changed while we're holding the lock, and // dequeueing and enqueueing can only be done from the head and tail segments, which these aren't. - for (ConcurrentQueueSegment s = head._nextSegment; s != tail; s = s._nextSegment) + for (ConcurrentQueueSegment s = head._nextSegment!; s != tail; s = s._nextSegment!) { Debug.Assert(s._frozenForEnqueues, "Internal segment must be frozen as there's a following segment."); count += s._headAndTail.Tail - s.FreezeOffset; @@ -415,7 +406,7 @@ private static long GetCount(ConcurrentQueueSegment head, int headHead, Concu // Since there were segments before these, for our purposes we consider them to start at // the 0th element, and since there is at least one segment after each, each was frozen // by the time we snapped it, so we can iterate until each's frozen tail. - for (ConcurrentQueueSegment s = head._nextSegment; s != tail; s = s._nextSegment) + for (ConcurrentQueueSegment s = head._nextSegment!; s != tail; s = s._nextSegment!) { Debug.Assert(s._preservedForObservation); Debug.Assert(s._frozenForEnqueues); @@ -471,7 +462,7 @@ public void CopyTo(T[] array, int index) // Get the number of items to be enumerated long count = GetCount(head, headHead, tail, tailTail); - if (index > array.Length - count) + if (index > array!.Length - count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } @@ -523,7 +514,7 @@ private void SnapForObservation(out ConcurrentQueueSegment head, out int head // Mark them and all segments in between as preserving, and ensure no additional items // can be added to the tail. - for (ConcurrentQueueSegment s = head; ; s = s._nextSegment) + for (ConcurrentQueueSegment s = head; ; s = s._nextSegment!) { s._preservedForObservation = true; if (s == tail) break; @@ -595,7 +586,7 @@ private IEnumerator Enumerate(ConcurrentQueueSegment head, int headHead, C { // Each segment between head and tail, not including head and tail. Since there were // segments before these, for our purposes we consider it to start at the 0th element. - for (ConcurrentQueueSegment s = head._nextSegment; s != tail; s = s._nextSegment) + for (ConcurrentQueueSegment s = head._nextSegment!; s != tail; s = s._nextSegment!) { Debug.Assert(s._preservedForObservation, "Would have had to been preserved as a segment part of enumeration"); Debug.Assert(s._frozenForEnqueues, "Would have had to be frozen for enqueues as it's intermediate"); @@ -688,7 +679,7 @@ private void EnqueueSlow(T item) /// true if an element was removed and returned from the beginning of the /// successfully; otherwise, false. /// - public bool TryDequeue(out T result) => + public bool TryDequeue(out T result) => // TODO-GENERIC-NULLABLE _head.TryDequeue(out result) || // fast-path that operates just on the head segment TryDequeueSlow(out result); // slow path that needs to fix up segments @@ -711,7 +702,7 @@ private bool TryDequeueSlow(out T item) // check and this check, another item could have arrived). if (head._nextSegment == null) { - item = default; + item = default!; // TODO-NULLABLE-GENERIC return false; } @@ -752,7 +743,7 @@ private bool TryDequeueSlow(out T item) /// For determining whether the collection contains any items, use of the /// property is recommended rather than peeking. /// - public bool TryPeek(out T result) => TryPeek(out result, resultUsed: true); + public bool TryPeek(out T result) => TryPeek(out result, resultUsed: true); // TODO-GENERIC-NULLABLE /// Attempts to retrieve the value for the first element in the queue. /// The value of the first element, if found. @@ -768,7 +759,7 @@ private bool TryPeek(out T result, bool resultUsed) // Grab the next segment from this one, before we peek. // This is to be able to see whether the value has changed // during the peek operation. - ConcurrentQueueSegment next = Volatile.Read(ref s._nextSegment); + ConcurrentQueueSegment? next = Volatile.Read(ref s._nextSegment); // Peek at the segment. If we find an element, we're done. if (s.TryPeek(out result, resultUsed)) @@ -805,7 +796,7 @@ private bool TryPeek(out T result, bool resultUsed) // and we'll traverse to that segment. } - result = default; + result = default!; // TODO-NULLABLE-GENERIC return false; } diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs index c724285c7ed8..c120d777621e 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; @@ -33,7 +34,7 @@ internal sealed class ConcurrentQueueSegment internal bool _frozenForEnqueues; #pragma warning disable 0649 // some builds don't assign to this field /// The segment following this one in the queue, or null if this segment is the last in the queue. - internal ConcurrentQueueSegment _nextSegment; // SOS's ThreadPool command depends on this name + internal ConcurrentQueueSegment? _nextSegment; // SOS's ThreadPool command depends on this name #pragma warning restore 0649 /// Creates the segment. @@ -126,7 +127,7 @@ internal static int RoundUpToPowerOf2(int i) } /// Tries to dequeue an element from the queue. - public bool TryDequeue(out T item) + public bool TryDequeue(out T item) // TODO-NULLABLE-GENERIC { Slot[] slots = _slots; @@ -164,7 +165,7 @@ public bool TryDequeue(out T item) // If we're preserving, though, we don't zero out the slot, as we need it for // enumerations, peeking, ToArray, etc. And we don't update the sequence number, // so that an enqueuer will see it as full and be forced to move to a new segment. - slots[slotsIndex].Item = default(T); + slots[slotsIndex].Item = default!; // TODO-NULLABLE-GENERIC Volatile.Write(ref slots[slotsIndex].SequenceNumber, currentHead + slots.Length); } return true; @@ -183,7 +184,7 @@ public bool TryDequeue(out T item) int currentTail = Volatile.Read(ref _headAndTail.Tail); if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0))) { - item = default(T); + item = default!; // TODO-NULLABLE-GENERIC return false; } @@ -198,7 +199,7 @@ public bool TryDequeue(out T item) } /// Tries to peek at an element from the queue, without removing it. - public bool TryPeek(out T result, bool resultUsed) + public bool TryPeek(out T result, bool resultUsed) // TODO-NULLABLE-GENERIC { if (resultUsed) { @@ -228,7 +229,7 @@ public bool TryPeek(out T result, bool resultUsed) int diff = sequenceNumber - (currentHead + 1); if (diff == 0) { - result = resultUsed ? slots[slotsIndex].Item : default(T); + result = resultUsed ? slots[slotsIndex].Item : default!; // TODO-NULLABLE-GENERIC return true; } else if (diff < 0) @@ -244,7 +245,7 @@ public bool TryPeek(out T result, bool resultUsed) int currentTail = Volatile.Read(ref _headAndTail.Tail); if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0))) { - result = default(T); + result = default!; // TODO-NULLABLE-GENERIC return false; } diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs index 9727150569a6..797bb0863dba 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; -using System.Diagnostics; namespace System.Collections.Concurrent { @@ -59,7 +59,7 @@ public interface IProducerConsumerCollection : IEnumerable, ICollection /// unspecified. /// /// true if an object was removed and returned successfully; otherwise, false. - bool TryTake(out T item); + bool TryTake(out T item); // TODO-NULLABLE-GENERIC /// /// Copies the elements contained in the to a new array. diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs index 0205e068eada..f30f8f66fcc6 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Collections.Concurrent @@ -21,12 +22,7 @@ internal sealed class IProducerConsumerCollectionDebugView /// A collection to browse in the debugger. public IProducerConsumerCollectionDebugView(IProducerConsumerCollection collection) { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - _collection = collection; + _collection = collection ?? throw new ArgumentNullException(nameof(collection)); } /// diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs index dbb0bdf56608..0a36cb5f7681 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Serialization; -using System.Threading; namespace System.Collections.Generic { @@ -38,8 +37,11 @@ public class Dictionary : IDictionary, IDictionary, { private struct Entry { - public int hashCode; // Lower 31 bits of hash code, -1 if unused - public int next; // Index of next entry, -1 if last + // 0-based index of next entry in chain: -1 means end of chain + // also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3, + // so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc. + public int next; + public uint hashCode; public TKey key; // Key of entry public TValue value; // Value of entry } @@ -53,6 +55,7 @@ private struct Entry private IEqualityComparer _comparer; private KeyCollection _keys; private ValueCollection _values; + private const int StartOfFreeList = -3; // constants for serialization private const string VersionName = "Version"; // Do not rename (binary serialization) @@ -103,7 +106,7 @@ public Dictionary(IDictionary dictionary, IEqualityComparer Entry[] entries = d._entries; for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) + if (entries[i].next >= -1) { Add(entries[i].key, entries[i].value); } @@ -278,7 +281,7 @@ public bool ContainsValue(TValue value) { for (int i = 0; i < _count; i++) { - if (entries[i].hashCode >= 0 && entries[i].value == null) return true; + if (entries[i].next >= -1 && entries[i].value == null) return true; } } else @@ -288,7 +291,7 @@ public bool ContainsValue(TValue value) // ValueType: Devirtualize with EqualityComparer.Default intrinsic for (int i = 0; i < _count; i++) { - if (entries[i].hashCode >= 0 && EqualityComparer.Default.Equals(entries[i].value, value)) return true; + if (entries[i].next >= -1 && EqualityComparer.Default.Equals(entries[i].value, value)) return true; } } else @@ -299,7 +302,7 @@ public bool ContainsValue(TValue value) EqualityComparer defaultComparer = EqualityComparer.Default; for (int i = 0; i < _count; i++) { - if (entries[i].hashCode >= 0 && defaultComparer.Equals(entries[i].value, value)) return true; + if (entries[i].next >= -1 && defaultComparer.Equals(entries[i].value, value)) return true; } } } @@ -327,7 +330,7 @@ private void CopyTo(KeyValuePair[] array, int index) Entry[] entries = _entries; for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) + if (entries[i].next >= -1) { array[index++] = new KeyValuePair(entries[i].key, entries[i].value); } @@ -375,9 +378,9 @@ private int FindEntry(TKey key) IEqualityComparer comparer = _comparer; if (comparer == null) { - int hashCode = key.GetHashCode() & 0x7FFFFFFF; + uint hashCode = (uint)key.GetHashCode(); // Value in _buckets is 1-based - i = buckets[hashCode % buckets.Length] - 1; + i = buckets[hashCode % (uint)buckets.Length] - 1; if (default(TKey) != null) { // ValueType: Devirtualize with EqualityComparer.Default intrinsic @@ -428,9 +431,9 @@ private int FindEntry(TKey key) } else { - int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; + uint hashCode = (uint)comparer.GetHashCode(key); // Value in _buckets is 1-based - i = buckets[hashCode % buckets.Length] - 1; + i = buckets[hashCode % (uint)buckets.Length] - 1; do { // Should be a while loop https://github.com/dotnet/coreclr/issues/15476 @@ -482,10 +485,10 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) Entry[] entries = _entries; IEqualityComparer comparer = _comparer; - int hashCode = ((comparer == null) ? key.GetHashCode() : comparer.GetHashCode(key)) & 0x7FFFFFFF; + uint hashCode = (uint)((comparer == null) ? key.GetHashCode() : comparer.GetHashCode(key)); int collisionCount = 0; - ref int bucket = ref _buckets[hashCode % _buckets.Length]; + ref int bucket = ref _buckets[hashCode % (uint)_buckets.Length]; // Value in _buckets is 1-based int i = bucket - 1; @@ -627,7 +630,7 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) if (count == entries.Length) { Resize(); - bucket = ref _buckets[hashCode % _buckets.Length]; + bucket = ref _buckets[hashCode % (uint)_buckets.Length]; } index = count; _count = count + 1; @@ -638,7 +641,9 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) if (updateFreeList) { - _freeList = entry.next; + Debug.Assert((StartOfFreeList - entries[_freeList].next) >= -1, "shouldn't overflow because `next` cannot underflow"); + + _freeList = StartOfFreeList - entries[_freeList].next; } entry.hashCode = hashCode; // Value in _buckets is 1-based @@ -725,19 +730,19 @@ private void Resize(int newSize, bool forceNewHashCodes) { for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) + if (entries[i].next >= -1) { Debug.Assert(_comparer == null); - entries[i].hashCode = (entries[i].key.GetHashCode() & 0x7FFFFFFF); + entries[i].hashCode = (uint)entries[i].key.GetHashCode(); } } } for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) + if (entries[i].next >= -1) { - int bucket = entries[i].hashCode % newSize; + uint bucket = entries[i].hashCode % (uint)newSize; // Value in _buckets is 1-based entries[i].next = buckets[bucket] - 1; // Value in _buckets is 1-based @@ -764,8 +769,8 @@ public bool Remove(TKey key) int collisionCount = 0; if (buckets != null) { - int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF; - int bucket = hashCode % buckets.Length; + uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode()); + uint bucket = hashCode % (uint)buckets.Length; int last = -1; // Value in buckets is 1-based int i = buckets[bucket] - 1; @@ -784,8 +789,10 @@ public bool Remove(TKey key) { entries[last].next = entry.next; } - entry.hashCode = -1; - entry.next = _freeList; + + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + + entry.next = StartOfFreeList - _freeList; if (RuntimeHelpers.IsReferenceOrContainsReferences()) { @@ -829,8 +836,8 @@ public bool Remove(TKey key, out TValue value) int collisionCount = 0; if (buckets != null) { - int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF; - int bucket = hashCode % buckets.Length; + uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode()); + uint bucket = hashCode % (uint)buckets.Length; int last = -1; // Value in buckets is 1-based int i = buckets[bucket] - 1; @@ -852,8 +859,9 @@ public bool Remove(TKey key, out TValue value) value = entry.value; - entry.hashCode = -1; - entry.next = _freeList; + Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646"); + + entry.next = StartOfFreeList - _freeList; if (RuntimeHelpers.IsReferenceOrContainsReferences()) { @@ -925,7 +933,7 @@ void ICollection.CopyTo(Array array, int index) Entry[] entries = _entries; for (int i = 0; i < _count; i++) { - if (entries[i].hashCode >= 0) + if (entries[i].next >= -1) { dictEntryArray[index++] = new DictionaryEntry(entries[i].key, entries[i].value); } @@ -945,7 +953,7 @@ void ICollection.CopyTo(Array array, int index) Entry[] entries = _entries; for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) + if (entries[i].next >= -1) { objects[index++] = new KeyValuePair(entries[i].key, entries[i].value); } @@ -1018,12 +1026,12 @@ public void TrimExcess(int capacity) int count = 0; for (int i = 0; i < oldCount; i++) { - int hashCode = oldEntries[i].hashCode; - if (hashCode >= 0) + uint hashCode = oldEntries[i].hashCode; + if (oldEntries[i].next >= -1) { ref Entry entry = ref entries[count]; entry = oldEntries[i]; - int bucket = hashCode % newSize; + uint bucket = hashCode % (uint)newSize; // Value in _buckets is 1-based entry.next = buckets[bucket] - 1; // Value in _buckets is 1-based @@ -1179,7 +1187,7 @@ public bool MoveNext() { ref Entry entry = ref _dictionary._entries[_index++]; - if (entry.hashCode >= 0) + if (entry.next >= -1) { _current = new KeyValuePair(entry.key, entry.value); return true; @@ -1307,7 +1315,7 @@ public void CopyTo(TKey[] array, int index) Entry[] entries = _dictionary._entries; for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) array[index++] = entries[i].key; + if (entries[i].next >= -1) array[index++] = entries[i].key; } } @@ -1367,7 +1375,7 @@ void ICollection.CopyTo(Array array, int index) { for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) objects[index++] = entries[i].key; + if (entries[i].next >= -1) objects[index++] = entries[i].key; } } catch (ArrayTypeMismatchException) @@ -1411,7 +1419,7 @@ public bool MoveNext() { ref Entry entry = ref _dictionary._entries[_index++]; - if (entry.hashCode >= 0) + if (entry.next >= -1) { _currentKey = entry.key; return true; @@ -1490,7 +1498,7 @@ public void CopyTo(TValue[] array, int index) Entry[] entries = _dictionary._entries; for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) array[index++] = entries[i].value; + if (entries[i].next >= -1) array[index++] = entries[i].value; } } @@ -1550,7 +1558,7 @@ void ICollection.CopyTo(Array array, int index) { for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0) objects[index++] = entries[i].value; + if (entries[i].next >= -1) objects[index++] = entries[i].value; } } catch (ArrayTypeMismatchException) @@ -1594,7 +1602,7 @@ public bool MoveNext() { ref Entry entry = ref _dictionary._entries[_index++]; - if (entry.hashCode >= 0) + if (entry.next >= -1) { _currentValue = entry.value; return true; diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/IEnumerable.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/IEnumerable.cs index 46d30cbdc8ba..d3ef9e86f76d 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Generic/IEnumerable.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/IEnumerable.cs @@ -2,11 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; - +#nullable enable namespace System.Collections.Generic { // Implement this interface if you need to support foreach semantics. diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/IEqualityComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/IEqualityComparer.cs index 543bdb5fcece..7b983a9ccbe0 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/Generic/IEqualityComparer.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/IEqualityComparer.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Collections.Generic { // The generic IEqualityComparer interface implements methods to if check two objects are equal @@ -12,7 +11,7 @@ namespace System.Collections.Generic public interface IEqualityComparer { bool Equals(T x, T y); - int GetHashCode(T obj); + int GetHashCode(T obj); // TODO-NULLABLE-GENERIC: This generally doesn't accept nulls. } } diff --git a/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs index 38bab78b3c48..46c12ff46a9a 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Collections { // The IComparer interface implements a method that compares two objects. It is @@ -17,6 +16,6 @@ public interface IComparer // value less than zero if x is less than y, zero if x is equal to y, or a // value greater than zero if x is greater than y. // - int Compare(object x, object y); + int Compare(object? x, object? y); } } diff --git a/src/System.Private.CoreLib/shared/System/Collections/IEnumerable.cs b/src/System.Private.CoreLib/shared/System/Collections/IEnumerable.cs index f2c91f51f422..5ca523f69249 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/IEnumerable.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/IEnumerable.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Runtime.InteropServices; namespace System.Collections diff --git a/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs b/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs index 29a6f475bfe2..83d2064dff8f 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -25,7 +26,7 @@ public interface IEnumerator // GetCurrent with no intervening calls to MoveNext // will return the same object. // - object Current + object? Current { get; } diff --git a/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs b/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs index 1784da58cb06..9fba68377cc4 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Collections { public interface IStructuralEquatable { - bool Equals(object other, IEqualityComparer comparer); + bool Equals(object? other, IEqualityComparer comparer); int GetHashCode(IEqualityComparer comparer); } } diff --git a/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs b/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs index fb2b49c94c10..9380064337d9 100644 --- a/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -20,31 +21,37 @@ public class DefaultValueAttribute : Attribute /// /// This is the default value. /// - private object _value; + private object? _value; // Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache - private static object s_convertFromInvariantString; + private static object? s_convertFromInvariantString; /// /// Initializes a new instance of the /// class, converting the specified value to the specified type, and using the U.S. English /// culture as the translation context. /// - public DefaultValueAttribute(Type type, string value) + public DefaultValueAttribute(Type? type, string? value) { - // The try/catch here is because attributes should never throw exceptions. + // The null check and try/catch here are because attributes should never throw exceptions. // We would fail to load an otherwise normal class. + + if (type == null) + { + return; + } + try { - if (TryConvertFromInvariantString(type, value, out object convertedValue)) + if (TryConvertFromInvariantString(type, value, out object? convertedValue)) { _value = convertedValue; } - else if (type.IsSubclassOf(typeof(Enum))) + else if (type.IsSubclassOf(typeof(Enum)) && value != null) { _value = Enum.Parse(type, value, true); } - else if (type == typeof(TimeSpan)) + else if (type == typeof(TimeSpan) && value != null) { _value = TimeSpan.Parse(value); } @@ -54,7 +61,7 @@ public DefaultValueAttribute(Type type, string value) } // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string) - bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out object conversionResult) + bool TryConvertFromInvariantString(Type? typeToConvert, string? stringValue, out object? conversionResult) { conversionResult = null; @@ -62,11 +69,11 @@ bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out o if (s_convertFromInvariantString == null) { Type typeDescriptorType = Type.GetType("System.ComponentModel.TypeDescriptor, System.ComponentModel.TypeConverter", throwOnError: false); - MethodInfo mi = typeDescriptorType?.GetMethod("ConvertFromInvariantString", BindingFlags.NonPublic | BindingFlags.Static); + MethodInfo? mi = typeDescriptorType?.GetMethod("ConvertFromInvariantString", BindingFlags.NonPublic | BindingFlags.Static); Volatile.Write(ref s_convertFromInvariantString, mi == null ? new object() : mi.CreateDelegate(typeof(Func))); } - if (!(s_convertFromInvariantString is Func convertFromInvariantString)) + if (!(s_convertFromInvariantString is Func convertFromInvariantString)) return false; try @@ -162,7 +169,7 @@ public DefaultValueAttribute(bool value) /// Initializes a new instance of the /// class using a . /// - public DefaultValueAttribute(string value) + public DefaultValueAttribute(string? value) { _value = value; } @@ -171,7 +178,7 @@ public DefaultValueAttribute(string value) /// Initializes a new instance of the /// class. /// - public DefaultValueAttribute(object value) + public DefaultValueAttribute(object? value) { _value = value; } @@ -219,9 +226,9 @@ public DefaultValueAttribute(ulong value) /// /// Gets the default value of the property this attribute is bound to. /// - public virtual object Value => _value; + public virtual object? Value => _value; - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj == this) { @@ -242,6 +249,6 @@ public override bool Equals(object obj) public override int GetHashCode() => base.GetHashCode(); - protected void SetValue(object value) => _value = value; + protected void SetValue(object? value) => _value = value; } } diff --git a/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableAttribute.cs b/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableAttribute.cs index de69538532f6..5ab2693eab24 100644 --- a/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.ComponentModel { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Interface)] @@ -18,7 +19,7 @@ public EditorBrowsableAttribute() : this(EditorBrowsableState.Always) public EditorBrowsableState State { get; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj == this) { diff --git a/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableState.cs b/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableState.cs index a98669c4e963..bb935e83c5e8 100644 --- a/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableState.cs +++ b/src/System.Private.CoreLib/shared/System/ComponentModel/EditorBrowsableState.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.ComponentModel { public enum EditorBrowsableState diff --git a/src/System.Private.CoreLib/shared/System/Convert.Base64.cs b/src/System.Private.CoreLib/shared/System/Convert.Base64.cs index 332f3b9d8b16..aef0cdeca3fc 100644 --- a/src/System.Private.CoreLib/shared/System/Convert.Base64.cs +++ b/src/System.Private.CoreLib/shared/System/Convert.Base64.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/System/Convert.cs b/src/System.Private.CoreLib/shared/System/Convert.cs index 2bc01794e406..03b1bccede4b 100644 --- a/src/System.Private.CoreLib/shared/System/Convert.cs +++ b/src/System.Private.CoreLib/shared/System/Convert.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Globalization; using System.Threading; @@ -157,7 +158,7 @@ private static bool DoAsserts() // the object does not implement IConvertible), the result is TypeCode.Object. // Otherwise, the result is the type code of the object, as determined by // the object's implementation of IConvertible. - public static TypeCode GetTypeCode(object value) + public static TypeCode GetTypeCode(object? value) { if (value == null) return TypeCode.Empty; if (value is IConvertible temp) @@ -169,7 +170,7 @@ public static TypeCode GetTypeCode(object value) // Returns true if the given object is a database null. This operation // corresponds to "value.GetTypeCode() == TypeCode.DBNull". - public static bool IsDBNull(object value) + public static bool IsDBNull(object? value) { if (value == System.DBNull.Value) return true; return value is IConvertible convertible ? convertible.GetTypeCode() == TypeCode.DBNull : false; @@ -187,12 +188,12 @@ public static bool IsDBNull(object value) // object already has the given type code, in which case the object is // simply returned. Otherwise, the appropriate ToXXX() is invoked on the // object's implementation of IConvertible. - public static object ChangeType(object value, TypeCode typeCode) + public static object? ChangeType(object? value, TypeCode typeCode) { return ChangeType(value, typeCode, CultureInfo.CurrentCulture); } - public static object ChangeType(object value, TypeCode typeCode, IFormatProvider provider) + public static object? ChangeType(object? value, TypeCode typeCode, IFormatProvider? provider) { if (value == null && (typeCode == TypeCode.Empty || typeCode == TypeCode.String || typeCode == TypeCode.Object)) { @@ -250,7 +251,7 @@ public static object ChangeType(object value, TypeCode typeCode, IFormatProvider } } - internal static object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) + internal static object DefaultToType(IConvertible value, Type targetType, IFormatProvider? provider) { Debug.Assert(value != null, "[Convert.DefaultToType]value!=null"); if (targetType == null) @@ -306,12 +307,12 @@ internal static object DefaultToType(IConvertible value, Type targetType, IForma throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, value.GetType().FullName, targetType.FullName)); } - public static object ChangeType(object value, Type conversionType) + public static object? ChangeType(object? value, Type conversionType) { return ChangeType(value, conversionType, CultureInfo.CurrentCulture); } - public static object ChangeType(object value, Type conversionType, IFormatProvider provider) + public static object? ChangeType(object? value, Type conversionType, IFormatProvider? provider) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (conversionType is null) { @@ -391,12 +392,12 @@ public static object ChangeType(object value, Type conversionType, IFormatProvid private static void ThrowUInt64OverflowException() { throw new OverflowException(SR.Overflow_UInt64); } // Conversions to Boolean - public static bool ToBoolean(object value) + public static bool ToBoolean(object? value) { return value == null ? false : ((IConvertible)value).ToBoolean(null); } - public static bool ToBoolean(object value, IFormatProvider provider) + public static bool ToBoolean(object? value, IFormatProvider? provider) { return value == null ? false : ((IConvertible)value).ToBoolean(provider); } @@ -459,14 +460,14 @@ public static bool ToBoolean(ulong value) return value != 0; } - public static bool ToBoolean(string value) + public static bool ToBoolean(string? value) { if (value == null) return false; return bool.Parse(value); } - public static bool ToBoolean(string value, IFormatProvider provider) + public static bool ToBoolean(string? value, IFormatProvider? provider) { if (value == null) return false; @@ -499,12 +500,12 @@ public static bool ToBoolean(DateTime value) // Conversions to Char - public static char ToChar(object value) + public static char ToChar(object? value) { return value == null ? (char)0 : ((IConvertible)value).ToChar(null); } - public static char ToChar(object value, IFormatProvider provider) + public static char ToChar(object? value, IFormatProvider? provider) { return value == null ? (char)0 : ((IConvertible)value).ToChar(provider); } @@ -578,7 +579,7 @@ public static char ToChar(string value) return ToChar(value, null); } - public static char ToChar(string value, IFormatProvider provider) + public static char ToChar(string value, IFormatProvider? provider) { if (value == null) throw new ArgumentNullException(nameof(value)); @@ -622,13 +623,13 @@ public static char ToChar(DateTime value) // Conversions to SByte [CLSCompliant(false)] - public static sbyte ToSByte(object value) + public static sbyte ToSByte(object? value) { return value == null ? (sbyte)0 : ((IConvertible)value).ToSByte(null); } [CLSCompliant(false)] - public static sbyte ToSByte(object value, IFormatProvider provider) + public static sbyte ToSByte(object? value, IFormatProvider? provider) { return value == null ? (sbyte)0 : ((IConvertible)value).ToSByte(provider); } @@ -720,7 +721,7 @@ public static sbyte ToSByte(decimal value) } [CLSCompliant(false)] - public static sbyte ToSByte(string value) + public static sbyte ToSByte(string? value) { if (value == null) return 0; @@ -728,7 +729,7 @@ public static sbyte ToSByte(string value) } [CLSCompliant(false)] - public static sbyte ToSByte(string value, IFormatProvider provider) + public static sbyte ToSByte(string value, IFormatProvider? provider) { return sbyte.Parse(value, NumberStyles.Integer, provider); } @@ -744,12 +745,12 @@ public static sbyte ToSByte(DateTime value) // Conversions to Byte - public static byte ToByte(object value) + public static byte ToByte(object? value) { return value == null ? (byte)0 : ((IConvertible)value).ToByte(null); } - public static byte ToByte(object value, IFormatProvider provider) + public static byte ToByte(object? value, IFormatProvider? provider) { return value == null ? (byte)0 : ((IConvertible)value).ToByte(provider); } @@ -831,14 +832,14 @@ public static byte ToByte(decimal value) return decimal.ToByte(decimal.Round(value, 0)); } - public static byte ToByte(string value) + public static byte ToByte(string? value) { if (value == null) return 0; return byte.Parse(value, CultureInfo.CurrentCulture); } - public static byte ToByte(string value, IFormatProvider provider) + public static byte ToByte(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -856,12 +857,12 @@ public static byte ToByte(DateTime value) // Conversions to Int16 - public static short ToInt16(object value) + public static short ToInt16(object? value) { return value == null ? (short)0 : ((IConvertible)value).ToInt16(null); } - public static short ToInt16(object value, IFormatProvider provider) + public static short ToInt16(object? value, IFormatProvider? provider) { return value == null ? (short)0 : ((IConvertible)value).ToInt16(provider); } @@ -941,14 +942,14 @@ public static short ToInt16(decimal value) return decimal.ToInt16(decimal.Round(value, 0)); } - public static short ToInt16(string value) + public static short ToInt16(string? value) { if (value == null) return 0; return short.Parse(value, CultureInfo.CurrentCulture); } - public static short ToInt16(string value, IFormatProvider provider) + public static short ToInt16(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -967,13 +968,13 @@ public static short ToInt16(DateTime value) // Conversions to UInt16 [CLSCompliant(false)] - public static ushort ToUInt16(object value) + public static ushort ToUInt16(object? value) { return value == null ? (ushort)0 : ((IConvertible)value).ToUInt16(null); } [CLSCompliant(false)] - public static ushort ToUInt16(object value, IFormatProvider provider) + public static ushort ToUInt16(object? value, IFormatProvider? provider) { return value == null ? (ushort)0 : ((IConvertible)value).ToUInt16(provider); } @@ -1065,7 +1066,7 @@ public static ushort ToUInt16(decimal value) } [CLSCompliant(false)] - public static ushort ToUInt16(string value) + public static ushort ToUInt16(string? value) { if (value == null) return 0; @@ -1073,7 +1074,7 @@ public static ushort ToUInt16(string value) } [CLSCompliant(false)] - public static ushort ToUInt16(string value, IFormatProvider provider) + public static ushort ToUInt16(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1091,12 +1092,12 @@ public static ushort ToUInt16(DateTime value) // Conversions to Int32 - public static int ToInt32(object value) + public static int ToInt32(object? value) { return value == null ? 0 : ((IConvertible)value).ToInt32(null); } - public static int ToInt32(object value, IFormatProvider provider) + public static int ToInt32(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToInt32(provider); } @@ -1194,14 +1195,14 @@ public static int ToInt32(decimal value) return decimal.ToInt32(decimal.Round(value, 0)); } - public static int ToInt32(string value) + public static int ToInt32(string? value) { if (value == null) return 0; return int.Parse(value, CultureInfo.CurrentCulture); } - public static int ToInt32(string value, IFormatProvider provider) + public static int ToInt32(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1220,13 +1221,13 @@ public static int ToInt32(DateTime value) // Conversions to UInt32 [CLSCompliant(false)] - public static uint ToUInt32(object value) + public static uint ToUInt32(object? value) { return value == null ? 0 : ((IConvertible)value).ToUInt32(null); } [CLSCompliant(false)] - public static uint ToUInt32(object value, IFormatProvider provider) + public static uint ToUInt32(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToUInt32(provider); } @@ -1323,7 +1324,7 @@ public static uint ToUInt32(decimal value) } [CLSCompliant(false)] - public static uint ToUInt32(string value) + public static uint ToUInt32(string? value) { if (value == null) return 0; @@ -1331,7 +1332,7 @@ public static uint ToUInt32(string value) } [CLSCompliant(false)] - public static uint ToUInt32(string value, IFormatProvider provider) + public static uint ToUInt32(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1349,12 +1350,12 @@ public static uint ToUInt32(DateTime value) // Conversions to Int64 - public static long ToInt64(object value) + public static long ToInt64(object? value) { return value == null ? 0 : ((IConvertible)value).ToInt64(null); } - public static long ToInt64(object value, IFormatProvider provider) + public static long ToInt64(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToInt64(provider); } @@ -1431,14 +1432,14 @@ public static long ToInt64(decimal value) return decimal.ToInt64(decimal.Round(value, 0)); } - public static long ToInt64(string value) + public static long ToInt64(string? value) { if (value == null) return 0; return long.Parse(value, CultureInfo.CurrentCulture); } - public static long ToInt64(string value, IFormatProvider provider) + public static long ToInt64(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1456,13 +1457,13 @@ public static long ToInt64(DateTime value) // Conversions to UInt64 [CLSCompliant(false)] - public static ulong ToUInt64(object value) + public static ulong ToUInt64(object? value) { return value == null ? 0 : ((IConvertible)value).ToUInt64(null); } [CLSCompliant(false)] - public static ulong ToUInt64(object value, IFormatProvider provider) + public static ulong ToUInt64(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToUInt64(provider); } @@ -1551,7 +1552,7 @@ public static ulong ToUInt64(decimal value) } [CLSCompliant(false)] - public static ulong ToUInt64(string value) + public static ulong ToUInt64(string? value) { if (value == null) return 0; @@ -1559,7 +1560,7 @@ public static ulong ToUInt64(string value) } [CLSCompliant(false)] - public static ulong ToUInt64(string value, IFormatProvider provider) + public static ulong ToUInt64(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1577,12 +1578,12 @@ public static ulong ToUInt64(DateTime value) // Conversions to Single - public static float ToSingle(object value) + public static float ToSingle(object? value) { return value == null ? 0 : ((IConvertible)value).ToSingle(null); } - public static float ToSingle(object value, IFormatProvider provider) + public static float ToSingle(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToSingle(provider); } @@ -1651,14 +1652,14 @@ public static float ToSingle(decimal value) return (float)value; } - public static float ToSingle(string value) + public static float ToSingle(string? value) { if (value == null) return 0; return float.Parse(value, CultureInfo.CurrentCulture); } - public static float ToSingle(string value, IFormatProvider provider) + public static float ToSingle(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1681,12 +1682,12 @@ public static float ToSingle(DateTime value) // Conversions to Double - public static double ToDouble(object value) + public static double ToDouble(object? value) { return value == null ? 0 : ((IConvertible)value).ToDouble(null); } - public static double ToDouble(object value, IFormatProvider provider) + public static double ToDouble(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToDouble(provider); } @@ -1756,14 +1757,14 @@ public static double ToDouble(decimal value) return (double)value; } - public static double ToDouble(string value) + public static double ToDouble(string? value) { if (value == null) return 0; return double.Parse(value, CultureInfo.CurrentCulture); } - public static double ToDouble(string value, IFormatProvider provider) + public static double ToDouble(string? value, IFormatProvider? provider) { if (value == null) return 0; @@ -1785,12 +1786,12 @@ public static double ToDouble(DateTime value) // Conversions to Decimal - public static decimal ToDecimal(object value) + public static decimal ToDecimal(object? value) { return value == null ? 0 : ((IConvertible)value).ToDecimal(null); } - public static decimal ToDecimal(object value, IFormatProvider provider) + public static decimal ToDecimal(object? value, IFormatProvider? provider) { return value == null ? 0 : ((IConvertible)value).ToDecimal(provider); } @@ -1854,14 +1855,14 @@ public static decimal ToDecimal(double value) return (decimal)value; } - public static decimal ToDecimal(string value) + public static decimal ToDecimal(string? value) { if (value == null) return 0m; return decimal.Parse(value, CultureInfo.CurrentCulture); } - public static decimal ToDecimal(string value, IFormatProvider provider) + public static decimal ToDecimal(string? value, IFormatProvider? provider) { if (value == null) return 0m; @@ -1893,24 +1894,24 @@ public static DateTime ToDateTime(DateTime value) return value; } - public static DateTime ToDateTime(object value) + public static DateTime ToDateTime(object? value) { return value == null ? DateTime.MinValue : ((IConvertible)value).ToDateTime(null); } - public static DateTime ToDateTime(object value, IFormatProvider provider) + public static DateTime ToDateTime(object? value, IFormatProvider? provider) { return value == null ? DateTime.MinValue : ((IConvertible)value).ToDateTime(provider); } - public static DateTime ToDateTime(string value) + public static DateTime ToDateTime(string? value) { if (value == null) return new DateTime(0); return DateTime.Parse(value, CultureInfo.CurrentCulture); } - public static DateTime ToDateTime(string value, IFormatProvider provider) + public static DateTime ToDateTime(string? value, IFormatProvider? provider) { if (value == null) return new DateTime(0); @@ -1991,12 +1992,12 @@ public static DateTime ToDateTime(decimal value) // Conversions to String - public static string ToString(object value) + public static string? ToString(object? value) { return ToString(value, null); } - public static string ToString(object value, IFormatProvider provider) + public static string? ToString(object? value, IFormatProvider? provider) { if (value is IConvertible ic) return ic.ToString(provider); @@ -2010,7 +2011,7 @@ public static string ToString(bool value) return value.ToString(); } - public static string ToString(bool value, IFormatProvider provider) + public static string ToString(bool value, IFormatProvider? provider) { return value.ToString(); } @@ -2020,7 +2021,7 @@ public static string ToString(char value) return char.ToString(value); } - public static string ToString(char value, IFormatProvider provider) + public static string ToString(char value, IFormatProvider? provider) { return value.ToString(); } @@ -2032,7 +2033,7 @@ public static string ToString(sbyte value) } [CLSCompliant(false)] - public static string ToString(sbyte value, IFormatProvider provider) + public static string ToString(sbyte value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2042,7 +2043,7 @@ public static string ToString(byte value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(byte value, IFormatProvider provider) + public static string ToString(byte value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2052,7 +2053,7 @@ public static string ToString(short value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(short value, IFormatProvider provider) + public static string ToString(short value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2064,7 +2065,7 @@ public static string ToString(ushort value) } [CLSCompliant(false)] - public static string ToString(ushort value, IFormatProvider provider) + public static string ToString(ushort value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2074,7 +2075,7 @@ public static string ToString(int value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(int value, IFormatProvider provider) + public static string ToString(int value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2086,7 +2087,7 @@ public static string ToString(uint value) } [CLSCompliant(false)] - public static string ToString(uint value, IFormatProvider provider) + public static string ToString(uint value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2096,7 +2097,7 @@ public static string ToString(long value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(long value, IFormatProvider provider) + public static string ToString(long value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2108,7 +2109,7 @@ public static string ToString(ulong value) } [CLSCompliant(false)] - public static string ToString(ulong value, IFormatProvider provider) + public static string ToString(ulong value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2118,7 +2119,7 @@ public static string ToString(float value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(float value, IFormatProvider provider) + public static string ToString(float value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2128,7 +2129,7 @@ public static string ToString(double value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(double value, IFormatProvider provider) + public static string ToString(double value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2138,7 +2139,7 @@ public static string ToString(decimal value) return value.ToString(CultureInfo.CurrentCulture); } - public static string ToString(decimal value, IFormatProvider provider) + public static string ToString(decimal value, IFormatProvider? provider) { return value.ToString(provider); } @@ -2148,17 +2149,17 @@ public static string ToString(DateTime value) return value.ToString(); } - public static string ToString(DateTime value, IFormatProvider provider) + public static string ToString(DateTime value, IFormatProvider? provider) { return value.ToString(provider); } - public static string ToString(string value) + public static string? ToString(string? value) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { return value; } - public static string ToString(string value, IFormatProvider provider) + public static string? ToString(string? value, IFormatProvider? provider) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { return value; // avoid the null check } @@ -2171,7 +2172,7 @@ public static string ToString(string value, IFormatProvider provider) // be 2, 8, 10, or 16. If base is 16, the number may be preceded // by 0x; any other leading or trailing characters cause an error. // - public static byte ToByte(string value, int fromBase) + public static byte ToByte(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2194,7 +2195,7 @@ public static byte ToByte(string value, int fromBase) // by 0x; any other leading or trailing characters cause an error. // [CLSCompliant(false)] - public static sbyte ToSByte(string value, int fromBase) + public static sbyte ToSByte(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2219,7 +2220,7 @@ public static sbyte ToSByte(string value, int fromBase) // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded // by 0x; any other leading or trailing characters cause an error. // - public static short ToInt16(string value, int fromBase) + public static short ToInt16(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2245,7 +2246,7 @@ public static short ToInt16(string value, int fromBase) // by 0x; any other leading or trailing characters cause an error. // [CLSCompliant(false)] - public static ushort ToUInt16(string value, int fromBase) + public static ushort ToUInt16(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2267,7 +2268,7 @@ public static ushort ToUInt16(string value, int fromBase) // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded // by 0x; any other leading or trailing characters cause an error. // - public static int ToInt32(string value, int fromBase) + public static int ToInt32(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2283,7 +2284,7 @@ public static int ToInt32(string value, int fromBase) // by 0x; any other leading or trailing characters cause an error. // [CLSCompliant(false)] - public static uint ToUInt32(string value, int fromBase) + public static uint ToUInt32(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2298,7 +2299,7 @@ public static uint ToUInt32(string value, int fromBase) // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded // by 0x; any other leading or trailing characters cause an error. // - public static long ToInt64(string value, int fromBase) + public static long ToInt64(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { @@ -2314,7 +2315,7 @@ public static long ToInt64(string value, int fromBase) // by 0x; any other leading or trailing characters cause an error. // [CLSCompliant(false)] - public static ulong ToUInt64(string value, int fromBase) + public static ulong ToUInt64(string? value, int fromBase) { if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16) { diff --git a/src/System.Private.CoreLib/shared/System/CoreLib.cs b/src/System.Private.CoreLib/shared/System/CoreLib.cs index 9c5d1c1aa377..9e18412742cf 100644 --- a/src/System.Private.CoreLib/shared/System/CoreLib.cs +++ b/src/System.Private.CoreLib/shared/System/CoreLib.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { // This class is used to define the name of the base class library diff --git a/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs b/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs index 207da218356b..5b5fdd63aa7c 100644 --- a/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs +++ b/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs @@ -17,6 +17,7 @@ ** ============================================================*/ +#nullable enable using System.Collections; using System.Globalization; @@ -148,7 +149,7 @@ public override DaylightTime GetDaylightChanges(int year) private static DaylightTime CreateDaylightChanges(int year) { - DaylightTime currentDaylightChanges = null; + DaylightTime? currentDaylightChanges = null; if (TimeZoneInfo.Local.SupportsDaylightSavingTime) { diff --git a/src/System.Private.CoreLib/shared/System/DBNull.cs b/src/System.Private.CoreLib/shared/System/DBNull.cs index 3cee2b15c8d9..5d2a12e96e02 100644 --- a/src/System.Private.CoreLib/shared/System/DBNull.cs +++ b/src/System.Private.CoreLib/shared/System/DBNull.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.Serialization; namespace System @@ -30,7 +31,7 @@ public override string ToString() return string.Empty; } - public string ToString(IFormatProvider provider) + public string ToString(IFormatProvider? provider) { return string.Empty; } @@ -40,77 +41,77 @@ public TypeCode GetTypeCode() return TypeCode.DBNull; } - bool IConvertible.ToBoolean(IFormatProvider provider) + bool IConvertible.ToBoolean(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - char IConvertible.ToChar(IFormatProvider provider) + char IConvertible.ToChar(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - sbyte IConvertible.ToSByte(IFormatProvider provider) + sbyte IConvertible.ToSByte(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - byte IConvertible.ToByte(IFormatProvider provider) + byte IConvertible.ToByte(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - short IConvertible.ToInt16(IFormatProvider provider) + short IConvertible.ToInt16(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - ushort IConvertible.ToUInt16(IFormatProvider provider) + ushort IConvertible.ToUInt16(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - int IConvertible.ToInt32(IFormatProvider provider) + int IConvertible.ToInt32(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - uint IConvertible.ToUInt32(IFormatProvider provider) + uint IConvertible.ToUInt32(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - long IConvertible.ToInt64(IFormatProvider provider) + long IConvertible.ToInt64(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - ulong IConvertible.ToUInt64(IFormatProvider provider) + ulong IConvertible.ToUInt64(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - float IConvertible.ToSingle(IFormatProvider provider) + float IConvertible.ToSingle(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - double IConvertible.ToDouble(IFormatProvider provider) + double IConvertible.ToDouble(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - decimal IConvertible.ToDecimal(IFormatProvider provider) + decimal IConvertible.ToDecimal(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - DateTime IConvertible.ToDateTime(IFormatProvider provider) + DateTime IConvertible.ToDateTime(IFormatProvider? provider) { throw new InvalidCastException(SR.InvalidCast_FromDBNull); } - object IConvertible.ToType(Type type, IFormatProvider provider) + object IConvertible.ToType(Type type, IFormatProvider? provider) { return Convert.DefaultToType((IConvertible)this, type, provider); } diff --git a/src/System.Private.CoreLib/shared/System/DateTime.Unix.cs b/src/System.Private.CoreLib/shared/System/DateTime.Unix.cs index 6cf018115bac..a8af81ffa72a 100644 --- a/src/System.Private.CoreLib/shared/System/DateTime.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/DateTime.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public readonly partial struct DateTime @@ -18,8 +19,8 @@ public static DateTime UtcNow } #endif - internal static DateTime FromFileTimeLeapSecondsAware(long fileTime) => default; - internal static long ToFileTimeLeapSecondsAware(long ticks) => default; + private static DateTime FromFileTimeLeapSecondsAware(long fileTime) => default; + private static long ToFileTimeLeapSecondsAware(long ticks) => default; // IsValidTimeWithLeapSeconds is not expected to be called at all for now on non-Windows platforms internal static bool IsValidTimeWithLeapSeconds(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) => false; diff --git a/src/System.Private.CoreLib/shared/System/DateTime.Win32.cs b/src/System.Private.CoreLib/shared/System/DateTime.Win32.cs new file mode 100644 index 000000000000..d742c891c7c0 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/DateTime.Win32.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System +{ + public readonly partial struct DateTime + { + private static unsafe bool SystemSupportsLeapSeconds() + { + Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION slsi; + + return Interop.NtDll.NtQuerySystemInformation( + Interop.NtDll.SystemLeapSecondInformation, + (void *) &slsi, + sizeof(Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION), + null) == 0 && slsi.Enabled; + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/DateTime.WinRT.cs b/src/System.Private.CoreLib/shared/System/DateTime.WinRT.cs new file mode 100644 index 000000000000..30a9a61aa3da --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/DateTime.WinRT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System +{ + public readonly partial struct DateTime + { + private static unsafe bool SystemSupportsLeapSeconds() + { + Interop.Kernel32.PROCESS_LEAP_SECOND_INFO info; + + // Store apps don't have access to an API that would let us find out whether leap seconds have been + // disabled by policy: this implementation will produce slightly different results from what + // we have for Win32. If GetProcessInformation succeeds, we have to act as if leap seconds existed. + // They could still have been disabled by policy, but we have no way to check for that. + return Interop.Kernel32.GetProcessInformation( + Interop.Kernel32.GetCurrentProcess(), + Interop.Kernel32.ProcessLeapSecondInfo, + &info, + sizeof(Interop.Kernel32.PROCESS_LEAP_SECOND_INFO)) != Interop.BOOL.FALSE; + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/DateTime.Windows.cs b/src/System.Private.CoreLib/shared/System/DateTime.Windows.cs new file mode 100644 index 000000000000..7596ec1cb14a --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/DateTime.Windows.cs @@ -0,0 +1,217 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System +{ + public readonly partial struct DateTime + { + internal static readonly bool s_systemSupportsLeapSeconds = SystemSupportsLeapSeconds(); + + public static unsafe DateTime UtcNow + { + get + { + if (s_systemSupportsLeapSeconds) + { + FullSystemTime time; + GetSystemTimeWithLeapSecondsHandling(&time); + return CreateDateTimeFromSystemTime(in time); + } + + return new DateTime(((ulong)(GetSystemTimeAsFileTime() + FileTimeOffset)) | KindUtc); + } + } + + internal static unsafe bool IsValidTimeWithLeapSeconds(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) + { + DateTime dt = new DateTime(year, month, day); + FullSystemTime time = new FullSystemTime(year, month, dt.DayOfWeek, day, hour, minute, second); + + switch (kind) + { + case DateTimeKind.Local: return ValidateSystemTime(&time.systemTime, localTime: true); + case DateTimeKind.Utc: return ValidateSystemTime(&time.systemTime, localTime: false); + default: + return ValidateSystemTime(&time.systemTime, localTime: true) || ValidateSystemTime(&time.systemTime, localTime: false); + } + } + + private static unsafe DateTime FromFileTimeLeapSecondsAware(long fileTime) + { + FullSystemTime time; + if (FileTimeToSystemTime(fileTime, &time)) + { + return CreateDateTimeFromSystemTime(in time); + } + + throw new ArgumentOutOfRangeException(nameof(fileTime), SR.ArgumentOutOfRange_DateTimeBadTicks); + } + + private static unsafe long ToFileTimeLeapSecondsAware(long ticks) + { + FullSystemTime time = new FullSystemTime(ticks); + long fileTime; + + if (SystemTimeToFileTime(&time.systemTime, &fileTime)) + { + return fileTime + ticks % TicksPerMillisecond; + } + + throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_FileTimeInvalid); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static DateTime CreateDateTimeFromSystemTime(in FullSystemTime time) + { + long ticks = DateToTicks(time.systemTime.Year, time.systemTime.Month, time.systemTime.Day); + ticks += TimeToTicks(time.systemTime.Hour, time.systemTime.Minute, time.systemTime.Second); + ticks += time.systemTime.Milliseconds * TicksPerMillisecond; + ticks += time.hundredNanoSecond; + return new DateTime( ((UInt64)(ticks)) | KindUtc); + } + + // FullSystemTime struct is the SYSTEMTIME struct with extra hundredNanoSecond field to store more precise time. + [StructLayout(LayoutKind.Sequential)] + private struct FullSystemTime + { + internal Interop.Kernel32.SYSTEMTIME systemTime; + internal long hundredNanoSecond; + + internal FullSystemTime(int year, int month, DayOfWeek dayOfWeek, int day, int hour, int minute, int second) + { + systemTime.Year = (ushort) year; + systemTime.Month = (ushort) month; + systemTime.DayOfWeek = (ushort) dayOfWeek; + systemTime.Day = (ushort) day; + systemTime.Hour = (ushort) hour; + systemTime.Minute = (ushort) minute; + systemTime.Second = (ushort) second; + systemTime.Milliseconds = 0; + hundredNanoSecond = 0; + } + + internal FullSystemTime(long ticks) + { + DateTime dt = new DateTime(ticks); + + int year, month, day; + dt.GetDatePart(out year, out month, out day); + + systemTime.Year = (ushort) year; + systemTime.Month = (ushort) month; + systemTime.DayOfWeek = (ushort) dt.DayOfWeek; + systemTime.Day = (ushort) day; + systemTime.Hour = (ushort) dt.Hour; + systemTime.Minute = (ushort) dt.Minute; + systemTime.Second = (ushort) dt.Second; + systemTime.Milliseconds = (ushort) dt.Millisecond; + hundredNanoSecond = 0; + } + }; + +#if !CORECLR + internal static readonly bool s_systemSupportsPreciseSystemTime = SystemSupportsPreciseSystemTime(); + + private static unsafe bool SystemSupportsPreciseSystemTime() + { + if (Environment.IsWindows8OrAbove) + { + // GetSystemTimePreciseAsFileTime exists and we'd like to use it. However, on + // misconfigured systems, it's possible for the "precise" time to be inaccurate: + // https://github.com/dotnet/coreclr/issues/14187 + // If it's inaccurate, though, we expect it to be wildly inaccurate, so as a + // workaround/heuristic, we get both the "normal" and "precise" times, and as + // long as they're close, we use the precise one. This workaround can be removed + // when we better understand what's causing the drift and the issue is no longer + // a problem or can be better worked around on all targeted OSes. + + long systemTimeResult; + Interop.Kernel32.GetSystemTimeAsFileTime(&systemTimeResult); + + long preciseSystemTimeResult; + Interop.Kernel32.GetSystemTimePreciseAsFileTime(&preciseSystemTimeResult); + + return Math.Abs(preciseSystemTimeResult - systemTimeResult) <= 100 * TicksPerMillisecond; + } + + return false; + } + + private static unsafe bool ValidateSystemTime(Interop.Kernel32.SYSTEMTIME* time, bool localTime) + { + if (localTime) + { + Interop.Kernel32.SYSTEMTIME st; + return Interop.Kernel32.TzSpecificLocalTimeToSystemTime(IntPtr.Zero, time, &st) != Interop.BOOL.FALSE; + } + else + { + long timestamp; + return Interop.Kernel32.SystemTimeToFileTime(time, ×tamp) != Interop.BOOL.FALSE; + } + } + + private static unsafe bool FileTimeToSystemTime(long fileTime, FullSystemTime* time) + { + if (Interop.Kernel32.FileTimeToSystemTime(&fileTime, &time->systemTime) != Interop.BOOL.FALSE) + { + // to keep the time precision + time->hundredNanoSecond = fileTime % TicksPerMillisecond; + if (time->systemTime.Second > 59) + { + // we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation. + // we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds + time->systemTime.Second = 59; + time->systemTime.Milliseconds = 999; + time->hundredNanoSecond = 9999; + } + return true; + } + return false; + } + + private static unsafe void GetSystemTimeWithLeapSecondsHandling(FullSystemTime* time) + { + if (!FileTimeToSystemTime(GetSystemTimeAsFileTime(), time)) + { + Interop.Kernel32.GetSystemTime(&time->systemTime); + time->hundredNanoSecond = 0; + if (time->systemTime.Second > 59) + { + // we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation. + // we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds + time->systemTime.Second = 59; + time->systemTime.Milliseconds = 999; + time->hundredNanoSecond = 9999; + } + } + } + + private static unsafe bool SystemTimeToFileTime(Interop.Kernel32.SYSTEMTIME* time, long* fileTime) + { + return Interop.Kernel32.SystemTimeToFileTime(time, fileTime) != Interop.BOOL.FALSE; + } + + private static unsafe long GetSystemTimeAsFileTime() + { + long timestamp; + + if (s_systemSupportsPreciseSystemTime) + { + Interop.Kernel32.GetSystemTimePreciseAsFileTime(×tamp); + } + else + { + Interop.Kernel32.GetSystemTimeAsFileTime(×tamp); + } + + return timestamp; + } +#endif + } +} diff --git a/src/System.Private.CoreLib/shared/System/DateTime.cs b/src/System.Private.CoreLib/shared/System/DateTime.cs index a94171f133bb..deb2da287693 100644 --- a/src/System.Private.CoreLib/shared/System/DateTime.cs +++ b/src/System.Private.CoreLib/shared/System/DateTime.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.Threading; @@ -623,7 +624,7 @@ public static int Compare(DateTime t1, DateTime t2) // occurs. Null is considered less than any instance. // // Returns a value less than zero if this object - public int CompareTo(object value) + public int CompareTo(object? value) { if (value == null) return 1; if (!(value is DateTime)) @@ -709,7 +710,7 @@ internal static long DoubleDateToTicks(double value) // is equal to the value of this DateTime. Returns false // otherwise. // - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is DateTime) { @@ -1205,20 +1206,20 @@ public static DateTime Parse(string s) // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTime Parse(string s, IFormatProvider provider) + public static DateTime Parse(string s, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), DateTimeStyles.None)); } - public static DateTime Parse(string s, IFormatProvider provider, DateTimeStyles styles) + public static DateTime Parse(string s, IFormatProvider? provider, DateTimeStyles styles) { DateTimeFormatInfo.ValidateStyles(styles, nameof(styles)); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), styles)); } - public static DateTime Parse(ReadOnlySpan s, IFormatProvider provider = null, DateTimeStyles styles = DateTimeStyles.None) + public static DateTime Parse(ReadOnlySpan s, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) { DateTimeFormatInfo.ValidateStyles(styles, nameof(styles)); return DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), styles); @@ -1228,7 +1229,7 @@ public static DateTime Parse(ReadOnlySpan s, IFormatProvider provider = nu // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTime ParseExact(string s, string format, IFormatProvider provider) + public static DateTime ParseExact(string s, string format, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format); @@ -1239,7 +1240,7 @@ public static DateTime ParseExact(string s, string format, IFormatProvider provi // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style) + public static DateTime ParseExact(string s, string format, IFormatProvider? provider, DateTimeStyles style) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); @@ -1247,20 +1248,20 @@ public static DateTime ParseExact(string s, string format, IFormatProvider provi return (DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style)); } - public static DateTime ParseExact(ReadOnlySpan s, ReadOnlySpan format, IFormatProvider provider, DateTimeStyles style = DateTimeStyles.None) + public static DateTime ParseExact(ReadOnlySpan s, ReadOnlySpan format, IFormatProvider? provider, DateTimeStyles style = DateTimeStyles.None) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style); } - public static DateTime ParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style) + public static DateTime ParseExact(string s, string[] formats, IFormatProvider? provider, DateTimeStyles style) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return DateTimeParse.ParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style); } - public static DateTime ParseExact(ReadOnlySpan s, string[] formats, IFormatProvider provider, DateTimeStyles style = DateTimeStyles.None) + public static DateTime ParseExact(ReadOnlySpan s, string[] formats, IFormatProvider? provider, DateTimeStyles style = DateTimeStyles.None) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.ParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style); @@ -1393,22 +1394,22 @@ public override string ToString() return DateTimeFormat.Format(this, null, null); } - public string ToString(string format) + public string ToString(string? format) { return DateTimeFormat.Format(this, format, null); } - public string ToString(IFormatProvider provider) + public string ToString(IFormatProvider? provider) { return DateTimeFormat.Format(this, null, provider); } - public string ToString(string format, IFormatProvider provider) + public string ToString(string? format, IFormatProvider? provider) { return DateTimeFormat.Format(this, format, provider); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider provider = null) => + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) => DateTimeFormat.TryFormat(this, destination, out charsWritten, format, provider); public DateTime ToUniversalTime() @@ -1416,7 +1417,7 @@ public DateTime ToUniversalTime() return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime); } - public static bool TryParse(string s, out DateTime result) + public static bool TryParse(string? s, out DateTime result) { if (s == null) { @@ -1431,7 +1432,7 @@ public static bool TryParse(ReadOnlySpan s, out DateTime result) return DateTimeParse.TryParse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out result); } - public static bool TryParse(string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result) + public static bool TryParse(string? s, IFormatProvider? provider, DateTimeStyles styles, out DateTime result) { DateTimeFormatInfo.ValidateStyles(styles, nameof(styles)); @@ -1444,13 +1445,13 @@ public static bool TryParse(string s, IFormatProvider provider, DateTimeStyles s return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result); } - public static bool TryParse(ReadOnlySpan s, IFormatProvider provider, DateTimeStyles styles, out DateTime result) + public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, DateTimeStyles styles, out DateTime result) { DateTimeFormatInfo.ValidateStyles(styles, nameof(styles)); return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result); } - public static bool TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact(string? s, string? format, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); @@ -1463,13 +1464,13 @@ public static bool TryParseExact(string s, string format, IFormatProvider provid return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result); } - public static bool TryParseExact(ReadOnlySpan s, ReadOnlySpan format, IFormatProvider provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact(ReadOnlySpan s, ReadOnlySpan format, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result); } - public static bool TryParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact(string? s, string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); @@ -1482,7 +1483,7 @@ public static bool TryParseExact(string s, string[] formats, IFormatProvider pro return DateTimeParse.TryParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style, out result); } - public static bool TryParseExact(ReadOnlySpan s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result) + public static bool TryParseExact(ReadOnlySpan s, string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateTime result) { DateTimeFormatInfo.ValidateStyles(style, nameof(style)); return DateTimeParse.TryParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style, out result); @@ -1557,7 +1558,7 @@ public string[] GetDateTimeFormats() // Returns a string array containing all of the known date and time options for the // using the information provided by IFormatProvider. The strings returned are properly formatted date and // time strings for the current instance of DateTime. - public string[] GetDateTimeFormats(IFormatProvider provider) + public string[] GetDateTimeFormats(IFormatProvider? provider) { return (DateTimeFormat.GetAllDateTimes(this, DateTimeFormatInfo.GetInstance(provider))); } @@ -1574,7 +1575,7 @@ public string[] GetDateTimeFormats(char format) // Returns a string array containing all of the date and time options for the // given format format and given culture. The strings returned are properly formatted date and // time strings for the current instance of DateTime. - public string[] GetDateTimeFormats(char format, IFormatProvider provider) + public string[] GetDateTimeFormats(char format, IFormatProvider? provider) { return (DateTimeFormat.GetAllDateTimes(this, format, DateTimeFormatInfo.GetInstance(provider))); } @@ -1589,77 +1590,77 @@ public TypeCode GetTypeCode() } - bool IConvertible.ToBoolean(IFormatProvider provider) + bool IConvertible.ToBoolean(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Boolean")); } - char IConvertible.ToChar(IFormatProvider provider) + char IConvertible.ToChar(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Char")); } - sbyte IConvertible.ToSByte(IFormatProvider provider) + sbyte IConvertible.ToSByte(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "SByte")); } - byte IConvertible.ToByte(IFormatProvider provider) + byte IConvertible.ToByte(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Byte")); } - short IConvertible.ToInt16(IFormatProvider provider) + short IConvertible.ToInt16(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Int16")); } - ushort IConvertible.ToUInt16(IFormatProvider provider) + ushort IConvertible.ToUInt16(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "UInt16")); } - int IConvertible.ToInt32(IFormatProvider provider) + int IConvertible.ToInt32(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Int32")); } - uint IConvertible.ToUInt32(IFormatProvider provider) + uint IConvertible.ToUInt32(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "UInt32")); } - long IConvertible.ToInt64(IFormatProvider provider) + long IConvertible.ToInt64(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Int64")); } - ulong IConvertible.ToUInt64(IFormatProvider provider) + ulong IConvertible.ToUInt64(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "UInt64")); } - float IConvertible.ToSingle(IFormatProvider provider) + float IConvertible.ToSingle(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Single")); } - double IConvertible.ToDouble(IFormatProvider provider) + double IConvertible.ToDouble(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Double")); } - decimal IConvertible.ToDecimal(IFormatProvider provider) + decimal IConvertible.ToDecimal(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Decimal")); } - DateTime IConvertible.ToDateTime(IFormatProvider provider) + DateTime IConvertible.ToDateTime(IFormatProvider? provider) { return this; } - object IConvertible.ToType(Type type, IFormatProvider provider) + object IConvertible.ToType(Type type, IFormatProvider? provider) { return Convert.DefaultToType((IConvertible)this, type, provider); } diff --git a/src/System.Private.CoreLib/shared/System/DateTimeKind.cs b/src/System.Private.CoreLib/shared/System/DateTimeKind.cs index 33c9bd925fe2..1f2ce006d88c 100644 --- a/src/System.Private.CoreLib/shared/System/DateTimeKind.cs +++ b/src/System.Private.CoreLib/shared/System/DateTimeKind.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { // This enum is used to indentify DateTime instances in cases when they are known to be in local time, diff --git a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs index 6fc5dfc996d9..8b0ea368a67d 100644 --- a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs +++ b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; @@ -489,7 +490,7 @@ public static int Compare(DateTimeOffset first, DateTimeOffset second) // argument must be another DateTimeOffset, or otherwise an exception // occurs. Null is considered less than any instance. // - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { if (obj == null) return 1; if (!(obj is DateTimeOffset)) @@ -519,7 +520,7 @@ public int CompareTo(DateTimeOffset other) // is equal to the value of this DateTimeOffset. Returns false // otherwise. // - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is DateTimeOffset) { @@ -624,8 +625,8 @@ private DateTimeOffset(SerializationInfo info, StreamingContext context) throw new ArgumentNullException(nameof(info)); } - _dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); // Do not rename (binary serialization) - _offsetMinutes = (short)info.GetValue("OffsetMinutes", typeof(short)); // Do not rename (binary serialization) + _dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime))!; // Do not rename (binary serialization) + _offsetMinutes = (short)info.GetValue("OffsetMinutes", typeof(short))!; // Do not rename (binary serialization) } // Returns the hash code for this DateTimeOffset. @@ -655,13 +656,13 @@ public static DateTimeOffset Parse(string input) // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTimeOffset Parse(string input, IFormatProvider formatProvider) + public static DateTimeOffset Parse(string input, IFormatProvider? formatProvider) { if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); - return Parse(input, formatProvider, DateTimeStyles.None); + return Parse(input!, formatProvider, DateTimeStyles.None); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } - public static DateTimeOffset Parse(string input, IFormatProvider formatProvider, DateTimeStyles styles) + public static DateTimeOffset Parse(string input, IFormatProvider? formatProvider, DateTimeStyles styles) { styles = ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); @@ -674,7 +675,7 @@ public static DateTimeOffset Parse(string input, IFormatProvider formatProvider, return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset Parse(ReadOnlySpan input, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None) + public static DateTimeOffset Parse(ReadOnlySpan input, IFormatProvider? formatProvider = null, DateTimeStyles styles = DateTimeStyles.None) { styles = ValidateStyles(styles, nameof(styles)); DateTime dateResult = DateTimeParse.Parse(input, DateTimeFormatInfo.GetInstance(formatProvider), styles, out TimeSpan offset); @@ -685,18 +686,18 @@ public static DateTimeOffset Parse(ReadOnlySpan input, IFormatProvider for // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTimeOffset ParseExact(string input, string format, IFormatProvider formatProvider) + public static DateTimeOffset ParseExact(string input, string format, IFormatProvider? formatProvider) { if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format); - return ParseExact(input, format, formatProvider, DateTimeStyles.None); + return ParseExact(input!, format!, formatProvider, DateTimeStyles.None); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Constructs a DateTimeOffset from a string. The string must specify a // date and optionally a time in a culture-specific or universal format. // Leading and trailing whitespace characters are allowed. // - public static DateTimeOffset ParseExact(string input, string format, IFormatProvider formatProvider, DateTimeStyles styles) + public static DateTimeOffset ParseExact(string input, string format, IFormatProvider? formatProvider, DateTimeStyles styles) { styles = ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); @@ -711,14 +712,14 @@ public static DateTimeOffset ParseExact(string input, string format, IFormatProv return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset ParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider formatProvider, DateTimeStyles styles = DateTimeStyles.None) + public static DateTimeOffset ParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, DateTimeStyles styles = DateTimeStyles.None) { styles = ValidateStyles(styles, nameof(styles)); DateTime dateResult = DateTimeParse.ParseExact(input, format, DateTimeFormatInfo.GetInstance(formatProvider), styles, out TimeSpan offset); return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset ParseExact(string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles) + public static DateTimeOffset ParseExact(string input, string[] formats, IFormatProvider? formatProvider, DateTimeStyles styles) { styles = ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); @@ -732,7 +733,7 @@ public static DateTimeOffset ParseExact(string input, string[] formats, IFormatP return new DateTimeOffset(dateResult.Ticks, offset); } - public static DateTimeOffset ParseExact(ReadOnlySpan input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles = DateTimeStyles.None) + public static DateTimeOffset ParseExact(ReadOnlySpan input, string[] formats, IFormatProvider? formatProvider, DateTimeStyles styles = DateTimeStyles.None) { styles = ValidateStyles(styles, nameof(styles)); DateTime dateResult = DateTimeParse.ParseExactMultiple(input, formats, DateTimeFormatInfo.GetInstance(formatProvider), styles, out TimeSpan offset); @@ -800,22 +801,22 @@ public override string ToString() return DateTimeFormat.Format(ClockDateTime, null, null, Offset); } - public string ToString(string format) + public string ToString(string? format) { return DateTimeFormat.Format(ClockDateTime, format, null, Offset); } - public string ToString(IFormatProvider formatProvider) + public string ToString(IFormatProvider? formatProvider) { return DateTimeFormat.Format(ClockDateTime, null, formatProvider, Offset); } - public string ToString(string format, IFormatProvider formatProvider) + public string ToString(string? format, IFormatProvider? formatProvider) { return DateTimeFormat.Format(ClockDateTime, format, formatProvider, Offset); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider formatProvider = null) => + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? formatProvider = null) => DateTimeFormat.TryFormat(ClockDateTime, destination, out charsWritten, format, formatProvider, Offset); public DateTimeOffset ToUniversalTime() @@ -823,7 +824,7 @@ public DateTimeOffset ToUniversalTime() return new DateTimeOffset(UtcDateTime); } - public static bool TryParse(string input, out DateTimeOffset result) + public static bool TryParse(string? input, out DateTimeOffset result) { TimeSpan offset; DateTime dateResult; @@ -843,7 +844,7 @@ public static bool TryParse(ReadOnlySpan input, out DateTimeOffset result) return parsed; } - public static bool TryParse(string input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) + public static bool TryParse(string? input, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); if (input == null) @@ -863,7 +864,7 @@ public static bool TryParse(string input, IFormatProvider formatProvider, DateTi return parsed; } - public static bool TryParse(ReadOnlySpan input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) + public static bool TryParse(ReadOnlySpan input, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); bool parsed = DateTimeParse.TryParse(input, DateTimeFormatInfo.GetInstance(formatProvider), styles, out DateTime dateResult, out TimeSpan offset); @@ -871,7 +872,7 @@ public static bool TryParse(ReadOnlySpan input, IFormatProvider formatProv return parsed; } - public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, DateTimeStyles styles, + public static bool TryParseExact(string? input, string? format, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); @@ -894,7 +895,7 @@ public static bool TryParseExact(string input, string format, IFormatProvider fo } public static bool TryParseExact( - ReadOnlySpan input, ReadOnlySpan format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) + ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); bool parsed = DateTimeParse.TryParseExact(input, format, DateTimeFormatInfo.GetInstance(formatProvider), styles, out DateTime dateResult, out TimeSpan offset); @@ -902,7 +903,7 @@ public static bool TryParseExact( return parsed; } - public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles, + public static bool TryParseExact(string? input, string?[]? formats, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); @@ -925,7 +926,7 @@ public static bool TryParseExact(string input, string[] formats, IFormatProvider } public static bool TryParseExact( - ReadOnlySpan input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) + ReadOnlySpan input, string?[]? formats, IFormatProvider? formatProvider, DateTimeStyles styles, out DateTimeOffset result) { styles = ValidateStyles(styles, nameof(styles)); bool parsed = DateTimeParse.TryParseExactMultiple(input, formats, DateTimeFormatInfo.GetInstance(formatProvider), styles, out DateTime dateResult, out TimeSpan offset); diff --git a/src/System.Private.CoreLib/shared/System/DayOfWeek.cs b/src/System.Private.CoreLib/shared/System/DayOfWeek.cs index f67d10e18150..19cb69a796a4 100644 --- a/src/System.Private.CoreLib/shared/System/DayOfWeek.cs +++ b/src/System.Private.CoreLib/shared/System/DayOfWeek.cs @@ -11,6 +11,7 @@ ** ============================================================*/ +#nullable enable namespace System { public enum DayOfWeek diff --git a/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs index 342aec9a8acc..04eb9aa09b32 100644 --- a/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs +++ b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/Decimal.cs b/src/System.Private.CoreLib/shared/System/Decimal.cs index eb8c4cd07140..6f2a0a15c63e 100644 --- a/src/System.Private.CoreLib/shared/System/Decimal.cs +++ b/src/System.Private.CoreLib/shared/System/Decimal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers.Binary; using System.Diagnostics; using System.Globalization; @@ -345,7 +346,7 @@ public static int Compare(decimal d1, decimal d2) // null is considered to be less than any instance. // If object is not of type Decimal, this method throws an ArgumentException. // - public int CompareTo(object value) + public int CompareTo(object? value) { if (value == null) return 1; @@ -373,7 +374,7 @@ public static decimal Divide(decimal d1, decimal d2) // if the given object is a boxed Decimal and its value is equal to the // value of this Decimal. Returns false otherwise. // - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is decimal) { @@ -421,22 +422,22 @@ public override string ToString() return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo); } - public string ToString(string format) + public string ToString(string? format) { return Number.FormatDecimal(this, format, NumberFormatInfo.CurrentInfo); } - public string ToString(IFormatProvider provider) + public string ToString(IFormatProvider? provider) { return Number.FormatDecimal(this, null, NumberFormatInfo.GetInstance(provider)); } - public string ToString(string format, IFormatProvider provider) + public string ToString(string? format, IFormatProvider? provider) { return Number.FormatDecimal(this, format, NumberFormatInfo.GetInstance(provider)); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider provider = null) + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) { return Number.TryFormatDecimal(this, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten); } @@ -461,26 +462,26 @@ public static decimal Parse(string s, NumberStyles style) return Number.ParseDecimal(s, style, NumberFormatInfo.CurrentInfo); } - public static decimal Parse(string s, IFormatProvider provider) + public static decimal Parse(string s, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.GetInstance(provider)); } - public static decimal Parse(string s, NumberStyles style, IFormatProvider provider) + public static decimal Parse(string s, NumberStyles style, IFormatProvider? provider) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider)); } - public static decimal Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Number, IFormatProvider provider = null) + public static decimal Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Number, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider)); } - public static bool TryParse(string s, out decimal result) + public static bool TryParse(string? s, out decimal result) { if (s == null) { @@ -496,7 +497,7 @@ public static bool TryParse(ReadOnlySpan s, out decimal result) return Number.TryParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out result) == Number.ParsingStatus.OK; } - public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out decimal result) + public static bool TryParse(string? s, NumberStyles style, IFormatProvider? provider, out decimal result) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); @@ -509,7 +510,7 @@ public static bool TryParse(string s, NumberStyles style, IFormatProvider provid return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; } - public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider provider, out decimal result) + public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out decimal result) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK; @@ -1048,77 +1049,77 @@ public TypeCode GetTypeCode() return TypeCode.Decimal; } - bool IConvertible.ToBoolean(IFormatProvider provider) + bool IConvertible.ToBoolean(IFormatProvider? provider) { return Convert.ToBoolean(this); } - char IConvertible.ToChar(IFormatProvider provider) + char IConvertible.ToChar(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "Char")); } - sbyte IConvertible.ToSByte(IFormatProvider provider) + sbyte IConvertible.ToSByte(IFormatProvider? provider) { return Convert.ToSByte(this); } - byte IConvertible.ToByte(IFormatProvider provider) + byte IConvertible.ToByte(IFormatProvider? provider) { return Convert.ToByte(this); } - short IConvertible.ToInt16(IFormatProvider provider) + short IConvertible.ToInt16(IFormatProvider? provider) { return Convert.ToInt16(this); } - ushort IConvertible.ToUInt16(IFormatProvider provider) + ushort IConvertible.ToUInt16(IFormatProvider? provider) { return Convert.ToUInt16(this); } - int IConvertible.ToInt32(IFormatProvider provider) + int IConvertible.ToInt32(IFormatProvider? provider) { return Convert.ToInt32(this); } - uint IConvertible.ToUInt32(IFormatProvider provider) + uint IConvertible.ToUInt32(IFormatProvider? provider) { return Convert.ToUInt32(this); } - long IConvertible.ToInt64(IFormatProvider provider) + long IConvertible.ToInt64(IFormatProvider? provider) { return Convert.ToInt64(this); } - ulong IConvertible.ToUInt64(IFormatProvider provider) + ulong IConvertible.ToUInt64(IFormatProvider? provider) { return Convert.ToUInt64(this); } - float IConvertible.ToSingle(IFormatProvider provider) + float IConvertible.ToSingle(IFormatProvider? provider) { return Convert.ToSingle(this); } - double IConvertible.ToDouble(IFormatProvider provider) + double IConvertible.ToDouble(IFormatProvider? provider) { return Convert.ToDouble(this); } - decimal IConvertible.ToDecimal(IFormatProvider provider) + decimal IConvertible.ToDecimal(IFormatProvider? provider) { return this; } - DateTime IConvertible.ToDateTime(IFormatProvider provider) + DateTime IConvertible.ToDateTime(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "DateTime")); } - object IConvertible.ToType(Type type, IFormatProvider provider) + object IConvertible.ToType(Type type, IFormatProvider? provider) { return Convert.DefaultToType((IConvertible)this, type, provider); } diff --git a/src/System.Private.CoreLib/shared/System/Delegate.cs b/src/System.Private.CoreLib/shared/System/Delegate.cs index 1e8b8c967a7f..79c12c137374 100644 --- a/src/System.Private.CoreLib/shared/System/Delegate.cs +++ b/src/System.Private.CoreLib/shared/System/Delegate.cs @@ -11,13 +11,9 @@ namespace System { public abstract partial class Delegate : ICloneable, ISerializable { - private Delegate() - { - } - public virtual object Clone() => MemberwiseClone(); - public static Delegate? Combine(Delegate? a, Delegate? b) + public static Delegate? Combine(Delegate? a, Delegate? b) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (a is null) return b; @@ -25,7 +21,7 @@ private Delegate() return a.CombineImpl(b); } - public static Delegate? Combine(params Delegate?[]? delegates) + public static Delegate? Combine(params Delegate?[]? delegates) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (delegates == null || delegates.Length == 0) return null; @@ -37,8 +33,6 @@ private Delegate() return d; } - protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine); - // V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed. public static Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method) => CreateDelegate(type, firstArgument, method, throwOnBindFailure: true)!; @@ -53,19 +47,23 @@ private Delegate() public static Delegate CreateDelegate(Type type, Type target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true)!; public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!; +#if !CORERT + protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine); + + protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this; + + public virtual Delegate[] GetInvocationList() => new Delegate[] { this }; + public object? DynamicInvoke(params object?[]? args) { return DynamicInvokeImpl(args); } - - public virtual Delegate[] GetInvocationList() => new Delegate[] { this }; +#endif public virtual void GetObjectData(SerializationInfo info, StreamingContext context) => throw new PlatformNotSupportedException(); public MethodInfo Method => GetMethodImpl(); - protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this; - public static Delegate? Remove(Delegate? source, Delegate? value) { if (source == null) diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs index 893d7b8bc99a..ae15b8ec6727 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs @@ -12,6 +12,7 @@ ** ===========================================================*/ +#nullable enable namespace System.Diagnostics.CodeAnalysis { [AttributeUsage( @@ -23,17 +24,17 @@ namespace System.Diagnostics.CodeAnalysis [Conditional("CODE_ANALYSIS")] public sealed class SuppressMessageAttribute : Attribute { - public SuppressMessageAttribute(string category, string checkId) + public SuppressMessageAttribute(string? category, string? checkId) { Category = category; CheckId = checkId; } - public string Category { get; } - public string CheckId { get; } - public string Scope { get; set; } - public string Target { get; set; } - public string MessageId { get; set; } - public string Justification { get; set; } + public string? Category { get; } + public string? CheckId { get; } + public string? Scope { get; set; } + public string? Target { get; set; } + public string? MessageId { get; set; } + public string? Justification { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/ConditionalAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/ConditionalAttribute.cs index 416625b779d7..9af1e2b80db9 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/ConditionalAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/ConditionalAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Diagnostics { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)] diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Contracts/ContractFailedEventArgs.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Contracts/ContractFailedEventArgs.cs index 5e45bc50a310..ad19e849be5a 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Contracts/ContractFailedEventArgs.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Contracts/ContractFailedEventArgs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections.Generic; using System.Diagnostics; @@ -13,15 +14,15 @@ namespace System.Diagnostics.Contracts public sealed class ContractFailedEventArgs : EventArgs { private ContractFailureKind _failureKind; - private string _message; - private string _condition; - private Exception _originalException; + private string? _message; + private string? _condition; + private Exception? _originalException; private bool _handled; private bool _unwind; - internal Exception thrownDuringHandler; + internal Exception? thrownDuringHandler; - public ContractFailedEventArgs(ContractFailureKind failureKind, string message, string condition, Exception originalException) + public ContractFailedEventArgs(ContractFailureKind failureKind, string? message, string? condition, Exception? originalException) { Debug.Assert(originalException == null || failureKind == ContractFailureKind.PostconditionOnException); _failureKind = failureKind; @@ -30,10 +31,10 @@ public ContractFailedEventArgs(ContractFailureKind failureKind, string message, _originalException = originalException; } - public string Message { get { return _message; } } - public string Condition { get { return _condition; } } + public string? Message { get { return _message; } } + public string? Condition { get { return _condition; } } public ContractFailureKind FailureKind { get { return _failureKind; } } - public Exception OriginalException { get { return _originalException; } } + public Exception? OriginalException { get { return _originalException; } } // Whether the event handler "handles" this contract failure, or to fail via escalation policy. public bool Handled diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.cs index ff56ffbc6ae1..590588a27ed4 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // Do not remove this, it is needed to retain calls to these conditional methods in release builds #define DEBUG using System.Threading; @@ -73,13 +74,13 @@ public static void Unindent() } [System.Diagnostics.Conditional("DEBUG")] - public static void Print(string message) + public static void Print(string? message) { Write(message); } [System.Diagnostics.Conditional("DEBUG")] - public static void Print(string format, params object[] args) + public static void Print(string format, params object?[] args) { Write(string.Format(null, format, args)); } @@ -91,13 +92,13 @@ public static void Assert(bool condition) } [System.Diagnostics.Conditional("DEBUG")] - public static void Assert(bool condition, string message) + public static void Assert(bool condition, string? message) { Assert(condition, message, string.Empty); } [System.Diagnostics.Conditional("DEBUG")] - public static void Assert(bool condition, string message, string detailMessage) + public static void Assert(bool condition, string? message, string? detailMessage) { if (!condition) { @@ -121,55 +122,55 @@ internal static void ContractFailure(string message, string detailMessage, strin } [System.Diagnostics.Conditional("DEBUG")] - public static void Fail(string message) + public static void Fail(string? message) { Fail(message, string.Empty); } [System.Diagnostics.Conditional("DEBUG")] - public static void Fail(string message, string detailMessage) + public static void Fail(string? message, string? detailMessage) { s_provider.Fail(message, detailMessage); } [System.Diagnostics.Conditional("DEBUG")] - public static void Assert(bool condition, string message, string detailMessageFormat, params object[] args) + public static void Assert(bool condition, string? message, string detailMessageFormat, params object?[] args) { Assert(condition, message, string.Format(detailMessageFormat, args)); } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLine(string message) + public static void WriteLine(string? message) { s_provider.WriteLine(message); } [System.Diagnostics.Conditional("DEBUG")] - public static void Write(string message) + public static void Write(string? message) { s_provider.Write(message); } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLine(object value) + public static void WriteLine(object? value) { WriteLine(value?.ToString()); } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLine(object value, string category) + public static void WriteLine(object? value, string? category) { WriteLine(value?.ToString(), category); } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLine(string format, params object[] args) + public static void WriteLine(string format, params object?[] args) { WriteLine(string.Format(null, format, args)); } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLine(string message, string category) + public static void WriteLine(string? message, string? category) { if (category == null) { @@ -182,13 +183,13 @@ public static void WriteLine(string message, string category) } [System.Diagnostics.Conditional("DEBUG")] - public static void Write(object value) + public static void Write(object? value) { Write(value?.ToString()); } [System.Diagnostics.Conditional("DEBUG")] - public static void Write(string message, string category) + public static void Write(string? message, string? category) { if (category == null) { @@ -201,13 +202,13 @@ public static void Write(string message, string category) } [System.Diagnostics.Conditional("DEBUG")] - public static void Write(object value, string category) + public static void Write(object? value, string? category) { Write(value?.ToString(), category); } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteIf(bool condition, string message) + public static void WriteIf(bool condition, string? message) { if (condition) { @@ -216,7 +217,7 @@ public static void WriteIf(bool condition, string message) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteIf(bool condition, object value) + public static void WriteIf(bool condition, object? value) { if (condition) { @@ -225,7 +226,7 @@ public static void WriteIf(bool condition, object value) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteIf(bool condition, string message, string category) + public static void WriteIf(bool condition, string? message, string? category) { if (condition) { @@ -234,7 +235,7 @@ public static void WriteIf(bool condition, string message, string category) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteIf(bool condition, object value, string category) + public static void WriteIf(bool condition, object? value, string? category) { if (condition) { @@ -243,7 +244,7 @@ public static void WriteIf(bool condition, object value, string category) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLineIf(bool condition, object value) + public static void WriteLineIf(bool condition, object? value) { if (condition) { @@ -252,7 +253,7 @@ public static void WriteLineIf(bool condition, object value) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLineIf(bool condition, object value, string category) + public static void WriteLineIf(bool condition, object? value, string? category) { if (condition) { @@ -261,7 +262,7 @@ public static void WriteLineIf(bool condition, object value, string category) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLineIf(bool condition, string message) + public static void WriteLineIf(bool condition, string? message) { if (condition) { @@ -270,7 +271,7 @@ public static void WriteLineIf(bool condition, string message) } [System.Diagnostics.Conditional("DEBUG")] - public static void WriteLineIf(bool condition, string message, string category) + public static void WriteLineIf(bool condition, string? message, string? category) { if (condition) { diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Unix.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Unix.cs index e1517179ec17..bc3e86c9fc09 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; namespace System.Diagnostics @@ -10,7 +11,7 @@ public partial class DebugProvider { private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr") == "1"; - public static void FailCore(string stackTrace, string message, string detailMessage, string errorSource) + public static void FailCore(string stackTrace, string? message, string? detailMessage, string errorSource) { if (s_FailCore != null) { @@ -77,7 +78,7 @@ private static void WriteToStderr(string message) // We don't want to write UTF-16 to a file like standard error. Ideally we would transcode this // to UTF8, but the downside of that is it pulls in a bunch of stuff into what is ideally // a path with minimal dependencies (as to prevent re-entrency), so we'll take the strategy - // of just throwing away any non ASCII characters from the message and writing the rest + // of just throwing away any non ASCII characters from the message and writing the rest const int BufferLength = 256; diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Windows.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Windows.cs index 1eb445df1781..12ea0160a18f 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.Windows.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { public partial class DebugProvider { - public static void FailCore(string stackTrace, string message, string detailMessage, string errorSource) + public static void FailCore(string stackTrace, string? message, string? detailMessage, string errorSource) { if (s_FailCore != null) { @@ -58,7 +60,7 @@ public static void WriteCore(string message) // We don't want output from multiple threads to be interleaved. lock (s_ForLock) { - if (message == null || message.Length <= WriteChunkLength) + if (message.Length <= WriteChunkLength) { WriteToDebugger(message); } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.cs index 686fc18db3e2..3c762733c41c 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebugProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // Do not remove this, it is needed to retain calls to these conditional methods in release builds #define DEBUG @@ -12,7 +13,7 @@ namespace System.Diagnostics /// public partial class DebugProvider { - public virtual void Fail(string message, string detailMessage) + public virtual void Fail(string? message, string? detailMessage) { string stackTrace; try @@ -27,7 +28,7 @@ public virtual void Fail(string message, string detailMessage) FailCore(stackTrace, message, detailMessage, "Assertion Failed"); } - internal void WriteAssert(string stackTrace, string message, string detailMessage) + internal void WriteAssert(string stackTrace, string? message, string? detailMessage) { WriteLine(SR.DebugAssertBanner + Environment.NewLine + SR.DebugAssertShortMessage + Environment.NewLine @@ -37,7 +38,7 @@ internal void WriteAssert(string stackTrace, string message, string detailMessag + stackTrace); } - public virtual void Write(string message) + public virtual void Write(string? message) { lock (s_lock) { @@ -59,7 +60,7 @@ public virtual void Write(string message) } } - public virtual void WriteLine(string message) + public virtual void WriteLine(string? message) { Write(message + Environment.NewLine); } @@ -72,17 +73,17 @@ public virtual void OnIndentSizeChanged(int indentSize) { } private sealed class DebugAssertException : Exception { - internal DebugAssertException(string stackTrace) : + internal DebugAssertException(string? stackTrace) : base(Environment.NewLine + stackTrace) { } - internal DebugAssertException(string message, string stackTrace) : + internal DebugAssertException(string? message, string? stackTrace) : base(message + Environment.NewLine + Environment.NewLine + stackTrace) { } - internal DebugAssertException(string message, string detailMessage, string stackTrace) : + internal DebugAssertException(string? message, string? detailMessage, string? stackTrace) : base(message + Environment.NewLine + detailMessage + Environment.NewLine + Environment.NewLine + stackTrace) { } @@ -90,20 +91,20 @@ internal DebugAssertException(string message, string detailMessage, string stack private bool _needIndent = true; - private string _indentString; + private string? _indentString; private string GetIndentString() { int indentCount = Debug.IndentSize * Debug.IndentLevel; if (_indentString?.Length == indentCount) { - return _indentString; + return _indentString!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34942 } return _indentString = new string(' ', indentCount); } // internal and not readonly so that the tests can swap this out. - internal static Action s_FailCore = null; - internal static Action s_WriteCore = null; + internal static Action? s_FailCore = null; + internal static Action? s_WriteCore = null; } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggableAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggableAttribute.cs index d05f8471b364..308f6835b3e2 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggableAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { // Attribute class used by the compiler to mark modules. diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerBrowsableAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerBrowsableAttribute.cs index 8a53052b6fca..4bd42caa927b 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerBrowsableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerBrowsableAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { // DebuggerBrowsableState states are defined as follows: diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerDisplayAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerDisplayAttribute.cs index 7aae4b939742..5f670852c4c7 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerDisplayAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerDisplayAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { // This attribute is used to control what is displayed for the given class or field @@ -16,9 +18,9 @@ namespace System.Diagnostics [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Assembly, AllowMultiple = true)] public sealed class DebuggerDisplayAttribute : Attribute { - private Type _target; + private Type? _target; - public DebuggerDisplayAttribute(string value) + public DebuggerDisplayAttribute(string? value) { Value = value ?? ""; Name = ""; @@ -27,11 +29,11 @@ public DebuggerDisplayAttribute(string value) public string Value { get; } - public string Name { get; set; } + public string? Name { get; set; } - public string Type { get; set; } + public string? Type { get; set; } - public Type Target + public Type? Target { get => _target; set @@ -46,6 +48,6 @@ public Type Target } } - public string TargetTypeName { get; set; } + public string? TargetTypeName { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerHiddenAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerHiddenAttribute.cs index ace452e911c3..4ee79302c053 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerHiddenAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerHiddenAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerNonUserCodeAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerNonUserCodeAttribute.cs index 1b61cb726285..c4e87ab8f4c2 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerNonUserCodeAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerNonUserCodeAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Struct, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepThroughAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepThroughAttribute.cs index 82a164771e85..633e38d1b9ca 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepThroughAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepThroughAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { #if PROJECTN diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepperBoundaryAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepperBoundaryAttribute.cs index 647f2fdb00a1..1db7fba9a467 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepperBoundaryAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerStepperBoundaryAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { /// Indicates the code following the attribute is to be executed in run, not step, mode. diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerTypeProxyAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerTypeProxyAttribute.cs index 445834e05652..4795228dcbc7 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerTypeProxyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerTypeProxyAttribute.cs @@ -2,12 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)] public sealed class DebuggerTypeProxyAttribute : Attribute { - private Type _target; + private Type? _target; public DebuggerTypeProxyAttribute(Type type) { @@ -19,14 +21,14 @@ public DebuggerTypeProxyAttribute(Type type) ProxyTypeName = type.AssemblyQualifiedName; } - public DebuggerTypeProxyAttribute(string typeName) + public DebuggerTypeProxyAttribute(string? typeName) { ProxyTypeName = typeName; } - public string ProxyTypeName { get; } + public string? ProxyTypeName { get; } - public Type Target + public Type? Target { get => _target; set @@ -41,6 +43,6 @@ public Type Target } } - public string TargetTypeName { get; set; } + public string? TargetTypeName { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerVisualizerAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerVisualizerAttribute.cs index 032eca8a159c..dc1fbd252343 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerVisualizerAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/DebuggerVisualizerAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { /// @@ -11,20 +13,20 @@ namespace System.Diagnostics [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)] public sealed class DebuggerVisualizerAttribute : Attribute { - private Type _target; + private Type? _target; - public DebuggerVisualizerAttribute(string visualizerTypeName) + public DebuggerVisualizerAttribute(string? visualizerTypeName) { VisualizerTypeName = visualizerTypeName; } - public DebuggerVisualizerAttribute(string visualizerTypeName, string visualizerObjectSourceTypeName) + public DebuggerVisualizerAttribute(string? visualizerTypeName, string? visualizerObjectSourceTypeName) { VisualizerTypeName = visualizerTypeName; VisualizerObjectSourceTypeName = visualizerObjectSourceTypeName; } - public DebuggerVisualizerAttribute(string visualizerTypeName, Type visualizerObjectSource) + public DebuggerVisualizerAttribute(string? visualizerTypeName, Type visualizerObjectSource) { if (visualizerObjectSource == null) { @@ -60,7 +62,7 @@ public DebuggerVisualizerAttribute(Type visualizer, Type visualizerObjectSource) VisualizerObjectSourceTypeName = visualizerObjectSource.AssemblyQualifiedName; } - public DebuggerVisualizerAttribute(Type visualizer, string visualizerObjectSourceTypeName) + public DebuggerVisualizerAttribute(Type visualizer, string? visualizerObjectSourceTypeName) { if (visualizer == null) { @@ -71,13 +73,13 @@ public DebuggerVisualizerAttribute(Type visualizer, string visualizerObjectSourc VisualizerObjectSourceTypeName = visualizerObjectSourceTypeName; } - public string VisualizerObjectSourceTypeName { get; } + public string? VisualizerObjectSourceTypeName { get; } - public string VisualizerTypeName { get; } + public string? VisualizerTypeName { get; } - public string Description { get; set; } + public string? Description { get; set; } - public Type Target + public Type? Target { get => _target; set @@ -92,6 +94,6 @@ public Type Target } } - public string TargetTypeName { get; set; } + public string? TargetTypeName { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs index 8c3d7affc0d5..a39c35a8a030 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System.Reflection; @@ -15,7 +16,7 @@ public partial class StackFrame /// /// Reflection information for the method if available, null otherwise. /// - private MethodBase _method; + private MethodBase? _method; /// /// Native offset of the current instruction within the current method if available, @@ -32,7 +33,7 @@ public partial class StackFrame /// /// Source file name representing the current code location if available, null otherwise. /// - private string _fileName; + private string? _fileName; /// /// Line number representing the current code location if available, 0 otherwise. @@ -96,7 +97,7 @@ public StackFrame(int skipFrames, bool needFileInfo) /// name and line number. Use when you don't want to use the /// debugger's line mapping logic. /// - public StackFrame(string fileName, int lineNumber) + public StackFrame(string? fileName, int lineNumber) { InitMembers(); @@ -110,7 +111,7 @@ public StackFrame(string fileName, int lineNumber) /// name, line number and column number. Use when you don't want to /// use the debugger's line mapping logic. /// - public StackFrame(string fileName, int lineNumber, int colNumber) + public StackFrame(string? fileName, int lineNumber, int colNumber) : this (fileName, lineNumber) { _columnNumber = colNumber; @@ -126,7 +127,7 @@ public StackFrame(string fileName, int lineNumber, int colNumber) /// /// Returns the method the frame is executing /// - public virtual MethodBase GetMethod() + public virtual MethodBase? GetMethod() { return _method; } @@ -156,7 +157,7 @@ public virtual int GetILOffset() /// information is normally extracted from the debugging symbols /// for the executable. /// - public virtual string GetFileName() + public virtual string? GetFileName() { return _fileName; } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs index 7b612a43f52b..fccd9e1cf069 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/StackTrace.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Globalization; @@ -25,7 +26,7 @@ public partial class StackTrace /// /// Stack frames comprising this stack trace. /// - private StackFrame[] _stackFrames; + private StackFrame?[]? _stackFrames; /// /// Constructs a stack trace from the current location. @@ -145,7 +146,7 @@ public virtual int FrameCount /// Returns a given stack frame. Stack frames are numbered starting at /// zero, which is the last stack frame pushed. /// - public virtual StackFrame GetFrame(int index) + public virtual StackFrame? GetFrame(int index) { if (_stackFrames != null && index < _numOfFrames && index >= 0) return _stackFrames[index + _methodsToSkip]; @@ -159,7 +160,7 @@ public virtual StackFrame GetFrame(int index) /// The nth element of this array is the same as GetFrame(n). /// The length of the array is the same as FrameCount. /// - public virtual StackFrame[] GetFrames() + public virtual StackFrame?[]? GetFrames() { if (_stackFrames == null || _numOfFrames <= 0) return null; @@ -204,8 +205,8 @@ internal string ToString(TraceFormat traceFormat) StringBuilder sb = new StringBuilder(255); for (int iFrameIndex = 0; iFrameIndex < _numOfFrames; iFrameIndex++) { - StackFrame sf = GetFrame(iFrameIndex); - MethodBase mb = sf.GetMethod(); + StackFrame? sf = GetFrame(iFrameIndex); + MethodBase? mb = sf?.GetMethod(); if (mb != null && (ShowInStackTrace(mb) || (iFrameIndex == _numOfFrames - 1))) // Don't filter last frame { @@ -218,7 +219,7 @@ internal string ToString(TraceFormat traceFormat) sb.AppendFormat(CultureInfo.InvariantCulture, " {0} ", word_At); bool isAsync = false; - Type declaringType = mb.DeclaringType; + Type? declaringType = mb.DeclaringType; string methodName = mb.Name; bool methodChanged = false; if (declaringType != null && declaringType.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false)) @@ -226,7 +227,7 @@ internal string ToString(TraceFormat traceFormat) isAsync = typeof(IAsyncStateMachine).IsAssignableFrom(declaringType); if (isAsync || typeof(IEnumerator).IsAssignableFrom(declaringType)) { - methodChanged = TryResolveStateMachineMethod(ref mb, out declaringType); + methodChanged = TryResolveStateMachineMethod(ref mb!, out declaringType); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -265,7 +266,7 @@ internal string ToString(TraceFormat traceFormat) sb.Append(']'); } - ParameterInfo[] pi = null; + ParameterInfo[]? pi = null; try { pi = mb.GetParameters(); @@ -306,11 +307,11 @@ internal string ToString(TraceFormat traceFormat) } // source location printing - if (sf.GetILOffset() != -1) + if (sf!.GetILOffset() != -1) { // If we don't have a PDB or PDB-reading is disabled for the module, // then the file name will be null. - string fileName = sf.GetFileName(); + string? fileName = sf.GetFileName(); if (fileName != null) { @@ -349,13 +350,13 @@ private static bool TryResolveStateMachineMethod(ref MethodBase method, out Type declaringType = method.DeclaringType; - Type parentType = declaringType.DeclaringType; + Type? parentType = declaringType.DeclaringType; if (parentType == null) { return false; } - MethodInfo[] methods = parentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); + MethodInfo[]? methods = parentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (methods == null) { return false; @@ -363,7 +364,7 @@ private static bool TryResolveStateMachineMethod(ref MethodBase method, out Type foreach (MethodInfo candidateMethod in methods) { - IEnumerable attributes = candidateMethod.GetCustomAttributes(inherit: false); + IEnumerable? attributes = candidateMethod.GetCustomAttributes(inherit: false); if (attributes == null) { continue; diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs index 474274ac0851..d12a08906d95 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + namespace System.Diagnostics { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/SymbolStore/ISymbolDocumentWriter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/SymbolStore/ISymbolDocumentWriter.cs index 4980ed76f6cd..1db401fcc15a 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/SymbolStore/ISymbolDocumentWriter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/SymbolStore/ISymbolDocumentWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Diagnostics.SymbolStore { public interface ISymbolDocumentWriter diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs index 010cbd508fb3..0382556f3b56 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs @@ -20,22 +20,22 @@ namespace System.Diagnostics.Tracing internal class CounterGroup { private readonly EventSource _eventSource; - private readonly List _counters; + private readonly List _counters; internal CounterGroup(EventSource eventSource) { _eventSource = eventSource; - _counters = new List(); + _counters = new List(); RegisterCommandCallback(); } - internal void Add(BaseCounter eventCounter) + internal void Add(DiagnosticCounter eventCounter) { lock (this) // Lock the CounterGroup _counters.Add(eventCounter); } - internal void Remove(BaseCounter eventCounter) + internal void Remove(DiagnosticCounter eventCounter) { lock (this) // Lock the CounterGroup _counters.Remove(eventCounter); diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs index ae4a1a7280f2..1be7d5494ae9 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs @@ -17,52 +17,6 @@ namespace Microsoft.Diagnostics.Tracing namespace System.Diagnostics.Tracing #endif { - // TODO: This should be removed as we make the new payloads public - [EventData] - internal class EventCounterPayload : IEnumerable> - { - public string Name { get; set; } - - public float Mean { get; set; } - - public float StandardDeviation { get; set; } - - public int Count { get; set; } - - public float Min { get; set; } - - public float Max { get; set; } - - public float IntervalSec { get; internal set; } - - #region Implementation of the IEnumerable interface - - public IEnumerator> GetEnumerator() - { - return ForEnumeration.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ForEnumeration.GetEnumerator(); - } - - private IEnumerable> ForEnumeration - { - get - { - yield return new KeyValuePair("Name", Name); - yield return new KeyValuePair("Mean", Mean); - yield return new KeyValuePair("StandardDeviation", StandardDeviation); - yield return new KeyValuePair("Count", Count); - yield return new KeyValuePair("Min", Min); - yield return new KeyValuePair("Max", Max); - } - } - - #endregion // Implementation of the IEnumerable interface - } - [EventData] internal class CounterPayload : IEnumerable> { @@ -70,19 +24,19 @@ internal class CounterPayload : IEnumerable> public string DisplayName { get; set; } - public float Mean { get; set; } + public double Mean { get; set; } - public float StandardDeviation { get; set; } + public double StandardDeviation { get; set; } public int Count { get; set; } - public float Min { get; set; } + public double Min { get; set; } - public float Max { get; set; } + public double Max { get; set; } public float IntervalSec { get; internal set; } - public string MetaData { get; set; } + public string Metadata { get; set; } #region Implementation of the IEnumerable interface @@ -110,7 +64,7 @@ private IEnumerable> ForEnumeration yield return new KeyValuePair("IntervalSec", IntervalSec); yield return new KeyValuePair("Series", $"Interval={IntervalSec}"); yield return new KeyValuePair("CounterType", "Mean"); - yield return new KeyValuePair("MetaData", MetaData); + yield return new KeyValuePair("Metadata", Metadata); } } @@ -126,11 +80,11 @@ internal class IncrementingCounterPayload : IEnumerable> ForEnumeration yield return new KeyValuePair("IntervalSec", IntervalSec); yield return new KeyValuePair("Series", $"Interval={IntervalSec}"); yield return new KeyValuePair("CounterType", "Sum"); - yield return new KeyValuePair("MetaData", MetaData); + yield return new KeyValuePair("Metadata", Metadata); } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs similarity index 71% rename from src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs rename to src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs index 447852e84a99..ea4cb92612b1 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs @@ -19,10 +19,10 @@ namespace System.Diagnostics.Tracing #endif { /// - /// BaseCounter is an abstract class that serves as the parent class for various Counter* classes, + /// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes, /// namely EventCounter, PollingCounter, IncrementingEventCounter, and IncrementingPollingCounter. /// - public abstract class BaseCounter : IDisposable + public abstract class DiagnosticCounter : IDisposable { /// /// All Counters live as long as the EventSource that they are attached to unless they are @@ -30,23 +30,22 @@ public abstract class BaseCounter : IDisposable /// /// The name. /// The event source. - public BaseCounter(string name, EventSource eventSource) + public DiagnosticCounter(string name, EventSource eventSource) { if (name == null) { - throw new ArgumentNullException(nameof(_name)); + throw new ArgumentNullException(nameof(Name)); } if (eventSource == null) { - throw new ArgumentNullException(nameof(eventSource)); + throw new ArgumentNullException(nameof(EventSource)); } _group = CounterGroup.GetCounterGroup(eventSource); _group.Add(this); - _eventSource = eventSource; - _name = name; - _metaData = new Dictionary(); + Name = name; + EventSource = eventSource; } /// @@ -67,38 +66,45 @@ public void Dispose() /// /// Adds a key-value metadata to the EventCounter that will be included as a part of the payload /// - internal void AddMetaData(string key, string value) + public void AddMetadata(string key, string value) { lock (MyLock) { - _metaData.Add(key, value); + _metadata = _metadata ?? new Dictionary(); + _metadata.Add(key, value); } } - internal string DisplayName { get; set; } + public string DisplayName { get; set; } - #region private implementation + public string Name { get; } + + public EventSource EventSource { get; } - internal readonly string _name; + #region private implementation private CounterGroup _group; - private Dictionary _metaData; - internal EventSource _eventSource; + private Dictionary _metadata; internal abstract void WritePayload(float intervalSec); // arbitrarily we use name as the lock object. - internal object MyLock { get { return _name; } } + internal object MyLock { get { return Name; } } internal void ReportOutOfBandMessage(string message) { - _eventSource.ReportOutOfBandMessage(message, true); + EventSource.ReportOutOfBandMessage(message, true); } - internal string GetMetaDataString() + internal string GetMetadataString() { + if (_metadata == null) + { + return ""; + } + StringBuilder sb = new StringBuilder(""); - foreach(KeyValuePair kvPair in _metaData) + foreach(KeyValuePair kvPair in _metadata) { sb.Append($"{kvPair.Key}:{kvPair.Value},"); } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs index 85fc40a08cc6..a9fc0895c9a8 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs @@ -26,7 +26,7 @@ namespace System.Diagnostics.Tracing /// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs /// which shows tests, which are also useful in seeing actual use. /// - public partial class EventCounter : BaseCounter + public partial class EventCounter : DiagnosticCounter { /// /// Initializes a new instance of the class. @@ -37,8 +37,8 @@ public partial class EventCounter : BaseCounter /// The event source. public EventCounter(string name, EventSource eventSource) : base(name, eventSource) { - _min = float.PositiveInfinity; - _max = float.NegativeInfinity; + _min = double.PositiveInfinity; + _max = double.NegativeInfinity; InitializeBuffer(); } @@ -49,22 +49,27 @@ public EventCounter(string name, EventSource eventSource) : base(name, eventSour /// /// The value. public void WriteMetric(float value) + { + Enqueue((double)value); + } + + public void WriteMetric(double value) { Enqueue(value); } - public override string ToString() => $"EventCounter '{_name}' Count {_count} Mean {(((double)_sum) / _count).ToString("n3")}"; + public override string ToString() => $"EventCounter '{Name}' Count {_count} Mean {(_sum / _count).ToString("n3")}"; #region Statistics Calculation // Statistics private int _count; - private float _sum; - private float _sumSquared; - private float _min; - private float _max; + private double _sum; + private double _sumSquared; + private double _min; + private double _max; - internal void OnMetricWritten(float value) + internal void OnMetricWritten(double value) { Debug.Assert(Monitor.IsEntered(MyLock)); _sum += value; @@ -83,14 +88,13 @@ internal override void WritePayload(float intervalSec) lock (MyLock) { Flush(); - EventCounterPayload payload = new EventCounterPayload(); - payload.Name = _name; + CounterPayload payload = new CounterPayload(); payload.Count = _count; payload.IntervalSec = intervalSec; if (0 < _count) { payload.Mean = _sum / _count; - payload.StandardDeviation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count); + payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count); } else { @@ -99,8 +103,12 @@ internal override void WritePayload(float intervalSec) } payload.Min = _min; payload.Max = _max; + + payload.Metadata = GetMetadataString(); + payload.DisplayName = DisplayName; + payload.Name = Name; ResetStatistics(); - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new EventCounterPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new CounterPayloadType(payload)); } } private void ResetStatistics() @@ -109,35 +117,35 @@ private void ResetStatistics() _count = 0; _sum = 0; _sumSquared = 0; - _min = float.PositiveInfinity; - _max = float.NegativeInfinity; + _min = double.PositiveInfinity; + _max = double.NegativeInfinity; } #endregion // Statistics Calculation // Values buffering private const int BufferedSize = 10; - private const float UnusedBufferSlotValue = float.NegativeInfinity; + private const double UnusedBufferSlotValue = double.NegativeInfinity; private const int UnsetIndex = -1; - private volatile float[] _bufferedValues; + private volatile double[] _bufferedValues; private volatile int _bufferedValuesIndex; private void InitializeBuffer() { - _bufferedValues = new float[BufferedSize]; + _bufferedValues = new double[BufferedSize]; for (int i = 0; i < _bufferedValues.Length; i++) { _bufferedValues[i] = UnusedBufferSlotValue; } } - protected void Enqueue(float value) + private void Enqueue(double value) { // It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay. int i = _bufferedValuesIndex; while (true) { - float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue); + double result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue); i++; if (_bufferedValues.Length <= i) { @@ -178,10 +186,10 @@ protected void Flush() /// This is the payload that is sent in the with EventSource.Write /// [EventData] - class EventCounterPayloadType + class CounterPayloadType { - public EventCounterPayloadType(EventCounterPayload payload) { Payload = payload; } - public EventCounterPayload Payload { get; set; } + public CounterPayloadType(CounterPayload payload) { Payload = payload; } + public CounterPayload Payload { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs index 345a9cf66cd9..a8622a8fb817 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs @@ -63,7 +63,7 @@ internal enum ControllerCommand #if ES_BUILD_STANDALONE [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] #endif - internal partial class EventProvider : IDisposable + internal class EventProvider : IDisposable { // This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what // subclasses of EventProvider use when creating efficient (but unsafe) version of @@ -92,10 +92,8 @@ internal SessionInfo(int sessionIdBit_, int etwSessionId_) { sessionIdBit = sessionIdBit_; etwSessionId = etwSessionId_; } } - private static bool m_setInformationMissing; - internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions. - UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function + Interop.Advapi32.EtwEnableCallback m_etwCallback; // Trace Callback function private long m_regHandle; // Trace Registration Handle private byte m_level; // Tracing Level private long m_anyKeywordMask; // Trace Enable Flags @@ -165,14 +163,14 @@ internal EventProvider(EventProviderType providerType) /// reason the ETW Register call failed a NotSupported exception will be thrown. /// // - // + // // // // internal unsafe void Register(EventSource eventSource) { uint status; - m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack); + m_etwCallback = new Interop.Advapi32.EtwEnableCallback(EtwEnableCallBack); status = EventRegister(eventSource, m_etwCallback); if (status != 0) @@ -264,13 +262,13 @@ public virtual void Close() // // unsafe void EtwEnableCallBack( - [In] ref System.Guid sourceId, - [In] int controlCode, - [In] byte setLevel, - [In] long anyKeyword, - [In] long allKeyword, - [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, - [In] void* callbackContext + in System.Guid sourceId, + int controlCode, + byte setLevel, + long anyKeyword, + long allKeyword, + Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, + void* callbackContext ) { // This is an optional callback API. We will therefore ignore any failures that happen as a @@ -281,7 +279,7 @@ [In] void* callbackContext ControllerCommand command = ControllerCommand.Update; IDictionary args = null; bool skipFinalOnControllerCommand = false; - if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_ENABLE_PROVIDER) + if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_ENABLE_PROVIDER) { m_enabled = true; m_level = setLevel; @@ -342,7 +340,7 @@ [In] void* callbackContext OnControllerCommand(command, args, (bEnabling ? sessionChanged : -sessionChanged), etwSessionId); } } - else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_DISABLE_PROVIDER) + else if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_DISABLE_PROVIDER) { m_enabled = false; m_level = 0; @@ -350,7 +348,7 @@ [In] void* callbackContext m_allKeywordMask = 0; m_liveSessions = null; } - else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_CAPTURE_STATE) + else if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_CAPTURE_STATE) { command = ControllerCommand.SendManifest; } @@ -491,24 +489,24 @@ private unsafe void GetSessionInfo(SessionInfoCallback action, ref ListInstanceCount; i++) { if (providerInstance->Pid == processId) { - var enabledInfos = (UnsafeNativeMethods.ManifestEtw.TRACE_ENABLE_INFO*)&providerInstance[1]; + var enabledInfos = (Interop.Advapi32.TRACE_ENABLE_INFO*)&providerInstance[1]; // iterate over the list of active ETW sessions "listening" to the current provider for (int j = 0; j < providerInstance->EnableCount; j++) action(enabledInfos[j].LoggerId, enabledInfos[j].MatchAllKeyword, ref sessionList); @@ -517,7 +515,7 @@ private unsafe void GetSessionInfo(SessionInfoCallback action, ref ListNextOffset && providerInstance->NextOffset < buffSize); var structBase = (byte*)providerInstance; - providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset]; + providerInstance = (Interop.Advapi32.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset]; } #else #if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds... @@ -602,7 +600,7 @@ private static int IndexOfSessionInList(List sessions, int etwSessi /// starts, and the command being issued associated with that data. /// private unsafe bool GetDataFromController(int etwSessionId, - UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart) + Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart) { data = null; dataStart = 0; @@ -704,18 +702,9 @@ public static WriteEventErrorCode GetLastWriteEventError() // // Helper function to set the last error on the thread // - private static void SetLastError(int error) + private static void SetLastError(WriteEventErrorCode error) { - switch (error) - { - case UnsafeNativeMethods.ManifestEtw.ERROR_ARITHMETIC_OVERFLOW: - case UnsafeNativeMethods.ManifestEtw.ERROR_MORE_DATA: - s_returnCode = WriteEventErrorCode.EventTooBig; - break; - case UnsafeNativeMethods.ManifestEtw.ERROR_NOT_ENOUGH_MEMORY: - s_returnCode = WriteEventErrorCode.NoFreeBuffers; - break; - } + s_returnCode = error; } // @@ -961,7 +950,7 @@ to fill the passed in ETW data descriptor. /// Payload for the ETW event. /// // - // + // // // // @@ -981,7 +970,7 @@ to fill the passed in ETW data descriptor. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload) { - int status = 0; + WriteEventErrorCode status = WriteEventErrorCode.NoError; if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords)) { @@ -1109,7 +1098,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even userDataPtr[refObjPosition[7]].Ptr = (ulong)v7; } - status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData); + status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData); } } else @@ -1135,7 +1124,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even } } - status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData); + status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData); for (int i = 0; i < refObjIndex; ++i) { @@ -1145,9 +1134,9 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even } } - if (status != 0) + if (status != WriteEventErrorCode.NoError) { - SetLastError((int)status); + SetLastError(status); return false; } @@ -1174,7 +1163,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even /// pointer do the event data /// // - // + // // [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data) @@ -1188,7 +1177,7 @@ internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, I (EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop); } - int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data); + WriteEventErrorCode status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data); if (status != 0) { @@ -1207,29 +1196,30 @@ internal unsafe bool WriteEventRaw( int dataCount, IntPtr data) { - int status; + WriteEventErrorCode status; - status = m_eventProvider.EventWriteTransferWrapper( + status = m_eventProvider.EventWriteTransfer( m_regHandle, - ref eventDescriptor, + in eventDescriptor, eventHandle, activityID, relatedActivityID, dataCount, (EventData*)data); - if (status != 0) + if (status != WriteEventErrorCode.NoError) { SetLastError(status); return false; } + return true; } // These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work // either with Manifest ETW or Classic ETW (if Manifest based ETW is not available). - private unsafe uint EventRegister(EventSource eventSource, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback) + private unsafe uint EventRegister(EventSource eventSource, Interop.Advapi32.EtwEnableCallback enableCallback) { m_providerName = eventSource.Name; m_providerId = eventSource.Guid; @@ -1241,6 +1231,36 @@ private uint EventUnregister(long registrationHandle) { return m_eventProvider.EventUnregister(registrationHandle); } + +#if PLATFORM_WINDOWS + private static bool m_setInformationMissing; + + internal unsafe int SetInformation( + Interop.Advapi32.EVENT_INFO_CLASS eventInfoClass, + IntPtr data, + uint dataSize) + { + int status = Interop.Errors.ERROR_NOT_SUPPORTED; + + if (!m_setInformationMissing) + { + try + { + status = Interop.Advapi32.EventSetInformation( + m_regHandle, + eventInfoClass, + (void*)data, + (int)dataSize); + } + catch (TypeLoadException) + { + m_setInformationMissing = true; + } + } + + return status; + } +#endif } #if PLATFORM_WINDOWS @@ -1251,13 +1271,13 @@ internal sealed class EtwEventProvider : IEventProvider // Register an event provider. unsafe uint IEventProvider.EventRegister( EventSource eventSource, - UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + Interop.Advapi32.EtwEnableCallback enableCallback, void* callbackContext, ref long registrationHandle) { Guid providerId = eventSource.Guid; - return UnsafeNativeMethods.ManifestEtw.EventRegister( - ref providerId, + return Interop.Advapi32.EventRegister( + in providerId, enableCallback, callbackContext, ref registrationHandle); @@ -1266,32 +1286,43 @@ unsafe uint IEventProvider.EventRegister( // Unregister an event provider. uint IEventProvider.EventUnregister(long registrationHandle) { - return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle); + return Interop.Advapi32.EventUnregister(registrationHandle); } // Write an event. - unsafe int IEventProvider.EventWriteTransferWrapper( + unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer( long registrationHandle, - ref EventDescriptor eventDescriptor, + in EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityId, Guid* relatedActivityId, int userDataCount, EventProvider.EventData* userData) { - return UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper( + int error = Interop.Advapi32.EventWriteTransfer( registrationHandle, - ref eventDescriptor, + in eventDescriptor, activityId, relatedActivityId, userDataCount, userData); + + switch (error) + { + case Interop.Errors.ERROR_ARITHMETIC_OVERFLOW: + case Interop.Errors.ERROR_MORE_DATA: + return EventProvider.WriteEventErrorCode.EventTooBig; + case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY: + return EventProvider.WriteEventErrorCode.NoFreeBuffers; + } + + return EventProvider.WriteEventErrorCode.NoError; } // Get or set the per-thread activity ID. - int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId) + int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId) { - return UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( + return Interop.Advapi32.EventActivityIdControl( ControlCode, ref ActivityId); } @@ -1308,7 +1339,7 @@ internal sealed class NoOpEventProvider : IEventProvider { unsafe uint IEventProvider.EventRegister( EventSource eventSource, - UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + Interop.Advapi32.EtwEnableCallback enableCallback, void* callbackContext, ref long registrationHandle) { @@ -1320,19 +1351,19 @@ uint IEventProvider.EventUnregister(long registrationHandle) return 0; } - unsafe int IEventProvider.EventWriteTransferWrapper( + unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer( long registrationHandle, - ref EventDescriptor eventDescriptor, + in EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityId, Guid* relatedActivityId, int userDataCount, EventProvider.EventData* userData) { - return 0; + return EventProvider.WriteEventErrorCode.NoError; } - int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId) + int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId) { return 0; } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs index 95ac1da80d13..50343b4c5f3d 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs @@ -132,8 +132,7 @@ // where it will write it to // // All ETW writes eventually call -// EventWriteTransfer (native PINVOKE wrapper) -// EventWriteTransferWrapper (fixes compat problem if you pass null as the related activityID) +// EventWriteTransfer // EventProvider.WriteEventRaw - sets last error // EventSource.WriteEventRaw - Does EventSource exception handling logic // WriteMultiMerge @@ -499,6 +498,123 @@ public event EventHandler EventCommandExecuted } } +#region ActivityID + + /// + /// When a thread starts work that is on behalf of 'something else' (typically another + /// thread or network request) it should mark the thread as working on that other work. + /// This API marks the current thread as working on activity 'activityID'. This API + /// should be used when the caller knows the thread's current activity (the one being + /// overwritten) has completed. Otherwise, callers should prefer the overload that + /// return the oldActivityThatWillContinue (below). + /// + /// All events created with the EventSource on this thread are also tagged with the + /// activity ID of the thread. + /// + /// It is common, and good practice after setting the thread to an activity to log an event + /// with a 'start' opcode to indicate that precise time/thread where the new activity + /// started. + /// + /// A Guid that represents the new activity with which to mark + /// the current thread + public static void SetCurrentThreadActivityId(Guid activityId) + { + if (TplEventSource.Log != null) + TplEventSource.Log.SetActivityId(activityId); + + // We ignore errors to keep with the convention that EventSources do not throw errors. + // Note we can't access m_throwOnWrites because this is a static method. +#if FEATURE_MANAGED_ETW +#if FEATURE_PERFTRACING + // Set the activity id via EventPipe. + EventPipeInternal.EventActivityIdControl( + (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, + ref activityId); +#endif // FEATURE_PERFTRACING +#if PLATFORM_WINDOWS + // Set the activity id via ETW. + Interop.Advapi32.EventActivityIdControl( + Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, + ref activityId); +#endif // PLATFORM_WINDOWS +#endif // FEATURE_MANAGED_ETW + } + + /// + /// Retrieves the ETW activity ID associated with the current thread. + /// + public static Guid CurrentThreadActivityId + { + get + { + // We ignore errors to keep with the convention that EventSources do not throw + // errors. Note we can't access m_throwOnWrites because this is a static method. + Guid retVal = new Guid(); +#if FEATURE_MANAGED_ETW +#if PLATFORM_WINDOWS + Interop.Advapi32.EventActivityIdControl( + Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, + ref retVal); +#elif FEATURE_PERFTRACING + EventPipeInternal.EventActivityIdControl( + (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, + ref retVal); +#endif // PLATFORM_WINDOWS +#endif // FEATURE_MANAGED_ETW + return retVal; + } + } + + /// + /// When a thread starts work that is on behalf of 'something else' (typically another + /// thread or network request) it should mark the thread as working on that other work. + /// This API marks the current thread as working on activity 'activityID'. It returns + /// whatever activity the thread was previously marked with. There is a convention that + /// callers can assume that callees restore this activity mark before the callee returns. + /// To encourage this, this API returns the old activity, so that it can be restored later. + /// + /// All events created with the EventSource on this thread are also tagged with the + /// activity ID of the thread. + /// + /// It is common, and good practice after setting the thread to an activity to log an event + /// with a 'start' opcode to indicate that precise time/thread where the new activity + /// started. + /// + /// A Guid that represents the new activity with which to mark + /// the current thread + /// The Guid that represents the current activity + /// which will continue at some point in the future, on the current thread + public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue) + { + oldActivityThatWillContinue = activityId; +#if FEATURE_MANAGED_ETW + // We ignore errors to keep with the convention that EventSources do not throw errors. + // Note we can't access m_throwOnWrites because this is a static method. + +#if FEATURE_PERFTRACING && PLATFORM_WINDOWS + EventPipeInternal.EventActivityIdControl( + (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, + ref oldActivityThatWillContinue); +#elif FEATURE_PERFTRACING + EventPipeInternal.EventActivityIdControl( + (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, + ref oldActivityThatWillContinue); +#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS + +#if PLATFORM_WINDOWS + Interop.Advapi32.EventActivityIdControl( + Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, + ref oldActivityThatWillContinue); +#endif // PLATFORM_WINDOWS +#endif // FEATURE_MANAGED_ETW + + // We don't call the activityDying callback here because the caller has declared that + // it is not dying. + if (TplEventSource.Log != null) + TplEventSource.Log.SetActivityId(activityId); + } +#endregion + #region protected /// /// This is the constructor that most users will use to create their eventSource. It takes @@ -1390,7 +1506,7 @@ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, str IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject(); setInformationResult = m_etwProvider.SetInformation( - UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits, + Interop.Advapi32.EVENT_INFO_CLASS.SetTraits, providerMetadata, (uint)this.providerMetadata.Length); @@ -2321,12 +2437,40 @@ For now I'm simply marking them as public again.A cleaner solution might be to u root them and modify shared library definition to force export them. */ #if ES_BUILD_PN - public + public #else - internal + internal #endif partial struct EventMetadata { +#if ES_BUILD_PN + public EventMetadata(EventDescriptor descriptor, + EventTags tags, + bool enabledForAnyListener, + bool enabledForETW, + string name, + string message, + EventParameterType[] parameterTypes) + { + this.Descriptor = descriptor; + this.Tags = tags; + this.EnabledForAnyListener = enabledForAnyListener; + this.EnabledForETW = enabledForETW; +#if FEATURE_PERFTRACING + this.EnabledForEventPipe = false; +#endif + this.TriggersActivityTracking = 0; + this.Name = name; + this.Message = message; + this.Parameters = null; + this.TraceLoggingEventTypes = null; + this.ActivityOptions = EventActivityOptions.None; + this.ParameterTypes = parameterTypes; + this.HasRelatedActivityID = false; + this.EventHandle = IntPtr.Zero; + } +#endif + public EventDescriptor Descriptor; public IntPtr EventHandle; // EventPipeEvent handle. public EventTags Tags; @@ -2352,6 +2496,114 @@ partial struct EventMetadata #endif }; +#if !ES_BUILD_PN + private int GetParameterCount(EventMetadata eventData) + { + return eventData.Parameters.Length; + } + + private Type GetDataType(EventMetadata eventData, int parameterId) + { + return eventData.Parameters[parameterId].ParameterType; + } + + private static readonly bool m_EventSourcePreventRecursion = false; +#else + private int GetParameterCount(EventMetadata eventData) + { + int paramCount; + if(eventData.Parameters == null) + { + paramCount = eventData.ParameterTypes.Length; + } + else + { + paramCount = eventData.Parameters.Length; + } + + return paramCount; + } + + private Type GetDataType(EventMetadata eventData, int parameterId) + { + Type dataType; + if(eventData.Parameters == null) + { + dataType = EventTypeToType(eventData.ParameterTypes[parameterId]); + } + else + { + dataType = eventData.Parameters[parameterId].ParameterType; + } + + return dataType; + } + + private static readonly bool m_EventSourcePreventRecursion = true; + + public enum EventParameterType + { + Boolean, + Byte, + SByte, + Char, + Int16, + UInt16, + Int32, + UInt32, + Int64, + UInt64, + IntPtr, + Single, + Double, + Decimal, + Guid, + String + } + + private Type EventTypeToType(EventParameterType type) + { + switch (type) + { + case EventParameterType.Boolean: + return typeof(bool); + case EventParameterType.Byte: + return typeof(byte); + case EventParameterType.SByte: + return typeof(sbyte); + case EventParameterType.Char: + return typeof(char); + case EventParameterType.Int16: + return typeof(short); + case EventParameterType.UInt16: + return typeof(ushort); + case EventParameterType.Int32: + return typeof(int); + case EventParameterType.UInt32: + return typeof(uint); + case EventParameterType.Int64: + return typeof(long); + case EventParameterType.UInt64: + return typeof(ulong); + case EventParameterType.IntPtr: + return typeof(IntPtr); + case EventParameterType.Single: + return typeof(float); + case EventParameterType.Double: + return typeof(double); + case EventParameterType.Decimal: + return typeof(decimal); + case EventParameterType.Guid: + return typeof(Guid); + case EventParameterType.String: + return typeof(string); + default: + // TODO: should I throw an exception here? + return null; + } + } +#endif + // This is the internal entry point that code:EventListeners call when wanting to send a command to a // eventSource. The logic is as follows // @@ -5102,7 +5354,7 @@ public enum EventManifestOptions /// ManifestBuilder is designed to isolate the details of the message of the event from the /// rest of EventSource. This one happens to create XML. /// - internal partial class ManifestBuilder + internal class ManifestBuilder { /// /// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'. @@ -5839,7 +6091,46 @@ private string GetTypeName(Type type) return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned. } - return GetTypeNameHelper(type); + switch (type.GetTypeCode()) + { + case TypeCode.Boolean: + return "win:Boolean"; + case TypeCode.Byte: + return "win:UInt8"; + case TypeCode.Char: + case TypeCode.UInt16: + return "win:UInt16"; + case TypeCode.UInt32: + return "win:UInt32"; + case TypeCode.UInt64: + return "win:UInt64"; + case TypeCode.SByte: + return "win:Int8"; + case TypeCode.Int16: + return "win:Int16"; + case TypeCode.Int32: + return "win:Int32"; + case TypeCode.Int64: + return "win:Int64"; + case TypeCode.String: + return "win:UnicodeString"; + case TypeCode.Single: + return "win:Float"; + case TypeCode.Double: + return "win:Double"; + case TypeCode.DateTime: + return "win:FILETIME"; + default: + if (type == typeof(Guid)) + return "win:GUID"; + else if (type == typeof(IntPtr)) + return "win:Pointer"; + else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte)) + return "win:Binary"; + + ManifestError(SR.Format(SR.EventSource_UnsupportedEventTypeInManifest, type.Name), true); + return string.Empty; + } } private static void UpdateStringBuilder(ref StringBuilder stringBuilder, string eventMessage, int startIndex, int count) diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs index 2e821ac10da4..f5f9ba13b1a0 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. #nullable enable +using System; using System.Runtime.Serialization; #if ES_BUILD_STANDALONE diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs index 9bbebc79ed23..bc7ab9aee002 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs @@ -17,7 +17,7 @@ internal interface IEventProvider // Register an event provider. unsafe uint EventRegister( EventSource eventSource, - UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + Interop.Advapi32.EtwEnableCallback enableCallback, void* callbackContext, ref long registrationHandle); @@ -25,9 +25,9 @@ unsafe uint EventRegister( uint EventUnregister(long registrationHandle); // Write an event. - unsafe int EventWriteTransferWrapper( + unsafe EventProvider.WriteEventErrorCode EventWriteTransfer( long registrationHandle, - ref EventDescriptor eventDescriptor, + in EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityId, Guid* relatedActivityId, @@ -35,7 +35,7 @@ unsafe int EventWriteTransferWrapper( EventProvider.EventData* userData); // Get or set the per-thread activity ID. - int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId); + int EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId); // Define an EventPipeEvent handle. unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength); diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs index 569c9a011353..40581051cc9f 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs @@ -23,7 +23,7 @@ namespace System.Diagnostics.Tracing /// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates /// the counter value. /// - internal partial class IncrementingEventCounter : BaseCounter + public partial class IncrementingEventCounter : DiagnosticCounter { /// /// Initializes a new instance of the class. @@ -41,7 +41,7 @@ public IncrementingEventCounter(string name, EventSource eventSource) : base(nam /// be logged on the next timer interval. /// /// The value to increment by. - public void Increment(float increment = 1) + public void Increment(double increment = 1) { lock(MyLock) { @@ -49,25 +49,25 @@ public void Increment(float increment = 1) } } - internal TimeSpan DisplayRateTimeScale { get; set; } - private float _increment; - private float _prevIncrement; + public TimeSpan DisplayRateTimeScale { get; set; } + private double _increment; + private double _prevIncrement; - public override string ToString() => $"IncrementingEventCounter '{_name}' Increment {_increment}"; + public override string ToString() => $"IncrementingEventCounter '{Name}' Increment {_increment}"; internal override void WritePayload(float intervalSec) { lock (MyLock) // Lock the counter { IncrementingCounterPayload payload = new IncrementingCounterPayload(); - payload.Name = _name; + payload.Name = Name; payload.IntervalSec = intervalSec; payload.DisplayName = DisplayName ?? ""; payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c"); - payload.MetaData = GetMetaDataString(); + payload.Metadata = GetMetadataString(); payload.Increment = _increment - _prevIncrement; _prevIncrement = _increment; - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload)); } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs index 8bad728a1807..1b8ee7553e4d 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs @@ -25,7 +25,7 @@ namespace System.Diagnostics.Tracing /// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update /// its own metric periodically. /// - internal partial class IncrementingPollingCounter : BaseCounter + public partial class IncrementingPollingCounter : DiagnosticCounter { /// /// Initializes a new instance of the class. @@ -34,20 +34,20 @@ internal partial class IncrementingPollingCounter : BaseCounter /// /// The name. /// The event source. - public IncrementingPollingCounter(string name, EventSource eventSource, Func getCountFunction) : base(name, eventSource) + public IncrementingPollingCounter(string name, EventSource eventSource, Func totalValueProvider) : base(name, eventSource) { - _getCountFunction = getCountFunction; + _totalValueProvider = totalValueProvider; } - public override string ToString() => $"IncrementingPollingCounter '{_name}' Increment {_increment}"; + public override string ToString() => $"IncrementingPollingCounter '{Name}' Increment {_increment}"; - internal TimeSpan DisplayRateTimeScale { get; set; } - private float _increment; - private float _prevIncrement; - private Func _getCountFunction; + public TimeSpan DisplayRateTimeScale { get; set; } + private double _increment; + private double _prevIncrement; + private Func _totalValueProvider; /// - /// Calls "_getCountFunction" to enqueue the counter value to the queue. + /// Calls "_totalValueProvider" to enqueue the counter value to the queue. /// private void UpdateMetric() { @@ -55,12 +55,12 @@ private void UpdateMetric() { lock(MyLock) { - _increment = _getCountFunction(); + _increment = _totalValueProvider(); } } catch (Exception ex) { - ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message); + ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} getMetricFunction callback: " + ex.Message); } } @@ -70,14 +70,14 @@ internal override void WritePayload(float intervalSec) lock (MyLock) // Lock the counter { IncrementingCounterPayload payload = new IncrementingCounterPayload(); - payload.Name = _name; + payload.Name = Name; payload.DisplayName = DisplayName ?? ""; payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c"); payload.IntervalSec = intervalSec; - payload.MetaData = GetMetaDataString(); + payload.Metadata = GetMetadataString(); payload.Increment = _increment - _prevIncrement; _prevIncrement = _increment; - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload)); } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs index 695b357f45a9..e0577181facc 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs @@ -23,7 +23,7 @@ namespace System.Diagnostics.Tracing /// function to collect metrics on its own rather than the user having to call WriteMetric() /// every time. /// - internal partial class PollingCounter : BaseCounter + public partial class PollingCounter : DiagnosticCounter { /// /// Initializes a new instance of the class. @@ -32,41 +32,42 @@ internal partial class PollingCounter : BaseCounter /// /// The name. /// The event source. - public PollingCounter(string name, EventSource eventSource, Func getMetricFunction) : base(name, eventSource) + public PollingCounter(string name, EventSource eventSource, Func metricProvider) : base(name, eventSource) { - _getMetricFunction = getMetricFunction; + _metricProvider = metricProvider; } - public override string ToString() => $"PollingCounter '{_name}' Count {1} Mean {_lastVal.ToString("n3")}"; + public override string ToString() => $"PollingCounter '{Name}' Count {1} Mean {_lastVal.ToString("n3")}"; - private Func _getMetricFunction; - private float _lastVal; + private Func _metricProvider; + private double _lastVal; internal override void WritePayload(float intervalSec) { lock (MyLock) { - float value = 0; + double value = 0; try { - value = _getMetricFunction(); + value = _metricProvider(); } catch (Exception ex) { - ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message); + ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message); } CounterPayload payload = new CounterPayload(); - payload.Name = _name; + payload.Name = Name; payload.DisplayName = DisplayName ?? ""; payload.Count = 1; // NOTE: These dumb-looking statistics is intentional payload.IntervalSec = intervalSec; payload.Mean = value; payload.Max = value; payload.Min = value; + payload.Metadata = GetMetadataString(); payload.StandardDeviation = 0; _lastVal = value; - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload)); } } } diff --git a/src/System.Private.CoreLib/shared/System/Empty.cs b/src/System.Private.CoreLib/shared/System/Empty.cs index 186b92078e87..64c54dca029e 100644 --- a/src/System.Private.CoreLib/shared/System/Empty.cs +++ b/src/System.Private.CoreLib/shared/System/Empty.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { #if CORERT diff --git a/src/System.Private.CoreLib/shared/System/Enum.cs b/src/System.Private.CoreLib/shared/System/Enum.cs index 52ae2908e7c2..d60be2c250a0 100644 --- a/src/System.Private.CoreLib/shared/System/Enum.cs +++ b/src/System.Private.CoreLib/shared/System/Enum.cs @@ -494,7 +494,7 @@ private static bool TryParse(string? value, bool ignoreCase, bool throwOn default: parsed = TryParseRareEnum(rt, value, valueSpan, ignoreCase, throwOnFailure, out object? objectResult); - result = parsed ? (TEnum)objectResult : default; + result = parsed ? (TEnum)objectResult! : default; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 return parsed; } } @@ -664,7 +664,7 @@ private static bool TryParseRareEnum(RuntimeType enumType, string? originalValue Type underlyingType = GetUnderlyingType(enumType); try { - result = ToObject(enumType, Convert.ChangeType(value.ToString(), underlyingType, CultureInfo.InvariantCulture)); + result = ToObject(enumType, Convert.ChangeType(value.ToString(), underlyingType, CultureInfo.InvariantCulture)!); return true; } catch (FormatException) diff --git a/src/System.Private.CoreLib/shared/System/Environment.NoRegistry.cs b/src/System.Private.CoreLib/shared/System/Environment.NoRegistry.cs index 427d29d818ff..4ba66bdb03e4 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.NoRegistry.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.NoRegistry.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Collections; using Microsoft.Win32; @@ -12,9 +13,9 @@ public static partial class Environment { // Systems without the Windows registry pretend that it's always empty. - private static string GetEnvironmentVariableFromRegistry(string variable, bool fromMachine) => null; + private static string? GetEnvironmentVariableFromRegistry(string variable, bool fromMachine) => null; - private static void SetEnvironmentVariableFromRegistry(string variable, string value, bool fromMachine) { } + private static void SetEnvironmentVariableFromRegistry(string variable, string? value, bool fromMachine) { } private static IDictionary GetEnvironmentVariablesFromRegistry(bool fromMachine) => new Hashtable(); } diff --git a/src/System.Private.CoreLib/shared/System/Environment.SpecialFolder.cs b/src/System.Private.CoreLib/shared/System/Environment.SpecialFolder.cs index ae2add730d2b..5e7d0549e49d 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.SpecialFolder.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.SpecialFolder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public static partial class Environment diff --git a/src/System.Private.CoreLib/shared/System/Environment.SpecialFolderOption.cs b/src/System.Private.CoreLib/shared/System/Environment.SpecialFolderOption.cs index 929e3d9036a1..05972a701bf7 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.SpecialFolderOption.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.SpecialFolderOption.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public static partial class Environment diff --git a/src/System.Private.CoreLib/shared/System/Environment.Unix.cs b/src/System.Private.CoreLib/shared/System/Environment.Unix.cs index 00b502991be2..d74086b0fc4c 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -15,7 +16,7 @@ namespace System { public static partial class Environment { - private static Func s_directoryCreateDirectory; + private static Func? s_directoryCreateDirectory; private static string CurrentDirectoryCore { @@ -34,7 +35,7 @@ private static string ExpandEnvironmentVariablesCore(string name) if (name[lastPos] == '%') { string key = name.Substring(lastPos + 1, pos - lastPos - 1); - string value = GetEnvironmentVariable(key); + string? value = GetEnvironmentVariable(key); if (value != null) { result.Append(value); @@ -81,7 +82,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio Type dirType = Type.GetType("System.IO.Directory, System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); MethodInfo mi = dirType.GetTypeInfo().GetDeclaredMethod("CreateDirectory"); return (Func)mi.CreateDelegate(typeof(Func)); - }); + })!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 createDirectory(path); return path; @@ -104,7 +105,7 @@ private static string GetFolderPathCoreWithoutValidation(SpecialFolder folder) // All other paths are based on the XDG Base Directory Specification: // https://specifications.freedesktop.org/basedir-spec/latest/ - string home = null; + string? home = null; try { home = PersistedFiles.GetHomeDirectory(); @@ -137,7 +138,7 @@ private static string GetFolderPathCoreWithoutValidation(SpecialFolder folder) case SpecialFolder.LocalApplicationData: // "$XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored." // "If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used." - string data = GetEnvironmentVariable("XDG_DATA_HOME"); + string? data = GetEnvironmentVariable("XDG_DATA_HOME"); if (string.IsNullOrEmpty(data) || data[0] != '/') { data = Path.Combine(home, ".local", "share"); @@ -181,7 +182,7 @@ private static string GetXdgConfig(string home) { // "$XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored." // "If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used." - string config = GetEnvironmentVariable("XDG_CONFIG_HOME"); + string? config = GetEnvironmentVariable("XDG_CONFIG_HOME"); if (string.IsNullOrEmpty(config) || config[0] != '/') { config = Path.Combine(home, ".config"); @@ -195,7 +196,7 @@ private static string ReadXdgDirectory(string homeDir, string key, string fallba Debug.Assert(!string.IsNullOrEmpty(key), $"Expected non-empty key"); Debug.Assert(!string.IsNullOrEmpty(fallback), $"Expected non-empty fallback"); - string envPath = GetEnvironmentVariable(key); + string? envPath = GetEnvironmentVariable(key); if (!string.IsNullOrEmpty(envPath) && envPath[0] == '/') { return envPath; @@ -215,7 +216,7 @@ private static string ReadXdgDirectory(string homeDir, string key, string fallba { using (var reader = new StreamReader(userDirsPath)) { - string line; + string? line; while ((line = reader.ReadLine()) != null) { // Example lines: @@ -366,12 +367,12 @@ public static unsafe string UserName get { // First try with a buffer that should suffice for 99% of cases. - string username; + string? username; const int BufLen = Interop.Sys.Passwd.InitialBufferSize; byte* stackBuf = stackalloc byte[BufLen]; if (TryGetUserNameFromPasswd(stackBuf, BufLen, out username)) { - return username; + return username ?? string.Empty; } // Fallback to heap allocations if necessary, growing the buffer until @@ -385,7 +386,7 @@ public static unsafe string UserName { if (TryGetUserNameFromPasswd(buf, heapBuf.Length, out username)) { - return username; + return username ?? string.Empty; } } } @@ -393,7 +394,7 @@ public static unsafe string UserName } } - private static unsafe bool TryGetUserNameFromPasswd(byte* buf, int bufLen, out string path) + private static unsafe bool TryGetUserNameFromPasswd(byte* buf, int bufLen, out string? username) { // Call getpwuid_r to get the passwd struct Interop.Sys.Passwd passwd; @@ -403,15 +404,15 @@ private static unsafe bool TryGetUserNameFromPasswd(byte* buf, int bufLen, out s if (error == 0) { Debug.Assert(passwd.Name != null); - path = Marshal.PtrToStringAnsi((IntPtr)passwd.Name); + username = Marshal.PtrToStringAnsi((IntPtr)passwd.Name); return true; } // If the current user's entry could not be found, give back null, - // but still return true as false indicates the buffer was too small. + // but still return true (false indicates the buffer was too small). if (error == -1) { - path = null; + username = null; return true; } @@ -421,7 +422,7 @@ private static unsafe bool TryGetUserNameFromPasswd(byte* buf, int bufLen, out s // indicate the caller should try again with a larger buffer. if (errorInfo.Error == Interop.Error.ERANGE) { - path = null; + username = null; return false; } diff --git a/src/System.Private.CoreLib/shared/System/Environment.Variables.Windows.cs b/src/System.Private.CoreLib/shared/System/Environment.Variables.Windows.cs index 92be84b1fb04..c13410207f49 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.Variables.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.Variables.Windows.cs @@ -2,18 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Collections; -using System.Collections.Generic; using System.Diagnostics; -using System.Reflection; using System.Runtime.InteropServices; namespace System { public static partial class Environment { - private static string GetEnvironmentVariableCore(string variable) + private static string? GetEnvironmentVariableCore(string variable) { Span buffer = stackalloc char[128]; // a somewhat reasonable default size int requiredSize = Interop.Kernel32.GetEnvironmentVariable(variable, buffer); @@ -47,7 +46,7 @@ private static string GetEnvironmentVariableCore(string variable) } } - private static void SetEnvironmentVariableCore(string variable, string value) + private static void SetEnvironmentVariableCore(string variable, string? value) { if (!Interop.Kernel32.SetEnvironmentVariable(variable, value)) { diff --git a/src/System.Private.CoreLib/shared/System/Environment.Win32.cs b/src/System.Private.CoreLib/shared/System/Environment.Win32.cs index f7b87ff7866b..bc32146cf9d6 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.Win32.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Diagnostics; using System.IO; @@ -14,7 +15,9 @@ namespace System { public static partial class Environment { - private static string GetEnvironmentVariableFromRegistry(string variable, bool fromMachine) + internal static bool IsWindows8OrAbove => WindowsVersion.IsWindows8OrAbove; + + private static string? GetEnvironmentVariableFromRegistry(string variable, bool fromMachine) { Debug.Assert(variable != null); @@ -23,13 +26,13 @@ private static string GetEnvironmentVariableFromRegistry(string variable, bool f return null; // Systems without the Windows registry pretend that it's always empty. #endif - using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false)) + using (RegistryKey? environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false)) { return environmentKey?.GetValue(variable) as string; } } - private static void SetEnvironmentVariableFromRegistry(string variable, string value, bool fromMachine) + private static void SetEnvironmentVariableFromRegistry(string variable, string? value, bool fromMachine) { Debug.Assert(variable != null); @@ -44,7 +47,7 @@ private static void SetEnvironmentVariableFromRegistry(string variable, string v throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(variable)); } - using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: true)) + using (RegistryKey? environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: true)) { if (environmentKey != null) { @@ -72,13 +75,13 @@ private static IDictionary GetEnvironmentVariablesFromRegistry(bool fromMachine) return results; #endif - using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false)) + using (RegistryKey? environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false)) { if (environmentKey != null) { foreach (string name in environmentKey.GetValueNames()) { - string value = environmentKey.GetValue(name, "").ToString(); + string? value = environmentKey.GetValue(name, "")!.ToString(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 try { results.Add(name, value); @@ -94,7 +97,7 @@ private static IDictionary GetEnvironmentVariablesFromRegistry(bool fromMachine) return results; } - private static RegistryKey OpenEnvironmentKeyIfExists(bool fromMachine, bool writable) + private static RegistryKey? OpenEnvironmentKeyIfExists(bool fromMachine, bool writable) { RegistryKey baseKey; string keyName; @@ -409,14 +412,44 @@ public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption opt if (s_winRTFolderPathsGetFolderPath == null) { Type winRtFolderPathsType = Type.GetType("System.WinRTFolderPaths, System.Runtime.WindowsRuntime, Version=4.0.14.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", throwOnError: false); - MethodInfo getFolderPathsMethod = winRtFolderPathsType?.GetMethod("GetFolderPath", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(SpecialFolder), typeof(SpecialFolderOption) }, null); - var d = (Func)getFolderPathsMethod?.CreateDelegate(typeof(Func)); - s_winRTFolderPathsGetFolderPath = d ?? delegate { return null; }; + MethodInfo? getFolderPathsMethod = winRtFolderPathsType?.GetMethod("GetFolderPath", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(SpecialFolder), typeof(SpecialFolderOption) }, null); + var d = (Func?)getFolderPathsMethod?.CreateDelegate(typeof(Func)); + s_winRTFolderPathsGetFolderPath = d ?? delegate { return string.Empty; }; } return s_winRTFolderPathsGetFolderPath(folder, option); } } #endif + + // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup + private static class WindowsVersion + { + // Cache the value in readonly static that can be optimized out by the JIT + internal readonly static bool IsWindows8OrAbove = GetIsWindows8OrAbove(); + + private static bool GetIsWindows8OrAbove() + { + ulong conditionMask = Interop.Kernel32.VerSetConditionMask(0, Interop.Kernel32.VER_MAJORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); + conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_MINORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); + conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMAJOR, Interop.Kernel32.VER_GREATER_EQUAL); + conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMINOR, Interop.Kernel32.VER_GREATER_EQUAL); + + // Windows 8 version is 6.2 + Interop.Kernel32.OSVERSIONINFOEX version = default; + unsafe + { + version.dwOSVersionInfoSize = sizeof(Interop.Kernel32.OSVERSIONINFOEX); + } + version.dwMajorVersion = 6; + version.dwMinorVersion = 2; + version.wServicePackMajor = 0; + version.wServicePackMinor = 0; + + return Interop.Kernel32.VerifyVersionInfoW(ref version, + Interop.Kernel32.VER_MAJORVERSION | Interop.Kernel32.VER_MINORVERSION | Interop.Kernel32.VER_SERVICEPACKMAJOR | Interop.Kernel32.VER_SERVICEPACKMINOR, + conditionMask); + } + } } } diff --git a/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs b/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs index a8e3dbced807..1a22b7b32881 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using Internal.Runtime.Augments; @@ -13,12 +14,14 @@ public static partial class Environment public static string UserDomainName => "Windows Domain"; + internal static readonly bool IsWindows8OrAbove = true; + private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option) { WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks; return callbacks != null && callbacks.IsAppxModel() ? callbacks.GetFolderPath(folder, option) : - null; + string.Empty; } } } diff --git a/src/System.Private.CoreLib/shared/System/Environment.Windows.cs b/src/System.Private.CoreLib/shared/System/Environment.Windows.cs index 0887630df00f..f60323b27d23 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.Windows.cs @@ -2,11 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; -using Microsoft.Win32; namespace System { diff --git a/src/System.Private.CoreLib/shared/System/Environment.cs b/src/System.Private.CoreLib/shared/System/Environment.cs index ade5091bd891..3691c0de2b7e 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; -using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Threading; @@ -12,7 +12,7 @@ namespace System { public static partial class Environment { - public static string GetEnvironmentVariable(string variable) + public static string? GetEnvironmentVariable(string variable) { if (variable == null) throw new ArgumentNullException(nameof(variable)); @@ -20,7 +20,7 @@ public static string GetEnvironmentVariable(string variable) return GetEnvironmentVariableCore(variable); } - public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target) + public static string? GetEnvironmentVariable(string variable, EnvironmentVariableTarget target) { if (target == EnvironmentVariableTarget.Process) return GetEnvironmentVariable(variable); @@ -41,13 +41,13 @@ public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget targ return GetEnvironmentVariablesFromRegistry(fromMachine); } - public static void SetEnvironmentVariable(string variable, string value) + public static void SetEnvironmentVariable(string variable, string? value) { ValidateVariableAndValue(variable, ref value); SetEnvironmentVariableCore(variable, value); } - public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) + public static void SetEnvironmentVariable(string variable, string? value, EnvironmentVariableTarget target) { if (target == EnvironmentVariableTarget.Process) { @@ -89,7 +89,7 @@ public static string ExpandEnvironmentVariables(string name) return ExpandEnvironmentVariablesCore(name); } - private static string[] s_commandLineArgs; + private static string[]? s_commandLineArgs; internal static void SetCommandLineArgs(string[] cmdLineArgs) // invoked from VM { @@ -113,7 +113,7 @@ public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption opt public static bool Is64BitOperatingSystem => Is64BitProcess || Is64BitOperatingSystemWhen32BitProcess; - private static OperatingSystem s_osVersion; + private static OperatingSystem? s_osVersion; public static OperatingSystem OSVersion { @@ -123,7 +123,7 @@ public static OperatingSystem OSVersion { Interlocked.CompareExchange(ref s_osVersion, GetOSVersion(), null); } - return s_osVersion; + return s_osVersion!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -134,7 +134,7 @@ public static Version Version get { // FX_PRODUCT_VERSION is expected to be set by the host - string versionString = (string)AppContext.GetData("FX_PRODUCT_VERSION"); + string? versionString = (string?)AppContext.GetData("FX_PRODUCT_VERSION"); if (versionString == null) { @@ -150,7 +150,7 @@ public static Version Version versionSpan = versionSpan.Slice(0, separatorIndex); // Return zeros rather then failing if the version string fails to parse - return Version.TryParse(versionSpan, out Version version) ? version : new Version(); + return Version.TryParse(versionSpan, out Version? version) ? version! : new Version(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -163,12 +163,12 @@ public static long WorkingSet // present in Process. If it proves important, we could look at separating that functionality out of Process into // Common files which could also be included here. Type processType = Type.GetType("System.Diagnostics.Process, System.Diagnostics.Process, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); - IDisposable currentProcess = processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) as IDisposable; + IDisposable? currentProcess = processType?.GetMethod("GetCurrentProcess")?.Invoke(null, BindingFlags.DoNotWrapExceptions, null, null, null) as IDisposable; if (currentProcess != null) { using (currentProcess) { - object result = processType.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null); + object? result = processType!.GetMethod("get_WorkingSet64")?.Invoke(currentProcess, BindingFlags.DoNotWrapExceptions, null, null, null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 if (result is long) return (long)result; } } @@ -191,7 +191,7 @@ private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget t throw new ArgumentOutOfRangeException(nameof(target), target, SR.Format(SR.Arg_EnumIllegalVal, target)); } - private static void ValidateVariableAndValue(string variable, ref string value) + private static void ValidateVariableAndValue(string variable, ref string? value) { if (variable == null) throw new ArgumentNullException(nameof(variable)); diff --git a/src/System.Private.CoreLib/shared/System/EnvironmentVariableTarget.cs b/src/System.Private.CoreLib/shared/System/EnvironmentVariableTarget.cs index 806eb75ad38b..1f8213cb5645 100644 --- a/src/System.Private.CoreLib/shared/System/EnvironmentVariableTarget.cs +++ b/src/System.Private.CoreLib/shared/System/EnvironmentVariableTarget.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { #if PROJECTN @@ -13,4 +14,4 @@ public enum EnvironmentVariableTarget User = 1, Machine = 2, } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/EventArgs.cs b/src/System.Private.CoreLib/shared/System/EventArgs.cs index f3561a8d0b14..0d806c6312ac 100644 --- a/src/System.Private.CoreLib/shared/System/EventArgs.cs +++ b/src/System.Private.CoreLib/shared/System/EventArgs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; namespace System diff --git a/src/System.Private.CoreLib/shared/System/EventHandler.cs b/src/System.Private.CoreLib/shared/System/EventHandler.cs index c38e17ce6fb7..7e0f183438f9 100644 --- a/src/System.Private.CoreLib/shared/System/EventHandler.cs +++ b/src/System.Private.CoreLib/shared/System/EventHandler.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; namespace System { - public delegate void EventHandler(object sender, EventArgs e); + public delegate void EventHandler(object? sender, EventArgs e); - public delegate void EventHandler(object sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4 + public delegate void EventHandler(object? sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4 } diff --git a/src/System.Private.CoreLib/shared/System/Exception.cs b/src/System.Private.CoreLib/shared/System/Exception.cs index c2522d558b57..0fc37ee78bed 100644 --- a/src/System.Private.CoreLib/shared/System/Exception.cs +++ b/src/System.Private.CoreLib/shared/System/Exception.cs @@ -41,8 +41,8 @@ protected Exception(SerializationInfo info, StreamingContext context) throw new ArgumentNullException(nameof(info)); _message = info.GetString("Message"); // Do not rename (binary serialization) - _data = (IDictionary)(info.GetValueNoThrow("Data", typeof(IDictionary))); // Do not rename (binary serialization) - _innerException = (Exception)(info.GetValue("InnerException", typeof(Exception))); // Do not rename (binary serialization) + _data = (IDictionary?)(info.GetValueNoThrow("Data", typeof(IDictionary))); // Do not rename (binary serialization) + _innerException = (Exception?)(info.GetValue("InnerException", typeof(Exception))); // Do not rename (binary serialization) _helpURL = info.GetString("HelpURL"); // Do not rename (binary serialization) _stackTraceString = info.GetString("StackTraceString"); // Do not rename (binary serialization) _HResult = info.GetInt32("HResult"); // Do not rename (binary serialization) diff --git a/src/System.Private.CoreLib/shared/System/FlagsAttribute.cs b/src/System.Private.CoreLib/shared/System/FlagsAttribute.cs index 4f3ab36bfd5a..751f944f838d 100644 --- a/src/System.Private.CoreLib/shared/System/FlagsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/FlagsAttribute.cs @@ -5,6 +5,7 @@ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// +#nullable enable namespace System { // Custom attribute to indicate that the enum diff --git a/src/System.Private.CoreLib/shared/System/FormattableString.cs b/src/System.Private.CoreLib/shared/System/FormattableString.cs index 51863d6e7c74..965a916bc3ec 100644 --- a/src/System.Private.CoreLib/shared/System/FormattableString.cs +++ b/src/System.Private.CoreLib/shared/System/FormattableString.cs @@ -11,6 +11,7 @@ ** ===========================================================*/ +#nullable enable namespace System { /// @@ -28,7 +29,7 @@ public abstract class FormattableString : IFormattable /// Returns an object array that contains zero or more objects to format. Clients should not /// mutate the contents of the array. /// - public abstract object[] GetArguments(); + public abstract object?[] GetArguments(); /// /// The number of arguments to be formatted. @@ -38,14 +39,14 @@ public abstract class FormattableString : IFormattable /// /// Returns one argument to be formatted from argument position . /// - public abstract object GetArgument(int index); + public abstract object? GetArgument(int index); /// /// Format to a string using the given culture. /// - public abstract string ToString(IFormatProvider formatProvider); + public abstract string ToString(IFormatProvider? formatProvider); - string IFormattable.ToString(string ignored, IFormatProvider formatProvider) + string IFormattable.ToString(string? ignored, IFormatProvider? formatProvider) { return ToString(formatProvider); } diff --git a/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs b/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs new file mode 100644 index 000000000000..72c2aca14da2 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System +{ + public readonly struct GCMemoryInfo + { + /// + /// High memory load threshold when the last GC occured + /// + public long HighMemoryLoadThresholdBytes { get; } + + /// + /// Memory load when the last GC ocurred + /// + public long MemoryLoadBytes { get; } + + /// + /// Total available memory for the GC to use when the last GC ocurred. By default this is the physical memory on the machine, but it may be customized by specifying a HardLimit. + /// + public long TotalAvailableMemoryBytes { get; } + + /// + /// The total heap size when the last GC ocurred + /// + public long HeapSizeBytes { get; } + + /// + /// The total fragmentation when the last GC ocurred + /// + /// Let's take the example below: + /// | OBJ_A | OBJ_B | OBJ_C | OBJ_D | OBJ_E | + /// + /// Let's say OBJ_B, OBJ_C and and OBJ_E are garbage and get collected, but the heap does not get compacted, the resulting heap will look like the following: + /// | OBJ_A | F | OBJ_D | + /// + /// The memory between OBJ_A and OBJ_D marked `F` is considered part of the FragmentedBytes, and will be used to allocate new objects. The memory after OBJ_D will not be + /// considered part of the FragmentedBytes, and will also be used to allocate new objects + /// + public long FragmentedBytes { get; } + + internal GCMemoryInfo(long highMemoryLoadThresholdBytes, + long memoryLoadBytes, + long totalAvailableMemoryBytes, + long heapSizeBytes, + long fragmentedBytes) + { + HighMemoryLoadThresholdBytes = highMemoryLoadThresholdBytes; + MemoryLoadBytes = memoryLoadBytes; + TotalAvailableMemoryBytes = totalAvailableMemoryBytes; + HeapSizeBytes = heapSizeBytes; + FragmentedBytes = fragmentedBytes; + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs index acc415b6d10d..10dffb544ad4 100644 --- a/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs +++ b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; @@ -13,9 +14,13 @@ namespace System /// internal sealed class Gen2GcCallback : CriticalFinalizerObject { - private Gen2GcCallback() - : base() + private readonly Func _callback; + private readonly GCHandle _weakTargetObj; + + private Gen2GcCallback(Func callback, object targetObj) { + _callback = callback; + _weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak); } /// @@ -28,23 +33,13 @@ private Gen2GcCallback() public static void Register(Func callback, object targetObj) { // Create a unreachable object that remembers the callback function and target object. - Gen2GcCallback gcCallback = new Gen2GcCallback(); - gcCallback.Setup(callback, targetObj); - } - - private Func _callback; - private GCHandle _weakTargetObj; - - private void Setup(Func callback, object targetObj) - { - _callback = callback; - _weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak); + new Gen2GcCallback(callback, targetObj); } ~Gen2GcCallback() { // Check to see if the target object is still alive. - object targetObj = _weakTargetObj.Target; + object? targetObj = _weakTargetObj.Target; if (targetObj == null) { // The target object is dead, so this callback object is no longer needed. @@ -71,10 +66,7 @@ private void Setup(Func callback, object targetObj) } // Resurrect ourselves by re-registering for finalization. - if (!Environment.HasShutdownStarted) - { - GC.ReRegisterForFinalize(this); - } + GC.ReRegisterForFinalize(this); } } } diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs index e57e0c5687d3..80e385376d05 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs @@ -108,7 +108,7 @@ private static bool SystemSupportsTaiwaneseCalendar() // PAL Layer ends here - private static unsafe bool GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string calendarString) + private static unsafe bool GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string? calendarString) { Debug.Assert(!GlobalizationMode.Invariant); diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs index 403e0e3583a1..84e4ddf5f2df 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; using System.Runtime.InteropServices; @@ -56,11 +57,11 @@ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId // String Arrays // Formats - ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SSHORTDATE, LOCALE_SSHORTDATE | useOverrides, out this.saShortDates); - ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SLONGDATE, LOCALE_SLONGDATE | useOverrides, out this.saLongDates); + ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SSHORTDATE, LOCALE_SSHORTDATE | useOverrides, out this.saShortDates!); + ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SLONGDATE, LOCALE_SLONGDATE | useOverrides, out this.saLongDates!); // Get the YearMonth pattern. - ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SYEARMONTH, LOCALE_SYEARMONTH, out this.saYearMonths); + ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SYEARMONTH, LOCALE_SYEARMONTH, out this.saYearMonths!); // Day & Month Names // These are all single calType entries, 1 per day, so we have to make 7 or 13 calls to collect all the names @@ -90,8 +91,8 @@ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId // Calendar Parts Names // This doesn't get always get localized names for gregorian (not available in windows < 7) // so: eg: coreclr on win < 7 won't get these - CallEnumCalendarInfo(localeName, calendarId, CAL_SERASTRING, 0, out this.saEraNames); - CallEnumCalendarInfo(localeName, calendarId, CAL_SABBREVERASTRING, 0, out this.saAbbrevEraNames); + CallEnumCalendarInfo(localeName, calendarId, CAL_SERASTRING, 0, out this.saEraNames!); + CallEnumCalendarInfo(localeName, calendarId, CAL_SABBREVERASTRING, 0, out this.saAbbrevEraNames!); // // Calendar Era Info @@ -100,10 +101,10 @@ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId // // Clean up the escaping of the formats - this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates); - this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates); - this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths); - this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay); + this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return ret; } @@ -247,7 +248,7 @@ private static void CheckSpecialCalendar(ref CalendarId calendar, ref string loc } } - private static bool CallGetCalendarInfoEx(string localeName, CalendarId calendar, uint calType, out int data) + private static bool CallGetCalendarInfoEx(string? localeName, CalendarId calendar, uint calType, out int data) { return (Interop.Kernel32.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType | CAL_RETURN_NUMBER, IntPtr.Zero, 0, out data) != 0); } @@ -276,8 +277,8 @@ private static unsafe bool CallGetCalendarInfoEx(string localeName, CalendarId c // Context for EnumCalendarInfoExEx callback. private struct EnumData { - public string userOverride; - public List strings; + public string? userOverride; + public List? strings; } // EnumCalendarInfoExEx callback itself. @@ -291,7 +292,10 @@ private static unsafe Interop.BOOL EnumCalendarInfoCallback(char* lpCalendarInfo // If we had a user override, check to make sure this differs if (context.userOverride != calendarInfo) + { + Debug.Assert(context.strings != null); context.strings.Add(calendarInfo); + } return Interop.BOOL.TRUE; } @@ -301,7 +305,7 @@ private static unsafe Interop.BOOL EnumCalendarInfoCallback(char* lpCalendarInfo } } - private static unsafe bool CallEnumCalendarInfo(string localeName, CalendarId calendar, uint calType, uint lcType, out string[] data) + private static unsafe bool CallEnumCalendarInfo(string localeName, CalendarId calendar, uint calType, uint lcType, out string[]? data) { EnumData context = new EnumData(); context.userOverride = null; @@ -319,7 +323,7 @@ private static unsafe bool CallEnumCalendarInfo(string localeName, CalendarId ca if (userCalendar == calendar) { // They matched, get the user override since locale & calendar match - string res = CultureData.GetLocaleInfoEx(localeName, lcType); + string? res = CultureData.GetLocaleInfoEx(localeName, lcType); // if it succeeded remember the override for the later callers if (res != null) @@ -340,6 +344,7 @@ private static unsafe bool CallEnumCalendarInfo(string localeName, CalendarId ca } // Now we have a list of data, fail if we didn't find anything. + Debug.Assert(context.strings != null); if (context.strings.Count == 0) { data = null; diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs index f5bba908b560..ef2eb4945afc 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs @@ -8,7 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Text; +using System.Text.Unicode; using Internal.Runtime.CompilerServices; namespace System.Globalization diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs index f27b97e9a12c..f92f119b4b3c 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs @@ -431,8 +431,7 @@ private static string GetLocaleInfoFromLCType(string localeName, uint lctype, bo { for (int i = 0; i < array.Length; i++) { - // only returns null when null is passed - array[i] = ReescapeWin32String(array[i])!; + array[i] = ReescapeWin32String(array[i])!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs index 7e1e66857f50..c86bab5afacb 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs @@ -11,6 +11,7 @@ namespace System.Globalization { #if CORERT + #pragma warning restore nullable using StringStringDictionary = LowLevelDictionary; using StringCultureDataDictionary = LowLevelDictionary; using LcidToCultureNameDictionary = LowLevelDictionary; diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs index 09041e9b7f68..8d312dfc5c49 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureInfo.Windows.cs @@ -82,7 +82,7 @@ private static CultureInfo GetUserDefaultUICulture() return null; } - CultureInfo toReturn; + CultureInfo? toReturn; try { diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs index cb61d5079aaf..87d26f8a6735 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs @@ -62,7 +62,7 @@ protected CultureNotFoundException(SerializationInfo info, StreamingContext cont : base(info, context) { _invalidCultureId = (int?)info.GetValue("InvalidCultureId", typeof(int?)); - _invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string)); + _invalidCultureName = (string?)info.GetValue("InvalidCultureName", typeof(string)); } public override void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs index 76ee9085bfdd..107fac5e6cd8 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs @@ -131,7 +131,7 @@ internal static DateTime ParseExactMultiple(ReadOnlySpan s, string[] forma } } - internal static bool TryParseExactMultiple(ReadOnlySpan s, string[] formats, + internal static bool TryParseExactMultiple(ReadOnlySpan s, string?[]? formats, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset) { result = DateTime.MinValue; @@ -149,7 +149,7 @@ internal static bool TryParseExactMultiple(ReadOnlySpan s, string[] format } - internal static bool TryParseExactMultiple(ReadOnlySpan s, string[] formats, + internal static bool TryParseExactMultiple(ReadOnlySpan s, string?[]? formats, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result) { result = DateTime.MinValue; @@ -163,7 +163,7 @@ internal static bool TryParseExactMultiple(ReadOnlySpan s, string[] format return false; } - internal static bool TryParseExactMultiple(ReadOnlySpan s, string[] formats, + internal static bool TryParseExactMultiple(ReadOnlySpan s, string?[]? formats, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result) { if (formats == null) @@ -192,7 +192,7 @@ internal static bool TryParseExactMultiple(ReadOnlySpan s, string[] format // for (int i = 0; i < formats.Length; i++) { - if (formats[i] == null || formats[i].Length == 0) + if (formats[i] == null || formats[i]!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 { result.SetBadFormatSpecifierFailure(); return false; @@ -5100,15 +5100,15 @@ private static Exception GetDateTimeParseException(ref DateTimeResult result) case ParseFailureKind.Format: return new FormatException(SR.GetResourceString(result.failureMessageID)); case ParseFailureKind.FormatWithParameter: - return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), result.failureMessageFormatArgument)); + return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, result.failureMessageFormatArgument)); case ParseFailureKind.FormatBadDateTimeCalendar: - return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.originalDateTimeString), result.calendar)); + return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.originalDateTimeString), result.calendar)); case ParseFailureKind.FormatWithOriginalDateTime: - return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.originalDateTimeString))); + return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.originalDateTimeString))); case ParseFailureKind.FormatWithFormatSpecifier: - return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.failedFormatSpecifier))); + return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.failedFormatSpecifier))); case ParseFailureKind.FormatWithOriginalDateTimeAndParameter: - return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.originalDateTimeString), result.failureMessageFormatArgument)); + return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID)!, new string(result.originalDateTimeString), result.failureMessageFormatArgument)); default: Debug.Fail("Unknown DateTimeParseFailure: " + result.failure.ToString()); return null!; diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs index 02e38e22edb2..1e8f7474d170 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs @@ -40,7 +40,7 @@ private int GetHijriDateAdjustment() ============================================================================*/ private static int GetAdvanceHijriDate() { - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(InternationalRegKey)) + using (RegistryKey? key = Registry.CurrentUser.OpenSubKey(InternationalRegKey)) { // Abort if we didn't find anything if (key == null) @@ -48,7 +48,7 @@ private static int GetAdvanceHijriDate() return 0; } - object value = key.GetValue(HijriAdvanceRegKeyEntry); + object? value = key.GetValue(HijriAdvanceRegKeyEntry); if (value == null) { return 0; diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs index 0f63f8cbc073..780b9533fd69 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs @@ -37,7 +37,7 @@ public partial class JapaneseCalendar : Calendar try { // Need to access registry - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(JapaneseErasHive)) + using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(JapaneseErasHive)) { // Abort if we didn't find anything if (key == null) return null; @@ -52,7 +52,7 @@ public partial class JapaneseCalendar : Calendar for (int i = 0; i < valueNames.Length; i++) { // See if the era is a valid date - EraInfo? era = GetEraFromValue(valueNames[i], key.GetValue(valueNames[i]).ToString()); + EraInfo? era = GetEraFromValue(valueNames[i], key.GetValue(valueNames[i])?.ToString()); // continue if not valid if (era == null) continue; @@ -93,10 +93,10 @@ public partial class JapaneseCalendar : Calendar Array.Resize(ref registryEraRanges, iFoundEras); // Sort them - Array.Sort(registryEraRanges, CompareEraRanges); + Array.Sort(registryEraRanges!, CompareEraRanges); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 // Clean up era information - for (int i = 0; i < registryEraRanges.Length; i++) + for (int i = 0; i < registryEraRanges!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { // eras count backwards from length to 1 (and are 1 based indexes into string arrays) registryEraRanges[i].era = registryEraRanges.Length - i; diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs index 89e4e2beb527..ce1b941077b8 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs @@ -202,7 +202,7 @@ private static EraInfo[] TrimEras(EraInfo[] baseEras) // If we didn't copy any then something was wrong, just return base if (newIndex == 0) return baseEras; - Array.Resize(ref newEras, newIndex); + Array.Resize(ref newEras!, newIndex); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return newEras; } diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs index 7b0136b8081d..4e34474f36fb 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs @@ -51,7 +51,7 @@ public bool MoveNext() return true; } - public object Current => GetTextElement(); + public object? Current => GetTextElement(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 public string GetTextElement() { diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs index cf89dff6a2e9..4391dec044fd 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Text; +using System.Text.Unicode; using Internal.Runtime.CompilerServices; #if BIT64 diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs index 39defa0b66f2..a03a02c1f8b1 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs @@ -664,7 +664,7 @@ internal static TimeSpan ParseExactMultiple(ReadOnlySpan input, string?[] return parseResult.parsedTimeSpan; } - internal static bool TryParseExactMultiple(ReadOnlySpan input, string?[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result) + internal static bool TryParseExactMultiple(ReadOnlySpan input, string?[]? formats, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result) { var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input); @@ -1670,7 +1670,7 @@ internal void SkipBlanks() } /// Common private ParseExactMultiple method called by both ParseExactMultiple and TryParseExactMultiple. - private static bool TryParseExactMultipleTimeSpan(ReadOnlySpan input, string?[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles, ref TimeSpanResult result) + private static bool TryParseExactMultipleTimeSpan(ReadOnlySpan input, string?[]? formats, IFormatProvider? formatProvider, TimeSpanStyles styles, ref TimeSpanResult result) { if (formats == null) { diff --git a/src/System.Private.CoreLib/shared/System/Guid.Unix.cs b/src/System.Private.CoreLib/shared/System/Guid.Unix.cs index 1c39e112ed7e..113f76dfe396 100644 --- a/src/System.Private.CoreLib/shared/System/Guid.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Guid.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/System/Guid.Windows.cs b/src/System.Private.CoreLib/shared/System/Guid.Windows.cs index 6a275084f938..46bdec2c0f29 100644 --- a/src/System.Private.CoreLib/shared/System/Guid.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Guid.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { partial struct Guid diff --git a/src/System.Private.CoreLib/shared/System/Guid.cs b/src/System.Private.CoreLib/shared/System/Guid.cs index ea3ae76a2609..6bcf48cf71c0 100644 --- a/src/System.Private.CoreLib/shared/System/Guid.cs +++ b/src/System.Private.CoreLib/shared/System/Guid.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; @@ -269,7 +270,7 @@ public static Guid ParseExact(ReadOnlySpan input, ReadOnlySpan forma return result._parsedGuid; } - public static bool TryParseExact(string input, string format, out Guid result) + public static bool TryParseExact(string? input, string? format, out Guid result) { if (input == null) { @@ -806,7 +807,7 @@ public override int GetHashCode() // Returns true if and only if the guid represented // by o is the same as this instance. - public override bool Equals(object o) + public override bool Equals(object? o) { Guid g; // Check that o is a Guid first @@ -832,7 +833,7 @@ public bool Equals(Guid g) private int GetResult(uint me, uint them) => me < them ? -1 : 1; - public int CompareTo(object value) + public int CompareTo(object? value) { if (value == null) { @@ -980,7 +981,7 @@ public int CompareTo(Guid value) Unsafe.Add(ref a._a, 3) != Unsafe.Add(ref b._a, 3); } - public string ToString(string format) + public string ToString(string? format) { return ToString(format, null); } @@ -1023,7 +1024,7 @@ private static unsafe int HexsToCharsHexOutput(char* guidChars, int a, int b) // IFormattable interface // We currently ignore provider - public string ToString(string format, IFormatProvider provider) + public string ToString(string? format, IFormatProvider? provider) { if (string.IsNullOrEmpty(format)) { @@ -1194,7 +1195,7 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan return true; } - bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider provider) + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) { // Like with the IFormattable implementation, provider is ignored. return TryFormat(destination, out charsWritten, format); diff --git a/src/System.Private.CoreLib/shared/System/HResults.cs b/src/System.Private.CoreLib/shared/System/HResults.cs index a7c1f8c34ee7..df12ac3e4896 100644 --- a/src/System.Private.CoreLib/shared/System/HResults.cs +++ b/src/System.Private.CoreLib/shared/System/HResults.cs @@ -18,7 +18,7 @@ // Reflection will use 0x1600 -> 0x161f. IO will use 0x1620 -> 0x163f. // Security will use 0x1640 -> 0x165f - +#nullable enable using System; namespace System diff --git a/src/System.Private.CoreLib/shared/System/HashCode.cs b/src/System.Private.CoreLib/shared/System/HashCode.cs index 39a905b78183..09fef5d95d3a 100644 --- a/src/System.Private.CoreLib/shared/System/HashCode.cs +++ b/src/System.Private.CoreLib/shared/System/HashCode.cs @@ -41,6 +41,7 @@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +#nullable enable using System.Collections.Generic; using System.ComponentModel; using System.Numerics; @@ -301,7 +302,7 @@ public void Add(T value) Add(value?.GetHashCode() ?? 0); } - public void Add(T value, IEqualityComparer comparer) + public void Add(T value, IEqualityComparer? comparer) { Add(comparer != null ? comparer.GetHashCode(value) : (value?.GetHashCode() ?? 0)); } @@ -417,7 +418,7 @@ public int ToHashCode() [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)] [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => throw new NotSupportedException(SR.HashCode_EqualityNotSupported); + public override bool Equals(object? obj) => throw new NotSupportedException(SR.HashCode_EqualityNotSupported); #pragma warning restore 0809 } } diff --git a/src/System.Private.CoreLib/shared/System/IAsyncDisposable.cs b/src/System.Private.CoreLib/shared/System/IAsyncDisposable.cs index c29f549df294..3139b0051329 100644 --- a/src/System.Private.CoreLib/shared/System/IAsyncDisposable.cs +++ b/src/System.Private.CoreLib/shared/System/IAsyncDisposable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Threading.Tasks; namespace System diff --git a/src/System.Private.CoreLib/shared/System/ICloneable.cs b/src/System.Private.CoreLib/shared/System/ICloneable.cs index 9f123e45c849..325a367ba76e 100644 --- a/src/System.Private.CoreLib/shared/System/ICloneable.cs +++ b/src/System.Private.CoreLib/shared/System/ICloneable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public interface ICloneable diff --git a/src/System.Private.CoreLib/shared/System/IComparable.cs b/src/System.Private.CoreLib/shared/System/IComparable.cs index cf71953e2552..1a23580e324f 100644 --- a/src/System.Private.CoreLib/shared/System/IComparable.cs +++ b/src/System.Private.CoreLib/shared/System/IComparable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { // The IComparable interface is implemented by classes that support an @@ -18,7 +19,7 @@ public interface IComparable // if this is equal to object, or a value greater than zero // if this is greater than object. // - int CompareTo(object obj); + int CompareTo(object? obj); } // Generic version of IComparable. diff --git a/src/System.Private.CoreLib/shared/System/IConvertible.cs b/src/System.Private.CoreLib/shared/System/IConvertible.cs index 7abd0c45c3ac..2b0c13425b3e 100644 --- a/src/System.Private.CoreLib/shared/System/IConvertible.cs +++ b/src/System.Private.CoreLib/shared/System/IConvertible.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { // The IConvertible interface represents an object that contains a value. This @@ -39,25 +40,25 @@ public interface IConvertible // implementation must throw an InvalidCastException. If the value of the // underlying object is not within the range of the target type, the // implementation must throw an OverflowException. The - // IFormatProvider will be used to get a NumberFormatInfo or similar + // IFormatProvider? will be used to get a NumberFormatInfo or similar // appropriate service object, and may safely be null. - bool ToBoolean(IFormatProvider provider); - char ToChar(IFormatProvider provider); - sbyte ToSByte(IFormatProvider provider); - byte ToByte(IFormatProvider provider); - short ToInt16(IFormatProvider provider); - ushort ToUInt16(IFormatProvider provider); - int ToInt32(IFormatProvider provider); - uint ToUInt32(IFormatProvider provider); - long ToInt64(IFormatProvider provider); - ulong ToUInt64(IFormatProvider provider); - float ToSingle(IFormatProvider provider); - double ToDouble(IFormatProvider provider); - decimal ToDecimal(IFormatProvider provider); - DateTime ToDateTime(IFormatProvider provider); - string ToString(IFormatProvider provider); - object ToType(Type conversionType, IFormatProvider provider); + bool ToBoolean(IFormatProvider? provider); + char ToChar(IFormatProvider? provider); + sbyte ToSByte(IFormatProvider? provider); + byte ToByte(IFormatProvider? provider); + short ToInt16(IFormatProvider? provider); + ushort ToUInt16(IFormatProvider? provider); + int ToInt32(IFormatProvider? provider); + uint ToUInt32(IFormatProvider? provider); + long ToInt64(IFormatProvider? provider); + ulong ToUInt64(IFormatProvider? provider); + float ToSingle(IFormatProvider? provider); + double ToDouble(IFormatProvider? provider); + decimal ToDecimal(IFormatProvider? provider); + DateTime ToDateTime(IFormatProvider? provider); + string ToString(IFormatProvider? provider); + object ToType(Type conversionType, IFormatProvider? provider); } } diff --git a/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs b/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs index cd798b4a1e27..df5d9b8cf438 100644 --- a/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs +++ b/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs @@ -12,13 +12,11 @@ ** ===========================================================*/ -using System; - +#nullable enable namespace System { public interface ICustomFormatter { - // Interface does not need to be marked with the serializable attribute - string Format(string format, object arg, IFormatProvider formatProvider); + string Format(string? format, object? arg, IFormatProvider? formatProvider); } } diff --git a/src/System.Private.CoreLib/shared/System/IDisposable.cs b/src/System.Private.CoreLib/shared/System/IDisposable.cs index 24f0740edced..fb89476b1529 100644 --- a/src/System.Private.CoreLib/shared/System/IDisposable.cs +++ b/src/System.Private.CoreLib/shared/System/IDisposable.cs @@ -12,6 +12,7 @@ ** ===========================================================*/ +#nullable enable namespace System { // IDisposable is an attempt at helping to solve problems with deterministic diff --git a/src/System.Private.CoreLib/shared/System/IEquatable.cs b/src/System.Private.CoreLib/shared/System/IEquatable.cs index 1264fdd57ac4..482f467f8529 100644 --- a/src/System.Private.CoreLib/shared/System/IEquatable.cs +++ b/src/System.Private.CoreLib/shared/System/IEquatable.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System { public interface IEquatable diff --git a/src/System.Private.CoreLib/shared/System/IFormatProvider.cs b/src/System.Private.CoreLib/shared/System/IFormatProvider.cs index 9369b074f98b..706dea8cc688 100644 --- a/src/System.Private.CoreLib/shared/System/IFormatProvider.cs +++ b/src/System.Private.CoreLib/shared/System/IFormatProvider.cs @@ -11,13 +11,12 @@ ** ============================================================*/ -using System; - +#nullable enable namespace System { public interface IFormatProvider { // Interface does not need to be marked with the serializable attribute - object GetFormat(Type formatType); + object? GetFormat(Type? formatType); } } diff --git a/src/System.Private.CoreLib/shared/System/IFormattable.cs b/src/System.Private.CoreLib/shared/System/IFormattable.cs index b5ed9bb45b6f..e3fa7c19f0a1 100644 --- a/src/System.Private.CoreLib/shared/System/IFormattable.cs +++ b/src/System.Private.CoreLib/shared/System/IFormattable.cs @@ -2,12 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System { public interface IFormattable { - string ToString(string format, IFormatProvider formatProvider); + string ToString(string? format, IFormatProvider? formatProvider); } } diff --git a/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs index 273d4c7cf983..280afe6665f4 100644 --- a/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs +++ b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs @@ -14,6 +14,7 @@ ** ============================================================*/ +#nullable enable using System.Buffers.Binary; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -29,8 +30,8 @@ public class BinaryReader : IDisposable private readonly Stream _stream; private readonly byte[] _buffer; private readonly Decoder _decoder; - private byte[] _charBytes; - private char[] _charBuffer; + private byte[]? _charBytes; + private char[]? _charBuffer; private int _maxCharsSize; // From MaxCharBytesSize & Encoding // Performance optimization for Read() w/ Unicode. Speeds us up by ~40% @@ -305,7 +306,7 @@ public virtual string ReadString() _charBuffer = new char[_maxCharsSize]; } - StringBuilder sb = null; + StringBuilder? sb = null; do { readLength = ((stringLength - currPos) > MaxCharBytesSize) ? MaxCharBytesSize : (stringLength - currPos); @@ -396,7 +397,7 @@ private int InternalReadChars(Span buffer) } int position = 0; - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (_isMemoryStream) { Debug.Assert(_stream is MemoryStream); @@ -580,7 +581,7 @@ private ReadOnlySpan InternalRead(int numBytes) // reasons. More about the subject in: https://github.com/dotnet/coreclr/pull/22102 protected virtual void FillBuffer(int numBytes) { - if (_buffer != null && (numBytes < 0 || numBytes > _buffer.Length)) + if (numBytes < 0 || numBytes > _buffer.Length) { throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_BinaryReaderFillBuffer); } diff --git a/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs index 9b6f865fe575..89ebf98f4bd0 100644 --- a/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs +++ b/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System.Diagnostics; using System.Buffers; @@ -25,7 +26,7 @@ public class BinaryWriter : IDisposable, IAsyncDisposable private bool _leaveOpen; // Perf optimization stuff - private byte[] _largeByteBuffer; // temp space for writing chars. + private byte[]? _largeByteBuffer; // temp space for writing chars. private int _maxChars; // max # of chars we can put in _largeByteBuffer // Size should be around the max number of chars/string * Encoding's max bytes/char private const int LargeByteBufferSize = 256; diff --git a/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs b/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs index a3a2d29837ca..cfb4b6667a7f 100644 --- a/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs +++ b/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if MS_IO_REDIST using System; diff --git a/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Unix.cs index 78ef95704fe9..c4eba1c24c5b 100644 --- a/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Text; diff --git a/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Windows.cs index 47dbcdd01db9..6d6c2eab77e7 100644 --- a/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/IO/DriveInfoInternal.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Text; @@ -51,7 +52,7 @@ public static string NormalizeDriveName(string driveName) { Debug.Assert(driveName != null); - string name; + string? name; if (driveName.Length == 1) { diff --git a/src/System.Private.CoreLib/shared/System/IO/EncodingCache.cs b/src/System.Private.CoreLib/shared/System/IO/EncodingCache.cs index 53379bc77f38..fb3795e5e266 100644 --- a/src/System.Private.CoreLib/shared/System/IO/EncodingCache.cs +++ b/src/System.Private.CoreLib/shared/System/IO/EncodingCache.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; namespace System.IO diff --git a/src/System.Private.CoreLib/shared/System/IO/Error.cs b/src/System.Private.CoreLib/shared/System/IO/Error.cs index 1e319a068039..db8095428ac8 100644 --- a/src/System.Private.CoreLib/shared/System/IO/Error.cs +++ b/src/System.Private.CoreLib/shared/System/IO/Error.cs @@ -2,11 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Runtime.InteropServices; -using System.Text; -using System.Globalization; - +#nullable enable namespace System.IO { /// diff --git a/src/System.Private.CoreLib/shared/System/IO/FileAccess.cs b/src/System.Private.CoreLib/shared/System/IO/FileAccess.cs index 1b70bae17297..2fd7408b85f5 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileAccess.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileAccess.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; namespace System.IO diff --git a/src/System.Private.CoreLib/shared/System/IO/FileMode.cs b/src/System.Private.CoreLib/shared/System/IO/FileMode.cs index 77f2fe6f20fb..39c74e50253f 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileMode.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileMode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.IO { // Contains constants for specifying how the OS should open a file. diff --git a/src/System.Private.CoreLib/shared/System/IO/FileOptions.cs b/src/System.Private.CoreLib/shared/System/IO/FileOptions.cs index ae8396a588f8..b11b9bb14017 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileOptions.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/System/IO/FileShare.cs b/src/System.Private.CoreLib/shared/System/IO/FileShare.cs index e9b9b5e32f98..12dc6e64ebc2 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileShare.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileShare.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; namespace System.IO diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs index 62e1fdec2574..f90b53c7d9c6 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs @@ -59,7 +59,7 @@ private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions op Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH; // Open the file and store the safe handle. - return SafeFileHandle.Open(_path, openFlags, (int)OpenPermissions); + return SafeFileHandle.Open(_path!, openFlags, (int)OpenPermissions); } private static bool GetDefaultIsAsync(SafeFileHandle handle) => handle.IsAsync ?? DefaultIsAsync; diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs index e3361aec62ab..f97f53153051 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs @@ -41,6 +41,7 @@ private unsafe SafeFileHandle CreateFileOpenHandle(FileMode mode, FileShare shar using (DisableMediaInsertionPrompt.Create()) { + Debug.Assert(_path != null); return ValidateFileHandle( Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero)); } diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs index 4de7a3b254e4..49e9812e0ae1 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs @@ -1374,7 +1374,7 @@ private async Task AsyncModeCopyToAsync(Stream destination, int bufferSize, Canc // Allocate a native overlapped for our reusable overlapped, and set position to read based on the next // desired address stored in the awaitable. (This position may be 0, if either we're at the beginning or // if the stream isn't seekable.) - readAwaitable._nativeOverlapped = _fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(awaitableOverlapped); + readAwaitable._nativeOverlapped = _fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(awaitableOverlapped); if (canSeek) { readAwaitable._nativeOverlapped->OffsetLow = unchecked((int)readAwaitable._position); @@ -1449,7 +1449,7 @@ private async Task AsyncModeCopyToAsync(Stream destination, int bufferSize, Canc } if (overlapped != null) { - _fileHandle.ThreadPoolBinding.FreeNativeOverlapped(overlapped); + _fileHandle.ThreadPoolBinding!.FreeNativeOverlapped(overlapped); } } } diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs index 54756a2edcbb..a1ad6291f736 100644 --- a/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs @@ -54,8 +54,8 @@ protected FileStreamCompletionSource(FileStream stream, int numBufferedBytes, by // The _preallocatedOverlapped is null if the internal buffer was never created, so we check for // a non-null bytes before using the stream's _preallocatedOverlapped _overlapped = bytes != null && _stream.CompareExchangeCurrentOverlappedOwner(this, null) == null ? - _stream._fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(_stream._preallocatedOverlapped!) : // allocated when buffer was created, and buffer is non-null - _stream._fileHandle.ThreadPoolBinding.AllocateNativeOverlapped(s_ioCallback, this, bytes); + _stream._fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_stream._preallocatedOverlapped!) : // allocated when buffer was created, and buffer is non-null + _stream._fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(s_ioCallback, this, bytes); Debug.Assert(_overlapped != null, "AllocateNativeOverlapped returned null"); } @@ -118,7 +118,7 @@ internal virtual void ReleaseNativeResource() // (this is why we disposed the registration above). if (_overlapped != null) { - _stream._fileHandle.ThreadPoolBinding.FreeNativeOverlapped(_overlapped); + _stream._fileHandle.ThreadPoolBinding!.FreeNativeOverlapped(_overlapped); _overlapped = null; } diff --git a/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs index bb9fa29adca3..7377271315c9 100644 --- a/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs +++ b/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs @@ -452,7 +452,7 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken // it then fall back to doing the ArrayPool/copy behavior. return new ValueTask( MemoryMarshal.TryGetArray(buffer, out ArraySegment destinationArray) ? - Read(destinationArray.Array, destinationArray.Offset, destinationArray.Count) : + Read(destinationArray.Array!, destinationArray.Offset, destinationArray.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 Read(buffer.Span)); } catch (OperationCanceledException oce) @@ -767,7 +767,7 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo // Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency. if (MemoryMarshal.TryGetArray(buffer, out ArraySegment sourceArray)) { - Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count); + Write(sourceArray.Array!, sourceArray.Offset, sourceArray.Count); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } else { diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs index ecf71e612702..f8c93d65160d 100644 --- a/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; @@ -77,7 +78,7 @@ public static string GetTempPath() // Get the temp path from the TMPDIR environment variable. // If it's not set, just return the default path. // If it is, return it, ensuring it ends with a slash. - string path = Environment.GetEnvironmentVariable(TempEnvVar); + string? path = Environment.GetEnvironmentVariable(TempEnvVar); return string.IsNullOrEmpty(path) ? DefaultTempPath : PathInternal.IsDirectorySeparator(path[path.Length - 1]) ? path : @@ -103,7 +104,7 @@ public static string GetTempFileName() return Encoding.UTF8.GetString(name, 0, name.Length - 1); // trim off the trailing '\0' } - public static bool IsPathRooted(string path) + public static bool IsPathRooted(string? path) { if (path == null) return false; @@ -119,7 +120,7 @@ public static bool IsPathRooted(ReadOnlySpan path) /// /// Returns the path root or null if path is empty or null. /// - public static string GetPathRoot(string path) + public static string? GetPathRoot(string? path) { if (PathInternal.IsEffectivelyEmpty(path)) return null; diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs index ddfd7966befd..71a986eeef4a 100644 --- a/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Text; @@ -83,7 +84,7 @@ public static string GetFullPath(string path, string basePath) return basePath; int length = path.Length; - string combinedPath = null; + string? combinedPath = null; if ((length >= 1 && PathInternal.IsDirectorySeparator(path[0]))) { @@ -189,7 +190,7 @@ public static string GetTempFileName() // Tests if the given path contains a root. A path is considered rooted // if it starts with a backslash ("\") or a valid drive letter and a colon (":"). - public static bool IsPathRooted(string path) + public static bool IsPathRooted(string? path) { return path != null && IsPathRooted(path.AsSpan()); } @@ -210,13 +211,13 @@ public static bool IsPathRooted(ReadOnlySpan path) // and "\\server\share" (a UNC path for a given server and share name). // The resulting string is null if path is null. If the path is empty or // only contains whitespace characters an ArgumentException gets thrown. - public static string GetPathRoot(string path) + public static string? GetPathRoot(string? path) { if (PathInternal.IsEffectivelyEmpty(path.AsSpan())) return null; ReadOnlySpan result = GetPathRoot(path.AsSpan()); - if (path.Length == result.Length) + if (path!.Length == result.Length) return PathInternal.NormalizeDirectorySeparators(path); return PathInternal.NormalizeDirectorySeparators(result.ToString()); diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.cs b/src/System.Private.CoreLib/shared/System/IO/Path.cs index 23da520db2ae..db491bfdc00f 100644 --- a/src/System.Private.CoreLib/shared/System/IO/Path.cs +++ b/src/System.Private.CoreLib/shared/System/IO/Path.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; @@ -45,7 +46,7 @@ public static partial class Path // returns null. If path does not contain a file extension, // the new file extension is appended to the path. If extension // is null, any existing extension is removed from path. - public static string ChangeExtension(string path, string extension) + public static string? ChangeExtension(string? path, string? extension) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (path == null) return null; @@ -98,7 +99,7 @@ public static string ChangeExtension(string path, string extension) /// /// Directory separators are normalized in the returned string. /// - public static string GetDirectoryName(string path) + public static string? GetDirectoryName(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (path == null || PathInternal.IsEffectivelyEmpty(path.AsSpan())) return null; @@ -146,7 +147,7 @@ private static int GetDirectoryNameOffset(ReadOnlySpan path) /// The returned value is null if the given path is null or empty if the given path does not include an /// extension. /// - public static string GetExtension(string path) + public static string? GetExtension(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (path == null) return null; @@ -185,7 +186,7 @@ public static ReadOnlySpan GetExtension(ReadOnlySpan path) /// the characters of path that follow the last separator in path. The resulting string is /// null if path is null. /// - public static string GetFileName(string path) + public static string? GetFileName(string? path) { if (path == null) return null; @@ -216,7 +217,7 @@ public static ReadOnlySpan GetFileName(ReadOnlySpan path) return path; } - public static string GetFileNameWithoutExtension(string path) + public static string? GetFileNameWithoutExtension(string? path) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (path == null) return null; @@ -290,7 +291,7 @@ public static bool IsPathFullyQualified(ReadOnlySpan path) /// Tests if a path's file name includes a file extension. A trailing period /// is not considered an extension. /// - public static bool HasExtension(string path) + public static bool HasExtension(string? path) { if (path != null) { @@ -433,12 +434,12 @@ public static string Join(ReadOnlySpan path1, ReadOnlySpan path2, Re return JoinInternal(path1, path2, path3); } - public static string Join(string path1, string path2) + public static string Join(string? path1, string? path2) { return Join(path1.AsSpan(), path2.AsSpan()); } - public static string Join(string path1, string path2, string path3) + public static string Join(string? path1, string? path2, string? path3) { return Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan()); } diff --git a/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs index a30ead11e254..f494412a52f2 100644 --- a/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; @@ -126,7 +127,7 @@ internal static int PrependDevicePathChars(ref ValueStringBuilder content, bool } } - internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath) + internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string? originalPath) { // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls. diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Unix.cs index fae309be5651..1888c85a1b34 100644 --- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Text; using System.Runtime.InteropServices; @@ -89,7 +90,7 @@ internal static bool IsPartiallyQualified(ReadOnlySpan path) /// For unix, this is empty or null. For Windows, this is empty, null, or /// just spaces ((char)32). /// - internal static bool IsEffectivelyEmpty(string path) + internal static bool IsEffectivelyEmpty(string? path) { return string.IsNullOrEmpty(path); } diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs index 5e9e61303461..40ed96f63c3a 100644 --- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Text; @@ -70,7 +71,7 @@ internal static bool IsValidDriveChar(char value) return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z')); } - internal static bool EndsWithPeriodOrSpace(string path) + internal static bool EndsWithPeriodOrSpace(string? path) { if (string.IsNullOrEmpty(path)) return false; @@ -86,7 +87,7 @@ internal static bool EndsWithPeriodOrSpace(string path) /// away from paths during normalization, but if we see such a path at this point it should be /// normalized and has retained the final characters. (Typically from one of the *Info classes) /// - internal static string EnsureExtendedPrefixIfNeeded(string path) + internal static string? EnsureExtendedPrefixIfNeeded(string? path) { if (path != null && (path.Length >= MaxShortPath || EndsWithPeriodOrSpace(path))) { @@ -98,23 +99,6 @@ internal static string EnsureExtendedPrefixIfNeeded(string path) } } - /// - /// DO NOT USE- Use EnsureExtendedPrefixIfNeeded. This will be removed shortly. - /// Adds the extended path prefix (\\?\) if not already a device path, IF the path is not relative, - /// AND the path is more than 259 characters. (> MAX_PATH + null) - /// - internal static string EnsureExtendedPrefixOverMaxPath(string path) - { - if (path != null && path.Length >= MaxShortPath) - { - return EnsureExtendedPrefix(path); - } - else - { - return path; - } - } - /// /// Adds the extended path prefix (\\?\) if not relative or already a device path. /// diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs index c6e1de46c8d7..549a2d18b29e 100644 --- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs +++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Text; diff --git a/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Names.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Names.Unix.cs index 8984f1aee32b..03bfc0251009 100644 --- a/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Names.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Names.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.IO { internal static partial class PersistedFiles diff --git a/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Unix.cs index d8064af2b761..8dfa2f19456b 100644 --- a/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/IO/PersistedFiles.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; @@ -9,7 +10,7 @@ namespace System.IO { internal static partial class PersistedFiles { - private static string s_userProductDirectory; + private static string? s_userProductDirectory; /// /// Get the location of where to persist information for a particular aspect of the framework, @@ -24,7 +25,7 @@ internal static string GetUserFeatureDirectory(string featureName) EnsureUserDirectories(); } - return Path.Combine(s_userProductDirectory, featureName); + return Path.Combine(s_userProductDirectory!, featureName); } /// @@ -41,7 +42,7 @@ internal static string GetUserFeatureDirectory(string featureName, string subFea EnsureUserDirectories(); } - return Path.Combine(s_userProductDirectory, featureName, subFeatureName); + return Path.Combine(s_userProductDirectory!, featureName, subFeatureName); } /// @@ -60,12 +61,12 @@ internal static string GetUserFeatureDirectory(params string[] featurePathParts) EnsureUserDirectories(); } - return Path.Combine(s_userProductDirectory, Path.Combine(featurePathParts)); + return Path.Combine(s_userProductDirectory!, Path.Combine(featurePathParts)); } private static void EnsureUserDirectories() { - string userHomeDirectory = GetHomeDirectory(); + string? userHomeDirectory = GetHomeDirectory(); if (string.IsNullOrEmpty(userHomeDirectory)) { @@ -80,11 +81,11 @@ private static void EnsureUserDirectories() /// Gets the current user's home directory. /// The path to the home directory, or null if it could not be determined. - internal static string GetHomeDirectory() + internal static string? GetHomeDirectory() { // First try to get the user's home directory from the HOME environment variable. // This should work in most cases. - string userHomeDirectory = Environment.GetEnvironmentVariable("HOME"); + string? userHomeDirectory = Environment.GetEnvironmentVariable("HOME"); if (!string.IsNullOrEmpty(userHomeDirectory)) return userHomeDirectory; @@ -123,7 +124,7 @@ internal static string GetHomeDirectory() /// The length of . /// The resulting path; null if the user didn't have an entry. /// true if the call was successful (path may still be null); false is a larger buffer is needed. - private static unsafe bool TryGetHomeDirectoryFromPasswd(byte* buf, int bufLen, out string path) + private static unsafe bool TryGetHomeDirectoryFromPasswd(byte* buf, int bufLen, out string? path) { // Call getpwuid_r to get the passwd struct Interop.Sys.Passwd passwd; diff --git a/src/System.Private.CoreLib/shared/System/IO/SeekOrigin.cs b/src/System.Private.CoreLib/shared/System/IO/SeekOrigin.cs index 3798a0ce7022..e1da4d5853d3 100644 --- a/src/System.Private.CoreLib/shared/System/IO/SeekOrigin.cs +++ b/src/System.Private.CoreLib/shared/System/IO/SeekOrigin.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.IO { // Provides seek reference points. To seek to the end of a stream, diff --git a/src/System.Private.CoreLib/shared/System/IO/Stream.cs b/src/System.Private.CoreLib/shared/System/IO/Stream.cs index 1f0943f2fcb3..55ae9007c8b4 100644 --- a/src/System.Private.CoreLib/shared/System/IO/Stream.cs +++ b/src/System.Private.CoreLib/shared/System/IO/Stream.cs @@ -381,7 +381,7 @@ public virtual ValueTask ReadAsync(Memory buffer, CancellationToken c { if (MemoryMarshal.TryGetArray(buffer, out ArraySegment array)) { - return new ValueTask(ReadAsync(array.Array, array.Offset, array.Count, cancellationToken)); + return new ValueTask(ReadAsync(array.Array!, array.Offset, array.Count, cancellationToken)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } else { @@ -692,7 +692,7 @@ public virtual ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTok { if (MemoryMarshal.TryGetArray(buffer, out ArraySegment array)) { - return new ValueTask(WriteAsync(array.Array, array.Offset, array.Count, cancellationToken)); + return new ValueTask(WriteAsync(array.Array!, array.Offset, array.Count, cancellationToken)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } else { diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs b/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs index bc5c00f986bb..9d836c0b98b2 100644 --- a/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs +++ b/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text; @@ -28,10 +29,10 @@ public class StreamReader : TextReader private const int MinBufferSize = 128; private readonly Stream _stream; - private Encoding _encoding; - private Decoder _decoder; - private readonly byte[] _byteBuffer; - private char[] _charBuffer; + private Encoding _encoding = null!; // only null in NullStreamReader where this is never used + private Decoder _decoder = null!; // only null in NullStreamReader where this is never used + private readonly byte[] _byteBuffer = null!; // only null in NullStreamReader where this is never used + private char[] _charBuffer = null!; // only null in NullStreamReader where this is never used private int _charPos; private int _charLen; // Record the number of valid bytes in the byteBuffer, for a few checks. @@ -94,6 +95,7 @@ private static void ThrowAsyncIOInProgress() => private StreamReader() { + Debug.Assert(this is NullStreamReader); _stream = Stream.Null; _closable = true; } @@ -769,7 +771,7 @@ private int ReadBuffer(Span userBuffer, out bool readToUserBuffer) // contain the terminating carriage return and/or line feed. The returned // value is null if the end of the input stream has been reached. // - public override string ReadLine() + public override string? ReadLine() { ThrowIfDisposed(); CheckAsyncTaskInProgress(); @@ -782,7 +784,7 @@ public override string ReadLine() } } - StringBuilder sb = null; + StringBuilder? sb = null; do { int i = _charPos; @@ -825,7 +827,7 @@ public override string ReadLine() return sb.ToString(); } - public override Task ReadLineAsync() + public override Task ReadLineAsync() { // If we have been inherited into a subclass, the following implementation could be incorrect // since it does not call through to Read() which a subclass might have overridden. @@ -839,20 +841,20 @@ public override Task ReadLineAsync() ThrowIfDisposed(); CheckAsyncTaskInProgress(); - Task task = ReadLineAsyncInternal(); + Task task = ReadLineAsyncInternal(); _asyncReadTask = task; return task; } - private async Task ReadLineAsyncInternal() + private async Task ReadLineAsyncInternal() { if (_charPos == _charLen && (await ReadBufferAsync().ConfigureAwait(false)) == 0) { return null; } - StringBuilder sb = null; + StringBuilder? sb = null; do { @@ -1342,7 +1344,7 @@ public override int Read(char[] buffer, int index, int count) return 0; } - public override string ReadLine() + public override string? ReadLine() { return null; } diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs index 8140d796480a..3a999195bc1d 100644 --- a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs +++ b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -335,7 +336,7 @@ public override void Write(char value) } [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites - public override void Write(char[] buffer) + public override void Write(char[]? buffer) { WriteSpan(buffer, appendNewLine: false); } @@ -453,13 +454,13 @@ private unsafe void WriteSpan(ReadOnlySpan buffer, bool appendNewLine) } [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites - public override void Write(string value) + public override void Write(string? value) { WriteSpan(value, appendNewLine: false); } [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites - public override void WriteLine(string value) + public override void WriteLine(string? value) { CheckAsyncTaskInProgress(); WriteSpan(value, appendNewLine: true); @@ -484,8 +485,8 @@ public override void WriteLine(ReadOnlySpan value) private void WriteFormatHelper(string format, ParamsArray args, bool appendNewLine) { StringBuilder sb = - StringBuilderCache.Acquire(format.Length + args.Length * 8) - .AppendFormatHelper(null, format, args); + StringBuilderCache.Acquire((format?.Length ?? 0) + args.Length * 8) + .AppendFormatHelper(null, format!, args); // AppendFormatHelper will appropriately throw ArgumentNullException for a null format StringBuilder.ChunkEnumerator chunks = sb.GetChunks(); @@ -502,7 +503,7 @@ private void WriteFormatHelper(string format, ParamsArray args, bool appendNewLi StringBuilderCache.Release(sb); } - public override void Write(string format, object arg0) + public override void Write(string format, object? arg0) { if (GetType() == typeof(StreamWriter)) { @@ -514,7 +515,7 @@ public override void Write(string format, object arg0) } } - public override void Write(string format, object arg0, object arg1) + public override void Write(string format, object? arg0, object? arg1) { if (GetType() == typeof(StreamWriter)) { @@ -526,7 +527,7 @@ public override void Write(string format, object arg0, object arg1) } } - public override void Write(string format, object arg0, object arg1, object arg2) + public override void Write(string format, object? arg0, object? arg1, object? arg2) { if (GetType() == typeof(StreamWriter)) { @@ -538,10 +539,14 @@ public override void Write(string format, object arg0, object arg1, object arg2) } } - public override void Write(string format, params object[] arg) + public override void Write(string format, params object?[] arg) { if (GetType() == typeof(StreamWriter)) { + if (arg == null) + { + throw new ArgumentNullException((format == null) ? nameof(format) : nameof(arg)); // same as base logic + } WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: false); } else @@ -550,7 +555,7 @@ public override void Write(string format, params object[] arg) } } - public override void WriteLine(string format, object arg0) + public override void WriteLine(string format, object? arg0) { if (GetType() == typeof(StreamWriter)) { @@ -562,7 +567,7 @@ public override void WriteLine(string format, object arg0) } } - public override void WriteLine(string format, object arg0, object arg1) + public override void WriteLine(string format, object? arg0, object? arg1) { if (GetType() == typeof(StreamWriter)) { @@ -574,7 +579,7 @@ public override void WriteLine(string format, object arg0, object arg1) } } - public override void WriteLine(string format, object arg0, object arg1, object arg2) + public override void WriteLine(string format, object? arg0, object? arg1, object? arg2) { if (GetType() == typeof(StreamWriter)) { @@ -586,10 +591,14 @@ public override void WriteLine(string format, object arg0, object arg1, object a } } - public override void WriteLine(string format, params object[] arg) + public override void WriteLine(string format, params object?[] arg) { if (GetType() == typeof(StreamWriter)) { + if (arg == null) + { + throw new ArgumentNullException(nameof(arg)); + } WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: true); } else @@ -661,7 +670,7 @@ private static async Task WriteAsyncInternal(StreamWriter _this, char value, _this.CharPos_Prop = charPos; } - public override Task WriteAsync(string value) + public override Task WriteAsync(string? value) { // If we have been inherited into a subclass, the following implementation could be incorrect // since it does not call through to Write() which a subclass might have overridden. @@ -901,7 +910,7 @@ public override Task WriteLineAsync(char value) } - public override Task WriteLineAsync(string value) + public override Task WriteLineAsync(string? value) { if (value == null) { diff --git a/src/System.Private.CoreLib/shared/System/IO/TextReader.cs b/src/System.Private.CoreLib/shared/System/IO/TextReader.cs index c1a9fd6c97c1..e2f0af91788d 100644 --- a/src/System.Private.CoreLib/shared/System/IO/TextReader.cs +++ b/src/System.Private.CoreLib/shared/System/IO/TextReader.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System.Threading; using System.Threading.Tasks; @@ -178,7 +179,7 @@ public virtual int ReadBlock(Span buffer) // contain the terminating carriage return and/or line feed. The returned // value is null if the end of the input stream has been reached. // - public virtual string ReadLine() + public virtual string? ReadLine() { StringBuilder sb = new StringBuilder(); while (true) @@ -205,11 +206,11 @@ public virtual string ReadLine() } #region Task based Async APIs - public virtual Task ReadLineAsync() + public virtual Task ReadLineAsync() { - return Task.Factory.StartNew(state => + return Task.Factory.StartNew(state => { - return ((TextReader)state).ReadLine(); + return ((TextReader)state!).ReadLine(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 }, this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } @@ -253,10 +254,10 @@ public virtual Task ReadAsync(char[] buffer, int index, int count) public virtual ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) => new ValueTask(MemoryMarshal.TryGetArray(buffer, out ArraySegment array) ? - ReadAsync(array.Array, array.Offset, array.Count) : + ReadAsync(array.Array!, array.Offset, array.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 Task.Factory.StartNew(state => { - var t = (Tuple>)state; + var t = (Tuple>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return t.Item1.Read(t.Item2.Span); }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)); @@ -265,7 +266,7 @@ internal virtual ValueTask ReadAsyncInternal(Memory buffer, Cancellat var tuple = new Tuple>(this, buffer); return new ValueTask(Task.Factory.StartNew(state => { - var t = (Tuple>)state; + var t = (Tuple>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return t.Item1.Read(t.Item2.Span); }, tuple, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)); @@ -291,10 +292,10 @@ public virtual Task ReadBlockAsync(char[] buffer, int index, int count) public virtual ValueTask ReadBlockAsync(Memory buffer, CancellationToken cancellationToken = default) => new ValueTask(MemoryMarshal.TryGetArray(buffer, out ArraySegment array) ? - ReadBlockAsync(array.Array, array.Offset, array.Count) : + ReadBlockAsync(array.Array!, array.Offset, array.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 Task.Factory.StartNew(state => { - var t = (Tuple>)state; + var t = (Tuple>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return t.Item1.ReadBlock(t.Item2.Span); }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)); @@ -320,7 +321,7 @@ public override int Read(char[] buffer, int index, int count) return 0; } - public override string ReadLine() + public override string? ReadLine() { return null; } @@ -367,7 +368,7 @@ protected override void Dispose(bool disposing) public override int ReadBlock(char[] buffer, int index, int count) => _in.ReadBlock(buffer, index, count); [MethodImpl(MethodImplOptions.Synchronized)] - public override string ReadLine() => _in.ReadLine(); + public override string? ReadLine() => _in.ReadLine(); [MethodImpl(MethodImplOptions.Synchronized)] public override string ReadToEnd() => _in.ReadToEnd(); @@ -377,7 +378,7 @@ protected override void Dispose(bool disposing) // [MethodImpl(MethodImplOptions.Synchronized)] - public override Task ReadLineAsync() => Task.FromResult(ReadLine()); + public override Task ReadLineAsync() => Task.FromResult(ReadLine()); [MethodImpl(MethodImplOptions.Synchronized)] public override Task ReadToEndAsync() => Task.FromResult(ReadToEnd()); diff --git a/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs b/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs index baf53b480ae3..f648df0ce60d 100644 --- a/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs +++ b/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System.Threading; using System.Globalization; @@ -36,14 +37,14 @@ public abstract partial class TextWriter : MarshalByRefObject, IDisposable, IAsy private string CoreNewLineStr = Environment.NewLine; // Can be null - if so, ask for the Thread's CurrentCulture every time. - private IFormatProvider _internalFormatProvider; + private IFormatProvider? _internalFormatProvider; protected TextWriter() { _internalFormatProvider = null; // Ask for CurrentCulture all the time. } - protected TextWriter(IFormatProvider formatProvider) + protected TextWriter(IFormatProvider? formatProvider) { _internalFormatProvider = formatProvider; } @@ -117,7 +118,7 @@ public abstract Encoding Encoding /// the TextWriter to be readable by a TextReader, only one of the following line /// terminator strings should be used: "\r", "\n", or "\r\n". /// - public virtual string NewLine + public virtual string? NewLine // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 { get { return CoreNewLineStr; } set @@ -145,7 +146,7 @@ public virtual void Write(char value) // Write(char) for each of the characters in the character array. // If the character array is null, nothing is written. // - public virtual void Write(char[] buffer) + public virtual void Write(char[]? buffer) { if (buffer != null) { @@ -268,7 +269,7 @@ public virtual void Write(decimal value) // Writes a string to the text stream. If the given string is null, nothing // is written to the text stream. // - public virtual void Write(string value) + public virtual void Write(string? value) { if (value != null) { @@ -282,7 +283,7 @@ public virtual void Write(string value) // string representation, and the resulting string is then written to the // output stream. // - public virtual void Write(object value) + public virtual void Write(object? value) { if (value != null) { @@ -300,7 +301,7 @@ public virtual void Write(object value) /// StringBuilder.GetChunks() method to avoid creating the intermediate string /// /// The string (as a StringBuilder) to write to the stream - public virtual void Write(StringBuilder value) + public virtual void Write(StringBuilder? value) { if (value != null) { @@ -312,7 +313,7 @@ public virtual void Write(StringBuilder value) // Writes out a formatted string. Uses the same semantics as // string.Format. // - public virtual void Write(string format, object arg0) + public virtual void Write(string format, object? arg0) { Write(string.Format(FormatProvider, format, arg0)); } @@ -320,7 +321,7 @@ public virtual void Write(string format, object arg0) // Writes out a formatted string. Uses the same semantics as // string.Format. // - public virtual void Write(string format, object arg0, object arg1) + public virtual void Write(string format, object? arg0, object? arg1) { Write(string.Format(FormatProvider, format, arg0, arg1)); } @@ -328,7 +329,7 @@ public virtual void Write(string format, object arg0, object arg1) // Writes out a formatted string. Uses the same semantics as // string.Format. // - public virtual void Write(string format, object arg0, object arg1, object arg2) + public virtual void Write(string format, object? arg0, object? arg1, object? arg2) { Write(string.Format(FormatProvider, format, arg0, arg1, arg2)); } @@ -336,7 +337,7 @@ public virtual void Write(string format, object arg0, object arg1, object arg2) // Writes out a formatted string. Uses the same semantics as // string.Format. // - public virtual void Write(string format, params object[] arg) + public virtual void Write(string format, params object?[] arg) { Write(string.Format(FormatProvider, format, arg)); } @@ -361,7 +362,7 @@ public virtual void WriteLine(char value) // Writes an array of characters followed by a line terminator to the text // stream. // - public virtual void WriteLine(char[] buffer) + public virtual void WriteLine(char[]? buffer) { Write(buffer); WriteLine(); @@ -464,7 +465,7 @@ public virtual void WriteLine(decimal value) // Writes a string followed by a line terminator to the text stream. // - public virtual void WriteLine(string value) + public virtual void WriteLine(string? value) { if (value != null) { @@ -477,7 +478,7 @@ public virtual void WriteLine(string value) /// Equivalent to WriteLine(stringBuilder.ToString()) however it uses the /// StringBuilder.GetChunks() method to avoid creating the intermediate string /// - public virtual void WriteLine(StringBuilder value) + public virtual void WriteLine(StringBuilder? value) { Write(value); WriteLine(); @@ -486,7 +487,7 @@ public virtual void WriteLine(StringBuilder value) // Writes the text representation of an object followed by a line // terminator to the text stream. // - public virtual void WriteLine(object value) + public virtual void WriteLine(object? value) { if (value == null) { @@ -510,7 +511,7 @@ public virtual void WriteLine(object value) // Writes out a formatted string and a new line. Uses the same // semantics as string.Format. // - public virtual void WriteLine(string format, object arg0) + public virtual void WriteLine(string format, object? arg0) { WriteLine(string.Format(FormatProvider, format, arg0)); } @@ -518,7 +519,7 @@ public virtual void WriteLine(string format, object arg0) // Writes out a formatted string and a new line. Uses the same // semantics as string.Format. // - public virtual void WriteLine(string format, object arg0, object arg1) + public virtual void WriteLine(string format, object? arg0, object? arg1) { WriteLine(string.Format(FormatProvider, format, arg0, arg1)); } @@ -526,7 +527,7 @@ public virtual void WriteLine(string format, object arg0, object arg1) // Writes out a formatted string and a new line. Uses the same // semantics as string.Format. // - public virtual void WriteLine(string format, object arg0, object arg1, object arg2) + public virtual void WriteLine(string format, object? arg0, object? arg1, object? arg2) { WriteLine(string.Format(FormatProvider, format, arg0, arg1, arg2)); } @@ -534,7 +535,7 @@ public virtual void WriteLine(string format, object arg0, object arg1, object ar // Writes out a formatted string and a new line. Uses the same // semantics as string.Format. // - public virtual void WriteLine(string format, params object[] arg) + public virtual void WriteLine(string format, params object?[] arg) { WriteLine(string.Format(FormatProvider, format, arg)); } @@ -545,18 +546,18 @@ public virtual Task WriteAsync(char value) var tuple = new Tuple(this, value); return Task.Factory.StartNew(state => { - var t = (Tuple)state; + var t = (Tuple)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.Write(t.Item2); }, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - public virtual Task WriteAsync(string value) + public virtual Task WriteAsync(string? value) { - var tuple = new Tuple(this, value); + var tuple = new Tuple(this, value); return Task.Factory.StartNew(state => { - var t = (Tuple)state; + var t = (Tuple)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.Write(t.Item2); }, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -567,7 +568,7 @@ public virtual Task WriteAsync(string value) /// StringBuilder.GetChunks() method to avoid creating the intermediate string /// /// The string (as a StringBuilder) to write to the stream - public virtual Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default) + public virtual Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default) { return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : @@ -583,7 +584,7 @@ async Task WriteAsyncCore(StringBuilder sb, CancellationToken ct) } } - public Task WriteAsync(char[] buffer) + public Task WriteAsync(char[]? buffer) { if (buffer == null) { @@ -598,7 +599,7 @@ public virtual Task WriteAsync(char[] buffer, int index, int count) var tuple = new Tuple(this, buffer, index, count); return Task.Factory.StartNew(state => { - var t = (Tuple)state; + var t = (Tuple)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.Write(t.Item2, t.Item3, t.Item4); }, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -606,11 +607,11 @@ public virtual Task WriteAsync(char[] buffer, int index, int count) public virtual Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : - MemoryMarshal.TryGetArray(buffer, out ArraySegment array) ? - WriteAsync(array.Array, array.Offset, array.Count) : + MemoryMarshal.TryGetArray(buffer, out ArraySegment array) ? // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + WriteAsync(array.Array!, array.Offset, array.Count) : Task.Factory.StartNew(state => { - var t = (Tuple>)state; + var t = (Tuple>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.Write(t.Item2.Span); }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -619,18 +620,18 @@ public virtual Task WriteLineAsync(char value) var tuple = new Tuple(this, value); return Task.Factory.StartNew(state => { - var t = (Tuple)state; + var t = (Tuple)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.WriteLine(t.Item2); }, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } - public virtual Task WriteLineAsync(string value) + public virtual Task WriteLineAsync(string? value) { - var tuple = new Tuple(this, value); + var tuple = new Tuple(this, value); return Task.Factory.StartNew(state => { - var t = (Tuple)state; + var t = (Tuple)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.WriteLine(t.Item2); }, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -641,7 +642,7 @@ public virtual Task WriteLineAsync(string value) /// StringBuilder.GetChunks() method to avoid creating the intermediate string /// /// The string (as a StringBuilder) to write to the stream - public virtual Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default) + public virtual Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default) { return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : @@ -658,7 +659,7 @@ async Task WriteLineAsyncCore(StringBuilder sb, CancellationToken ct) } } - public Task WriteLineAsync(char[] buffer) + public Task WriteLineAsync(char[]? buffer) { if (buffer == null) { @@ -673,7 +674,7 @@ public virtual Task WriteLineAsync(char[] buffer, int index, int count) var tuple = new Tuple(this, buffer, index, count); return Task.Factory.StartNew(state => { - var t = (Tuple)state; + var t = (Tuple)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.WriteLine(t.Item2, t.Item3, t.Item4); }, tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -681,11 +682,11 @@ public virtual Task WriteLineAsync(char[] buffer, int index, int count) public virtual Task WriteLineAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : - MemoryMarshal.TryGetArray(buffer, out ArraySegment array) ? - WriteLineAsync(array.Array, array.Offset, array.Count) : + MemoryMarshal.TryGetArray(buffer, out ArraySegment array) ? // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + WriteLineAsync(array.Array!, array.Offset, array.Count) : Task.Factory.StartNew(state => { - var t = (Tuple>)state; + var t = (Tuple>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 t.Item1.WriteLine(t.Item2.Span); }, Tuple.Create(this, buffer), cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -698,7 +699,7 @@ public virtual Task FlushAsync() { return Task.Factory.StartNew(state => { - ((TextWriter)state).Flush(); + ((TextWriter)state!).Flush(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 }, this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); } @@ -722,7 +723,7 @@ public override void Write(char[] buffer, int index, int count) { } - public override void Write(string value) + public override void Write(string? value) { } @@ -732,11 +733,11 @@ public override void WriteLine() } // Not strictly necessary, but for perf reasons - public override void WriteLine(string value) + public override void WriteLine(string? value) { } - public override void WriteLine(object value) + public override void WriteLine(object? value) { } @@ -762,11 +763,11 @@ internal SyncTextWriter(TextWriter t) : base(t.FormatProvider) _out = t; } - public override Encoding Encoding => _out.Encoding; + public override Encoding Encoding => _out.Encoding; public override IFormatProvider FormatProvider => _out.FormatProvider; - public override string NewLine + public override string? NewLine { [MethodImpl(MethodImplOptions.Synchronized)] get { return _out.NewLine; } @@ -792,7 +793,7 @@ protected override void Dispose(bool disposing) public override void Write(char value) => _out.Write(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(char[] buffer) => _out.Write(buffer); + public override void Write(char[]? buffer) => _out.Write(buffer); [MethodImpl(MethodImplOptions.Synchronized)] public override void Write(char[] buffer, int index, int count) => _out.Write(buffer, index, count); @@ -825,25 +826,25 @@ protected override void Dispose(bool disposing) public override void Write(decimal value) => _out.Write(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(string value) => _out.Write(value); + public override void Write(string? value) => _out.Write(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(StringBuilder value) => _out.Write(value); + public override void Write(StringBuilder? value) => _out.Write(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(object value) => _out.Write(value); + public override void Write(object? value) => _out.Write(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(string format, object arg0) => _out.Write(format, arg0); + public override void Write(string format, object? arg0) => _out.Write(format, arg0); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(string format, object arg0, object arg1) => _out.Write(format, arg0, arg1); + public override void Write(string format, object? arg0, object? arg1) => _out.Write(format, arg0, arg1); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(string format, object arg0, object arg1, object arg2) => _out.Write(format, arg0, arg1, arg2); + public override void Write(string format, object? arg0, object? arg1, object? arg2) => _out.Write(format, arg0, arg1, arg2); [MethodImpl(MethodImplOptions.Synchronized)] - public override void Write(string format, object[] arg) => _out.Write(format, arg); + public override void Write(string format, object?[] arg) => _out.Write(format, arg); [MethodImpl(MethodImplOptions.Synchronized)] public override void WriteLine() => _out.WriteLine(); @@ -855,7 +856,7 @@ protected override void Dispose(bool disposing) public override void WriteLine(decimal value) => _out.WriteLine(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(char[] buffer) => _out.WriteLine(buffer); + public override void WriteLine(char[]? buffer) => _out.WriteLine(buffer); [MethodImpl(MethodImplOptions.Synchronized)] public override void WriteLine(char[] buffer, int index, int count) => _out.WriteLine(buffer, index, count); @@ -885,25 +886,25 @@ protected override void Dispose(bool disposing) public override void WriteLine(double value) => _out.WriteLine(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(string value) => _out.WriteLine(value); + public override void WriteLine(string? value) => _out.WriteLine(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(StringBuilder value) => _out.WriteLine(value); + public override void WriteLine(StringBuilder? value) => _out.WriteLine(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(object value) => _out.WriteLine(value); + public override void WriteLine(object? value) => _out.WriteLine(value); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(string format, object arg0) => _out.WriteLine(format, arg0); + public override void WriteLine(string format, object? arg0) => _out.WriteLine(format, arg0); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(string format, object arg0, object arg1) => _out.WriteLine(format, arg0, arg1); + public override void WriteLine(string format, object? arg0, object? arg1) => _out.WriteLine(format, arg0, arg1); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(string format, object arg0, object arg1, object arg2) => _out.WriteLine(format, arg0, arg1, arg2); + public override void WriteLine(string format, object? arg0, object? arg1, object? arg2) => _out.WriteLine(format, arg0, arg1, arg2); [MethodImpl(MethodImplOptions.Synchronized)] - public override void WriteLine(string format, object[] arg) => _out.WriteLine(format, arg); + public override void WriteLine(string format, object?[] arg) => _out.WriteLine(format, arg); // // On SyncTextWriter all APIs should run synchronously, even the async ones. @@ -924,14 +925,14 @@ public override Task WriteAsync(char value) } [MethodImpl(MethodImplOptions.Synchronized)] - public override Task WriteAsync(string value) + public override Task WriteAsync(string? value) { Write(value); return Task.CompletedTask; } [MethodImpl(MethodImplOptions.Synchronized)] - public override Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default) + public override Task WriteAsync(StringBuilder? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -988,14 +989,14 @@ public override Task WriteLineAsync() } [MethodImpl(MethodImplOptions.Synchronized)] - public override Task WriteLineAsync(string value) + public override Task WriteLineAsync(string? value) { WriteLine(value); return Task.CompletedTask; } [MethodImpl(MethodImplOptions.Synchronized)] - public override Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default) + public override Task WriteLineAsync(StringBuilder? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { diff --git a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryAccessor.cs b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryAccessor.cs index 1247ad6d5d36..4e66b7cdec12 100644 --- a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryAccessor.cs +++ b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryAccessor.cs @@ -13,8 +13,7 @@ ** ===========================================================*/ -using System.Diagnostics; -using System.Runtime.CompilerServices; +#nullable enable using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; @@ -25,7 +24,7 @@ namespace System.IO /// this gives better throughput; benchmarks showed about 12-15% better. public class UnmanagedMemoryAccessor : IDisposable { - private SafeBuffer _buffer; + private SafeBuffer _buffer = null!; // initialized in helper called by ctor private long _offset; private long _capacity; private FileAccess _access; diff --git a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs index 8489d66286b5..a42cdf918ced 100644 --- a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs +++ b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs @@ -512,7 +512,7 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken // it then fall back to doing the ArrayPool/copy behavior. return new ValueTask( MemoryMarshal.TryGetArray(buffer, out ArraySegment destinationArray) ? - Read(destinationArray.Array, destinationArray.Offset, destinationArray.Count) : + Read(destinationArray.Array!, destinationArray.Offset, destinationArray.Count) : // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 Read(buffer.Span)); } catch (Exception ex) @@ -797,7 +797,7 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo // Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency. if (MemoryMarshal.TryGetArray(buffer, out ArraySegment sourceArray)) { - Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count); + Write(sourceArray.Array!, sourceArray.Offset, sourceArray.Count); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } else { diff --git a/src/System.Private.CoreLib/shared/System/IObservable.cs b/src/System.Private.CoreLib/shared/System/IObservable.cs index aabb0b8fb426..c451a7b8ea26 100644 --- a/src/System.Private.CoreLib/shared/System/IObservable.cs +++ b/src/System.Private.CoreLib/shared/System/IObservable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public interface IObservable diff --git a/src/System.Private.CoreLib/shared/System/IObserver.cs b/src/System.Private.CoreLib/shared/System/IObserver.cs index 39e123de8dbf..35906682b320 100644 --- a/src/System.Private.CoreLib/shared/System/IObserver.cs +++ b/src/System.Private.CoreLib/shared/System/IObserver.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public interface IObserver diff --git a/src/System.Private.CoreLib/shared/System/IProgress.cs b/src/System.Private.CoreLib/shared/System/IProgress.cs index 724c7bdce9ae..e344c73afe28 100644 --- a/src/System.Private.CoreLib/shared/System/IProgress.cs +++ b/src/System.Private.CoreLib/shared/System/IProgress.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { /// Defines a provider for progress updates. diff --git a/src/System.Private.CoreLib/shared/System/ISpanFormattable.cs b/src/System.Private.CoreLib/shared/System/ISpanFormattable.cs index df46b5bcd194..d63e6ff8af21 100644 --- a/src/System.Private.CoreLib/shared/System/ISpanFormattable.cs +++ b/src/System.Private.CoreLib/shared/System/ISpanFormattable.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { internal interface ISpanFormattable { - bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider provider); + bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider); } } diff --git a/src/System.Private.CoreLib/shared/System/Index.cs b/src/System.Private.CoreLib/shared/System/Index.cs index 62d7f3440ca0..9ed7ed1127be 100644 --- a/src/System.Private.CoreLib/shared/System/Index.cs +++ b/src/System.Private.CoreLib/shared/System/Index.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; @@ -117,7 +118,7 @@ public int GetOffset(int length) /// Indicates whether the current Index object is equal to another object of the same type. /// An object to compare with this object - public override bool Equals(object value) => value is Index && _value == ((Index)value)._value; + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; /// Indicates whether the current Index object is equal to another Index object. /// An object to compare with this object diff --git a/src/System.Private.CoreLib/shared/System/IntPtr.cs b/src/System.Private.CoreLib/shared/System/IntPtr.cs index d23742fa7bbf..1aedd04bbe62 100644 --- a/src/System.Private.CoreLib/shared/System/IntPtr.cs +++ b/src/System.Private.CoreLib/shared/System/IntPtr.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -72,7 +73,7 @@ unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext info.AddValue("value", ToInt64()); } - public unsafe override bool Equals(object obj) + public unsafe override bool Equals(object? obj) { if (obj is IntPtr) { diff --git a/src/System.Private.CoreLib/shared/System/Lazy.cs b/src/System.Private.CoreLib/shared/System/Lazy.cs index 6b8c0a4835f9..d8e9a155fd5b 100644 --- a/src/System.Private.CoreLib/shared/System/Lazy.cs +++ b/src/System.Private.CoreLib/shared/System/Lazy.cs @@ -150,11 +150,11 @@ internal static LazyHelper Create(LazyThreadSafetyMode mode, bool useDefaultCons } } - internal static object CreateViaDefaultConstructor(Type type) + internal static T CreateViaDefaultConstructor() { try { - return Activator.CreateInstance(type); + return Activator.CreateInstance(); } catch (MissingMethodException) { @@ -183,10 +183,7 @@ internal static LazyThreadSafetyMode GetModeFromIsThreadSafe(bool isThreadSafe) [DebuggerDisplay("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")] public class Lazy { - private static T CreateViaDefaultConstructor() - { - return (T)LazyHelper.CreateViaDefaultConstructor(typeof(T)); - } + private static T CreateViaDefaultConstructor() => LazyHelper.CreateViaDefaultConstructor(); // _state, a volatile reference, is set to null after _value has been set private volatile LazyHelper? _state; diff --git a/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.Common.cs b/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.Common.cs index 6c0e75019971..a7c2436c6e88 100644 --- a/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.Common.cs +++ b/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.Common.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Runtime.CompilerServices; namespace System diff --git a/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.cs b/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.cs index b0999da1d8b1..b63a98024970 100644 --- a/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.cs +++ b/src/System.Private.CoreLib/shared/System/LocalAppContextSwitches.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Runtime.CompilerServices; namespace System diff --git a/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs b/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs index ae9a741e2dac..616967c9460b 100644 --- a/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs +++ b/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Threading; namespace System @@ -11,13 +12,13 @@ namespace System #endif public sealed class LocalDataStoreSlot { - internal LocalDataStoreSlot(ThreadLocal data) + internal LocalDataStoreSlot(ThreadLocal data) { Data = data; GC.SuppressFinalize(this); } - internal ThreadLocal Data { get; private set; } + internal ThreadLocal Data { get; private set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA1821", Justification = "Finalizer preserved for compat, it is suppressed by the constructor.")] ~LocalDataStoreSlot() diff --git a/src/System.Private.CoreLib/shared/System/MarshalByRefObject.cs b/src/System.Private.CoreLib/shared/System/MarshalByRefObject.cs index a083c97c9d75..9ef86b4124e4 100644 --- a/src/System.Private.CoreLib/shared/System/MarshalByRefObject.cs +++ b/src/System.Private.CoreLib/shared/System/MarshalByRefObject.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace System diff --git a/src/System.Private.CoreLib/shared/System/Marvin.OrdinalIgnoreCase.cs b/src/System.Private.CoreLib/shared/System/Marvin.OrdinalIgnoreCase.cs index beab0cfe02e8..fa02f187e012 100644 --- a/src/System.Private.CoreLib/shared/System/Marvin.OrdinalIgnoreCase.cs +++ b/src/System.Private.CoreLib/shared/System/Marvin.OrdinalIgnoreCase.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Text; +using System.Text.Unicode; using Internal.Runtime.CompilerServices; #if BIT64 @@ -74,7 +75,7 @@ private static int ComputeHash32OrdinalIgnoreCaseSlow(ref char data, int count, { Debug.Assert(count > 0); - char[] borrowedArr = null; + char[]? borrowedArr = null; Span scratch = (uint)count <= 64 ? stackalloc char[64] : (borrowedArr = ArrayPool.Shared.Rent(count)); int charsWritten = new ReadOnlySpan(ref data, count).ToUpperInvariant(scratch); diff --git a/src/System.Private.CoreLib/shared/System/Marvin.cs b/src/System.Private.CoreLib/shared/System/Marvin.cs index 832c84ba82dc..c03ede43fbd9 100644 --- a/src/System.Private.CoreLib/shared/System/Marvin.cs +++ b/src/System.Private.CoreLib/shared/System/Marvin.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/Math.cs b/src/System.Private.CoreLib/shared/System/Math.cs index 1c36c9d23071..2a9c828ce8d0 100644 --- a/src/System.Private.CoreLib/shared/System/Math.cs +++ b/src/System.Private.CoreLib/shared/System/Math.cs @@ -13,6 +13,7 @@ //This class contains only static members and doesn't require serialization. +#nullable enable using System.Diagnostics; using System.Runtime; using System.Runtime.CompilerServices; @@ -538,31 +539,23 @@ public static decimal Max(decimal val1, decimal val2) public static double Max(double val1, double val2) { - // When val1 and val2 are both finite or infinite, return the larger - // * We count +0.0 as larger than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (double.IsNaN(val1)) - { - return val2; - } - - if (double.IsNaN(val2)) + if ((val1 > val2) || double.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return double.IsNegative(val1) ? val2 : val1; } - return (val1 < val2) ? val2 : val1; + return val2; } [NonVersionable] @@ -592,31 +585,23 @@ public static sbyte Max(sbyte val1, sbyte val2) public static float Max(float val1, float val2) { - // When val1 and val2 are both finite or infinite, return the larger - // * We count +0.0 as larger than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (float.IsNaN(val1)) - { - return val2; - } - - if (float.IsNaN(val2)) + if ((val1 > val2) || float.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return float.IsNegative(val1) ? val2 : val1; } - return (val1 < val2) ? val2 : val1; + return val2; } [CLSCompliant(false)] @@ -642,34 +627,26 @@ public static ulong Max(ulong val1, ulong val2) public static double MaxMagnitude(double x, double y) { - // When x and y are both finite or infinite, return the larger magnitude - // * We count +0.0 as larger than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (double.IsNaN(x)) - { - return y; - } + double ax = Abs(x); + double ay = Abs(y); - if (double.IsNaN(y)) + if ((ax > ay) || double.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - double ax = Abs(x); - double ay = Abs(y); - if (ax == ay) { return double.IsNegative(x) ? y : x; } - return (ax < ay) ? y : x; + return y; } [NonVersionable] @@ -686,31 +663,23 @@ public static decimal Min(decimal val1, decimal val2) public static double Min(double val1, double val2) { - // When val1 and val2 are both finite or infinite, return the smaller - // * We count -0.0 as smaller than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (double.IsNaN(val1)) - { - return val2; - } - - if (double.IsNaN(val2)) + if ((val1 < val2) || double.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return double.IsNegative(val1) ? val1 : val2; } - return (val1 < val2) ? val1 : val2; + return val2; } [NonVersionable] @@ -740,31 +709,23 @@ public static sbyte Min(sbyte val1, sbyte val2) public static float Min(float val1, float val2) { - // When val1 and val2 are both finite or infinite, return the smaller - // * We count -0.0 as smaller than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (float.IsNaN(val1)) - { - return val2; - } - - if (float.IsNaN(val2)) + if ((val1 < val2) || float.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return float.IsNegative(val1) ? val1 : val2; } - return (val1 < val2) ? val1 : val2; + return val2; } [CLSCompliant(false)] @@ -790,34 +751,26 @@ public static ulong Min(ulong val1, ulong val2) public static double MinMagnitude(double x, double y) { - // When x and y are both finite or infinite, return the smaller magnitude - // * We count -0.0 as smaller than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (double.IsNaN(x)) - { - return y; - } + double ax = Abs(x); + double ay = Abs(y); - if (double.IsNaN(y)) + if ((ax < ay) || double.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - double ax = Abs(x); - double ay = Abs(y); - if (ax == ay) { return double.IsNegative(x) ? x : y; } - return (ax < ay) ? x : y; + return y; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/System.Private.CoreLib/shared/System/MathF.cs b/src/System.Private.CoreLib/shared/System/MathF.cs index 1defa4e40baa..a039bb9a390f 100644 --- a/src/System.Private.CoreLib/shared/System/MathF.cs +++ b/src/System.Private.CoreLib/shared/System/MathF.cs @@ -10,7 +10,7 @@ //This class contains only static members and doesn't require serialization. -using System.Runtime; +#nullable enable using System.Runtime.CompilerServices; namespace System @@ -190,34 +190,26 @@ public static float Max(float x, float y) public static float MaxMagnitude(float x, float y) { - // When x and y are both finite or infinite, return the larger magnitude - // * We count +0.0 as larger than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (float.IsNaN(x)) - { - return y; - } + float ax = Abs(x); + float ay = Abs(y); - if (float.IsNaN(y)) + if ((ax > ay) || float.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - float ax = Abs(x); - float ay = Abs(y); - if (ax == ay) { return float.IsNegative(x) ? y : x; } - return (ax < ay) ? y : x; + return y; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -228,34 +220,26 @@ public static float Min(float x, float y) public static float MinMagnitude(float x, float y) { - // When x and y are both finite or infinite, return the smaller magnitude - // * We count -0.0 as smaller than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (float.IsNaN(x)) - { - return y; - } + float ax = Abs(x); + float ay = Abs(y); - if (float.IsNaN(y)) + if ((ax < ay) || float.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - float ax = Abs(x); - float ay = Abs(y); - if (ax == ay) { return float.IsNegative(x) ? x : y; } - return (ax < ay) ? x : y; + return y; } [Intrinsic] diff --git a/src/System.Private.CoreLib/shared/System/Memory.cs b/src/System.Private.CoreLib/shared/System/Memory.cs index e61ada7a45c5..399c6f015146 100644 --- a/src/System.Private.CoreLib/shared/System/Memory.cs +++ b/src/System.Private.CoreLib/shared/System/Memory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -36,7 +37,7 @@ namespace System // The highest order bit of _index is used to discern whether _object is a pre-pinned array. // (_index < 0) => _object is a pre-pinned array, so Pin() will not allocate a new GCHandle // (else) => Pin() needs to allocate a new GCHandle to pin the object. - private readonly object _object; + private readonly object? _object; private readonly int _index; private readonly int _length; @@ -47,14 +48,14 @@ namespace System /// Returns default when is null. /// Thrown when is covariant and array's type is not exactly T[]. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory(T[] array) + public Memory(T[]? array) { if (array == null) { this = default; return; // returns default } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); _object = array; @@ -63,7 +64,7 @@ public Memory(T[] array) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Memory(T[] array, int start) + internal Memory(T[]? array, int start) { if (array == null) { @@ -72,7 +73,7 @@ internal Memory(T[] array, int start) this = default; return; // returns default } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); if ((uint)start > (uint)array.Length) ThrowHelper.ThrowArgumentOutOfRangeException(); @@ -95,7 +96,7 @@ internal Memory(T[] array, int start) /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory(T[] array, int start, int length) + public Memory(T[]? array, int start, int length) { if (array == null) { @@ -104,7 +105,7 @@ public Memory(T[] array, int start, int length) this = default; return; // returns default } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); #if BIT64 // See comment in Span.Slice for how this works. @@ -168,7 +169,7 @@ internal Memory(MemoryManager manager, int start, int length) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Memory(object obj, int start, int length) + internal Memory(object? obj, int start, int length) { // No validation performed in release builds; caller must provide any necessary validation. @@ -189,7 +190,7 @@ internal Memory(object obj, int start, int length) /// /// Defines an implicit conversion of an array to a /// - public static implicit operator Memory(T[] array) => new Memory(array); + public static implicit operator Memory(T[]? array) => new Memory(array); /// /// Defines an implicit conversion of a to a @@ -281,35 +282,6 @@ public Memory Slice(int start, int length) return new Memory(_object, _index + start, length); } - /// - /// Forms a slice out of the given memory, beginning at 'startIndex' - /// - /// The index at which to begin this slice. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory Slice(Index startIndex) - { - int actualIndex = startIndex.GetOffset(_length); - return Slice(actualIndex); - } - - /// - /// Forms a slice out of the given memory using the range start and end indexes. - /// - /// The range used to slice the memory using its start and end indexes. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Memory Slice(Range range) - { - (int start, int length) = range.GetOffsetAndLength(_length); - // It is expected for _index + start to be negative if the memory is already pre-pinned. - return new Memory(_object, _index + start, length); - } - - /// - /// Forms a slice out of the given memory using the range start and end indexes. - /// - /// The range used to slice the memory using its start and end indexes. - public Memory this[Range range] => Slice(range); - /// /// Returns a span from the memory. /// @@ -330,7 +302,7 @@ public unsafe Span Span // Copy this field into a local so that it can't change out from under us mid-operation. - object tmpObject = _object; + object? tmpObject = _object; if (tmpObject != null) { if (typeof(T) == typeof(char) && tmpObject.GetType() == typeof(string)) @@ -448,7 +420,7 @@ public unsafe MemoryHandle Pin() // is torn. This is ok since the caller is expecting to use raw pointers, // and we're not required to keep this as safe as the other Span-based APIs. - object tmpObject = _object; + object? tmpObject = _object; if (tmpObject != null) { if (typeof(T) == typeof(char) && tmpObject is string s) @@ -505,7 +477,7 @@ public unsafe MemoryHandle Pin() /// Returns true if the object is Memory or ReadOnlyMemory and if both objects point to the same array and have the same length. /// [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is ReadOnlyMemory) { diff --git a/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs b/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs index 6ab6e5065cf3..563d010d61e5 100644 --- a/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs +++ b/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs index 1e1fd90e4468..82f3d2321ef9 100644 --- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs +++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; @@ -237,7 +238,7 @@ public static int ToLower(this ReadOnlySpan source, Span destination if (GlobalizationMode.Invariant) TextInfo.ToLowerAsciiInvariant(source, destination); else - culture.TextInfo.ChangeCaseToLower(source, destination); + culture!.TextInfo.ChangeCaseToLower(source, destination); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 return source.Length; } @@ -288,7 +289,7 @@ public static int ToUpper(this ReadOnlySpan source, Span destination if (GlobalizationMode.Invariant) TextInfo.ToUpperAsciiInvariant(source, destination); else - culture.TextInfo.ChangeCaseToUpper(source, destination); + culture!.TextInfo.ChangeCaseToUpper(source, destination); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 return source.Length; } @@ -384,7 +385,7 @@ public static bool StartsWith(this ReadOnlySpan span, ReadOnlySpan v /// Creates a new span over the portion of the target array. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span AsSpan(this T[] array, int start) + public static Span AsSpan(this T[]? array, int start) { if (array == null) { @@ -392,7 +393,7 @@ public static Span AsSpan(this T[] array, int start) ThrowHelper.ThrowArgumentOutOfRangeException(); return default; } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); if ((uint)start > (uint)array.Length) ThrowHelper.ThrowArgumentOutOfRangeException(); @@ -404,7 +405,7 @@ public static Span AsSpan(this T[] array, int start) /// Creates a new span over the portion of the target array. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span AsSpan(this T[] array, Index startIndex) + public static Span AsSpan(this T[]? array, Index startIndex) { if (array == null) { @@ -414,7 +415,7 @@ public static Span AsSpan(this T[] array, Index startIndex) return default; } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); int actualIndex = startIndex.GetOffset(array.Length); @@ -428,7 +429,7 @@ public static Span AsSpan(this T[] array, Index startIndex) /// Creates a new span over the portion of the target array. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span AsSpan(this T[] array, Range range) + public static Span AsSpan(this T[]? array, Range range) { if (array == null) { @@ -441,7 +442,7 @@ public static Span AsSpan(this T[] array, Range range) return default; } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); (int start, int length) = range.GetOffsetAndLength(array.Length); @@ -454,7 +455,7 @@ public static Span AsSpan(this T[] array, Range range) /// The target string. /// Returns default when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsSpan(this string text) + public static ReadOnlySpan AsSpan(this string? text) { if (text == null) return default; @@ -472,7 +473,7 @@ public static ReadOnlySpan AsSpan(this string text) /// Thrown when the specified index is not in range (<0 or >text.Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsSpan(this string text, int start) + public static ReadOnlySpan AsSpan(this string? text, int start) { if (text == null) { @@ -498,7 +499,7 @@ public static ReadOnlySpan AsSpan(this string text, int start) /// Thrown when the specified index or is not in range. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsSpan(this string text, int start, int length) + public static ReadOnlySpan AsSpan(this string? text, int start, int length) { if (text == null) { @@ -522,7 +523,7 @@ public static ReadOnlySpan AsSpan(this string text, int start, int length) /// Creates a new over the portion of the target string. /// The target string. /// Returns default when is null. - public static ReadOnlyMemory AsMemory(this string text) + public static ReadOnlyMemory AsMemory(this string? text) { if (text == null) return default; @@ -537,7 +538,7 @@ public static ReadOnlyMemory AsMemory(this string text) /// /// Thrown when the specified index is not in range (<0 or >text.Length). /// - public static ReadOnlyMemory AsMemory(this string text, int start) + public static ReadOnlyMemory AsMemory(this string? text, int start) { if (text == null) { @@ -555,7 +556,7 @@ public static ReadOnlyMemory AsMemory(this string text, int start) /// Creates a new over the portion of the target string. /// The target string. /// The index at which to begin this slice. - public static ReadOnlyMemory AsMemory(this string text, Index startIndex) + public static ReadOnlyMemory AsMemory(this string? text, Index startIndex) { if (text == null) { @@ -580,7 +581,7 @@ public static ReadOnlyMemory AsMemory(this string text, Index startIndex) /// /// Thrown when the specified index or is not in range. /// - public static ReadOnlyMemory AsMemory(this string text, int start, int length) + public static ReadOnlyMemory AsMemory(this string? text, int start, int length) { if (text == null) { @@ -604,7 +605,7 @@ public static ReadOnlyMemory AsMemory(this string text, int start, int len /// Creates a new over the portion of the target string. /// The target string. /// The range used to indicate the start and length of the sliced string. - public static ReadOnlyMemory AsMemory(this string text, Range range) + public static ReadOnlyMemory AsMemory(this string? text, Range range) { if (text == null) { diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Trim.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Trim.cs index 96581c7c0183..5c776cd4ea45 100644 --- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Trim.cs +++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Trim.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs index 4f7cab10b637..50130974336d 100644 --- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs +++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -981,7 +982,7 @@ public static void Reverse(this Span span) /// Creates a new span over the target array. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span AsSpan(this T[] array) + public static Span AsSpan(this T[]? array) { return new Span(array); } @@ -999,7 +1000,7 @@ public static Span AsSpan(this T[] array) /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span AsSpan(this T[] array, int start, int length) + public static Span AsSpan(this T[]? array, int start, int length) { return new Span(array, start, length); } @@ -1084,7 +1085,7 @@ public static Span AsSpan(this ArraySegment segment, Range range) /// /// Creates a new memory over the target array. /// - public static Memory AsMemory(this T[] array) => new Memory(array); + public static Memory AsMemory(this T[]? array) => new Memory(array); /// /// Creates a new memory over the portion of the target array beginning @@ -1097,13 +1098,13 @@ public static Span AsSpan(this ArraySegment segment, Range range) /// /// Thrown when the specified or end index is not in the range (<0 or >=array.Length). /// - public static Memory AsMemory(this T[] array, int start) => new Memory(array, start); + public static Memory AsMemory(this T[]? array, int start) => new Memory(array, start); /// /// Creates a new memory over the portion of the target array starting from /// 'startIndex' to the end of the array. /// - public static Memory AsMemory(this T[] array, Index startIndex) + public static Memory AsMemory(this T[]? array, Index startIndex) { if (array == null) { @@ -1129,13 +1130,13 @@ public static Memory AsMemory(this T[] array, Index startIndex) /// /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// - public static Memory AsMemory(this T[] array, int start, int length) => new Memory(array, start, length); + public static Memory AsMemory(this T[]? array, int start, int length) => new Memory(array, start, length); /// /// Creates a new memory over the portion of the target array beginning at inclusive start index of the range /// and ending at the exclusive end index of the range. /// - public static Memory AsMemory(this T[] array, Range range) + public static Memory AsMemory(this T[]? array, Range range) { if (array == null) { @@ -1209,7 +1210,7 @@ public static Memory AsMemory(this ArraySegment segment, int start, int /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyTo(this T[] source, Span destination) + public static void CopyTo(this T[]? source, Span destination) { new ReadOnlySpan(source).CopyTo(destination); } @@ -1226,7 +1227,7 @@ public static void CopyTo(this T[] source, Span destination) /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyTo(this T[] source, Memory destination) + public static void CopyTo(this T[]? source, Memory destination) { source.CopyTo(destination.Span); } diff --git a/src/System.Private.CoreLib/shared/System/MidpointRounding.cs b/src/System.Private.CoreLib/shared/System/MidpointRounding.cs index 835dafe7eeee..146fed9bd6b0 100644 --- a/src/System.Private.CoreLib/shared/System/MidpointRounding.cs +++ b/src/System.Private.CoreLib/shared/System/MidpointRounding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public enum MidpointRounding diff --git a/src/System.Private.CoreLib/shared/System/MissingMemberException.cs b/src/System.Private.CoreLib/shared/System/MissingMemberException.cs index e04a468c8f2e..cc8be87286c8 100644 --- a/src/System.Private.CoreLib/shared/System/MissingMemberException.cs +++ b/src/System.Private.CoreLib/shared/System/MissingMemberException.cs @@ -40,7 +40,7 @@ protected MissingMemberException(SerializationInfo info, StreamingContext contex { ClassName = info.GetString("MMClassName"); MemberName = info.GetString("MMMemberName"); - Signature = (byte[])info.GetValue("MMSignature", typeof(byte[])); + Signature = (byte[]?)info.GetValue("MMSignature", typeof(byte[])); } public override void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/System.Private.CoreLib/shared/System/NonSerializedAttribute.cs b/src/System.Private.CoreLib/shared/System/NonSerializedAttribute.cs index cabd5a2aa25a..2caa285a76a4 100644 --- a/src/System.Private.CoreLib/shared/System/NonSerializedAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/NonSerializedAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { [AttributeUsage(AttributeTargets.Field, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Nullable.cs b/src/System.Private.CoreLib/shared/System/Nullable.cs index 6f8d667bc1d5..10df282d10fb 100644 --- a/src/System.Private.CoreLib/shared/System/Nullable.cs +++ b/src/System.Private.CoreLib/shared/System/Nullable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Runtime.Versioning; @@ -59,7 +60,7 @@ public T GetValueOrDefault(T defaultValue) return hasValue ? value : defaultValue; } - public override bool Equals(object other) + public override bool Equals(object? other) { if (!hasValue) return other == null; if (other == null) return false; @@ -71,7 +72,7 @@ public override int GetHashCode() return hasValue ? value.GetHashCode() : 0; } - public override string ToString() + public override string? ToString() { return hasValue ? value.ToString() : ""; } @@ -85,7 +86,7 @@ public static implicit operator Nullable(T value) [NonVersionable] public static explicit operator T(Nullable value) { - return value.Value; + return value!.Value; } } @@ -115,7 +116,7 @@ public static bool Equals(Nullable n1, Nullable n2) where T : struct // If the type provided is not a Nullable Type, return null. // Otherwise, returns the underlying type of the Nullable type - public static Type GetUnderlyingType(Type nullableType) + public static Type? GetUnderlyingType(Type nullableType) { if ((object)nullableType == null) { diff --git a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs index 6f2fb50119b9..378832e5bc06 100644 --- a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs +++ b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs @@ -2218,6 +2218,7 @@ private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuff if (nMaxDigits > 0) { + Debug.Assert(sDecimal != null); sb.Append(sDecimal); if ((digPos < 0) && (nMaxDigits > 0)) { diff --git a/src/System.Private.CoreLib/shared/System/Numerics/BitOperations.cs b/src/System.Private.CoreLib/shared/System/Numerics/BitOperations.cs index 3813b9a68977..e2a6720ec68c 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/BitOperations.cs +++ b/src/System.Private.CoreLib/shared/System/Numerics/BitOperations.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.X86; diff --git a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs index 3fb3086b2dfa..4426c88cb3a8 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs +++ b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs @@ -1,7 +1,8 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System.Numerics @@ -139,4 +140,4 @@ public static double GetDoubleWithAllBitsSet() return value; } } -} +} \ No newline at end of file diff --git a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt index dd823abc0a72..9d897547dd72 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt +++ b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt @@ -14,6 +14,7 @@ <#@ import namespace="System.Runtime.InteropServices" #> <#@ include file="GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> +#nullable enable using System.Runtime.CompilerServices; namespace System.Numerics diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Hashing/HashHelpers.cs b/src/System.Private.CoreLib/shared/System/Numerics/Hashing/HashHelpers.cs index fd9d708d3674..ed23f1cae746 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/Hashing/HashHelpers.cs +++ b/src/System.Private.CoreLib/shared/System/Numerics/Hashing/HashHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Numerics.Hashing { internal static class HashHelpers diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Register.cs b/src/System.Private.CoreLib/shared/System/Numerics/Register.cs index 8efa85b199ee..a5dfd5e1301a 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/Register.cs +++ b/src/System.Private.CoreLib/shared/System/Numerics/Register.cs @@ -1,7 +1,8 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace System.Numerics diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Register.tt b/src/System.Private.CoreLib/shared/System/Numerics/Register.tt index 676b89f547e7..f447051f807d 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/Register.tt +++ b/src/System.Private.CoreLib/shared/System/Numerics/Register.tt @@ -8,6 +8,7 @@ <#@ import namespace="System.Diagnostics" #> <#@ include file="GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> +#nullable enable using System.Runtime.InteropServices; namespace System.Numerics @@ -43,4 +44,4 @@ namespace System.Numerics } #> #endregion Internal Storage Fields } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs b/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs index 0c1787d3f65f..3f7832a3a0cc 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs +++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable #if netcoreapp using Internal.Runtime.CompilerServices; #endif @@ -1195,7 +1196,7 @@ public unsafe T this[int index] /// The Object to compare against. /// True if the Object is equal to this vector; False otherwise. [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is Vector)) { @@ -1562,7 +1563,7 @@ public override string ToString() /// /// The format of individual elements. /// The string representation. - public string ToString(string format) + public string ToString(string? format) { return ToString(format, CultureInfo.CurrentCulture); } @@ -1574,7 +1575,7 @@ public string ToString(string format) /// The format of individual elements. /// The format provider to use when formatting elements. /// The string representation. - public string ToString(string format, IFormatProvider formatProvider) + public string ToString(string? format, IFormatProvider? formatProvider) { StringBuilder sb = new StringBuilder(); string separator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator; diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt b/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt index 4b0fc4f6d579..5132b09a4a52 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt +++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt @@ -7,6 +7,7 @@ <#@ import namespace="System.Runtime.InteropServices" #> <#@ include file="GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #> +#nullable enable #if netcoreapp using Internal.Runtime.CompilerServices; #endif @@ -450,7 +451,7 @@ namespace System.Numerics /// The Object to compare against. /// True if the Object is equal to this vector; False otherwise. [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is Vector)) { @@ -591,7 +592,7 @@ namespace System.Numerics /// /// The format of individual elements. /// The string representation. - public string ToString(string format) + public string ToString(string? format) { return ToString(format, CultureInfo.CurrentCulture); } @@ -603,7 +604,7 @@ namespace System.Numerics /// The format of individual elements. /// The format provider to use when formatting elements. /// The string representation. - public string ToString(string format, IFormatProvider formatProvider) + public string ToString(string? format, IFormatProvider? formatProvider) { StringBuilder sb = new StringBuilder(); string separator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator; diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs b/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs index 567a0a78eb2e..5e7bc607c733 100644 --- a/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs +++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System.Numerics diff --git a/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs b/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs index 748681756db9..dbad93f99347 100644 --- a/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs @@ -11,8 +11,7 @@ ** ===========================================================*/ -using System; - +#nullable enable namespace System { // This attribute is attached to members that are not to be used any longer. @@ -26,7 +25,7 @@ namespace System , Inherited = false)] public sealed class ObsoleteAttribute : Attribute { - private string _message; + private string? _message; private bool _error; public ObsoleteAttribute() @@ -35,19 +34,19 @@ public ObsoleteAttribute() _error = false; } - public ObsoleteAttribute(string message) + public ObsoleteAttribute(string? message) { _message = message; _error = false; } - public ObsoleteAttribute(string message, bool error) + public ObsoleteAttribute(string? message, bool error) { _message = message; _error = error; } - public string Message + public string? Message { get { return _message; } } diff --git a/src/System.Private.CoreLib/shared/System/OperatingSystem.cs b/src/System.Private.CoreLib/shared/System/OperatingSystem.cs index be3027135869..2e806de778dc 100644 --- a/src/System.Private.CoreLib/shared/System/OperatingSystem.cs +++ b/src/System.Private.CoreLib/shared/System/OperatingSystem.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.Serialization; @@ -14,14 +15,14 @@ public sealed class OperatingSystem : ISerializable, ICloneable { private readonly Version _version; private readonly PlatformID _platform; - private readonly string _servicePack; - private string _versionString; + private readonly string? _servicePack; + private string? _versionString; public OperatingSystem(PlatformID platform, Version version) : this(platform, version, null) { } - internal OperatingSystem(PlatformID platform, Version version, string servicePack) + internal OperatingSystem(PlatformID platform, Version version, string? servicePack) { if (platform < PlatformID.Win32S || platform > PlatformID.MacOSX) { diff --git a/src/System.Private.CoreLib/shared/System/ParamArrayAttribute.cs b/src/System.Private.CoreLib/shared/System/ParamArrayAttribute.cs index d3c3d46d569a..8faffc4eeaab 100644 --- a/src/System.Private.CoreLib/shared/System/ParamArrayAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/ParamArrayAttribute.cs @@ -11,6 +11,7 @@ ** =============================================================================*/ +#nullable enable namespace System { [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/ParamsArray.cs b/src/System.Private.CoreLib/shared/System/ParamsArray.cs index 043ee679eef3..91b2bd1d8675 100644 --- a/src/System.Private.CoreLib/shared/System/ParamsArray.cs +++ b/src/System.Private.CoreLib/shared/System/ParamsArray.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { internal readonly struct ParamsArray @@ -9,19 +10,19 @@ internal readonly struct ParamsArray // Sentinel fixed-length arrays eliminate the need for a "count" field keeping this // struct down to just 4 fields. These are only used for their "Length" property, // that is, their elements are never set or referenced. - private static readonly object[] s_oneArgArray = new object[1]; - private static readonly object[] s_twoArgArray = new object[2]; - private static readonly object[] s_threeArgArray = new object[3]; + private static readonly object?[] s_oneArgArray = new object?[1]; + private static readonly object?[] s_twoArgArray = new object?[2]; + private static readonly object?[] s_threeArgArray = new object?[3]; - private readonly object _arg0; - private readonly object _arg1; - private readonly object _arg2; + private readonly object? _arg0; + private readonly object? _arg1; + private readonly object? _arg2; // After construction, the first three elements of this array will never be accessed // because the indexer will retrieve those values from arg0, arg1, and arg2. - private readonly object[] _args; + private readonly object?[] _args; - public ParamsArray(object arg0) + public ParamsArray(object? arg0) { _arg0 = arg0; _arg1 = null; @@ -31,7 +32,7 @@ public ParamsArray(object arg0) _args = s_oneArgArray; } - public ParamsArray(object arg0, object arg1) + public ParamsArray(object? arg0, object? arg1) { _arg0 = arg0; _arg1 = arg1; @@ -41,7 +42,7 @@ public ParamsArray(object arg0, object arg1) _args = s_twoArgArray; } - public ParamsArray(object arg0, object arg1, object arg2) + public ParamsArray(object? arg0, object? arg1, object? arg2) { _arg0 = arg0; _arg1 = arg1; @@ -51,7 +52,7 @@ public ParamsArray(object arg0, object arg1, object arg2) _args = s_threeArgArray; } - public ParamsArray(object[] args) + public ParamsArray(object?[] args) { int len = args.Length; _arg0 = len > 0 ? args[0] : null; @@ -65,12 +66,12 @@ public int Length get { return _args.Length; } } - public object this[int index] + public object? this[int index] { get { return index == 0 ? _arg0 : GetAtSlow(index); } } - private object GetAtSlow(int index) + private object? GetAtSlow(int index) { if (index == 1) return _arg1; diff --git a/src/System.Private.CoreLib/shared/System/ParseNumbers.cs b/src/System.Private.CoreLib/shared/System/ParseNumbers.cs index 0978186902d4..ab04cf6b8af2 100644 --- a/src/System.Private.CoreLib/shared/System/ParseNumbers.cs +++ b/src/System.Private.CoreLib/shared/System/ParseNumbers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/PasteArguments.Unix.cs b/src/System.Private.CoreLib/shared/System/PasteArguments.Unix.cs index 1a4d92850f89..fdad698b95e9 100644 --- a/src/System.Private.CoreLib/shared/System/PasteArguments.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/PasteArguments.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Text; diff --git a/src/System.Private.CoreLib/shared/System/PasteArguments.Windows.cs b/src/System.Private.CoreLib/shared/System/PasteArguments.Windows.cs index 7cdcbc4533a0..42a817b428e6 100644 --- a/src/System.Private.CoreLib/shared/System/PasteArguments.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/PasteArguments.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Text; diff --git a/src/System.Private.CoreLib/shared/System/PasteArguments.cs b/src/System.Private.CoreLib/shared/System/PasteArguments.cs index c088fd4eb737..afa2e4419e0c 100644 --- a/src/System.Private.CoreLib/shared/System/PasteArguments.cs +++ b/src/System.Private.CoreLib/shared/System/PasteArguments.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; namespace System diff --git a/src/System.Private.CoreLib/shared/System/PlatformID.cs b/src/System.Private.CoreLib/shared/System/PlatformID.cs index 2eda3c05f30e..0ec46f3d4372 100644 --- a/src/System.Private.CoreLib/shared/System/PlatformID.cs +++ b/src/System.Private.CoreLib/shared/System/PlatformID.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; namespace System diff --git a/src/System.Private.CoreLib/shared/System/Progress.cs b/src/System.Private.CoreLib/shared/System/Progress.cs index 6ddfc18bce6c..4dae2b190831 100644 --- a/src/System.Private.CoreLib/shared/System/Progress.cs +++ b/src/System.Private.CoreLib/shared/System/Progress.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Threading; using System.Diagnostics; @@ -24,7 +24,7 @@ public class Progress : IProgress /// The synchronization context captured upon construction. This will never be null. private readonly SynchronizationContext _synchronizationContext; /// The handler specified to the constructor. This may be null. - private readonly Action _handler; + private readonly Action? _handler; /// A cached delegate used to post invocation to the synchronization context. private readonly SendOrPostCallback _invokeHandlers; @@ -49,8 +49,7 @@ public Progress() /// The is null (Nothing in Visual Basic). public Progress(Action handler) : this() { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - _handler = handler; + _handler = handler ?? throw new ArgumentNullException(nameof(handler)); } /// Raised for each reported progress value. @@ -67,7 +66,7 @@ protected virtual void OnReport(T value) // If there's no handler, don't bother going through the sync context. // Inside the callback, we'll need to check again, in case // an event handler is removed between now and then. - Action handler = _handler; + Action? handler = _handler; EventHandler changedEvent = ProgressChanged; if (handler != null || changedEvent != null) { @@ -87,7 +86,7 @@ private void InvokeHandlers(object state) { T value = (T)state; - Action handler = _handler; + Action? handler = _handler; EventHandler changedEvent = ProgressChanged; if (handler != null) handler(value); diff --git a/src/System.Private.CoreLib/shared/System/Random.cs b/src/System.Private.CoreLib/shared/System/Random.cs index ed79732c25a1..92daa51aac8e 100644 --- a/src/System.Private.CoreLib/shared/System/Random.cs +++ b/src/System.Private.CoreLib/shared/System/Random.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public class Random diff --git a/src/System.Private.CoreLib/shared/System/Range.cs b/src/System.Private.CoreLib/shared/System/Range.cs index 0098dea17ff7..2a3379265af6 100644 --- a/src/System.Private.CoreLib/shared/System/Range.cs +++ b/src/System.Private.CoreLib/shared/System/Range.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; @@ -35,7 +36,7 @@ public Range(Index start, Index end) /// Indicates whether the current Range object is equal to another object of the same type. /// An object to compare with this object - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is Range) { @@ -48,7 +49,7 @@ public override bool Equals(object value) /// Indicates whether the current Range object is equal to another Range object. /// An object to compare with this object - public bool Equals (Range other) => other.Start.Equals(Start) && other.End.Equals(End); + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); /// Returns the hash code for this instance. public override int GetHashCode() @@ -95,15 +96,15 @@ public override string ToString() /// Create a Range object starting from first element to the end. public static Range All => new Range(Index.Start, Index.End); - /// Destruct the range object according to a collection length and return the start offset from the beginning and the length of this range. - /// The length of the collection that the range will be used with. length has to be a positive value + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. /// /// For performance reason, we don't validate the input length parameter against negative values. /// It is expected Range will be used with collections which always have non negative length/count. /// We validate the range is inside the length scope though. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public OffsetAndLength GetOffsetAndLength(int length) + public (int Offset, int Length) GetOffsetAndLength(int length) { int start; Index startIndex = Start; @@ -124,25 +125,7 @@ public OffsetAndLength GetOffsetAndLength(int length) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length); } - return new OffsetAndLength(start, end - start); - } - - public readonly struct OffsetAndLength - { - public int Offset { get; } - public int Length { get; } - - public OffsetAndLength(int offset, int length) - { - Offset = offset; - Length = length; - } - - public void Deconstruct(out int offset, out int length) - { - offset = Offset; - length = Length; - } + return (start, end - start); } } } diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs b/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs index b7814cf140f1..37008d7c158a 100644 --- a/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs +++ b/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -36,7 +37,7 @@ namespace System // The highest order bit of _index is used to discern whether _object is a pre-pinned array. // (_index < 0) => _object is a pre-pinned array, so Pin() will not allocate a new GCHandle // (else) => Pin() needs to allocate a new GCHandle to pin the object. - private readonly object _object; + private readonly object? _object; private readonly int _index; private readonly int _length; @@ -49,7 +50,7 @@ namespace System /// Returns default when is null. /// Thrown when is covariant and array's type is not exactly T[]. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory(T[] array) + public ReadOnlyMemory(T[]? array) { if (array == null) { @@ -75,7 +76,7 @@ public ReadOnlyMemory(T[] array) /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory(T[] array, int start, int length) + public ReadOnlyMemory(T[]? array, int start, int length) { if (array == null) { @@ -103,7 +104,7 @@ public ReadOnlyMemory(T[] array, int start, int length) /// The index at which to begin the memory. /// The number of items in the memory. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ReadOnlyMemory(object obj, int start, int length) + internal ReadOnlyMemory(object? obj, int start, int length) { // No validation performed in release builds; caller must provide any necessary validation. @@ -124,7 +125,7 @@ internal ReadOnlyMemory(object obj, int start, int length) /// /// Defines an implicit conversion of an array to a /// - public static implicit operator ReadOnlyMemory(T[] array) => new ReadOnlyMemory(array); + public static implicit operator ReadOnlyMemory(T[]? array) => new ReadOnlyMemory(array); /// /// Defines an implicit conversion of a to a @@ -210,35 +211,6 @@ public ReadOnlyMemory Slice(int start, int length) return new ReadOnlyMemory(_object, _index + start, length); } - /// - /// Forms a slice out of the given memory, beginning at 'startIndex' - /// - /// The index at which to begin this slice. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory Slice(Index startIndex) - { - int actualIndex = startIndex.GetOffset(_length); - return Slice(actualIndex); - } - - /// - /// Forms a slice out of the given memory using the range start and end indexes. - /// - /// The range used to slice the memory using its start and end indexes. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory Slice(Range range) - { - (int start, int length) = range.GetOffsetAndLength(_length); - // It is expected for _index + start to be negative if the memory is already pre-pinned. - return new ReadOnlyMemory(_object, _index + start, length); - } - - /// - /// Forms a slice out of the given memory using the range start and end indexes. - /// - /// The range used to slice the memory using its start and end indexes. - public ReadOnlyMemory this[Range range] => Slice(range); - /// /// Returns a span from the memory. /// @@ -252,7 +224,7 @@ public unsafe ReadOnlySpan Span // Copy this field into a local so that it can't change out from under us mid-operation. - object tmpObject = _object; + object? tmpObject = _object; if (tmpObject != null) { if (typeof(T) == typeof(char) && tmpObject.GetType() == typeof(string)) @@ -363,7 +335,7 @@ public unsafe MemoryHandle Pin() // is torn. This is ok since the caller is expecting to use raw pointers, // and we're not required to keep this as safe as the other Span-based APIs. - object tmpObject = _object; + object? tmpObject = _object; if (tmpObject != null) { if (typeof(T) == typeof(char) && tmpObject is string s) @@ -417,7 +389,7 @@ public unsafe MemoryHandle Pin() /// Determines whether the specified object is equal to the current object. [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is ReadOnlyMemory readOnlyMemory) { @@ -459,7 +431,7 @@ public override int GetHashCode() /// The count. /// The object. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal object GetObjectStartLength(out int start, out int length) + internal object? GetObjectStartLength(out int start, out int length) { start = _index; length = _length; diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs index 00337a5fd7f5..1968a41d160e 100644 --- a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs +++ b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Versioning; @@ -41,7 +42,7 @@ public readonly ref partial struct ReadOnlySpan /// The target array. /// Returns default when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan(T[] array) + public ReadOnlySpan(T[]? array) { if (array == null) { @@ -65,7 +66,7 @@ public ReadOnlySpan(T[] array) /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan(T[] array, int start, int length) + public ReadOnlySpan(T[]? array, int start, int length) { if (array == null) { @@ -153,18 +154,6 @@ public ref readonly T this[int index] #endif } - public ref readonly T this[Index index] - { - get - { - // Evaluate the actual index first because it helps performance - int actualIndex = index.GetOffset(_length); - return ref this [actualIndex]; - } - } - - public ReadOnlySpan this[Range range] => Slice(range); - /// /// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference. /// It can be used for pinning and is required to support the use of span within a fixed statement. @@ -292,33 +281,6 @@ public ReadOnlySpan Slice(int start, int length) return new ReadOnlySpan(ref Unsafe.Add(ref _pointer.Value, start), length); } - /// - /// Forms a slice out of the given read-only span, beginning at 'startIndex' - /// - /// The index at which to begin this slice. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan Slice(Index startIndex) - { - int actualIndex; - if (startIndex.IsFromEnd) - actualIndex = _length - startIndex.Value; - else - actualIndex = startIndex.Value; - - return Slice(actualIndex); - } - - /// - /// Forms a slice out of the given read-only span, beginning at range start index to the range end - /// - /// The range which has the start and end indexes used to slice the span. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan Slice(Range range) - { - (int start, int length) = range.GetOffsetAndLength(_length); - return new ReadOnlySpan(ref Unsafe.Add(ref _pointer.Value, start), length); - } - /// /// Copies the contents of this read-only span into a new array. This heap /// allocates, so should generally be avoided, however it is sometimes diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs index 17b7134e27c0..2533d1d8b878 100644 --- a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs +++ b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -58,7 +59,7 @@ public bool IsEmpty /// [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")] [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { throw new NotSupportedException(SR.NotSupported_CannotCallEqualsOnSpan); } @@ -79,7 +80,7 @@ public override int GetHashCode() /// /// Defines an implicit conversion of an array to a /// - public static implicit operator ReadOnlySpan(T[] array) => new ReadOnlySpan(array); + public static implicit operator ReadOnlySpan(T[]? array) => new ReadOnlySpan(array); /// /// Defines an implicit conversion of a to a diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs index 3db428ed7937..1e9699f62f27 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs @@ -205,7 +205,17 @@ public static Assembly LoadWithPartialName(string partialName) if (partialName == null) throw new ArgumentNullException(nameof(partialName)); - return Load(partialName); + if ((partialName.Length == 0) || (partialName[0] == '\0')) + throw new ArgumentException(SR.Format_StringZeroLength, nameof(partialName)); + + try + { + return Load(partialName); + } + catch (FileNotFoundException) + { + return null; + } } // Loads the assembly with a COFF based IMAGE containing diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyAlgorithmIdAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyAlgorithmIdAttribute.cs index fe24f353beb1..df91553db0b2 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyAlgorithmIdAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyAlgorithmIdAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Configuration.Assemblies; namespace System.Reflection diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCompanyAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCompanyAttribute.cs index d986db60a341..c1e7a82c578d 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCompanyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCompanyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyConfigurationAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyConfigurationAttribute.cs index 195c4d0ca60d..4c6d367dace8 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyConfigurationAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyConfigurationAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyContentType.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyContentType.cs index 2ee1a008181c..938ac26d653e 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyContentType.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyContentType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { public enum AssemblyContentType diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCopyrightAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCopyrightAttribute.cs index e50e19932b9b..fe06a4f5cc79 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCopyrightAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCopyrightAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCultureAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCultureAttribute.cs index e31c6f9c1cbd..ee70784873b7 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCultureAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyCultureAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDelaySignAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDelaySignAttribute.cs index eae2cf613c7c..02acff9ed3a0 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDelaySignAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDelaySignAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDescriptionAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDescriptionAttribute.cs index 50f57c96a659..4348a78698cd 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDescriptionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyDescriptionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFileVersionAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFileVersionAttribute.cs index b5face65bcbd..2bd76ceaa64c 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFileVersionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFileVersionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] @@ -9,9 +10,7 @@ public sealed class AssemblyFileVersionAttribute : Attribute { public AssemblyFileVersionAttribute(string version) { - if (version == null) - throw new ArgumentNullException(nameof(version)); - Version = version; + Version = version ?? throw new ArgumentNullException(nameof(version)); } public string Version { get; } diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFlagsAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFlagsAttribute.cs index be35bc028933..6520831aa726 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFlagsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyFlagsAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyInformationalVersionAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyInformationalVersionAttribute.cs index 915b973ab94e..29384a84517e 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyInformationalVersionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyInformationalVersionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyFileAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyFileAttribute.cs index 9f7387d8af06..5bfcb170a404 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyFileAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyFileAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyNameAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyNameAttribute.cs index 4cf51754eaf2..4a1dc4eb5969 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyNameAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyKeyNameAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyMetadataAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyMetadataAttribute.cs index de9f6351ec65..3ca34e81fb33 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyMetadataAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyMetadataAttribute.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] public sealed class AssemblyMetadataAttribute : Attribute { - public AssemblyMetadataAttribute(string key, string value) + public AssemblyMetadataAttribute(string key, string? value) { Key = key; Value = value; @@ -15,7 +16,7 @@ public AssemblyMetadataAttribute(string key, string value) public string Key { get; } - public string Value { get; } + public string? Value { get; } } } diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyName.cs similarity index 70% rename from src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs rename to src/System.Private.CoreLib/shared/System/Reflection/AssemblyName.cs index e80479903507..8af4a9218024 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyName.cs @@ -2,77 +2,61 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Configuration.Assemblies; using System.IO; -using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Text; using CultureInfo = System.Globalization.CultureInfo; namespace System.Reflection { - public sealed class AssemblyName : ICloneable, IDeserializationCallback, ISerializable + public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable { // If you modify any of these fields, you must also update the // AssemblyBaseObject structure in object.h - private string _name; - private byte[] _publicKey; - private byte[] _publicKeyToken; - private CultureInfo _cultureInfo; - private string _codeBase; - private Version _version; + private string? _name; + private byte[]? _publicKey; + private byte[]? _publicKeyToken; + private CultureInfo? _cultureInfo; + private string? _codeBase; + private Version? _version; - private StrongNameKeyPair _strongNameKeyPair; + private StrongNameKeyPair? _strongNameKeyPair; - private byte[] _hashForControl; private AssemblyHashAlgorithm _hashAlgorithm; - private AssemblyHashAlgorithm _hashAlgorithmForControl; private AssemblyVersionCompatibility _versionCompatibility; private AssemblyNameFlags _flags; public AssemblyName() { - _hashAlgorithm = AssemblyHashAlgorithm.None; _versionCompatibility = AssemblyVersionCompatibility.SameMachine; - _flags = AssemblyNameFlags.None; - } - - public AssemblyName(string assemblyName) - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if ((assemblyName.Length == 0) || - (assemblyName[0] == '\0')) - throw new ArgumentException(SR.Format_StringZeroLength); - - _name = assemblyName; - nInit(); } // Set and get the name of the assembly. If this is a weak Name // then it optionally contains a site. For strong assembly names, // the name partitions up the strong name's namespace - public string Name + public string? Name { get { return _name; } set { _name = value; } } - public Version Version + public Version? Version { get { return _version; } set { _version = value; } } // Locales, internally the LCID is used for the match. - public CultureInfo CultureInfo + public CultureInfo? CultureInfo { get { return _cultureInfo; } set { _cultureInfo = value; } } - public string CultureName + public string? CultureName { get { @@ -84,13 +68,13 @@ public string CultureName } } - public string CodeBase + public string? CodeBase { get { return _codeBase; } set { _codeBase = value; } } - public string EscapedCodeBase + public string? EscapedCodeBase { get { @@ -144,19 +128,18 @@ public AssemblyContentType ContentType // Make a copy of this assembly name. public object Clone() { - AssemblyName name = new AssemblyName(); - name.Init(_name, - _publicKey, - _publicKeyToken, - _version, - _cultureInfo, - _hashAlgorithm, - _versionCompatibility, - _codeBase, - _flags, - _strongNameKeyPair); - name._hashForControl = _hashForControl; - name._hashAlgorithmForControl = _hashAlgorithmForControl; + var name = new AssemblyName + { + _name = _name, + _publicKey = (byte[]?)_publicKey?.Clone(), + _publicKeyToken = (byte[]?)_publicKeyToken?.Clone(), + _cultureInfo = _cultureInfo, + _version = (Version?)_version?.Clone(), + _flags = _flags, + _codeBase = _codeBase, + _hashAlgorithm = _hashAlgorithm, + _versionCompatibility = _versionCompatibility, + }; return name; } @@ -170,22 +153,15 @@ public static AssemblyName GetAssemblyName(string assemblyFile) if (assemblyFile == null) throw new ArgumentNullException(nameof(assemblyFile)); - // Assembly.GetNameInternal() will not demand path discovery - // permission, so do that first. - string fullPath = Path.GetFullPath(assemblyFile); - return nGetFileInformation(fullPath); + return GetFileInformationCore(assemblyFile); } - // The public key that is used to verify an assemblies - // inclusion into the namespace. If the public key associated - // with the namespace cannot verify the assembly the assembly - // will fail to load. - public byte[] GetPublicKey() + public byte[]? GetPublicKey() { return _publicKey; } - public void SetPublicKey(byte[] publicKey) + public void SetPublicKey(byte[]? publicKey) { _publicKey = publicKey; @@ -200,11 +176,11 @@ public void SetPublicKey(byte[] publicKey) public byte[] GetPublicKeyToken() { if (_publicKeyToken == null) - _publicKeyToken = nGetPublicKeyToken(); + _publicKeyToken = ComputePublicKeyToken(); return _publicKeyToken; } - public void SetPublicKeyToken(byte[] publicKeyToken) + public void SetPublicKeyToken(byte[]? publicKeyToken) { _publicKeyToken = publicKeyToken; } @@ -238,7 +214,7 @@ public AssemblyVersionCompatibility VersionCompatibility set { _versionCompatibility = value; } } - public StrongNameKeyPair KeyPair + public StrongNameKeyPair? KeyPair { get { return _strongNameKeyPair; } set { _strongNameKeyPair = value; } @@ -251,7 +227,7 @@ public string FullName if (this.Name == null) return string.Empty; // Do not call GetPublicKeyToken() here - that latches the result into AssemblyName which isn't a side effect we want. - byte[] pkt = _publicKeyToken ?? nGetPublicKeyToken(); + byte[] pkt = _publicKeyToken ?? ComputePublicKeyToken(); return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags, ContentType); } } @@ -260,7 +236,7 @@ public override string ToString() { string s = FullName; if (s == null) - return base.ToString(); + return base.ToString()!; else return s; } @@ -280,7 +256,7 @@ public void OnDeserialization(object sender) /// match the intent of this api, this api has been broken this way since its debut and we cannot /// change its behavior now. /// - public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition) + public static bool ReferenceMatchesDefinition(AssemblyName? reference, AssemblyName? definition) { if (object.ReferenceEquals(reference, definition)) return true; @@ -296,110 +272,13 @@ public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyNa return refName.Equals(defName, StringComparison.OrdinalIgnoreCase); } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern void nInit(out RuntimeAssembly assembly, bool raiseResolveEvent); - - internal void nInit() - { - RuntimeAssembly dummy = null; - nInit(out dummy, false); - } - - internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) - { - ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _flags); - } - - internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags) - { - if (((uint)flags & 0xF0) == 0x70) - return ProcessorArchitecture.None; - - if ((pek & System.Reflection.PortableExecutableKinds.PE32Plus) == System.Reflection.PortableExecutableKinds.PE32Plus) - { - switch (ifm) - { - case System.Reflection.ImageFileMachine.IA64: - return ProcessorArchitecture.IA64; - case System.Reflection.ImageFileMachine.AMD64: - return ProcessorArchitecture.Amd64; - case System.Reflection.ImageFileMachine.I386: - if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly) - return ProcessorArchitecture.MSIL; - break; - } - } - else - { - if (ifm == System.Reflection.ImageFileMachine.I386) - { - if ((pek & System.Reflection.PortableExecutableKinds.Required32Bit) == System.Reflection.PortableExecutableKinds.Required32Bit) - return ProcessorArchitecture.X86; - - if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly) - return ProcessorArchitecture.MSIL; - - return ProcessorArchitecture.X86; - } - if (ifm == System.Reflection.ImageFileMachine.ARM) - { - return ProcessorArchitecture.Arm; - } - } - return ProcessorArchitecture.None; - } - - internal void Init(string name, - byte[] publicKey, - byte[] publicKeyToken, - Version version, - CultureInfo cultureInfo, - AssemblyHashAlgorithm hashAlgorithm, - AssemblyVersionCompatibility versionCompatibility, - string codeBase, - AssemblyNameFlags flags, - StrongNameKeyPair keyPair) // Null if ref, matching Assembly if def - { - _name = name; - - if (publicKey != null) - { - _publicKey = new byte[publicKey.Length]; - Array.Copy(publicKey, 0, _publicKey, 0, publicKey.Length); - } - - if (publicKeyToken != null) - { - _publicKeyToken = new byte[publicKeyToken.Length]; - Array.Copy(publicKeyToken, 0, _publicKeyToken, 0, publicKeyToken.Length); - } - - if (version != null) - _version = (Version)version.Clone(); - - _cultureInfo = cultureInfo; - _hashAlgorithm = hashAlgorithm; - _versionCompatibility = versionCompatibility; - _codeBase = codeBase; - _flags = flags; - _strongNameKeyPair = keyPair; - } - - // This call opens and closes the file, but does not add the - // assembly to the domain. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern AssemblyName nGetFileInformation(string s); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern byte[] nGetPublicKeyToken(); - - internal static string EscapeCodeBase(string codebase) + internal static string EscapeCodeBase(string? codebase) { if (codebase == null) return string.Empty; int position = 0; - char[] dest = EscapeString(codebase, 0, codebase.Length, null, ref position, true, c_DummyChar, c_DummyChar, c_DummyChar); + char[]? dest = EscapeString(codebase, 0, codebase.Length, null, ref position, true, c_DummyChar, c_DummyChar, c_DummyChar); if (dest == null) return codebase; @@ -418,7 +297,7 @@ internal static string EscapeCodeBase(string codebase) // // Returns null if nothing has to be escaped AND passed dest was null, otherwise the resulting array with the updated destPos // - internal static unsafe char[] EscapeString(string input, int start, int end, char[] dest, ref int destPos, + internal static unsafe char[]? EscapeString(string input, int start, int end, char[]? dest, ref int destPos, bool isUriString, char force1, char force2, char rsvd) { int i = start; @@ -519,15 +398,15 @@ internal static unsafe char[] EscapeString(string input, int start, int end, cha // // ensure destination array has enough space and contains all the needed input stuff // - private static unsafe char[] EnsureDestinationSize(char* pStr, char[] dest, int currentInputPos, + private static unsafe char[] EnsureDestinationSize(char* pStr, char[]? dest, int currentInputPos, short charsToAdd, short minReallocateChars, ref int destPos, int prevInputPos) { - if ((object)dest == null || dest.Length < destPos + (currentInputPos - prevInputPos) + charsToAdd) + if (dest is null || dest.Length < destPos + (currentInputPos - prevInputPos) + charsToAdd) { // allocating or reallocating array by ensuring enough space based on maxCharsToAdd. char[] newresult = new char[destPos + (currentInputPos - prevInputPos) + minReallocateChars]; - if ((object)dest != null && destPos != 0) + if (!(dest is null) && destPos != 0) Buffer.BlockCopy(dest, 0, newresult, 0, destPos << 1); dest = newresult; } diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFlags.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFlags.cs index d32103203142..82f64c160aab 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFlags.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFlags.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyProductAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyProductAttribute.cs index 43cb62df9978..9966d603cb46 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyProductAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyProductAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblySignatureKeyAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblySignatureKeyAttribute.cs index e6ec8af1b389..8410b4f60267 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblySignatureKeyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblySignatureKeyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTitleAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTitleAttribute.cs index 26d7a2e66c0e..d03dad6440ac 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTitleAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTitleAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTrademarkAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTrademarkAttribute.cs index 1d3edf51d585..5b373193f6f3 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTrademarkAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyTrademarkAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyVersionAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyVersionAttribute.cs index b3557bac9739..9cba8e3f9af4 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyVersionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyVersionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/BindingFlags.cs b/src/System.Private.CoreLib/shared/System/Reflection/BindingFlags.cs index 7ba83e20da63..ac64814edd08 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/BindingFlags.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/BindingFlags.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/CallingConventions.cs b/src/System.Private.CoreLib/shared/System/Reflection/CallingConventions.cs index bb6d6cd80944..3bd060769bec 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/CallingConventions.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/CallingConventions.cs @@ -4,6 +4,7 @@ // CallingConventions is a set of Bits representing the calling conventions in the system. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/CorElementType.cs b/src/System.Private.CoreLib/shared/System/Reflection/CorElementType.cs index 37ffcfa1e254..b6968f1f11d5 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/CorElementType.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/CorElementType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { internal enum CorElementType : byte diff --git a/src/System.Private.CoreLib/shared/System/Reflection/DefaultMemberAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/DefaultMemberAttribute.cs index 585fdb07cd0f..0667d34878d7 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/DefaultMemberAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/DefaultMemberAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs index b096960406ed..baac3a7a4101 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs @@ -2,11 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - // This enumeration defines the access modes for a dynamic assembly. // EE uses these enum values..look for m_dwDynamicAssemblyAccess in Assembly.hpp +#nullable enable namespace System.Reflection.Emit { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/EventToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/EventToken.cs index 7bcc9ac4df29..85c917864f7a 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/EventToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/EventToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public struct EventToken @@ -17,7 +18,7 @@ internal EventToken(int eventToken) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is EventToken et && Equals(et); + public override bool Equals(object? obj) => obj is EventToken et && Equals(et); public bool Equals(EventToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/FieldToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FieldToken.cs index 83af736f4b30..e0aba63ba134 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/FieldToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FieldToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { /// @@ -26,7 +27,7 @@ internal FieldToken(int fieldToken, Type fieldClass) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is FieldToken ft && Equals(ft); + public override bool Equals(object? obj) => obj is FieldToken ft && Equals(ft); public bool Equals(FieldToken obj) => obj.Token == Token && obj._class == _class; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs index 12a97c70be2e..0410cc915f40 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs @@ -12,8 +12,7 @@ ** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.** ==============================================================*/ -using System; - +#nullable enable namespace System.Reflection.Emit { public enum FlowControl diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs index 503d8b32beec..4aa5e7c9596b 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs @@ -14,10 +14,7 @@ ** ===========================================================*/ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - +#nullable enable namespace System.Reflection.Emit { // The Label class is an opaque representation of a label used by the @@ -49,7 +46,7 @@ public override int GetHashCode() return m_label; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is Label) return Equals((Label)obj); diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/MethodToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/MethodToken.cs index be4b0ee005ca..0ed6872e0bb9 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/MethodToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/MethodToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public struct MethodToken @@ -17,7 +18,7 @@ internal MethodToken(int methodToken) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is MethodToken mt && Equals(mt); + public override bool Equals(object? obj) => obj is MethodToken mt && Equals(mt); public bool Equals(MethodToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs index 4304c730ddbc..779aacaf6b0c 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs @@ -12,8 +12,7 @@ ** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.** ==============================================================*/ -using System; - +#nullable enable namespace System.Reflection.Emit { public enum OpCodeType diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs index 7690005e2f18..b4895938d49a 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { // diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs index fdac84f44352..6b191bfa00aa 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Threading; namespace System.Reflection.Emit @@ -108,9 +109,9 @@ public short Value } } - private static volatile string[] g_nameCache; + private static volatile string[]? g_nameCache; - public string Name + public string? Name { get { @@ -119,7 +120,7 @@ public string Name // Create and cache the opcode names lazily. They should be rarely used (only for logging, etc.) // Note that we do not any locks here because of we always get the same names. The last one wins. - string[] nameCache = g_nameCache; + string[]? nameCache = g_nameCache; if (nameCache == null) { nameCache = new string[0x11f]; @@ -149,13 +150,13 @@ public string Name return name; // Create ilasm style name from the enum value name. - name = Enum.GetName(typeof(OpCodeValues), opCodeValue).ToLowerInvariant().Replace('_', '.'); + name = Enum.GetName(typeof(OpCodeValues), opCodeValue)!.ToLowerInvariant().Replace('_', '.'); Volatile.Write(ref nameCache[idx], name); return name; } } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is OpCode) return Equals((OpCode)obj); @@ -183,7 +184,7 @@ public override int GetHashCode() return Value; } - public override string ToString() + public override string? ToString() { return Name; } diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs index 356fffab03fd..3bc5c7030817 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs @@ -12,8 +12,7 @@ ** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.** ==============================================================*/ -using System; - +#nullable enable namespace System.Reflection.Emit { public enum OperandType diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs index f6606c477a08..d01e6bf34bdd 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -using System; - +#nullable enable namespace System.Reflection.Emit { // This Enum matchs the CorFieldAttr defined in CorHdr.h diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs index f734e1a3423c..d0bb0441899b 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public enum PackingSize diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/ParameterToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/ParameterToken.cs index d8a087d5298b..a0ce2eeb220c 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/ParameterToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/ParameterToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { /// @@ -21,7 +22,7 @@ internal ParameterToken(int parameterToken) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is ParameterToken pt && Equals(pt); + public override bool Equals(object? obj) => obj is ParameterToken pt && Equals(pt); public bool Equals(ParameterToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PropertyToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PropertyToken.cs index b63fe7896638..c116426e43ac 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PropertyToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PropertyToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public struct PropertyToken @@ -17,7 +18,7 @@ internal PropertyToken(int propertyToken) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is PropertyToken pt && Equals(pt); + public override bool Equals(object? obj) => obj is PropertyToken pt && Equals(pt); public bool Equals(PropertyToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/SignatureToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/SignatureToken.cs index ba583587609c..5af7ca2b3528 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/SignatureToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/SignatureToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public struct SignatureToken @@ -17,7 +18,7 @@ internal SignatureToken(int signatureToken) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is SignatureToken st && Equals(st); + public override bool Equals(object? obj) => obj is SignatureToken st && Equals(st); public bool Equals(SignatureToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs index 3e64b48798df..6015da5efe0a 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs @@ -12,8 +12,7 @@ ** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.** ==============================================================*/ -using System; - +#nullable enable namespace System.Reflection.Emit { public enum StackBehaviour diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/StringToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StringToken.cs index 380f0ab05aae..02d3a87771de 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/StringToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StringToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public struct StringToken @@ -18,7 +19,7 @@ internal StringToken(int str) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is StringToken st && Equals(st); + public override bool Equals(object? obj) => obj is StringToken st && Equals(st); public bool Equals(StringToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/TypeToken.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/TypeToken.cs index da8a5da5ae53..303716b0d187 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/Emit/TypeToken.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/TypeToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection.Emit { public struct TypeToken @@ -17,7 +18,7 @@ internal TypeToken(int typeToken) public override int GetHashCode() => Token; - public override bool Equals(object obj) => obj is TypeToken tt && Equals(tt); + public override bool Equals(object? obj) => obj is TypeToken tt && Equals(tt); public bool Equals(TypeToken obj) => obj.Token == Token; diff --git a/src/System.Private.CoreLib/shared/System/Reflection/EventAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/EventAttributes.cs index fbc2972f697d..b41e84e787f6 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/EventAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/EventAttributes.cs @@ -5,6 +5,7 @@ // EventAttributes are an enum defining the attributes associated with and Event. // These are defined in CorHdr.h and are a combination of bits and enums. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs index 15780f11cf2f..5e753fdd8e3e 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; namespace System.Reflection @@ -15,7 +16,7 @@ protected ExceptionHandlingClause() { } public virtual int HandlerOffset => 0; public virtual int HandlerLength => 0; public virtual int FilterOffset => throw new InvalidOperationException(SR.Arg_EHClauseNotFilter); - public virtual Type CatchType => null; + public virtual Type? CatchType => null; public override string ToString() { diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClauseOptions.cs b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClauseOptions.cs index 46285f7c8264..30c72e593e9e 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClauseOptions.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClauseOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/FieldAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/FieldAttributes.cs index 048d0e70319a..90cc482eb4d7 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/FieldAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/FieldAttributes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { // This Enum matchs the CorFieldAttr defined in CorHdr.h diff --git a/src/System.Private.CoreLib/shared/System/Reflection/GenericParameterAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/GenericParameterAttributes.cs index 4b579d273ea2..4cf14a5d016e 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/GenericParameterAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/GenericParameterAttributes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ImageFileMachine.cs b/src/System.Private.CoreLib/shared/System/Reflection/ImageFileMachine.cs index 230bc952e5e9..425967a3b3fd 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ImageFileMachine.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ImageFileMachine.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { public enum ImageFileMachine diff --git a/src/System.Private.CoreLib/shared/System/Reflection/InterfaceMapping.cs b/src/System.Private.CoreLib/shared/System/Reflection/InterfaceMapping.cs index 2e0c0d8a28e6..ec8b1184ec32 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/InterfaceMapping.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/InterfaceMapping.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // TODO-NULLABLE: Re-review namespace System.Reflection { public struct InterfaceMapping diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MemberTypes.cs b/src/System.Private.CoreLib/shared/System/Reflection/MemberTypes.cs index 57072dcfbeaf..06823b86de43 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/MemberTypes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/MemberTypes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] @@ -17,4 +18,4 @@ public enum MemberTypes NestedType = 0x80, All = Constructor | Event | Field | Method | Property | TypeInfo | NestedType, } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MethodAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/MethodAttributes.cs index 1a7c7bf154e1..4448eb5a2382 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/MethodAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/MethodAttributes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MethodImplAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/MethodImplAttributes.cs index b16f4a45756c..f46331b1f84b 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/MethodImplAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/MethodImplAttributes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { // This Enum matchs the CorMethodImpl defined in CorHdr.h diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ObfuscateAssemblyAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/ObfuscateAssemblyAttribute.cs index f8f765ced2c3..f183b92e086a 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ObfuscateAssemblyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ObfuscateAssemblyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ObfuscationAttribute.cs b/src/System.Private.CoreLib/shared/System/Reflection/ObfuscationAttribute.cs index 11d93b6313d9..a28d41a1474f 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ObfuscationAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ObfuscationAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Delegate, @@ -15,7 +16,7 @@ public ObfuscationAttribute() public bool StripAfterObfuscation { get; set; } = true; public bool Exclude { get; set; } = true; public bool ApplyToMembers { get; set; } = true; - public string Feature { get; set; } = "all"; + public string? Feature { get; set; } = "all"; } } diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ParameterAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/ParameterAttributes.cs index ce195897c26b..12cd1f4980c9 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ParameterAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ParameterAttributes.cs @@ -5,6 +5,7 @@ // ParameterAttributes is an enum defining the attributes that may be // associated with a Parameter. These are defined in CorHdr.h. +#nullable enable namespace System.Reflection { // This Enum matchs the CorParamAttr defined in CorHdr.h diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ParameterModifier.cs b/src/System.Private.CoreLib/shared/System/Reflection/ParameterModifier.cs index 0fb75ffbd88f..1b9cc08a0319 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ParameterModifier.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ParameterModifier.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { public readonly struct ParameterModifier diff --git a/src/System.Private.CoreLib/shared/System/Reflection/PortableExecutableKinds.cs b/src/System.Private.CoreLib/shared/System/Reflection/PortableExecutableKinds.cs index 79be33868573..b6427fd07c47 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/PortableExecutableKinds.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/PortableExecutableKinds.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ProcessorArchitecture.cs b/src/System.Private.CoreLib/shared/System/Reflection/ProcessorArchitecture.cs index becb346c4fd8..a90752110701 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ProcessorArchitecture.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ProcessorArchitecture.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { public enum ProcessorArchitecture diff --git a/src/System.Private.CoreLib/shared/System/Reflection/PropertyAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/PropertyAttributes.cs index 31e7a653bb07..1722fb4dc61b 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/PropertyAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/PropertyAttributes.cs @@ -5,6 +5,7 @@ // PropertyAttributes is an enum which defines the attributes that may be associated // with a property. The values here are defined in Corhdr.h. +#nullable enable namespace System.Reflection { // This Enum matchs the CorPropertyAttr defined in CorHdr.h diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ReflectionTypeLoadException.cs b/src/System.Private.CoreLib/shared/System/Reflection/ReflectionTypeLoadException.cs index ff2d85a83a89..c471fd9216ff 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ReflectionTypeLoadException.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ReflectionTypeLoadException.cs @@ -31,7 +31,7 @@ public ReflectionTypeLoadException(Type[]? classes, Exception?[]? exceptions, st private ReflectionTypeLoadException(SerializationInfo info, StreamingContext context) : base(info, context) { - LoaderExceptions = (Exception[])(info.GetValue("Exceptions", typeof(Exception[]))); + LoaderExceptions = (Exception[]?)(info.GetValue("Exceptions", typeof(Exception[]))); } public override void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ResourceAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/ResourceAttributes.cs index 2d03f42ba00f..26f5e75749ef 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ResourceAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ResourceAttributes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ResourceLocation.cs b/src/System.Private.CoreLib/shared/System/Reflection/ResourceLocation.cs index 4902333ac0dc..12d8928d5233 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/ResourceLocation.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/ResourceLocation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Reflection/TypeAttributes.cs b/src/System.Private.CoreLib/shared/System/Reflection/TypeAttributes.cs index aa3033185694..e164a2977f8d 100644 --- a/src/System.Private.CoreLib/shared/System/Reflection/TypeAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/TypeAttributes.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Runtime.InteropServices; - +#nullable enable namespace System.Reflection { // This Enum matchs the CorTypeAttr defined in CorHdr.h diff --git a/src/System.Private.CoreLib/shared/System/ResolveEventArgs.cs b/src/System.Private.CoreLib/shared/System/ResolveEventArgs.cs index 6196947bb55e..447d4343ef57 100644 --- a/src/System.Private.CoreLib/shared/System/ResolveEventArgs.cs +++ b/src/System.Private.CoreLib/shared/System/ResolveEventArgs.cs @@ -2,24 +2,25 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; namespace System { public class ResolveEventArgs : EventArgs { - public ResolveEventArgs(string name) + public ResolveEventArgs(string? name) { Name = name; } - public ResolveEventArgs(string name, Assembly requestingAssembly) + public ResolveEventArgs(string? name, Assembly? requestingAssembly) { Name = name; RequestingAssembly = requestingAssembly; } - public string Name { get; } - public Assembly RequestingAssembly { get; } + public string? Name { get; } + public Assembly? RequestingAssembly { get; } } } diff --git a/src/System.Private.CoreLib/shared/System/ResolveEventHandler.cs b/src/System.Private.CoreLib/shared/System/ResolveEventHandler.cs index cb9af5de66cd..829b146993af 100644 --- a/src/System.Private.CoreLib/shared/System/ResolveEventHandler.cs +++ b/src/System.Private.CoreLib/shared/System/ResolveEventHandler.cs @@ -2,9 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; namespace System { - public delegate Assembly ResolveEventHandler(object sender, ResolveEventArgs args); + public delegate Assembly ResolveEventHandler(object? sender, ResolveEventArgs args); } diff --git a/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs b/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs index 6b813a0cec32..51058c5ac6f9 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -21,7 +22,7 @@ namespace System.Resources { - internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer + internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer // TODO-NULLABLE: IEqualityComparer.GetHashCode does not accept nulls but Equals does { internal static readonly FastResourceComparer Default = new FastResourceComparer(); @@ -32,8 +33,9 @@ public int GetHashCode(object key) return FastResourceComparer.HashFunction(s); } - public int GetHashCode(string key) + public int GetHashCode(string? key) // TODO-NULLABLE: argument should be non-nullable but IEqualityComparer.Equals accepts null { + Debug.Assert(key != null, "TODO-NULLABLE"); return FastResourceComparer.HashFunction(key); } @@ -52,29 +54,29 @@ internal static int HashFunction(string key) } // Compares Strings quickly in a case-sensitive way - public int Compare(object a, object b) + public int Compare(object? a, object? b) { if (a == b) return 0; - string sa = (string)a; - string sb = (string)b; + string? sa = (string?)a; + string? sb = (string?)b; return string.CompareOrdinal(sa, sb); } - public int Compare(string a, string b) + public int Compare(string? a, string? b) { return string.CompareOrdinal(a, b); } - public bool Equals(string a, string b) + public bool Equals(string? a, string? b) { return string.Equals(a, b); } - public new bool Equals(object a, object b) + public new bool Equals(object? a, object? b) { if (a == b) return true; - string sa = (string)a; - string sb = (string)b; + string? sa = (string?)a; + string? sb = (string?)b; return string.Equals(sa, sb); } diff --git a/src/System.Private.CoreLib/shared/System/Resources/FileBasedResourceGroveler.cs b/src/System.Private.CoreLib/shared/System/Resources/FileBasedResourceGroveler.cs index 216ebb1e4a0a..be44da2d628b 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/FileBasedResourceGroveler.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/FileBasedResourceGroveler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -34,12 +35,12 @@ public FileBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediato // Consider modifying IResourceGroveler interface (hence this method signature) when we figure out // serialization compat story for moving ResourceManager members to either file-based or // manifest-based classes. Want to continue tightening the design to get rid of unused params. - public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists) + public ResourceSet? GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists) { Debug.Assert(culture != null, "culture shouldn't be null; check caller"); - string fileName = null; - ResourceSet rs = null; + string? fileName = null; + ResourceSet? rs = null; // Don't use Assembly manifest, but grovel on disk for a file. // Create new ResourceSet, if a file exists on disk for it. @@ -72,8 +73,7 @@ public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, + ResourceSet? GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists); } } diff --git a/src/System.Private.CoreLib/shared/System/Resources/IResourceReader.cs b/src/System.Private.CoreLib/shared/System/Resources/IResourceReader.cs index 543a5a67de8a..56b691fe6d55 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/IResourceReader.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/IResourceReader.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** diff --git a/src/System.Private.CoreLib/shared/System/Resources/ManifestBasedResourceGroveler.cs b/src/System.Private.CoreLib/shared/System/Resources/ManifestBasedResourceGroveler.cs index 485417d52a41..569fcf93ef41 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/ManifestBasedResourceGroveler.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/ManifestBasedResourceGroveler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -51,14 +52,14 @@ public ManifestBasedResourceGroveler(ResourceManager.ResourceManagerMediator med _mediator = mediator; } - public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists) + public ResourceSet? GrovelForResourceSet(CultureInfo culture, Dictionary localResourceSets, bool tryParents, bool createIfNotExists) { Debug.Assert(culture != null, "culture shouldn't be null; check caller"); Debug.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller"); - ResourceSet rs = null; - Stream stream = null; - Assembly satellite = null; + ResourceSet? rs = null; + Stream? stream = null; + Assembly? satellite = null; // 1. Fixups for ultimate fallbacks CultureInfo lookForCulture = UltimateFallbackFixup(culture); @@ -106,6 +107,7 @@ public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary(ref c, 1), name) : string.Concat(nameSpace, name); - string canonicalName = null; + string? canonicalName = null; foreach (string existingName in satellite.GetManifestResourceNames()) { if (string.Equals(existingName, resourceName, StringComparison.InvariantCultureIgnoreCase)) @@ -368,15 +374,16 @@ private Stream CaseInsensitiveManifestResourceStreamLookup(Assembly satellite, s return satellite.GetManifestResourceStream(canonicalName); } - private Assembly GetSatelliteAssembly(CultureInfo lookForCulture) + private Assembly? GetSatelliteAssembly(CultureInfo lookForCulture) { + Debug.Assert(_mediator.MainAssembly != null); if (!_mediator.LookedForSatelliteContractVersion) { _mediator.SatelliteContractVersion = _mediator.ObtainSatelliteContractVersion(_mediator.MainAssembly); _mediator.LookedForSatelliteContractVersion = true; } - Assembly satellite = null; + Assembly? satellite = null; // Look up the satellite assembly, but don't let problems // like a partially signed satellite assembly stop us from @@ -431,6 +438,7 @@ private bool CanUseDefaultResourceClasses(string readerTypeName, string resSetTy private void HandleSatelliteMissing() { + Debug.Assert(_mediator.MainAssembly != null); string satAssemName = _mediator.MainAssembly.GetName().Name + ".resources.dll"; if (_mediator.SatelliteContractVersion != null) { @@ -447,6 +455,7 @@ private void HandleSatelliteMissing() } satAssemName += ", PublicKeyToken=" + publicKeyTok; + Debug.Assert(_mediator.NeutralResourcesCulture != null); string missingCultureName = _mediator.NeutralResourcesCulture.Name; if (missingCultureName.Length == 0) { @@ -457,6 +466,7 @@ private void HandleSatelliteMissing() private void HandleResourceStreamMissing(string fileName) { + Debug.Assert(_mediator.BaseName != null); // Keep people from bothering me about resources problems if (_mediator.MainAssembly == typeof(object).Assembly && _mediator.BaseName.Equals(System.CoreLib.Name)) { @@ -473,6 +483,7 @@ private void HandleResourceStreamMissing(string fileName) if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null) resName = _mediator.LocationInfo.Namespace + Type.Delimiter; resName += fileName; + Debug.Assert(_mediator.MainAssembly != null); throw new MissingManifestResourceException(SR.Format(SR.MissingManifestResource_NoNeutralAsm, resName, _mediator.MainAssembly.GetName().Name)); } } diff --git a/src/System.Private.CoreLib/shared/System/Resources/NeutralResourcesLanguageAttribute.cs b/src/System.Private.CoreLib/shared/System/Resources/NeutralResourcesLanguageAttribute.cs index 495c5205b25d..3a1e8cf5cc92 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/NeutralResourcesLanguageAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/NeutralResourcesLanguageAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Resources { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceFallbackManager.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceFallbackManager.cs index 8268f3208d1d..731979313cfc 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/ResourceFallbackManager.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceFallbackManager.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -27,10 +28,10 @@ namespace System.Resources internal class ResourceFallbackManager : IEnumerable { private CultureInfo m_startingCulture; - private CultureInfo m_neutralResourcesCulture; + private CultureInfo? m_neutralResourcesCulture; private bool m_useParents; - internal ResourceFallbackManager(CultureInfo startingCulture, CultureInfo neutralResourcesCulture, bool useParents) + internal ResourceFallbackManager(CultureInfo? startingCulture, CultureInfo? neutralResourcesCulture, bool useParents) { if (startingCulture != null) { diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.Uap.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.Uap.cs index 1a89d56061b1..7437ac966761 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.Uap.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.Uap.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - +#nullable enable using System; using System.IO; using System.Globalization; @@ -23,12 +23,12 @@ namespace System.Resources { public partial class ResourceManager { - private WindowsRuntimeResourceManagerBase _WinRTResourceManager; - private PRIExceptionInfo _PRIExceptionInfo; + private WindowsRuntimeResourceManagerBase? _WinRTResourceManager; + private PRIExceptionInfo? _PRIExceptionInfo; private bool _PRIInitialized; private bool _useUapResourceManagement; - private string GetStringFromPRI(string stringName, CultureInfo culture, string neutralResourcesCulture) + private string? GetStringFromPRI(string stringName, CultureInfo? culture, string? neutralResourcesCulture) { Debug.Assert(_useUapResourceManagement); Debug.Assert(_WinRTResourceManager != null); @@ -42,7 +42,7 @@ private string GetStringFromPRI(string stringName, CultureInfo culture, string n culture = null; } - string startingCulture = culture?.Name; + string? startingCulture = culture?.Name; if (_PRIInitialized == false) { @@ -76,7 +76,7 @@ internal static WindowsRuntimeResourceManagerBase GetWinRTResourceManager() Assembly hiddenScopeAssembly = Assembly.Load(Internal.Runtime.Augments.RuntimeAugments.HiddenScopeAssemblyName); Type WinRTResourceManagerType = hiddenScopeAssembly.GetType("System.Resources.WindowsRuntimeResourceManager", true); #endif - return (WindowsRuntimeResourceManagerBase)Activator.CreateInstance(WinRTResourceManagerType, true); + return (WindowsRuntimeResourceManagerBase)Activator.CreateInstance(WinRTResourceManagerType, nonPublic: true)!; } // CoreCLR: When running under AppX, the following rules apply for resource lookup: @@ -100,7 +100,7 @@ private static bool ShouldUseUapResourceManagement(Assembly resourcesAssembly) #if FEATURE_APPX // Check to see if the assembly is under PLATFORM_RESOURCE_ROOTS. If it is, then we should use satellite assembly lookup for it. - string platformResourceRoots = (string)(AppContext.GetData("PLATFORM_RESOURCE_ROOTS")); + string? platformResourceRoots = (string?)AppContext.GetData("PLATFORM_RESOURCE_ROOTS"); if ((platformResourceRoots != null) && (platformResourceRoots != string.Empty)) { string resourceAssemblyPath = resourcesAssembly.Location; @@ -118,7 +118,7 @@ private static bool ShouldUseUapResourceManagement(Assembly resourcesAssembly) #else // ENABLE_WINRT foreach (var attrib in resourcesAssembly.GetCustomAttributes()) { - AssemblyMetadataAttribute meta = attrib as AssemblyMetadataAttribute; + AssemblyMetadataAttribute? meta = attrib as AssemblyMetadataAttribute; if (meta != null && meta.Key.Equals(".NETFrameworkAssembly")) { return false; @@ -147,13 +147,14 @@ private void SetUapConfiguration() return; #endif + Debug.Assert(MainAssembly != null); if (!ShouldUseUapResourceManagement(MainAssembly)) return; _useUapResourceManagement = true; // If we have the type information from the ResourceManager(Type) constructor, we use it. Otherwise, we use BaseNameField. - string reswFilename = _locationInfo == null ? BaseNameField : _locationInfo.FullName; + string? reswFilename = _locationInfo == null ? BaseNameField : _locationInfo.FullName; // The only way this can happen is if a class inherited from ResourceManager and // did not set the BaseNameField before calling the protected ResourceManager() constructor. diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.cs index b770bd7c5433..db5f81ddcdf3 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceManager.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - +#nullable enable using System.IO; using System.Globalization; using System.Reflection; @@ -95,20 +95,20 @@ public partial class ResourceManager { internal class CultureNameResourceSetPair { - public string lastCultureName; - public ResourceSet lastResourceSet; + public string? lastCultureName; + public ResourceSet? lastResourceSet; } - protected string BaseNameField; - protected Assembly MainAssembly; // Need the assembly manifest sometimes. + protected string? BaseNameField; + protected Assembly? MainAssembly; // Need the assembly manifest sometimes. - private Dictionary _resourceSets; - private string _moduleDir; // For assembly-ignorant directory location - private Type _locationInfo; // For Assembly or type-based directory layout - private Type _userResourceSet; // Which ResourceSet instance to create - private CultureInfo _neutralResourcesCulture; // For perf optimizations. + private Dictionary? _resourceSets; + private string? _moduleDir; // For assembly-ignorant directory location + private Type? _locationInfo; // For Assembly or type-based directory layout + private Type? _userResourceSet; // Which ResourceSet instance to create + private CultureInfo? _neutralResourcesCulture; // For perf optimizations. - private CultureNameResourceSetPair _lastUsedResourceCache; + private CultureNameResourceSetPair? _lastUsedResourceCache; private bool _ignoreCase; // Whether case matters in GetString & GetObject @@ -118,10 +118,10 @@ internal class CultureNameResourceSetPair // satellite for the neutral resources. private UltimateResourceFallbackLocation _fallbackLoc; // Version number of satellite assemblies to look for. May be null. - private Version _satelliteContractVersion; + private Version? _satelliteContractVersion; private bool _lookedForSatelliteContractVersion; - private IResourceGroveler _resourceGroveler; + private IResourceGroveler _resourceGroveler = null!; public static readonly int MagicNumber = unchecked((int)0xBEEFCACE); // If only hex had a K... @@ -168,7 +168,7 @@ protected ResourceManager() // // Note: System.Windows.Forms uses this method at design time. // - private ResourceManager(string baseName, string resourceDir, Type usingResourceSet) + private ResourceManager(string baseName, string resourceDir, Type? userResourceSet) { if (null == baseName) throw new ArgumentNullException(nameof(baseName)); @@ -178,7 +178,7 @@ private ResourceManager(string baseName, string resourceDir, Type usingResourceS BaseNameField = baseName; _moduleDir = resourceDir; - _userResourceSet = usingResourceSet; + _userResourceSet = userResourceSet; _resourceSets = new Dictionary(); _lastUsedResourceCache = new CultureNameResourceSetPair(); _useManifest = false; @@ -202,7 +202,7 @@ public ResourceManager(string baseName, Assembly assembly) CommonAssemblyInit(); } - public ResourceManager(string baseName, Assembly assembly, Type usingResourceSet) + public ResourceManager(string baseName, Assembly assembly, Type? usingResourceSet) { if (null == baseName) throw new ArgumentNullException(nameof(baseName)); @@ -252,11 +252,12 @@ private void CommonAssemblyInit() ResourceManagerMediator mediator = new ResourceManagerMediator(this); _resourceGroveler = new ManifestBasedResourceGroveler(mediator); + Debug.Assert(MainAssembly != null); _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, out _fallbackLoc); } // Gets the base name for the ResourceManager. - public virtual string BaseName + public virtual string? BaseName { get { return BaseNameField; } } @@ -293,6 +294,7 @@ protected UltimateResourceFallbackLocation FallbackLocation // creating a new ResourceManager isn't quite the correct behavior. public virtual void ReleaseAllResources() { + Debug.Assert(_resourceSets != null); Dictionary localResourceSets = _resourceSets; // If any calls to Close throw, at least leave ourselves in a @@ -340,7 +342,7 @@ protected virtual string GetResourceFileName(CultureInfo culture) // WARNING: This function must be kept in sync with ResourceFallbackManager.GetEnumerator() // Return the first ResourceSet, based on the first culture ResourceFallbackManager would return - internal ResourceSet GetFirstResourceSet(CultureInfo culture) + internal ResourceSet? GetFirstResourceSet(CultureInfo culture) { // Logic from ResourceFallbackManager.GetEnumerator() if (_neutralResourcesCulture != null && culture.Name == _neutralResourcesCulture.Name) @@ -358,8 +360,8 @@ internal ResourceSet GetFirstResourceSet(CultureInfo culture) } // Look in the ResourceSet table - Dictionary localResourceSets = _resourceSets; - ResourceSet rs = null; + Dictionary? localResourceSets = _resourceSets; + ResourceSet? rs = null; if (localResourceSets != null) { lock (localResourceSets) @@ -393,12 +395,12 @@ internal ResourceSet GetFirstResourceSet(CultureInfo culture) // if it hasn't yet been loaded and if parent CultureInfos should be // loaded as well for resource inheritance. // - public virtual ResourceSet GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) + public virtual ResourceSet? GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) { if (null == culture) throw new ArgumentNullException(nameof(culture)); - Dictionary localResourceSets = _resourceSets; + Dictionary? localResourceSets = _resourceSets; ResourceSet rs; if (localResourceSets != null) { @@ -412,10 +414,12 @@ public virtual ResourceSet GetResourceSet(CultureInfo culture, bool createIfNotE if (_useManifest && culture.HasInvariantCultureName) { string fileName = GetResourceFileName(culture); + Debug.Assert(MainAssembly != null); Stream stream = MainAssembly.GetManifestResourceStream(_locationInfo, fileName); if (createIfNotExists && stream != null) { rs = ((ManifestBasedResourceGroveler)_resourceGroveler).CreateResourceSet(stream, MainAssembly); + Debug.Assert(localResourceSets != null); AddResourceSet(localResourceSets, culture.Name, ref rs); return rs; } @@ -428,13 +432,14 @@ public virtual ResourceSet GetResourceSet(CultureInfo culture, bool createIfNotE // for getting a resource set lives. Access to it is controlled by // threadsafe methods such as GetResourceSet, GetString, & GetObject. // This will take a minimal number of locks. - protected virtual ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) + protected virtual ResourceSet? InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) { Debug.Assert(culture != null, "culture != null"); + Debug.Assert(_resourceSets != null); Dictionary localResourceSets = _resourceSets; - ResourceSet rs = null; - CultureInfo foundCulture = null; + ResourceSet? rs = null; + CultureInfo? foundCulture = null; lock (localResourceSets) { if (localResourceSets.TryGetValue(culture.Name, out rs)) @@ -483,7 +488,7 @@ protected virtual ResourceSet InternalGetResourceSet(CultureInfo culture, bool c // that had resources. foreach (CultureInfo updateCultureInfo in mgr) { - AddResourceSet(localResourceSets, updateCultureInfo.Name, ref rs); + AddResourceSet(localResourceSets, updateCultureInfo.Name, ref rs!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34874 // stop when we've added current or reached invariant (top of chain) if (updateCultureInfo == foundCulture) @@ -526,7 +531,7 @@ private static void AddResourceSet(Dictionary localResource } } - protected static Version GetSatelliteContractVersion(Assembly a) + protected static Version? GetSatelliteContractVersion(Assembly a) { // Ensure that the assembly reference is not null if (a == null) @@ -534,7 +539,7 @@ protected static Version GetSatelliteContractVersion(Assembly a) throw new ArgumentNullException(nameof(a), SR.ArgumentNull_Assembly); } - string v = a.GetCustomAttribute()?.Version; + string? v = a.GetCustomAttribute()?.Version; if (v == null) { // Return null. The calling code will use the assembly version instead to avoid potential type @@ -542,7 +547,7 @@ protected static Version GetSatelliteContractVersion(Assembly a) return null; } - if (!Version.TryParse(v, out Version version)) + if (!Version.TryParse(v, out Version? version)) { throw new ArgumentException(SR.Format(SR.Arg_InvalidSatelliteContract_Asm_Ver, a, v)); } @@ -589,16 +594,16 @@ internal static bool IsDefaultType(string asmTypeName, // current thread's CultureInfo, and if not found, all parent CultureInfos. // Returns null if the resource wasn't found. // - public virtual string GetString(string name) + public virtual string? GetString(string name) { - return GetString(name, (CultureInfo)null); + return GetString(name, (CultureInfo?)null); } // Looks up a resource value for a particular name. Looks in the // specified CultureInfo, and if not found, all parent CultureInfos. // Returns null if the resource wasn't found. // - public virtual string GetString(string name, CultureInfo culture) + public virtual string? GetString(string name, CultureInfo? culture) { if (null == name) throw new ArgumentNullException(nameof(name)); @@ -607,6 +612,7 @@ public virtual string GetString(string name, CultureInfo culture) if (_useUapResourceManagement) { // Throws WinRT hresults. + Debug.Assert(_neutralResourcesCulture != null); return GetStringFromPRI(name, culture, _neutralResourcesCulture.Name); } #endif @@ -616,11 +622,11 @@ public virtual string GetString(string name, CultureInfo culture) culture = CultureInfo.CurrentUICulture; } - ResourceSet last = GetFirstResourceSet(culture); + ResourceSet? last = GetFirstResourceSet(culture); if (last != null) { - string value = last.GetString(name, _ignoreCase); + string? value = last.GetString(name, _ignoreCase); if (value != null) return value; } @@ -631,13 +637,13 @@ public virtual string GetString(string name, CultureInfo culture) ResourceFallbackManager mgr = new ResourceFallbackManager(culture, _neutralResourcesCulture, true); foreach (CultureInfo currentCultureInfo in mgr) { - ResourceSet rs = InternalGetResourceSet(currentCultureInfo, true, true); + ResourceSet? rs = InternalGetResourceSet(currentCultureInfo, true, true); if (rs == null) break; if (rs != last) { - string value = rs.GetString(name, _ignoreCase); + string? value = rs.GetString(name, _ignoreCase); if (value != null) { // update last used ResourceSet @@ -663,20 +669,20 @@ public virtual string GetString(string name, CultureInfo culture) // current thread's CultureInfo, and if not found, all parent CultureInfos. // Returns null if the resource wasn't found. // - public virtual object GetObject(string name) + public virtual object? GetObject(string name) { - return GetObject(name, (CultureInfo)null, true); + return GetObject(name, (CultureInfo?)null, true); } // Looks up a resource value for a particular name. Looks in the // specified CultureInfo, and if not found, all parent CultureInfos. // Returns null if the resource wasn't found. - public virtual object GetObject(string name, CultureInfo culture) + public virtual object? GetObject(string name, CultureInfo culture) { return GetObject(name, culture, true); } - private object GetObject(string name, CultureInfo culture, bool wrapUnmanagedMemStream) + private object? GetObject(string name, CultureInfo? culture, bool wrapUnmanagedMemStream) { if (null == name) throw new ArgumentNullException(nameof(name)); @@ -686,10 +692,10 @@ private object GetObject(string name, CultureInfo culture, bool wrapUnmanagedMem culture = CultureInfo.CurrentUICulture; } - ResourceSet last = GetFirstResourceSet(culture); + ResourceSet? last = GetFirstResourceSet(culture); if (last != null) { - object value = last.GetObject(name, _ignoreCase); + object? value = last.GetObject(name, _ignoreCase); if (value != null) { @@ -707,13 +713,13 @@ private object GetObject(string name, CultureInfo culture, bool wrapUnmanagedMem foreach (CultureInfo currentCultureInfo in mgr) { - ResourceSet rs = InternalGetResourceSet(currentCultureInfo, true, true); + ResourceSet? rs = InternalGetResourceSet(currentCultureInfo, true, true); if (rs == null) break; if (rs != last) { - object value = rs.GetObject(name, _ignoreCase); + object? value = rs.GetObject(name, _ignoreCase); if (value != null) { // update the last used ResourceSet @@ -739,15 +745,15 @@ private object GetObject(string name, CultureInfo culture, bool wrapUnmanagedMem return null; } - public UnmanagedMemoryStream GetStream(string name) + public UnmanagedMemoryStream? GetStream(string name) { - return GetStream(name, (CultureInfo)null); + return GetStream(name, (CultureInfo?)null); } - public UnmanagedMemoryStream GetStream(string name, CultureInfo culture) + public UnmanagedMemoryStream? GetStream(string name, CultureInfo? culture) { - object obj = GetObject(name, culture, false); - UnmanagedMemoryStream ums = obj as UnmanagedMemoryStream; + object? obj = GetObject(name, culture, false); + UnmanagedMemoryStream? ums = obj as UnmanagedMemoryStream; if (ums == null && obj != null) throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotStream_Name, name)); return ums; @@ -767,28 +773,28 @@ internal ResourceManagerMediator(ResourceManager rm) } // NEEDED ONLY BY FILE-BASED - internal string ModuleDir + internal string? ModuleDir { get { return _rm._moduleDir; } } // NEEDED BOTH BY FILE-BASED AND ASSEMBLY-BASED - internal Type LocationInfo + internal Type? LocationInfo { get { return _rm._locationInfo; } } - internal Type UserResourceSet + internal Type? UserResourceSet { get { return _rm._userResourceSet; } } - internal string BaseNameField + internal string? BaseNameField { get { return _rm.BaseNameField; } } - internal CultureInfo NeutralResourcesCulture + internal CultureInfo? NeutralResourcesCulture { get { return _rm._neutralResourcesCulture; } set { _rm._neutralResourcesCulture = value; } @@ -806,13 +812,13 @@ internal bool LookedForSatelliteContractVersion set { _rm._lookedForSatelliteContractVersion = value; } } - internal Version SatelliteContractVersion + internal Version? SatelliteContractVersion { get { return _rm._satelliteContractVersion; } set { _rm._satelliteContractVersion = value; } } - internal Version ObtainSatelliteContractVersion(Assembly a) + internal Version? ObtainSatelliteContractVersion(Assembly a) { return ResourceManager.GetSatelliteContractVersion(a); } @@ -823,14 +829,14 @@ internal UltimateResourceFallbackLocation FallbackLoc set { _rm._fallbackLoc = value; } } - internal Assembly MainAssembly + internal Assembly? MainAssembly { get { return _rm.MainAssembly; } } // this is weird because we have BaseNameField accessor above, but we're sticking // with it for compat. - internal string BaseName + internal string? BaseName { get { return _rm.BaseName; } } diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs index 7170a988b6da..d8545507d063 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -41,10 +42,10 @@ namespace System.Resources internal struct ResourceLocator { - internal object _value; // Can be null. Consider WeakReference instead? + internal object? _value; // Can be null. Consider WeakReference instead? internal int _dataPos; - internal ResourceLocator(int dataPos, object value) + internal ResourceLocator(int dataPos, object? value) { _dataPos = dataPos; _value = value; @@ -58,7 +59,7 @@ internal int DataPosition // Allows adding in profiling data in a future version, or a special // resource profiling build. We could also use WeakReference. - internal object Value + internal object? Value { get { return _value; } set { _value = value; } @@ -82,7 +83,7 @@ public sealed class ResourceReader : IResourceReader // Used by RuntimeResourceSet and this class's enumerator. Maps // resource name to a value, a ResourceLocator, or a // LooselyLinkedManifestResource. - internal Dictionary _resCache; + internal Dictionary? _resCache; private long _nameSectionOffset; // Offset to name section of file. private long _dataSectionOffset; // Offset to Data section of file. @@ -91,26 +92,26 @@ public sealed class ResourceReader : IResourceReader // we're given an UnmanagedMemoryStream referring to the mmap'ed portion // of the assembly. The pointers here are pointers into that block of // memory controlled by the OS's loader. - private int[] _nameHashes; // hash values for all names. + private int[]? _nameHashes; // hash values for all names. private unsafe int* _nameHashesPtr; // In case we're using UnmanagedMemoryStream - private int[] _namePositions; // relative locations of names + private int[]? _namePositions; // relative locations of names private unsafe int* _namePositionsPtr; // If we're using UnmanagedMemoryStream - private Type[] _typeTable; // Lazy array of Types for resource values. - private int[] _typeNamePositions; // To delay initialize type table + private Type?[] _typeTable = null!; // Lazy array of Types for resource values. + private int[] _typeNamePositions = null!; // To delay initialize type table private int _numResources; // Num of resources files, in case arrays aren't allocated. private readonly bool _permitDeserialization; // can deserialize BinaryFormatted resources - private object _binaryFormatter; // binary formatter instance to use for deserializing + private object? _binaryFormatter; // binary formatter instance to use for deserializing // statics used to dynamically call into BinaryFormatter // When successfully located s_binaryFormatterType will point to the BinaryFormatter type // and s_deserializeMethod will point to an unbound delegate to the deserialize method. private static Type s_binaryFormatterType; - private static Func s_deserializeMethod; + private static Func s_deserializeMethod; // We'll include a separate code path that uses UnmanagedMemoryStream to // avoid allocating String objects and the like. - private UnmanagedMemoryStream _ums; + private UnmanagedMemoryStream? _ums; // Version number of .resources file, for compatibility private int _version; @@ -188,11 +189,11 @@ private unsafe void Dispose(bool disposing) // Close the stream in a thread-safe way. This fix means // that we may call Close n times, but that's safe. BinaryReader copyOfStore = _store; - _store = null; + _store = null!; // TODO-NULLABLE: dispose should not null this out if (copyOfStore != null) copyOfStore.Close(); } - _store = null; + _store = null!; // TODO-NULLABLE: dispose should not null this out _namePositions = null; _nameHashes = null; _ums = null; @@ -222,24 +223,34 @@ private void SkipString() private unsafe int GetNameHash(int index) { Debug.Assert(index >= 0 && index < _numResources, "Bad index into hash array. index: " + index); - Debug.Assert((_ums == null && _nameHashes != null && _nameHashesPtr == null) || - (_ums != null && _nameHashes == null && _nameHashesPtr != null), "Internal state mangled."); + if (_ums == null) + { + Debug.Assert(_nameHashes != null && _nameHashesPtr == null, "Internal state mangled."); return _nameHashes[index]; + } else + { + Debug.Assert(_nameHashes == null && _nameHashesPtr != null, "Internal state mangled."); return ReadUnalignedI4(&_nameHashesPtr[index]); + } } private unsafe int GetNamePosition(int index) { Debug.Assert(index >= 0 && index < _numResources, "Bad index into name position array. index: " + index); - Debug.Assert((_ums == null && _namePositions != null && _namePositionsPtr == null) || - (_ums != null && _namePositions == null && _namePositionsPtr != null), "Internal state mangled."); int r; if (_ums == null) + { + Debug.Assert(_namePositions != null && _namePositionsPtr == null, "Internal state mangled."); r = _namePositions[index]; + } else + { + Debug.Assert(_namePositions == null && _namePositionsPtr != null, "Internal state mangled."); r = ReadUnalignedI4(&_namePositionsPtr[index]); + } + if (r < 0 || r > _dataSectionOffset - _nameSectionOffset) { throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesNameInvalidOffset, r)); @@ -412,7 +423,7 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) if (_ums.Position > _ums.Length - byteLen) throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourcesIndexTooLong, index)); - string s = null; + string? s = null; char* charPtr = (char*)_ums.PositionPointer; s = new string(charPtr, 0, byteLen / 2); @@ -450,7 +461,7 @@ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset) // This is used in the enumerator. The enumerator iterates from 0 to n // of our resources and this returns the resource value for a particular // index. The parameter is NOT a virtual offset. - private object GetValueForNameIndex(int index) + private object? GetValueForNameIndex(int index) { Debug.Assert(_store != null, "ResourceReader is closed!"); long nameVA = GetNamePosition(index); @@ -476,11 +487,11 @@ private object GetValueForNameIndex(int index) // from that location. // Anyone who calls LoadObject should make sure they take a lock so // no one can cause us to do a seek in here. - internal string LoadString(int pos) + internal string? LoadString(int pos) { Debug.Assert(_store != null, "ResourceReader is closed!"); _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); - string s = null; + string? s = null; int typeIndex = _store.Read7BitEncodedInt(); if (_version == 1) { @@ -509,7 +520,7 @@ internal string LoadString(int pos) } // Called from RuntimeResourceSet - internal object LoadObject(int pos) + internal object? LoadObject(int pos) { if (_version == 1) return LoadObjectV1(pos); @@ -517,11 +528,11 @@ internal object LoadObject(int pos) return LoadObjectV2(pos, out typeCode); } - internal object LoadObject(int pos, out ResourceTypeCode typeCode) + internal object? LoadObject(int pos, out ResourceTypeCode typeCode) { if (_version == 1) { - object o = LoadObjectV1(pos); + object? o = LoadObjectV1(pos); typeCode = (o is string) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes; return o; } @@ -532,7 +543,7 @@ internal object LoadObject(int pos, out ResourceTypeCode typeCode) // from that location. // Anyone who calls LoadObject should make sure they take a lock so // no one can cause us to do a seek in here. - internal object LoadObjectV1(int pos) + internal object? LoadObjectV1(int pos) { Debug.Assert(_store != null, "ResourceReader is closed!"); Debug.Assert(_version == 1, ".resources file was not a V1 .resources file!"); @@ -553,7 +564,7 @@ internal object LoadObjectV1(int pos) } } - private object _LoadObjectV1(int pos) + private object? _LoadObjectV1(int pos) { _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); int typeIndex = _store.Read7BitEncodedInt(); @@ -607,7 +618,7 @@ private object _LoadObjectV1(int pos) } } - internal object LoadObjectV2(int pos, out ResourceTypeCode typeCode) + internal object? LoadObjectV2(int pos, out ResourceTypeCode typeCode) { Debug.Assert(_store != null, "ResourceReader is closed!"); Debug.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!"); @@ -628,7 +639,7 @@ internal object LoadObjectV2(int pos, out ResourceTypeCode typeCode) } } - private object _LoadObjectV2(int pos, out ResourceTypeCode typeCode) + private object? _LoadObjectV2(int pos, out ResourceTypeCode typeCode) { _store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin); typeCode = (ResourceTypeCode)_store.Read7BitEncodedInt(); @@ -793,7 +804,7 @@ private void InitializeBinaryFormatter() MethodInfo binaryFormatterDeserialize = s_binaryFormatterType.GetMethod("Deserialize", new Type[] { typeof(Stream) }); // create an unbound delegate that can accept a BinaryFormatter instance as object - return (Func)typeof(ResourceReader) + return (Func)typeof(ResourceReader) .GetMethod(nameof(CreateUntypedDelegate), BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(s_binaryFormatterType) .Invoke(null, new object[] { binaryFormatterDeserialize }); @@ -1030,7 +1041,7 @@ private Type FindType(int typeIndex) } } Debug.Assert(_typeTable[typeIndex] != null, "Should have found a type!"); - return _typeTable[typeIndex]; + return _typeTable[typeIndex]!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 } public void GetResourceData(string resourceName, out string resourceType, out byte[] resourceData) @@ -1166,7 +1177,7 @@ public object Key } } - public object Current + public object? Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { get { @@ -1192,7 +1203,7 @@ public DictionaryEntry Entry if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed); string key; - object value = null; + object? value = null; lock (_reader) { // locks should be taken in the same order as in RuntimeResourceSet.GetObject to avoid deadlock lock (_reader._resCache) @@ -1221,7 +1232,7 @@ public DictionaryEntry Entry } } - public object Value + public object? Value { get { diff --git a/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs index 2d33f3a8b086..05df000b7caf 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -14,6 +15,7 @@ ===========================================================*/ using System.Collections; +using System.Diagnostics; using System.IO; using System.Reflection; @@ -27,16 +29,16 @@ namespace System.Resources // public class ResourceSet : IDisposable, IEnumerable { - protected IResourceReader Reader; - internal Hashtable Table; + protected IResourceReader Reader = null!; + internal Hashtable? Table; // TODO-NULLABLE: should not be nulled out in Dispose - private Hashtable _caseInsensitiveTable; // For case-insensitive lookups. + private Hashtable? _caseInsensitiveTable; // For case-insensitive lookups. protected ResourceSet() { // To not inconvenience people subclassing us, we should allocate a new // hashtable here just so that Table is set to something. - CommonInit(); + Table = new Hashtable(); } // For RuntimeResourceSet, ignore the Table parameter - it's a wasted @@ -50,9 +52,9 @@ internal ResourceSet(bool junk) // on disk. // public ResourceSet(string fileName) + : this() { Reader = new ResourceReader(fileName); - CommonInit(); ReadResources(); } @@ -61,26 +63,21 @@ public ResourceSet(string fileName) // of data. // public ResourceSet(Stream stream) + : this() { Reader = new ResourceReader(stream); - CommonInit(); ReadResources(); } public ResourceSet(IResourceReader reader) + : this() { if (reader == null) throw new ArgumentNullException(nameof(reader)); Reader = reader; - CommonInit(); ReadResources(); } - private void CommonInit() - { - Table = new Hashtable(); - } - // Closes and releases any resources used by this ResourceSet, if any. // All calls to methods on the ResourceSet after a call to close may // fail. Close is guaranteed to be safely callable multiple times on a @@ -95,12 +92,12 @@ protected virtual void Dispose(bool disposing) if (disposing) { // Close the Reader in a thread-safe way. - IResourceReader copyOfReader = Reader; - Reader = null; + IResourceReader? copyOfReader = Reader; + Reader = null!; // TODO-NULLABLE: should not be nulled out in the Dispose if (copyOfReader != null) copyOfReader.Close(); } - Reader = null; + Reader = null!; // TODO-NULLABLE: should not be nulled out in the Dispose _caseInsensitiveTable = null; Table = null; } @@ -139,7 +136,7 @@ IEnumerator IEnumerable.GetEnumerator() private IDictionaryEnumerator GetEnumeratorHelper() { - Hashtable copyOfTable = Table; // Avoid a race with Dispose + Hashtable? copyOfTable = Table; // Avoid a race with Dispose if (copyOfTable == null) throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet); return copyOfTable.GetEnumerator(); @@ -147,12 +144,12 @@ private IDictionaryEnumerator GetEnumeratorHelper() // Look up a string value for a resource given its name. // - public virtual string GetString(string name) + public virtual string? GetString(string name) { - object obj = GetObjectInternal(name); + object? obj = GetObjectInternal(name); try { - return (string)obj; + return (string?)obj; } catch (InvalidCastException) { @@ -160,16 +157,16 @@ public virtual string GetString(string name) } } - public virtual string GetString(string name, bool ignoreCase) + public virtual string? GetString(string name, bool ignoreCase) { - object obj; - string s; + object? obj; + string? s; // Case-sensitive lookup obj = GetObjectInternal(name); try { - s = (string)obj; + s = (string?)obj; } catch (InvalidCastException) { @@ -186,7 +183,7 @@ public virtual string GetString(string name, bool ignoreCase) obj = GetCaseInsensitiveObjectInternal(name); try { - return (string)obj; + return (string?)obj; } catch (InvalidCastException) { @@ -196,14 +193,14 @@ public virtual string GetString(string name, bool ignoreCase) // Look up an object value for a resource given its name. // - public virtual object GetObject(string name) + public virtual object? GetObject(string name) { return GetObjectInternal(name); } - public virtual object GetObject(string name, bool ignoreCase) + public virtual object? GetObject(string name, bool ignoreCase) { - object obj = GetObjectInternal(name); + object? obj = GetObjectInternal(name); if (obj != null || !ignoreCase) return obj; @@ -213,22 +210,24 @@ public virtual object GetObject(string name, bool ignoreCase) protected virtual void ReadResources() { + Debug.Assert(Table != null); + Debug.Assert(Reader != null); IDictionaryEnumerator en = Reader.GetEnumerator(); while (en.MoveNext()) { - object value = en.Value; + object? value = en.Value; Table.Add(en.Key, value); } // While technically possible to close the Reader here, don't close it // to help with some WinRes lifetime issues. } - private object GetObjectInternal(string name) + private object? GetObjectInternal(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); - Hashtable copyOfTable = Table; // Avoid a race with Dispose + Hashtable? copyOfTable = Table; // Avoid a race with Dispose if (copyOfTable == null) throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet); @@ -236,14 +235,14 @@ private object GetObjectInternal(string name) return copyOfTable[name]; } - private object GetCaseInsensitiveObjectInternal(string name) + private object? GetCaseInsensitiveObjectInternal(string name) { - Hashtable copyOfTable = Table; // Avoid a race with Dispose + Hashtable? copyOfTable = Table; // Avoid a race with Dispose if (copyOfTable == null) throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet); - Hashtable caseTable = _caseInsensitiveTable; // Avoid a race condition with Close + Hashtable? caseTable = _caseInsensitiveTable; // Avoid a race condition with Close if (caseTable == null) { caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase); diff --git a/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs b/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs index 210fff7bf6bc..c2d27d2e60db 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -173,19 +174,19 @@ sealed class RuntimeResourceSet : ResourceSet, IEnumerable // for arbitrarily long times, since the object is usually a string // literal that will live for the lifetime of the appdomain. The // value is a ResourceLocator instance, which might cache the object. - private Dictionary _resCache; + private Dictionary? _resCache; // TODO-NULLABLE: should not be nulled out in Dispose // For our special load-on-demand reader, cache the cast. The // RuntimeResourceSet's implementation knows how to treat this reader specially. - private ResourceReader _defaultReader; + private ResourceReader? _defaultReader; // TODO-NULLABLE: should not be nulled out in Dispose // This is a lookup table for case-insensitive lookups, and may be null. // Consider always using a case-insensitive resource cache, as we don't // want to fill this out if we can avoid it. The problem is resource // fallback will somewhat regularly cause us to look up resources that // don't exist. - private Dictionary _caseInsensitiveTable; + private Dictionary? _caseInsensitiveTable; // If we're not using our custom reader, then enumerate through all // the resources once, adding them into the table. @@ -256,36 +257,36 @@ private IDictionaryEnumerator GetEnumeratorHelper() } - public override string GetString(string key) + public override string? GetString(string key) { - object o = GetObject(key, false, true); - return (string)o; + object? o = GetObject(key, false, true); + return (string?)o; } - public override string GetString(string key, bool ignoreCase) + public override string? GetString(string key, bool ignoreCase) { - object o = GetObject(key, ignoreCase, true); - return (string)o; + object? o = GetObject(key, ignoreCase, true); + return (string?)o; } - public override object GetObject(string key) + public override object? GetObject(string key) { return GetObject(key, false, false); } - public override object GetObject(string key, bool ignoreCase) + public override object? GetObject(string key, bool ignoreCase) { return GetObject(key, ignoreCase, false); } - private object GetObject(string key, bool ignoreCase, bool isString) + private object? GetObject(string key, bool ignoreCase, bool isString) { if (key == null) throw new ArgumentNullException(nameof(key)); if (Reader == null || _resCache == null) throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet); - object value = null; + object? value = null; ResourceLocator resLocation; lock (Reader) @@ -361,7 +362,10 @@ private object GetObject(string key, bool ignoreCase, bool isString) ResourceLocator resLoc = new ResourceLocator(-1, entry.Value); _resCache.Add(readKey, resLoc); if (ignoreCase) + { + Debug.Assert(_caseInsensitiveTable != null); _caseInsensitiveTable.Add(readKey, resLoc); + } } // Only close the reader if it is NOT our default one, // since we need it around to resolve ResourceLocators. @@ -371,6 +375,7 @@ private object GetObject(string key, bool ignoreCase, bool isString) else { Debug.Assert(ignoreCase, "This should only happen for case-insensitive lookups"); + Debug.Assert(_caseInsensitiveTable != null); ResourceReader.ResourceEnumerator en = _defaultReader.GetEnumeratorInternal(); while (en.MoveNext()) { @@ -383,7 +388,7 @@ private object GetObject(string key, bool ignoreCase, bool isString) } _haveReadFromReader = true; } - object obj = null; + object? obj = null; bool found = false; bool keyInWrongCase = false; if (_defaultReader != null) @@ -396,6 +401,7 @@ private object GetObject(string key, bool ignoreCase, bool isString) } if (!found && ignoreCase) { + Debug.Assert(_caseInsensitiveTable != null); if (_caseInsensitiveTable.TryGetValue(key, out resLocation)) { found = true; @@ -410,16 +416,17 @@ private object GetObject(string key, bool ignoreCase, bool isString) // The last parameter indicates whether the lookup required a // case-insensitive lookup to succeed, indicating we shouldn't add // the ResourceLocation to our case-sensitive cache. - private object ResolveResourceLocator(ResourceLocator resLocation, string key, Dictionary copyOfCache, bool keyInWrongCase) + private object? ResolveResourceLocator(ResourceLocator resLocation, string key, Dictionary copyOfCache, bool keyInWrongCase) { // We need to explicitly resolve loosely linked manifest // resources, and we need to resolve ResourceLocators with null objects. - object value = resLocation.Value; + object? value = resLocation.Value; if (value == null) { ResourceTypeCode typeCode; lock (Reader) { + Debug.Assert(_defaultReader != null); value = _defaultReader.LoadObject(resLocation.DataPosition, out typeCode); } if (!keyInWrongCase && ResourceLocator.CanCache(typeCode)) diff --git a/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs b/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs index aeccadca99bb..c11ec0a3f971 100644 --- a/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable /*============================================================ ** ** @@ -14,6 +15,7 @@ ** ===========================================================*/ +#nullable enable namespace System.Resources { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs index 25efcafa3fd8..3a74d9bfa489 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Field)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs index f1d3335c51c7..942a867b034f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; using System.Threading; -using System.Threading.Tasks; namespace System.Runtime.CompilerServices { diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorStateMachineAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorStateMachineAttribute.cs index 489195569de2..08cdcf0253c6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorStateMachineAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorStateMachineAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { /// Indicates whether a method is an asynchronous iterator. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index 47853b17d7a4..53978e8d0c19 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -10,6 +10,7 @@ // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +#nullable enable using System.Diagnostics; using System.Diagnostics.Tracing; using System.Reflection; @@ -28,7 +29,7 @@ namespace System.Runtime.CompilerServices public struct AsyncVoidMethodBuilder { /// The synchronization context associated with this operation. - private SynchronizationContext _synchronizationContext; + private SynchronizationContext? _synchronizationContext; /// The builder this void builder wraps. private AsyncTaskMethodBuilder _builder; // mutable struct: must not be readonly @@ -36,7 +37,7 @@ public struct AsyncVoidMethodBuilder /// The initialized . public static AsyncVoidMethodBuilder Create() { - SynchronizationContext sc = SynchronizationContext.Current; + SynchronizationContext? sc = SynchronizationContext.Current; sc?.OperationStarted(); #if PROJECTN // ProjectN's AsyncTaskMethodBuilder.Create() currently does additional debugger-related @@ -131,7 +132,7 @@ public void SetException(Exception exception) // and decrement its outstanding operation count. try { - System.Threading.Tasks.Task.ThrowAsync(exception, targetContext: _synchronizationContext); + System.Threading.Tasks.Task.ThrowAsync(exception!, targetContext: _synchronizationContext); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } finally { @@ -143,7 +144,7 @@ public void SetException(Exception exception) // Otherwise, queue the exception to be thrown on the ThreadPool. This will // result in a crash unless legacy exception behavior is enabled by a config // file or a CLR host. - System.Threading.Tasks.Task.ThrowAsync(exception, targetContext: null); + System.Threading.Tasks.Task.ThrowAsync(exception!, targetContext: null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // The exception was propagated already; we don't need or want to fault the builder, just mark it as completed. @@ -314,7 +315,7 @@ public struct AsyncTaskMethodBuilder { #if !PROJECTN /// A cached task for default(TResult). - internal readonly static Task s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)); + internal readonly static Task s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)!); // TODO-NULLABLE-GENERIC #endif /// The lazily-initialized built task. @@ -411,17 +412,17 @@ public void AwaitUnsafeOnCompleted( // The null tests here ensure that the jit can optimize away the interface // tests when TAwaiter is a ref type. - if ((null != (object)default(TAwaiter)) && (awaiter is ITaskAwaiter)) + if ((null != (object)default(TAwaiter)!) && (awaiter is ITaskAwaiter)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { ref TaskAwaiter ta = ref Unsafe.As(ref awaiter); // relies on TaskAwaiter/TaskAwaiter having the same layout TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, continueOnCapturedContext: true); } - else if ((null != (object)default(TAwaiter)) && (awaiter is IConfiguredTaskAwaiter)) + else if ((null != (object)default(TAwaiter)!) && (awaiter is IConfiguredTaskAwaiter)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { ref ConfiguredTaskAwaitable.ConfiguredTaskAwaiter ta = ref Unsafe.As(ref awaiter); TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, ta.m_continueOnCapturedContext); } - else if ((null != (object)default(TAwaiter)) && (awaiter is IStateMachineBoxAwareAwaiter)) + else if ((null != (object)default(TAwaiter)!) && (awaiter is IStateMachineBoxAwareAwaiter)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { try { @@ -461,7 +462,7 @@ private IAsyncStateMachineBox GetStateMachineBox( ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { - ExecutionContext currentContext = ExecutionContext.Capture(); + ExecutionContext? currentContext = ExecutionContext.Capture(); // Check first for the most common case: not the first yield in an async method. // In this case, the first yield will have already "boxed" the state machine in @@ -573,7 +574,7 @@ private class AsyncStateMachineBox : // SOS DumpAsync command dep // Used to initialize s_callback above. We don't use a lambda for this on purpose: a lambda would // introduce a new generic type behind the scenes that comes with a hefty size penalty in AOT builds. - private static void ExecutionContextCallback(object s) + private static void ExecutionContextCallback(object? s) { Debug.Assert(s is AsyncStateMachineBox); // Only used privately to pass directly to EC.Run @@ -581,11 +582,11 @@ private static void ExecutionContextCallback(object s) } /// A delegate to the method. - private Action _moveNextAction; + private Action? _moveNextAction; /// The state machine itself. - public TStateMachine StateMachine; // mutable struct; do not make this readonly. SOS DumpAsync command depends on this name. + public TStateMachine StateMachine = default!; // mutable struct; do not make this readonly. SOS DumpAsync command depends on this name. // TODO-NULLABLE-GENERIC /// Captured ExecutionContext with which to invoke ; may be null. - public ExecutionContext Context; + public ExecutionContext? Context; /// A delegate to the method. public Action MoveNextAction => _moveNextAction ?? (_moveNextAction = new Action(MoveNext)); @@ -595,7 +596,7 @@ private static void ExecutionContextCallback(object s) /// Calls MoveNext on public void MoveNext() => MoveNext(threadPoolThread: null); - private void MoveNext(Thread threadPoolThread) + private void MoveNext(Thread? threadPoolThread) { Debug.Assert(!IsCompleted); @@ -605,7 +606,7 @@ private void MoveNext(Thread threadPoolThread) AsyncCausalityTracer.TraceSynchronousWorkStart(this, CausalitySynchronousWork.Execution); } - ExecutionContext context = Context; + ExecutionContext? context = Context; if (context == null) { StateMachine.MoveNext(); @@ -627,7 +628,7 @@ private void MoveNext(Thread threadPoolThread) // Clear out state now that the async method has completed. // This avoids keeping arbitrary state referenced by lifted locals // if this Task / state machine box is held onto. - StateMachine = default; + StateMachine = default!; // TODO-NULLABLE-GENERIC Context = default; #if !CORERT @@ -770,7 +771,7 @@ internal void SetResult(Task completedTask) else { // Otherwise, complete the task that's there. - SetExistingTaskResult(default); + SetExistingTaskResult(default!); // TODO-NULLABLE-GENERIC } } @@ -794,7 +795,7 @@ public void SetException(Exception exception) // If the exception represents cancellation, cancel the task. Otherwise, fault the task. bool successfullySet = exception is OperationCanceledException oce ? task.TrySetCanceled(oce.CancellationToken, oce) : - task.TrySetException(exception); + task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 // Unlike with TaskCompletionSource, we do not need to spin here until _taskAndStateMachine is completed, // since AsyncTaskMethodBuilder.SetException should not be immediately followed by any code @@ -878,7 +879,7 @@ internal static Task GetTaskForResult(TResult result) // find a cached value, since static fields (even if readonly and integral types) // require special access helpers in this NGEN'd and domain-neutral. - if (null != (object)default(TResult)) // help the JIT avoid the value type branches for ref types + if (null != (object)default(TResult)!) // help the JIT avoid the value type branches for ref types // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { // Special case simple value types: // - Boolean @@ -894,7 +895,7 @@ internal static Task GetTaskForResult(TResult result) // For Boolean, we cache all possible values. if (typeof(TResult) == typeof(bool)) // only the relevant branches are kept for each value-type generic instantiation { - bool value = (bool)(object)result; + bool value = (bool)(object)result!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 Task task = value ? AsyncTaskCache.TrueTask : AsyncTaskCache.FalseTask; return Unsafe.As>(task); // UnsafeCast avoids type check we know will succeed } @@ -904,7 +905,7 @@ internal static Task GetTaskForResult(TResult result) // Compare to constants to avoid static field access if outside of cached range. // We compare to the upper bound first, as we're more likely to cache miss on the upper side than on the // lower side, due to positive values being more common than negative as return values. - int value = (int)(object)result; + int value = (int)(object)result!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 if (value < AsyncTaskCache.EXCLUSIVE_INT32_MAX && value >= AsyncTaskCache.INCLUSIVE_INT32_MIN) { @@ -914,16 +915,16 @@ internal static Task GetTaskForResult(TResult result) } // For other known value types, we only special-case 0 / default(TResult). else if ( - (typeof(TResult) == typeof(uint) && default == (uint)(object)result) || - (typeof(TResult) == typeof(byte) && default(byte) == (byte)(object)result) || - (typeof(TResult) == typeof(sbyte) && default(sbyte) == (sbyte)(object)result) || - (typeof(TResult) == typeof(char) && default(char) == (char)(object)result) || - (typeof(TResult) == typeof(long) && default == (long)(object)result) || - (typeof(TResult) == typeof(ulong) && default == (ulong)(object)result) || - (typeof(TResult) == typeof(short) && default(short) == (short)(object)result) || - (typeof(TResult) == typeof(ushort) && default(ushort) == (ushort)(object)result) || - (typeof(TResult) == typeof(IntPtr) && default == (IntPtr)(object)result) || - (typeof(TResult) == typeof(UIntPtr) && default == (UIntPtr)(object)result)) + (typeof(TResult) == typeof(uint) && default == (uint)(object)result!) || + (typeof(TResult) == typeof(byte) && default(byte) == (byte)(object)result!) || + (typeof(TResult) == typeof(sbyte) && default(sbyte) == (sbyte)(object)result!) || + (typeof(TResult) == typeof(char) && default(char) == (char)(object)result!) || + (typeof(TResult) == typeof(long) && default == (long)(object)result!) || + (typeof(TResult) == typeof(ulong) && default == (ulong)(object)result!) || + (typeof(TResult) == typeof(short) && default(short) == (short)(object)result!) || + (typeof(TResult) == typeof(ushort) && default(ushort) == (ushort)(object)result!) || + (typeof(TResult) == typeof(IntPtr) && default == (IntPtr)(object)result!) || + (typeof(TResult) == typeof(UIntPtr) && default == (UIntPtr)(object)result!)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 { return s_defaultResultTask; } @@ -1013,22 +1014,22 @@ public static void Start(ref TStateMachine stateMachine) where TS // Capture references to Thread Contexts Thread currentThread0 = Thread.CurrentThread; Thread currentThread = currentThread0; - ExecutionContext previousExecutionCtx0 = currentThread0._executionContext; + ExecutionContext? previousExecutionCtx0 = currentThread0._executionContext; // Store current ExecutionContext and SynchronizationContext as "previousXxx". // This allows us to restore them and undo any Context changes made in stateMachine.MoveNext // so that they won't "leak" out of the first await. - ExecutionContext previousExecutionCtx = previousExecutionCtx0; - SynchronizationContext previousSyncCtx = currentThread0._synchronizationContext; + ExecutionContext? previousExecutionCtx = previousExecutionCtx0; + SynchronizationContext? previousSyncCtx = currentThread0._synchronizationContext; try { - stateMachine.MoveNext(); + stateMachine!.MoveNext(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } finally { // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack - SynchronizationContext previousSyncCtx1 = previousSyncCtx; + SynchronizationContext? previousSyncCtx1 = previousSyncCtx; Thread currentThread1 = currentThread; // The common case is that these have not changed, so avoid the cost of a write barrier if not needed. if (previousSyncCtx1 != currentThread1._synchronizationContext) @@ -1037,8 +1038,8 @@ public static void Start(ref TStateMachine stateMachine) where TS currentThread1._synchronizationContext = previousSyncCtx1; } - ExecutionContext previousExecutionCtx1 = previousExecutionCtx; - ExecutionContext currentExecutionCtx1 = currentThread1._executionContext; + ExecutionContext? previousExecutionCtx1 = previousExecutionCtx; + ExecutionContext? currentExecutionCtx1 = currentThread1._executionContext; if (previousExecutionCtx1 != currentExecutionCtx1) { ExecutionContext.RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1); @@ -1074,7 +1075,7 @@ internal static string GetAsyncStateMachineDescription(IAsyncStateMachine stateM return sb.ToString(); } - internal static Action CreateContinuationWrapper(Action continuation, Action invokeAction, Task innerTask) => + internal static Action CreateContinuationWrapper(Action continuation, Action invokeAction, Task innerTask) => new ContinuationWrapper(continuation, invokeAction, innerTask).Invoke; /// This helper routine is targeted by the debugger. Its purpose is to remove any delegate wrappers introduced by @@ -1084,14 +1085,14 @@ internal static Action CreateContinuationWrapper(Action continuation, Action + internal static Task? TryGetContinuationTask(Action continuation) => (continuation?.Target as ContinuationWrapper)?._innerTask; /// @@ -1111,11 +1112,12 @@ private sealed class ContinuationWrapper // SOS DumpAsync command depends on thi internal ContinuationWrapper(Action continuation, Action invokeAction, Task innerTask) { Debug.Assert(continuation != null, "Expected non-null continuation"); - Debug.Assert(invokeAction != null, "Expected non-null continuation"); + Debug.Assert(invokeAction != null, "Expected non-null invokeAction"); + Debug.Assert(innerTask != null, "Expected non-null innerTask"); _invokeAction = invokeAction; _continuation = continuation; - _innerTask = innerTask ?? TryGetContinuationTask(continuation); // if we don't have a task, see if our continuation is a wrapper and use that. + _innerTask = innerTask; } internal void Invoke() => _invokeAction(_continuation, _innerTask); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs index 688a3a01ba72..b8d9a37407b2 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { /// diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs index 66c9175ee75a..74bd1bdde236 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs index 7ae8015326f1..7560e0fadf67 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncValueTaskMethodBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; using System.Security; using System.Threading.Tasks; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs index 6e1c4c56cd05..1bf9fd7cd896 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerFilePathAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerFilePathAttribute.cs index 5858634b4274..74782adf80b1 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerFilePathAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerFilePathAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs index 5bd2fcb91b94..f92ad55ef894 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs index 8b046335b5a4..646036fc9cc8 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxations.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxations.cs index 88e2657a6ac1..422b82bd94f1 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxations.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxations.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { /// IMPORTANT: Keep this in sync with corhdr.h @@ -12,4 +13,4 @@ public enum CompilationRelaxations : int // so we'll start here just in case somebody used them. This flag is only // valid when set for Assemblies. } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxationsAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxationsAttribute.cs index d6da23fdf2a7..71ccbd095255 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxationsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilationRelaxationsAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Method)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs index 1c05abd1fec4..d09282f53650 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.All, Inherited = true)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs index 752295e87626..815d5f838b62 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { // Attribute used to communicate to the VS7 debugger that a class should be treated as if it has global scope. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConditionalWeakTable.cs index a7ea972b4113..4594e2d77c16 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConditionalWeakTable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConditionalWeakTable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -11,8 +12,8 @@ namespace System.Runtime.CompilerServices { public sealed class ConditionalWeakTable : IEnumerable> - where TKey : class - where TValue : class + where TKey : class? + where TValue : class? { // Lifetimes of keys and values: // Inserting a key and value into the dictonary will not @@ -264,7 +265,7 @@ private sealed class Enumerator : IEnumerator> // This, however, would cause the enumerator's understanding of indices to break. So, as long as // there is any outstanding enumerator, no compaction is performed. - private ConditionalWeakTable _table; // parent table, set to null when disposed + private ConditionalWeakTable? _table; // parent table, set to null when disposed private readonly int _maxIndexInclusive; // last index in the container that should be enumerated private int _currentIndex = -1; // the current index into the container private KeyValuePair _current; // the current entry set by MoveNext and returned from Current @@ -295,7 +296,7 @@ public void Dispose() { // Use an interlocked operation to ensure that only one thread can get access to // the _table for disposal and thus only decrement the ref count once. - ConditionalWeakTable table = Interlocked.Exchange(ref _table, null); + ConditionalWeakTable? table = Interlocked.Exchange(ref _table, null); if (table != null) { // Ensure we don't keep the last current alive unnecessarily @@ -316,7 +317,7 @@ public void Dispose() public bool MoveNext() { // Start by getting the current table. If it's already been disposed, it will be null. - ConditionalWeakTable table = _table; + ConditionalWeakTable? table = _table; if (table != null) { // Once have the table, we need to lock to synchronize with other operations on @@ -362,7 +363,7 @@ public KeyValuePair Current } } - object IEnumerator.Current => Current; + object? IEnumerator.Current => Current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 public void Reset() { } } @@ -437,7 +438,7 @@ private sealed class Container private int _firstFreeEntry; // _firstFreeEntry < _entries.Length => table has capacity, entries grow from the bottom of the table. private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock. private bool _finalized; // set to true when initially finalized - private volatile object _oldKeepAlive; // used to ensure the next allocated container isn't finalized until this one is GC'd + private volatile object? _oldKeepAlive; // used to ensure the next allocated container isn't finalized until this one is GC'd internal Container(ConditionalWeakTable parent) { @@ -480,6 +481,7 @@ private Container(ConditionalWeakTable parent, int[] buckets, Entr /// Worker for adding a new key/value pair. Container must NOT be full. internal void CreateEntryNoResize(TKey key, TValue value) { + Debug.Assert(key != null); // key already validated as non-null and not already in table. Debug.Assert(HasCapacity); VerifyIntegrity(); @@ -505,7 +507,7 @@ internal bool TryGetValueWorker(TKey key, out TValue value) { Debug.Assert(key != null); // Key already validated as non-null - int entryIndex = FindEntry(key, out object secondary); + int entryIndex = FindEntry(key, out object? secondary); value = Unsafe.As(secondary); return entryIndex != -1; } @@ -514,7 +516,7 @@ internal bool TryGetValueWorker(TKey key, out TValue value) /// Returns -1 if not found (if key expires during FindEntry, this can be treated as "not found."). /// Must hold _lock, or be prepared to retry the search while holding _lock. /// - internal int FindEntry(TKey key, out object value) + internal int FindEntry(TKey key, out object? value) { Debug.Assert(key != null); // Key already validated as non-null. @@ -539,7 +541,7 @@ internal bool TryGetEntry(int index, out TKey key, out TValue value) { if (index < _entries.Length) { - object oKey = _entries[index].depHnd.GetPrimaryAndSecondary(out object oValue); + object? oKey = _entries[index].depHnd.GetPrimaryAndSecondary(out object? oValue); GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. if (oKey != null) @@ -550,8 +552,8 @@ internal bool TryGetEntry(int index, out TKey key, out TValue value) } } - key = default; - value = default; + key = default!; // TODO-NULLABLE-GENERIC + value = default!; // TODO-NULLABLE-GENERIC return false; } @@ -724,7 +726,7 @@ internal Container Resize(int newSize) // the old container to the new container, and also ensure that the new container isn't finalized // while the old container may still be in use. As such, we store a reference from the old container // to the new one, which will keep the new container alive as long as the old one is. - var newContainer = new Container(_parent, newBuckets, newEntries, newEntriesIndex); + var newContainer = new Container(_parent!, newBuckets, newEntries, newEntriesIndex); if (activeEnumerators) { // If there are active enumerators, both the old container and the new container may be storing @@ -750,11 +752,9 @@ private void VerifyIntegrity() ~Container() { - // We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD, - // don't bother. (Despite its name, Environment.HasShutdownStart also returns true if the current - // AD is finalizing.) We also skip doing anything if the container is invalid, including if someone + // Skip doing anything if the container is invalid, including if somehow // the container object was allocated but its associated table never set. - if (Environment.HasShutdownStarted || _invalid || _parent is null) + if (_invalid || _parent is null) { return; } @@ -773,7 +773,7 @@ private void VerifyIntegrity() { if (_parent._container == this) { - _parent._container = null; + _parent._container = null!; } } GC.ReRegisterForFinalize(this); // next time it's finalized, we'll be sure there are no remaining refs @@ -782,8 +782,8 @@ private void VerifyIntegrity() Entry[] entries = _entries; _invalid = true; - _entries = null; - _buckets = null; + _entries = null!; + _buckets = null!; if (entries != null) { diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs index aa5e882dc654..b5e5b9a38a15 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace System.Runtime.CompilerServices diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredCancelableAsyncEnumerable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredCancelableAsyncEnumerable.cs index 4f1bca71695e..c8d2cb29ea60 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredCancelableAsyncEnumerable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredCancelableAsyncEnumerable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs index 20119685a99e..dedc16f98b84 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; @@ -57,7 +58,7 @@ public bool IsCompleted /// Schedules the continuation action for the . public void OnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -79,7 +80,7 @@ public void OnCompleted(Action continuation) /// Schedules the continuation action for the . public void UnsafeOnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -99,7 +100,7 @@ public void UnsafeOnCompleted(Action continuation) void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -163,7 +164,7 @@ public bool IsCompleted /// Schedules the continuation action for the . public void OnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -185,7 +186,7 @@ public void OnCompleted(Action continuation) /// Schedules the continuation action for the . public void UnsafeOnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -205,7 +206,7 @@ public void UnsafeOnCompleted(Action continuation) void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ContractHelper.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ContractHelper.cs index 362fe6f78d6c..f3104621eaa3 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ContractHelper.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ContractHelper.cs @@ -4,7 +4,7 @@ #define DEBUG // The behavior of this contract library should be consistent regardless of build type. -using System.Diagnostics; +#nullable enable using System.Diagnostics.Contracts; namespace System.Runtime.CompilerServices @@ -31,14 +31,14 @@ public static class ContractHelper /// Otherwise, returns the localized failure message. /// [System.Diagnostics.DebuggerNonUserCode] - public static string RaiseContractFailedEvent(ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException) + public static string? RaiseContractFailedEvent(ContractFailureKind failureKind, string? userMessage, string? conditionText, Exception? innerException) { if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume) throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, failureKind), nameof(failureKind)); - string returnValue; + string? returnValue; string displayMessage = "contract failed."; // Incomplete, but in case of OOM during resource lookup... - ContractFailedEventArgs eventArgs = null; // In case of OOM. + ContractFailedEventArgs? eventArgs = null; // In case of OOM. try { @@ -78,6 +78,7 @@ public static string RaiseContractFailedEvent(ContractFailureKind failureKind, s returnValue = displayMessage; } } + return returnValue; } @@ -85,7 +86,7 @@ public static string RaiseContractFailedEvent(ContractFailureKind failureKind, s /// Rewriter calls this method to get the default failure behavior. /// [System.Diagnostics.DebuggerNonUserCode] - public static void TriggerFailure(ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, Exception innerException) + public static void TriggerFailure(ContractFailureKind kind, string? displayMessage, string? userMessage, string? conditionText, Exception? innerException) { if (string.IsNullOrEmpty(displayMessage)) { @@ -95,7 +96,7 @@ public static void TriggerFailure(ContractFailureKind kind, string displayMessag System.Diagnostics.Debug.ContractFailure(displayMessage, string.Empty, GetFailureMessage(kind, null)); } - private static string GetFailureMessage(ContractFailureKind failureKind, string conditionText) + private static string GetFailureMessage(ContractFailureKind failureKind, string? conditionText) { bool hasConditionText = !string.IsNullOrEmpty(conditionText); switch (failureKind) @@ -124,7 +125,7 @@ private static string GetFailureMessage(ContractFailureKind failureKind, string } } - private static string GetDisplayMessage(ContractFailureKind failureKind, string userMessage, string conditionText) + private static string GetDisplayMessage(ContractFailureKind failureKind, string? userMessage, string? conditionText) { string failureMessage; // Well-formatted English messages will take one of four forms. A sentence ending in diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs index d3116cc8ad85..23c82aed9ddc 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] public abstract class CustomConstantAttribute : Attribute { - public abstract object Value { get; } + public abstract object? Value { get; } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs index 44c497706e30..8c3179887b96 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] @@ -14,6 +15,6 @@ public DateTimeConstantAttribute(long ticks) _date = new DateTime(ticks); } - public override object Value => _date; + public override object? Value => _date; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs index 521a3abe9cb6..2f900f4220b3 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs @@ -4,6 +4,7 @@ // Note: If you add a new ctor overloads you need to update ParameterInfo.RawDefaultValue +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DefaultDependencyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DefaultDependencyAttribute.cs index 4c1f48921583..b225396b1338 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DefaultDependencyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DefaultDependencyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly)] @@ -14,4 +15,4 @@ public DefaultDependencyAttribute(LoadHint loadHintArgument) public LoadHint LoadHint { get; } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs index 7bb7acec4171..b2e27f2d6c13 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] @@ -16,4 +17,4 @@ public DependencyAttribute(string dependentAssemblyArgument, LoadHint loadHintAr public string DependentAssembly { get; } public LoadHint LoadHint { get; } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs index 4fc00e10edeb..8c56b80f1cfd 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DiscardableAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DiscardableAttribute.cs index c88b3a7599e9..861305e23b67 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DiscardableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DiscardableAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { // Custom attribute to indicating a TypeDef is a discardable attribute. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ExtensionAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ExtensionAttribute.cs index 92170880f1da..7dfec4a409a3 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ExtensionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ExtensionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; namespace System.Runtime.CompilerServices diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs index 8dc6c43126e9..ae70dc667e46 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Field)] @@ -9,4 +10,4 @@ public sealed class FixedAddressValueTypeAttribute : Attribute { public FixedAddressValueTypeAttribute() { } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedBufferAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedBufferAttribute.cs index bb8f00f68635..b98195a1f4eb 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedBufferAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FixedBufferAttribute.cs @@ -13,8 +13,7 @@ ** ===========================================================*/ -using System; - +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Field, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FormattableStringFactory.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FormattableStringFactory.cs index 23d03860ed96..3e17cd0d4f8b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FormattableStringFactory.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/FormattableStringFactory.cs @@ -11,6 +11,7 @@ ** ===========================================================*/ +#nullable enable namespace System.Runtime.CompilerServices { /// @@ -22,7 +23,7 @@ public static class FormattableStringFactory /// Create a from a composite format string and object /// array containing zero or more objects to format. /// - public static FormattableString Create(string format, params object[] arguments) + public static FormattableString Create(string format, params object?[] arguments) { if (format == null) { @@ -40,19 +41,19 @@ public static FormattableString Create(string format, params object[] arguments) private sealed class ConcreteFormattableString : FormattableString { private readonly string _format; - private readonly object[] _arguments; + private readonly object?[] _arguments; - internal ConcreteFormattableString(string format, object[] arguments) + internal ConcreteFormattableString(string format, object?[] arguments) { _format = format; _arguments = arguments; } public override string Format { get { return _format; } } - public override object[] GetArguments() { return _arguments; } + public override object?[] GetArguments() { return _arguments; } public override int ArgumentCount { get { return _arguments.Length; } } - public override object GetArgument(int index) { return _arguments[index]; } - public override string ToString(IFormatProvider formatProvider) { return string.Format(formatProvider, _format, _arguments); } + public override object? GetArgument(int index) { return _arguments[index]; } + public override string ToString(IFormatProvider? formatProvider) { return string.Format(formatProvider, _format, _arguments); } } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IAsyncStateMachine.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IAsyncStateMachine.cs index 7fb7ea539529..8d5d0dad47d1 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IAsyncStateMachine.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IAsyncStateMachine.cs @@ -10,6 +10,7 @@ // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +#nullable enable namespace System.Runtime.CompilerServices { /// diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs index 37e77358ad7a..3eabbc523af0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Runtime.CompilerServices { /// @@ -33,7 +32,7 @@ public interface ICastable // because this is the only guard placed before an interface invocation at runtime. If a type decides // it no longer wants to implement a given interface it has no way to synchronize with callers that // have already cached this relationship and can invoke directly via the interface pointer. - bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception castError); + bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception? castError); // This is called as part of the interface dispatch mechanism when the dispatcher logic cannot find // the given interface type in the interface map of this object. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/INotifyCompletion.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/INotifyCompletion.cs index aba0a0691f18..d1a64931f710 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/INotifyCompletion.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/INotifyCompletion.cs @@ -9,9 +9,7 @@ // Interfaces used to represent instances that notify listeners of their completion via continuations. // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -using System; -using System.Security; - +#nullable enable namespace System.Runtime.CompilerServices { /// diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ITuple.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ITuple.cs index cafee11f8a55..c78b65aa43f2 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ITuple.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ITuple.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { /// @@ -17,6 +18,6 @@ public interface ITuple /// /// Get the element at position . /// - object this[int index] { get; } + object? this[int index] { get; } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs index bc76250adc82..b4090e7e1505 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Property, Inherited = true)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs index f754694815b9..35fa95066761 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs index 6bdd91d84487..9c76c65693d6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { // Calls to methods or references to fields marked with this attribute may be replaced at diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsByRefLikeAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsByRefLikeAttribute.cs index 90e49d2a4252..a5e7760feea0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsByRefLikeAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsByRefLikeAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; namespace System.Runtime.CompilerServices diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsConst.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsConst.cs index 7f948b608a14..036df6f4476c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsConst.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsConst.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { public static partial class IsConst diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsReadOnlyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsReadOnlyAttribute.cs index 657df43957f5..186086c9f240 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsReadOnlyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsReadOnlyAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; namespace System.Runtime.CompilerServices diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsVolatile.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsVolatile.cs index fd1c6a1b12b2..a83cd2d0a10a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsVolatile.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IsVolatile.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { public static class IsVolatile diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs index 53afc9566438..f74c6bc54f78 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/LoadHint.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/LoadHint.cs index 3820f8544b90..e924f57da724 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/LoadHint.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/LoadHint.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { public enum LoadHint @@ -10,4 +11,4 @@ public enum LoadHint Always = 0x0001, // Dependency is always loaded Sometimes = 0x0002, // Dependency is sometimes loaded } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodCodeType.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodCodeType.cs index 841b6661989d..fa5d7aaf641d 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodCodeType.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodCodeType.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; namespace System.Runtime.CompilerServices diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs index 8e8f93c268de..405ade1203f5 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { // Custom attribute to specify additional method properties. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplOptions.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplOptions.cs index b50ae094ce04..20d0b52e8d76 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplOptions.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/MethodImplOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { // This Enum matchs the miImpl flags defined in corhdr.h. It is used to specify @@ -19,4 +20,4 @@ public enum MethodImplOptions AggressiveOptimization = 0x0200, InternalCall = 0x1000 } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs index 6c6fe9e258c8..d8cf02be5b7e 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs @@ -13,6 +13,7 @@ ** ============================================================*/ +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] @@ -22,11 +23,11 @@ public ReferenceAssemblyAttribute() { } - public ReferenceAssemblyAttribute(string description) + public ReferenceAssemblyAttribute(string? description) { Description = description; } - public string Description { get; } + public string? Description { get; } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs index 609c5603300d..f0844a001e92 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs @@ -11,6 +11,7 @@ ** =============================================================================*/ +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs index b0cd9ddce26b..7e8b2d0cd40b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { public static partial class RuntimeFeature diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs index fcb69eceecef..2ec8b760bdb6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -2,33 +2,52 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.Serialization; +using Internal.Runtime.CompilerServices; namespace System.Runtime.CompilerServices { public static partial class RuntimeHelpers { - public delegate void TryCode(object userData); + public delegate void TryCode(object? userData); - public delegate void CleanupCode(object userData, bool exceptionThrown); + public delegate void CleanupCode(object? userData, bool exceptionThrown); /// - /// GetSubArray helper method for the compiler to slice an array using a range. + /// Slices the specified array using the specified range. /// public static T[] GetSubArray(T[] array, Range range) { - Type elementType = array.GetType().GetElementType(); - Span source = array.AsSpan(range); + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + (int offset, int length) = range.GetOffsetAndLength(array!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 - if (elementType.IsValueType) + if (default(T)! != null || typeof(T[]) == array.GetType()) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { - return source.ToArray(); + // We know the type of the array to be exactly T[]. + + if (length == 0) + { + return Array.Empty(); + } + + var dest = new T[length]; + Buffer.Memmove( + ref Unsafe.As(ref dest.GetRawSzArrayData()), + ref Unsafe.Add(ref Unsafe.As(ref array.GetRawSzArrayData()), offset), + (uint)length); + return dest; } else { - T[] newArray = (T[])Array.CreateInstance(elementType, source.Length); - source.CopyTo(newArray); - return newArray; + // The array is actually a U[] where U:T. + T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length); + Array.Copy(array, offset, dest, 0, length); + return dest; } } @@ -38,7 +57,7 @@ public static object GetUninitializedObject(Type type) { throw new ArgumentNullException(nameof(type), SR.ArgumentNull_Type); } - + if (!type.IsRuntimeImplemented()) { throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type.ToString())); @@ -63,4 +82,4 @@ public static void PrepareConstrainedRegionsNoOP() { } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs index 6af2b280b3a1..863de0705d9c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeWrappedException.cs @@ -28,7 +28,7 @@ public RuntimeWrappedException(object thrownObject) private RuntimeWrappedException(SerializationInfo info, StreamingContext context) : base(info, context) { - _wrappedException = info.GetValue("WrappedException", typeof(object)); + _wrappedException = info.GetValue("WrappedException", typeof(object))!; } public override void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SpecialNameAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SpecialNameAttribute.cs index b18e62895fdf..a4246c2b697f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SpecialNameAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SpecialNameAttribute.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System.Runtime.CompilerServices +#nullable enable +namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Struct)] public sealed class SpecialNameAttribute : Attribute diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StateMachineAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StateMachineAttribute.cs index e081d63e71f2..3f6400926a7d 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StateMachineAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StateMachineAttribute.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StringFreezingAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StringFreezingAttribute.cs index 25a8bfbc2647..473252a86352 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StringFreezingAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StringFreezingAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { // Custom attribute to indicate that strings should be frozen. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StrongBox.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StrongBox.cs index 0a1a565f545e..e17f338952c0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StrongBox.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/StrongBox.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { /// @@ -15,7 +16,7 @@ public class StrongBox : IStrongBox /// This is explicitly exposed as a field instead of a property to enable loading the address of the field. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")] - public T Value; + public T Value = default!; // TODO-NULLABLE-GENERIC /// /// Initializes a new StrongBox which can receive a value when used in a reference call. @@ -33,7 +34,7 @@ public StrongBox(T value) Value = value; } - object IStrongBox.Value + object? IStrongBox.Value { get { @@ -41,7 +42,7 @@ object IStrongBox.Value } set { - Value = (T)value; + Value = (T)value!; // TODO-NULLABLE-GENERIC } } } @@ -54,6 +55,6 @@ public interface IStrongBox /// /// Gets or sets the value the object references. /// - object Value { get; set; } + object? Value { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs index b4224b1c89a4..04054d10a8cb 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs index f4e57728667a..9124c6b8fbdf 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs @@ -37,6 +37,7 @@ // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +#nullable enable using System.Diagnostics; using System.Diagnostics.Tracing; using System.Threading; @@ -187,7 +188,7 @@ private static void ThrowForNonSuccess(Task task) else { Debug.Fail("There should be exceptions if we're Faulted."); - throw task.Exception; + throw task.Exception!; } } } @@ -261,7 +262,7 @@ private static Action OutputWaitEtwEvents(Task task, Action continuation) // If this task's continuation is another task, get it. var continuationTask = AsyncMethodBuilderCore.TryGetContinuationTask(continuation); log.TaskWaitBegin( - (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id), + (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler!.Id : TaskScheduler.Default.Id), (currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0), task.Id, TplEventSource.TaskWaitBehavior.Asynchronous, (continuationTask != null ? continuationTask.Id : 0)); @@ -288,7 +289,7 @@ private static Action OutputWaitEtwEvents(Task task, Action continuation) { var currentTaskAtEnd = Task.InternalCurrent; innerEtwLog.TaskWaitEnd( - (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler.Id : TaskScheduler.Default.Id), + (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler!.Id : TaskScheduler.Default.Id), (currentTaskAtEnd != null ? currentTaskAtEnd.Id : 0), innerTask.Id); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs index ad923dfae50f..24d114d06901 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; namespace System.Runtime.CompilerServices @@ -13,7 +14,7 @@ namespace System.Runtime.CompilerServices [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Event)] public sealed class TupleElementNamesAttribute : Attribute { - private readonly string[] _transformNames; + private readonly string?[] _transformNames; /// /// Initializes a new instance of the transformNames value of { "name1", "name2", null, null, /// null }. /// - public TupleElementNamesAttribute(string[] transformNames) + public TupleElementNamesAttribute(string?[] transformNames) { if (transformNames == null) { @@ -52,6 +53,6 @@ public TupleElementNamesAttribute(string[] transformNames) /// construction, which elements are /// meant to carry element names. /// - public IList TransformNames => _transformNames; + public IList TransformNames => _transformNames; } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs index 27dd64575578..401b02141f8a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs index 85d5c030c19b..64107099dabc 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs index f049c89b3f3e..ada7f0569867 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Struct)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs index a56911f6d00a..62860bd70e73 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Threading; using System.Threading.Tasks; @@ -17,7 +18,7 @@ namespace System.Runtime.CompilerServices public readonly struct ValueTaskAwaiter : ICriticalNotifyCompletion, IStateMachineBoxAwareAwaiter { /// Shim used to invoke an passed as the state argument to a . - internal static readonly Action s_invokeActionDelegate = state => + internal static readonly Action s_invokeActionDelegate = state => { if (!(state is Action action)) { @@ -50,7 +51,7 @@ public bool IsCompleted /// Schedules the continuation action for this ValueTask. public void OnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -70,7 +71,7 @@ public void OnCompleted(Action continuation) /// Schedules the continuation action for this ValueTask. public void UnsafeOnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -89,7 +90,7 @@ public void UnsafeOnCompleted(Action continuation) void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -133,7 +134,7 @@ public bool IsCompleted /// Schedules the continuation action for this ValueTask. public void OnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -153,7 +154,7 @@ public void OnCompleted(Action continuation) /// Schedules the continuation action for this ValueTask. public void UnsafeOnCompleted(Action continuation) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) @@ -172,7 +173,7 @@ public void UnsafeOnCompleted(Action continuation) void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box) { - object obj = _value._obj; + object? obj = _value._obj; Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource); if (obj is Task t) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs index a8e87481ce70..b7f7779a8099 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs @@ -21,8 +21,7 @@ // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -using System; -using System.Security; +#nullable enable using System.Diagnostics; using System.Diagnostics.Tracing; using System.Threading; @@ -129,10 +128,10 @@ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox b // Otherwise, this is the same logic as in QueueContinuation, except using // an IAsyncStateMachineBox instead of an Action, and only for flowContext:false. - SynchronizationContext syncCtx = SynchronizationContext.Current; + SynchronizationContext? syncCtx = SynchronizationContext.Current; if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext)) { - syncCtx.Post(s => ((IAsyncStateMachineBox)s).MoveNext(), box); + syncCtx.Post(s => ((IAsyncStateMachineBox)s!).MoveNext(), box); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } else { @@ -143,7 +142,7 @@ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox b } else { - Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler); + Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s!).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } } @@ -155,7 +154,7 @@ private static Action OutputCorrelationEtwEvent(Action continuation) return continuation; #else int continuationId = Task.NewId(); - Task currentTask = Task.InternalCurrent; + Task? currentTask = Task.InternalCurrent; // fire the correlation ETW event TplEventSource.Log.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, (currentTask != null) ? currentTask.Id : 0, continuationId); @@ -188,7 +187,7 @@ private static Action OutputCorrelationEtwEvent(Action continuation) private static readonly SendOrPostCallback s_sendOrPostCallbackRunAction = RunAction; /// Runs an Action delegate provided as state. /// The Action delegate to invoke. - private static void RunAction(object state) { ((Action)state)(); } + private static void RunAction(object? state) { ((Action)state!)(); } /// Ends the await operation. public void GetResult() { } // Nop. It exists purely because the compiler pattern demands it. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs index 3f35f816a304..60b36ad966fe 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs @@ -12,6 +12,7 @@ ** ===========================================================*/ +#nullable enable namespace System.Runtime.ConstrainedExecution { public abstract class CriticalFinalizerObject diff --git a/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/ReliabilityContractAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/ReliabilityContractAttribute.cs index b3cb0143fa0f..59ef5da2b98c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/ReliabilityContractAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/ReliabilityContractAttribute.cs @@ -16,6 +16,7 @@ ** ===========================================================*/ +#nullable enable namespace System.Runtime.ConstrainedExecution { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Interface /* | AttributeTargets.Delegate*/, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs index cc1bc81e5a65..61a4de616d1e 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/ExceptionServices/HandleProcessCorruptedStateExceptionsAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.ExceptionServices { // This attribute can be applied to methods to indicate that ProcessCorruptedState diff --git a/src/System.Private.CoreLib/shared/System/Runtime/GCSettings.cs b/src/System.Private.CoreLib/shared/System/Runtime/GCSettings.cs index 86d10f4b5345..cb25a1efe932 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/GCSettings.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/GCSettings.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Runtime diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/AllowReversePInvokeCallsAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/AllowReversePInvokeCallsAttribute.cs index cb640a7a8c85..55d9ec0347a6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/AllowReversePInvokeCallsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/AllowReversePInvokeCallsAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { // To be used on methods that sink reverse P/Invoke calls. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs index 4ebee1538ca4..eea085208d00 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/BestFitMappingAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ClassInterfaceAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ClassInterfaceAttribute.cs index 59d79ff44383..7bb699e8537a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ClassInterfaceAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ClassInterfaceAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/CoClassAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/CoClassAttribute.cs index 4be6622c3da5..ccf5a928658c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/CoClassAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/CoClassAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Interface, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComDefaultInterfaceAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComDefaultInterfaceAttribute.cs index 1b84f5f561a3..af980c2bcc22 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComDefaultInterfaceAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComDefaultInterfaceAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Class, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComEventInterfaceAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComEventInterfaceAttribute.cs index d4ccc702e05e..01cddd63239d 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComEventInterfaceAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComEventInterfaceAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Interface, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComImportAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComImportAttribute.cs index a290bf4510d2..66663237b4ce 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComImportAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComImportAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComSourceInterfacesAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComSourceInterfacesAttribute.cs index bb264e83910f..b5ea55c2813e 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComSourceInterfacesAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComSourceInterfacesAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Class, Inherited = true)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IBindCtx.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IBindCtx.cs index a535b94f88f3..f662c639fff0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IBindCtx.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IBindCtx.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [StructLayout(LayoutKind.Sequential)] @@ -23,10 +24,10 @@ public interface IBindCtx void ReleaseBoundObjects(); void SetBindOptions([In()] ref BIND_OPTS pbindopts); void GetBindOptions(ref BIND_OPTS pbindopts); - void GetRunningObjectTable(out IRunningObjectTable pprot); + void GetRunningObjectTable(out IRunningObjectTable? pprot); void RegisterObjectParam([MarshalAs(UnmanagedType.LPWStr)] string pszKey, [MarshalAs(UnmanagedType.Interface)] object punk); - void GetObjectParam([MarshalAs(UnmanagedType.LPWStr)] string pszKey, [MarshalAs(UnmanagedType.Interface)] out object ppunk); - void EnumObjectParam(out IEnumString ppenum); + void GetObjectParam([MarshalAs(UnmanagedType.LPWStr)] string pszKey, [MarshalAs(UnmanagedType.Interface)] out object? ppunk); + void EnumObjectParam(out IEnumString? ppenum); [PreserveSig] int RevokeObjectParam([MarshalAs(UnmanagedType.LPWStr)] string pszKey); } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs index b2ce1928a138..ab5cf2e3990b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("B196B286-BAB4-101A-B69C-00AA00341D07")] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs index 84c590d4365b..9203b6780490 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("B196B284-BAB4-101A-B69C-00AA00341D07")] @@ -10,6 +11,6 @@ namespace System.Runtime.InteropServices.ComTypes public interface IConnectionPointContainer { void EnumConnectionPoints(out IEnumConnectionPoints ppEnum); - void FindConnectionPoint([In] ref Guid riid, out IConnectionPoint ppCP); + void FindConnectionPoint([In] ref Guid riid, out IConnectionPoint? ppCP); } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs index 99df6ac60e44..8536c0f60704 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("B196B285-BAB4-101A-B69C-00AA00341D07")] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs index 951685beff7e..6220c9bb2c6a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs index 9a63ba0a11a3..514cb9489b77 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("00000102-0000-0000-C000-000000000046")] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumString.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumString.cs index 57fc59121f00..ff050d419c63 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumString.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumString.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("00000101-0000-0000-C000-000000000046")] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs index 8440c060bb53..6b970b886e2b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("00020404-0000-0000-C000-000000000046")] @@ -10,7 +11,7 @@ namespace System.Runtime.InteropServices.ComTypes public interface IEnumVARIANT { [PreserveSig] - int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] object[] rgVar, IntPtr pceltFetched); + int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] object?[] rgVar, IntPtr pceltFetched); [PreserveSig] int Skip(int celt); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IMoniker.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IMoniker.cs index 7a2dd57d163b..49cbe0577df1 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IMoniker.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IMoniker.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [StructLayout(LayoutKind.Sequential)] @@ -27,21 +28,21 @@ public interface IMoniker void GetSizeMax(out long pcbSize); // IMoniker portion - void BindToObject(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riidResult, [MarshalAs(UnmanagedType.Interface)] out object ppvResult); - void BindToStorage(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObj); - void Reduce(IBindCtx pbc, int dwReduceHowFar, ref IMoniker ppmkToLeft, out IMoniker ppmkReduced); - void ComposeWith(IMoniker pmkRight, [MarshalAs(UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out IMoniker ppmkComposite); - void Enum([MarshalAs(UnmanagedType.Bool)] bool fForward, out IEnumMoniker ppenumMoniker); + void BindToObject(IBindCtx pbc, IMoniker? pmkToLeft, [In()] ref Guid riidResult, [MarshalAs(UnmanagedType.Interface)] out object ppvResult); + void BindToStorage(IBindCtx pbc, IMoniker? pmkToLeft, [In()] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObj); + void Reduce(IBindCtx pbc, int dwReduceHowFar, ref IMoniker? ppmkToLeft, out IMoniker? ppmkReduced); + void ComposeWith(IMoniker pmkRight, [MarshalAs(UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out IMoniker? ppmkComposite); + void Enum([MarshalAs(UnmanagedType.Bool)] bool fForward, out IEnumMoniker? ppenumMoniker); [PreserveSig] int IsEqual(IMoniker pmkOtherMoniker); void Hash(out int pdwHash); [PreserveSig] - int IsRunning(IBindCtx pbc, IMoniker pmkToLeft, IMoniker pmkNewlyRunning); - void GetTimeOfLastChange(IBindCtx pbc, IMoniker pmkToLeft, out FILETIME pFileTime); + int IsRunning(IBindCtx pbc, IMoniker? pmkToLeft, IMoniker? pmkNewlyRunning); + void GetTimeOfLastChange(IBindCtx pbc, IMoniker? pmkToLeft, out FILETIME pFileTime); void Inverse(out IMoniker ppmk); - void CommonPrefixWith(IMoniker pmkOther, out IMoniker ppmkPrefix); - void RelativePathTo(IMoniker pmkOther, out IMoniker ppmkRelPath); - void GetDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDisplayName); + void CommonPrefixWith(IMoniker pmkOther, out IMoniker? ppmkPrefix); + void RelativePathTo(IMoniker pmkOther, out IMoniker? ppmkRelPath); + void GetDisplayName(IBindCtx pbc, IMoniker? pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] out string ppszDisplayName); void ParseDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, out int pchEaten, out IMoniker ppmkOut); [PreserveSig] int IsSystemMoniker(out int pdwMksys); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IPersistFile.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IPersistFile.cs index cb24d985dcdd..6fa3f80d29d1 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IPersistFile.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IPersistFile.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("0000010b-0000-0000-C000-000000000046")] @@ -16,7 +17,7 @@ public interface IPersistFile [PreserveSig] int IsDirty(); void Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, int dwMode); - void Save([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember); + void Save([MarshalAs(UnmanagedType.LPWStr)] string? pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember); void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] string pszFileName); void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out string ppszFileName); } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs index 1884fcc99b50..49078daffceb 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("00000010-0000-0000-C000-000000000046")] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IStream.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IStream.cs index 09b284041e72..d15a09faa01b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IStream.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/IStream.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeComp.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeComp.cs index 7e6379361518..aea9a8219f07 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeComp.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeComp.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { public enum DESCKIND diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs index 61776e446d5b..a48d38d092a8 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { public enum TYPEKIND @@ -290,8 +291,8 @@ public interface ITypeInfo void GetDllEntry(int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal); void GetRefTypeInfo(int hRef, out ITypeInfo ppTI); void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv); - void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out object ppvObj); - void GetMops(int memid, out string pBstrMops); + void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object? pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out object ppvObj); + void GetMops(int memid, out string? pBstrMops); void GetContainingTypeLib(out ITypeLib ppTLB, out int pIndex); [PreserveSig] void ReleaseTypeAttr(IntPtr pTypeAttr); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs index bad4f6cbbe79..e8918f52833f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("00020412-0000-0000-C000-000000000046")] @@ -22,8 +23,8 @@ public interface ITypeInfo2 : ITypeInfo new void GetDllEntry(int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal); new void GetRefTypeInfo(int hRef, out ITypeInfo ppTI); new void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv); - new void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out object ppvObj); - new void GetMops(int memid, out string pBstrMops); + new void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object? pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out object ppvObj); + new void GetMops(int memid, out string? pBstrMops); new void GetContainingTypeLib(out ITypeLib ppTLB, out int pIndex); [PreserveSig] new void ReleaseTypeAttr(IntPtr pTypeAttr); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib.cs index 6cab58e117dc..4e390c28ce56 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { public enum SYSKIND diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs index 61703d1cfe36..ba0d8f9f63f9 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.ComTypes { [Guid("00020411-0000-0000-C000-000000000046")] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComVisibleAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComVisibleAttribute.cs index 84b9505a5a47..3f9673f7ebf7 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComVisibleAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ComVisibleAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs index 7a486f7017b7..cfddfb1d78bf 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultCharSetAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Module, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs index 1ff27fbbd557..1dc184d0106f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultParameterValueAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultParameterValueAttribute.cs index 8ab7ee2e01a8..bc405bca2e29 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultParameterValueAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DefaultParameterValueAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { // @@ -13,11 +14,11 @@ namespace System.Runtime.InteropServices [AttributeUsageAttribute(AttributeTargets.Parameter)] public sealed class DefaultParameterValueAttribute : Attribute { - public DefaultParameterValueAttribute(object value) + public DefaultParameterValueAttribute(object? value) { Value = value; } - public object Value { get; } + public object? Value { get; } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DispIdAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DispIdAttribute.cs index 1f147280c5c5..e49cf7705321 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DispIdAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DispIdAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DllImportAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DllImportAttribute.cs index 97f870d49ccd..b18990bb095c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DllImportAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/DllImportAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, Inherited = false)] @@ -14,7 +15,7 @@ public DllImportAttribute(string dllName) public string Value { get; } - public string EntryPoint; + public string? EntryPoint; public CharSet CharSet; public bool SetLastError; public bool ExactSpelling; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs index 27e1097749f4..73f7c85faf8f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/FieldOffsetAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Field, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GCHandle.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GCHandle.cs index 67e8ad27d0c4..4418b3742cb6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GCHandle.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GCHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; @@ -34,7 +35,7 @@ public partial struct GCHandle private IntPtr _handle; // Allocate a handle storing the object and the type. - private GCHandle(object value, GCHandleType type) + private GCHandle(object? value, GCHandleType type) { // Make sure the type parameter is within the valid range for the enum. if ((uint)type > (uint)GCHandleType.Pinned) // IMPORTANT: This must be kept in sync with the GCHandleType enum. @@ -64,13 +65,13 @@ private GCHandle(object value, GCHandleType type) /// Creates a new GC handle for an object. /// The object that the GC handle is created for. /// A new GC handle that protects the object. - public static GCHandle Alloc(object value) => new GCHandle(value, GCHandleType.Normal); + public static GCHandle Alloc(object? value) => new GCHandle(value, GCHandleType.Normal); /// Creates a new GC handle for an object. /// The object that the GC handle is created for. /// The type of GC handle to create. /// A new GC handle that protects the object. - public static GCHandle Alloc(object value, GCHandleType type) => new GCHandle(value, type); + public static GCHandle Alloc(object? value, GCHandleType type) => new GCHandle(value, type); /// Frees a GC handle. public void Free() @@ -82,7 +83,7 @@ public void Free() } // Target property - allows getting / updating of the handle's referent. - public object Target + public object? Target { get { @@ -168,7 +169,7 @@ public static GCHandle FromIntPtr(IntPtr value) public override int GetHashCode() => _handle.GetHashCode(); - public override bool Equals(object o) => o is GCHandle && _handle == ((GCHandle)o)._handle; + public override bool Equals(object? o) => o is GCHandle && _handle == ((GCHandle)o)._handle; public static bool operator ==(GCHandle a, GCHandle b) => a._handle == b._handle; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GuidAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GuidAttribute.cs index cf60b9bf70a3..dd8f6920764c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GuidAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/GuidAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ICustomMarshaler.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ICustomMarshaler.cs index cf442d4fde1f..6a5f5d89d3bc 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ICustomMarshaler.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ICustomMarshaler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { // This the base interface that must be implemented by all custom marshalers. diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InAttribute.cs index 39f5a958bc85..f7da173ad3b8 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InterfaceTypeAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InterfaceTypeAttribute.cs index 695faa793784..3ed8321dc72f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InterfaceTypeAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/InterfaceTypeAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Interface, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/LCIDConversionAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/LCIDConversionAttribute.cs index 75f8fcfc9149..87424e11889e 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/LCIDConversionAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/LCIDConversionAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.NoCom.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.NoCom.cs index 7eda97bb1029..bab7d3454e34 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.NoCom.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.NoCom.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; using System.Runtime.InteropServices.ComTypes; @@ -9,7 +10,7 @@ namespace System.Runtime.InteropServices { public static partial class Marshal { - public static int GetHRForException(Exception e) + public static int GetHRForException(Exception? e) { return e?.HResult ?? 0; } @@ -26,7 +27,7 @@ public static IntPtr CreateAggregatedObject(IntPtr pOuter, object o) throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static Object BindToMoniker(String monikerName) + public static object BindToMoniker(string monikerName) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } @@ -37,20 +38,22 @@ public static void CleanupUnusedObjectsInCurrentContext() public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) { + // TODO-NULLABLE-GENERIC: T cannot be null throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static object CreateWrapperOfType(object o, Type t) + public static object? CreateWrapperOfType(object? o, Type t) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } public static TWrapper CreateWrapperOfType(T o) { + // TODO-NULLABLE-GENERIC: T can be null throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static void ChangeWrapperHandleStrength(Object otp, bool fIsWeak) + public static void ChangeWrapperHandleStrength(object otp, bool fIsWeak) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } @@ -72,22 +75,23 @@ public static IntPtr GetComInterfaceForObject(object o, Type T, CustomQueryInter public static IntPtr GetComInterfaceForObject(T o) { + // TODO-NULLABLE-GENERIC: T cannot be null throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static object GetComObjectData(object obj, object key) + public static object? GetComObjectData(object obj, object key) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } public static IntPtr GetHINSTANCE(Module m) { - if (m == null) + if (m is null) { throw new ArgumentNullException(nameof(m)); } - return (IntPtr) (-1); + return (IntPtr)(-1); } public static IntPtr GetIUnknownForObject(object o) @@ -95,17 +99,18 @@ public static IntPtr GetIUnknownForObject(object o) throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static void GetNativeVariantForObject(object obj, IntPtr pDstNativeVariant) + public static void GetNativeVariantForObject(object? obj, IntPtr pDstNativeVariant) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } public static void GetNativeVariantForObject(T obj, IntPtr pDstNativeVariant) { + // TODO-NULLABLE-GENERIC: T can be null throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static Object GetTypedObjectForIUnknown(IntPtr pUnk, Type t) + public static object GetTypedObjectForIUnknown(IntPtr pUnk, Type t) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } @@ -115,21 +120,23 @@ public static object GetObjectForIUnknown(IntPtr pUnk) throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static object GetObjectForNativeVariant(IntPtr pSrcNativeVariant) + public static object? GetObjectForNativeVariant(IntPtr pSrcNativeVariant) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } public static T GetObjectForNativeVariant(IntPtr pSrcNativeVariant) { + // TODO-NULLABLE-GENERIC: T can be null throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static object[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) + public static object?[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } + // TODO-NULLABLE-GENERIC: T[] contents can be null public static T[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); @@ -162,7 +169,7 @@ public static object GetUniqueObjectForIUnknown(IntPtr unknown) public static bool IsComObject(object o) { - if (o == null) + if (o is null) { throw new ArgumentNullException(nameof(o)); } @@ -172,7 +179,7 @@ public static bool IsComObject(object o) public static bool IsTypeVisibleFromCom(Type t) { - if (t == null) + if (t is null) { throw new ArgumentNullException(nameof(t)); } @@ -194,7 +201,7 @@ public static int ReleaseComObject(object o) throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } - public static bool SetComObjectData(object obj, object key, object data) + public static bool SetComObjectData(object obj, object key, object? data) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Unix.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Unix.cs index 08892b10b47c..fbcc06626554 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Text; @@ -9,22 +10,24 @@ namespace System.Runtime.InteropServices { public static partial class Marshal { - public static string PtrToStringAuto(IntPtr ptr, int len) + // TODO-NULLABLE: This has different behavior from the other PtrToString(IntPtr, int) functions + // This is due to PtrToStringUTF8 on Unix and is being resolved independently + public static string? PtrToStringAuto(IntPtr ptr, int len) { return PtrToStringUTF8(ptr, len); } - public static string PtrToStringAuto(IntPtr ptr) + public static string? PtrToStringAuto(IntPtr ptr) { return PtrToStringUTF8(ptr); } - public static IntPtr StringToHGlobalAuto(string s) + public static IntPtr StringToHGlobalAuto(string? s) { return StringToHGlobalUTF8(s); } - public static IntPtr StringToCoTaskMemAuto(string s) + public static IntPtr StringToCoTaskMemAuto(string? s) { return StringToCoTaskMemUTF8(s); } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Windows.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Windows.cs index c9e1bafcf77d..999624787e89 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.Windows.cs @@ -2,28 +2,31 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Runtime.InteropServices { public static partial class Marshal { - public static string PtrToStringAuto(IntPtr ptr, int len) + // TODO-NULLABLE: This has different behavior from the other PtrToString(IntPtr, int) functions + // This is due to PtrToStringUTF8 on Unix and is being resolved independently + public static string? PtrToStringAuto(IntPtr ptr, int len) { return PtrToStringUni(ptr, len); } - public static string PtrToStringAuto(IntPtr ptr) + public static string? PtrToStringAuto(IntPtr ptr) { return PtrToStringUni(ptr); } - public static IntPtr StringToHGlobalAuto(string s) + public static IntPtr StringToHGlobalAuto(string? s) { return StringToHGlobalUni(s); } - public static IntPtr StringToCoTaskMemAuto(string s) + public static IntPtr StringToCoTaskMemAuto(string? s) { return StringToCoTaskMemUni(s); } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.cs index 65d4b4fc6a4b..7cdab7b2aa72 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/Marshal.cs @@ -2,13 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; -using System.Diagnostics; +#nullable enable using System.Security; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; -using Microsoft.Win32; using Internal.Runtime.CompilerServices; @@ -39,7 +37,7 @@ public static partial class Marshal public static IntPtr AllocHGlobal(int cb) => AllocHGlobal((IntPtr)cb); - public static unsafe string PtrToStringAnsi(IntPtr ptr) + public static unsafe string? PtrToStringAnsi(IntPtr ptr) { if (ptr == IntPtr.Zero || IsWin32Atom(ptr)) { @@ -63,7 +61,7 @@ public static unsafe string PtrToStringAnsi(IntPtr ptr, int len) return new string((sbyte*)ptr, 0, len); } - public static unsafe string PtrToStringUni(IntPtr ptr) + public static unsafe string? PtrToStringUni(IntPtr ptr) { if (ptr == IntPtr.Zero || IsWin32Atom(ptr)) { @@ -87,7 +85,7 @@ public static unsafe string PtrToStringUni(IntPtr ptr, int len) return new string((char*)ptr, 0, len); } - public static unsafe string PtrToStringUTF8(IntPtr ptr) + public static unsafe string? PtrToStringUTF8(IntPtr ptr) { if (ptr == IntPtr.Zero || IsWin32Atom(ptr)) { @@ -98,7 +96,8 @@ public static unsafe string PtrToStringUTF8(IntPtr ptr) return string.CreateStringFromEncoding((byte*)ptr, nbBytes, Encoding.UTF8); } - public static unsafe string PtrToStringUTF8(IntPtr ptr, int byteLen) + // TODO-NULLABLE: This has different behavior from the other PtrToString(IntPtr, int) functions + public static unsafe string? PtrToStringUTF8(IntPtr ptr, int byteLen) { if (ptr == IntPtr.Zero) { @@ -114,7 +113,7 @@ public static unsafe string PtrToStringUTF8(IntPtr ptr, int byteLen) public static int SizeOf(object structure) { - if (structure == null) + if (structure is null) { throw new ArgumentNullException(nameof(structure)); } @@ -124,7 +123,7 @@ public static int SizeOf(object structure) public static int SizeOf(T structure) { - if (structure == null) + if (structure is null) { throw new ArgumentNullException(nameof(structure)); } @@ -134,7 +133,7 @@ public static int SizeOf(T structure) public static int SizeOf(Type t) { - if (t == null) + if (t is null) { throw new ArgumentNullException(nameof(t)); } @@ -159,7 +158,7 @@ public static int SizeOf(Type t) /// public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index) { - if (arr == null) + if (arr is null) throw new ArgumentNullException(nameof(arr)); void* pRawData = Unsafe.AsPointer(ref arr.GetRawArrayData()); @@ -168,7 +167,7 @@ public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index) public static unsafe IntPtr UnsafeAddrOfPinnedArrayElement(T[] arr, int index) { - if (arr == null) + if (arr is null) throw new ArgumentNullException(nameof(arr)); void* pRawData = Unsafe.AsPointer(ref arr.GetRawSzArrayData()); @@ -219,7 +218,7 @@ public static void Copy(IntPtr[] source, int startIndex, IntPtr destination, int private static unsafe void CopyToNative(T[] source, int startIndex, IntPtr destination, int length) { - if (source == null) + if (source is null) throw new ArgumentNullException(nameof(source)); if (destination == IntPtr.Zero) throw new ArgumentNullException(nameof(destination)); @@ -273,7 +272,7 @@ private static unsafe void CopyToManaged(IntPtr source, T[] destination, int { if (source == IntPtr.Zero) throw new ArgumentNullException(nameof(source)); - if (destination == null) + if (destination is null) throw new ArgumentNullException(nameof(destination)); if (startIndex < 0) throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex); @@ -509,7 +508,7 @@ public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val) public static void Prelink(MethodInfo m) { - if (m == null) + if (m is null) { throw new ArgumentNullException(nameof(m)); } @@ -519,38 +518,37 @@ public static void Prelink(MethodInfo m) public static void PrelinkAll(Type c) { - if (c == null) + if (c is null) { throw new ArgumentNullException(nameof(c)); } MethodInfo[] mi = c.GetMethods(); - if (mi != null) + + for (int i = 0; i < mi.Length; i++) { - for (int i = 0; i < mi.Length; i++) - { - Prelink(mi[i]); - } + Prelink(mi[i]); } } public static void StructureToPtr(T structure, IntPtr ptr, bool fDeleteOld) { - StructureToPtr((object)structure, ptr, fDeleteOld); + // TODO-NULLABLE-GENERIC: T cannot be null + StructureToPtr((object)structure!, ptr, fDeleteOld); } /// /// Creates a new instance of "structuretype" and marshals data from a /// native memory block to it. /// - public static object PtrToStructure(IntPtr ptr, Type structureType) + public static object? PtrToStructure(IntPtr ptr, Type structureType) { if (ptr == IntPtr.Zero) { return null; } - if (structureType == null) + if (structureType is null) { throw new ArgumentNullException(nameof(structureType)); } @@ -576,19 +574,21 @@ public static void PtrToStructure(IntPtr ptr, object structure) public static void PtrToStructure(IntPtr ptr, T structure) { - PtrToStructure(ptr, (object)structure); + // TODO-NULLABLE-GENERIC: T cannot be null + PtrToStructure(ptr, (object)structure!); } - public static T PtrToStructure(IntPtr ptr) => (T)PtrToStructure(ptr, typeof(T)); + // TODO-NULLABLE-GENERIC: T can be null + public static T PtrToStructure(IntPtr ptr) => (T)PtrToStructure(ptr, typeof(T))!; public static void DestroyStructure(IntPtr ptr) => DestroyStructure(ptr, typeof(T)); /// /// Converts the HRESULT to a CLR exception. /// - public static Exception GetExceptionForHR(int errorCode) => GetExceptionForHR(errorCode, IntPtr.Zero); + public static Exception? GetExceptionForHR(int errorCode) => GetExceptionForHR(errorCode, IntPtr.Zero); - public static Exception GetExceptionForHR(int errorCode, IntPtr errorInfo) + public static Exception? GetExceptionForHR(int errorCode, IntPtr errorInfo) { if (errorCode >= 0) { @@ -605,7 +605,7 @@ public static void ThrowExceptionForHR(int errorCode) { if (errorCode < 0) { - throw GetExceptionForHR(errorCode, IntPtr.Zero); + throw GetExceptionForHR(errorCode, IntPtr.Zero)!; } } @@ -613,13 +613,13 @@ public static void ThrowExceptionForHR(int errorCode, IntPtr errorInfo) { if (errorCode < 0) { - throw GetExceptionForHR(errorCode, errorInfo); + throw GetExceptionForHR(errorCode, errorInfo)!; } } public static IntPtr SecureStringToBSTR(SecureString s) { - if (s == null) + if (s is null) { throw new ArgumentNullException(nameof(s)); } @@ -629,7 +629,7 @@ public static IntPtr SecureStringToBSTR(SecureString s) public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s) { - if (s == null) + if (s is null) { throw new ArgumentNullException(nameof(s)); } @@ -639,7 +639,7 @@ public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s) public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s) { - if (s == null) + if (s is null) { throw new ArgumentNullException(nameof(s)); } @@ -649,7 +649,7 @@ public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s) public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s) { - if (s == null) + if (s is null) { throw new ArgumentNullException(nameof(s)); } @@ -659,7 +659,7 @@ public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s) public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s) { - if (s == null) + if (s is null) { throw new ArgumentNullException(nameof(s)); } @@ -667,9 +667,9 @@ public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s) return s.MarshalToString(globalAlloc: true, unicode: true); ; } - public static unsafe IntPtr StringToHGlobalAnsi(string s) + public static unsafe IntPtr StringToHGlobalAnsi(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -689,9 +689,9 @@ public static unsafe IntPtr StringToHGlobalAnsi(string s) return hglobal; } - public static unsafe IntPtr StringToHGlobalUni(string s) + public static unsafe IntPtr StringToHGlobalUni(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -713,9 +713,9 @@ public static unsafe IntPtr StringToHGlobalUni(string s) return hglobal; } - private static unsafe IntPtr StringToHGlobalUTF8(string s) + private static unsafe IntPtr StringToHGlobalUTF8(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -737,9 +737,9 @@ private static unsafe IntPtr StringToHGlobalUTF8(string s) return pMem; } - public static unsafe IntPtr StringToCoTaskMemUni(string s) + public static unsafe IntPtr StringToCoTaskMemUni(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -761,9 +761,9 @@ public static unsafe IntPtr StringToCoTaskMemUni(string s) return hglobal; } - public static unsafe IntPtr StringToCoTaskMemUTF8(string s) + public static unsafe IntPtr StringToCoTaskMemUTF8(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -785,9 +785,9 @@ public static unsafe IntPtr StringToCoTaskMemUTF8(string s) return pMem; } - public static unsafe IntPtr StringToCoTaskMemAnsi(string s) + public static unsafe IntPtr StringToCoTaskMemAnsi(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -814,7 +814,7 @@ public static unsafe IntPtr StringToCoTaskMemAnsi(string s) /// public static Guid GenerateGuidForType(Type type) { - if (type == null) + if (type is null) { throw new ArgumentNullException(nameof(type)); } @@ -833,7 +833,7 @@ public static Guid GenerateGuidForType(Type type) /// public static string GenerateProgIdForType(Type type) { - if (type == null) + if (type is null) { throw new ArgumentNullException(nameof(type)); } @@ -846,7 +846,7 @@ public static string GenerateProgIdForType(Type type) throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); } - ProgIdAttribute progIdAttribute = type.GetCustomAttribute(); + ProgIdAttribute? progIdAttribute = type.GetCustomAttribute(); if (progIdAttribute != null) { return progIdAttribute.Value ?? string.Empty; @@ -862,7 +862,7 @@ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) { throw new ArgumentNullException(nameof(ptr)); } - if (t == null) + if (t is null) { throw new ArgumentNullException(nameof(t)); } @@ -875,7 +875,7 @@ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t)); } - Type c = t.BaseType; + Type? c = t.BaseType; if (c != typeof(Delegate) && c != typeof(MulticastDelegate)) { throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(t)); @@ -891,7 +891,7 @@ public static TDelegate GetDelegateForFunctionPointer(IntPtr ptr) public static IntPtr GetFunctionPointerForDelegate(Delegate d) { - if (d == null) + if (d is null) { throw new ArgumentNullException(nameof(d)); } @@ -901,7 +901,8 @@ public static IntPtr GetFunctionPointerForDelegate(Delegate d) public static IntPtr GetFunctionPointerForDelegate(TDelegate d) { - return GetFunctionPointerForDelegate((Delegate)(object)d); + // TODO-NULLABLE-GENERIC: T cannot be null + return GetFunctionPointerForDelegate((Delegate)(object)d!); } public static int GetHRForLastWin32Error() diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs index 4a64050ed109..bf8bc04e4ba4 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalAsAttribute.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.ReturnValue, Inherited = false)] - public sealed class MarshalAsAttribute : Attribute + public sealed partial class MarshalAsAttribute : Attribute { public MarshalAsAttribute(UnmanagedType unmanagedType) { @@ -20,7 +21,7 @@ public MarshalAsAttribute(short unmanagedType) // Fields used with SubType = SafeArray. public VarEnum SafeArraySubType; - public Type SafeArrayUserDefinedSubType; + public Type? SafeArrayUserDefinedSubType; // Field used with iid_is attribute (interface pointers). public int IidParameterIndex; @@ -32,8 +33,8 @@ public MarshalAsAttribute(short unmanagedType) public int SizeConst; // constant C // Fields used with SubType = CustomMarshaler - public string MarshalType; // Name of marshaler class - public Type MarshalTypeRef; // Type of marshaler class - public string MarshalCookie; // cookie to pass to marshaler + public string? MarshalType; // Name of marshaler class + public Type? MarshalTypeRef; // Type of marshaler class + public string? MarshalCookie; // cookie to pass to marshaler } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs index e3cf0a84e248..e653fc6d3613 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs index 225f4343821f..0ddbdb26583b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Runtime.CompilerServices; using System.Collections.Generic; @@ -23,7 +24,7 @@ public static partial class MemoryMarshal /// public static bool TryGetArray(ReadOnlyMemory memory, out ArraySegment segment) { - object obj = memory.GetObjectStartLength(out int index, out int length); + object? obj = memory.GetObjectStartLength(out int index, out int length); // As an optimization, we skip the "is string?" check below if typeof(T) is not char, // as Memory / ROM can't possibly contain a string instance in this case. @@ -55,7 +56,7 @@ public static bool TryGetArray(ReadOnlyMemory memory, out ArraySegment Debug.Assert(obj is MemoryManager); if (Unsafe.As>(obj).TryGetArray(out ArraySegment tempArraySegment)) { - segment = new ArraySegment(tempArraySegment.Array, tempArraySegment.Offset + index, length); + segment = new ArraySegment(tempArraySegment.Array!, tempArraySegment.Offset + index, length); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return true; } } @@ -86,12 +87,12 @@ public static bool TryGetArray(ReadOnlyMemory memory, out ArraySegment /// The memory to get the manager for. /// The returned manager of the . /// A indicating if it was successful. - public static bool TryGetMemoryManager(ReadOnlyMemory memory, out TManager manager) + public static bool TryGetMemoryManager(ReadOnlyMemory memory, out TManager? manager) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 where TManager : MemoryManager { - TManager localManager; // Use register for null comparison rather than byref + TManager? localManager; // Use register for null comparison rather than byref manager = localManager = memory.GetObjectStartLength(out _, out _) as TManager; - return manager != null; + return localManager != null; } /// @@ -105,15 +106,15 @@ public static bool TryGetMemoryManager(ReadOnlyMemory memory, ou /// The offset from the start of the that the represents. /// The length of the that the represents. /// A indicating if it was successful. - public static bool TryGetMemoryManager(ReadOnlyMemory memory, out TManager manager, out int start, out int length) + public static bool TryGetMemoryManager(ReadOnlyMemory memory, out TManager? manager, out int start, out int length) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 where TManager : MemoryManager { - TManager localManager; // Use register for null comparison rather than byref + TManager? localManager; // Use register for null comparison rather than byref manager = localManager = memory.GetObjectStartLength(out start, out length) as TManager; Debug.Assert(length >= 0); - if (manager == null) + if (localManager == null) { start = default; length = default; @@ -141,7 +142,7 @@ public static IEnumerable ToEnumerable(ReadOnlyMemory memory) /// The starting location in . /// The number of items in . /// - public static bool TryGetString(ReadOnlyMemory memory, out string text, out int start, out int length) + public static bool TryGetString(ReadOnlyMemory memory, out string? text, out int start, out int length) { if (memory.GetObjectStartLength(out int offset, out int count) is string s) { @@ -298,7 +299,7 @@ public static ref readonly T AsRef(ReadOnlySpan span) /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Memory CreateFromPinnedArray(T[] array, int start, int length) + public static Memory CreateFromPinnedArray(T[]? array, int start, int length) { if (array == null) { @@ -306,7 +307,7 @@ public static Memory CreateFromPinnedArray(T[] array, int start, int lengt ThrowHelper.ThrowArgumentOutOfRangeException(); return default; } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs index bad4d7f6ad63..f6b151ebf5fb 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { /// @@ -24,6 +25,6 @@ public NativeCallableAttribute() /// /// Optional. If omitted, then the method is native callable, but no EAT is emitted. /// - public string EntryPoint; + public string? EntryPoint; } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OptionalAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OptionalAttribute.cs index 5ac75d7b3e95..93ff349c3c9a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OptionalAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OptionalAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OutAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OutAttribute.cs index 338ceac91e13..841ffb3e5b53 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OutAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/OutAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs index 464e1abcbeba..50c066bbedff 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/PreserveSigAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ProgIdAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ProgIdAttribute.cs index bc4bd18bb1b4..55476dac6cd2 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ProgIdAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ProgIdAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Class, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeHandle.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeHandle.cs index 72c8f66abf20..b0a7c02bd63a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeHandle.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.ConstrainedExecution; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs index c4cce9956e1d..216ed59abc98 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/StructLayoutAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/TypeIdentifierAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/TypeIdentifierAttribute.cs index 6dfe9df78012..16fa15649094 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/TypeIdentifierAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/TypeIdentifierAttribute.cs @@ -2,19 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] public sealed class TypeIdentifierAttribute : Attribute { public TypeIdentifierAttribute() { } - public TypeIdentifierAttribute(string scope, string identifier) + public TypeIdentifierAttribute(string? scope, string? identifier) { Scope = scope; Identifier = identifier; } - public string Scope { get; } - public string Identifier { get; } + public string? Scope { get; } + public string? Identifier { get; } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs index c4f96903ee2c..f5edd8309a15 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/UnmanagedFunctionPointerAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs index cda8e2f92fcd..a6415f68ca28 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { // Event registration tokens are 64 bit opaque structures returned from WinRT style event adders, in order @@ -23,7 +24,7 @@ public struct EventRegistrationToken : IEquatable public static bool operator !=(EventRegistrationToken left, EventRegistrationToken right) => !left.Equals(right); - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj is EventRegistrationToken && ((EventRegistrationToken)obj)._value == _value; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs index 903d2cd9410c..e0ab5c28bfec 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs @@ -105,13 +105,13 @@ public bool Equals(Vector256 other) { if (typeof(T) == typeof(float)) { - Vector256 result = Avx.Compare(this.AsSingle(), other.AsSingle(), FloatComparisonMode.EqualOrderedNonSignaling); + Vector256 result = Avx.Compare(this.AsSingle(), other.AsSingle(), FloatComparisonMode.OrderedEqualNonSignaling); return Avx.MoveMask(result) == 0b1111_1111; // We have one bit per element } if (typeof(T) == typeof(double)) { - Vector256 result = Avx.Compare(this.AsDouble(), other.AsDouble(), FloatComparisonMode.EqualOrderedNonSignaling); + Vector256 result = Avx.Compare(this.AsDouble(), other.AsDouble(), FloatComparisonMode.OrderedEqualNonSignaling); return Avx.MoveMask(result) == 0b1111; // We have one bit per element } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs index 6a7ca3c52add..2696c866b799 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs @@ -674,64 +674,125 @@ internal Avx2() { } /// /// __m256i _mm256_cvtepi8_epi16 (__m128i a) - /// VPMOVSXBW ymm, xmm/m128 + /// VPMOVSXBW ymm, xmm /// public static Vector256 ConvertToVector256Int16(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m256i _mm256_cvtepu8_epi16 (__m128i a) - /// VPMOVZXBW ymm, xmm/m128 + /// VPMOVZXBW ymm, xmm /// - public static Vector256 ConvertToVector256UInt16(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector256 ConvertToVector256Int16(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m256i _mm256_cvtepi8_epi32 (__m128i a) - /// VPMOVSXBD ymm, xmm/m128 + /// VPMOVSXBD ymm, xmm /// public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// - /// __m256i _mm256_cvtepi16_epi32 (__m128i a) - /// VPMOVSXWD ymm, xmm/m128 + /// __m256i _mm256_cvtepu8_epi32 (__m128i a) + /// VPMOVZXBD ymm, xmm /// - public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// - /// __m256i _mm256_cvtepu8_epi32 (__m128i a) - /// VPMOVZXBD ymm, xmm/m128 + /// __m256i _mm256_cvtepi16_epi32 (__m128i a) + /// VPMOVSXWD ymm, xmm /// - public static Vector256 ConvertToVector256UInt32(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m256i _mm256_cvtepu16_epi32 (__m128i a) - /// VPMOVZXWD ymm, xmm/m128 + /// VPMOVZXWD ymm, xmm /// - public static Vector256 ConvertToVector256UInt32(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m256i _mm256_cvtepi8_epi64 (__m128i a) - /// VPMOVSXBQ ymm, xmm/m128 + /// VPMOVSXBQ ymm, xmm /// public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// + /// __m256i _mm256_cvtepu8_epi64 (__m128i a) + /// VPMOVZXBQ ymm, xmm + /// + public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); } + /// /// __m256i _mm256_cvtepi16_epi64 (__m128i a) - /// VPMOVSXWQ ymm, xmm/m128 + /// VPMOVSXWQ ymm, xmm /// public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// + /// __m256i _mm256_cvtepu16_epi64 (__m128i a) + /// VPMOVZXWQ ymm, xmm + /// + public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); } + /// /// __m256i _mm256_cvtepi32_epi64 (__m128i a) - /// VPMOVSXDQ ymm, xmm/m128 + /// VPMOVSXDQ ymm, xmm /// public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// - /// __m256i _mm256_cvtepu8_epi64 (__m128i a) - /// VPMOVZXBQ ymm, xmm/m128 + /// __m256i _mm256_cvtepu32_epi64 (__m128i a) + /// VPMOVZXDQ ymm, xmm /// - public static Vector256 ConvertToVector256UInt64(Vector128 value) { throw new PlatformNotSupportedException(); } + public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); } + /// - /// __m256i _mm256_cvtepu16_epi64 (__m128i a) - /// VPMOVZXWQ ymm, xmm/m128 + /// VPMOVSXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// - public static Vector256 ConvertToVector256UInt64(Vector128 value) { throw new PlatformNotSupportedException(); } + public static unsafe Vector256 ConvertToVector256Int16(sbyte* address) { throw new PlatformNotSupportedException(); } /// - /// __m256i _mm256_cvtepu32_epi64 (__m128i a) - /// VPMOVZXDQ ymm, xmm/m128 + /// VPMOVZXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int16(byte* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVSXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(sbyte* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVZXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(byte* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVSXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(short* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVZXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(ushort* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVSXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(sbyte* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVZXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(byte* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVSXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(short* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVZXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(ushort* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVSXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(int* address) { throw new PlatformNotSupportedException(); } + /// + /// VPMOVZXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// - public static Vector256 ConvertToVector256UInt64(Vector128 value) { throw new PlatformNotSupportedException(); } + public static unsafe Vector256 ConvertToVector256Int64(uint* address) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs index 33b101b96211..9b6f2a61622c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs @@ -674,64 +674,125 @@ internal Avx2() { } /// /// __m256i _mm256_cvtepi8_epi16 (__m128i a) - /// VPMOVSXBW ymm, xmm/m128 + /// VPMOVSXBW ymm, xmm /// public static Vector256 ConvertToVector256Int16(Vector128 value) => ConvertToVector256Int16(value); /// /// __m256i _mm256_cvtepu8_epi16 (__m128i a) - /// VPMOVZXBW ymm, xmm/m128 + /// VPMOVZXBW ymm, xmm /// - public static Vector256 ConvertToVector256UInt16(Vector128 value) => ConvertToVector256UInt16(value); + public static Vector256 ConvertToVector256Int16(Vector128 value) => ConvertToVector256Int16(value); /// /// __m256i _mm256_cvtepi8_epi32 (__m128i a) - /// VPMOVSXBD ymm, xmm/m128 + /// VPMOVSXBD ymm, xmm /// public static Vector256 ConvertToVector256Int32(Vector128 value) => ConvertToVector256Int32(value); /// - /// __m256i _mm256_cvtepi16_epi32 (__m128i a) - /// VPMOVSXWD ymm, xmm/m128 + /// __m256i _mm256_cvtepu8_epi32 (__m128i a) + /// VPMOVZXBD ymm, xmm /// - public static Vector256 ConvertToVector256Int32(Vector128 value) => ConvertToVector256Int32(value); + public static Vector256 ConvertToVector256Int32(Vector128 value) => ConvertToVector256Int32(value); /// - /// __m256i _mm256_cvtepu8_epi32 (__m128i a) - /// VPMOVZXBD ymm, xmm/m128 + /// __m256i _mm256_cvtepi16_epi32 (__m128i a) + /// VPMOVSXWD ymm, xmm /// - public static Vector256 ConvertToVector256UInt32(Vector128 value) => ConvertToVector256UInt32(value); + public static Vector256 ConvertToVector256Int32(Vector128 value) => ConvertToVector256Int32(value); /// /// __m256i _mm256_cvtepu16_epi32 (__m128i a) - /// VPMOVZXWD ymm, xmm/m128 + /// VPMOVZXWD ymm, xmm /// - public static Vector256 ConvertToVector256UInt32(Vector128 value) => ConvertToVector256UInt32(value); + public static Vector256 ConvertToVector256Int32(Vector128 value) => ConvertToVector256Int32(value); /// /// __m256i _mm256_cvtepi8_epi64 (__m128i a) - /// VPMOVSXBQ ymm, xmm/m128 + /// VPMOVSXBQ ymm, xmm /// public static Vector256 ConvertToVector256Int64(Vector128 value) => ConvertToVector256Int64(value); /// + /// __m256i _mm256_cvtepu8_epi64 (__m128i a) + /// VPMOVZXBQ ymm, xmm + /// + public static Vector256 ConvertToVector256Int64(Vector128 value) => ConvertToVector256Int64(value); + /// /// __m256i _mm256_cvtepi16_epi64 (__m128i a) - /// VPMOVSXWQ ymm, xmm/m128 + /// VPMOVSXWQ ymm, xmm /// public static Vector256 ConvertToVector256Int64(Vector128 value) => ConvertToVector256Int64(value); /// + /// __m256i _mm256_cvtepu16_epi64 (__m128i a) + /// VPMOVZXWQ ymm, xmm + /// + public static Vector256 ConvertToVector256Int64(Vector128 value) => ConvertToVector256Int64(value); + /// /// __m256i _mm256_cvtepi32_epi64 (__m128i a) - /// VPMOVSXDQ ymm, xmm/m128 + /// VPMOVSXDQ ymm, xmm /// public static Vector256 ConvertToVector256Int64(Vector128 value) => ConvertToVector256Int64(value); /// - /// __m256i _mm256_cvtepu8_epi64 (__m128i a) - /// VPMOVZXBQ ymm, xmm/m128 + /// __m256i _mm256_cvtepu32_epi64 (__m128i a) + /// VPMOVZXDQ ymm, xmm /// - public static Vector256 ConvertToVector256UInt64(Vector128 value) => ConvertToVector256UInt64(value); + public static Vector256 ConvertToVector256Int64(Vector128 value) => ConvertToVector256Int64(value); + /// - /// __m256i _mm256_cvtepu16_epi64 (__m128i a) - /// VPMOVZXWQ ymm, xmm/m128 + /// VPMOVSXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// - public static Vector256 ConvertToVector256UInt64(Vector128 value) => ConvertToVector256UInt64(value); + public static unsafe Vector256 ConvertToVector256Int16(sbyte* address) => ConvertToVector256Int16(address); /// - /// __m256i _mm256_cvtepu32_epi64 (__m128i a) - /// VPMOVZXDQ ymm, xmm/m128 + /// VPMOVZXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int16(byte* address) => ConvertToVector256Int16(address); + /// + /// VPMOVSXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(sbyte* address) => ConvertToVector256Int32(address); + /// + /// VPMOVZXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(byte* address) => ConvertToVector256Int32(address); + /// + /// VPMOVSXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(short* address) => ConvertToVector256Int32(address); + /// + /// VPMOVZXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int32(ushort* address) => ConvertToVector256Int32(address); + /// + /// VPMOVSXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(sbyte* address) => ConvertToVector256Int64(address); + /// + /// VPMOVZXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(byte* address) => ConvertToVector256Int64(address); + /// + /// VPMOVSXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(short* address) => ConvertToVector256Int64(address); + /// + /// VPMOVZXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(ushort* address) => ConvertToVector256Int64(address); + /// + /// VPMOVSXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector256 ConvertToVector256Int64(int* address) => ConvertToVector256Int64(address); + /// + /// VPMOVZXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// - public static Vector256 ConvertToVector256UInt64(Vector128 value) => ConvertToVector256UInt64(value); + public static unsafe Vector256 ConvertToVector256Int64(uint* address) => ConvertToVector256Int64(address); /// /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs index 5dbbbed88f53..80aa680cc6e3 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs @@ -10,17 +10,17 @@ public enum FloatComparisonMode : byte /// /// _CMP_EQ_OQ /// - EqualOrderedNonSignaling = 0, + OrderedEqualNonSignaling = 0, /// /// _CMP_LT_OS /// - LessThanOrderedSignaling = 1, + OrderedLessThanSignaling = 1, /// /// _CMP_LE_OS /// - LessThanOrEqualOrderedSignaling = 2, + OrderedLessThanOrEqualSignaling = 2, /// /// _CMP_UNORD_Q @@ -30,17 +30,17 @@ public enum FloatComparisonMode : byte /// /// _CMP_NEQ_UQ /// - NotEqualUnorderedNonSignaling = 4, + UnorderedNotEqualNonSignaling = 4, /// /// _CMP_NLT_US /// - NotLessThanUnorderedSignaling = 5, + UnorderedNotLessThanSignaling = 5, /// /// _CMP_NLE_US /// - NotLessThanOrEqualUnorderedSignaling = 6, + UnorderedNotLessThanOrEqualSignaling = 6, /// /// _CMP_ORD_Q @@ -50,57 +50,57 @@ public enum FloatComparisonMode : byte /// /// _CMP_EQ_UQ /// - EqualUnorderedNonSignaling = 8, + UnorderedEqualNonSignaling = 8, /// /// _CMP_NGE_US /// - NotGreaterThanOrEqualUnorderedSignaling = 9, + UnorderedNotGreaterThanOrEqualSignaling = 9, /// /// _CMP_NGT_US /// - NotGreaterThanUnorderedSignaling = 10, + UnorderedNotGreaterThanSignaling = 10, /// /// _CMP_FALSE_OQ /// - FalseOrderedNonSignaling = 11, + OrderedFalseNonSignaling = 11, /// /// _CMP_NEQ_OQ /// - NotEqualOrderedNonSignaling = 12, + OrderedNotEqualNonSignaling = 12, /// /// _CMP_GE_OS /// - GreaterThanOrEqualOrderedSignaling = 13, + OrderedGreaterThanOrEqualSignaling = 13, /// /// _CMP_GT_OS /// - GreaterThanOrderedSignaling = 14, + OrderedGreaterThanSignaling = 14, /// /// _CMP_TRUE_UQ /// - TrueUnorderedNonSignaling = 15, + UnorderedTrueNonSignaling = 15, /// /// _CMP_EQ_OS /// - EqualOrderedSignaling = 16, + OrderedEqualSignaling = 16, /// /// _CMP_LT_OQ /// - LessThanOrderedNonSignaling = 17, + OrderedLessThanNonSignaling = 17, /// /// _CMP_LE_OQ /// - LessThanOrEqualOrderedNonSignaling = 18, + OrderedLessThanOrEqualNonSignaling = 18, /// /// _CMP_UNORD_S @@ -110,17 +110,17 @@ public enum FloatComparisonMode : byte /// /// _CMP_NEQ_US /// - NotEqualUnorderedSignaling = 20, + UnorderedNotEqualSignaling = 20, /// /// _CMP_NLT_UQ /// - NotLessThanUnorderedNonSignaling = 21, + UnorderedNotLessThanNonSignaling = 21, /// /// _CMP_NLE_UQ /// - NotLessThanOrEqualUnorderedNonSignaling = 22, + UnorderedNotLessThanOrEqualNonSignaling = 22, /// /// _CMP_ORD_S @@ -130,41 +130,41 @@ public enum FloatComparisonMode : byte /// /// _CMP_EQ_US /// - EqualUnorderedSignaling = 24, + UnorderedEqualSignaling = 24, /// /// _CMP_NGE_UQ /// - NotGreaterThanOrEqualUnorderedNonSignaling = 25, + UnorderedNotGreaterThanOrEqualNonSignaling = 25, /// /// _CMP_NGT_UQ /// - NotGreaterThanUnorderedNonSignaling = 26, + UnorderedNotGreaterThanNonSignaling = 26, /// /// _CMP_FALSE_OS /// - FalseOrderedSignaling = 27, + OrderedFalseSignaling = 27, /// /// _CMP_NEQ_OS /// - NotEqualOrderedSignaling = 28, + OrderedNotEqualSignaling = 28, /// /// _CMP_GE_OQ /// - GreaterThanOrEqualOrderedNonSignaling = 29, + OrderedGreaterThanOrEqualNonSignaling = 29, /// /// _CMP_GT_OQ /// - GreaterThanOrderedNonSignaling = 30, + OrderedGreaterThanNonSignaling = 30, /// /// _CMP_TRUE_US /// - TrueUnorderedSignaling = 31, + UnorderedTrueSignaling = 31, } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs index 4187dd27dfa4..44d7b1fa7947 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs @@ -81,19 +81,19 @@ internal X64() { } /// int _mm_comieq_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomieq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(0) /// - public static Vector128 CompareEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b) @@ -105,19 +105,19 @@ internal X64() { } /// int _mm_comigt_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomigt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(6) /// - public static Vector128 CompareGreaterThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpge_ps (__m128 a, __m128 b) @@ -129,19 +129,19 @@ internal X64() { } /// int _mm_comige_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomige_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpge_ss (__m128 a, __m128 b) /// CMPPS xmm, xmm/m32, imm8(5) /// - public static Vector128 CompareGreaterThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmplt_ps (__m128 a, __m128 b) @@ -153,19 +153,19 @@ internal X64() { } /// int _mm_comilt_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareLessThanOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomilt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareLessThanUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmplt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(1) /// - public static Vector128 CompareLessThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmple_ps (__m128 a, __m128 b) @@ -177,19 +177,19 @@ internal X64() { } /// int _mm_comile_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareLessThanOrEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomile_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareLessThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmple_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(2) /// - public static Vector128 CompareLessThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b) @@ -201,19 +201,19 @@ internal X64() { } /// int _mm_comineq_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareNotEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedNotEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomineq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareNotEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedNotEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(4) /// - public static Vector128 CompareNotEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b) @@ -225,7 +225,7 @@ internal X64() { } /// __m128 _mm_cmpngt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(2) /// - public static Vector128 CompareNotGreaterThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b) @@ -237,7 +237,7 @@ internal X64() { } /// __m128 _mm_cmpnge_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(1) /// - public static Vector128 CompareNotGreaterThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b) @@ -249,7 +249,7 @@ internal X64() { } /// __m128 _mm_cmpnlt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(5) /// - public static Vector128 CompareNotLessThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b) @@ -261,7 +261,7 @@ internal X64() { } /// __m128 _mm_cmpnle_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(6) /// - public static Vector128 CompareNotLessThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpord_ps (__m128 a, __m128 b) @@ -273,7 +273,7 @@ internal X64() { } /// __m128 _mm_cmpord_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(7) /// - public static Vector128 CompareOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarOrdered(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b) @@ -285,7 +285,7 @@ internal X64() { } /// __m128 _mm_cmpunord_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(3) /// - public static Vector128 CompareUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarUnordered(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_cvtss_si32 (__m128 a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs index f65aedaf818a..c9c2d7e139e9 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs @@ -83,19 +83,19 @@ internal X64() { } /// int _mm_comieq_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareEqualOrderedScalar(Vector128 left, Vector128 right) => CompareEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedEqual(Vector128 left, Vector128 right) => CompareScalarOrderedEqual(left, right); /// /// int _mm_ucomieq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedEqual(left, right); /// /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(0) /// - public static Vector128 CompareEqualScalar(Vector128 left, Vector128 right) => CompareEqualScalar(left, right); + public static Vector128 CompareScalarEqual(Vector128 left, Vector128 right) => CompareScalarEqual(left, right); /// /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b) @@ -107,19 +107,19 @@ internal X64() { } /// int _mm_comigt_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanOrderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThan(Vector128 left, Vector128 right) => CompareScalarOrderedGreaterThan(left, right); /// /// int _mm_ucomigt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanUnorderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThan(Vector128 left, Vector128 right) => CompareScalarUnorderedGreaterThan(left, right); /// /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(6) /// - public static Vector128 CompareGreaterThanScalar(Vector128 left, Vector128 right) => CompareGreaterThanScalar(left, right); + public static Vector128 CompareScalarGreaterThan(Vector128 left, Vector128 right) => CompareScalarGreaterThan(left, right); /// /// __m128 _mm_cmpge_ps (__m128 a, __m128 b) @@ -131,19 +131,19 @@ internal X64() { } /// int _mm_comige_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarOrderedGreaterThanOrEqual(left, right); /// /// int _mm_ucomige_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedGreaterThanOrEqual(left, right); /// /// __m128 _mm_cmpge_ss (__m128 a, __m128 b) /// CMPPS xmm, xmm/m32, imm8(5) /// - public static Vector128 CompareGreaterThanOrEqualScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrEqualScalar(left, right); + public static Vector128 CompareScalarGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarGreaterThanOrEqual(left, right); /// /// __m128 _mm_cmplt_ps (__m128 a, __m128 b) @@ -155,19 +155,19 @@ internal X64() { } /// int _mm_comilt_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareLessThanOrderedScalar(Vector128 left, Vector128 right) => CompareLessThanOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThan(Vector128 left, Vector128 right) => CompareScalarOrderedLessThan(left, right); /// /// int _mm_ucomilt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareLessThanUnorderedScalar(Vector128 left, Vector128 right) => CompareLessThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThan(Vector128 left, Vector128 right) => CompareScalarUnorderedLessThan(left, right); /// /// __m128 _mm_cmplt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(1) /// - public static Vector128 CompareLessThanScalar(Vector128 left, Vector128 right) => CompareLessThanScalar(left, right); + public static Vector128 CompareScalarLessThan(Vector128 left, Vector128 right) => CompareScalarLessThan(left, right); /// /// __m128 _mm_cmple_ps (__m128 a, __m128 b) @@ -179,19 +179,19 @@ internal X64() { } /// int _mm_comile_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareLessThanOrEqualOrderedScalar(Vector128 left, Vector128 right) => CompareLessThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarOrderedLessThanOrEqual(left, right); /// /// int _mm_ucomile_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareLessThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareLessThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedLessThanOrEqual(left, right); /// /// __m128 _mm_cmple_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(2) /// - public static Vector128 CompareLessThanOrEqualScalar(Vector128 left, Vector128 right) => CompareLessThanOrEqualScalar(left, right); + public static Vector128 CompareScalarLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarLessThanOrEqual(left, right); /// /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b) @@ -203,19 +203,19 @@ internal X64() { } /// int _mm_comineq_ss (__m128 a, __m128 b) /// COMISS xmm, xmm/m32 /// - public static bool CompareNotEqualOrderedScalar(Vector128 left, Vector128 right) => CompareNotEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedNotEqual(Vector128 left, Vector128 right) => CompareScalarOrderedNotEqual(left, right); /// /// int _mm_ucomineq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// - public static bool CompareNotEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareNotEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedNotEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedNotEqual(left, right); /// /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(4) /// - public static Vector128 CompareNotEqualScalar(Vector128 left, Vector128 right) => CompareNotEqualScalar(left, right); + public static Vector128 CompareScalarNotEqual(Vector128 left, Vector128 right) => CompareScalarNotEqual(left, right); /// /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b) @@ -227,7 +227,7 @@ internal X64() { } /// __m128 _mm_cmpngt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(2) /// - public static Vector128 CompareNotGreaterThanScalar(Vector128 left, Vector128 right) => CompareNotGreaterThanScalar(left, right); + public static Vector128 CompareScalarNotGreaterThan(Vector128 left, Vector128 right) => CompareScalarNotGreaterThan(left, right); /// /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b) @@ -239,7 +239,7 @@ internal X64() { } /// __m128 _mm_cmpnge_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(1) /// - public static Vector128 CompareNotGreaterThanOrEqualScalar(Vector128 left, Vector128 right) => CompareNotGreaterThanOrEqualScalar(left, right); + public static Vector128 CompareScalarNotGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarNotGreaterThanOrEqual(left, right); /// /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b) @@ -251,7 +251,7 @@ internal X64() { } /// __m128 _mm_cmpnlt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(5) /// - public static Vector128 CompareNotLessThanScalar(Vector128 left, Vector128 right) => CompareNotLessThanScalar(left, right); + public static Vector128 CompareScalarNotLessThan(Vector128 left, Vector128 right) => CompareScalarNotLessThan(left, right); /// /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b) @@ -263,7 +263,7 @@ internal X64() { } /// __m128 _mm_cmpnle_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(6) /// - public static Vector128 CompareNotLessThanOrEqualScalar(Vector128 left, Vector128 right) => CompareNotLessThanOrEqualScalar(left, right); + public static Vector128 CompareScalarNotLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarNotLessThanOrEqual(left, right); /// /// __m128 _mm_cmpord_ps (__m128 a, __m128 b) @@ -275,7 +275,7 @@ internal X64() { } /// __m128 _mm_cmpord_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(7) /// - public static Vector128 CompareOrderedScalar(Vector128 left, Vector128 right) => CompareOrderedScalar(left, right); + public static Vector128 CompareScalarOrdered(Vector128 left, Vector128 right) => CompareScalarOrdered(left, right); /// /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b) @@ -287,7 +287,7 @@ internal X64() { } /// __m128 _mm_cmpunord_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(3) /// - public static Vector128 CompareUnorderedScalar(Vector128 left, Vector128 right) => CompareUnorderedScalar(left, right); + public static Vector128 CompareScalarUnordered(Vector128 left, Vector128 right) => CompareScalarUnordered(left, right); /// /// int _mm_cvtss_si32 (__m128 a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs index 7ad61f50c029..b787cc916dd4 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs @@ -301,21 +301,21 @@ internal X64() { } /// /// int _mm_comieq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomieq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(0) /// - public static Vector128 CompareEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b) @@ -340,21 +340,21 @@ internal X64() { } /// /// int _mm_comigt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomigt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(6) /// - public static Vector128 CompareGreaterThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpge_pd (__m128d a, __m128d b) @@ -364,21 +364,21 @@ internal X64() { } /// /// int _mm_comige_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomige_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpge_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(5) /// - public static Vector128 CompareGreaterThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b) @@ -403,21 +403,21 @@ internal X64() { } /// /// int _mm_comilt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareLessThanOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomilt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareLessThanUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmplt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(1) /// - public static Vector128 CompareLessThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmple_pd (__m128d a, __m128d b) @@ -427,21 +427,21 @@ internal X64() { } /// /// int _mm_comile_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareLessThanOrEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomile_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareLessThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmple_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(2) /// - public static Vector128 CompareLessThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b) @@ -451,21 +451,21 @@ internal X64() { } /// /// int _mm_comineq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareNotEqualOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedNotEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// int _mm_ucomineq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareNotEqualUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedNotEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(4) /// - public static Vector128 CompareNotEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b) @@ -477,7 +477,7 @@ internal X64() { } /// __m128d _mm_cmpngt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(2) /// - public static Vector128 CompareNotGreaterThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotGreaterThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b) @@ -489,7 +489,7 @@ internal X64() { } /// __m128d _mm_cmpnge_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(1) /// - public static Vector128 CompareNotGreaterThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotGreaterThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b) @@ -501,7 +501,7 @@ internal X64() { } /// __m128d _mm_cmpnlt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(5) /// - public static Vector128 CompareNotLessThanScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotLessThan(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b) @@ -513,7 +513,7 @@ internal X64() { } /// __m128d _mm_cmpnle_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(6) /// - public static Vector128 CompareNotLessThanOrEqualScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarNotLessThanOrEqual(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpord_pd (__m128d a, __m128d b) @@ -525,7 +525,7 @@ internal X64() { } /// __m128d _mm_cmpord_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(7) /// - public static Vector128 CompareOrderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarOrdered(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b) @@ -537,7 +537,7 @@ internal X64() { } /// __m128d _mm_cmpunord_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(3) /// - public static Vector128 CompareUnorderedScalar(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } + public static Vector128 CompareScalarUnordered(Vector128 left, Vector128 right) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtps_epi32 (__m128 a) @@ -1295,6 +1295,16 @@ internal X64() { } /// MOVSD m64, xmm /// public static unsafe void StoreScalar(double* address, Vector128 source) { throw new PlatformNotSupportedException(); } + /// + /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a) + /// MOVQ m64, xmm + /// + public static unsafe void StoreScalar(long* address, Vector128 source) { throw new PlatformNotSupportedException(); } + /// + /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a) + /// MOVQ m64, xmm + /// + public static unsafe void StoreScalar(ulong* address, Vector128 source) { throw new PlatformNotSupportedException(); } /// /// void _mm_store_si128 (__m128i* mem_addr, __m128i a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs index d9d1307cc869..ad674457a9a7 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs @@ -303,21 +303,21 @@ internal X64() { } /// /// int _mm_comieq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareEqualOrderedScalar(Vector128 left, Vector128 right) => CompareEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedEqual(Vector128 left, Vector128 right) => CompareScalarOrderedEqual(left, right); /// /// int _mm_ucomieq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedEqual(left, right); /// /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(0) /// - public static Vector128 CompareEqualScalar(Vector128 left, Vector128 right) => CompareEqualScalar(left, right); + public static Vector128 CompareScalarEqual(Vector128 left, Vector128 right) => CompareScalarEqual(left, right); /// /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b) @@ -342,21 +342,21 @@ internal X64() { } /// /// int _mm_comigt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanOrderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThan(Vector128 left, Vector128 right) => CompareScalarOrderedGreaterThan(left, right); /// /// int _mm_ucomigt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanUnorderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThan(Vector128 left, Vector128 right) => CompareScalarUnorderedGreaterThan(left, right); /// /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(6) /// - public static Vector128 CompareGreaterThanScalar(Vector128 left, Vector128 right) => CompareGreaterThanScalar(left, right); + public static Vector128 CompareScalarGreaterThan(Vector128 left, Vector128 right) => CompareScalarGreaterThan(left, right); /// /// __m128d _mm_cmpge_pd (__m128d a, __m128d b) @@ -366,21 +366,21 @@ internal X64() { } /// /// int _mm_comige_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarOrderedGreaterThanOrEqual(left, right); /// /// int _mm_ucomige_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedGreaterThanOrEqual(left, right); /// /// __m128d _mm_cmpge_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(5) /// - public static Vector128 CompareGreaterThanOrEqualScalar(Vector128 left, Vector128 right) => CompareGreaterThanOrEqualScalar(left, right); + public static Vector128 CompareScalarGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarGreaterThanOrEqual(left, right); /// /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b) @@ -405,21 +405,21 @@ internal X64() { } /// /// int _mm_comilt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareLessThanOrderedScalar(Vector128 left, Vector128 right) => CompareLessThanOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThan(Vector128 left, Vector128 right) => CompareScalarOrderedLessThan(left, right); /// /// int _mm_ucomilt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareLessThanUnorderedScalar(Vector128 left, Vector128 right) => CompareLessThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThan(Vector128 left, Vector128 right) => CompareScalarUnorderedLessThan(left, right); /// /// __m128d _mm_cmplt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(1) /// - public static Vector128 CompareLessThanScalar(Vector128 left, Vector128 right) => CompareLessThanScalar(left, right); + public static Vector128 CompareScalarLessThan(Vector128 left, Vector128 right) => CompareScalarLessThan(left, right); /// /// __m128d _mm_cmple_pd (__m128d a, __m128d b) @@ -429,21 +429,21 @@ internal X64() { } /// /// int _mm_comile_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareLessThanOrEqualOrderedScalar(Vector128 left, Vector128 right) => CompareLessThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarOrderedLessThanOrEqual(left, right); /// /// int _mm_ucomile_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareLessThanOrEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareLessThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedLessThanOrEqual(left, right); /// /// __m128d _mm_cmple_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(2) /// - public static Vector128 CompareLessThanOrEqualScalar(Vector128 left, Vector128 right) => CompareLessThanOrEqualScalar(left, right); + public static Vector128 CompareScalarLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarLessThanOrEqual(left, right); /// /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b) @@ -453,21 +453,21 @@ internal X64() { } /// /// int _mm_comineq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// - public static bool CompareNotEqualOrderedScalar(Vector128 left, Vector128 right) => CompareNotEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedNotEqual(Vector128 left, Vector128 right) => CompareScalarOrderedNotEqual(left, right); /// /// int _mm_ucomineq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// - public static bool CompareNotEqualUnorderedScalar(Vector128 left, Vector128 right) => CompareNotEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedNotEqual(Vector128 left, Vector128 right) => CompareScalarUnorderedNotEqual(left, right); /// /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(4) /// - public static Vector128 CompareNotEqualScalar(Vector128 left, Vector128 right) => CompareNotEqualScalar(left, right); + public static Vector128 CompareScalarNotEqual(Vector128 left, Vector128 right) => CompareScalarNotEqual(left, right); /// /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b) @@ -479,7 +479,7 @@ internal X64() { } /// __m128d _mm_cmpngt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(2) /// - public static Vector128 CompareNotGreaterThanScalar(Vector128 left, Vector128 right) => CompareNotGreaterThanScalar(left, right); + public static Vector128 CompareScalarNotGreaterThan(Vector128 left, Vector128 right) => CompareScalarNotGreaterThan(left, right); /// /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b) @@ -491,7 +491,7 @@ internal X64() { } /// __m128d _mm_cmpnge_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(1) /// - public static Vector128 CompareNotGreaterThanOrEqualScalar(Vector128 left, Vector128 right) => CompareNotGreaterThanOrEqualScalar(left, right); + public static Vector128 CompareScalarNotGreaterThanOrEqual(Vector128 left, Vector128 right) => CompareScalarNotGreaterThanOrEqual(left, right); /// /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b) @@ -503,7 +503,7 @@ internal X64() { } /// __m128d _mm_cmpnlt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(5) /// - public static Vector128 CompareNotLessThanScalar(Vector128 left, Vector128 right) => CompareNotLessThanScalar(left, right); + public static Vector128 CompareScalarNotLessThan(Vector128 left, Vector128 right) => CompareScalarNotLessThan(left, right); /// /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b) @@ -515,7 +515,7 @@ internal X64() { } /// __m128d _mm_cmpnle_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(6) /// - public static Vector128 CompareNotLessThanOrEqualScalar(Vector128 left, Vector128 right) => CompareNotLessThanOrEqualScalar(left, right); + public static Vector128 CompareScalarNotLessThanOrEqual(Vector128 left, Vector128 right) => CompareScalarNotLessThanOrEqual(left, right); /// /// __m128d _mm_cmpord_pd (__m128d a, __m128d b) @@ -527,7 +527,7 @@ internal X64() { } /// __m128d _mm_cmpord_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(7) /// - public static Vector128 CompareOrderedScalar(Vector128 left, Vector128 right) => CompareOrderedScalar(left, right); + public static Vector128 CompareScalarOrdered(Vector128 left, Vector128 right) => CompareScalarOrdered(left, right); /// /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b) @@ -539,7 +539,7 @@ internal X64() { } /// __m128d _mm_cmpunord_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(3) /// - public static Vector128 CompareUnorderedScalar(Vector128 left, Vector128 right) => CompareUnorderedScalar(left, right); + public static Vector128 CompareScalarUnordered(Vector128 left, Vector128 right) => CompareScalarUnordered(left, right); /// /// __m128i _mm_cvtps_epi32 (__m128 a) @@ -1301,6 +1301,16 @@ internal X64() { } /// MOVSD m64, xmm /// public static unsafe void StoreScalar(double* address, Vector128 source) => StoreScalar(address, source); + /// + /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a) + /// MOVQ m64, xmm + /// + public static unsafe void StoreScalar(long* address, Vector128 source) => StoreScalar(address, source); + /// + /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a) + /// MOVQ m64, xmm + /// + public static unsafe void StoreScalar(ulong* address, Vector128 source) => StoreScalar(address, source); /// /// void _mm_store_si128 (__m128i* mem_addr, __m128i a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs index dfa5b568c73d..d9f67bcb6791 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs @@ -181,65 +181,126 @@ internal X64() { } /// /// __m128i _mm_cvtepi8_epi16 (__m128i a) - /// PMOVSXBW xmm, xmm/m64 + /// PMOVSXBW xmm, xmm /// public static Vector128 ConvertToVector128Int16(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepu8_epi16 (__m128i a) - /// PMOVZXBW xmm, xmm/m64 + /// PMOVZXBW xmm, xmm /// public static Vector128 ConvertToVector128Int16(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepi8_epi32 (__m128i a) - /// PMOVSXBD xmm, xmm/m32 + /// PMOVSXBD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepu8_epi32 (__m128i a) - /// PMOVZXBD xmm, xmm/m32 + /// PMOVZXBD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepi16_epi32 (__m128i a) - /// PMOVSXWD xmm, xmm/m64 + /// PMOVSXWD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepu16_epi32 (__m128i a) - /// PMOVZXWD xmm, xmm/m64 + /// PMOVZXWD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepi8_epi64 (__m128i a) - /// PMOVSXBQ xmm, xmm/m16 + /// PMOVSXBQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepu8_epi64 (__m128i a) - /// PMOVZXBQ xmm, xmm/m16 + /// PMOVZXBQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepi16_epi64 (__m128i a) - /// PMOVSXWQ xmm, xmm/m32 + /// PMOVSXWQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepu16_epi64 (__m128i a) - /// PMOVZXWQ xmm, xmm/m32 + /// PMOVZXWQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepi32_epi64 (__m128i a) - /// PMOVSXDQ xmm, xmm/m64 + /// PMOVSXDQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) { throw new PlatformNotSupportedException(); } /// /// __m128i _mm_cvtepu32_epi64 (__m128i a) - /// PMOVZXDQ xmm, xmm/m64 + /// PMOVZXDQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) { throw new PlatformNotSupportedException(); } + /// + /// PMOVSXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int16(sbyte* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVZXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int16(byte* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVSXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(sbyte* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVZXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(byte* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVSXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(short* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVZXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(ushort* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVSXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(sbyte* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVZXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(byte* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVSXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(short* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVZXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(ushort* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVSXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(int* address) { throw new PlatformNotSupportedException(); } + /// + /// PMOVZXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(uint* address) { throw new PlatformNotSupportedException(); } + /// /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8) /// DPPS xmm, xmm/m128, imm8 diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs index 834b48856f9c..8fe0a3cf944f 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs @@ -183,65 +183,126 @@ internal X64() { } /// /// __m128i _mm_cvtepi8_epi16 (__m128i a) - /// PMOVSXBW xmm, xmm/m64 + /// PMOVSXBW xmm, xmm /// public static Vector128 ConvertToVector128Int16(Vector128 value) => ConvertToVector128Int16(value); /// /// __m128i _mm_cvtepu8_epi16 (__m128i a) - /// PMOVZXBW xmm, xmm/m64 + /// PMOVZXBW xmm, xmm /// public static Vector128 ConvertToVector128Int16(Vector128 value) => ConvertToVector128Int16(value); /// /// __m128i _mm_cvtepi8_epi32 (__m128i a) - /// PMOVSXBD xmm, xmm/m32 + /// PMOVSXBD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) => ConvertToVector128Int32(value); /// /// __m128i _mm_cvtepu8_epi32 (__m128i a) - /// PMOVZXBD xmm, xmm/m32 + /// PMOVZXBD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) => ConvertToVector128Int32(value); /// /// __m128i _mm_cvtepi16_epi32 (__m128i a) - /// PMOVSXWD xmm, xmm/m64 + /// PMOVSXWD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) => ConvertToVector128Int32(value); /// /// __m128i _mm_cvtepu16_epi32 (__m128i a) - /// PMOVZXWD xmm, xmm/m64 + /// PMOVZXWD xmm, xmm /// public static Vector128 ConvertToVector128Int32(Vector128 value) => ConvertToVector128Int32(value); /// /// __m128i _mm_cvtepi8_epi64 (__m128i a) - /// PMOVSXBQ xmm, xmm/m16 + /// PMOVSXBQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) => ConvertToVector128Int64(value); /// /// __m128i _mm_cvtepu8_epi64 (__m128i a) - /// PMOVZXBQ xmm, xmm/m16 + /// PMOVZXBQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) => ConvertToVector128Int64(value); /// /// __m128i _mm_cvtepi16_epi64 (__m128i a) - /// PMOVSXWQ xmm, xmm/m32 + /// PMOVSXWQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) => ConvertToVector128Int64(value); /// /// __m128i _mm_cvtepu16_epi64 (__m128i a) - /// PMOVZXWQ xmm, xmm/m32 + /// PMOVZXWQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) => ConvertToVector128Int64(value); /// /// __m128i _mm_cvtepi32_epi64 (__m128i a) - /// PMOVSXDQ xmm, xmm/m64 + /// PMOVSXDQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) => ConvertToVector128Int64(value); /// /// __m128i _mm_cvtepu32_epi64 (__m128i a) - /// PMOVZXDQ xmm, xmm/m64 + /// PMOVZXDQ xmm, xmm /// public static Vector128 ConvertToVector128Int64(Vector128 value) => ConvertToVector128Int64(value); + /// + /// PMOVSXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int16(sbyte* address) => ConvertToVector128Int16(address); + /// + /// PMOVZXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int16(byte* address) => ConvertToVector128Int16(address); + /// + /// PMOVSXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(sbyte* address) => ConvertToVector128Int32(address); + /// + /// PMOVZXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(byte* address) => ConvertToVector128Int32(address); + /// + /// PMOVSXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(short* address) => ConvertToVector128Int32(address); + /// + /// PMOVZXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int32(ushort* address) => ConvertToVector128Int32(address); + /// + /// PMOVSXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(sbyte* address) => ConvertToVector128Int64(address); + /// + /// PMOVZXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(byte* address) => ConvertToVector128Int64(address); + /// + /// PMOVSXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(short* address) => ConvertToVector128Int64(address); + /// + /// PMOVZXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(ushort* address) => ConvertToVector128Int64(address); + /// + /// PMOVSXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(int* address) => ConvertToVector128Int64(address); + /// + /// PMOVZXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// + public static unsafe Vector128 ConvertToVector128Int64(uint* address) => ConvertToVector128Int64(address); + /// /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8) /// DPPS xmm, xmm/m128, imm8 diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs b/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs index 8316e1093e7b..c0a118c8e7b0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; @@ -31,18 +32,33 @@ private enum InternalState private static readonly Dictionary> s_allContexts = new Dictionary>(); private static long s_nextId; - // Indicates the state of this ALC (Alive or in Unloading state) - private InternalState _state; - - // Id used by s_allContexts - private readonly long _id; +#region private data members + // If you modify any of these fields, you must also update the + // AssemblyLoadContextBaseObject structure in object.h // synchronization primitive to protect against usage of this instance while unloading private readonly object _unloadLock; + private event Func _resolvingUnmanagedDll; + + private event Func _resolving; + + private event Action _unloading; + + private readonly string? _name; + // Contains the reference to VM's representation of the AssemblyLoadContext private readonly IntPtr _nativeAssemblyLoadContext; + // Id used by s_allContexts + private readonly long _id; + + // Indicates the state of this ALC (Alive or in Unloading state) + private InternalState _state; + + private readonly bool _isCollectible; +#endregion + protected AssemblyLoadContext() : this(false, false, null) { } @@ -51,16 +67,16 @@ protected AssemblyLoadContext(bool isCollectible) : this(false, isCollectible, n { } - public AssemblyLoadContext(string name, bool isCollectible = false) : this(false, isCollectible, name) + public AssemblyLoadContext(string? name, bool isCollectible = false) : this(false, isCollectible, name) { } - private protected AssemblyLoadContext(bool representsTPALoadContext, bool isCollectible, string name) + private protected AssemblyLoadContext(bool representsTPALoadContext, bool isCollectible, string? name) { // Initialize the VM side of AssemblyLoadContext if not already done. - IsCollectible = isCollectible; + _isCollectible = isCollectible; - Name = name; + _name = name; // The _unloadLock needs to be assigned after the IsCollectible to ensure proper behavior of the finalizer // even in case the following allocation fails or the thread is aborted between these two lines. @@ -103,7 +119,7 @@ private protected AssemblyLoadContext(bool representsTPALoadContext, bool isColl private void RaiseUnloadEvent() { // Ensure that we raise the Unload event only once - Interlocked.Exchange(ref Unloading, null)?.Invoke(this); + Interlocked.Exchange(ref _unloading, null!)?.Invoke(this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } private void InitiateUnload() @@ -137,7 +153,7 @@ public IEnumerable Assemblies { foreach (Assembly a in GetLoadedAssemblies()) { - AssemblyLoadContext alc = GetLoadContext(a); + AssemblyLoadContext? alc = GetLoadContext(a); if (alc == this) { @@ -153,7 +169,17 @@ public IEnumerable Assemblies // // Inputs: Invoking assembly, and library name to resolve // Returns: A handle to the loaded native library - public event Func ResolvingUnmanagedDll; + public event Func ResolvingUnmanagedDll + { + add + { + _resolvingUnmanagedDll += value; + } + remove + { + _resolvingUnmanagedDll -= value; + } + } // Event handler for resolving managed assemblies. // This event is raised if the managed assembly could not be resolved via @@ -161,9 +187,29 @@ public IEnumerable Assemblies // // Inputs: The AssemblyLoadContext and AssemblyName to be loaded // Returns: The Loaded assembly object. - public event Func Resolving; + public event Func Resolving + { + add + { + _resolving += value; + } + remove + { + _resolving -= value; + } + } - public event Action Unloading; + public event Action Unloading + { + add + { + _unloading += value; + } + remove + { + _unloading -= value; + } + } // Occurs when an Assembly is loaded public static event AssemblyLoadEventHandler AssemblyLoad; @@ -180,9 +226,9 @@ public IEnumerable Assemblies public static AssemblyLoadContext Default => DefaultAssemblyLoadContext.s_loadContext; - public bool IsCollectible { get; } + public bool IsCollectible { get { return _isCollectible;} } - public string Name { get; } + public string? Name { get { return _name;} } public override string ToString() => "\"" + Name + "\" " + GetType().ToString() + " #" + _id; @@ -190,9 +236,9 @@ public static IEnumerable All { get { - AssemblyLoadContext d = AssemblyLoadContext.Default; // Ensure default is initialized + _ = AssemblyLoadContext.Default; // Ensure default is initialized - List> alcList = null; + List>? alcList = null; lock (s_allContexts) { // To make this thread safe we need a quick snapshot while locked @@ -201,7 +247,7 @@ public static IEnumerable All foreach (WeakReference weakAlc in alcList) { - AssemblyLoadContext alc = null; + AssemblyLoadContext? alc = null; weakAlc.TryGetTarget(out alc); @@ -227,7 +273,7 @@ public static AssemblyName GetAssemblyName(string assemblyPath) // Custom AssemblyLoadContext implementations can override this // method to perform custom processing and use one of the protected // helpers above to load the assembly. - protected virtual Assembly Load(AssemblyName assemblyName) + protected virtual Assembly? Load(AssemblyName assemblyName) { return null; } @@ -240,7 +286,7 @@ public Assembly LoadFromAssemblyName(AssemblyName assemblyName) // Attempt to load the assembly, using the same ordering as static load, in the current load context. StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return Assembly.Load(assemblyName, ref stackMark, _nativeAssemblyLoadContext); + return Assembly.Load(assemblyName, ref stackMark, this); } // These methods load assemblies into the current AssemblyLoadContext @@ -265,7 +311,7 @@ public Assembly LoadFromAssemblyPath(string assemblyPath) } } - public Assembly LoadFromNativeImagePath(string nativeImagePath, string assemblyPath) + public Assembly LoadFromNativeImagePath(string nativeImagePath, string? assemblyPath) { if (nativeImagePath == null) { @@ -295,7 +341,7 @@ public Assembly LoadFromStream(Stream assembly) return LoadFromStream(assembly, null); } - public Assembly LoadFromStream(Stream assembly, Stream assemblySymbols) + public Assembly LoadFromStream(Stream assembly, Stream? assemblySymbols) { if (assembly == null) { @@ -316,7 +362,7 @@ public Assembly LoadFromStream(Stream assembly, Stream assemblySymbols) assembly.Read(arrAssembly, 0, iAssemblyStreamLength); // Get the symbol stream in byte[] if provided - byte[] arrSymbols = null; + byte[]? arrSymbols = null; if (assemblySymbols != null) { var iSymbolLength = (int)assemblySymbols.Length; @@ -396,6 +442,119 @@ private void VerifyIsAlive() throw new InvalidOperationException(SR.AssemblyLoadContext_Verify_NotUnloading); } } + + private static AsyncLocal? s_asyncLocalCurrent; + + /// Nullable current AssemblyLoadContext used for context sensitive reflection APIs + /// + /// This is an advanced setting used in reflection assembly loading scenarios. + /// + /// There are a set of contextual reflection APIs which load managed assemblies through an inferred AssemblyLoadContext. + /// * + /// * + /// * + /// * + /// + /// When CurrentContextualReflectionContext is null, the AssemblyLoadContext is inferred. + /// The inference logic is simple. + /// * For static methods, it is the AssemblyLoadContext which loaded the method caller's assembly. + /// * For instance methods, it is the AssemblyLoadContext which loaded the instance's assembly. + /// + /// When this property is set, the CurrentContextualReflectionContext value is used by these contextual reflection APIs for loading. + /// + /// This property is typically set in a using block by + /// . + /// + /// The property is stored in an AsyncLocal<AssemblyLoadContext>. This means the setting can be unique for every async or thread in the process. + /// + /// For more details see https://github.com/dotnet/coreclr/blob/master/Documentation/design-docs/AssemblyLoadContext.ContextualReflection.md + /// + public static AssemblyLoadContext? CurrentContextualReflectionContext + { + get { return s_asyncLocalCurrent?.Value; } + } + + private static void SetCurrentContextualReflectionContext(AssemblyLoadContext? value) + { + if (s_asyncLocalCurrent == null) + { + Interlocked.CompareExchange?>(ref s_asyncLocalCurrent, new AsyncLocal(), null); + } + s_asyncLocalCurrent!.Value = value!; // TODO-NULLABLE-GENERIC + } + + /// Enter scope using this AssemblyLoadContext for ContextualReflection + /// A disposable ContextualReflectionScope for use in a using block + /// + /// Sets CurrentContextualReflectionContext to this instance. + /// + /// + /// Returns a disposable ContextualReflectionScope for use in a using block. When the using calls the + /// Dispose() method, it restores the ContextualReflectionScope to its previous value. + /// + public ContextualReflectionScope EnterContextualReflection() + { + return new ContextualReflectionScope(this); + } + + /// Enter scope using this AssemblyLoadContext for ContextualReflection + /// Set CurrentContextualReflectionContext to the AssemblyLoadContext which loaded activating. + /// A disposable ContextualReflectionScope for use in a using block + /// + /// Sets CurrentContextualReflectionContext to to the AssemblyLoadContext which loaded activating. + /// + /// + /// Returns a disposable ContextualReflectionScope for use in a using block. When the using calls the + /// Dispose() method, it restores the ContextualReflectionScope to its previous value. + /// + public static ContextualReflectionScope EnterContextualReflection(Assembly? activating) + { + if (activating == null) + return new ContextualReflectionScope(null); + + AssemblyLoadContext? assemblyLoadContext = GetLoadContext(activating); + + if (assemblyLoadContext == null) + { + // All RuntimeAssemblies & Only RuntimeAssemblies have an AssemblyLoadContext + throw new ArgumentException(SR.Arg_MustBeRuntimeAssembly, nameof(activating)); + } + + return assemblyLoadContext.EnterContextualReflection(); + } + + /// Opaque disposable struct used to restore CurrentContextualReflectionContext + /// + /// This is an implmentation detail of the AssemblyLoadContext.EnterContextualReflection APIs. + /// It is a struct, to avoid heap allocation. + /// It is required to be public to avoid boxing. + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public struct ContextualReflectionScope : IDisposable + { + private readonly AssemblyLoadContext? _activated; + private readonly AssemblyLoadContext? _predecessor; + private readonly bool _initialized; + + internal ContextualReflectionScope(AssemblyLoadContext? activating) + { + _predecessor = AssemblyLoadContext.CurrentContextualReflectionContext; + AssemblyLoadContext.SetCurrentContextualReflectionContext(activating); + _activated = activating; + _initialized = true; + } + + public void Dispose() + { + if (_initialized) + { + // Do not clear initialized. Always restore the _predecessor in Dispose() + // _initialized = false; + AssemblyLoadContext.SetCurrentContextualReflectionContext(_predecessor); + } + } + } } internal sealed class DefaultAssemblyLoadContext : AssemblyLoadContext diff --git a/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Unix.cs b/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Unix.cs index 2f5305200198..37575d0c7b3b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime { public sealed partial class MemoryFailPoint diff --git a/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Windows.cs b/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Windows.cs index 966c3a278f38..5ab51a79c30e 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.cs b/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.cs index 88e222f3187d..4e4ed2920281 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/MemoryFailPoint.cs @@ -13,7 +13,7 @@ ** ===========================================================*/ -using System.IO; +#nullable enable using System.Threading; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs b/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs index a47aaf9ca19c..e53aeb08f231 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs @@ -2,22 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Remoting { public class ObjectHandle : MarshalByRefObject { - private object _wrappedObject; + private object? _wrappedObject; private ObjectHandle() { } - public ObjectHandle(object o) + public ObjectHandle(object? o) { _wrappedObject = o; } - public object Unwrap() + public object? Unwrap() { return _wrappedObject; } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationToken.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationToken.cs index e879ef543ceb..92e0fcb0b071 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationToken.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationToken.cs @@ -2,18 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Runtime.CompilerServices; -using System.Threading; - +#nullable enable namespace System.Runtime.Serialization { // Tracks whether deserialization is currently in progress public readonly struct DeserializationToken : IDisposable { - private readonly DeserializationTracker _tracker; + private readonly DeserializationTracker? _tracker; - internal DeserializationToken(DeserializationTracker tracker) + internal DeserializationToken(DeserializationTracker? tracker) { _tracker = tracker; } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationTracker.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationTracker.cs index fb4ac51edf04..04ea6bdaddcc 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationTracker.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/DeserializationTracker.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Runtime.CompilerServices; - +#nullable enable namespace System.Runtime.Serialization { // Tracks whether deserialization is currently in progress diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IDeserializationCallback.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IDeserializationCallback.cs index a1c1671a8b8b..67628b464015 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IDeserializationCallback.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IDeserializationCallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { public interface IDeserializationCallback diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IFormatterConverter.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IFormatterConverter.cs index c173144854c0..d0e3d81d5b2c 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IFormatterConverter.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IFormatterConverter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { [CLSCompliant(false)] @@ -23,6 +24,6 @@ public interface IFormatterConverter double ToDouble(object value); decimal ToDecimal(object value); DateTime ToDateTime(object value); - string ToString(object value); + string? ToString(object value); } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IObjectReference.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IObjectReference.cs index d41bc50dde4e..f232cf59fa85 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IObjectReference.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/IObjectReference.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { public interface IObjectReference diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISafeSerializationData.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISafeSerializationData.cs index 5089d134c314..f4babe439711 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISafeSerializationData.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISafeSerializationData.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { // diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISerializable.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISerializable.cs index 383b3f07af35..8edf62849387 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISerializable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/ISerializable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { public interface ISerializable diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializedAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializedAttribute.cs index 408a55ccf9e9..d3273f467518 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializedAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializedAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { [AttributeUsage(AttributeTargets.Method, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializingAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializingAttribute.cs index 162857e8d3b8..f2dec85cdf27 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializingAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnDeserializingAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { [AttributeUsage(AttributeTargets.Method, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializedAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializedAttribute.cs index 020dd0257cac..2b82dd7e3c01 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializedAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializedAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { [AttributeUsage(AttributeTargets.Method, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializingAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializingAttribute.cs index 8dc8af3f2356..8c9c8a07a170 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializingAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OnSerializingAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { [AttributeUsage(AttributeTargets.Method, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OptionalFieldAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OptionalFieldAttribute.cs index 84daa539be2c..48eca2821862 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OptionalFieldAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/OptionalFieldAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { [AttributeUsage(AttributeTargets.Field, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SafeSerializationEventArgs.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SafeSerializationEventArgs.cs index 896b91fca026..19870425eac0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SafeSerializationEventArgs.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SafeSerializationEventArgs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; namespace System.Runtime.Serialization diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs index 44aadf3cd41d..e30e7d394ac4 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; using System.Security; @@ -18,7 +18,7 @@ public sealed class SerializationInfo // Even though we have a dictionary, we're still keeping all the arrays around for back-compat. // Otherwise we may run into potentially breaking behaviors like GetEnumerator() not returning entries in the same order they were added. private string[] _names; - private object[] _values; + private object?[] _values; private Type[] _types; private int _count; private Dictionary _nameToIndex; @@ -282,7 +282,7 @@ private void ExpandArrays() _types = newTypes; } - public void AddValue(string name, object value, Type type) + public void AddValue(string name, object? value, Type type) { if (null == name) { @@ -297,7 +297,7 @@ public void AddValue(string name, object value, Type type) AddValueInternal(name, value, type); } - public void AddValue(string name, object value) + public void AddValue(string name, object? value) { if (null == value) { @@ -383,7 +383,7 @@ public void AddValue(string name, DateTime value) AddValue(name, (object)value, typeof(DateTime)); } - internal void AddValueInternal(string name, object value, Type type) + internal void AddValueInternal(string name, object? value, Type type) { if (_nameToIndex.ContainsKey(name)) { @@ -462,7 +462,7 @@ private int FindElement(string name) /// The name of the element to find. /// The type of the element associated with the given name. /// The value of the element at the position associated with name. - private object GetElement(string name, out Type foundType) + private object? GetElement(string name, out Type foundType) { int index = FindElement(name); if (index == -1) @@ -478,7 +478,7 @@ private object GetElement(string name, out Type foundType) return _values[index]; } - private object GetElementNoThrow(string name, out Type foundType) + private object? GetElementNoThrow(string name, out Type? foundType) { int index = FindElement(name); if (index == -1) @@ -495,7 +495,7 @@ private object GetElementNoThrow(string name, out Type foundType) return _values[index]; } - public object GetValue(string name, Type type) + public object? GetValue(string name, Type type) { if ((object)type == null) { @@ -504,10 +504,9 @@ public object GetValue(string name, Type type) if (!type.IsRuntimeImplemented()) throw new ArgumentException(SR.Argument_MustBeRuntimeType); - Type foundType; - object value; - value = GetElement(name, out foundType); + Type foundType; + object? value = GetElement(name, out foundType); if (ReferenceEquals(foundType, type) || type.IsAssignableFrom(foundType) || value == null) { @@ -518,15 +517,13 @@ public object GetValue(string name, Type type) return _converter.Convert(value, type); } - internal object GetValueNoThrow(string name, Type type) + internal object? GetValueNoThrow(string name, Type type) { - Type foundType; - object value; - Debug.Assert((object)type != null, "[SerializationInfo.GetValue]type ==null"); Debug.Assert(type.IsRuntimeImplemented(), "[SerializationInfo.GetValue]type is not a runtime type"); - value = GetElementNoThrow(name, out foundType); + Type? foundType; + object? value = GetElementNoThrow(name, out foundType); if (value == null) return null; @@ -543,14 +540,14 @@ internal object GetValueNoThrow(string name, Type type) public bool GetBoolean(string name) { Type foundType; - object value = GetElement(name, out foundType); - return ReferenceEquals(foundType, typeof(bool)) ? (bool)value : _converter.ToBoolean(value); + object value = GetElement(name, out foundType)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 + return ReferenceEquals(foundType, typeof(bool)) ? (bool)value : _converter.ToBoolean(value); // if value is null To* method will either deal with it or throw } public char GetChar(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(char)) ? (char)value : _converter.ToChar(value); } @@ -558,21 +555,21 @@ public char GetChar(string name) public sbyte GetSByte(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(sbyte)) ? (sbyte)value : _converter.ToSByte(value); } public byte GetByte(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(byte)) ? (byte)value : _converter.ToByte(value); } public short GetInt16(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(short)) ? (short)value : _converter.ToInt16(value); } @@ -580,14 +577,14 @@ public short GetInt16(string name) public ushort GetUInt16(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(ushort)) ? (ushort)value : _converter.ToUInt16(value); } public int GetInt32(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(int)) ? (int)value : _converter.ToInt32(value); } @@ -595,14 +592,14 @@ public int GetInt32(string name) public uint GetUInt32(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(uint)) ? (uint)value : _converter.ToUInt32(value); } public long GetInt64(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(long)) ? (long)value : _converter.ToInt64(value); } @@ -610,14 +607,14 @@ public long GetInt64(string name) public ulong GetUInt64(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(ulong)) ? (ulong)value : _converter.ToUInt64(value); } public float GetSingle(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(float)) ? (float)value : _converter.ToSingle(value); } @@ -625,29 +622,29 @@ public float GetSingle(string name) public double GetDouble(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(double)) ? (double)value : _converter.ToDouble(value); } public decimal GetDecimal(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(decimal)) ? (decimal)value : _converter.ToDecimal(value); } public DateTime GetDateTime(string name) { Type foundType; - object value = GetElement(name, out foundType); + object value = GetElement(name, out foundType)!; return ReferenceEquals(foundType, typeof(DateTime)) ? (DateTime)value : _converter.ToDateTime(value); } - public string GetString(string name) + public string? GetString(string name) { Type foundType; - object value = GetElement(name, out foundType); - return ReferenceEquals(foundType, typeof(string)) || value == null ? (string)value : _converter.ToString(value); + object? value = GetElement(name, out foundType); + return ReferenceEquals(foundType, typeof(string)) || value == null ? (string?)value : _converter.ToString(value); } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs index ba84e6542357..9ce2080ac6e8 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Diagnostics; @@ -10,17 +11,17 @@ namespace System.Runtime.Serialization public readonly struct SerializationEntry { private readonly string _name; - private readonly object _value; + private readonly object? _value; private readonly Type _type; - internal SerializationEntry(string entryName, object entryValue, Type entryType) + internal SerializationEntry(string entryName, object? entryValue, Type entryType) { _name = entryName; _value = entryValue; _type = entryType; } - public object Value => _value; + public object? Value => _value; public string Name => _name; public Type ObjectType => _type; } @@ -28,13 +29,13 @@ internal SerializationEntry(string entryName, object entryValue, Type entryType) public sealed class SerializationInfoEnumerator : IEnumerator { private readonly string[] _members; - private readonly object[] _data; + private readonly object?[] _data; private readonly Type[] _types; private readonly int _numItems; private int _currItem; private bool _current; - internal SerializationInfoEnumerator(string[] members, object[] info, Type[] types, int numItems) + internal SerializationInfoEnumerator(string[] members, object?[] info, Type[] types, int numItems) { Debug.Assert(members != null, "[SerializationInfoEnumerator.ctor]members!=null"); Debug.Assert(info != null, "[SerializationInfoEnumerator.ctor]info!=null"); @@ -70,7 +71,7 @@ public bool MoveNext() return _current; } - object IEnumerator.Current => Current; + object? IEnumerator.Current => Current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 public SerializationEntry Current { @@ -101,7 +102,7 @@ public string Name return _members[_currItem]; } } - public object Value + public object? Value { get { diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/StreamingContext.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/StreamingContext.cs index cdcb1c335b7f..e67f307ffdd2 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/StreamingContext.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/StreamingContext.cs @@ -2,24 +2,25 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.Serialization { public readonly struct StreamingContext { - private readonly object _additionalContext; + private readonly object? _additionalContext; private readonly StreamingContextStates _state; public StreamingContext(StreamingContextStates state) : this(state, null) { } - public StreamingContext(StreamingContextStates state, object additional) + public StreamingContext(StreamingContextStates state, object? additional) { _state = state; _additionalContext = additional; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is StreamingContext)) { @@ -33,7 +34,7 @@ public override bool Equals(object obj) public StreamingContextStates State => _state; - public object Context => _additionalContext; + public object? Context => _additionalContext; } [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/NonVersionableAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/NonVersionableAttribute.cs index e4809953bc1f..b2d1d25ea504 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/NonVersionableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/NonVersionableAttribute.cs @@ -20,9 +20,7 @@ ** significantly extend its usage or allow 3rd parties to use it please discuss with the diagnostics team. ===========================================================*/ -using System; -using System.Diagnostics; - +#nullable enable namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor, diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs index dcb14f0efe91..e3e6d60ff1e3 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs @@ -12,15 +12,14 @@ ** ===========================================================*/ -using System; - +#nullable enable namespace System.Runtime.Versioning { [AttributeUsageAttribute(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] public sealed class TargetFrameworkAttribute : Attribute { private string _frameworkName; // A target framework moniker - private string _frameworkDisplayName; + private string? _frameworkDisplayName; // The frameworkName parameter is intended to be the string form of a FrameworkName instance. public TargetFrameworkAttribute(string frameworkName) @@ -37,7 +36,7 @@ public string FrameworkName get { return _frameworkName; } } - public string FrameworkDisplayName + public string? FrameworkDisplayName { get { return _frameworkDisplayName; } set { _frameworkDisplayName = value; } diff --git a/src/System.Private.CoreLib/shared/System/SByte.cs b/src/System.Private.CoreLib/shared/System/SByte.cs index 0ebe8821b895..62db8812688b 100644 --- a/src/System.Private.CoreLib/shared/System/SByte.cs +++ b/src/System.Private.CoreLib/shared/System/SByte.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -29,7 +30,7 @@ namespace System // null is considered to be less than any instance. // If object is not of type SByte, this method throws an ArgumentException. // - public int CompareTo(object obj) + public int CompareTo(object? obj) { if (obj == null) { @@ -48,7 +49,7 @@ public int CompareTo(sbyte value) } // Determines whether two Byte objects are equal. - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is sbyte)) { @@ -76,17 +77,17 @@ public override string ToString() return Number.FormatInt32(m_value, null, null); } - public string ToString(IFormatProvider provider) + public string ToString(IFormatProvider? provider) { return Number.FormatInt32(m_value, null, provider); } - public string ToString(string format) + public string ToString(string? format) { return ToString(format, null); } - public string ToString(string format, IFormatProvider provider) + public string ToString(string? format, IFormatProvider? provider) { if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x')) { @@ -96,7 +97,7 @@ public string ToString(string format, IFormatProvider provider) return Number.FormatInt32(m_value, format, provider); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider provider = null) + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) { if (m_value < 0 && format.Length > 0 && (format[0] == 'X' || format[0] == 'x')) { @@ -122,7 +123,7 @@ public static sbyte Parse(string s, NumberStyles style) } [CLSCompliant(false)] - public static sbyte Parse(string s, IFormatProvider provider) + public static sbyte Parse(string s, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); return Parse((ReadOnlySpan)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider)); @@ -133,7 +134,7 @@ public static sbyte Parse(string s, IFormatProvider provider) // NumberFormatInfo is assumed. // [CLSCompliant(false)] - public static sbyte Parse(string s, NumberStyles style, IFormatProvider provider) + public static sbyte Parse(string s, NumberStyles style, IFormatProvider? provider) { NumberFormatInfo.ValidateParseStyleInteger(style); if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); @@ -141,7 +142,7 @@ public static sbyte Parse(string s, NumberStyles style, IFormatProvider provider } [CLSCompliant(false)] - public static sbyte Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null) + public static sbyte Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleInteger(style); return Parse(s, style, NumberFormatInfo.GetInstance(provider)); @@ -171,7 +172,7 @@ private static sbyte Parse(ReadOnlySpan s, NumberStyles style, NumberForma } [CLSCompliant(false)] - public static bool TryParse(string s, out sbyte result) + public static bool TryParse(string? s, out sbyte result) { if (s == null) { @@ -189,7 +190,7 @@ public static bool TryParse(ReadOnlySpan s, out sbyte result) } [CLSCompliant(false)] - public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out sbyte result) + public static bool TryParse(string? s, NumberStyles style, IFormatProvider? provider, out sbyte result) { NumberFormatInfo.ValidateParseStyleInteger(style); @@ -203,7 +204,7 @@ public static bool TryParse(string s, NumberStyles style, IFormatProvider provid } [CLSCompliant(false)] - public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider provider, out sbyte result) + 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); @@ -233,77 +234,77 @@ public TypeCode GetTypeCode() } - bool IConvertible.ToBoolean(IFormatProvider provider) + bool IConvertible.ToBoolean(IFormatProvider? provider) { return Convert.ToBoolean(m_value); } - char IConvertible.ToChar(IFormatProvider provider) + char IConvertible.ToChar(IFormatProvider? provider) { return Convert.ToChar(m_value); } - sbyte IConvertible.ToSByte(IFormatProvider provider) + sbyte IConvertible.ToSByte(IFormatProvider? provider) { return m_value; } - byte IConvertible.ToByte(IFormatProvider provider) + byte IConvertible.ToByte(IFormatProvider? provider) { return Convert.ToByte(m_value); } - short IConvertible.ToInt16(IFormatProvider provider) + short IConvertible.ToInt16(IFormatProvider? provider) { return Convert.ToInt16(m_value); } - ushort IConvertible.ToUInt16(IFormatProvider provider) + ushort IConvertible.ToUInt16(IFormatProvider? provider) { return Convert.ToUInt16(m_value); } - int IConvertible.ToInt32(IFormatProvider provider) + int IConvertible.ToInt32(IFormatProvider? provider) { return m_value; } - uint IConvertible.ToUInt32(IFormatProvider provider) + uint IConvertible.ToUInt32(IFormatProvider? provider) { return Convert.ToUInt32(m_value); } - long IConvertible.ToInt64(IFormatProvider provider) + long IConvertible.ToInt64(IFormatProvider? provider) { return Convert.ToInt64(m_value); } - ulong IConvertible.ToUInt64(IFormatProvider provider) + ulong IConvertible.ToUInt64(IFormatProvider? provider) { return Convert.ToUInt64(m_value); } - float IConvertible.ToSingle(IFormatProvider provider) + float IConvertible.ToSingle(IFormatProvider? provider) { return Convert.ToSingle(m_value); } - double IConvertible.ToDouble(IFormatProvider provider) + double IConvertible.ToDouble(IFormatProvider? provider) { return Convert.ToDouble(m_value); } - decimal IConvertible.ToDecimal(IFormatProvider provider) + decimal IConvertible.ToDecimal(IFormatProvider? provider) { return Convert.ToDecimal(m_value); } - DateTime IConvertible.ToDateTime(IFormatProvider provider) + DateTime IConvertible.ToDateTime(IFormatProvider? provider) { throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "SByte", "DateTime")); } - object IConvertible.ToType(Type type, IFormatProvider provider) + object IConvertible.ToType(Type type, IFormatProvider? provider) { return Convert.DefaultToType((IConvertible)this, type, provider); } diff --git a/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs b/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs index 974d9a1f55dd..05c13c8a02af 100644 --- a/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs +++ b/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs @@ -328,12 +328,12 @@ public bool Equal(SecurityElement? other) IEnumerator lhs = _children.GetEnumerator(); IEnumerator rhs = other._children.GetEnumerator(); - SecurityElement e1, e2; + SecurityElement? e1, e2; while (lhs.MoveNext()) { rhs.MoveNext(); - e1 = (SecurityElement)lhs.Current; - e2 = (SecurityElement)rhs.Current; + e1 = (SecurityElement?)lhs.Current; + e2 = (SecurityElement?)rhs.Current; if (e1 == null || !e1.Equal(e2)) return false; } @@ -617,7 +617,7 @@ private void ToString(string indent, object obj, Action write) // an invalid tag simply won't be found. if (_children == null) return null; - foreach (SecurityElement current in _children) + foreach (SecurityElement? current in _children) { if (current != null && string.Equals(current.Tag, tag)) return current; @@ -639,9 +639,9 @@ private void ToString(string indent, object obj, Action write) if (_children == null) return null; - foreach (SecurityElement child in Children!) + foreach (SecurityElement? child in Children!) { - string? text = child.SearchForTextOfTag(tag); + string? text = child?.SearchForTextOfTag(tag); if (text != null) return text; } diff --git a/src/System.Private.CoreLib/shared/System/Security/SecurityException.cs b/src/System.Private.CoreLib/shared/System/Security/SecurityException.cs index f1494757d4b4..b6156ca368b1 100644 --- a/src/System.Private.CoreLib/shared/System/Security/SecurityException.cs +++ b/src/System.Private.CoreLib/shared/System/Security/SecurityException.cs @@ -55,12 +55,12 @@ public SecurityException(string? message, Type? type, string? state) protected SecurityException(SerializationInfo info, StreamingContext context) : base(info, context) { - Demanded = (string)info.GetValueNoThrow(DemandedName, typeof(string)); - GrantedSet = (string)info.GetValueNoThrow(GrantedSetName, typeof(string)); - RefusedSet = (string)info.GetValueNoThrow(RefusedSetName, typeof(string)); - DenySetInstance = (string)info.GetValueNoThrow(DeniedName, typeof(string)); - PermitOnlySetInstance = (string)info.GetValueNoThrow(PermitOnlyName, typeof(string)); - Url = (string)info.GetValueNoThrow(UrlName, typeof(string)); + Demanded = (string?)info.GetValueNoThrow(DemandedName, typeof(string)); + GrantedSet = (string?)info.GetValueNoThrow(GrantedSetName, typeof(string)); + RefusedSet = (string?)info.GetValueNoThrow(RefusedSetName, typeof(string)); + DenySetInstance = (string?)info.GetValueNoThrow(DeniedName, typeof(string)); + PermitOnlySetInstance = (string?)info.GetValueNoThrow(PermitOnlyName, typeof(string)); + Url = (string?)info.GetValueNoThrow(UrlName, typeof(string)); } public override string ToString() => base.ToString(); diff --git a/src/System.Private.CoreLib/shared/System/SerializableAttribute.cs b/src/System.Private.CoreLib/shared/System/SerializableAttribute.cs index c25693137301..9d21d39cc243 100644 --- a/src/System.Private.CoreLib/shared/System/SerializableAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/SerializableAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate, Inherited = false)] diff --git a/src/System.Private.CoreLib/shared/System/Span.Fast.cs b/src/System.Private.CoreLib/shared/System/Span.Fast.cs index adc1f3903d14..1bfa8eee5b54 100644 --- a/src/System.Private.CoreLib/shared/System/Span.Fast.cs +++ b/src/System.Private.CoreLib/shared/System/Span.Fast.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Versioning; @@ -42,14 +43,14 @@ public readonly ref partial struct Span /// Returns default when is null. /// Thrown when is covariant and array's type is not exactly T[]. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span(T[] array) + public Span(T[]? array) { if (array == null) { this = default; return; // returns default } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); _pointer = new ByReference(ref Unsafe.As(ref array.GetRawSzArrayData())); @@ -69,7 +70,7 @@ public Span(T[] array) /// Thrown when the specified or end index is not in the range (<0 or >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span(T[] array, int start, int length) + public Span(T[]? array, int start, int length) { if (array == null) { @@ -78,7 +79,7 @@ public Span(T[] array, int start, int length) this = default; return; // returns default } - if (default(T) == null && array.GetType() != typeof(T[])) + if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArrayTypeMismatchException(); #if BIT64 // See comment in Span.Slice for how this works. @@ -159,18 +160,6 @@ public ref T this[int index] #endif } - public ref T this[Index index] - { - get - { - // Evaluate the actual index first because it helps performance - int actualIndex = index.GetOffset(_length); - return ref this [actualIndex]; - } - } - - public Span this[Range range] => Slice(range); - /// /// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference. /// It can be used for pinning and is required to support the use of span within a fixed statement. @@ -376,28 +365,6 @@ public Span Slice(int start, int length) return new Span(ref Unsafe.Add(ref _pointer.Value, start), length); } - /// - /// Forms a slice out of the given span, beginning at 'startIndex' - /// - /// The index at which to begin this slice. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span Slice(Index startIndex) - { - int actualIndex = startIndex.GetOffset(_length); - return Slice(actualIndex); - } - - /// - /// Forms a slice out of the given span, beginning at range start index to the range end - /// - /// The range which has the start and end indexes used to slice the span. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span Slice(Range range) - { - (int start, int length) = range.GetOffsetAndLength(_length); - return new Span(ref Unsafe.Add(ref _pointer.Value, start), length); - } - /// /// Copies the contents of this span into a new array. This heap /// allocates, so should generally be avoided, however it is sometimes diff --git a/src/System.Private.CoreLib/shared/System/Span.cs b/src/System.Private.CoreLib/shared/System/Span.cs index 185042fb55a0..20bf8e20f806 100644 --- a/src/System.Private.CoreLib/shared/System/Span.cs +++ b/src/System.Private.CoreLib/shared/System/Span.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -59,7 +60,7 @@ public bool IsEmpty /// [Obsolete("Equals() on Span will always throw an exception. Use == instead.")] [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { throw new NotSupportedException(SR.NotSupported_CannotCallEqualsOnSpan); } @@ -80,7 +81,7 @@ public override int GetHashCode() /// /// Defines an implicit conversion of an array to a /// - public static implicit operator Span(T[] array) => new Span(array); + public static implicit operator Span(T[]? array) => new Span(array); /// /// Defines an implicit conversion of a to a diff --git a/src/System.Private.CoreLib/shared/System/SpanDebugView.cs b/src/System.Private.CoreLib/shared/System/SpanDebugView.cs index f79c67306cee..b1613b462bf8 100644 --- a/src/System.Private.CoreLib/shared/System/SpanDebugView.cs +++ b/src/System.Private.CoreLib/shared/System/SpanDebugView.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs index 2aec70409696..165b28fe701c 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs index 4104d93347c0..f13c0c650aa1 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs index 9bf1c57244a7..bfdbc46bfead 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs index d4feba069b40..49f4ff461b61 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; // Do not remove. This is necessary for netstandard, since this file is mirrored into corefx @@ -57,7 +58,7 @@ public unsafe static bool Contains(ref T searchSpace, T value, int length) IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations - if (default(T) != null || (object)value != null) + if (default(T)! != null || (object)value != null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while (length >= 8) { @@ -127,7 +128,7 @@ public static unsafe int IndexOf(ref T searchSpace, T value, int length) Debug.Assert(length >= 0); IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations - if (default(T) != null || (object)value != null) + if (default(T)! != null || (object)value != null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while (length >= 8) { @@ -216,7 +217,7 @@ public static int IndexOfAny(ref T searchSpace, T value0, T value1, int lengt T lookUp; int index = 0; - if (default(T) != null || ((object)value0 != null && (object)value1 != null)) + if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while ((length - index) >= 8) { @@ -280,9 +281,9 @@ public static int IndexOfAny(ref T searchSpace, T value0, T value1, int lengt for (index = 0; index < length; index++) { lookUp = Unsafe.Add(ref searchSpace, index); - if ((object)lookUp is null) + if ((object?)lookUp is null) { - if ((object)value0 is null || (object)value1 is null) + if ((object?)value0 is null || (object?)value1 is null) { goto Found; } @@ -321,7 +322,7 @@ public static int IndexOfAny(ref T searchSpace, T value0, T value1, T value2, T lookUp; int index = 0; - if (default(T) != null || ((object)value0 != null && (object)value1 != null && (object)value2 != null)) + if (default(T)! != null || ((object)value0 != null && (object)value1 != null && (object)value2 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while ((length - index) >= 8) { @@ -385,9 +386,9 @@ public static int IndexOfAny(ref T searchSpace, T value0, T value1, T value2, for (index = 0; index < length; index++) { lookUp = Unsafe.Add(ref searchSpace, index); - if ((object)lookUp is null) + if ((object?)lookUp is null) { - if ((object)value0 is null || (object)value1 is null || (object)value2 is null) + if ((object?)value0 is null || (object?)value1 is null || (object?)value2 is null) { goto Found; } @@ -484,7 +485,7 @@ public static int LastIndexOf(ref T searchSpace, T value, int length) { Debug.Assert(length >= 0); - if (default(T) != null || (object)value != null) + if (default(T)! != null || (object)value != null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while (length >= 8) { @@ -567,7 +568,7 @@ public static int LastIndexOfAny(ref T searchSpace, T value0, T value1, int l Debug.Assert(length >= 0); T lookUp; - if (default(T) != null || ((object)value0 != null && (object)value1 != null)) + if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while (length >= 8) { @@ -631,9 +632,9 @@ public static int LastIndexOfAny(ref T searchSpace, T value0, T value1, int l for (length--; length >= 0; length--) { lookUp = Unsafe.Add(ref searchSpace, length); - if ((object)lookUp is null) + if ((object?)lookUp is null) { - if ((object)value0 is null || (object)value1 is null) + if ((object?)value0 is null || (object?)value1 is null) { goto Found; } @@ -671,7 +672,7 @@ public static int LastIndexOfAny(ref T searchSpace, T value0, T value1, T val Debug.Assert(length >= 0); T lookUp; - if (default(T) != null || ((object)value0 != null && (object)value1 != null)) + if (default(T)! != null || ((object)value0 != null && (object)value1 != null)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { while (length >= 8) { @@ -735,9 +736,9 @@ public static int LastIndexOfAny(ref T searchSpace, T value0, T value1, T val for (length--; length >= 0; length--) { lookUp = Unsafe.Add(ref searchSpace, length); - if ((object)lookUp is null) + if ((object?)lookUp is null) { - if ((object)value0 is null || (object)value1 is null || (object)value2 is null) + if ((object?)value0 is null || (object?)value1 is null || (object?)value2 is null) { goto Found; } @@ -805,35 +806,35 @@ public static bool SequenceEqual(ref T first, ref T second, int length) lookUp0 = Unsafe.Add(ref first, index); lookUp1 = Unsafe.Add(ref second, index); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 1); lookUp1 = Unsafe.Add(ref second, index + 1); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 2); lookUp1 = Unsafe.Add(ref second, index + 2); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 3); lookUp1 = Unsafe.Add(ref second, index + 3); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 4); lookUp1 = Unsafe.Add(ref second, index + 4); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 5); lookUp1 = Unsafe.Add(ref second, index + 5); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 6); lookUp1 = Unsafe.Add(ref second, index + 6); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 7); lookUp1 = Unsafe.Add(ref second, index + 7); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; index += 8; @@ -845,19 +846,19 @@ public static bool SequenceEqual(ref T first, ref T second, int length) lookUp0 = Unsafe.Add(ref first, index); lookUp1 = Unsafe.Add(ref second, index); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 1); lookUp1 = Unsafe.Add(ref second, index + 1); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 2); lookUp1 = Unsafe.Add(ref second, index + 2); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; lookUp0 = Unsafe.Add(ref first, index + 3); lookUp1 = Unsafe.Add(ref second, index + 3); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; index += 4; @@ -867,7 +868,7 @@ public static bool SequenceEqual(ref T first, ref T second, int length) { lookUp0 = Unsafe.Add(ref first, index); lookUp1 = Unsafe.Add(ref second, index); - if (!(lookUp0?.Equals(lookUp1) ?? (object)lookUp1 is null)) + if (!(lookUp0?.Equals(lookUp1) ?? (object?)lookUp1 is null)) goto NotEqual; index += 1; length--; @@ -892,7 +893,7 @@ public static int SequenceCompareTo(ref T first, int firstLength, ref T secon for (int i = 0; i < minLength; i++) { T lookUp = Unsafe.Add(ref second, i); - int result = (Unsafe.Add(ref first, i)?.CompareTo(lookUp) ?? (((object)lookUp is null) ? 0 : -1)); + int result = (Unsafe.Add(ref first, i)?.CompareTo(lookUp) ?? (((object?)lookUp is null) ? 0 : -1)); if (result != 0) return result; } diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.cs index 9ea42ec39f15..1c32a62b3333 100644 --- a/src/System.Private.CoreLib/shared/System/SpanHelpers.cs +++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime; diff --git a/src/System.Private.CoreLib/shared/System/String.Manipulation.cs b/src/System.Private.CoreLib/shared/System/String.Manipulation.cs index dc7f01591bb0..278a3b6b98a5 100644 --- a/src/System.Private.CoreLib/shared/System/String.Manipulation.cs +++ b/src/System.Private.CoreLib/shared/System/String.Manipulation.cs @@ -1680,20 +1680,6 @@ public string Substring(int startIndex, int length) return InternalSubString(startIndex, length); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string Substring(Index startIndex) - { - int actualIndex = startIndex.GetOffset(Length); - return Substring(actualIndex); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string Substring(Range range) - { - (int start, int length) = range.GetOffsetAndLength(Length); - return Substring(start, length); - } - private unsafe string InternalSubString(int startIndex, int length) { Debug.Assert(startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!"); diff --git a/src/System.Private.CoreLib/shared/System/String.cs b/src/System.Private.CoreLib/shared/System/String.cs index 3ae88bbe8119..3701434defa1 100644 --- a/src/System.Private.CoreLib/shared/System/String.cs +++ b/src/System.Private.CoreLib/shared/System/String.cs @@ -448,19 +448,6 @@ public static bool IsNullOrEmpty(string? value) return (value == null || 0u >= (uint)value.Length) ? true : false; } - [System.Runtime.CompilerServices.IndexerName("Chars")] - public char this[Index index] - { - get - { - int actualIndex = index.GetOffset(Length); - return this[actualIndex]; - } - } - - [System.Runtime.CompilerServices.IndexerName("Chars")] - public string this[Range range] => Substring(range); - public static bool IsNullOrWhiteSpace(string? value) { if (value == null) return true; diff --git a/src/System.Private.CoreLib/shared/System/StringComparer.cs b/src/System.Private.CoreLib/shared/System/StringComparer.cs index 8fab8335929d..4ffb83876d28 100644 --- a/src/System.Private.CoreLib/shared/System/StringComparer.cs +++ b/src/System.Private.CoreLib/shared/System/StringComparer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Globalization; @@ -11,7 +12,7 @@ namespace System { [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public abstract class StringComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer + public abstract class StringComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer { private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, CompareOptions.None); private static readonly CultureAwareComparer s_invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, CompareOptions.IgnoreCase); @@ -108,7 +109,7 @@ public static StringComparer Create(CultureInfo culture, CompareOptions options) return new CultureAwareComparer(culture, options); } - public int Compare(object x, object y) + public int Compare(object? x, object? y) { if (x == y) return 0; if (x == null) return -1; @@ -130,7 +131,7 @@ public int Compare(object x, object y) throw new ArgumentException(SR.Argument_ImplementIComparable); } - public new bool Equals(object x, object y) + public new bool Equals(object? x, object? y) { if (x == y) return true; if (x == null || y == null) return false; @@ -159,9 +160,9 @@ public int GetHashCode(object obj) return obj.GetHashCode(); } - public abstract int Compare(string x, string y); - public abstract bool Equals(string x, string y); - public abstract int GetHashCode(string obj); + public abstract int Compare(string? x, string? y); + public abstract bool Equals(string? x, string? y); + public abstract int GetHashCode(string? obj); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 } [Serializable] @@ -188,7 +189,7 @@ internal CultureAwareComparer(CompareInfo compareInfo, CompareOptions options) private CultureAwareComparer(SerializationInfo info, StreamingContext context) { - _compareInfo = (CompareInfo)info.GetValue("_compareInfo", typeof(CompareInfo)); + _compareInfo = (CompareInfo)info.GetValue("_compareInfo", typeof(CompareInfo))!; bool ignoreCase = info.GetBoolean("_ignoreCase"); var obj = info.GetValueNoThrow("_options", typeof(CompareOptions)); @@ -199,7 +200,7 @@ private CultureAwareComparer(SerializationInfo info, StreamingContext context) _options |= ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None; } - public override int Compare(string x, string y) + public override int Compare(string? x, string? y) { if (object.ReferenceEquals(x, y)) return 0; if (x == null) return -1; @@ -207,14 +208,14 @@ public override int Compare(string x, string y) return _compareInfo.Compare(x, y, _options); } - public override bool Equals(string x, string y) + public override bool Equals(string? x, string? y) { if (object.ReferenceEquals(x, y)) return true; if (x == null || y == null) return false; return _compareInfo.Compare(x, y, _options) == 0; } - public override int GetHashCode(string obj) + public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { if (obj == null) { @@ -224,7 +225,7 @@ public override int GetHashCode(string obj) } // Equals method for the comparer itself. - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is CultureAwareComparer comparer && @@ -256,7 +257,7 @@ internal OrdinalComparer(bool ignoreCase) _ignoreCase = ignoreCase; } - public override int Compare(string x, string y) + public override int Compare(string? x, string? y) { if (ReferenceEquals(x, y)) return 0; @@ -273,7 +274,7 @@ public override int Compare(string x, string y) return string.CompareOrdinal(x, y); } - public override bool Equals(string x, string y) + public override bool Equals(string? x, string? y) { if (ReferenceEquals(x, y)) return true; @@ -291,7 +292,7 @@ public override bool Equals(string x, string y) return x.Equals(y); } - public override int GetHashCode(string obj) + public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { if (obj == null) { @@ -300,14 +301,14 @@ public override int GetHashCode(string obj) if (_ignoreCase) { - return obj.GetHashCodeOrdinalIgnoreCase(); + return obj!.GetHashCodeOrdinalIgnoreCase(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } - return obj.GetHashCode(); + return obj!.GetHashCode(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } // Equals method for the comparer itself. - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is OrdinalComparer comparer)) { @@ -330,17 +331,17 @@ public OrdinalCaseSensitiveComparer() : base(false) { } - public override int Compare(string x, string y) => string.CompareOrdinal(x, y); + public override int Compare(string? x, string? y) => string.CompareOrdinal(x, y); - public override bool Equals(string x, string y) => string.Equals(x, y); + public override bool Equals(string? x, string? y) => string.Equals(x, y); - public override int GetHashCode(string obj) + public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { if (obj == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj); } - return obj.GetHashCode(); + return obj!.GetHashCode(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public void GetObjectData(SerializationInfo info, StreamingContext context) @@ -357,9 +358,9 @@ public OrdinalIgnoreCaseComparer() : base(true) { } - public override int Compare(string x, string y) => string.Compare(x, y, StringComparison.OrdinalIgnoreCase); + public override int Compare(string? x, string? y) => string.Compare(x, y, StringComparison.OrdinalIgnoreCase); - public override bool Equals(string x, string y) + public override bool Equals(string? x, string? y) { if (ReferenceEquals(x, y)) { @@ -379,13 +380,13 @@ public override bool Equals(string x, string y) return CompareInfo.EqualsOrdinalIgnoreCase(ref x.GetRawStringData(), ref y.GetRawStringData(), x.Length); } - public override int GetHashCode(string obj) + public override int GetHashCode(string? obj) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { if (obj == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj); } - return obj.GetHashCodeOrdinalIgnoreCase(); + return obj!.GetHashCodeOrdinalIgnoreCase(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/System.Private.CoreLib/shared/System/StringComparison.cs b/src/System.Private.CoreLib/shared/System/StringComparison.cs index d5c18c8021e5..3f31f33a41b3 100644 --- a/src/System.Private.CoreLib/shared/System/StringComparison.cs +++ b/src/System.Private.CoreLib/shared/System/StringComparison.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public enum StringComparison diff --git a/src/System.Private.CoreLib/shared/System/StringSplitOptions.cs b/src/System.Private.CoreLib/shared/System/StringSplitOptions.cs index d7020559a1d1..31328365b8f4 100644 --- a/src/System.Private.CoreLib/shared/System/StringSplitOptions.cs +++ b/src/System.Private.CoreLib/shared/System/StringSplitOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { [Flags] diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs index 8cf1f57ccb10..296e0ea09593 100644 --- a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -90,7 +91,7 @@ public override unsafe int GetByteCount(char[] chars, int index, int count) ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - if (chars.Length - index < count) + if (chars!.Length - index < count) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); } @@ -117,7 +118,7 @@ public override unsafe int GetByteCount(string chars) fixed (char* pChars = chars) { - return GetByteCountCommon(pChars, chars.Length); + return GetByteCountCommon(pChars, chars!.Length); } } @@ -159,7 +160,7 @@ private unsafe int GetByteCountCommon(char* pChars, int charCount) // Common helper method for all non-EncoderNLS entry points to GetByteCount. // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. - Debug.Assert(charCount >= 0, "Caller should't specify negative length buffer."); + Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer."); Debug.Assert(pChars != null || charCount == 0, "Input pointer shouldn't be null if non-zero length specified."); // First call into the fast path. @@ -183,7 +184,7 @@ private unsafe int GetByteCountCommon(char* pChars, int charCount) } [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetByteCountCommon - private protected sealed override unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback fallback, out int charsConsumed) + private protected sealed override unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback? fallback, out int charsConsumed) { // First: Can we short-circuit the entire calculation? // If an EncoderReplacementFallback is in use, all non-ASCII chars @@ -230,12 +231,12 @@ public override unsafe int GetBytes(string chars, int charIndex, int charCount, resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - if (chars.Length - charIndex < charCount) + if (chars!.Length - charIndex < charCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCount); } - if ((uint)byteIndex > bytes.Length) + if ((uint)byteIndex > bytes!.Length) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutOfRange_Index); } @@ -280,12 +281,12 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - if (chars.Length - charIndex < charCount) + if (chars!.Length - charIndex < charCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCount); } - if ((uint)byteIndex > bytes.Length) + if ((uint)byteIndex > bytes!.Length) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutOfRange_Index); } @@ -340,9 +341,9 @@ private unsafe int GetBytesCommon(char* pChars, int charCount, byte* pBytes, int // Common helper method for all non-EncoderNLS entry points to GetBytes. // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. - Debug.Assert(charCount >= 0, "Caller should't specify negative length buffer."); + Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer."); Debug.Assert(pChars != null || charCount == 0, "Input pointer shouldn't be null if non-zero length specified."); - Debug.Assert(byteCount >= 0, "Caller should't specify negative length buffer."); + Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer."); Debug.Assert(pBytes != null || byteCount == 0, "Input pointer shouldn't be null if non-zero length specified."); // First call into the fast path. @@ -372,7 +373,7 @@ private protected sealed override unsafe int GetBytesFast(char* pChars, int char return bytesWritten; } - private protected sealed override unsafe int GetBytesWithFallback(ReadOnlySpan chars, int originalCharsLength, Span bytes, int originalBytesLength, EncoderNLS encoder) + private protected sealed override unsafe int GetBytesWithFallback(ReadOnlySpan chars, int originalCharsLength, Span bytes, int originalBytesLength, EncoderNLS? encoder) { // We special-case EncoderReplacementFallback if it's telling us to write a single ASCII char, // since we believe this to be relatively common and we can handle it more efficiently than @@ -447,7 +448,7 @@ public override unsafe int GetCharCount(byte[] bytes, int index, int count) ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - if (bytes.Length - index < count) + if (bytes!.Length - index < count) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); } @@ -496,7 +497,7 @@ private unsafe int GetCharCountCommon(byte* pBytes, int byteCount) // Common helper method for all non-DecoderNLS entry points to GetCharCount. // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. - Debug.Assert(byteCount >= 0, "Caller should't specify negative length buffer."); + Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer."); Debug.Assert(pBytes != null || byteCount == 0, "Input pointer shouldn't be null if non-zero length specified."); // First call into the fast path. @@ -520,7 +521,7 @@ private unsafe int GetCharCountCommon(byte* pBytes, int byteCount) } [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharCountCommon - private protected sealed override unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback fallback, out int bytesConsumed) + private protected sealed override unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback? fallback, out int bytesConsumed) { // First: Can we short-circuit the entire calculation? // If a DecoderReplacementFallback is in use, all non-ASCII bytes are replaced with @@ -564,12 +565,12 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - if (bytes.Length - byteIndex < byteCount) + if (bytes!.Length - byteIndex < byteCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); } - if ((uint)charIndex > (uint)chars.Length) + if ((uint)charIndex > (uint)chars!.Length) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.charIndex, ExceptionResource.ArgumentOutOfRange_Index); } @@ -624,9 +625,9 @@ private unsafe int GetCharsCommon(byte* pBytes, int byteCount, char* pChars, int // Common helper method for all non-DecoderNLS entry points to GetChars. // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. - Debug.Assert(byteCount >= 0, "Caller should't specify negative length buffer."); + Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer."); Debug.Assert(pBytes != null || byteCount == 0, "Input pointer shouldn't be null if non-zero length specified."); - Debug.Assert(charCount >= 0, "Caller should't specify negative length buffer."); + Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer."); Debug.Assert(pChars != null || charCount == 0, "Input pointer shouldn't be null if non-zero length specified."); // First call into the fast path. @@ -656,7 +657,7 @@ private protected sealed override unsafe int GetCharsFast(byte* pBytes, int byte return charsWritten; } - private protected sealed override unsafe int GetCharsWithFallback(ReadOnlySpan bytes, int originalBytesLength, Span chars, int originalCharsLength, DecoderNLS decoder) + private protected sealed override unsafe int GetCharsWithFallback(ReadOnlySpan bytes, int originalBytesLength, Span chars, int originalCharsLength, DecoderNLS? decoder) { // We special-case DecoderReplacementFallback if it's telling us to write a single BMP char, // since we believe this to be relatively common and we can handle it more efficiently than @@ -732,7 +733,7 @@ public override unsafe string GetString(byte[] bytes, int byteIndex, int byteCou resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - if (bytes.Length - byteIndex < byteCount) + if (bytes!.Length - byteIndex < byteCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); } diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.Helpers.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.Helpers.cs new file mode 100644 index 000000000000..1b53d94aaa7f --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.Helpers.cs @@ -0,0 +1,109 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.X86; + +namespace System.Text +{ + internal static partial class ASCIIUtility + { + /// + /// A mask which selects only the high bit of each byte of the given . + /// + private const uint UInt32HighBitsOnlyMask = 0x80808080u; + + /// + /// A mask which selects only the high bit of each byte of the given . + /// + private const ulong UInt64HighBitsOnlyMask = 0x80808080_80808080ul; + + /// + /// Returns iff all bytes in are ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool AllBytesInUInt32AreAscii(uint value) + { + // If the high bit of any byte is set, that byte is non-ASCII. + + return (value & UInt32HighBitsOnlyMask) == 0; + } + + /// + /// Given a DWORD which represents a four-byte buffer read in machine endianness, and which + /// the caller has asserted contains a non-ASCII byte *somewhere* in the data, counts the + /// number of consecutive ASCII bytes starting from the beginning of the buffer. Returns + /// a value 0 - 3, inclusive. (The caller is responsible for ensuring that the buffer doesn't + /// contain all-ASCII data.) + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static uint CountNumberOfLeadingAsciiBytesFromUInt32WithSomeNonAsciiData(uint value) + { + Debug.Assert(!AllBytesInUInt32AreAscii(value), "Caller shouldn't provide an all-ASCII value."); + + // Use BMI1 directly rather than going through BitOperations. We only see a perf gain here + // if we're able to emit a real tzcnt instruction; the software fallback used by BitOperations + // is too slow for our purposes since we can provide our own faster, specialized software fallback. + + if (Bmi1.IsSupported) + { + Debug.Assert(BitConverter.IsLittleEndian); + return Bmi1.TrailingZeroCount(value & UInt32HighBitsOnlyMask) >> 3; + } + + // Couldn't emit tzcnt, use specialized software fallback. + // The 'allBytesUpToNowAreAscii' DWORD uses bit twiddling to hold a 1 or a 0 depending + // on whether all processed bytes were ASCII. Then we accumulate all of the + // results to calculate how many consecutive ASCII bytes are present. + + value = ~value; + + if (BitConverter.IsLittleEndian) + { + // Read first byte + value >>= 7; + uint allBytesUpToNowAreAscii = value & 1; + uint numAsciiBytes = allBytesUpToNowAreAscii; + + // Read second byte + value >>= 8; + allBytesUpToNowAreAscii &= value; + numAsciiBytes += allBytesUpToNowAreAscii; + + // Read third byte + value >>= 8; + allBytesUpToNowAreAscii &= value; + numAsciiBytes += allBytesUpToNowAreAscii; + + return numAsciiBytes; + } + else + { + // BinaryPrimitives.ReverseEndianness is only implemented as an intrinsic on + // little-endian platforms, so using it in this big-endian path would be too + // expensive. Instead we'll just change how we perform the shifts. + + // Read first byte + value = BitOperations.RotateLeft(value, 1); + uint allBytesUpToNowAreAscii = value & 1; + uint numAsciiBytes = allBytesUpToNowAreAscii; + + // Read second byte + value = BitOperations.RotateLeft(value, 8); + allBytesUpToNowAreAscii &= value; + numAsciiBytes += allBytesUpToNowAreAscii; + + // Read third byte + value = BitOperations.RotateLeft(value, 8); + allBytesUpToNowAreAscii &= value; + numAsciiBytes += allBytesUpToNowAreAscii; + + return numAsciiBytes; + } + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs index 755f92561033..87b742f678ad 100644 --- a/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs +++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIUtility.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; @@ -21,19 +22,20 @@ namespace System.Text { internal static partial class ASCIIUtility { - /// - /// Returns iff all bytes in are ASCII. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool AllBytesInUInt32AreAscii(uint value) +#if DEBUG + static ASCIIUtility() { - return ((value & 0x80808080u) == 0); + Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); + Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); } +#endif // DEBUG [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool AllBytesInUInt64AreAscii(ulong value) { - return ((value & 0x80808080_80808080ul) == 0); + // If the high bit of any byte is set, that byte is non-ASCII. + + return ((value & UInt64HighBitsOnlyMask) == 0); } /// @@ -54,56 +56,6 @@ private static bool AllCharsInUInt64AreAscii(ulong value) return ((value & ~0x007F007F_007F007Ful) == 0); } - /// - /// Given a 24-bit integer which represents a three-byte buffer read in machine endianness, - /// counts the number of consecutive ASCII bytes starting from the beginning of the buffer. - /// Returns a value 0 - 3, inclusive. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint CountNumberOfLeadingAsciiBytesFrom24BitInteger(uint value) - { - // This implementation seems to have better performance than tzcnt. - - // The 'allBytesUpToNowAreAscii' DWORD uses bit twiddling to hold a 1 or a 0 depending - // on whether all processed bytes were ASCII. Then we accumulate all of the - // results to calculate how many consecutive ASCII bytes are present. - - value = ~value; - - if (BitConverter.IsLittleEndian) - { - // Read first byte - uint allBytesUpToNowAreAscii = (value >>= 7) & 1; - uint numAsciiBytes = allBytesUpToNowAreAscii; - - // Read second byte - allBytesUpToNowAreAscii &= (value >>= 8); - numAsciiBytes += allBytesUpToNowAreAscii; - - // Read third byte - allBytesUpToNowAreAscii &= (value >>= 8); - numAsciiBytes += allBytesUpToNowAreAscii; - - return numAsciiBytes; - } - else - { - // Read first byte - uint allBytesUpToNowAreAscii = (value = ROL32(value, 1)) & 1; - uint numAsciiBytes = allBytesUpToNowAreAscii; - - // Read second byte - allBytesUpToNowAreAscii &= (value = ROL32(value, 8)); - numAsciiBytes += allBytesUpToNowAreAscii; - - // Read third byte - allBytesUpToNowAreAscii &= (value = ROL32(value, 8)); - numAsciiBytes += allBytesUpToNowAreAscii; - - return numAsciiBytes; - } - } - /// /// Given a DWORD which represents two packed chars in machine-endian order, /// iff the first char (in machine-endian order) is ASCII. @@ -273,7 +225,7 @@ private static unsafe nuint GetIndexOfFirstNonAsciiByte_Default(byte* pBuffer, n // we get to the high byte; or (b) all of the earlier bytes are ASCII, so the high byte must be // non-ASCII. In both cases we only care about the low 24 bits. - pBuffer += CountNumberOfLeadingAsciiBytesFrom24BitInteger(currentUInt32); + pBuffer += CountNumberOfLeadingAsciiBytesFromUInt32WithSomeNonAsciiData(currentUInt32); goto Finish; } @@ -435,7 +387,7 @@ private static unsafe nuint GetIndexOfFirstNonAsciiByte_Sse2(byte* pBuffer, nuin uint currentDWord; Debug.Assert(!AllBytesInUInt32AreAscii(currentDWord), "Shouldn't be here unless we see non-ASCII data."); - pBuffer += CountNumberOfLeadingAsciiBytesFrom24BitInteger(currentDWord); + pBuffer += CountNumberOfLeadingAsciiBytesFromUInt32WithSomeNonAsciiData(currentDWord); goto Finish; @@ -461,7 +413,7 @@ private static unsafe nuint GetIndexOfFirstNonAsciiByte_Sse2(byte* pBuffer, nuin // Clear everything but the high bit of each byte, then tzcnt. // Remember the / 8 at the end to convert bit count to byte count. - candidateUInt64 &= 0x80808080_80808080ul; + candidateUInt64 &= UInt64HighBitsOnlyMask; pBuffer += (nuint)(Bmi1.X64.TrailingZeroCount(candidateUInt64) / 8); goto Finish; } @@ -1395,17 +1347,7 @@ private static unsafe nuint NarrowUtf16ToAscii_Sse2(char* pUtf16Buffer, byte* pA // Turn the 8 ASCII chars we just read into 8 ASCII bytes, then copy it to the destination. Vector128 asciiVector = Sse2.PackUnsignedSaturate(utf16VectorFirst, utf16VectorFirst); - - if (Sse41.X64.IsSupported) - { - // Use PEXTRQ instruction if available, since it can extract from the vector directly to the destination address. - Unsafe.WriteUnaligned(pAsciiBuffer, Sse41.X64.Extract(asciiVector.AsUInt64(), 0)); - } - else - { - // Bounce this through a temporary register (with potential stack spillage) before writing to memory. - Unsafe.WriteUnaligned(pAsciiBuffer, asciiVector.AsUInt64().GetElement(0)); - } + Sse2.StoreLow((ulong*)pAsciiBuffer, asciiVector.AsUInt64()); // ulong* calculated here is UNALIGNED nuint currentOffsetInElements = SizeOfVector128 / 2; // we processed 8 elements so far @@ -1444,16 +1386,7 @@ private static unsafe nuint NarrowUtf16ToAscii_Sse2(char* pUtf16Buffer, byte* pA // Turn the 8 ASCII chars we just read into 8 ASCII bytes, then copy it to the destination. asciiVector = Sse2.PackUnsignedSaturate(utf16VectorFirst, utf16VectorFirst); - - // See comments earlier in this method for information about how this works. - if (Sse41.X64.IsSupported) - { - Unsafe.WriteUnaligned(pAsciiBuffer + currentOffsetInElements, Sse41.X64.Extract(asciiVector.AsUInt64(), 0)); - } - else - { - Unsafe.WriteUnaligned(pAsciiBuffer + currentOffsetInElements, asciiVector.AsUInt64().GetElement(0)); - } + Sse2.StoreLow((ulong*)(pAsciiBuffer + currentOffsetInElements), asciiVector.AsUInt64()); // ulong* calculated here is UNALIGNED } // Calculate how many elements we wrote in order to get pAsciiBuffer to its next alignment @@ -1529,26 +1462,12 @@ private static unsafe nuint NarrowUtf16ToAscii_Sse2(char* pUtf16Buffer, byte* pA Debug.Assert(((nuint)pAsciiBuffer + currentOffsetInElements) % sizeof(ulong) == 0, "Destination should be ulong-aligned."); - // See comments earlier in this method for information about how this works. - if (Sse41.X64.IsSupported) - { - *(ulong*)(pAsciiBuffer + currentOffsetInElements) = Sse41.X64.Extract(asciiVector.AsUInt64(), 0); - } - else - { - *(ulong*)(pAsciiBuffer + currentOffsetInElements) = asciiVector.AsUInt64().GetElement(0); - } + Sse2.StoreLow((ulong*)(pAsciiBuffer + currentOffsetInElements), asciiVector.AsUInt64()); // ulong* calculated here is aligned currentOffsetInElements += SizeOfVector128 / 2; goto Finish; } - /// - /// Rotates a left. The JIT is smart enough to turn this into a ROL / ROR instruction. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ROL32(uint value, int shift) => (value << shift) | (value >> (32 - shift)); - /// /// Copies as many ASCII bytes (00..7F) as possible from /// to , stopping when the first non-ASCII byte is encountered diff --git a/src/System.Private.CoreLib/shared/System/Text/CodePageDataItem.cs b/src/System.Private.CoreLib/shared/System/Text/CodePageDataItem.cs index e4b8d4d73020..cb796ff1a171 100644 --- a/src/System.Private.CoreLib/shared/System/Text/CodePageDataItem.cs +++ b/src/System.Private.CoreLib/shared/System/Text/CodePageDataItem.cs @@ -2,25 +2,26 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Text { internal class CodePageDataItem { public int CodePage { get; } public int UIFamilyCodePage { get; } - public string WebName { get; } - public string HeaderName { get; } - public string BodyName { get; } - public string DisplayName { get; } + public string? WebName { get; } + public string? HeaderName { get; } + public string? BodyName { get; } + public string? DisplayName { get; } public uint Flags { get; } internal CodePageDataItem( int codePage, int uiFamilyCodePage, - string webName, - string headerName, - string bodyName, - string displayName, + string? webName, + string? headerName, + string? bodyName, + string? displayName, uint flags) { CodePage = codePage; diff --git a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs index b4a7575ba685..9197e4c09ce3 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System; using System.Diagnostics; @@ -22,16 +23,16 @@ namespace System.Text // public abstract class Decoder { - internal DecoderFallback _fallback = null; + internal DecoderFallback? _fallback = null; - internal DecoderFallbackBuffer _fallbackBuffer = null; + internal DecoderFallbackBuffer? _fallbackBuffer = null; protected Decoder() { // We don't call default reset because default reset probably isn't good if we aren't initialized. } - public DecoderFallback Fallback + public DecoderFallback? Fallback { get { diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs index d94554c6fd0a..3387a091896b 100644 --- a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // // This is used internally to create best fit behavior as per the original windows best fit behavior. // @@ -14,8 +15,8 @@ namespace System.Text internal sealed class InternalDecoderBestFitFallback : DecoderFallback { // Our variables - internal Encoding _encoding = null; - internal char[] _arrayBestFit = null; + internal Encoding _encoding; + internal char[]? _arrayBestFit = null; internal char _cReplacement = '?'; internal InternalDecoderBestFitFallback(Encoding encoding) @@ -38,13 +39,13 @@ public override int MaxCharCount } } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is InternalDecoderBestFitFallback that) { - return (_encoding.CodePage == that._encoding.CodePage); + return _encoding.CodePage == that._encoding.CodePage; } - return (false); + return false; } public override int GetHashCode() @@ -62,7 +63,7 @@ internal sealed class InternalDecoderBestFitFallbackBuffer : DecoderFallbackBuff private InternalDecoderBestFitFallback _oFallback; // Private object for locking instead of locking on a public type for SQL reliability work. - private static object s_InternalSyncObject; + private static object? s_InternalSyncObject; private static object InternalSyncObject { get @@ -70,9 +71,9 @@ private static object InternalSyncObject if (s_InternalSyncObject == null) { object o = new object(); - Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); + Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); } - return s_InternalSyncObject; + return s_InternalSyncObject!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -172,6 +173,7 @@ private char TryBestFit(byte[] bytesCheck) { // Need to figure out our best fit character, low is beginning of array, high is 1 AFTER end of array int lowBound = 0; + Debug.Assert(_oFallback._arrayBestFit != null); int highBound = _oFallback._arrayBestFit.Length; int index; char cCheck; diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs index 0525861a5bb1..450ba3212acd 100644 --- a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Globalization; using System.Runtime.Serialization; @@ -29,7 +30,7 @@ public override int MaxCharCount } } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is DecoderExceptionFallback that) { @@ -75,6 +76,8 @@ public override int Remaining private void Throw(byte[] bytesUnknown, int index) { + bytesUnknown = bytesUnknown ?? Array.Empty(); + // Create a string representation of our bytes. StringBuilder strBytes = new StringBuilder(bytesUnknown.Length * 3); @@ -102,7 +105,7 @@ private void Throw(byte[] bytesUnknown, int index) [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class DecoderFallbackException : ArgumentException { - private byte[] _bytesUnknown = null; + private byte[]? _bytesUnknown = null; private int _index = 0; public DecoderFallbackException() @@ -111,19 +114,19 @@ public DecoderFallbackException() HResult = HResults.COR_E_ARGUMENT; } - public DecoderFallbackException(string message) + public DecoderFallbackException(string? message) : base(message) { HResult = HResults.COR_E_ARGUMENT; } - public DecoderFallbackException(string message, Exception innerException) + public DecoderFallbackException(string? message, Exception? innerException) : base(message, innerException) { HResult = HResults.COR_E_ARGUMENT; } - public DecoderFallbackException(string message, byte[] bytesUnknown, int index) + public DecoderFallbackException(string? message, byte[]? bytesUnknown, int index) : base(message) { _bytesUnknown = bytesUnknown; @@ -135,11 +138,11 @@ private DecoderFallbackException(SerializationInfo serializationInfo, StreamingC { } - public byte[] BytesUnknown + public byte[]? BytesUnknown { get { - return (_bytesUnknown); + return _bytesUnknown; } } diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs index d5782d58e43f..77730c214c8c 100644 --- a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Globalization; using System.Threading; @@ -10,15 +11,15 @@ namespace System.Text { public abstract class DecoderFallback { - private static DecoderFallback s_replacementFallback; // Default fallback, uses no best fit & "?" - private static DecoderFallback s_exceptionFallback; + private static DecoderFallback? s_replacementFallback; // Default fallback, uses no best fit & "?" + private static DecoderFallback? s_exceptionFallback; public static DecoderFallback ReplacementFallback => - s_replacementFallback ?? Interlocked.CompareExchange(ref s_replacementFallback, new DecoderReplacementFallback(), null) ?? s_replacementFallback; + s_replacementFallback ?? Interlocked.CompareExchange(ref s_replacementFallback, new DecoderReplacementFallback(), null) ?? s_replacementFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 public static DecoderFallback ExceptionFallback => - s_exceptionFallback ?? Interlocked.CompareExchange(ref s_exceptionFallback, new DecoderExceptionFallback(), null) ?? s_exceptionFallback; + s_exceptionFallback ?? Interlocked.CompareExchange(ref s_exceptionFallback, new DecoderExceptionFallback(), null) ?? s_exceptionFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 // Fallback // @@ -67,8 +68,8 @@ public virtual void Reset() internal unsafe byte* byteStart; internal unsafe char* charEnd; - internal Encoding _encoding; - internal DecoderNLS _decoder; + internal Encoding? _encoding; + internal DecoderNLS? _decoder; private int _originalByteCount; // Internal Reset @@ -86,7 +87,7 @@ internal unsafe void InternalInitialize(byte* byteStart, char* charEnd) this.charEnd = charEnd; } - internal static DecoderFallbackBuffer CreateAndInitialize(Encoding encoding, DecoderNLS decoder, int originalByteCount) + internal static DecoderFallbackBuffer CreateAndInitialize(Encoding encoding, DecoderNLS? decoder, int originalByteCount) { // The original byte count is only used for keeping track of what 'index' value needs // to be passed to the abstract Fallback method. The index value is calculated by subtracting @@ -298,6 +299,8 @@ internal bool TryDrainRemainingDataForGetChars(Span chars, out int charsWr // private helper methods internal void ThrowLastBytesRecursive(byte[] bytesUnknown) { + bytesUnknown = bytesUnknown ?? Array.Empty(); + // Create a string representation of our bytes. StringBuilder strBytes = new StringBuilder(bytesUnknown.Length * 3); int i; diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs index 9040a94f0f6d..a84b607ea297 100644 --- a/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs +++ b/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.InteropServices; @@ -36,13 +37,6 @@ internal DecoderNLS(Encoding encoding) this.Reset(); } - // This is used by our child deserializers - internal DecoderNLS() - { - _encoding = null; - this.Reset(); - } - public override void Reset() { ClearLeftoverData(); @@ -90,6 +84,7 @@ public unsafe override int GetCharCount(byte* bytes, int count, bool flush) _throwOnOverflow = true; // By default just call the encoding version, no flush by default + Debug.Assert(_encoding != null); return _encoding.GetCharCount(bytes, count, this); } @@ -146,6 +141,7 @@ public unsafe override int GetChars(byte* bytes, int byteCount, _throwOnOverflow = true; // By default just call the encodings version + Debug.Assert(_encoding != null); return _encoding.GetChars(bytes, byteCount, chars, charCount, this); } @@ -208,6 +204,7 @@ public unsafe override void Convert(byte* bytes, int byteCount, _bytesUsed = 0; // Do conversion + Debug.Assert(_encoding != null); charsUsed = _encoding.GetChars(bytes, byteCount, chars, charCount, this); bytesUsed = _bytesUsed; @@ -266,6 +263,7 @@ internal int DrainLeftoverDataForGetCharCount(ReadOnlySpan bytes, out int // to be in progress. Unlike EncoderNLS, this is simply a Debug.Assert. No exception is thrown. Debug.Assert(_fallbackBuffer is null || _fallbackBuffer.Remaining == 0, "Should have no data remaining in the fallback buffer."); + Debug.Assert(HasLeftoverData, "Caller shouldn't invoke this routine unless there's leftover data in the decoder."); // Copy the existing leftover data plus as many bytes as possible of the new incoming data // into a temporary concated buffer, then get its char count by decoding it. @@ -274,6 +272,7 @@ internal int DrainLeftoverDataForGetCharCount(ReadOnlySpan bytes, out int combinedBuffer = combinedBuffer.Slice(0, ConcatInto(GetLeftoverData(), bytes, combinedBuffer)); int charCount = 0; + Debug.Assert(_encoding != null); switch (_encoding.DecodeFirstRune(combinedBuffer, out Rune value, out int combinedBufferBytesConsumed)) { case OperationStatus.Done: @@ -302,7 +301,7 @@ internal int DrainLeftoverDataForGetCharCount(ReadOnlySpan bytes, out int if (FallbackBuffer.Fallback(combinedBuffer.Slice(0, combinedBufferBytesConsumed).ToArray(), index: 0)) { - charCount = _fallbackBuffer.DrainRemainingDataForGetCharCount(); + charCount = _fallbackBuffer!.DrainRemainingDataForGetCharCount(); Debug.Assert(charCount >= 0, "Fallback buffer shouldn't have returned a negative char count."); } @@ -319,6 +318,7 @@ internal int DrainLeftoverDataForGetChars(ReadOnlySpan bytes, Span c // to be in progress. Unlike EncoderNLS, this is simply a Debug.Assert. No exception is thrown. Debug.Assert(_fallbackBuffer is null || _fallbackBuffer.Remaining == 0, "Should have no data remaining in the fallback buffer."); + Debug.Assert(HasLeftoverData, "Caller shouldn't invoke this routine unless there's leftover data in the decoder."); // Copy the existing leftover data plus as many bytes as possible of the new incoming data // into a temporary concated buffer, then transcode it from bytes to chars. @@ -329,6 +329,7 @@ internal int DrainLeftoverDataForGetChars(ReadOnlySpan bytes, Span c bool persistNewCombinedBuffer = false; + Debug.Assert(_encoding != null); switch (_encoding.DecodeFirstRune(combinedBuffer, out Rune value, out int combinedBufferBytesConsumed)) { case OperationStatus.Done: @@ -363,13 +364,21 @@ internal int DrainLeftoverDataForGetChars(ReadOnlySpan bytes, Span c // Couldn't decode the buffer. Fallback the buffer instead. if (FallbackBuffer.Fallback(combinedBuffer.Slice(0, combinedBufferBytesConsumed).ToArray(), index: 0) - && !_fallbackBuffer.TryDrainRemainingDataForGetChars(chars, out charsWritten)) + && !_fallbackBuffer!.TryDrainRemainingDataForGetChars(chars, out charsWritten)) { goto DestinationTooSmall; } Finish: + // Report back the number of bytes (from the new incoming span) we consumed just now. + // This calculation is simple: it's the difference between the original leftover byte + // count and the number of bytes from the combined buffer we needed to decode the first + // scalar value. We need to report this before the call to SetLeftoverData / + // ClearLeftoverData because those methods will overwrite the _leftoverByteCount field. + + bytesConsumed = combinedBufferBytesConsumed - _leftoverByteCount; + if (persistNewCombinedBuffer) { Debug.Assert(combinedBufferBytesConsumed == combinedBuffer.Length, "We should be asked to persist the entire combined buffer."); @@ -380,7 +389,6 @@ internal int DrainLeftoverDataForGetChars(ReadOnlySpan bytes, Span c ClearLeftoverData(); // the buffer contains no partial data; we'll go down the normal paths } - bytesConsumed = combinedBufferBytesConsumed - _leftoverByteCount; // amount of 'bytes' buffer consumed just now return charsWritten; DestinationTooSmall: @@ -391,7 +399,8 @@ internal int DrainLeftoverDataForGetChars(ReadOnlySpan bytes, Span c // opportunity for any code before us to make forward progress, so we must fail immediately. _encoding.ThrowCharsOverflow(this, nothingDecoded: true); - throw null; // will never reach this point + // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + throw null!; // will never reach this point } /// diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs index 2af0d12535f1..2bfb4b0e3201 100644 --- a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Text @@ -82,13 +83,13 @@ public override int MaxCharCount } } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is DecoderReplacementFallback that) { - return (_strDefault == that._strDefault); + return _strDefault == that._strDefault; } - return (false); + return false; } public override int GetHashCode() @@ -109,6 +110,7 @@ public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer // Construction public DecoderReplacementFallbackBuffer(DecoderReplacementFallback fallback) { + // TODO-NULLABLE: NullReferenceException (fallback) _strDefault = fallback.DefaultString; } diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs index df7d51203ffe..77874ce7101e 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System; using System.Diagnostics; @@ -22,16 +23,16 @@ namespace System.Text // public abstract class Encoder { - internal EncoderFallback _fallback = null; + internal EncoderFallback? _fallback = null; - internal EncoderFallbackBuffer _fallbackBuffer = null; + internal EncoderFallbackBuffer? _fallbackBuffer = null; protected Encoder() { // We don't call default reset because default reset probably isn't good if we aren't initialized. } - public EncoderFallback Fallback + public EncoderFallback? Fallback { get { diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs index c3d07c980e8d..363dd5e165f0 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // // This is used internally to create best fit behavior as per the original windows best fit behavior. // @@ -15,8 +16,8 @@ namespace System.Text internal class InternalEncoderBestFitFallback : EncoderFallback { // Our variables - internal Encoding _encoding = null; - internal char[] _arrayBestFit = null; + internal Encoding _encoding; + internal char[]? _arrayBestFit = null; internal InternalEncoderBestFitFallback(Encoding encoding) { @@ -38,13 +39,13 @@ public override int MaxCharCount } } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is InternalEncoderBestFitFallback that) { - return (_encoding.CodePage == that._encoding.CodePage); + return _encoding.CodePage == that._encoding.CodePage; } - return (false); + return false; } public override int GetHashCode() @@ -62,7 +63,7 @@ internal sealed class InternalEncoderBestFitFallbackBuffer : EncoderFallbackBuff private int _iSize; // Private object for locking instead of locking on a public type for SQL reliability work. - private static object s_InternalSyncObject; + private static object? s_InternalSyncObject; private static object InternalSyncObject { get @@ -70,9 +71,9 @@ private static object InternalSyncObject if (s_InternalSyncObject == null) { object o = new object(); - Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); + Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); } - return s_InternalSyncObject; + return s_InternalSyncObject!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -190,6 +191,7 @@ private char TryBestFit(char cUnknown) { // Need to figure out our best fit character, low is beginning of array, high is 1 AFTER end of array int lowBound = 0; + Debug.Assert(_oFallback._arrayBestFit != null); int highBound = _oFallback._arrayBestFit.Length; int index; diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs index 077d92762f67..37df57680446 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.Serialization; @@ -28,13 +29,13 @@ public override int MaxCharCount } } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is EncoderExceptionFallback that) { - return (true); + return true; } - return (false); + return false; } public override int GetHashCode() @@ -110,20 +111,20 @@ public EncoderFallbackException() HResult = HResults.COR_E_ARGUMENT; } - public EncoderFallbackException(string message) + public EncoderFallbackException(string? message) : base(message) { HResult = HResults.COR_E_ARGUMENT; } - public EncoderFallbackException(string message, Exception innerException) + public EncoderFallbackException(string? message, Exception? innerException) : base(message, innerException) { HResult = HResults.COR_E_ARGUMENT; } internal EncoderFallbackException( - string message, char charUnknown, int index) : base(message) + string? message, char charUnknown, int index) : base(message) { _charUnknown = charUnknown; _index = index; @@ -157,7 +158,7 @@ public char CharUnknown { get { - return (_charUnknown); + return _charUnknown; } } @@ -165,7 +166,7 @@ public char CharUnknownHigh { get { - return (_charUnknownHigh); + return _charUnknownHigh; } } @@ -173,7 +174,7 @@ public char CharUnknownLow { get { - return (_charUnknownLow); + return _charUnknownLow; } } @@ -188,7 +189,7 @@ public int Index // Return true if the unknown character is a surrogate pair. public bool IsUnknownSurrogate() { - return (_charUnknownHigh != '\0'); + return _charUnknownHigh != '\0'; } } } diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs index ff895d678879..b1c11270b616 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Threading; @@ -10,8 +11,8 @@ namespace System.Text { public abstract class EncoderFallback { - private static EncoderFallback s_replacementFallback; // Default fallback, uses no best fit & "?" - private static EncoderFallback s_exceptionFallback; + private static EncoderFallback? s_replacementFallback; // Default fallback, uses no best fit & "?" + private static EncoderFallback? s_exceptionFallback; // Get each of our generic fallbacks. @@ -20,9 +21,9 @@ public static EncoderFallback ReplacementFallback get { if (s_replacementFallback == null) - Interlocked.CompareExchange(ref s_replacementFallback, new EncoderReplacementFallback(), null); + Interlocked.CompareExchange(ref s_replacementFallback, new EncoderReplacementFallback(), null); - return s_replacementFallback; + return s_replacementFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -32,9 +33,9 @@ public static EncoderFallback ExceptionFallback get { if (s_exceptionFallback == null) - Interlocked.CompareExchange(ref s_exceptionFallback, new EncoderExceptionFallback(), null); + Interlocked.CompareExchange(ref s_exceptionFallback, new EncoderExceptionFallback(), null); - return s_exceptionFallback; + return s_exceptionFallback!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -87,13 +88,13 @@ public virtual void Reset() // These help us with our performance and messages internally internal unsafe char* charStart; internal unsafe char* charEnd; - internal EncoderNLS encoder; // TODO: MAKE ME PRIVATE + internal EncoderNLS? encoder; // TODO: MAKE ME PRIVATE internal bool setEncoder; internal bool bUsedEncoder; internal bool bFallingBack = false; internal int iRecursionCount = 0; private const int iMaxRecursion = 250; - private Encoding encoding; + private Encoding? encoding; private int originalCharCount; // Internal Reset @@ -108,7 +109,7 @@ internal unsafe void InternalReset() // Set the above values // This can't be part of the constructor because EncoderFallbacks would have to know how to implement these. - internal unsafe void InternalInitialize(char* charStart, char* charEnd, EncoderNLS encoder, bool setEncoder) + internal unsafe void InternalInitialize(char* charStart, char* charEnd, EncoderNLS? encoder, bool setEncoder) { this.charStart = charStart; this.charEnd = charEnd; @@ -119,7 +120,7 @@ internal unsafe void InternalInitialize(char* charStart, char* charEnd, EncoderN this.iRecursionCount = 0; } - internal static EncoderFallbackBuffer CreateAndInitialize(Encoding encoding, EncoderNLS encoder, int originalCharCount) + internal static EncoderFallbackBuffer CreateAndInitialize(Encoding encoding, EncoderNLS? encoder, int originalCharCount) { // The original char count is only used for keeping track of what 'index' value needs // to be passed to the abstract Fallback method. The index value is calculated by subtracting @@ -218,6 +219,7 @@ internal bool TryDrainRemainingDataForGetBytes(Span bytes, out int bytesWr { int originalBytesLength = bytes.Length; + Debug.Assert(encoding != null); Rune thisRune; while ((thisRune = GetNextRune()).Value != 0) { @@ -267,6 +269,7 @@ internal int DrainRemainingDataForGetByteCount() { int totalByteCount = 0; + Debug.Assert(encoding != null); Rune thisRune; while ((thisRune = GetNextRune()).Value != 0) { diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderNLS.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderNLS.cs index 2901fc37b9bf..41a249409fae 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncoderNLS.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncoderNLS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.InteropServices; @@ -36,12 +37,6 @@ internal EncoderNLS(Encoding encoding) this.Reset(); } - internal EncoderNLS() - { - _encoding = null; - this.Reset(); - } - public override void Reset() { _charLeftOver = (char)0; @@ -86,6 +81,7 @@ public unsafe override int GetByteCount(char* chars, int count, bool flush) _mustFlush = flush; _throwOnOverflow = true; + Debug.Assert(_encoding != null); return _encoding.GetByteCount(chars, count, this); } @@ -133,6 +129,7 @@ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int _mustFlush = flush; _throwOnOverflow = true; + Debug.Assert(_encoding != null); return _encoding.GetBytes(chars, charCount, bytes, byteCount, this); } @@ -194,6 +191,7 @@ public override unsafe void Convert(char* chars, int charCount, _charsUsed = 0; // Do conversion + Debug.Assert(_encoding != null); bytesUsed = _encoding.GetBytes(chars, charCount, bytes, byteCount, this); charsUsed = _charsUsed; @@ -212,6 +210,7 @@ public Encoding Encoding { get { + Debug.Assert(_encoding != null); return _encoding; } } @@ -296,6 +295,7 @@ internal int DrainLeftoverDataForGetByteCount(ReadOnlySpan chars, out int { charsConsumed = 1; // consumed the leftover high surrogate + the first char in the input buffer + Debug.Assert(_encoding != null); if (_encoding.TryGetByteCount(rune, out int byteCount)) { Debug.Assert(byteCount >= 0, "Encoding shouldn't have returned a negative byte count."); @@ -312,7 +312,7 @@ internal int DrainLeftoverDataForGetByteCount(ReadOnlySpan chars, out int } // Now tally the number of bytes that would've been emitted as part of fallback. - + Debug.Assert(_fallbackBuffer != null); return _fallbackBuffer.DrainRemainingDataForGetByteCount(); } } @@ -355,6 +355,7 @@ internal bool TryDrainLeftoverDataForGetBytes(ReadOnlySpan chars, Span /// Entry point from . /// - internal virtual unsafe int GetByteCount(char* pChars, int charCount, EncoderNLS encoder) + internal virtual unsafe int GetByteCount(char* pChars, int charCount, EncoderNLS? encoder) { Debug.Assert(encoder != null, "This code path should only be called from EncoderNLS."); Debug.Assert(charCount >= 0, "Caller should've checked this condition."); @@ -173,7 +174,7 @@ internal virtual unsafe int GetByteCount(char* pChars, int charCount, EncoderNLS /// The implementation should not attempt to perform any sort of fallback behavior. /// If custom fallback behavior is necessary, override . /// - private protected virtual unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback fallback, out int charsConsumed) + private protected virtual unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback? fallback, out int charsConsumed) { // Any production-quality type would override this method and provide a real // implementation, so we won't provide a base implementation. However, a @@ -309,7 +310,7 @@ private unsafe int GetByteCountWithFallback(char* pOriginalChars, int originalCh /// If the resulting byte count is greater than . /// (Implementation should call .) /// - private protected virtual unsafe int GetByteCountWithFallback(ReadOnlySpan chars, int originalCharsLength, EncoderNLS encoder) + private protected virtual unsafe int GetByteCountWithFallback(ReadOnlySpan chars, int originalCharsLength, EncoderNLS? encoder) { Debug.Assert(!chars.IsEmpty, "Caller shouldn't invoke this method with an empty input buffer."); Debug.Assert(originalCharsLength >= 0, "Caller provided invalid parameter."); @@ -397,7 +398,7 @@ private protected virtual unsafe int GetByteCountWithFallback(ReadOnlySpan /// /// Entry point from and . /// - internal virtual unsafe int GetBytes(char* pChars, int charCount, byte* pBytes, int byteCount, EncoderNLS encoder) + internal virtual unsafe int GetBytes(char* pChars, int charCount, byte* pBytes, int byteCount, EncoderNLS? encoder) { Debug.Assert(encoder != null, "This code path should only be called from EncoderNLS."); Debug.Assert(charCount >= 0, "Caller should've checked this condition."); @@ -584,7 +585,7 @@ private unsafe int GetBytesWithFallback(char* pOriginalChars, int originalCharCo /// implementation, deferring to the base implementation if needed. This method calls /// if necessary. /// - private protected virtual unsafe int GetBytesWithFallback(ReadOnlySpan chars, int originalCharsLength, Span bytes, int originalBytesLength, EncoderNLS encoder) + private protected virtual unsafe int GetBytesWithFallback(ReadOnlySpan chars, int originalCharsLength, Span bytes, int originalBytesLength, EncoderNLS? encoder) { Debug.Assert(!chars.IsEmpty, "Caller shouldn't invoke this method with an empty input buffer."); Debug.Assert(originalCharsLength >= 0, "Caller provided invalid parameter."); @@ -705,7 +706,7 @@ private protected virtual unsafe int GetBytesWithFallback(ReadOnlySpan cha /// /// Entry point from . /// - internal virtual unsafe int GetCharCount(byte* pBytes, int byteCount, DecoderNLS decoder) + internal virtual unsafe int GetCharCount(byte* pBytes, int byteCount, DecoderNLS? decoder) { Debug.Assert(decoder != null, "This code path should only be called from DecoderNLS."); Debug.Assert(byteCount >= 0, "Caller should've checked this condition."); @@ -760,7 +761,7 @@ internal virtual unsafe int GetCharCount(byte* pBytes, int byteCount, DecoderNLS /// The implementation should not attempt to perform any sort of fallback behavior. /// If custom fallback behavior is necessary, override . /// - private protected virtual unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback fallback, out int bytesConsumed) + private protected virtual unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback? fallback, out int bytesConsumed) { // Any production-quality type would override this method and provide a real // implementation, so we won't provide a base implementation. However, a @@ -850,8 +851,14 @@ private unsafe int GetCharCountWithFallback(byte* pOriginalBytes, int originalBy ReadOnlySpan bytes = new ReadOnlySpan(pOriginalBytes, originalByteCount).Slice(bytesConsumedSoFar); - int totalCharCount = decoder.DrainLeftoverDataForGetCharCount(bytes, out int bytesConsumedJustNow); - bytes = bytes.Slice(bytesConsumedJustNow); + int bytesConsumedJustNow = 0; + int totalCharCount = 0; + + if (decoder.HasLeftoverData) + { + totalCharCount = decoder.DrainLeftoverDataForGetCharCount(bytes, out bytesConsumedJustNow); + bytes = bytes.Slice(bytesConsumedJustNow); + } // Now try invoking the "fast path" (no fallback) implementation. // We can use Unsafe.AsPointer here since these spans are created from pinned data (raw pointers). @@ -895,7 +902,7 @@ private unsafe int GetCharCountWithFallback(byte* pOriginalBytes, int originalBy /// If the resulting char count is greater than . /// (Implementation should call .) /// - private unsafe int GetCharCountWithFallback(ReadOnlySpan bytes, int originalBytesLength, DecoderNLS decoder) + private unsafe int GetCharCountWithFallback(ReadOnlySpan bytes, int originalBytesLength, DecoderNLS? decoder) { Debug.Assert(!bytes.IsEmpty, "Caller shouldn't invoke this method with an empty input buffer."); Debug.Assert(originalBytesLength >= 0, "Caller provided invalid parameter."); @@ -979,7 +986,7 @@ private unsafe int GetCharCountWithFallback(ReadOnlySpan bytes, int origin /// /// Entry point from and . /// - internal virtual unsafe int GetChars(byte* pBytes, int byteCount, char* pChars, int charCount, DecoderNLS decoder) + internal virtual unsafe int GetChars(byte* pBytes, int byteCount, char* pChars, int charCount, DecoderNLS? decoder) { Debug.Assert(decoder != null, "This code path should only be called from DecoderNLS."); Debug.Assert(byteCount >= 0, "Caller should've checked this condition."); @@ -1120,10 +1127,15 @@ private protected unsafe int GetCharsWithFallback(byte* pOriginalBytes, int orig ReadOnlySpan bytes = new ReadOnlySpan(pOriginalBytes, originalByteCount).Slice(bytesConsumedSoFar); Span chars = new Span(pOriginalChars, originalCharCount).Slice(charsWrittenSoFar); - int charsWrittenJustNow = decoder.DrainLeftoverDataForGetChars(bytes, chars, out int bytesConsumedJustNow); + int bytesConsumedJustNow = 0; + int charsWrittenJustNow = 0; - bytes = bytes.Slice(bytesConsumedJustNow); - chars = chars.Slice(charsWrittenJustNow); + if (decoder.HasLeftoverData) + { + charsWrittenJustNow = decoder.DrainLeftoverDataForGetChars(bytes, chars, out bytesConsumedJustNow); + bytes = bytes.Slice(bytesConsumedJustNow); + chars = chars.Slice(charsWrittenJustNow); + } Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "Should be no remaining fallback data at this point."); @@ -1166,7 +1178,7 @@ private protected unsafe int GetCharsWithFallback(byte* pOriginalBytes, int orig /// implementation, deferring to the base implementation if needed. This method calls /// if necessary. /// - private protected virtual unsafe int GetCharsWithFallback(ReadOnlySpan bytes, int originalBytesLength, Span chars, int originalCharsLength, DecoderNLS decoder) + private protected virtual unsafe int GetCharsWithFallback(ReadOnlySpan bytes, int originalBytesLength, Span chars, int originalCharsLength, DecoderNLS? decoder) { Debug.Assert(!bytes.IsEmpty, "Caller shouldn't invoke this method with an empty input buffer."); Debug.Assert(originalBytesLength >= 0, "Caller provided invalid parameter."); diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs index 8947b7fca0eb..fee129bac9ca 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.Serialization; @@ -153,15 +154,15 @@ public abstract partial class Encoding : ICloneable internal int _codePage = 0; - internal CodePageDataItem _dataItem = null; + internal CodePageDataItem? _dataItem = null; // Because of encoders we may be read only [OptionalField(VersionAdded = 2)] private bool _isReadOnly = true; // Encoding (encoder) fallback - internal EncoderFallback encoderFallback = null; - internal DecoderFallback decoderFallback = null; + internal EncoderFallback encoderFallback = null!; + internal DecoderFallback decoderFallback = null!; protected Encoding() : this(0) { @@ -186,7 +187,7 @@ protected Encoding(int codePage) // This constructor is needed to allow any sub-classing implementation to provide encoder/decoder fallback objects // because the encoding object is always created as read-only object and don't allow setting encoder/decoder fallback // after the creation is done. - protected Encoding(int codePage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) + protected Encoding(int codePage, EncoderFallback? encoderFallback, DecoderFallback? decoderFallback) { // Validate code page if (codePage < 0) @@ -254,7 +255,7 @@ public static void RegisterProvider(EncodingProvider provider) public static Encoding GetEncoding(int codepage) { - Encoding result = EncodingProvider.GetEncodingFromProvider(codepage); + Encoding? result = EncodingProvider.GetEncodingFromProvider(codepage); if (result != null) return result; @@ -290,7 +291,7 @@ public static Encoding GetEncoding(int codepage) public static Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { - Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(codepage, encoderFallback, decoderFallback); + Encoding? baseEncoding = EncodingProvider.GetEncodingFromProvider(codepage, encoderFallback, decoderFallback); if (baseEncoding != null) return baseEncoding; @@ -310,7 +311,7 @@ public static Encoding GetEncoding(int codepage, // public static Encoding GetEncoding(string name) { - Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name); + Encoding? baseEncoding = EncodingProvider.GetEncodingFromProvider(name); if (baseEncoding != null) return baseEncoding; @@ -328,7 +329,7 @@ public static Encoding GetEncoding(string name) public static Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { - Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name, encoderFallback, decoderFallback); + Encoding? baseEncoding = EncodingProvider.GetEncodingFromProvider(name, encoderFallback, decoderFallback); if (baseEncoding != null) return baseEncoding; @@ -338,7 +339,7 @@ public static Encoding GetEncoding(string name, // Otherwise, the code below will throw exception when trying to call // EncodingTable.GetCodePageFromName(). // - return (GetEncoding(EncodingTable.GetCodePageFromName(name), encoderFallback, decoderFallback)); + return GetEncoding(EncodingTable.GetCodePageFromName(name), encoderFallback, decoderFallback); } // Return a list of all EncodingInfo objects describing all of our encodings @@ -369,7 +370,7 @@ private void GetDataItem() // Returns the name for this encoding that can be used with mail agent body tags. // If the encoding may not be used, the string is empty. - public virtual string BodyName + public virtual string? BodyName { get { @@ -377,12 +378,12 @@ public virtual string BodyName { GetDataItem(); } - return (_dataItem.BodyName); + return _dataItem!.BodyName; } } // Returns the human-readable description of the encoding ( e.g. Hebrew (DOS)). - public virtual string EncodingName + public virtual string? EncodingName { get { @@ -391,14 +392,14 @@ public virtual string EncodingName GetDataItem(); } - return _dataItem.DisplayName; + return _dataItem!.DisplayName; } } // Returns the name for this encoding that can be used with mail agent header // tags. If the encoding may not be used, the string is empty. - public virtual string HeaderName + public virtual string? HeaderName { get { @@ -406,12 +407,12 @@ public virtual string HeaderName { GetDataItem(); } - return (_dataItem.HeaderName); + return _dataItem!.HeaderName; } } // Returns the IANA preferred name for this encoding. - public virtual string WebName + public virtual string? WebName { get { @@ -419,7 +420,7 @@ public virtual string WebName { GetDataItem(); } - return (_dataItem.WebName); + return _dataItem!.WebName; } } @@ -433,7 +434,7 @@ public virtual int WindowsCodePage { GetDataItem(); } - return (_dataItem.UIFamilyCodePage); + return _dataItem!.UIFamilyCodePage; } } @@ -448,7 +449,7 @@ public virtual bool IsBrowserDisplay { GetDataItem(); } - return ((_dataItem.Flags & MIMECONTF_BROWSER) != 0); + return (_dataItem!.Flags & MIMECONTF_BROWSER) != 0; } } @@ -462,7 +463,7 @@ public virtual bool IsBrowserSave { GetDataItem(); } - return ((_dataItem.Flags & MIMECONTF_SAVABLE_BROWSER) != 0); + return (_dataItem!.Flags & MIMECONTF_SAVABLE_BROWSER) != 0; } } @@ -476,7 +477,7 @@ public virtual bool IsMailNewsDisplay { GetDataItem(); } - return ((_dataItem.Flags & MIMECONTF_MAILNEWS) != 0); + return (_dataItem!.Flags & MIMECONTF_MAILNEWS) != 0; } } @@ -492,7 +493,7 @@ public virtual bool IsMailNewsSave { GetDataItem(); } - return ((_dataItem.Flags & MIMECONTF_SAVABLE_MAILNEWS) != 0); + return (_dataItem!.Flags & MIMECONTF_SAVABLE_MAILNEWS) != 0; } } @@ -1154,7 +1155,7 @@ public virtual string GetString(byte[] bytes, int index, int count) private static Encoding BigEndianUTF32 => UTF32Encoding.s_bigEndianDefault; - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is Encoding that) return (_codePage == that._codePage) && @@ -1189,7 +1190,7 @@ internal void ThrowBytesOverflow() SR.Format(SR.Argument_EncodingConversionOverflowBytes, EncodingName, EncoderFallback.GetType()), "bytes"); } - internal void ThrowBytesOverflow(EncoderNLS encoder, bool nothingEncoded) + internal void ThrowBytesOverflow(EncoderNLS? encoder, bool nothingEncoded) { if (encoder == null || encoder._throwOnOverflow || nothingEncoded) { @@ -1201,7 +1202,7 @@ internal void ThrowBytesOverflow(EncoderNLS encoder, bool nothingEncoded) } // If we didn't throw, we are in convert and have to remember our flushing - encoder.ClearMustFlush(); + encoder!.ClearMustFlush(); } [StackTraceHidden] @@ -1218,7 +1219,7 @@ internal void ThrowCharsOverflow() SR.Format(SR.Argument_EncodingConversionOverflowChars, EncodingName, DecoderFallback.GetType()), "chars"); } - internal void ThrowCharsOverflow(DecoderNLS decoder, bool nothingDecoded) + internal void ThrowCharsOverflow(DecoderNLS? decoder, bool nothingDecoded) { if (decoder == null || decoder._throwOnOverflow || nothingDecoded) { @@ -1231,7 +1232,7 @@ internal void ThrowCharsOverflow(DecoderNLS decoder, bool nothingDecoded) } // If we didn't throw, we are in convert and have to remember our flushing - decoder.ClearMustFlush(); + decoder!.ClearMustFlush(); } internal sealed class DefaultEncoder : Encoder, IObjectReference @@ -1380,13 +1381,13 @@ internal class EncodingCharBuffer private unsafe char* _charEnd; private int _charCountResult = 0; private Encoding _enc; - private DecoderNLS _decoder; + private DecoderNLS? _decoder; private unsafe byte* _byteStart; private unsafe byte* _byteEnd; private unsafe byte* _bytes; private DecoderFallbackBuffer _fallbackBuffer; - internal unsafe EncodingCharBuffer(Encoding enc, DecoderNLS decoder, char* charStart, int charCount, + internal unsafe EncodingCharBuffer(Encoding enc, DecoderNLS? decoder, char* charStart, int charCount, byte* byteStart, int byteCount) { _enc = enc; @@ -1556,10 +1557,10 @@ internal class EncodingByteBuffer private unsafe char* _charEnd; private int _byteCountResult = 0; private Encoding _enc; - private EncoderNLS _encoder; + private EncoderNLS? _encoder; internal EncoderFallbackBuffer fallbackBuffer; - internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder, + internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS? inEncoder, byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount) { _enc = inEncoding; @@ -1582,7 +1583,7 @@ internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder, if (_encoder._throwOnOverflow && _encoder.InternalHasFallbackBuffer && this.fallbackBuffer.Remaining > 0) throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, - _encoder.Encoding.EncodingName, _encoder.Fallback.GetType())); + _encoder.Encoding.EncodingName, _encoder.Fallback!.GetType())); } fallbackBuffer.InternalInitialize(_chars, _charEnd, _encoder, _bytes != null); } @@ -1607,17 +1608,17 @@ internal unsafe bool AddByte(byte b, int moreBytesExpected) internal bool AddByte(byte b1) { - return (AddByte(b1, 0)); + return AddByte(b1, 0); } internal bool AddByte(byte b1, byte b2) { - return (AddByte(b1, b2, 0)); + return AddByte(b1, b2, 0); } internal bool AddByte(byte b1, byte b2, int moreBytesExpected) { - return (AddByte(b1, 1 + moreBytesExpected) && AddByte(b2, moreBytesExpected)); + return AddByte(b1, 1 + moreBytesExpected) && AddByte(b2, moreBytesExpected); } internal bool AddByte(byte b1, byte b2, byte b3) @@ -1627,17 +1628,17 @@ internal bool AddByte(byte b1, byte b2, byte b3) internal bool AddByte(byte b1, byte b2, byte b3, int moreBytesExpected) { - return (AddByte(b1, 2 + moreBytesExpected) && + return AddByte(b1, 2 + moreBytesExpected) && AddByte(b2, 1 + moreBytesExpected) && - AddByte(b3, moreBytesExpected)); + AddByte(b3, moreBytesExpected); } internal bool AddByte(byte b1, byte b2, byte b3, byte b4) { - return (AddByte(b1, 3) && + return AddByte(b1, 3) && AddByte(b2, 2) && AddByte(b3, 1) && - AddByte(b4, 0)); + AddByte(b4, 0); } internal unsafe void MovePrevious(bool bThrow) @@ -1668,7 +1669,7 @@ internal unsafe bool MoreData get { // See if fallbackBuffer is not empty or if there's data left in chars buffer. - return ((fallbackBuffer.Remaining > 0) || (_chars < _charEnd)); + return (fallbackBuffer.Remaining > 0) || (_chars < _charEnd); } } diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingData.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingData.cs index 01837fc5314b..a1b7c9278379 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncodingData.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncodingData.cs @@ -6,6 +6,8 @@ // https://github.com/dotnet/buildtools/blob/6736870b84e06b75e7df32bb84d442db1b2afa10/src/Microsoft.DotNet.Build.Tasks/PackageFiles/encoding.targets // +// TODO-NULLABLE: We should edit original source instead: https://github.com/dotnet/buildtools/blob/master/src/Microsoft.DotNet.Build.Tasks/GenerateEncodingTable.cs#L235 +#nullable enable namespace System.Text { internal static partial class EncodingTable diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs index 002d9ef0b5ce..cfffd3c3f5e1 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Text { public sealed class EncodingInfo @@ -22,7 +23,7 @@ public Encoding GetEncoding() return Encoding.GetEncoding(CodePage); } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is EncodingInfo that) { diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs index 51d0e66044bd..0df2975dd293 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections; using System.Diagnostics; @@ -66,7 +67,7 @@ public override unsafe int GetByteCount(char[] chars, int index, int count) public override unsafe int GetByteCount(string s) { // Validate input - if (s==null) + if (s == null) throw new ArgumentNullException(nameof(s)); fixed (char* pChars = s) diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs index 22ce52c01c42..47b7636acc04 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections; using System.Collections.Generic; @@ -11,16 +12,16 @@ namespace System.Text public abstract class EncodingProvider { public EncodingProvider() { } - public abstract Encoding GetEncoding(string name); - public abstract Encoding GetEncoding(int codepage); + public abstract Encoding? GetEncoding(string name); + public abstract Encoding? GetEncoding(int codepage); // GetEncoding should return either valid encoding or null. shouldn't throw any exception except on null name - public virtual Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback) + public virtual Encoding? GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { - Encoding enc = GetEncoding(name); + Encoding? enc = GetEncoding(name); if (enc != null) { - enc = (Encoding)GetEncoding(name).Clone(); + enc = (Encoding)enc.Clone(); enc.EncoderFallback = encoderFallback; enc.DecoderFallback = decoderFallback; } @@ -28,12 +29,12 @@ public virtual Encoding GetEncoding(string name, EncoderFallback encoderFallback return enc; } - public virtual Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) + public virtual Encoding? GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback) { - Encoding enc = GetEncoding(codepage); + Encoding? enc = GetEncoding(codepage); if (enc != null) { - enc = (Encoding)GetEncoding(codepage).Clone(); + enc = (Encoding)enc.Clone(); enc.EncoderFallback = encoderFallback; enc.DecoderFallback = decoderFallback; } @@ -66,7 +67,7 @@ internal static void AddProvider(EncodingProvider provider) } } - internal static Encoding GetEncodingFromProvider(int codepage) + internal static Encoding? GetEncodingFromProvider(int codepage) { if (s_providers == null) return null; @@ -74,7 +75,7 @@ internal static Encoding GetEncodingFromProvider(int codepage) EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { - Encoding enc = provider.GetEncoding(codepage); + Encoding? enc = provider.GetEncoding(codepage); if (enc != null) return enc; } @@ -82,7 +83,7 @@ internal static Encoding GetEncodingFromProvider(int codepage) return null; } - internal static Encoding GetEncodingFromProvider(string encodingName) + internal static Encoding? GetEncodingFromProvider(string encodingName) { if (s_providers == null) return null; @@ -90,7 +91,7 @@ internal static Encoding GetEncodingFromProvider(string encodingName) EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { - Encoding enc = provider.GetEncoding(encodingName); + Encoding? enc = provider.GetEncoding(encodingName); if (enc != null) return enc; } @@ -98,7 +99,7 @@ internal static Encoding GetEncodingFromProvider(string encodingName) return null; } - internal static Encoding GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec) + internal static Encoding? GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec) { if (s_providers == null) return null; @@ -106,15 +107,15 @@ internal static Encoding GetEncodingFromProvider(int codepage, EncoderFallback e EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { - Encoding encing = provider.GetEncoding(codepage, enc, dec); - if (encing != null) - return encing; + Encoding? encoding = provider.GetEncoding(codepage, enc, dec); + if (encoding != null) + return encoding; } return null; } - internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec) + internal static Encoding? GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec) { if (s_providers == null) return null; @@ -122,7 +123,7 @@ internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFal EncodingProvider[] providers = s_providers; foreach (EncodingProvider provider in providers) { - Encoding encoding = provider.GetEncoding(encodingName, enc, dec); + Encoding? encoding = provider.GetEncoding(encodingName, enc, dec); if (encoding != null) return encoding; } @@ -131,6 +132,6 @@ internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFal } private static object s_InternalSyncObject = new object(); - private static volatile EncodingProvider[] s_providers; + private static volatile EncodingProvider[]? s_providers; } } diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingTable.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingTable.cs index 38f32e2636ca..14c9bbe329da 100644 --- a/src/System.Private.CoreLib/shared/System/Text/EncodingTable.cs +++ b/src/System.Private.CoreLib/shared/System/Text/EncodingTable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Diagnostics; using System.Threading; @@ -16,7 +17,7 @@ namespace System.Text internal static partial class EncodingTable { private static readonly Hashtable s_nameToCodePage = Hashtable.Synchronized(new Hashtable(StringComparer.OrdinalIgnoreCase)); - private static CodePageDataItem[] s_codePageToCodePageData; + private static CodePageDataItem?[]? s_codePageToCodePageData; /*=================================GetCodePageFromName========================== **Action: Given a encoding name, return the correct code page number for this encoding. @@ -120,11 +121,11 @@ internal static EncodingInfo[] GetEncodings() return arrayEncodingInfo; } - internal static CodePageDataItem GetCodePageDataItem(int codePage) + internal static CodePageDataItem? GetCodePageDataItem(int codePage) { if (s_codePageToCodePageData == null) { - Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[s_mappedCodePages.Length], null); + Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[s_mappedCodePages.Length], null); } // Keep in sync with s_mappedCodePages @@ -159,10 +160,10 @@ internal static CodePageDataItem GetCodePageDataItem(int codePage) return null; } - CodePageDataItem data = s_codePageToCodePageData[index]; + CodePageDataItem? data = s_codePageToCodePageData![index]; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 if (data == null) { - Interlocked.CompareExchange(ref s_codePageToCodePageData[index], InternalGetCodePageDataItem(codePage, index), null); + Interlocked.CompareExchange(ref s_codePageToCodePageData[index], InternalGetCodePageDataItem(codePage, index), null); data = s_codePageToCodePageData[index]; } @@ -184,7 +185,7 @@ private static CodePageDataItem InternalGetCodePageDataItem(int codePage, int in private static string GetDisplayName(int codePage, int englishNameIndex) { - string displayName = SR.GetResourceString("Globalization_cp_" + codePage.ToString()); + string? displayName = SR.GetResourceString("Globalization_cp_" + codePage.ToString()); if (string.IsNullOrEmpty(displayName)) displayName = s_englishNames.Substring(s_englishNameIndices[englishNameIndex], s_englishNameIndices[englishNameIndex + 1] - s_englishNameIndices[englishNameIndex]); diff --git a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs index 736fff5d2608..672348b54b9a 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Diagnostics; @@ -25,7 +26,7 @@ public Latin1Encoding() : base(Encoding.ISO_8859_1) // GetByteCount // Note: We start by assuming that the output will be the same as count. Having // an encoder or fallback may change that assumption - internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder) + internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS? encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(charCount >= 0, "[Latin1Encoding.GetByteCount]count is negative"); @@ -38,7 +39,7 @@ internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS // If we have an encoder AND we aren't using default fallback, // then we may have a complicated count. - EncoderReplacementFallback fallback; + EncoderReplacementFallback? fallback; if (encoder != null) { charLeftOver = encoder._charLeftOver; @@ -79,7 +80,7 @@ internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS char* charEnd = chars + charCount; // For fallback we may need a fallback buffer, we know we aren't default fallback. - EncoderFallbackBuffer fallbackBuffer = null; + EncoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; // We may have a left over character from last time, try and process it. @@ -146,7 +147,7 @@ internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS } internal override unsafe int GetBytes(char* chars, int charCount, - byte* bytes, int byteCount, EncoderNLS encoder) + byte* bytes, int byteCount, EncoderNLS? encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[Latin1Encoding.GetBytes]bytes is null"); @@ -159,7 +160,7 @@ internal override unsafe int GetBytes(char* chars, int charCount, // Get any left over characters & check fast or slower fallback type char charLeftOver = (char)0; - EncoderReplacementFallback fallback = null; + EncoderReplacementFallback? fallback = null; if (encoder != null) { charLeftOver = encoder._charLeftOver; @@ -244,7 +245,7 @@ internal override unsafe int GetBytes(char* chars, int charCount, byte* byteEnd = bytes + byteCount; // For fallback we may need a fallback buffer, we know we aren't default fallback, create & init it - EncoderFallbackBuffer fallbackBuffer = null; + EncoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; // We may have a left over character from last time, try and process it. @@ -365,7 +366,7 @@ internal override unsafe int GetBytes(char* chars, int charCount, } // This is internal and called by something else, - internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder) + internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS? decoder) { // Just assert, we're called internally so these should be safe, checked already Debug.Assert(bytes != null, "[Latin1Encoding.GetCharCount]bytes is null"); @@ -377,7 +378,7 @@ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS dec } internal override unsafe int GetChars(byte* bytes, int byteCount, - char* chars, int charCount, DecoderNLS decoder) + char* chars, int charCount, DecoderNLS? decoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[Latin1Encoding.GetChars]bytes is null"); diff --git a/src/System.Private.CoreLib/shared/System/Text/Rune.cs b/src/System.Private.CoreLib/shared/System/Text/Rune.cs index a91c0fcb9950..c743e213b8c2 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Rune.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Rune.cs @@ -2,10 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; +using System.Text.Unicode; namespace System.Text { @@ -662,46 +664,6 @@ public static OperationStatus DecodeLastFromUtf8(ReadOnlySpan source, out } } - public static OperationStatus DecodeUtf16(ReadOnlySpan utf16Source, out Rune result, out int charsConsumed) - { - // [TODO] This method was renamed to DecodeFromUtf16. We'll leave this copy of - // the method here temporarily so that we don't break corefx consumers - // while the rename takes place. - // Tracking issue: https://github.com/dotnet/coreclr/issues/23319 - - return DecodeFromUtf16(utf16Source, out result, out charsConsumed); - } - - public static OperationStatus DecodeUtf16FromEnd(ReadOnlySpan utf16Source, out Rune result, out int charsConsumed) - { - // [TODO] This method was renamed to DecodeLastFromUtf16. We'll leave this copy of - // the method here temporarily so that we don't break corefx consumers - // while the rename takes place. - // Tracking issue: https://github.com/dotnet/coreclr/issues/23319 - - return DecodeLastFromUtf16(utf16Source, out result, out charsConsumed); - } - - public static OperationStatus DecodeUtf8(ReadOnlySpan utf8Source, out Rune result, out int bytesConsumed) - { - // [TODO] This method was renamed to DecodeFromUtf8. We'll leave this copy of - // the method here temporarily so that we don't break corefx consumers - // while the rename takes place. - // Tracking issue: https://github.com/dotnet/coreclr/issues/23319 - - return DecodeFromUtf8(utf8Source, out result, out bytesConsumed); - } - - public static OperationStatus DecodeUtf8FromEnd(ReadOnlySpan utf8Source, out Rune result, out int bytesConsumed) - { - // [TODO] This method was renamed to DecodeLastFromUtf8. We'll leave this copy of - // the method here temporarily so that we don't break corefx consumers - // while the rename takes place. - // Tracking issue: https://github.com/dotnet/coreclr/issues/23319 - - return DecodeLastFromUtf8(utf8Source, out result, out bytesConsumed); - } - /// /// Encodes this to a UTF-16 destination buffer. /// @@ -738,7 +700,7 @@ public int EncodeToUtf8(Span destination) return bytesWritten; } - public override bool Equals(object obj) => (obj is Rune other) && this.Equals(other); + public override bool Equals(object? obj) => (obj is Rune other) && this.Equals(other); public bool Equals(Rune other) => (this == other); @@ -821,7 +783,7 @@ private static int ReadRuneFromString(string input, int index) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); } - if ((uint)index >= (uint)input.Length) + if ((uint)index >= (uint)input!.Length) { ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } @@ -984,16 +946,6 @@ public bool TryEncodeToUtf16(Span destination, out int charsWritten) return false; } - public bool TryEncode(Span destination, out int charsWritten) - { - // [TODO] This method was renamed to TryEncodeToUtf16. We'll leave this copy of - // the method here temporarily so that we don't break corefx consumers - // while the rename takes place. - // Tracking issue: https://github.com/dotnet/coreclr/issues/23319 - - return TryEncodeToUtf16(destination, out charsWritten); - } - /// /// Encodes this to a destination buffer as UTF-8 bytes. /// @@ -1062,16 +1014,6 @@ public bool TryEncodeToUtf8(Span destination, out int bytesWritten) return false; } - public bool TryEncodeToUtf8Bytes(Span destination, out int bytesWritten) - { - // [TODO] This method was renamed to TryEncodeToUtf8. We'll leave this copy of - // the method here temporarily so that we don't break corefx consumers - // while the rename takes place. - // Tracking issue: https://github.com/dotnet/coreclr/issues/23319 - - return TryEncodeToUtf8(destination, out bytesWritten); - } - /// /// Attempts to get the which begins at index in /// string . @@ -1210,7 +1152,7 @@ public static bool IsDigit(Rune value) } else { - return (GetUnicodeCategoryNonAscii(value) == UnicodeCategory.DecimalDigitNumber); + return GetUnicodeCategoryNonAscii(value) == UnicodeCategory.DecimalDigitNumber; } } @@ -1246,7 +1188,7 @@ public static bool IsLower(Rune value) } else { - return (GetUnicodeCategoryNonAscii(value) == UnicodeCategory.LowercaseLetter); + return GetUnicodeCategoryNonAscii(value) == UnicodeCategory.LowercaseLetter; } } @@ -1285,7 +1227,7 @@ public static bool IsUpper(Rune value) } else { - return (GetUnicodeCategoryNonAscii(value) == UnicodeCategory.UppercaseLetter); + return GetUnicodeCategoryNonAscii(value) == UnicodeCategory.UppercaseLetter; } } @@ -1324,7 +1266,7 @@ public static Rune ToLower(Rune value, CultureInfo culture) return ToLowerInvariant(value); } - return ChangeCaseCultureAware(value, culture.TextInfo, toUpper: false); + return ChangeCaseCultureAware(value, culture!.TextInfo, toUpper: false); } public static Rune ToLowerInvariant(Rune value) @@ -1367,7 +1309,7 @@ public static Rune ToUpper(Rune value, CultureInfo culture) return ToUpperInvariant(value); } - return ChangeCaseCultureAware(value, culture.TextInfo, toUpper: true); + return ChangeCaseCultureAware(value, culture!.TextInfo, toUpper: true); } public static Rune ToUpperInvariant(Rune value) diff --git a/src/System.Private.CoreLib/shared/System/Text/SpanRuneEnumerator.cs b/src/System.Private.CoreLib/shared/System/Text/SpanRuneEnumerator.cs index 082a5108c140..d650eb9d19fd 100644 --- a/src/System.Private.CoreLib/shared/System/Text/SpanRuneEnumerator.cs +++ b/src/System.Private.CoreLib/shared/System/Text/SpanRuneEnumerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Text { // An enumerator for retrieving System.Text.Rune instances from a ROS. diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs index a62c4777adb3..a7681d071d99 100644 --- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs +++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Text @@ -11,7 +12,9 @@ public sealed partial class StringBuilder private void ShowChunks(int maxChunksToShow = 10) { int count = 0; - StringBuilder head = this, current = this; + StringBuilder head = this; + StringBuilder? current = this; + while (current != null) { if (count < maxChunksToShow) @@ -20,17 +23,21 @@ private void ShowChunks(int maxChunksToShow = 10) } else { + Debug.Assert(head.m_ChunkPrevious != null); head = head.m_ChunkPrevious; } current = current.m_ChunkPrevious; } + current = head; string[] chunks = new string[count]; for (int i = count; i > 0; i--) { chunks[i - 1] = new string(current.m_ChunkChars).Replace('\0', '.'); + Debug.Assert(current.m_ChunkPrevious != null); current = current.m_ChunkPrevious; } + Debug.WriteLine('|' + string.Join('|', chunks) + '|'); } } diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs index cd88d2199d90..eee36e52ec1d 100644 --- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; using System.Runtime; using System.Runtime.Serialization; @@ -41,7 +42,7 @@ public sealed partial class StringBuilder : ISerializable /// /// The chunk that logically precedes this chunk. /// - internal StringBuilder m_ChunkPrevious; + internal StringBuilder? m_ChunkPrevious; /// /// The number of characters in this chunk. @@ -98,7 +99,7 @@ public StringBuilder(int capacity) /// Initializes a new instance of the class. /// /// The initial contents of this builder. - public StringBuilder(string value) + public StringBuilder(string? value) : this(value, DefaultCapacity) { } @@ -108,7 +109,7 @@ public StringBuilder(string value) /// /// The initial contents of this builder. /// The initial capacity of this builder. - public StringBuilder(string value, int capacity) + public StringBuilder(string? value, int capacity) : this(value, 0, value?.Length ?? 0, capacity) { } @@ -120,7 +121,7 @@ public StringBuilder(string value, int capacity) /// The index to start in . /// The number of characters to read in . /// The initial capacity of this builder. - public StringBuilder(string value, int startIndex, int length, int capacity) + public StringBuilder(string? value, int startIndex, int length, int capacity) { if (capacity < 0) { @@ -200,7 +201,7 @@ private StringBuilder(SerializationInfo info, StreamingContext context) } int persistedCapacity = 0; - string persistedString = null; + string? persistedString = null; int persistedMaxCapacity = int.MaxValue; bool capacityPresent = false; @@ -288,7 +289,7 @@ private void AssertInvariants() Debug.Assert(currentBlock.m_ChunkLength >= 0); Debug.Assert(currentBlock.m_ChunkOffset >= 0); - StringBuilder prevBlock = currentBlock.m_ChunkPrevious; + StringBuilder? prevBlock = currentBlock.m_ChunkPrevious; if (prevBlock == null) { Debug.Assert(currentBlock.m_ChunkOffset == 0); @@ -363,7 +364,7 @@ public override string ToString() } string result = string.FastAllocateString(Length); - StringBuilder chunk = this; + StringBuilder? chunk = this; unsafe { fixed (char* destinationPtr = result) @@ -514,7 +515,7 @@ public char this[int index] { get { - StringBuilder chunk = this; + StringBuilder? chunk = this; for (;;) { int indexInBlock = index - chunk.m_ChunkOffset; @@ -535,7 +536,7 @@ public char this[int index] } set { - StringBuilder chunk = this; + StringBuilder? chunk = this; for (;;) { int indexInBlock = index - chunk.m_ChunkOffset; @@ -595,8 +596,8 @@ public char this[int index] public struct ChunkEnumerator { private readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string) - private StringBuilder _currentChunk; // The chunk that this enumerator is currently returning (Current). - private readonly ManyChunkInfo _manyChunks; // Only used for long string builders with many chunks (see constructor) + private StringBuilder? _currentChunk; // The chunk that this enumerator is currently returning (Current). + private readonly ManyChunkInfo? _manyChunks; // Only used for long string builders with many chunks (see constructor) /// /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator @@ -617,7 +618,10 @@ public bool MoveNext() StringBuilder next = _firstChunk; while (next.m_ChunkPrevious != _currentChunk) + { + Debug.Assert(next.m_ChunkPrevious != null); next = next.m_ChunkPrevious; + } _currentChunk = next; return true; } @@ -625,7 +629,18 @@ public bool MoveNext() /// /// Implements the IEnumerator pattern. /// - public ReadOnlyMemory Current => new ReadOnlyMemory(_currentChunk.m_ChunkChars, 0, _currentChunk.m_ChunkLength); + public ReadOnlyMemory Current + { + get + { + if (_currentChunk == null) + { + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); + } + + return new ReadOnlyMemory(_currentChunk!.m_ChunkChars, 0, _currentChunk.m_ChunkLength); // TODO-NULLABLE: https://github.com/dotnet/csharplang#538 + } + } #region private internal ChunkEnumerator(StringBuilder stringBuilder) @@ -646,7 +661,7 @@ internal ChunkEnumerator(StringBuilder stringBuilder) _manyChunks = new ManyChunkInfo(stringBuilder, chunkCount); } - private static int ChunkCount(StringBuilder stringBuilder) + private static int ChunkCount(StringBuilder? stringBuilder) { int ret = 0; while (stringBuilder != null) @@ -665,7 +680,7 @@ private class ManyChunkInfo private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first) private int _chunkPos; - public bool MoveNext(ref StringBuilder current) + public bool MoveNext(ref StringBuilder? current) { int pos = ++_chunkPos; if (_chunks.Length <= pos) @@ -674,7 +689,7 @@ public bool MoveNext(ref StringBuilder current) return true; } - public ManyChunkInfo(StringBuilder stringBuilder, int chunkCount) + public ManyChunkInfo(StringBuilder? stringBuilder, int chunkCount) { _chunks = new StringBuilder[chunkCount]; while (0 <= --chunkCount) @@ -742,7 +757,7 @@ public StringBuilder Append(char value, int repeatCount) /// The characters to append. /// The index to start in . /// The number of characters to read in . - public StringBuilder Append(char[] value, int startIndex, int charCount) + public StringBuilder Append(char[]? value, int startIndex, int charCount) { if (startIndex < 0) { @@ -787,7 +802,7 @@ public StringBuilder Append(char[] value, int startIndex, int charCount) /// Appends a string to the end of this builder. /// /// The string to append. - public StringBuilder Append(string value) + public StringBuilder Append(string? value) { if (value != null) { @@ -848,7 +863,7 @@ private void AppendHelper(string value) /// The string to append. /// The index to start in . /// The number of characters to read in . - public StringBuilder Append(string value, int startIndex, int count) + public StringBuilder Append(string? value, int startIndex, int count) { if (startIndex < 0) { @@ -888,7 +903,7 @@ public StringBuilder Append(string value, int startIndex, int count) } } - public StringBuilder Append(StringBuilder value) + public StringBuilder Append(StringBuilder? value) { if (value != null && value.Length != 0) { @@ -897,7 +912,7 @@ public StringBuilder Append(StringBuilder value) return this; } - public StringBuilder Append(StringBuilder value, int startIndex, int count) + public StringBuilder Append(StringBuilder? value, int startIndex, int count) { if (startIndex < 0) { @@ -963,7 +978,7 @@ private StringBuilder AppendCore(StringBuilder value, int startIndex, int count) public StringBuilder AppendLine() => Append(Environment.NewLine); - public StringBuilder AppendLine(string value) + public StringBuilder AppendLine(string? value) { Append(value); return Append(Environment.NewLine); @@ -1008,11 +1023,12 @@ public void CopyTo(int sourceIndex, Span destination, int count) AssertInvariants(); - StringBuilder chunk = this; + StringBuilder? chunk = this; int sourceEndIndex = sourceIndex + count; int curDestIndex = count; while (count > 0) { + Debug.Assert(chunk != null); int chunkEndIndex = sourceEndIndex - chunk.m_ChunkOffset; if (chunkEndIndex >= 0) { @@ -1042,7 +1058,7 @@ public void CopyTo(int sourceIndex, Span destination, int count) /// The index to insert in this builder. /// The string to insert. /// The number of times to insert the string. - public StringBuilder Insert(int index, string value, int count) + public StringBuilder Insert(int index, string? value, int count) { if (count < 0) { @@ -1078,7 +1094,7 @@ public StringBuilder Insert(int index, string value, int count) { while (count > 0) { - ReplaceInPlaceAtChunk(ref chunk, ref indexInChunk, valuePtr, value.Length); + ReplaceInPlaceAtChunk(ref chunk!, ref indexInChunk, valuePtr, value.Length); --count; } @@ -1179,7 +1195,7 @@ private StringBuilder AppendSpanFormattable(T value) where T : ISpanFormattab return Append(value.ToString()); } - internal StringBuilder AppendSpanFormattable(T value, string format, IFormatProvider provider) where T : ISpanFormattable, IFormattable + internal StringBuilder AppendSpanFormattable(T value, string? format, IFormatProvider? provider) where T : ISpanFormattable, IFormattable { if (value.TryFormat(RemainingCurrentChunk, out int charsWritten, format, provider)) { @@ -1190,9 +1206,9 @@ internal StringBuilder AppendSpanFormattable(T value, string format, IFormatP return Append(value.ToString(format, provider)); } - public StringBuilder Append(object value) => (value == null) ? this : Append(value.ToString()); + public StringBuilder Append(object? value) => (value == null) ? this : Append(value.ToString()); - public StringBuilder Append(char[] value) + public StringBuilder Append(char[]? value) { if (value?.Length > 0) { @@ -1226,7 +1242,7 @@ public StringBuilder Append(ReadOnlySpan value) #region AppendJoin - public unsafe StringBuilder AppendJoin(string separator, params object[] values) + public unsafe StringBuilder AppendJoin(string? separator, params object?[] values) { separator = separator ?? string.Empty; fixed (char* pSeparator = separator) @@ -1235,7 +1251,7 @@ public unsafe StringBuilder AppendJoin(string separator, params object[] values) } } - public unsafe StringBuilder AppendJoin(string separator, IEnumerable values) + public unsafe StringBuilder AppendJoin(string? separator, IEnumerable values) { separator = separator ?? string.Empty; fixed (char* pSeparator = separator) @@ -1244,7 +1260,7 @@ public unsafe StringBuilder AppendJoin(string separator, IEnumerable value } } - public unsafe StringBuilder AppendJoin(string separator, params string[] values) + public unsafe StringBuilder AppendJoin(string? separator, params string?[] values) { separator = separator ?? string.Empty; fixed (char* pSeparator = separator) @@ -1253,7 +1269,7 @@ public unsafe StringBuilder AppendJoin(string separator, params string[] values) } } - public unsafe StringBuilder AppendJoin(char separator, params object[] values) + public unsafe StringBuilder AppendJoin(char separator, params object?[] values) { return AppendJoinCore(&separator, 1, values); } @@ -1263,7 +1279,7 @@ public unsafe StringBuilder AppendJoin(char separator, IEnumerable values) return AppendJoinCore(&separator, 1, values); } - public unsafe StringBuilder AppendJoin(char separator, params string[] values) + public unsafe StringBuilder AppendJoin(char separator, params string?[] values) { return AppendJoinCore(&separator, 1, values); } @@ -1278,6 +1294,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); } + Debug.Assert(values != null); using (IEnumerator en = values.GetEnumerator()) { if (!en.MoveNext()) @@ -1311,6 +1328,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen ThrowHelper.ThrowArgumentNullException(ExceptionArgument.values); } + Debug.Assert(values != null); if (values.Length == 0) { return this; @@ -1318,7 +1336,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen if (values[0] != null) { - Append(values[0].ToString()); + Append(values[0]!.ToString()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 } for (int i = 1; i < values.Length; i++) @@ -1326,7 +1344,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen Append(separator, separatorLength); if (values[i] != null) { - Append(values[i].ToString()); + Append(values[i]!.ToString()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 } } return this; @@ -1334,7 +1352,7 @@ private unsafe StringBuilder AppendJoinCore(char* separator, int separatorLen #endregion - public StringBuilder Insert(int index, string value) + public StringBuilder Insert(int index, string? value) { if ((uint)index > (uint)Length) { @@ -1370,7 +1388,7 @@ public StringBuilder Insert(int index, char value) return this; } - public StringBuilder Insert(int index, char[] value) + public StringBuilder Insert(int index, char[]? value) { if ((uint)index > (uint)Length) { @@ -1382,7 +1400,7 @@ public StringBuilder Insert(int index, char[] value) return this; } - public StringBuilder Insert(int index, char[] value, int startIndex, int charCount) + public StringBuilder Insert(int index, char[]? value, int startIndex, int charCount) { int currentLength = Length; if ((uint)index > (uint)currentLength) @@ -1444,7 +1462,7 @@ public StringBuilder Insert(int index, char[] value, int startIndex, int charCou [CLSCompliant(false)] public StringBuilder Insert(int index, ulong value) => Insert(index, value.ToString(), 1); - public StringBuilder Insert(int index, object value) => (value == null) ? this : Insert(index, value.ToString(), 1); + public StringBuilder Insert(int index, object? value) => (value == null) ? this : Insert(index, value.ToString(), 1); public StringBuilder Insert(int index, ReadOnlySpan value) { @@ -1464,13 +1482,13 @@ public StringBuilder Insert(int index, ReadOnlySpan value) return this; } - public StringBuilder AppendFormat(string format, object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0)); + public StringBuilder AppendFormat(string format, object? arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0)); - public StringBuilder AppendFormat(string format, object arg0, object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1)); + public StringBuilder AppendFormat(string format, object? arg0, object? arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1)); - public StringBuilder AppendFormat(string format, object arg0, object arg1, object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2)); + public StringBuilder AppendFormat(string format, object? arg0, object? arg1, object? arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2)); - public StringBuilder AppendFormat(string format, params object[] args) + public StringBuilder AppendFormat(string format, params object?[] args) { if (args == null) { @@ -1483,13 +1501,13 @@ public StringBuilder AppendFormat(string format, params object[] args) return AppendFormatHelper(null, format, new ParamsArray(args)); } - public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0)); + public StringBuilder AppendFormat(IFormatProvider provider, string format, object? arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0)); - public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1)); + public StringBuilder AppendFormat(IFormatProvider provider, string format, object? arg0, object? arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1)); - public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1, object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2)); + public StringBuilder AppendFormat(IFormatProvider provider, string format, object? arg0, object? arg1, object? arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2)); - public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args) + public StringBuilder AppendFormat(IFormatProvider provider, string format, params object?[] args) { if (args == null) { @@ -1511,7 +1529,7 @@ private static void FormatError() private const int IndexLimit = 1000000; // Note: 0 <= ArgIndex < IndexLimit private const int WidthLimit = 1000000; // Note: -WidthLimit < ArgAlign < WidthLimit - internal StringBuilder AppendFormatHelper(IFormatProvider provider, string format, ParamsArray args) + internal StringBuilder AppendFormatHelper(IFormatProvider? provider, string format, ParamsArray args) { if (format == null) { @@ -1521,12 +1539,12 @@ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string forma int pos = 0; int len = format.Length; char ch = '\x0'; - StringBuilder unescapedItemFormat = null; + StringBuilder? unescapedItemFormat = null; - ICustomFormatter cf = null; + ICustomFormatter? cf = null; if (provider != null) { - cf = (ICustomFormatter)provider.GetFormat(typeof(ICustomFormatter)); + cf = (ICustomFormatter?)provider.GetFormat(typeof(ICustomFormatter)); } while (true) @@ -1647,8 +1665,8 @@ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string forma // // Start of parsing of optional formatting parameter. // - object arg = args[index]; - string itemFormat = null; + object? arg = args[index]; + string? itemFormat = null; ReadOnlySpan itemFormatSpan = default; // used if itemFormat is null // Is current character a colon? which indicates start of formatting parameter. if (ch == ':') @@ -1718,7 +1736,7 @@ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string forma if (ch != '}') FormatError(); // Construct the output for this arg hole. pos++; - string s = null; + string? s = null; if (cf != null) { if (itemFormatSpan.Length != 0 && itemFormat == null) @@ -1780,13 +1798,13 @@ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string forma /// If is null, instances of /// are removed from this builder. /// - public StringBuilder Replace(string oldValue, string newValue) => Replace(oldValue, newValue, 0, Length); + public StringBuilder Replace(string oldValue, string? newValue) => Replace(oldValue, newValue, 0, Length); /// /// Determines if the contents of this builder are equal to the contents of another builder. /// /// The other builder. - public bool Equals(StringBuilder sb) + public bool Equals(StringBuilder? sb) { if (sb == null) return false; @@ -1795,9 +1813,9 @@ public bool Equals(StringBuilder sb) if (sb == this) return true; - StringBuilder thisChunk = this; + StringBuilder? thisChunk = this; int thisChunkIndex = thisChunk.m_ChunkLength; - StringBuilder sbChunk = sb; + StringBuilder? sbChunk = sb; int sbChunkIndex = sbChunk.m_ChunkLength; for (;;) { @@ -1824,6 +1842,8 @@ public bool Equals(StringBuilder sb) return sbChunkIndex < 0; if (sbChunkIndex < 0) return false; + + Debug.Assert(thisChunk != null && sbChunk != null); if (thisChunk.m_ChunkChars[thisChunkIndex] != sbChunk.m_ChunkChars[sbChunkIndex]) return false; } @@ -1838,7 +1858,7 @@ public bool Equals(ReadOnlySpan span) if (span.Length != Length) return false; - StringBuilder sbChunk = this; + StringBuilder? sbChunk = this; int offset = 0; do @@ -1869,7 +1889,7 @@ public bool Equals(ReadOnlySpan span) /// If is null, instances of /// are removed from this builder. /// - public StringBuilder Replace(string oldValue, string newValue, int startIndex, int count) + public StringBuilder Replace(string oldValue, string? newValue, int startIndex, int count) { int currentLength = Length; if ((uint)startIndex > (uint)currentLength) @@ -1893,7 +1913,7 @@ public StringBuilder Replace(string oldValue, string newValue, int startIndex, i int deltaLength = newValue.Length - oldValue.Length; - int[] replacements = null; // A list of replacement positions in a chunk to apply + int[]? replacements = null; // A list of replacement positions in a chunk to apply int replacementsCount = 0; // Find the chunk, indexInChunk for the starting point @@ -1901,6 +1921,7 @@ public StringBuilder Replace(string oldValue, string newValue, int startIndex, i int indexInChunk = startIndex - chunk.m_ChunkOffset; while (count > 0) { + Debug.Assert(chunk != null, "chunk was null in replace"); // Look for a match in the chunk,indexInChunk pointer if (StartsWith(chunk, indexInChunk, count, oldValue)) { @@ -1913,9 +1934,9 @@ public StringBuilder Replace(string oldValue, string newValue, int startIndex, i } else if (replacementsCount >= replacements.Length) { - Array.Resize(ref replacements, replacements.Length * 3 / 2 + 4); // Grow by ~1.5x, but more in the begining + Array.Resize(ref replacements!, replacements.Length * 3 / 2 + 4); // Grow by ~1.5x, but more in the begining // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } - replacements[replacementsCount++] = indexInChunk; + replacements![replacementsCount++] = indexInChunk; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 indexInChunk += oldValue.Length; count -= oldValue.Length; } @@ -1932,6 +1953,7 @@ public StringBuilder Replace(string oldValue, string newValue, int startIndex, i int indexBeforeAdjustment = index; // See if we accumulated any replacements, if so apply them. + Debug.Assert(replacements != null || replacementsCount == 0, "replacements was null and replacementsCount != 0"); ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue); // The replacement has affected the logical index. Adjust it. index += ((newValue.Length - oldValue.Length) * replacementsCount); @@ -1997,6 +2019,8 @@ public StringBuilder Replace(char oldChar, char newChar, int startIndex, int cou } if (startIndexInChunk >= 0) break; + + Debug.Assert(chunk.m_ChunkPrevious != null); chunk = chunk.m_ChunkPrevious; } @@ -2074,7 +2098,7 @@ private unsafe void Insert(int index, char* value, int valueCount) StringBuilder chunk; int indexInChunk; MakeRoom(index, valueCount, out chunk, out indexInChunk, false); - ReplaceInPlaceAtChunk(ref chunk, ref indexInChunk, value, valueCount); + ReplaceInPlaceAtChunk(ref chunk!, ref indexInChunk, value, valueCount); } } @@ -2089,7 +2113,7 @@ private unsafe void Insert(int index, char* value, int valueCount) /// /// This routine is very efficient because it does replacements in bulk. /// - private void ReplaceAllInChunk(int[] replacements, int replacementsCount, StringBuilder sourceChunk, int removeCount, string value) + private void ReplaceAllInChunk(int[]? replacements, int replacementsCount, StringBuilder sourceChunk, int removeCount, string value) { if (replacementsCount <= 0) { @@ -2100,6 +2124,7 @@ private void ReplaceAllInChunk(int[] replacements, int replacementsCount, String { fixed (char* valuePtr = value) { + Debug.Assert(replacements != null, "replacements was null when replacementsCount > 0"); // calculate the total amount of extra space or space needed for all the replacements. long longDelta = (value.Length - removeCount) * (long)replacementsCount; int delta = (int)longDelta; @@ -2117,7 +2142,7 @@ private void ReplaceAllInChunk(int[] replacements, int replacementsCount, String for (;;) { // Copy in the new string for the ith replacement - ReplaceInPlaceAtChunk(ref targetChunk, ref targetIndexInChunk, valuePtr, value.Length); + ReplaceInPlaceAtChunk(ref targetChunk!, ref targetIndexInChunk, valuePtr, value.Length); int gapStart = replacements[i] + removeCount; i++; if (i >= replacementsCount) @@ -2133,7 +2158,7 @@ private void ReplaceAllInChunk(int[] replacements, int replacementsCount, String { // Copy the gap data between the current replacement and the next replacement fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart]) - ReplaceInPlaceAtChunk(ref targetChunk, ref targetIndexInChunk, sourcePtr, gapEnd - gapStart); + ReplaceInPlaceAtChunk(ref targetChunk!, ref targetIndexInChunk, sourcePtr, gapEnd - gapStart); } else { @@ -2167,7 +2192,7 @@ private bool StartsWith(StringBuilder chunk, int indexInChunk, int count, string if (indexInChunk >= chunk.m_ChunkLength) { - chunk = Next(chunk); + chunk = Next(chunk)!; if (chunk == null) return false; indexInChunk = 0; @@ -2199,12 +2224,13 @@ private bool StartsWith(StringBuilder chunk, int indexInChunk, int count, string /// /// The pointer to the start of the character buffer. /// The number of characters in the buffer. - private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count) + private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder? chunk, ref int indexInChunk, char* value, int count) { if (count != 0) { for (;;) { + Debug.Assert(chunk != null, "chunk should not be null at this point"); int lengthInChunk = chunk.m_ChunkLength - indexInChunk; Debug.Assert(lengthInChunk >= 0, "Index isn't in the chunk."); @@ -2283,6 +2309,7 @@ private StringBuilder FindChunkForIndex(int index) StringBuilder result = this; while (result.m_ChunkOffset > index) { + Debug.Assert(result.m_ChunkPrevious != null); result = result.m_ChunkPrevious; } @@ -2301,6 +2328,7 @@ private StringBuilder FindChunkForByte(int byteIndex) StringBuilder result = this; while (result.m_ChunkOffset * sizeof(char) > byteIndex) { + Debug.Assert(result.m_ChunkPrevious != null); result = result.m_ChunkPrevious; } @@ -2325,7 +2353,7 @@ private Span RemainingCurrentChunk /// way down until it finds the specified chunk (which is O(n)). Thus, it is more expensive than /// a field fetch. /// - private StringBuilder Next(StringBuilder chunk) => chunk == this ? null : FindChunkForIndex(chunk.m_ChunkOffset + chunk.m_ChunkLength); + private StringBuilder? Next(StringBuilder chunk) => chunk == this ? null : FindChunkForIndex(chunk.m_ChunkOffset + chunk.m_ChunkLength); /// /// Transfers the character buffer from this chunk to a new chunk, and allocates a new buffer with a minimum size for this chunk. @@ -2438,6 +2466,7 @@ private void MakeRoom(int index, int count, out StringBuilder chunk, out int ind while (chunk.m_ChunkOffset > index) { chunk.m_ChunkOffset += count; + Debug.Assert(chunk.m_ChunkPrevious != null); chunk = chunk.m_ChunkPrevious; } indexInChunk = index - chunk.m_ChunkOffset; @@ -2498,7 +2527,7 @@ private void MakeRoom(int index, int count, out StringBuilder chunk, out int ind /// The size of the character buffer for this chunk. /// The maximum capacity, to be stored in this chunk. /// The predecessor of this chunk. - private StringBuilder(int size, int maxCapacity, StringBuilder previousBlock) + private StringBuilder(int size, int maxCapacity, StringBuilder? previousBlock) { Debug.Assert(size > 0); Debug.Assert(maxCapacity > 0); @@ -2532,7 +2561,7 @@ private void Remove(int startIndex, int count, out StringBuilder chunk, out int // Find the chunks for the start and end of the block to delete. chunk = this; - StringBuilder endChunk = null; + StringBuilder? endChunk = null; int endIndexInChunk = 0; for (;;) { @@ -2553,6 +2582,8 @@ private void Remove(int startIndex, int count, out StringBuilder chunk, out int { chunk.m_ChunkOffset -= count; } + + Debug.Assert(chunk.m_ChunkPrevious != null); chunk = chunk.m_ChunkPrevious; } Debug.Assert(chunk != null, "We fell off the beginning of the string!"); diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs index e699cc27ccfa..ebffbe42d79d 100644 --- a/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs +++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Text { /// Provide a cached reusable instance of stringbuilder per thread. @@ -18,7 +19,7 @@ internal static class StringBuilderCache // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools. // Get in touch with the diagnostics team if you have questions. [ThreadStatic] - private static StringBuilder t_cachedInstance; + private static StringBuilder? t_cachedInstance; /// Get a StringBuilder for the specified capacity. /// If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied. @@ -26,7 +27,7 @@ public static StringBuilder Acquire(int capacity = DefaultCapacity) { if (capacity <= MaxBuilderSize) { - StringBuilder sb = t_cachedInstance; + StringBuilder? sb = t_cachedInstance; if (sb != null) { // Avoid stringbuilder block fragmentation by getting a new StringBuilder @@ -39,6 +40,7 @@ public static StringBuilder Acquire(int capacity = DefaultCapacity) } } } + return new StringBuilder(capacity); } diff --git a/src/System.Private.CoreLib/shared/System/Text/StringRuneEnumerator.cs b/src/System.Private.CoreLib/shared/System/Text/StringRuneEnumerator.cs index fe12dfa4f74b..3528884d3fd2 100644 --- a/src/System.Private.CoreLib/shared/System/Text/StringRuneEnumerator.cs +++ b/src/System.Private.CoreLib/shared/System/Text/StringRuneEnumerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; @@ -50,7 +51,7 @@ public bool MoveNext() return true; } - object IEnumerator.Current => _current; + object? IEnumerator.Current => _current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 void IDisposable.Dispose() { diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs index 02f3167df2a4..1b81f17a1d31 100644 --- a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused. // @@ -125,7 +126,7 @@ public override unsafe int GetByteCount(char[] chars, int index, int count) public override unsafe int GetByteCount(string s) { // Validate input - if (s==null) + if (s == null) throw new ArgumentNullException(nameof(s)); fixed (char* pChars = s) @@ -362,8 +363,7 @@ public override unsafe string GetString(byte[] bytes, int index, int count) // // End of standard methods copied from EncodingNLS.cs // - - internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) + internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS? encoder) { Debug.Assert(chars != null, "[UTF32Encoding.GetByteCount]chars!=null"); Debug.Assert(count >= 0, "[UTF32Encoding.GetByteCount]count >=0"); @@ -375,7 +375,7 @@ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS enc char highSurrogate = '\0'; // For fallback we may need a fallback buffer - EncoderFallbackBuffer fallbackBuffer = null; + EncoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; if (encoder != null) @@ -385,7 +385,7 @@ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS enc // We mustn't have left over fallback data when counting if (fallbackBuffer.Remaining > 0) - throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType())); + throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback?.GetType().ToString() ?? string.Empty)); } else { @@ -495,7 +495,7 @@ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS enc } internal override unsafe int GetBytes(char* chars, int charCount, - byte* bytes, int byteCount, EncoderNLS encoder) + byte* bytes, int byteCount, EncoderNLS? encoder) { Debug.Assert(chars != null, "[UTF32Encoding.GetBytes]chars!=null"); Debug.Assert(bytes != null, "[UTF32Encoding.GetBytes]bytes!=null"); @@ -510,7 +510,7 @@ internal override unsafe int GetBytes(char* chars, int charCount, char highSurrogate = '\0'; // For fallback we may need a fallback buffer - EncoderFallbackBuffer fallbackBuffer = null; + EncoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; if (encoder != null) @@ -520,7 +520,7 @@ internal override unsafe int GetBytes(char* chars, int charCount, // We mustn't have left over fallback data when not converting if (encoder._throwOnOverflow && fallbackBuffer.Remaining > 0) - throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType())); + throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback!.GetType())); // TODO-NULLABLE: NullReferenceException } else { @@ -696,12 +696,12 @@ internal override unsafe int GetBytes(char* chars, int charCount, return (int)(bytes - byteStart); } - internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) + internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS? baseDecoder) { Debug.Assert(bytes != null, "[UTF32Encoding.GetCharCount]bytes!=null"); Debug.Assert(count >= 0, "[UTF32Encoding.GetCharCount]count >=0"); - UTF32Decoder decoder = (UTF32Decoder)baseDecoder; + UTF32Decoder? decoder = (UTF32Decoder?)baseDecoder; // None so far! int charCount = 0; @@ -713,7 +713,7 @@ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS bas uint iChar = 0; // For fallback we may need a fallback buffer - DecoderFallbackBuffer fallbackBuffer = null; + DecoderFallbackBuffer? fallbackBuffer = null; // See if there's anything in our decoder if (decoder != null) @@ -839,14 +839,14 @@ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS bas } internal override unsafe int GetChars(byte* bytes, int byteCount, - char* chars, int charCount, DecoderNLS baseDecoder) + char* chars, int charCount, DecoderNLS? baseDecoder) { Debug.Assert(chars != null, "[UTF32Encoding.GetChars]chars!=null"); Debug.Assert(bytes != null, "[UTF32Encoding.GetChars]bytes!=null"); Debug.Assert(byteCount >= 0, "[UTF32Encoding.GetChars]byteCount >=0"); Debug.Assert(charCount >= 0, "[UTF32Encoding.GetChars]charCount >=0"); - UTF32Decoder decoder = (UTF32Decoder)baseDecoder; + UTF32Decoder? decoder = (UTF32Decoder?)baseDecoder; // None so far! char* charStart = chars; @@ -860,7 +860,7 @@ internal override unsafe int GetChars(byte* bytes, int byteCount, uint iChar = 0; // For fallback we may need a fallback buffer - DecoderFallbackBuffer fallbackBuffer = null; + DecoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; // See if there's anything in our decoder @@ -868,6 +868,7 @@ internal override unsafe int GetChars(byte* bytes, int byteCount, { readCount = decoder.readByteCount; iChar = (uint)decoder.iChar; + Debug.Assert(baseDecoder != null); fallbackBuffer = baseDecoder.FallbackBuffer; // Shouldn't have anything in fallback buffer for GetChars @@ -1157,7 +1158,7 @@ public override byte[] GetPreamble() _bigEndian ? (ReadOnlySpan)new byte[4] { 0x00, 0x00, 0xFE, 0xFF } : // uses C# compiler's optimization for static byte[] data (ReadOnlySpan)new byte[4] { 0xFF, 0xFE, 0x00, 0x00 }; - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is UTF32Encoding that) { @@ -1166,7 +1167,8 @@ public override bool Equals(object value) (EncoderFallback.Equals(that.EncoderFallback)) && (DecoderFallback.Equals(that.DecoderFallback)); } - return (false); + + return false; } diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs index a932778b45d2..d398aec66b3b 100644 --- a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused. // @@ -32,15 +33,15 @@ public class UTF7Encoding : Encoding internal static readonly UTF7Encoding s_default = new UTF7Encoding(); // The set of base 64 characters. - private byte[] _base64Bytes; + private byte[] _base64Bytes = null!; // The decoded bits for every base64 values. This array has a size of 128 elements. // The index is the code point value of the base 64 characters. The value is -1 if // the code point is not a valid base 64 character. Otherwise, the value is a value // from 0 ~ 63. - private sbyte[] _base64Values; + private sbyte[] _base64Values = null!; // The array to decide if a Unicode code point below 0x80 can be directly encoded in UTF7. // This array has a size of 128. - private bool[] _directEncode; + private bool[] _directEncode = null!; private bool _allowOptionals; @@ -97,7 +98,7 @@ internal sealed override void SetDefaultFallbacks() this.decoderFallback = new DecoderUTF7Fallback(); } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is UTF7Encoding that) { @@ -105,7 +106,7 @@ public override bool Equals(object value) (EncoderFallback.Equals(that.EncoderFallback)) && (DecoderFallback.Equals(that.DecoderFallback)); } - return (false); + return false; } // Compared to all the other encodings, variations of UTF7 are unlikely @@ -157,7 +158,7 @@ public override unsafe int GetByteCount(char[] chars, int index, int count) public override unsafe int GetByteCount(string s) { // Validate input - if (s==null) + if (s == null) throw new ArgumentNullException(nameof(s)); fixed (char* pChars = s) @@ -394,8 +395,7 @@ public override unsafe string GetString(byte[] bytes, int index, int count) // // End of standard methods copied from EncodingNLS.cs // - - internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder) + internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS? baseEncoder) { Debug.Assert(chars != null, "[UTF7Encoding.GetByteCount]chars!=null"); Debug.Assert(count >= 0, "[UTF7Encoding.GetByteCount]count >=0"); @@ -405,14 +405,14 @@ internal sealed override unsafe int GetByteCount(char* chars, int count, Encoder } internal sealed override unsafe int GetBytes( - char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder) + char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS? baseEncoder) { Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetBytes]byteCount >=0"); Debug.Assert(chars != null, "[UTF7Encoding.GetBytes]chars!=null"); Debug.Assert(charCount >= 0, "[UTF7Encoding.GetBytes]charCount >=0"); // Get encoder info - UTF7Encoding.Encoder encoder = (UTF7Encoding.Encoder)baseEncoder; + UTF7Encoding.Encoder? encoder = (UTF7Encoding.Encoder?)baseEncoder; // Default bits & count int bits = 0; @@ -544,7 +544,7 @@ internal sealed override unsafe int GetBytes( return buffer.Count; } - internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) + internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS? baseDecoder) { Debug.Assert(count >= 0, "[UTF7Encoding.GetCharCount]count >=0"); Debug.Assert(bytes != null, "[UTF7Encoding.GetCharCount]bytes!=null"); @@ -554,14 +554,14 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder } internal sealed override unsafe int GetChars( - byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) + byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS? baseDecoder) { Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetChars]byteCount >=0"); Debug.Assert(bytes != null, "[UTF7Encoding.GetChars]bytes!=null"); Debug.Assert(charCount >= 0, "[UTF7Encoding.GetChars]charCount >=0"); // Might use a decoder - UTF7Encoding.Decoder decoder = (UTF7Encoding.Decoder)baseDecoder; + UTF7Encoding.Decoder? decoder = (UTF7Encoding.Decoder?)baseDecoder; // Get our output buffer info. Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer( @@ -843,7 +843,7 @@ internal override bool HasState { get { - return (this.bits != 0 || this.bitCount != -1); + return this.bits != 0 || this.bitCount != -1; } } } @@ -872,14 +872,14 @@ public override int MaxCharCount } } - public override bool Equals(object value) + public override bool Equals(object? value) { - DecoderUTF7Fallback that = value as DecoderUTF7Fallback; + DecoderUTF7Fallback? that = value as DecoderUTF7Fallback; if (that != null) { return true; } - return (false); + return false; } public override int GetHashCode() @@ -938,7 +938,7 @@ public override bool MovePrevious() } // return true if we were allowed to do this - return (iCount >= 0 && iCount <= iSize); + return iCount >= 0 && iCount <= iSize; } // Return # of chars left in this fallback diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs index aaac975ec887..688a431f055c 100644 --- a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs @@ -10,14 +10,13 @@ // The fast loops attempts to blaze through as fast as possible with optimistic range checks, // processing multiple characters at a time, and falling back to the slow loop for all special cases. -// This define can be used to turn off the fast loops. Useful for finding whether -// the problem is fastloop-specific. -#define FASTLOOP - +#nullable enable using System; +using System.Buffers; using System.Diagnostics; -using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Text.Unicode; namespace System.Text { @@ -129,22 +128,26 @@ internal sealed override void SetDefaultFallbacks() public override unsafe int GetByteCount(char[] chars, int index, int count) { // Validate input parameters - if (chars == null) - throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum); + if (chars is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars, ExceptionResource.ArgumentNull_Array); + } - if (chars.Length - index < count) - throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer); + if ((index | count) < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - // If no input, return 0, avoid fixed empty array problem - if (count == 0) - return 0; + if (chars!.Length - index < count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); + } - // Just call the pointer version fixed (char* pChars = chars) - return GetByteCount(pChars + index, count, null); + { + return GetByteCountCommon(pChars + index, count); + } } // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) @@ -154,12 +157,17 @@ public override unsafe int GetByteCount(char[] chars, int index, int count) public override unsafe int GetByteCount(string chars) { - // Validate input - if (chars==null) - throw new ArgumentNullException("s"); + // Validate input parameters + + if (chars is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars); + } fixed (char* pChars = chars) - return GetByteCount(pChars, chars.Length, null); + { + return GetByteCountCommon(pChars, chars!.Length); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + } } // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) @@ -170,24 +178,80 @@ public override unsafe int GetByteCount(string chars) public override unsafe int GetByteCount(char* chars, int count) { // Validate Parameters + if (chars == null) - throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array); + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.chars); + } if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - // Call it with empty encoder - return GetByteCount(chars, count, null); + return GetByteCountCommon(chars, count); } public override unsafe int GetByteCount(ReadOnlySpan chars) { - fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars)) + // It's ok for us to pass null pointers down to the workhorse below. + + fixed (char* charsPtr = &MemoryMarshal.GetReference(chars)) { - return GetByteCount(charsPtr, chars.Length, baseEncoder: null); + return GetByteCountCommon(charsPtr, chars.Length); } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe int GetByteCountCommon(char* pChars, int charCount) + { + // Common helper method for all non-EncoderNLS entry points to GetByteCount. + // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. + + Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer."); + Debug.Assert(pChars != null || charCount == 0, "Input pointer shouldn't be null if non-zero length specified."); + + // First call into the fast path. + // Don't bother providing a fallback mechanism; our fast path doesn't use it. + + int totalByteCount = GetByteCountFast(pChars, charCount, fallback: null, out int charsConsumed); + + if (charsConsumed != charCount) + { + // If there's still data remaining in the source buffer, go down the fallback path. + // We need to check for integer overflow since the fallback could change the required + // output count in unexpected ways. + + totalByteCount += GetByteCountWithFallback(pChars, charCount, charsConsumed); + if (totalByteCount < 0) + { + ThrowConversionOverflow(); + } + } + + return totalByteCount; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharCountCommon + private protected sealed override unsafe int GetByteCountFast(char* pChars, int charsLength, EncoderFallback? fallback, out int charsConsumed) + { + // The number of UTF-8 code units may exceed the number of UTF-16 code units, + // so we'll need to check for overflow before casting to Int32. + + char* ptrToFirstInvalidChar = Utf16Utility.GetPointerToFirstInvalidChar(pChars, charsLength, out long utf8CodeUnitCountAdjustment, out _); + + int tempCharsConsumed = (int)(ptrToFirstInvalidChar - pChars); + charsConsumed = tempCharsConsumed; + + long totalUtf8Bytes = tempCharsConsumed + utf8CodeUnitCountAdjustment; + if ((ulong)totalUtf8Bytes > int.MaxValue) + { + ThrowConversionOverflow(); + } + + return (int)totalUtf8Bytes; + } + // Parent method is safe. // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) // So if you fix this, fix the others. Currently those include: @@ -196,22 +260,37 @@ public override unsafe int GetByteCount(ReadOnlySpan chars) public override unsafe int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { - if (s == null || bytes == null) - throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array); + // Validate Parameters - if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum); + if (s is null || bytes is null) + { + ThrowHelper.ThrowArgumentNullException( + argument: (s is null) ? ExceptionArgument.s : ExceptionArgument.bytes, + resource: ExceptionResource.ArgumentNull_Array); + } - if (s.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount); + if ((charIndex | charCount) < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException( + argument: (charIndex < 0) ? ExceptionArgument.charIndex : ExceptionArgument.charCount, + resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - if (byteIndex < 0 || byteIndex > bytes.Length) - throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index); + if (s!.Length - charIndex < charCount) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.s, ExceptionResource.ArgumentOutOfRange_IndexCount); + } - int byteCount = bytes.Length - byteIndex; + if ((uint)byteIndex > bytes!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutOfRange_Index); + } - fixed (char* pChars = s) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span)bytes)) - return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null); + fixed (char* pChars = s) + fixed (byte* pBytes = bytes) + { + return GetBytesCommon(pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex); + } } // Encodes a range of characters in a character array into a range of bytes @@ -232,28 +311,36 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { // Validate parameters - if (chars == null || bytes == null) - throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array); - - if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum); - if (chars.Length - charIndex < charCount) - throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer); + if (chars is null || bytes is null) + { + ThrowHelper.ThrowArgumentNullException( + argument: (chars is null) ? ExceptionArgument.chars : ExceptionArgument.bytes, + resource: ExceptionResource.ArgumentNull_Array); + } - if (byteIndex < 0 || byteIndex > bytes.Length) - throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index); + if ((charIndex | charCount) < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException( + argument: (charIndex < 0) ? ExceptionArgument.charIndex : ExceptionArgument.charCount, + resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - // If nothing to encode return 0, avoid fixed problem - if (charCount == 0) - return 0; + if (chars!.Length - charIndex < charCount) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.chars, ExceptionResource.ArgumentOutOfRange_IndexCount); + } - // Just call pointer version - int byteCount = bytes.Length - byteIndex; + if ((uint)byteIndex > bytes!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.byteIndex, ExceptionResource.ArgumentOutOfRange_Index); + } - fixed (char* pChars = chars) fixed (byte* pBytes = &MemoryMarshal.GetReference((Span)bytes)) - // Remember that byteCount is # to decode, not size of array. - return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, null); + fixed (char* pChars = chars) + fixed (byte* pBytes = bytes) + { + return GetBytesCommon(pChars + charIndex, charCount, pBytes + byteIndex, bytes.Length - byteIndex); + } } // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) @@ -264,24 +351,77 @@ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount, public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { // Validate Parameters - if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array); - if (charCount < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum); + if (chars == null || bytes == null) + { + ThrowHelper.ThrowArgumentNullException( + argument: (chars is null) ? ExceptionArgument.chars : ExceptionArgument.bytes, + resource: ExceptionResource.ArgumentNull_Array); + } - return GetBytes(chars, charCount, bytes, byteCount, null); + if ((charCount | byteCount) < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException( + argument: (charCount < 0) ? ExceptionArgument.charCount : ExceptionArgument.byteCount, + resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + return GetBytesCommon(chars, charCount, bytes, byteCount); } public override unsafe int GetBytes(ReadOnlySpan chars, Span bytes) { - fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars)) - fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes)) + // It's ok for us to operate on null / empty spans. + + fixed (char* charsPtr = &MemoryMarshal.GetReference(chars)) + fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes)) + { + return GetBytesCommon(charsPtr, chars.Length, bytesPtr, bytes.Length); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe int GetBytesCommon(char* pChars, int charCount, byte* pBytes, int byteCount) + { + // Common helper method for all non-EncoderNLS entry points to GetBytes. + // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. + + Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer."); + Debug.Assert(pChars != null || charCount == 0, "Input pointer shouldn't be null if non-zero length specified."); + Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer."); + Debug.Assert(pBytes != null || byteCount == 0, "Input pointer shouldn't be null if non-zero length specified."); + + // First call into the fast path. + + int bytesWritten = GetBytesFast(pChars, charCount, pBytes, byteCount, out int charsConsumed); + + if (charsConsumed == charCount) + { + // All elements converted - return immediately. + + return bytesWritten; + } + else { - return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, baseEncoder: null); + // Simple narrowing conversion couldn't operate on entire buffer - invoke fallback. + + return GetBytesWithFallback(pChars, charCount, pBytes, byteCount, charsConsumed, bytesWritten); } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetBytesCommon + private protected sealed override unsafe int GetBytesFast(char* pChars, int charsLength, byte* pBytes, int bytesLength, out int charsConsumed) + { + // We don't care about the exact OperationStatus value returned by the workhorse routine; we only + // care if the workhorse was able to consume the entire input payload. If we're unable to do so, + // we'll handle the remainder in the fallback routine. + + Utf8Utility.TranscodeToUtf8(pChars, charsLength, pBytes, bytesLength, out char* pInputBufferRemaining, out byte* pOutputBufferRemaining); + + charsConsumed = (int)(pInputBufferRemaining - pChars); + return (int)(pOutputBufferRemaining - pBytes); + } + // Returns the number of characters produced by decoding a range of bytes // in a byte array. // @@ -293,22 +433,26 @@ public override unsafe int GetBytes(ReadOnlySpan chars, Span bytes) public override unsafe int GetCharCount(byte[] bytes, int index, int count) { // Validate Parameters - if (bytes == null) - throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum); + if (bytes is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array); + } - if (bytes.Length - index < count) - throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer); + if ((index | count) < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - // If no input just return 0, fixed doesn't like 0 length arrays. - if (count == 0) - return 0; + if (bytes!.Length - index < count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); + } - // Just call pointer version fixed (byte* pBytes = bytes) - return GetCharCount(pBytes + index, count, null); + { + return GetCharCountCommon(pBytes + index, count); + } } // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) @@ -319,20 +463,27 @@ public override unsafe int GetCharCount(byte[] bytes, int index, int count) public override unsafe int GetCharCount(byte* bytes, int count) { // Validate Parameters + if (bytes == null) - throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array); + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array); + } if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum); + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - return GetCharCount(bytes, count, null); + return GetCharCountCommon(bytes, count); } public override unsafe int GetCharCount(ReadOnlySpan bytes) { - fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes)) + // It's ok for us to pass null pointers down to the workhorse routine. + + fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes)) { - return GetCharCount(bytesPtr, bytes.Length, baseDecoder: null); + return GetCharCountCommon(bytesPtr, bytes.Length); } } @@ -345,28 +496,36 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { // Validate Parameters - if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array); - - if (byteIndex < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum); - if ( bytes.Length - byteIndex < byteCount) - throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer); + if (bytes is null || chars is null) + { + ThrowHelper.ThrowArgumentNullException( + argument: (bytes is null) ? ExceptionArgument.bytes : ExceptionArgument.chars, + resource: ExceptionResource.ArgumentNull_Array); + } - if (charIndex < 0 || charIndex > chars.Length) - throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index); + if ((byteIndex | byteCount) < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException( + argument: (byteIndex < 0) ? ExceptionArgument.byteIndex : ExceptionArgument.byteCount, + resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } - // If no input, return 0 & avoid fixed problem - if (byteCount == 0) - return 0; + if (bytes!.Length - byteIndex < byteCount) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); + } - // Just call pointer version - int charCount = chars.Length - charIndex; + if ((uint)charIndex > (uint)chars!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.charIndex, ExceptionResource.ArgumentOutOfRange_Index); + } - fixed (byte* pBytes = bytes) fixed (char* pChars = &MemoryMarshal.GetReference((Span)chars)) - // Remember that charCount is # to decode, not size of array - return GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, null); + fixed (byte* pBytes = bytes) + fixed (char* pChars = chars) + { + return GetCharsCommon(pBytes + byteIndex, byteCount, pChars + charIndex, chars.Length - charIndex); + } } // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) @@ -377,2120 +536,245 @@ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount, public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { // Validate Parameters - if (bytes == null || chars == null) - throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array); - - if (charCount < 0 || byteCount < 0) - throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum); - return GetChars(bytes, byteCount, chars, charCount, null); - } + if (bytes is null || chars is null) + { + ThrowHelper.ThrowArgumentNullException( + argument: (bytes is null) ? ExceptionArgument.bytes : ExceptionArgument.chars, + resource: ExceptionResource.ArgumentNull_Array); + } - public override unsafe int GetChars(ReadOnlySpan bytes, Span chars) - { - fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes)) - fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars)) + if ((byteCount | charCount) < 0) { - return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, baseDecoder: null); + ThrowHelper.ThrowArgumentOutOfRangeException( + argument: (byteCount < 0) ? ExceptionArgument.byteCount : ExceptionArgument.charCount, + resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - } - // Returns a string containing the decoded representation of a range of - // bytes in a byte array. - // - // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) - // So if you fix this, fix the others. Currently those include: - // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding - // parent method is safe + return GetCharsCommon(bytes, byteCount, chars, charCount); + } - public override unsafe string GetString(byte[] bytes, int index, int count) + public override unsafe int GetChars(ReadOnlySpan bytes, Span chars) { - // Validate Parameters - if (bytes == null) - throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array); - - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum); + // It's ok for us to pass null pointers down to the workhorse below. - if (bytes.Length - index < count) - throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer); - - // Avoid problems with empty input buffer - if (count == 0) return string.Empty; - - fixed (byte* pBytes = bytes) - return string.CreateStringFromEncoding( - pBytes + index, count, this); + fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes)) + fixed (char* charsPtr = &MemoryMarshal.GetReference(chars)) + { + return GetCharsCommon(bytesPtr, bytes.Length, charsPtr, chars.Length); + } } + // WARNING: If we throw an error, then System.Resources.ResourceReader calls this method. + // So if we're really broken, then that could also throw an error... recursively. + // So try to make sure GetChars can at least process all uses by + // System.Resources.ResourceReader! // - // End of standard methods copied from EncodingNLS.cs - // - - // To simplify maintenance, the structure of GetByteCount and GetBytes should be - // kept the same as much as possible - internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder) + // Note: We throw exceptions on individually encoded surrogates and other non-shortest forms. + // If exceptions aren't turned on, then we drop all non-shortest &individual surrogates. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe int GetCharsCommon(byte* pBytes, int byteCount, char* pChars, int charCount) { - // For fallback we may need a fallback buffer. - // We wait to initialize it though in case we don't have any broken input unicode - EncoderFallbackBuffer fallbackBuffer = null; - char* pSrcForFallback; + // Common helper method for all non-DecoderNLS entry points to GetChars. + // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. - char* pSrc = chars; - char* pEnd = pSrc + count; + Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer."); + Debug.Assert(pBytes != null || byteCount == 0, "Input pointer shouldn't be null if non-zero length specified."); + Debug.Assert(charCount >= 0, "Caller shouldn't specify negative length buffer."); + Debug.Assert(pChars != null || charCount == 0, "Input pointer shouldn't be null if non-zero length specified."); - // Start by assuming we have as many as count - int byteCount = count; + // First call into the fast path. - int ch = 0; + int charsWritten = GetCharsFast(pBytes, byteCount, pChars, charCount, out int bytesConsumed); - if (baseEncoder != null) + if (bytesConsumed == byteCount) { - UTF8Encoder encoder = (UTF8Encoder)baseEncoder; - ch = encoder.surrogateChar; + // All elements converted - return immediately. - // We mustn't have left over fallback data when counting - if (encoder.InternalHasFallbackBuffer) - { - fallbackBuffer = encoder.FallbackBuffer; - if (fallbackBuffer.Remaining > 0) - throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType())); - - // Set our internal fallback interesting things. - fallbackBuffer.InternalInitialize(chars, pEnd, encoder, false); - } + return charsWritten; } - - for (;;) + else { - // SLOWLOOP: does all range checks, handles all special cases, but it is slow - if (pSrc >= pEnd) - { - if (ch == 0) - { - // Unroll any fallback that happens at the end - ch = fallbackBuffer != null ? fallbackBuffer.InternalGetNextChar() : 0; - if (ch > 0) - { - byteCount++; - goto ProcessChar; - } - } - else - { - // Case of surrogates in the fallback. - if (fallbackBuffer != null && fallbackBuffer.bFallingBack) - { - Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, - "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); - - ch = fallbackBuffer.InternalGetNextChar(); - byteCount++; - - if (InRange(ch, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - ch = 0xfffd; - byteCount++; - goto EncodeChar; - } - else if (ch > 0) - { - goto ProcessChar; - } - else - { - byteCount--; // ignore last one. - break; - } - } - } - - if (ch <= 0) - { - break; - } - if (baseEncoder != null && !baseEncoder.MustFlush) - { - break; - } - - // attempt to encode the partial surrogate (will fallback or ignore it), it'll also subtract 1. - byteCount++; - goto EncodeChar; - } - - if (ch > 0) - { - Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, - "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); - - // use separate helper variables for local contexts so that the jit optimizations - // won't get confused about the variable lifetimes - int cha = *pSrc; - - // count the pending surrogate - byteCount++; - - // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here. - // if (IsLowSurrogate(cha)) { - if (InRange(cha, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // Don't need a real # because we're just counting, anything > 0x7ff ('cept surrogate) will do. - ch = 0xfffd; - // ch = cha + (ch << 10) + - // (0x10000 - // - CharUnicodeInfo.LOW_SURROGATE_START - // - (CharUnicodeInfo.HIGH_SURROGATE_START << 10) ); - - // Use this next char - pSrc++; - } - // else ch is still high surrogate and encoding will fail (so don't add count) - - // attempt to encode the surrogate or partial surrogate - goto EncodeChar; - } - - // If we've used a fallback, then we have to check for it - if (fallbackBuffer != null) - { - ch = fallbackBuffer.InternalGetNextChar(); - if (ch > 0) - { - // We have an extra byte we weren't expecting. - byteCount++; - goto ProcessChar; - } - } - - // read next char. The JIT optimization seems to be getting confused when - // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead - ch = *pSrc; - pSrc++; + // Simple narrowing conversion couldn't operate on entire buffer - invoke fallback. - ProcessChar: - // if (IsHighSurrogate(ch)) { - if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.HIGH_SURROGATE_END)) - { - // we will count this surrogate next time around - byteCount--; - continue; - } - // either good char or partial surrogate - - EncodeChar: - // throw exception on partial surrogate if necessary - // if (IsLowSurrogate(ch) || IsHighSurrogate(ch)) - if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // Lone surrogates aren't allowed - // Have to make a fallback buffer if we don't have one - if (fallbackBuffer == null) - { - // wait on fallbacks if we can - // For fallback we may need a fallback buffer - if (baseEncoder == null) - fallbackBuffer = this.encoderFallback.CreateFallbackBuffer(); - else - fallbackBuffer = baseEncoder.FallbackBuffer; - - // Set our internal fallback interesting things. - fallbackBuffer.InternalInitialize(chars, chars + count, baseEncoder, false); - } - - // Do our fallback. Actually we already know its a mixed up surrogate, - // so the ref pSrc isn't gonna do anything. - pSrcForFallback = pSrc; // Avoid passing pSrc by reference to allow it to be en-registered - fallbackBuffer.InternalFallback(unchecked((char)ch), ref pSrcForFallback); - pSrc = pSrcForFallback; - - // Ignore it if we don't throw (we had preallocated this ch) - byteCount--; - ch = 0; - continue; - } - - // Count them - if (ch > 0x7F) - { - if (ch > 0x7FF) - { - // the extra surrogate byte was compensated by the second surrogate character - // (2 surrogates make 4 bytes. We've already counted 2 bytes, 1 per char) - byteCount++; - } - byteCount++; - } - -#if BIT64 - // check for overflow - if (byteCount < 0) - { - break; - } -#endif - -#if FASTLOOP - // If still have fallback don't do fast loop - if (fallbackBuffer != null && (ch = fallbackBuffer.InternalGetNextChar()) != 0) - { - // We're reserving 1 byte for each char by default - byteCount++; - goto ProcessChar; - } - - int availableChars = PtrDiff(pEnd, pSrc); - - // don't fall into the fast decoding loop if we don't have enough characters - if (availableChars <= 13) - { - // try to get over the remainder of the ascii characters fast though - char* pLocalEnd = pEnd; // hint to get pLocalEnd en-registered - while (pSrc < pLocalEnd) - { - ch = *pSrc; - pSrc++; - if (ch > 0x7F) - goto ProcessChar; - } - - // we are done - break; - } - -#if BIT64 - // make sure that we won't get a silent overflow inside the fast loop - // (Fall out to slow loop if we have this many characters) - availableChars &= 0x0FFFFFFF; -#endif - - // To compute the upper bound, assume that all characters are ASCII characters at this point, - // the boundary will be decreased for every non-ASCII character we encounter - // Also, we need 3 + 4 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates - char* pStop = pSrc + availableChars - (3 + 4); - - while (pSrc < pStop) - { - ch = *pSrc; - pSrc++; - - if (ch > 0x7F) // Not ASCII - { - if (ch > 0x7FF) // Not 2 Byte - { - if ((ch & 0xF800) == 0xD800) // See if its a Surrogate - goto LongCode; - byteCount++; - } - byteCount++; - } - - // get pSrc aligned - if ((unchecked((int)pSrc) & 0x2) != 0) - { - ch = *pSrc; - pSrc++; - if (ch > 0x7F) // Not ASCII - { - if (ch > 0x7FF) // Not 2 Byte - { - if ((ch & 0xF800) == 0xD800) // See if its a Surrogate - goto LongCode; - byteCount++; - } - byteCount++; - } - } - - // Run 2 * 4 characters at a time! - while (pSrc < pStop) - { - ch = *(int*)pSrc; - int chc = *(int*)(pSrc + 2); - if (((ch | chc) & unchecked((int)0xFF80FF80)) != 0) // See if not ASCII - { - if (((ch | chc) & unchecked((int)0xF800F800)) != 0) // See if not 2 Byte - { - goto LongCodeWithMask; - } - - - if ((ch & unchecked((int)0xFF800000)) != 0) // Actually 0x07800780 is all we care about (4 bits) - byteCount++; - if ((ch & unchecked((int)0xFF80)) != 0) - byteCount++; - if ((chc & unchecked((int)0xFF800000)) != 0) - byteCount++; - if ((chc & unchecked((int)0xFF80)) != 0) - byteCount++; - } - pSrc += 4; - - ch = *(int*)pSrc; - chc = *(int*)(pSrc + 2); - if (((ch | chc) & unchecked((int)0xFF80FF80)) != 0) // See if not ASCII - { - if (((ch | chc) & unchecked((int)0xF800F800)) != 0) // See if not 2 Byte - { - goto LongCodeWithMask; - } - - if ((ch & unchecked((int)0xFF800000)) != 0) - byteCount++; - if ((ch & unchecked((int)0xFF80)) != 0) - byteCount++; - if ((chc & unchecked((int)0xFF800000)) != 0) - byteCount++; - if ((chc & unchecked((int)0xFF80)) != 0) - byteCount++; - } - pSrc += 4; - } - break; - - LongCodeWithMask: - if (BitConverter.IsLittleEndian) - { - ch = (char)ch; - } - else - { - // be careful about the sign extension - ch = (int)(((uint)ch) >> 16); - } - pSrc++; - - if (ch <= 0x7F) - { - continue; - } - - LongCode: - // use separate helper variables for slow and fast loop so that the jit optimizations - // won't get confused about the variable lifetimes - if (ch > 0x7FF) - { - // if (IsLowSurrogate(ch) || IsHighSurrogate(ch)) - if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // 4 byte encoding - high surrogate + low surrogate - - int chd = *pSrc; - if ( - // !IsHighSurrogate(ch) // low without high -> bad - ch > CharUnicodeInfo.HIGH_SURROGATE_END || - // !IsLowSurrogate(chd) // high not followed by low -> bad - !InRange(chd, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // Back up and drop out to slow loop to figure out error - pSrc--; - break; - } - pSrc++; - - // byteCount - this byte is compensated by the second surrogate character - } - byteCount++; - } - byteCount++; - - // byteCount - the last byte is already included - } -#endif // FASTLOOP - - // no pending char at this point - ch = 0; + return GetCharsWithFallback(pBytes, byteCount, pChars, charCount, bytesConsumed, charsWritten); } - -#if BIT64 - // check for overflow - if (byteCount < 0) - { - throw new ArgumentException( - SR.Argument_ConversionOverflow); - } -#endif - - Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, - "[UTF8Encoding.GetByteCount]Expected Empty fallback buffer"); - - return byteCount; } - // diffs two char pointers using unsigned arithmetic. The unsigned arithmetic - // is good enough for us, and it tends to generate better code than the signed - // arithmetic generated by default - private static unsafe int PtrDiff(char* a, char* b) + [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharsCommon + private protected sealed override unsafe int GetCharsFast(byte* pBytes, int bytesLength, char* pChars, int charsLength, out int bytesConsumed) { - return (int)(((uint)((byte*)a - (byte*)b)) >> 1); - } + // We don't care about the exact OperationStatus value returned by the workhorse routine; we only + // care if the workhorse was able to consume the entire input payload. If we're unable to do so, + // we'll handle the remainder in the fallback routine. - // byte* flavor just for parity - private static unsafe int PtrDiff(byte* a, byte* b) - { - return (int)(a - b); - } + Utf8Utility.TranscodeToUtf16(pBytes, bytesLength, pChars, charsLength, out byte* pInputBufferRemaining, out char* pOutputBufferRemaining); - private static bool InRange(int ch, int start, int end) - { - return (uint)(ch - start) <= (uint)(end - start); + bytesConsumed = (int)(pInputBufferRemaining - pBytes); + return (int)(pOutputBufferRemaining - pChars); } - // Our workhorse - // Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw - internal sealed override unsafe int GetBytes( - char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder) + private protected sealed override unsafe int GetCharsWithFallback(ReadOnlySpan bytes, int originalBytesLength, Span chars, int originalCharsLength, DecoderNLS? decoder) { - Debug.Assert(chars != null, "[UTF8Encoding.GetBytes]chars!=null"); - Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetBytes]byteCount >=0"); - Debug.Assert(charCount >= 0, "[UTF8Encoding.GetBytes]charCount >=0"); - Debug.Assert(bytes != null, "[UTF8Encoding.GetBytes]bytes!=null"); - - UTF8Encoder encoder = null; - - // For fallback we may need a fallback buffer. - // We wait to initialize it though in case we don't have any broken input unicode - EncoderFallbackBuffer fallbackBuffer = null; - char* pSrcForFallback; - - char* pSrc = chars; - byte* pTarget = bytes; + // We special-case DecoderReplacementFallback if it's telling us to write a single U+FFFD char, + // since we believe this to be relatively common and we can handle it more efficiently than + // the base implementation. - char* pEnd = pSrc + charCount; - byte* pAllocatedBufferEnd = pTarget + byteCount; - - int ch = 0; - - // assume that JIT will en-register pSrc, pTarget and ch - - if (baseEncoder != null) + if (((decoder is null) ? this.DecoderFallback : decoder.Fallback) is DecoderReplacementFallback replacementFallback + && replacementFallback.MaxCharCount == 1 + && replacementFallback.DefaultString[0] == UnicodeUtility.ReplacementChar) { - encoder = (UTF8Encoder)baseEncoder; - ch = encoder.surrogateChar; + // Don't care about the exact OperationStatus, just how much of the payload we were able + // to process. - // We mustn't have left over fallback data when counting - if (encoder.InternalHasFallbackBuffer) - { - // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary - fallbackBuffer = encoder.FallbackBuffer; - if (fallbackBuffer.Remaining > 0 && encoder._throwOnOverflow) - throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType())); - - // Set our internal fallback interesting things. - fallbackBuffer.InternalInitialize(chars, pEnd, encoder, true); - } - } + Utf8.ToUtf16(bytes, chars, out int bytesRead, out int charsWritten, replaceInvalidSequences: true, isFinalBlock: decoder is null || decoder.MustFlush); - for (;;) - { - // SLOWLOOP: does all range checks, handles all special cases, but it is slow - - if (pSrc >= pEnd) - { - if (ch == 0) - { - // Check if there's anything left to get out of the fallback buffer - ch = fallbackBuffer != null ? fallbackBuffer.InternalGetNextChar() : 0; - if (ch > 0) - { - goto ProcessChar; - } - } - else - { - // Case of leftover surrogates in the fallback buffer - if (fallbackBuffer != null && fallbackBuffer.bFallingBack) - { - Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, - "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); - - int cha = ch; - - ch = fallbackBuffer.InternalGetNextChar(); - - if (InRange(ch, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - ch = ch + (cha << 10) + (0x10000 - CharUnicodeInfo.LOW_SURROGATE_START - (CharUnicodeInfo.HIGH_SURROGATE_START << 10)); - goto EncodeChar; - } - else if (ch > 0) - { - goto ProcessChar; - } - else - { - break; - } - } - } - - // attempt to encode the partial surrogate (will fail or ignore) - if (ch > 0 && (encoder == null || encoder.MustFlush)) - goto EncodeChar; - - // We're done - break; - } - - if (ch > 0) - { - // We have a high surrogate left over from a previous loop. - Debug.Assert(ch >= 0xD800 && ch <= 0xDBFF, - "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture)); - - // use separate helper variables for local contexts so that the jit optimizations - // won't get confused about the variable lifetimes - int cha = *pSrc; - - // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here. - // if (IsLowSurrogate(cha)) { - if (InRange(cha, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - ch = cha + (ch << 10) + - (0x10000 - - CharUnicodeInfo.LOW_SURROGATE_START - - (CharUnicodeInfo.HIGH_SURROGATE_START << 10)); - - pSrc++; - } - // else ch is still high surrogate and encoding will fail - - // attempt to encode the surrogate or partial surrogate - goto EncodeChar; - } - - // If we've used a fallback, then we have to check for it - if (fallbackBuffer != null) - { - ch = fallbackBuffer.InternalGetNextChar(); - if (ch > 0) goto ProcessChar; - } - - // read next char. The JIT optimization seems to be getting confused when - // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead - ch = *pSrc; - pSrc++; - - ProcessChar: - // if (IsHighSurrogate(ch)) { - if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.HIGH_SURROGATE_END)) - { - continue; - } - // either good char or partial surrogate + // Slice off how much we consumed / wrote. - EncodeChar: - // throw exception on partial surrogate if necessary - // if (IsLowSurrogate(ch) || IsHighSurrogate(ch)) - if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // Lone surrogates aren't allowed, we have to do fallback for them - // Have to make a fallback buffer if we don't have one - if (fallbackBuffer == null) - { - // wait on fallbacks if we can - // For fallback we may need a fallback buffer - if (baseEncoder == null) - fallbackBuffer = this.encoderFallback.CreateFallbackBuffer(); - else - fallbackBuffer = baseEncoder.FallbackBuffer; - - // Set our internal fallback interesting things. - fallbackBuffer.InternalInitialize(chars, pEnd, baseEncoder, true); - } - - // Do our fallback. Actually we already know its a mixed up surrogate, - // so the ref pSrc isn't gonna do anything. - pSrcForFallback = pSrc; // Avoid passing pSrc by reference to allow it to be en-registered - fallbackBuffer.InternalFallback(unchecked((char)ch), ref pSrcForFallback); - pSrc = pSrcForFallback; - - // Ignore it if we don't throw - ch = 0; - continue; - } - - // Count bytes needed - int bytesNeeded = 1; - if (ch > 0x7F) - { - if (ch > 0x7FF) - { - if (ch > 0xFFFF) - { - bytesNeeded++; // 4 bytes (surrogate pair) - } - bytesNeeded++; // 3 bytes (800-FFFF) - } - bytesNeeded++; // 2 bytes (80-7FF) - } - - if (pTarget > pAllocatedBufferEnd - bytesNeeded) - { - // Left over surrogate from last time will cause pSrc == chars, so we'll throw - if (fallbackBuffer != null && fallbackBuffer.bFallingBack) - { - fallbackBuffer.MovePrevious(); // Didn't use this fallback char - if (ch > 0xFFFF) - fallbackBuffer.MovePrevious(); // Was surrogate, didn't use 2nd part either - } - else - { - pSrc--; // Didn't use this char - if (ch > 0xFFFF) - pSrc--; // Was surrogate, didn't use 2nd part either - } - Debug.Assert(pSrc >= chars || pTarget == bytes, - "[UTF8Encoding.GetBytes]Expected pSrc to be within buffer or to throw with insufficient room."); - ThrowBytesOverflow(encoder, pTarget == bytes); // Throw if we must - ch = 0; // Nothing left over (we backed up to start of pair if supplementary) - break; - } - - if (ch <= 0x7F) - { - *pTarget = (byte)ch; - } - else - { - // use separate helper variables for local contexts so that the jit optimizations - // won't get confused about the variable lifetimes - int chb; - if (ch <= 0x7FF) - { - // 2 byte encoding - chb = (byte)(unchecked((sbyte)0xC0) | (ch >> 6)); - } - else - { - if (ch <= 0xFFFF) - { - chb = (byte)(unchecked((sbyte)0xE0) | (ch >> 12)); - } - else - { - *pTarget = (byte)(unchecked((sbyte)0xF0) | (ch >> 18)); - pTarget++; - - chb = unchecked((sbyte)0x80) | (ch >> 12) & 0x3F; - } - *pTarget = (byte)chb; - pTarget++; - - chb = unchecked((sbyte)0x80) | (ch >> 6) & 0x3F; - } - *pTarget = (byte)chb; - pTarget++; - - *pTarget = (byte)(unchecked((sbyte)0x80) | ch & 0x3F); - } - pTarget++; - - -#if FASTLOOP - // If still have fallback don't do fast loop - if (fallbackBuffer != null && (ch = fallbackBuffer.InternalGetNextChar()) != 0) - goto ProcessChar; - - int availableChars = PtrDiff(pEnd, pSrc); - int availableBytes = PtrDiff(pAllocatedBufferEnd, pTarget); - - // don't fall into the fast decoding loop if we don't have enough characters - // Note that if we don't have enough bytes, pStop will prevent us from entering the fast loop. - if (availableChars <= 13) - { - // we are hoping for 1 byte per char - if (availableBytes < availableChars) - { - // not enough output room. no pending bits at this point - ch = 0; - continue; - } - - // try to get over the remainder of the ascii characters fast though - char* pLocalEnd = pEnd; // hint to get pLocalEnd en-registered - while (pSrc < pLocalEnd) - { - ch = *pSrc; - pSrc++; - - // Not ASCII, need more than 1 byte per char - if (ch > 0x7F) - goto ProcessChar; - - *pTarget = (byte)ch; - pTarget++; - } - // we are done, let ch be 0 to clear encoder - ch = 0; - break; - } - - // we need at least 1 byte per character, but Convert might allow us to convert - // only part of the input, so try as much as we can. Reduce charCount if necessary - if (availableBytes < availableChars) - { - availableChars = availableBytes; - } - - // FASTLOOP: - // - optimistic range checks - // - fallbacks to the slow loop for all special cases, exception throwing, etc. - - // To compute the upper bound, assume that all characters are ASCII characters at this point, - // the boundary will be decreased for every non-ASCII character we encounter - // Also, we need 5 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates - // If there aren't enough bytes for the output, then pStop will be <= pSrc and will bypass the loop. - char* pStop = pSrc + availableChars - 5; - - while (pSrc < pStop) - { - ch = *pSrc; - pSrc++; - - if (ch > 0x7F) - { - goto LongCode; - } - *pTarget = (byte)ch; - pTarget++; - - // get pSrc aligned - if ((unchecked((int)pSrc) & 0x2) != 0) - { - ch = *pSrc; - pSrc++; - if (ch > 0x7F) - { - goto LongCode; - } - *pTarget = (byte)ch; - pTarget++; - } - - // Run 4 characters at a time! - while (pSrc < pStop) - { - ch = *(int*)pSrc; - int chc = *(int*)(pSrc + 2); - if (((ch | chc) & unchecked((int)0xFF80FF80)) != 0) - { - goto LongCodeWithMask; - } - - // Unfortunately, this is endianess sensitive - if (BitConverter.IsLittleEndian) - { - *pTarget = (byte)ch; - *(pTarget + 1) = (byte)(ch >> 16); - pSrc += 4; - *(pTarget + 2) = (byte)chc; - *(pTarget + 3) = (byte)(chc >> 16); - pTarget += 4; - } - else - { - *pTarget = (byte)(ch>>16); - *(pTarget+1) = (byte)ch; - pSrc += 4; - *(pTarget+2) = (byte)(chc>>16); - *(pTarget+3) = (byte)chc; - pTarget += 4; - } - } - continue; - - LongCodeWithMask: - if (BitConverter.IsLittleEndian) - { - ch = (char)ch; - } - else - { - // be careful about the sign extension - ch = (int)(((uint)ch) >> 16); - } - pSrc++; - - if (ch > 0x7F) - { - goto LongCode; - } - *pTarget = (byte)ch; - pTarget++; - continue; - - LongCode: - // use separate helper variables for slow and fast loop so that the jit optimizations - // won't get confused about the variable lifetimes - int chd; - if (ch <= 0x7FF) - { - // 2 byte encoding - chd = unchecked((sbyte)0xC0) | (ch >> 6); - } - else - { - // if (!IsLowSurrogate(ch) && !IsHighSurrogate(ch)) - if (!InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // 3 byte encoding - chd = unchecked((sbyte)0xE0) | (ch >> 12); - } - else - { - // 4 byte encoding - high surrogate + low surrogate - // if (!IsHighSurrogate(ch)) - if (ch > CharUnicodeInfo.HIGH_SURROGATE_END) - { - // low without high -> bad, try again in slow loop - pSrc -= 1; - break; - } - - chd = *pSrc; - pSrc++; - - // if (!IsLowSurrogate(chd)) { - if (!InRange(chd, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) - { - // high not followed by low -> bad, try again in slow loop - pSrc -= 2; - break; - } - - ch = chd + (ch << 10) + - (0x10000 - - CharUnicodeInfo.LOW_SURROGATE_START - - (CharUnicodeInfo.HIGH_SURROGATE_START << 10)); - - *pTarget = (byte)(unchecked((sbyte)0xF0) | (ch >> 18)); - // pStop - this byte is compensated by the second surrogate character - // 2 input chars require 4 output bytes. 2 have been anticipated already - // and 2 more will be accounted for by the 2 pStop-- calls below. - pTarget++; - - chd = unchecked((sbyte)0x80) | (ch >> 12) & 0x3F; - } - *pTarget = (byte)chd; - pStop--; // 3 byte sequence for 1 char, so need pStop-- and the one below too. - pTarget++; - - chd = unchecked((sbyte)0x80) | (ch >> 6) & 0x3F; - } - *pTarget = (byte)chd; - pStop--; // 2 byte sequence for 1 char so need pStop--. - pTarget++; - - *pTarget = (byte)(unchecked((sbyte)0x80) | ch & 0x3F); - // pStop - this byte is already included - pTarget++; - } - - Debug.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetBytes]pTarget <= pAllocatedBufferEnd"); + bytes = bytes.Slice(bytesRead); + chars = chars.Slice(charsWritten); + } -#endif // FASTLOOP + // If we couldn't go through our fast fallback mechanism, or if we still have leftover + // data because we couldn't consume everything in the loop above, we need to go down the + // slow fallback path. - // no pending char at this point - ch = 0; + if (bytes.IsEmpty) + { + return originalCharsLength - chars.Length; // total number of chars written } - - // Do we have to set the encoder bytes? - if (encoder != null) + else { - Debug.Assert(!encoder.MustFlush || ch == 0, - "[UTF8Encoding.GetBytes] Expected no mustflush or 0 leftover ch " + ch.ToString("X2", CultureInfo.InvariantCulture)); - - encoder.surrogateChar = ch; - encoder._charsUsed = (int)(pSrc - chars); + return base.GetCharsWithFallback(bytes, originalBytesLength, chars, originalCharsLength, decoder); } - - Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 || - baseEncoder == null || !baseEncoder._throwOnOverflow, - "[UTF8Encoding.GetBytes]Expected empty fallback buffer if not converting"); - - return (int)(pTarget - bytes); } - - // These are bitmasks used to maintain the state in the decoder. They occupy the higher bits - // while the actual character is being built in the lower bits. They are shifted together - // with the actual bits of the character. - - // bits 30 & 31 are used for pending bits fixup - private const int FinalByte = 1 << 29; - private const int SupplimentarySeq = 1 << 28; - private const int ThreeByteSeq = 1 << 27; - - // Note: We throw exceptions on individually encoded surrogates and other non-shortest forms. - // If exceptions aren't turned on, then we drop all non-shortest &individual surrogates. + // Returns a string containing the decoded representation of a range of + // bytes in a byte array. // - // To simplify maintenance, the structure of GetCharCount and GetChars should be - // kept the same as much as possible - internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) - { - Debug.Assert(count >= 0, "[UTF8Encoding.GetCharCount]count >=0"); - Debug.Assert(bytes != null, "[UTF8Encoding.GetCharCount]bytes!=null"); - - // Initialize stuff - byte* pSrc = bytes; - byte* pEnd = pSrc + count; + // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS) + // So if you fix this, fix the others. Currently those include: + // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding + // parent method is safe - // Start by assuming we have as many as count, charCount always includes the adjustment - // for the character being decoded - int charCount = count; - int ch = 0; - DecoderFallbackBuffer fallback = null; + public override unsafe string GetString(byte[] bytes, int index, int count) + { + // Validate Parameters - if (baseDecoder != null) + if (bytes is null) { - UTF8Decoder decoder = (UTF8Decoder)baseDecoder; - ch = decoder.bits; - charCount -= (ch >> 30); // Adjust char count for # of expected bytes and expected output chars. - - // Shouldn't have anything in fallback buffer for GetCharCount - // (don't have to check _throwOnOverflow for count) - Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, - "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at start"); + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.bytes, ExceptionResource.ArgumentNull_Array); } - for (;;) + if ((index | count) < 0) { - // SLOWLOOP: does all range checks, handles all special cases, but it is slow - - if (pSrc >= pEnd) - { - break; - } - - if (ch == 0) - { - // no pending bits - goto ReadChar; - } - - // read next byte. The JIT optimization seems to be getting confused when - // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead - int cha = *pSrc; - pSrc++; - - // we are expecting to see trailing bytes like 10vvvvvv - if ((cha & unchecked((sbyte)0xC0)) != 0x80) - { - // This can be a valid starting byte for another UTF8 byte sequence, so let's put - // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence - pSrc--; - charCount += (ch >> 30); - goto InvalidByteSequence; - } - - // fold in the new byte - ch = (ch << 6) | (cha & 0x3F); - - if ((ch & FinalByte) == 0) - { - Debug.Assert((ch & (SupplimentarySeq | ThreeByteSeq)) != 0, - "[UTF8Encoding.GetChars]Invariant volation"); - - if ((ch & SupplimentarySeq) != 0) - { - if ((ch & (FinalByte >> 6)) != 0) - { - // this is 3rd byte (of 4 byte supplementary) - nothing to do - continue; - } - - // 2nd byte, check for non-shortest form of supplementary char and the valid - // supplementary characters in range 0x010000 - 0x10FFFF at the same time - if (!InRange(ch & 0x1F0, 0x10, 0x100)) - { - goto InvalidByteSequence; - } - } - else - { - // Must be 2nd byte of a 3-byte sequence - // check for non-shortest form of 3 byte seq - if ((ch & (0x1F << 5)) == 0 || // non-shortest form - (ch & (0xF800 >> 6)) == (0xD800 >> 6)) // illegal individually encoded surrogate - { - goto InvalidByteSequence; - } - } - continue; - } - - // ready to punch - - // adjust for surrogates in non-shortest form - if ((ch & (SupplimentarySeq | 0x1F0000)) == SupplimentarySeq) - { - charCount--; - } - goto EncodeChar; - - InvalidByteSequence: - // this code fragment should be close to the goto referencing it - // Have to do fallback for invalid bytes - if (fallback == null) - { - if (baseDecoder == null) - fallback = this.decoderFallback.CreateFallbackBuffer(); - else - fallback = baseDecoder.FallbackBuffer; - fallback.InternalInitialize(bytes, null); - } - charCount += FallbackInvalidByteSequence(pSrc, ch, fallback); - - ch = 0; - continue; - - ReadChar: - ch = *pSrc; - pSrc++; - - ProcessChar: - if (ch > 0x7F) - { - // If its > 0x7F, its start of a new multi-byte sequence - - // Long sequence, so unreserve our char. - charCount--; - - // bit 6 has to be non-zero for start of multibyte chars. - if ((ch & 0x40) == 0) - { - // Unexpected trail byte - goto InvalidByteSequence; - } - - // start a new long code - if ((ch & 0x20) != 0) - { - if ((ch & 0x10) != 0) - { - // 4 byte encoding - supplimentary character (2 surrogates) - - ch &= 0x0F; - - // check that bit 4 is zero and the valid supplimentary character - // range 0x000000 - 0x10FFFF at the same time - if (ch > 0x04) - { - ch |= 0xf0; - goto InvalidByteSequence; - } - - // Add bit flags so that when we check new characters & rotate we'll be flagged correctly. - // Final byte flag, count fix if we don't make final byte & supplimentary sequence flag. - ch |= (FinalByte >> 3 * 6) | // Final byte is 3 more bytes from now - (1 << 30) | // If it dies on next byte we'll need an extra char - (3 << (30 - 2 * 6)) | // If it dies on last byte we'll need to subtract a char - (SupplimentarySeq) | (SupplimentarySeq >> 6) | - (SupplimentarySeq >> 2 * 6) | (SupplimentarySeq >> 3 * 6); - - // Our character count will be 2 characters for these 4 bytes, so subtract another char - charCount--; - } - else - { - // 3 byte encoding - // Add bit flags so that when we check new characters & rotate we'll be flagged correctly. - ch = (ch & 0x0F) | ((FinalByte >> 2 * 6) | (1 << 30) | - (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2 * 6)); - - // We'll expect 1 character for these 3 bytes, so subtract another char. - charCount--; - } - } - else - { - // 2 byte encoding - - ch &= 0x1F; - - // check for non-shortest form - if (ch <= 1) - { - ch |= 0xc0; - goto InvalidByteSequence; - } - - // Add bit flags so we'll be flagged correctly - ch |= (FinalByte >> 6); - } - continue; - } - - EncodeChar: - -#if FASTLOOP - int availableBytes = PtrDiff(pEnd, pSrc); - - // don't fall into the fast decoding loop if we don't have enough bytes - if (availableBytes <= 13) - { - // try to get over the remainder of the ascii characters fast though - byte* pLocalEnd = pEnd; // hint to get pLocalEnd en-registered - while (pSrc < pLocalEnd) - { - ch = *pSrc; - pSrc++; - - if (ch > 0x7F) - goto ProcessChar; - } - // we are done - ch = 0; - break; - } - - // To compute the upper bound, assume that all characters are ASCII characters at this point, - // the boundary will be decreased for every non-ASCII character we encounter - // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences - byte* pStop = pSrc + availableBytes - 7; - - while (pSrc < pStop) - { - ch = *pSrc; - pSrc++; - - if (ch > 0x7F) - { - goto LongCode; - } - - // get pSrc 2-byte aligned - if ((unchecked((int)pSrc) & 0x1) != 0) - { - ch = *pSrc; - pSrc++; - if (ch > 0x7F) - { - goto LongCode; - } - } - - // get pSrc 4-byte aligned - if ((unchecked((int)pSrc) & 0x2) != 0) - { - ch = *(ushort*)pSrc; - if ((ch & 0x8080) != 0) - { - goto LongCodeWithMask16; - } - pSrc += 2; - } - - // Run 8 + 8 characters at a time! - while (pSrc < pStop) - { - ch = *(int*)pSrc; - int chb = *(int*)(pSrc + 4); - if (((ch | chb) & unchecked((int)0x80808080)) != 0) - { - goto LongCodeWithMask32; - } - pSrc += 8; - - // This is a really small loop - unroll it - if (pSrc >= pStop) - break; - - ch = *(int*)pSrc; - chb = *(int*)(pSrc + 4); - if (((ch | chb) & unchecked((int)0x80808080)) != 0) - { - goto LongCodeWithMask32; - } - pSrc += 8; - } - break; - - LongCodeWithMask32: - if (BitConverter.IsLittleEndian) - { - ch &= 0xFF; - } - else - { - // be careful about the sign extension - ch = (int)(((uint)ch) >> 16); - } - LongCodeWithMask16: - if (BitConverter.IsLittleEndian) - { - ch &= 0xFF; - } - else - { - ch = (int)(((uint)ch) >> 8); - } - - pSrc++; - if (ch <= 0x7F) - { - continue; - } - - LongCode: - int chc = *pSrc; - pSrc++; - - if ( - // bit 6 has to be zero - (ch & 0x40) == 0 || - // we are expecting to see trailing bytes like 10vvvvvv - (chc & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - - chc &= 0x3F; - - // start a new long code - if ((ch & 0x20) != 0) - { - // fold the first two bytes together - chc |= (ch & 0x0F) << 6; - - if ((ch & 0x10) != 0) - { - // 4 byte encoding - surrogate - ch = *pSrc; - if ( - // check that bit 4 is zero, the non-shortest form of surrogate - // and the valid surrogate range 0x000000 - 0x10FFFF at the same time - !InRange(chc >> 4, 0x01, 0x10) || - // we are expecting to see trailing bytes like 10vvvvvv - (ch & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - - chc = (chc << 6) | (ch & 0x3F); - - ch = *(pSrc + 1); - // we are expecting to see trailing bytes like 10vvvvvv - if ((ch & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - pSrc += 2; - - // extra byte - charCount--; - } - else - { - // 3 byte encoding - ch = *pSrc; - if ( - // check for non-shortest form of 3 byte seq - (chc & (0x1F << 5)) == 0 || - // Can't have surrogates here. - (chc & (0xF800 >> 6)) == (0xD800 >> 6) || - // we are expecting to see trailing bytes like 10vvvvvv - (ch & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - pSrc++; - - // extra byte - charCount--; - } - } - else - { - // 2 byte encoding - - // check for non-shortest form - if ((ch & 0x1E) == 0) - { - goto BadLongCode; - } - } - - // extra byte - charCount--; - } -#endif // FASTLOOP - - // no pending bits at this point - ch = 0; - continue; - - BadLongCode: - pSrc -= 2; - ch = 0; - continue; + ThrowHelper.ThrowArgumentOutOfRangeException( + argument: (index < 0) ? ExceptionArgument.index : ExceptionArgument.count, + resource: ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); } - // May have a problem if we have to flush - if (ch != 0) + if (bytes!.Length - index < count) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { - // We were already adjusting for these, so need to un-adjust - charCount += (ch >> 30); - if (baseDecoder == null || baseDecoder.MustFlush) - { - // Have to do fallback for invalid bytes - if (fallback == null) - { - if (baseDecoder == null) - fallback = this.decoderFallback.CreateFallbackBuffer(); - else - fallback = baseDecoder.FallbackBuffer; - fallback.InternalInitialize(bytes, null); - } - charCount += FallbackInvalidByteSequence(pSrc, ch, fallback); - } + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.bytes, ExceptionResource.ArgumentOutOfRange_IndexCountBuffer); } - // Shouldn't have anything in fallback buffer for GetCharCount - // (don't have to check _throwOnOverflow for count) - Debug.Assert(fallback == null || fallback.Remaining == 0, - "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at end"); + // Avoid problems with empty input buffer + if (count == 0) + return string.Empty; - return charCount; + fixed (byte* pBytes = bytes) + { + return string.CreateStringFromEncoding(pBytes + index, count, this); + } } - // WARNING: If we throw an error, then System.Resources.ResourceReader calls this method. - // So if we're really broken, then that could also throw an error... recursively. - // So try to make sure GetChars can at least process all uses by - // System.Resources.ResourceReader! // - // Note: We throw exceptions on individually encoded surrogates and other non-shortest forms. - // If exceptions aren't turned on, then we drop all non-shortest &individual surrogates. + // End of standard methods copied from EncodingNLS.cs // - // To simplify maintenance, the structure of GetCharCount and GetChars should be - // kept the same as much as possible - internal sealed override unsafe int GetChars( - byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) - { - Debug.Assert(chars != null, "[UTF8Encoding.GetChars]chars!=null"); - Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetChars]count >=0"); - Debug.Assert(charCount >= 0, "[UTF8Encoding.GetChars]charCount >=0"); - Debug.Assert(bytes != null, "[UTF8Encoding.GetChars]bytes!=null"); - - byte* pSrc = bytes; - char* pTarget = chars; - - byte* pEnd = pSrc + byteCount; - char* pAllocatedBufferEnd = pTarget + charCount; - - int ch = 0; - - DecoderFallbackBuffer fallback = null; - byte* pSrcForFallback; - char* pTargetForFallback; - if (baseDecoder != null) - { - UTF8Decoder decoder = (UTF8Decoder)baseDecoder; - ch = decoder.bits; - - // Shouldn't have anything in fallback buffer for GetChars - // (don't have to check _throwOnOverflow for chars, we always use all or none so always should be empty) - Debug.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, - "[UTF8Encoding.GetChars]Expected empty fallback buffer at start"); - } - - for (;;) - { - // SLOWLOOP: does all range checks, handles all special cases, but it is slow - - if (pSrc >= pEnd) - { - break; - } - - if (ch == 0) - { - // no pending bits - goto ReadChar; - } - - // read next byte. The JIT optimization seems to be getting confused when - // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead - int cha = *pSrc; - pSrc++; - - // we are expecting to see trailing bytes like 10vvvvvv - if ((cha & unchecked((sbyte)0xC0)) != 0x80) - { - // This can be a valid starting byte for another UTF8 byte sequence, so let's put - // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence - pSrc--; - goto InvalidByteSequence; - } - - // fold in the new byte - ch = (ch << 6) | (cha & 0x3F); - - if ((ch & FinalByte) == 0) - { - // Not at last byte yet - Debug.Assert((ch & (SupplimentarySeq | ThreeByteSeq)) != 0, - "[UTF8Encoding.GetChars]Invariant volation"); - - if ((ch & SupplimentarySeq) != 0) - { - // Its a 4-byte supplimentary sequence - if ((ch & (FinalByte >> 6)) != 0) - { - // this is 3rd byte of 4 byte sequence - nothing to do - continue; - } - - // 2nd byte of 4 bytes - // check for non-shortest form of surrogate and the valid surrogate - // range 0x000000 - 0x10FFFF at the same time - if (!InRange(ch & 0x1F0, 0x10, 0x100)) - { - goto InvalidByteSequence; - } - } - else - { - // Must be 2nd byte of a 3-byte sequence - // check for non-shortest form of 3 byte seq - if ((ch & (0x1F << 5)) == 0 || // non-shortest form - (ch & (0xF800 >> 6)) == (0xD800 >> 6)) // illegal individually encoded surrogate - { - goto InvalidByteSequence; - } - } - continue; - } - - // ready to punch - - // surrogate in shortest form? - // Might be possible to get rid of this? Already did non-shortest check for 4-byte sequence when reading 2nd byte? - if ((ch & (SupplimentarySeq | 0x1F0000)) > SupplimentarySeq) - { - // let the range check for the second char throw the exception - if (pTarget < pAllocatedBufferEnd) - { - *pTarget = (char)(((ch >> 10) & 0x7FF) + - unchecked((short)((CharUnicodeInfo.HIGH_SURROGATE_START - (0x10000 >> 10))))); - pTarget++; - - ch = (ch & 0x3FF) + - unchecked((int)(CharUnicodeInfo.LOW_SURROGATE_START)); - } - } - - goto EncodeChar; - - InvalidByteSequence: - // this code fragment should be close to the gotos referencing it - // Have to do fallback for invalid bytes - if (fallback == null) - { - if (baseDecoder == null) - fallback = this.decoderFallback.CreateFallbackBuffer(); - else - fallback = baseDecoder.FallbackBuffer; - fallback.InternalInitialize(bytes, pAllocatedBufferEnd); - } - // That'll back us up the appropriate # of bytes if we didn't get anywhere - pSrcForFallback = pSrc; // Avoid passing pSrc by reference to allow it to be en-registered - pTargetForFallback = pTarget; // Avoid passing pTarget by reference to allow it to be en-registered - bool fallbackResult = FallbackInvalidByteSequence(ref pSrcForFallback, ch, fallback, ref pTargetForFallback); - pSrc = pSrcForFallback; - pTarget = pTargetForFallback; - - if (!fallbackResult) - { - // Ran out of buffer space - // Need to throw an exception? - Debug.Assert(pSrc >= bytes || pTarget == chars, - "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer after fallback"); - fallback.InternalReset(); - ThrowCharsOverflow(baseDecoder, pTarget == chars); - ch = 0; - break; - } - Debug.Assert(pSrc >= bytes, - "[UTF8Encoding.GetChars]Expected invalid byte sequence to have remained within the byte array"); - ch = 0; - continue; - - ReadChar: - ch = *pSrc; - pSrc++; - - ProcessChar: - if (ch > 0x7F) - { - // If its > 0x7F, its start of a new multi-byte sequence - - // bit 6 has to be non-zero - if ((ch & 0x40) == 0) - { - goto InvalidByteSequence; - } - - // start a new long code - if ((ch & 0x20) != 0) - { - if ((ch & 0x10) != 0) - { - // 4 byte encoding - supplimentary character (2 surrogates) - - ch &= 0x0F; - - // check that bit 4 is zero and the valid supplimentary character - // range 0x000000 - 0x10FFFF at the same time - if (ch > 0x04) - { - ch |= 0xf0; - goto InvalidByteSequence; - } - - ch |= (FinalByte >> 3 * 6) | (1 << 30) | (3 << (30 - 2 * 6)) | - (SupplimentarySeq) | (SupplimentarySeq >> 6) | - (SupplimentarySeq >> 2 * 6) | (SupplimentarySeq >> 3 * 6); - } - else - { - // 3 byte encoding - ch = (ch & 0x0F) | ((FinalByte >> 2 * 6) | (1 << 30) | - (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2 * 6)); - } - } - else - { - // 2 byte encoding - - ch &= 0x1F; - - // check for non-shortest form - if (ch <= 1) - { - ch |= 0xc0; - goto InvalidByteSequence; - } - - ch |= (FinalByte >> 6); - } - continue; - } - - EncodeChar: - // write the pending character - if (pTarget >= pAllocatedBufferEnd) - { - // Fix chars so we make sure to throw if we didn't output anything - ch &= 0x1fffff; - if (ch > 0x7f) - { - if (ch > 0x7ff) - { - if (ch >= CharUnicodeInfo.LOW_SURROGATE_START && - ch <= CharUnicodeInfo.LOW_SURROGATE_END) - { - pSrc--; // It was 4 bytes - pTarget--; // 1 was stored already, but we can't remember 1/2, so back up - } - else if (ch > 0xffff) - { - pSrc--; // It was 4 bytes, nothing was stored - } - pSrc--; // It was at least 3 bytes - } - pSrc--; // It was at least 2 bytes - } - pSrc--; - - // Throw that we don't have enough room (pSrc could be < chars if we had started to process - // a 4 byte sequence already) - Debug.Assert(pSrc >= bytes || pTarget == chars, - "[UTF8Encoding.GetChars]Expected pSrc to be within input buffer or throw due to no output]"); - ThrowCharsOverflow(baseDecoder, pTarget == chars); - - // Don't store ch in decoder, we already backed up to its start - ch = 0; - - // Didn't throw, just use this buffer size. - break; - } - *pTarget = (char)ch; - pTarget++; - -#if FASTLOOP - int availableChars = PtrDiff(pAllocatedBufferEnd, pTarget); - int availableBytes = PtrDiff(pEnd, pSrc); - - // don't fall into the fast decoding loop if we don't have enough bytes - // Test for availableChars is done because pStop would be <= pTarget. - if (availableBytes <= 13) - { - // we may need as many as 1 character per byte - if (availableChars < availableBytes) - { - // not enough output room. no pending bits at this point - ch = 0; - continue; - } - - // try to get over the remainder of the ascii characters fast though - byte* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered - while (pSrc < pLocalEnd) - { - ch = *pSrc; - pSrc++; - - if (ch > 0x7F) - goto ProcessChar; - - *pTarget = (char)ch; - pTarget++; - } - // we are done - ch = 0; - break; - } - - // we may need as many as 1 character per byte, so reduce the byte count if necessary. - // If availableChars is too small, pStop will be before pTarget and we won't do fast loop. - if (availableChars < availableBytes) - { - availableBytes = availableChars; - } - - // To compute the upper bound, assume that all characters are ASCII characters at this point, - // the boundary will be decreased for every non-ASCII character we encounter - // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences - char* pStop = pTarget + availableBytes - 7; - while (pTarget < pStop) - { - ch = *pSrc; - pSrc++; - - if (ch > 0x7F) - { - goto LongCode; - } - *pTarget = (char)ch; - pTarget++; - - // get pSrc to be 2-byte aligned - if ((unchecked((int)pSrc) & 0x1) != 0) - { - ch = *pSrc; - pSrc++; - if (ch > 0x7F) - { - goto LongCode; - } - *pTarget = (char)ch; - pTarget++; - } - - // get pSrc to be 4-byte aligned - if ((unchecked((int)pSrc) & 0x2) != 0) - { - ch = *(ushort*)pSrc; - if ((ch & 0x8080) != 0) - { - goto LongCodeWithMask16; - } - - // Unfortunately, this is endianess sensitive - if (BitConverter.IsLittleEndian) - { - *pTarget = (char)(ch & 0x7F); - pSrc += 2; - *(pTarget + 1) = (char)((ch >> 8) & 0x7F); - pTarget += 2; - } - else - { - *pTarget = (char)((ch >> 8) & 0x7F); - pSrc += 2; - *(pTarget+1) = (char)(ch & 0x7F); - pTarget += 2; - } - } - - // Run 8 characters at a time! - while (pTarget < pStop) - { - ch = *(int*)pSrc; - int chb = *(int*)(pSrc + 4); - if (((ch | chb) & unchecked((int)0x80808080)) != 0) - { - goto LongCodeWithMask32; - } - - // Unfortunately, this is endianess sensitive - if (BitConverter.IsLittleEndian) - { - *pTarget = (char)(ch & 0x7F); - *(pTarget + 1) = (char)((ch >> 8) & 0x7F); - *(pTarget + 2) = (char)((ch >> 16) & 0x7F); - *(pTarget + 3) = (char)((ch >> 24) & 0x7F); - pSrc += 8; - *(pTarget + 4) = (char)(chb & 0x7F); - *(pTarget + 5) = (char)((chb >> 8) & 0x7F); - *(pTarget + 6) = (char)((chb >> 16) & 0x7F); - *(pTarget + 7) = (char)((chb >> 24) & 0x7F); - pTarget += 8; - } - else - { - *pTarget = (char)((ch >> 24) & 0x7F); - *(pTarget+1) = (char)((ch >> 16) & 0x7F); - *(pTarget+2) = (char)((ch >> 8) & 0x7F); - *(pTarget+3) = (char)(ch & 0x7F); - pSrc += 8; - *(pTarget+4) = (char)((chb >> 24) & 0x7F); - *(pTarget+5) = (char)((chb >> 16) & 0x7F); - *(pTarget+6) = (char)((chb >> 8) & 0x7F); - *(pTarget+7) = (char)(chb & 0x7F); - pTarget += 8; - } - } - break; - - LongCodeWithMask32: - if (BitConverter.IsLittleEndian) - { - ch &= 0xFF; - } - else - { - // be careful about the sign extension - ch = (int)(((uint)ch) >> 16); - } - LongCodeWithMask16: - if (BitConverter.IsLittleEndian) - { - ch &= 0xFF; - } - else - { - ch = (int)(((uint)ch) >> 8); - } - pSrc++; - if (ch <= 0x7F) - { - *pTarget = (char)ch; - pTarget++; - continue; - } - - LongCode: - int chc = *pSrc; - pSrc++; - - if ( - // bit 6 has to be zero - (ch & 0x40) == 0 || - // we are expecting to see trailing bytes like 10vvvvvv - (chc & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - - chc &= 0x3F; - - // start a new long code - if ((ch & 0x20) != 0) - { - // fold the first two bytes together - chc |= (ch & 0x0F) << 6; - - if ((ch & 0x10) != 0) - { - // 4 byte encoding - surrogate - ch = *pSrc; - if ( - // check that bit 4 is zero, the non-shortest form of surrogate - // and the valid surrogate range 0x000000 - 0x10FFFF at the same time - !InRange(chc >> 4, 0x01, 0x10) || - // we are expecting to see trailing bytes like 10vvvvvv - (ch & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - - chc = (chc << 6) | (ch & 0x3F); - - ch = *(pSrc + 1); - // we are expecting to see trailing bytes like 10vvvvvv - if ((ch & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - pSrc += 2; - - ch = (chc << 6) | (ch & 0x3F); - - *pTarget = (char)(((ch >> 10) & 0x7FF) + - unchecked((short)(CharUnicodeInfo.HIGH_SURROGATE_START - (0x10000 >> 10)))); - pTarget++; - - ch = (ch & 0x3FF) + - unchecked((short)(CharUnicodeInfo.LOW_SURROGATE_START)); - - // extra byte, we're already planning 2 chars for 2 of these bytes, - // but the big loop is testing the target against pStop, so we need - // to subtract 2 more or we risk overrunning the input. Subtract - // one here and one below. - pStop--; - } - else - { - // 3 byte encoding - ch = *pSrc; - if ( - // check for non-shortest form of 3 byte seq - (chc & (0x1F << 5)) == 0 || - // Can't have surrogates here. - (chc & (0xF800 >> 6)) == (0xD800 >> 6) || - // we are expecting to see trailing bytes like 10vvvvvv - (ch & unchecked((sbyte)0xC0)) != 0x80) - { - goto BadLongCode; - } - pSrc++; - - ch = (chc << 6) | (ch & 0x3F); - - // extra byte, we're only expecting 1 char for each of these 3 bytes, - // but the loop is testing the target (not source) against pStop, so - // we need to subtract 2 more or we risk overrunning the input. - // Subtract 1 here and one more below - pStop--; - } - } - else - { - // 2 byte encoding - - ch &= 0x1F; - - // check for non-shortest form - if (ch <= 1) - { - goto BadLongCode; - } - ch = (ch << 6) | chc; - } - - *pTarget = (char)ch; - pTarget++; - - // extra byte, we're only expecting 1 char for each of these 2 bytes, - // but the loop is testing the target (not source) against pStop. - // subtract an extra count from pStop so that we don't overrun the input. - pStop--; - } -#endif // FASTLOOP + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe int GetCharCountCommon(byte* pBytes, int byteCount) + { + // Common helper method for all non-DecoderNLS entry points to GetCharCount. + // A modification of this method should be copied in to each of the supported encodings: ASCII, UTF8, UTF16, UTF32. - Debug.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetChars]pTarget <= pAllocatedBufferEnd"); + Debug.Assert(byteCount >= 0, "Caller shouldn't specify negative length buffer."); + Debug.Assert(pBytes != null || byteCount == 0, "Input pointer shouldn't be null if non-zero length specified."); - // no pending bits at this point - ch = 0; - continue; + // First call into the fast path. + // Don't bother providing a fallback mechanism; our fast path doesn't use it. - BadLongCode: - pSrc -= 2; - ch = 0; - continue; - } + int totalCharCount = GetCharCountFast(pBytes, byteCount, fallback: null, out int bytesConsumed); - if (ch != 0 && (baseDecoder == null || baseDecoder.MustFlush)) + if (bytesConsumed != byteCount) { - // Have to do fallback for invalid bytes - if (fallback == null) - { - if (baseDecoder == null) - fallback = this.decoderFallback.CreateFallbackBuffer(); - else - fallback = baseDecoder.FallbackBuffer; - fallback.InternalInitialize(bytes, pAllocatedBufferEnd); - } + // If there's still data remaining in the source buffer, go down the fallback path. + // We need to check for integer overflow since the fallback could change the required + // output count in unexpected ways. - // That'll back us up the appropriate # of bytes if we didn't get anywhere - pSrcForFallback = pSrc; // Avoid passing pSrc by reference to allow it to be en-registered - pTargetForFallback = pTarget; // Avoid passing pTarget by reference to allow it to be en-registered - bool fallbackResult = FallbackInvalidByteSequence(ref pSrcForFallback, ch, fallback, ref pTargetForFallback); - pSrc = pSrcForFallback; - pTarget = pTargetForFallback; - - if (!fallbackResult) + totalCharCount += GetCharCountWithFallback(pBytes, byteCount, bytesConsumed); + if (totalCharCount < 0) { - Debug.Assert(pSrc >= bytes || pTarget == chars, - "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer while flushing"); - - // Ran out of buffer space - // Need to throw an exception? - fallback.InternalReset(); - ThrowCharsOverflow(baseDecoder, pTarget == chars); + ThrowConversionOverflow(); } - Debug.Assert(pSrc >= bytes, - "[UTF8Encoding.GetChars]Expected flushing invalid byte sequence to have remained within the byte array"); - ch = 0; } - if (baseDecoder != null) - { - UTF8Decoder decoder = (UTF8Decoder)baseDecoder; - - // If we're storing flush data we expect all bits to be used or else - // we're stuck in the middle of a conversion - Debug.Assert(!baseDecoder.MustFlush || ch == 0 || !baseDecoder._throwOnOverflow, - "[UTF8Encoding.GetChars]Expected no must flush or no left over bits or no throw on overflow."); + return totalCharCount; + } - // Remember our leftover bits. - decoder.bits = ch; + [MethodImpl(MethodImplOptions.AggressiveInlining)] // called directly by GetCharCountCommon + private protected sealed override unsafe int GetCharCountFast(byte* pBytes, int bytesLength, DecoderFallback? fallback, out int bytesConsumed) + { + // The number of UTF-16 code units will never exceed the number of UTF-8 code units, + // so the addition at the end of this method will not overflow. - baseDecoder._bytesUsed = (int)(pSrc - bytes); - } + byte* ptrToFirstInvalidByte = Utf8Utility.GetPointerToFirstInvalidByte(pBytes, bytesLength, out int utf16CodeUnitCountAdjustment, out _); - // Shouldn't have anything in fallback buffer for GetChars - // (don't have to check _throwOnOverflow for chars) - Debug.Assert(fallback == null || fallback.Remaining == 0, - "[UTF8Encoding.GetChars]Expected empty fallback buffer at end"); + int tempBytesConsumed = (int)(ptrToFirstInvalidByte - pBytes); + bytesConsumed = tempBytesConsumed; - return PtrDiff(pTarget, chars); + return tempBytesConsumed + utf16CodeUnitCountAdjustment; } - // During GetChars we had an invalid byte sequence - // pSrc is backed up to the start of the bad sequence if we didn't have room to - // fall it back. Otherwise pSrc remains where it is. - private unsafe bool FallbackInvalidByteSequence( - ref byte* pSrc, int ch, DecoderFallbackBuffer fallback, ref char* pTarget) + public override Decoder GetDecoder() { - // Get our byte[] - byte* pStart = pSrc; - byte[] bytesUnknown = GetBytesUnknown(ref pStart, ch); - - // Do the actual fallback - if (!fallback.InternalFallback(bytesUnknown, pSrc, ref pTarget)) - { - // Oops, it failed, back up to pStart - pSrc = pStart; - return false; - } - - // It worked - return true; + return new DecoderNLS(this); } - // During GetCharCount we had an invalid byte sequence - // pSrc is used to find the index that points to the invalid bytes, - // however the byte[] contains the fallback bytes (in case the index is -1) - private unsafe int FallbackInvalidByteSequence( - byte* pSrc, int ch, DecoderFallbackBuffer fallback) + + public override Encoder GetEncoder() { - // Calling GetBytesUnknown can adjust the pSrc pointer but we need to pass the pointer before the adjustment - // to fallback.InternalFallback. The input pSrc to fallback.InternalFallback will only be used to calculate the - // index inside bytesUnknown and if we pass the adjusted pointer we can end up with negative index values. - // We store the original pSrc in pOriginalSrc and then pass pOriginalSrc to fallback.InternalFallback. - byte* pOriginalSrc = pSrc; - - // Get our byte[] - byte[] bytesUnknown = GetBytesUnknown(ref pSrc, ch); - - // Do the actual fallback - int count = fallback.InternalFallback(bytesUnknown, pOriginalSrc); - - // # of fallback chars expected. - // Note that we only get here for "long" sequences, and have already unreserved - // the count that we prereserved for the input bytes - return count; + return new EncoderNLS(this); } - // Note that some of these bytes may have come from a previous fallback, so we cannot - // just decrement the pointer and use the values we read. In those cases we have - // to regenerate the original values. - private unsafe byte[] GetBytesUnknown(ref byte* pSrc, int ch) - { - // Get our byte[] - byte[] bytesUnknown = null; + // + // Beginning of methods used by shared fallback logic. + // - // See if it was a plain char - // (have to check >= 0 because we have all sorts of wierd bit flags) - if (ch < 0x100 && ch >= 0) - { - pSrc--; - bytesUnknown = new byte[] { unchecked((byte)ch) }; - } - // See if its an unfinished 2 byte sequence - else if ((ch & (SupplimentarySeq | ThreeByteSeq)) == 0) - { - pSrc--; - bytesUnknown = new byte[] { unchecked((byte)((ch & 0x1F) | 0xc0)) }; - } - // So now we're either 2nd byte of 3 or 4 byte sequence or - // we hit a non-trail byte or we ran out of space for 3rd byte of 4 byte sequence - // 1st check if its a 4 byte sequence - else if ((ch & SupplimentarySeq) != 0) - { - // 3rd byte of 4 byte sequence? - if ((ch & (FinalByte >> 6)) != 0) - { - // 3rd byte of 4 byte sequence - pSrc -= 3; - bytesUnknown = new byte[] { - unchecked((byte)(((ch >> 12) & 0x07) | 0xF0)), - unchecked((byte)(((ch >> 6) & 0x3F) | 0x80)), - unchecked((byte)(((ch) & 0x3F) | 0x80)) }; - } - else if ((ch & (FinalByte >> 12)) != 0) - { - // 2nd byte of a 4 byte sequence - pSrc -= 2; - bytesUnknown = new byte[] { - unchecked((byte)(((ch >> 6) & 0x07) | 0xF0)), - unchecked((byte)(((ch) & 0x3F) | 0x80)) }; - } - else - { - // 4th byte of a 4 byte sequence - pSrc--; - bytesUnknown = new byte[] { unchecked((byte)(((ch) & 0x07) | 0xF0)) }; - } - } - else - { - // 2nd byte of 3 byte sequence? - if ((ch & (FinalByte >> 6)) != 0) - { - // So its 2nd byte of a 3 byte sequence - pSrc -= 2; - bytesUnknown = new byte[] { - unchecked((byte)(((ch >> 6) & 0x0F) | 0xE0)), unchecked ((byte)(((ch) & 0x3F) | 0x80)) }; - } - else - { - // 1st byte of a 3 byte sequence - pSrc--; - bytesUnknown = new byte[] { unchecked((byte)(((ch) & 0x0F) | 0xE0)) }; - } - } + internal sealed override bool TryGetByteCount(Rune value, out int byteCount) + { + // All well-formed Rune instances can be converted to 1..4 UTF-8 code units. - return bytesUnknown; + byteCount = value.Utf8SequenceLength; + return true; } - - public override Decoder GetDecoder() + internal sealed override OperationStatus EncodeRune(Rune value, Span bytes, out int bytesWritten) { - return new UTF8Decoder(this); - } + // All well-formed Rune instances can be encoded as 1..4 UTF-8 code units. + // If there's an error, it's because the destination was too small. + return value.TryEncodeToUtf8(bytes, out bytesWritten) ? OperationStatus.Done : OperationStatus.DestinationTooSmall; + } - public override Encoder GetEncoder() + internal sealed override OperationStatus DecodeFirstRune(ReadOnlySpan bytes, out Rune value, out int bytesConsumed) { - return new UTF8Encoder(this); + return Rune.DecodeFromUtf8(bytes, out value, out bytesConsumed); } + // + // End of methods used by shared fallback logic. + // public override int GetMaxByteCount(int charCount) { @@ -2553,7 +837,7 @@ public override byte[] GetPreamble() _emitUTF8Identifier ? PreambleSpan : default; - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is UTF8Encoding that) { @@ -2561,7 +845,7 @@ public override bool Equals(object value) (EncoderFallback.Equals(that.EncoderFallback)) && (DecoderFallback.Equals(that.DecoderFallback)); } - return (false); + return false; } @@ -2571,62 +855,5 @@ public override int GetHashCode() return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() + UTF8_CODEPAGE + (_emitUTF8Identifier ? 1 : 0); } - - private sealed class UTF8Encoder : EncoderNLS - { - // We must save a high surrogate value until the next call, looking - // for a low surrogate value. - internal int surrogateChar; - - public UTF8Encoder(UTF8Encoding encoding) : base(encoding) - { - // base calls reset - } - - public override void Reset() - - { - this.surrogateChar = 0; - if (_fallbackBuffer != null) - _fallbackBuffer.Reset(); - } - - // Anything left in our encoder? - internal override bool HasState - { - get - { - return (this.surrogateChar != 0); - } - } - } - - private sealed class UTF8Decoder : DecoderNLS - { - // We'll need to remember the previous information. See the comments around definition - // of FinalByte for details. - internal int bits; - - public UTF8Decoder(UTF8Encoding encoding) : base(encoding) - { - // base calls reset - } - - public override void Reset() - { - this.bits = 0; - if (_fallbackBuffer != null) - _fallbackBuffer.Reset(); - } - - // Anything left in our decoder? - internal override bool HasState - { - get - { - return (this.bits != 0); - } - } - } } } diff --git a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf16Utility.Validation.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf16Utility.Validation.cs new file mode 100644 index 000000000000..d398c1f36b1a --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf16Utility.Validation.cs @@ -0,0 +1,429 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Diagnostics; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using System.Numerics; +using Internal.Runtime.CompilerServices; + +#if BIT64 +using nint = System.Int64; +using nuint = System.UInt64; +#else // BIT64 +using nint = System.Int32; +using nuint = System.UInt32; +#endif // BIT64 + +namespace System.Text.Unicode +{ + internal static unsafe partial class Utf16Utility + { +#if DEBUG + static Utf16Utility() + { + Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); + Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); + } +#endif // DEBUG + + // Returns &inputBuffer[inputLength] if the input buffer is valid. + /// + /// Given an input buffer of char length , + /// returns a pointer to where the first invalid data appears in . + /// + /// + /// Returns a pointer to the end of if the buffer is well-formed. + /// + public static char* GetPointerToFirstInvalidChar(char* pInputBuffer, int inputLength, out long utf8CodeUnitCountAdjustment, out int scalarCountAdjustment) + { + Debug.Assert(inputLength >= 0, "Input length must not be negative."); + Debug.Assert(pInputBuffer != null || inputLength == 0, "Input length must be zero if input buffer pointer is null."); + + // First, we'll handle the common case of all-ASCII. If this is able to + // consume the entire buffer, we'll skip the remainder of this method's logic. + + int numAsciiCharsConsumedJustNow = (int)ASCIIUtility.GetIndexOfFirstNonAsciiChar(pInputBuffer, (uint)inputLength); + Debug.Assert(0 <= numAsciiCharsConsumedJustNow && numAsciiCharsConsumedJustNow <= inputLength); + + pInputBuffer += (uint)numAsciiCharsConsumedJustNow; + inputLength -= numAsciiCharsConsumedJustNow; + + if (inputLength == 0) + { + utf8CodeUnitCountAdjustment = 0; + scalarCountAdjustment = 0; + return pInputBuffer; + } + + // If we got here, it means we saw some non-ASCII data, so within our + // vectorized code paths below we'll handle all non-surrogate UTF-16 + // code points branchlessly. We'll only branch if we see surrogates. + // + // We still optimistically assume the data is mostly ASCII. This means that the + // number of UTF-8 code units and the number of scalars almost matches the number + // of UTF-16 code units. As we go through the input and find non-ASCII + // characters, we'll keep track of these "adjustment" fixups. To get the + // total number of UTF-8 code units required to encode the input data, add + // the UTF-8 code unit count adjustment to the number of UTF-16 code units + // seen. To get the total number of scalars present in the input data, + // add the scalar count adjustment to the number of UTF-16 code units seen. + + long tempUtf8CodeUnitCountAdjustment = 0; + int tempScalarCountAdjustment = 0; + + if (Sse2.IsSupported) + { + if (inputLength >= Vector128.Count) + { + Vector128 vector0080 = Vector128.Create((ushort)0x80); + Vector128 vectorA800 = Vector128.Create((ushort)0xA800); + Vector128 vector8800 = Vector128.Create(unchecked((short)0x8800)); + Vector128 vectorZero = Vector128.Zero; + + do + { + Vector128 utf16Data = Sse2.LoadVector128((ushort*)pInputBuffer); // unaligned + uint mask; + + // The 'charIsNonAscii' vector we're about to build will have the 0x8000 or the 0x0080 + // bit set (but not both!) only if the corresponding input char is non-ASCII. Which of + // the two bits is set doesn't matter, as will be explained in the diagram a few lines + // below. + + Vector128 charIsNonAscii; + if (Sse41.IsSupported) + { + // sets 0x0080 bit if corresponding char element is >= 0x0080 + charIsNonAscii = Sse41.Min(utf16Data, vector0080); + } + else + { + // sets 0x8000 bit if corresponding char element is >= 0x0080 + charIsNonAscii = Sse2.AndNot(vector0080, Sse2.Subtract(vectorZero, Sse2.ShiftRightLogical(utf16Data, 7))); + } + +#if DEBUG + // Quick check to ensure we didn't accidentally set both 0x8080 bits in any element. + uint debugMask = (uint)Sse2.MoveMask(charIsNonAscii.AsByte()); + Debug.Assert((debugMask & (debugMask << 1)) == 0, "Two set bits shouldn't occur adjacent to each other in this mask."); +#endif // DEBUG + + // sets 0x8080 bits if corresponding char element is >= 0x0800 + Vector128 charIsThreeByteUtf8Encoded = Sse2.Subtract(vectorZero, Sse2.ShiftRightLogical(utf16Data, 11)); + + mask = (uint)Sse2.MoveMask(Sse2.Or(charIsNonAscii, charIsThreeByteUtf8Encoded).AsByte()); + + // Each odd bit of mask will be 1 only if the char was >= 0x0080, + // and each even bit of mask will be 1 only if the char was >= 0x0800. + // + // Example for UTF-16 input "[ 0123 ] [ 1234 ] ...": + // + // ,-- set if char[1] is non-ASCII + // | ,-- set if char[0] is non-ASCII + // v v + // mask = ... 1 1 1 0 + // ^ ^-- set if char[0] is >= 0x0800 + // `-- set if char[1] is >= 0x0800 + // + // (If the SSE4.1 code path is taken above, the meaning of the odd and even + // bits are swapped, but the logic below otherwise holds.) + // + // This means we can popcnt the number of set bits, and the result is the + // number of *additional* UTF-8 bytes that each UTF-16 code unit requires as + // it expands. This results in the wrong count for UTF-16 surrogate code + // units (we just counted that each individual code unit expands to 3 bytes, + // but in reality a well-formed UTF-16 surrogate pair expands to 4 bytes). + // We'll handle this in just a moment. + // + // For now, compute the popcnt but squirrel it away. We'll fold it in to the + // cumulative UTF-8 adjustment factor once we determine that there are no + // unpaired surrogates in our data. (Unpaired surrogates would invalidate + // our computed result and we'd have to throw it away.) + + uint popcnt = (uint)BitOperations.PopCount(mask); + + // Surrogates need to be special-cased for two reasons: (a) we need + // to account for the fact that we over-counted in the addition above; + // and (b) they require separate validation. + + utf16Data = Sse2.Add(utf16Data, vectorA800); + mask = (uint)Sse2.MoveMask(Sse2.CompareLessThan(utf16Data.AsInt16(), vector8800).AsByte()); + + if (mask != 0) + { + // There's at least one UTF-16 surrogate code unit present. + // Since we performed a pmovmskb operation on the result of a 16-bit pcmpgtw, + // the resulting bits of 'mask' will occur in pairs: + // - 00 if the corresponding UTF-16 char was not a surrogate code unit; + // - 11 if the corresponding UTF-16 char was a surrogate code unit. + // + // A UTF-16 high/low surrogate code unit has the bit pattern [ 11011q## ######## ], + // where # is any bit; q = 0 represents a high surrogate, and q = 1 represents + // a low surrogate. Since we added 0xA800 in the vectorized operation above, + // our surrogate pairs will now have the bit pattern [ 10000q## ######## ]. + // If we logical right-shift each word by 3, we'll end up with the bit pattern + // [ 00010000 q####### ], which means that we can immediately use pmovmskb to + // determine whether a given char was a high or a low surrogate. + // + // Therefore the resulting bits of 'mask2' will occur in pairs: + // - 00 if the corresponding UTF-16 char was a high surrogate code unit; + // - 01 if the corresponding UTF-16 char was a low surrogate code unit; + // - ## (garbage) if the corresponding UTF-16 char was not a surrogate code unit. + // Since 'mask' already has 00 in these positions (since the corresponding char + // wasn't a surrogate), "mask AND mask2 == 00" holds for these positions. + + uint mask2 = (uint)Sse2.MoveMask(Sse2.ShiftRightLogical(utf16Data, 3).AsByte()); + + // 'lowSurrogatesMask' has its bits occur in pairs: + // - 01 if the corresponding char was a low surrogate char, + // - 00 if the corresponding char was a high surrogate char or not a surrogate at all. + + uint lowSurrogatesMask = mask2 & mask; + + // 'highSurrogatesMask' has its bits occur in pairs: + // - 01 if the corresponding char was a high surrogate char, + // - 00 if the corresponding char was a low surrogate char or not a surrogate at all. + + uint highSurrogatesMask = (mask2 ^ 0b_0101_0101_0101_0101u /* flip all even-numbered bits 00 <-> 01 */) & mask; + + Debug.Assert((highSurrogatesMask & lowSurrogatesMask) == 0, + "A char cannot simultaneously be both a high and a low surrogate char."); + + Debug.Assert(((highSurrogatesMask | lowSurrogatesMask) & 0b_1010_1010_1010_1010u) == 0, + "Only even bits (no odd bits) of the masks should be set."); + + // Now check that each high surrogate is followed by a low surrogate and that each + // low surrogate follows a high surrogate. We make an exception for the case where + // the final char of the vector is a high surrogate, since we can't perform validation + // on it until the next iteration of the loop when we hope to consume the matching + // low surrogate. + + highSurrogatesMask <<= 2; + if ((ushort)highSurrogatesMask != lowSurrogatesMask) + { + goto NonVectorizedLoop; // error: mismatched surrogate pair; break out of vectorized logic + } + + if (highSurrogatesMask > ushort.MaxValue) + { + // There was a standalone high surrogate at the end of the vector. + // We'll adjust our counters so that we don't consider this char consumed. + + highSurrogatesMask = (ushort)highSurrogatesMask; // don't allow stray high surrogate to be consumed by popcnt + popcnt -= 2; // the '0xC000_0000' bits in the original mask are shifted out and discarded, so account for that here + pInputBuffer--; + inputLength++; + } + + // If we're 64-bit, we can perform the zero-extension of the surrogate pairs count for + // free right now, saving the extension step a few lines below. If we're 32-bit, the + // convertion to nuint immediately below is a no-op, and we'll pay the cost of the real + // 64 -bit extension a few lines below. + nuint surrogatePairsCountNuint = (uint)BitOperations.PopCount(highSurrogatesMask); + + // 2 UTF-16 chars become 1 Unicode scalar + + tempScalarCountAdjustment -= (int)surrogatePairsCountNuint; + + // Since each surrogate code unit was >= 0x0800, we eagerly assumed + // it'd be encoded as 3 UTF-8 code units, so our earlier popcnt computation + // assumes that the pair is encoded as 6 UTF-8 code units. Since each + // pair is in reality only encoded as 4 UTF-8 code units, we need to + // perform this adjustment now. + + if (IntPtr.Size == 8) + { + // Since we've already zero-extended surrogatePairsCountNuint, we can directly + // sub + sub. It's more efficient than shl + sub. + tempUtf8CodeUnitCountAdjustment -= (long)surrogatePairsCountNuint; + tempUtf8CodeUnitCountAdjustment -= (long)surrogatePairsCountNuint; + } + else + { + // Take the hit of the 64-bit extension now. + tempUtf8CodeUnitCountAdjustment -= 2 * (uint)surrogatePairsCountNuint; + } + } + + tempUtf8CodeUnitCountAdjustment += popcnt; + pInputBuffer += Vector128.Count; + inputLength -= Vector128.Count; + } while (inputLength >= Vector128.Count); + } + } + else if (Vector.IsHardwareAccelerated) + { + if (inputLength >= Vector.Count) + { + Vector vector0080 = new Vector(0x0080); + Vector vector0400 = new Vector(0x0400); + Vector vector0800 = new Vector(0x0800); + Vector vectorD800 = new Vector(0xD800); + + do + { + // The 'twoOrMoreUtf8Bytes' and 'threeOrMoreUtf8Bytes' vectors will contain + // elements whose values are 0xFFFF (-1 as signed word) iff the corresponding + // UTF-16 code unit was >= 0x0080 and >= 0x0800, respectively. By summing these + // vectors, each element of the sum will contain one of three values: + // + // 0x0000 ( 0) = original char was 0000..007F + // 0xFFFF (-1) = original char was 0080..07FF + // 0xFFFE (-2) = original char was 0800..FFFF + // + // We'll negate them to produce a value 0..2 for each element, then sum all the + // elements together to produce the number of *additional* UTF-8 code units + // required to represent this UTF-16 data. This is similar to the popcnt step + // performed by the SSE2 code path. This will overcount surrogates, but we'll + // handle that shortly. + + Vector utf16Data = Unsafe.ReadUnaligned>(pInputBuffer); + Vector twoOrMoreUtf8Bytes = Vector.GreaterThanOrEqual(utf16Data, vector0080); + Vector threeOrMoreUtf8Bytes = Vector.GreaterThanOrEqual(utf16Data, vector0800); + Vector sumVector = (Vector)(Vector.Zero - twoOrMoreUtf8Bytes - threeOrMoreUtf8Bytes); + + // We'll try summing by a natural word (rather than a 16-bit word) at a time, + // which should halve the number of operations we must perform. + + nuint popcnt = 0; + for (int i = 0; i < Vector.Count; i++) + { + popcnt += sumVector[i]; + } + + uint popcnt32 = (uint)popcnt; + if (IntPtr.Size == 8) + { + popcnt32 += (uint)(popcnt >> 32); + } + + // As in the SSE4.1 paths, compute popcnt but don't fold it in until we + // know there aren't any unpaired surrogates in the input data. + + popcnt32 = (ushort)popcnt32 + (popcnt32 >> 16); + + // Now check for surrogates. + + utf16Data -= vectorD800; + Vector surrogateChars = Vector.LessThan(utf16Data, vector0800); + if (surrogateChars != Vector.Zero) + { + // There's at least one surrogate (high or low) UTF-16 code unit in + // the vector. We'll build up additional vectors: 'highSurrogateChars' + // and 'lowSurrogateChars', where the elements are 0xFFFF iff the original + // UTF-16 code unit was a high or low surrogate, respectively. + + Vector highSurrogateChars = Vector.LessThan(utf16Data, vector0400); + Vector lowSurrogateChars = Vector.AndNot(surrogateChars, highSurrogateChars); + + // We want to make sure that each high surrogate code unit is followed by + // a low surrogate code unit and each low surrogate code unit follows a + // high surrogate code unit. Since we don't have an equivalent of pmovmskb + // or palignr available to us, we'll do this as a loop. We won't look at + // the very last high surrogate char element since we don't yet know if + // the next vector read will have a low surrogate char element. + + ushort surrogatePairsCount = 0; + for (int i = 0; i < Vector.Count - 1; i++) + { + surrogatePairsCount -= highSurrogateChars[i]; // turns into +1 or +0 + if (highSurrogateChars[i] != lowSurrogateChars[i + 1]) + { + goto NonVectorizedLoop; // error: mismatched surrogate pair; break out of vectorized logic + } + } + + if (highSurrogateChars[Vector.Count - 1] != 0) + { + // There was a standalone high surrogate at the end of the vector. + // We'll adjust our counters so that we don't consider this char consumed. + + pInputBuffer--; + inputLength++; + popcnt32 -= 2; + } + + nint surrogatePairsCountNint = (nint)surrogatePairsCount; // zero-extend to native int size + + // 2 UTF-16 chars become 1 Unicode scalar + + tempScalarCountAdjustment -= (int)surrogatePairsCountNint; + + // Since each surrogate code unit was >= 0x0800, we eagerly assumed + // it'd be encoded as 3 UTF-8 code units. Each surrogate half is only + // encoded as 2 UTF-8 code units (for 4 UTF-8 code units total), + // so we'll adjust this now. + + tempUtf8CodeUnitCountAdjustment -= surrogatePairsCountNint; + tempUtf8CodeUnitCountAdjustment -= surrogatePairsCountNint; + } + + tempUtf8CodeUnitCountAdjustment += popcnt32; + pInputBuffer += Vector.Count; + inputLength -= Vector.Count; + } while (inputLength >= Vector.Count); + } + } + + NonVectorizedLoop: + + // Vectorization isn't supported on our current platform, or the input was too small to benefit + // from vectorization, or we saw invalid UTF-16 data in the vectorized code paths and need to + // drain remaining valid chars before we report failure. + + for (; inputLength > 0; pInputBuffer++, inputLength--) + { + uint thisChar = pInputBuffer[0]; + if (thisChar <= 0x7F) + { + continue; + } + + // Bump adjustment by +1 for U+0080..U+07FF; by +2 for U+0800..U+FFFF. + // This optimistically assumes no surrogates, which we'll handle shortly. + + tempUtf8CodeUnitCountAdjustment += (thisChar + 0x0001_F800u) >> 16; + + if (!UnicodeUtility.IsSurrogateCodePoint(thisChar)) + { + continue; + } + + // Found a surrogate char. Back out the adjustment we made above, then + // try to consume the entire surrogate pair all at once. We won't bother + // trying to interpret the surrogate pair as a scalar value; we'll only + // validate that its bit pattern matches what's expected for a surrogate pair. + + tempUtf8CodeUnitCountAdjustment -= 2; + + if (inputLength == 1) + { + goto Error; // input buffer too small to read a surrogate pair + } + + thisChar = Unsafe.ReadUnaligned(pInputBuffer); + if (((thisChar - (BitConverter.IsLittleEndian ? 0xDC00_D800u : 0xD800_DC00u)) & 0xFC00_FC00u) != 0) + { + goto Error; // not a well-formed surrogate pair + } + + tempScalarCountAdjustment--; // 2 UTF-16 code units -> 1 scalar + tempUtf8CodeUnitCountAdjustment += 2; // 2 UTF-16 code units -> 4 UTF-8 code units + + pInputBuffer++; // consumed one extra char + inputLength--; + } + + Error: + + // Also used for normal return. + + utf8CodeUnitCountAdjustment = tempUtf8CodeUnitCountAdjustment; + scalarCountAdjustment = tempScalarCountAdjustment; + return pInputBuffer; + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Text/Utf16Utility.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf16Utility.cs similarity index 99% rename from src/System.Private.CoreLib/shared/System/Text/Utf16Utility.cs rename to src/System.Private.CoreLib/shared/System/Text/Unicode/Utf16Utility.cs index bed39057e44f..44d0316d280e 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Utf16Utility.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf16Utility.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Diagnostics; -namespace System.Text +namespace System.Text.Unicode { internal static partial class Utf16Utility { diff --git a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8.cs index 6c8197d22b13..1badd7db1112 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; +using System.Runtime.InteropServices; +using Internal.Runtime.CompilerServices; namespace System.Text.Unicode { @@ -37,79 +40,87 @@ public static class Utf8 /// in will be replaced with U+FFFD in , and /// this method will not return . /// - public static OperationStatus FromUtf16(ReadOnlySpan source, Span destination, out int numCharsRead, out int numBytesWritten, bool replaceInvalidSequences = true, bool isFinalBlock = true) + public static unsafe OperationStatus FromUtf16(ReadOnlySpan source, Span destination, out int charsRead, out int bytesWritten, bool replaceInvalidSequences = true, bool isFinalBlock = true) { - int originalSourceLength = source.Length; - int originalDestinationLength = destination.Length; - OperationStatus status = OperationStatus.Done; + // Throwaway span accesses - workaround for https://github.com/dotnet/coreclr/issues/23437 - // In a loop, this is going to read and transcode one scalar value at a time - // from the source to the destination. + _ = source.Length; + _ = destination.Length; - while (!source.IsEmpty) + fixed (char* pOriginalSource = &MemoryMarshal.GetReference(source)) + fixed (byte* pOriginalDestination = &MemoryMarshal.GetReference(destination)) { - status = Rune.DecodeFromUtf16(source, out Rune firstScalarValue, out int charsConsumed); + // We're going to bulk transcode as much as we can in a loop, iterating + // every time we see bad data that requires replacement. - switch (status) + OperationStatus operationStatus = OperationStatus.Done; + char* pInputBufferRemaining = pOriginalSource; + byte* pOutputBufferRemaining = pOriginalDestination; + + while (!source.IsEmpty) { - case OperationStatus.NeedMoreData: - - // Input buffer ended with a high surrogate. Only treat this as an error - // if the caller told us that we shouldn't expect additional data in a - // future call. - - if (!isFinalBlock) - { - goto Finish; - } - - status = OperationStatus.InvalidData; - goto case OperationStatus.InvalidData; - - case OperationStatus.InvalidData: - - // Input buffer contained invalid data. If the caller told us not to - // perform U+FFFD replacement, terminate the loop immediately and return - // an error to the caller. - - if (!replaceInvalidSequences) - { - goto Finish; - } - - firstScalarValue = Rune.ReplacementChar; - goto default; - - default: - - // We know which scalar value we need to transcode to UTF-8. - // Do so now, and only terminate the loop if we ran out of space - // in the destination buffer. - - if (firstScalarValue.TryEncodeToUtf8(destination, out int bytesWritten)) - { - source = source.Slice(charsConsumed); // don't use Rune.Utf8SequenceLength; we may have performed substitution - destination = destination.Slice(bytesWritten); - status = OperationStatus.Done; // forcibly set success - continue; - } - else - { - status = OperationStatus.DestinationTooSmall; - goto Finish; - } + // We've pinned the spans at the entry point to this method. + // It's safe for us to use Unsafe.AsPointer on them during this loop. + + operationStatus = Utf8Utility.TranscodeToUtf8( + pInputBuffer: (char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)), + inputLength: source.Length, + pOutputBuffer: (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(destination)), + outputBytesRemaining: destination.Length, + pInputBufferRemaining: out pInputBufferRemaining, + pOutputBufferRemaining: out pOutputBufferRemaining); + + // If we finished the operation entirely or we ran out of space in the destination buffer, + // or if we need more input data and the caller told us that there's possibly more data + // coming, return immediately. + + if (operationStatus <= OperationStatus.DestinationTooSmall + || (operationStatus == OperationStatus.NeedMoreData && !isFinalBlock)) + { + break; + } + + // We encountered invalid data, or we need more data but the caller told us we're + // at the end of the stream. In either case treat this as truly invalid. + // If the caller didn't tell us to replace invalid sequences, return immediately. + + if (!replaceInvalidSequences) + { + operationStatus = OperationStatus.InvalidData; // status code may have been NeedMoreData - force to be error + break; + } + + // We're going to attempt to write U+FFFD to the destination buffer. + // Do we even have enough space to do so? + + destination = destination.Slice((int)(pOutputBufferRemaining - (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(destination)))); + + if (2 >= (uint)destination.Length) + { + operationStatus = OperationStatus.DestinationTooSmall; + break; + } + + destination[0] = 0xEF; // U+FFFD = [ EF BF BD ] in UTF-8 + destination[1] = 0xBF; + destination[2] = 0xBD; + destination = destination.Slice(3); + + // Invalid UTF-16 sequences are always of length 1. Just skip the next character. + + source = source.Slice((int)(pInputBufferRemaining - (char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source))) + 1); + + operationStatus = OperationStatus.Done; // we patched the error - if we're about to break out of the loop this is a success case + pInputBufferRemaining = (char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)); + pOutputBufferRemaining = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(destination)); } - } - - Finish: - numCharsRead = originalSourceLength - source.Length; - numBytesWritten = originalDestinationLength - destination.Length; + // Not possible to make any further progress - report to our caller how far we got. - Debug.Assert((status == OperationStatus.Done) == (numCharsRead == originalSourceLength), - "Should report OperationStatus.Done if and only if we've consumed the entire input buffer."); - - return status; + charsRead = (int)(pInputBufferRemaining - pOriginalSource); + bytesWritten = (int)(pOutputBufferRemaining - pOriginalDestination); + return operationStatus; + } } /// @@ -120,79 +131,92 @@ public static OperationStatus FromUtf16(ReadOnlySpan source, Span de /// in will be replaced with U+FFFD in , and /// this method will not return . /// - public static OperationStatus ToUtf16(ReadOnlySpan source, Span destination, out int numBytesRead, out int numCharsWritten, bool replaceInvalidSequences = true, bool isFinalBlock = true) + public static unsafe OperationStatus ToUtf16(ReadOnlySpan source, Span destination, out int numBytesRead, out int numCharsWritten, bool replaceInvalidSequences = true, bool isFinalBlock = true) { - int originalSourceLength = source.Length; - int originalDestinationLength = destination.Length; - OperationStatus status = OperationStatus.Done; + // Throwaway span accesses - workaround for https://github.com/dotnet/coreclr/issues/23437 + + _ = source.Length; + _ = destination.Length; - // In a loop, this is going to read and transcode one scalar value at a time - // from the source to the destination. + // We'll be mutating these values throughout our loop. - while (!source.IsEmpty) + fixed (byte* pOriginalSource = &MemoryMarshal.GetReference(source)) + fixed (char* pOriginalDestination = &MemoryMarshal.GetReference(destination)) { - status = Rune.DecodeFromUtf8(source, out Rune firstScalarValue, out int bytesConsumed); + // We're going to bulk transcode as much as we can in a loop, iterating + // every time we see bad data that requires replacement. - switch (status) + OperationStatus operationStatus = OperationStatus.Done; + byte* pInputBufferRemaining = pOriginalSource; + char* pOutputBufferRemaining = pOriginalDestination; + + while (!source.IsEmpty) { - case OperationStatus.NeedMoreData: - - // Input buffer ended with a partial UTF-8 sequence. Only treat this as an error - // if the caller told us that we shouldn't expect additional data in a - // future call. - - if (!isFinalBlock) - { - goto Finish; - } - - status = OperationStatus.InvalidData; - goto case OperationStatus.InvalidData; - - case OperationStatus.InvalidData: - - // Input buffer contained invalid data. If the caller told us not to - // perform U+FFFD replacement, terminate the loop immediately and return - // an error to the caller. - - if (!replaceInvalidSequences) - { - goto Finish; - } - - firstScalarValue = Rune.ReplacementChar; - goto default; - - default: - - // We know which scalar value we need to transcode to UTF-16. - // Do so now, and only terminate the loop if we ran out of space - // in the destination buffer. - - if (firstScalarValue.TryEncodeToUtf16(destination, out int charsWritten)) - { - source = source.Slice(bytesConsumed); // don't use Rune.Utf16SequenceLength; we may have performed substitution - destination = destination.Slice(charsWritten); - status = OperationStatus.Done; // forcibly set success - continue; - } - else - { - status = OperationStatus.DestinationTooSmall; - goto Finish; - } + // We've pinned the spans at the entry point to this method. + // It's safe for us to use Unsafe.AsPointer on them during this loop. + + operationStatus = Utf8Utility.TranscodeToUtf16( + pInputBuffer: (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)), + inputLength: source.Length, + pOutputBuffer: (char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(destination)), + outputCharsRemaining: destination.Length, + pInputBufferRemaining: out pInputBufferRemaining, + pOutputBufferRemaining: out pOutputBufferRemaining); + + // If we finished the operation entirely or we ran out of space in the destination buffer, + // or if we need more input data and the caller told us that there's possibly more data + // coming, return immediately. + + if (operationStatus <= OperationStatus.DestinationTooSmall + || (operationStatus == OperationStatus.NeedMoreData && !isFinalBlock)) + { + break; + } + + // We encountered invalid data, or we need more data but the caller told us we're + // at the end of the stream. In either case treat this as truly invalid. + // If the caller didn't tell us to replace invalid sequences, return immediately. + + if (!replaceInvalidSequences) + { + operationStatus = OperationStatus.InvalidData; // status code may have been NeedMoreData - force to be error + break; + } + + // We're going to attempt to write U+FFFD to the destination buffer. + // Do we even have enough space to do so? + + destination = destination.Slice((int)(pOutputBufferRemaining - (char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(destination)))); + + if (destination.IsEmpty) + { + operationStatus = OperationStatus.DestinationTooSmall; + break; + } + + destination[0] = (char)UnicodeUtility.ReplacementChar; + destination = destination.Slice(1); + + // Now figure out how many bytes of the source we must skip over before we should retry + // the operation. This might be more than 1 byte. + + source = source.Slice((int)(pInputBufferRemaining - (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)))); + Debug.Assert(!source.IsEmpty, "Expected 'Done' if source is fully consumed."); + + Rune.DecodeFromUtf8(source, out _, out int bytesConsumedJustNow); + source = source.Slice(bytesConsumedJustNow); + + operationStatus = OperationStatus.Done; // we patched the error - if we're about to break out of the loop this is a success case + pInputBufferRemaining = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)); + pOutputBufferRemaining = (char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(destination)); } - } - - Finish: - numBytesRead = originalSourceLength - source.Length; - numCharsWritten = originalDestinationLength - destination.Length; + // Not possible to make any further progress - report to our caller how far we got. - Debug.Assert((status == OperationStatus.Done) == (numBytesRead == originalSourceLength), - "Should report OperationStatus.Done if and only if we've consumed the entire input buffer."); - - return status; + numBytesRead = (int)(pInputBufferRemaining - pOriginalSource); + numCharsWritten = (int)(pOutputBufferRemaining - pOriginalDestination); + return operationStatus; + } } } } diff --git a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Helpers.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Helpers.cs new file mode 100644 index 000000000000..4bfc6158af29 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Helpers.cs @@ -0,0 +1,864 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Buffers.Binary; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.X86; +using Internal.Runtime.CompilerServices; + +namespace System.Text.Unicode +{ + internal static partial class Utf8Utility + { + /// + /// Given a machine-endian DWORD which four bytes of UTF-8 data, interprets the + /// first three bytes as a three-byte UTF-8 subsequence and returns the UTF-16 representation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ExtractCharFromFirstThreeByteSequence(uint value) + { + Debug.Assert(UInt32BeginsWithUtf8ThreeByteMask(value)); + + if (BitConverter.IsLittleEndian) + { + // value = [ ######## | 10xxxxxx 10yyyyyy 1110zzzz ] + return ((value & 0x003F0_000u) >> 16) + | ((value & 0x0000_3F00u) >> 2) + | ((value & 0x0000_000Fu) << 12); + } + else + { + // value = [ 1110zzzz 10yyyyyy 10xxxxxx | ######## ] + return ((value & 0x0F00_0000u) >> 12) + | ((value & 0x003F_0000u) >> 10) + | ((value & 0x0000_3F00u) >> 8); + } + } + + /// + /// Given a machine-endian DWORD which four bytes of UTF-8 data, interprets the + /// first two bytes as a two-byte UTF-8 subsequence and returns the UTF-16 representation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ExtractCharFromFirstTwoByteSequence(uint value) + { + Debug.Assert(UInt32BeginsWithUtf8TwoByteMask(value) && !UInt32BeginsWithOverlongUtf8TwoByteSequence(value)); + + if (BitConverter.IsLittleEndian) + { + // value = [ ######## ######## | 10xxxxxx 110yyyyy ] + uint leadingByte = (uint)(byte)value << 6; + return (uint)(byte)(value >> 8) + leadingByte - (0xC0u << 6) - 0x80u; // remove header bits + } + else + { + // value = [ 110yyyyy 10xxxxxx | ######## ######## ] + return (char)(((value & 0x1F00_0000u) >> 18) | ((value & 0x003F_0000u) >> 16)); + } + } + + /// + /// Given a machine-endian DWORD which four bytes of UTF-8 data, interprets the input as a + /// four-byte UTF-8 sequence and returns the machine-endian DWORD of the UTF-16 representation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static uint ExtractCharsFromFourByteSequence(uint value) + { + if (BitConverter.IsLittleEndian) + { + if (Bmi2.IsSupported) + { + // need to reverse endianness for bit manipulation to work correctly + value = BinaryPrimitives.ReverseEndianness(value); + + // value = [ 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ] + // want to return [ 110110wwwwxxxxxx 110111xxxxxxxxxx ] + // where wwww = uuuuu - 1 + + uint highSurrogateChar = Bmi2.ParallelBitExtract(value, 0b00000111_00111111_00110000_00000000u); + uint lowSurrogateChar = Bmi2.ParallelBitExtract(value, 0b00000000_00000000_00001111_00111111u); + + uint combined = (lowSurrogateChar << 16) + highSurrogateChar; + combined -= 0x40u; // wwww = uuuuu - 1 + combined += 0xDC00_D800u; // add surrogate markers + return combined; + } + else + { + // input is UTF8 [ 10xxxxxx 10yyyyyy 10uuzzzz 11110uuu ] = scalar 000uuuuu zzzzyyyy yyxxxxxx + // want to return UTF16 scalar 000uuuuuzzzzyyyyyyxxxxxx = [ 110111yy yyxxxxxx 110110ww wwzzzzyy ] + // where wwww = uuuuu - 1 + uint retVal = (uint)(byte)value << 8; // retVal = [ 00000000 00000000 11110uuu 00000000 ] + retVal |= (value & 0x0000_3F00u) >> 6; // retVal = [ 00000000 00000000 11110uuu uuzzzz00 ] + retVal |= (value & 0x0030_0000u) >> 20; // retVal = [ 00000000 00000000 11110uuu uuzzzzyy ] + retVal |= (value & 0x3F00_0000u) >> 8; // retVal = [ 00000000 00xxxxxx 11110uuu uuzzzzyy ] + retVal |= (value & 0x000F_0000u) << 6; // retVal = [ 000000yy yyxxxxxx 11110uuu uuzzzzyy ] + retVal -= 0x0000_0040u; // retVal = [ 000000yy yyxxxxxx 111100ww wwzzzzyy ] + retVal -= 0x0000_2000u; // retVal = [ 000000yy yyxxxxxx 110100ww wwzzzzyy ] + retVal += 0x0000_0800u; // retVal = [ 000000yy yyxxxxxx 110110ww wwzzzzyy ] + retVal += 0xDC00_0000u; // retVal = [ 110111yy yyxxxxxx 110110ww wwzzzzyy ] + return retVal; + } + } + else + { + // input is UTF8 [ 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ] = scalar 000uuuuu zzzzyyyy yyxxxxxx + // want to return UTF16 scalar 000uuuuuxxxxxxxxxxxxxxxx = [ 110110wwwwxxxxxx 110111xxxxxxxxx ] + // where wwww = uuuuu - 1 + uint retVal = value & 0xFF00_0000u; // retVal = [ 11110uuu 00000000 00000000 00000000 ] + retVal |= (value & 0x003F_0000u) << 2; // retVal = [ 11110uuu uuzzzz00 00000000 00000000 ] + retVal |= (value & 0x0000_3000u) << 4; // retVal = [ 11110uuu uuzzzzyy 00000000 00000000 ] + retVal |= (value & 0x0000_0F00u) >> 2; // retVal = [ 11110uuu uuzzzzyy 000000yy yy000000 ] + retVal |= (value & 0x0000_003Fu); // retVal = [ 11110uuu uuzzzzyy 000000yy yyxxxxxx ] + retVal -= 0x2000_0000u; // retVal = [ 11010uuu uuzzzzyy 000000yy yyxxxxxx ] + retVal -= 0x0040_0000u; // retVal = [ 110100ww wwzzzzyy 000000yy yyxxxxxx ] + retVal += 0x0000_DC00u; // retVal = [ 110100ww wwzzzzyy 110111yy yyxxxxxx ] + retVal += 0x0800_0000u; // retVal = [ 110110ww wwzzzzyy 110111yy yyxxxxxx ] + return retVal; + } + } + + /// + /// Given a 32-bit integer that represents a valid packed UTF-16 surrogate pair, all in machine-endian order, + /// returns the packed 4-byte UTF-8 representation of this scalar value, also in machine-endian order. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ExtractFourUtf8BytesFromSurrogatePair(uint value) + { + Debug.Assert(IsWellFormedUtf16SurrogatePair(value)); + + if (BitConverter.IsLittleEndian) + { + // input = [ 110111yyyyxxxxxx 110110wwwwzzzzyy ] = scalar (000uuuuu zzzzyyyy yyxxxxxx) + // must return [ 10xxxxxx 10yyyyyy 10uuzzzz 11110uuu ], where wwww = uuuuu - 1 + + if (Bmi2.IsSupported) + { + // Since pdep and pext have high latencies and can only be dispatched to a single execution port, we want + // to use them conservatively. Here, we'll build up the scalar value (this would normally be pext) via simple + // logical and arithmetic operations, and use only pdep for the expensive step of exploding the scalar across + // all four output bytes. + + uint unmaskedScalar = (value << 10) + (value >> 16) + ((0x40u) << 10) /* uuuuu = wwww + 1 */ - 0xDC00u /* remove low surrogate marker */; + + // Now, unmaskedScalar = [ xxxxxx11 011uuuuu zzzzyyyy yyxxxxxx ]. There's a bit of unneeded junk at the beginning + // that should normally be masked out via an and, but we'll just direct pdep to ignore it. + + uint exploded = Bmi2.ParallelBitDeposit(unmaskedScalar, 0b00000111_00111111_00111111_00111111u); // = [ 00000uuu 00uuzzzz 00yyyyyy 00xxxxxx ] + return BinaryPrimitives.ReverseEndianness(exploded + 0xF080_8080u); // = [ 10xxxxxx 10yyyyyy 10uuzzzz 11110uuu ] + } + else + { + value += 0x0000_0040u; // = [ 110111yyyyxxxxxx 11011uuuuuzzzzyy ] + + uint tempA = BinaryPrimitives.ReverseEndianness(value & 0x003F_0700u); // = [ 00000000 00000uuu 00xxxxxx 00000000 ] + tempA = BitOperations.RotateLeft(tempA, 16); // = [ 00xxxxxx 00000000 00000000 00000uuu ] + + uint tempB = (value & 0x00FCu) << 6; // = [ 00000000 00000000 00uuzzzz 00000000 ] + uint tempC = (value >> 6) & 0x000F_0000u; // = [ 00000000 0000yyyy 00000000 00000000 ] + tempC |= tempB; + + uint tempD = (value & 0x03u) << 20; // = [ 00000000 00yy0000 00000000 00000000 ] + tempD |= 0x8080_80F0u; + + return (tempD | tempA | tempC); // = [ 10xxxxxx 10yyyyyy 10uuzzzz 11110uuu ] + } + } + else + { + // input = [ 110110wwwwzzzzyy 110111yyyyxxxxxx ], where wwww = uuuuu - 1 + // must return [ 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ], where wwww = uuuuu - 1 + + value -= 0xD800_DC00u; // = [ 000000wwwwzzzzyy 000000yyyyxxxxxx ] + value += 0x0040_0000u; // = [ 00000uuuuuzzzzyy 000000yyyyxxxxxx ] + + uint tempA = value & 0x0700_0000u; // = [ 00000uuu 00000000 00000000 00000000 ] + uint tempB = (value >> 2) & 0x003F_0000u; // = [ 00000000 00uuzzzz 00000000 00000000 ] + tempB |= tempA; + + uint tempC = (value << 2) & 0x0000_0F00u; // = [ 00000000 00000000 0000yyyy 00000000 ] + uint tempD = (value >> 6) & 0x0003_0000u; // = [ 00000000 00000000 00yy0000 00000000 ] + tempD |= tempC; + + uint tempE = (value & 0x3Fu) + 0xF080_8080u; // = [ 11110000 10000000 10000000 10xxxxxx ] + return (tempE | tempB | tempD); // = [ 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ] + } + } + + /// + /// Given a machine-endian DWORD which represents two adjacent UTF-8 two-byte sequences, + /// returns the machine-endian DWORD representation of that same data as two adjacent + /// UTF-16 byte sequences. + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ExtractTwoCharsPackedFromTwoAdjacentTwoByteSequences(uint value) + { + // We don't want to swap the position of the high and low WORDs, + // as the buffer was read in machine order and will be written in + // machine order. + + if (BitConverter.IsLittleEndian) + { + // value = [ 10xxxxxx 110yyyyy | 10xxxxxx 110yyyyy ] + return ((value & 0x3F003F00u) >> 8) | ((value & 0x001F001Fu) << 6); + } + else + { + // value = [ 110yyyyy 10xxxxxx | 110yyyyy 10xxxxxx ] + return ((value & 0x1F001F00u) >> 2) | (value & 0x003F003Fu); + } + } + + /// + /// Given a machine-endian DWORD which represents two adjacent UTF-16 sequences, + /// returns the machine-endian DWORD representation of that same data as two + /// adjacent UTF-8 two-byte sequences. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ExtractTwoUtf8TwoByteSequencesFromTwoPackedUtf16Chars(uint value) + { + // stays in machine endian + + Debug.Assert(IsFirstCharTwoUtf8Bytes(value) && IsSecondCharTwoUtf8Bytes(value)); + + if (BitConverter.IsLittleEndian) + { + // value = [ 00000YYY YYXXXXXX 00000yyy yyxxxxxx ] + // want to return [ 10XXXXXX 110YYYYY 10xxxxxx 110yyyyy ] + + return ((value >> 6) & 0x001F_001Fu) + ((value << 8) & 0x3F00_3F00u) + 0x80C0_80C0u; + } + else + { + // value = [ 00000YYY YYXXXXXX 00000yyy yyxxxxxx ] + // want to return [ 110YYYYY 10XXXXXX 110yyyyy 10xxxxxx ] + + return ((value << 2) & 0x1F00_1F00u) + (value & 0x003F_003Fu) + 0xC080_C080u; + } + } + + /// + /// Given a machine-endian DWORD which represents two adjacent UTF-16 sequences, + /// returns the machine-endian DWORD representation of the first UTF-16 char + /// as a UTF-8 two-byte sequence packed into a WORD and zero-extended to DWORD. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ExtractUtf8TwoByteSequenceFromFirstUtf16Char(uint value) + { + // stays in machine endian + + Debug.Assert(IsFirstCharTwoUtf8Bytes(value)); + + if (BitConverter.IsLittleEndian) + { + // value = [ ######## ######## 00000yyy yyxxxxxx ] + // want to return [ ######## ######## 10xxxxxx 110yyyyy ] + + uint temp = (value << 2) & 0x1F00u; // [ 00000000 00000000 000yyyyy 00000000 ] + value &= 0x3Fu; // [ 00000000 00000000 00000000 00xxxxxx ] + return BinaryPrimitives.ReverseEndianness((ushort)(temp + value + 0xC080u)); // [ 00000000 00000000 10xxxxxx 110yyyyy ] + } + else + { + // value = [ 00000yyy yyxxxxxx ######## ######## ] + // want to return [ ######## ######## 110yyyyy 10xxxxxx ] + + uint temp = (value >> 16) & 0x3Fu; // [ 00000000 00000000 00000000 00xxxxxx ] + value = (value >> 22) & 0x1F00u; // [ 00000000 00000000 000yyyyy 0000000 ] + return value + temp + 0xC080u; + } + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the first UTF-16 character is ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsFirstCharAscii(uint value) + { + // Little-endian: Given [ #### AAAA ], return whether AAAA is in range [ 0000..007F ]. + // Big-endian: Given [ AAAA #### ], return whether AAAA is in range [ 0000..007F ]. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (value & 0xFF80u) == 0) + || (!BitConverter.IsLittleEndian && value < 0x0080_0000u); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the first UTF-16 character requires *at least* 3 bytes to encode in UTF-8. + /// This also returns true if the first UTF-16 character is a surrogate character (well-formedness is not validated). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsFirstCharAtLeastThreeUtf8Bytes(uint value) + { + // Little-endian: Given [ #### AAAA ], return whether AAAA is in range [ 0800..FFFF ]. + // Big-endian: Given [ AAAA #### ], return whether AAAA is in range [ 0800..FFFF ]. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (value & 0xF800u) != 0) + || (!BitConverter.IsLittleEndian && value >= 0x0800_0000u); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the first UTF-16 character is a surrogate character (either high or low). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsFirstCharSurrogate(uint value) + { + // Little-endian: Given [ #### AAAA ], return whether AAAA is in range [ D800..DFFF ]. + // Big-endian: Given [ AAAA #### ], return whether AAAA is in range [ D800..DFFF ]. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value - 0xD800u) & 0xF800u) == 0) + || (!BitConverter.IsLittleEndian && (value - 0xD800_0000u) < 0x0800_0000u); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the first UTF-16 character would be encoded as exactly 2 bytes in UTF-8. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsFirstCharTwoUtf8Bytes(uint value) + { + // Little-endian: Given [ #### AAAA ], return whether AAAA is in range [ 0080..07FF ]. + // Big-endian: Given [ AAAA #### ], return whether AAAA is in range [ 0080..07FF ]. + + // TODO: I'd like to be able to write "(ushort)(value - 0x0080u) < 0x0780u" for the little-endian + // case, but the JIT doesn't currently emit 16-bit comparisons efficiently. + // Tracked as https://github.com/dotnet/coreclr/issues/18022. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value - 0x0080u) & 0xFFFFu) < 0x0780u) + || (!BitConverter.IsLittleEndian && UnicodeUtility.IsInRangeInclusive(value, 0x0080_0000u, 0x07FF_FFFFu)); + } + + /// + /// Returns iff the low byte of + /// is a UTF-8 continuation byte. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsLowByteUtf8ContinuationByte(uint value) + { + // The JIT won't emit a single 8-bit signed cmp instruction (see IsUtf8ContinuationByte), + // so the best we can do for now is the lea / cmp pair. + // Tracked as https://github.com/dotnet/coreclr/issues/18022. + + return (byte)(value - 0x80u) <= 0x3Fu; + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the second UTF-16 character is ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsSecondCharAscii(uint value) + { + // Little-endian: Given [ BBBB #### ], return whether BBBB is in range [ 0000..007F ]. + // Big-endian: Given [ #### BBBB ], return whether BBBB is in range [ 0000..007F ]. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && value < 0x0080_0000u) + || (!BitConverter.IsLittleEndian && (value & 0xFF80u) == 0); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the second UTF-16 character requires *at least* 3 bytes to encode in UTF-8. + /// This also returns true if the second UTF-16 character is a surrogate character (well-formedness is not validated). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsSecondCharAtLeastThreeUtf8Bytes(uint value) + { + // Little-endian: Given [ BBBB #### ], return whether BBBB is in range [ 0800..FFFF ]. + // Big-endian: Given [ #### BBBB ], return whether ABBBBAAA is in range [ 0800..FFFF ]. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (value & 0xF800_0000u) != 0) + || (!BitConverter.IsLittleEndian && (value & 0xF800u) != 0); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the second UTF-16 character is a surrogate character (either high or low). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsSecondCharSurrogate(uint value) + { + // Little-endian: Given [ BBBB #### ], return whether BBBB is in range [ D800..DFFF ]. + // Big-endian: Given [ #### BBBB ], return whether BBBB is in range [ D800..DFFF ]. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (value - 0xD800_0000u) < 0x0800_0000u) + || (!BitConverter.IsLittleEndian && ((value - 0xD800u) & 0xF800u) == 0); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the second UTF-16 character would be encoded as exactly 2 bytes in UTF-8. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsSecondCharTwoUtf8Bytes(uint value) + { + // Little-endian: Given [ BBBB #### ], return whether BBBB is in range [ 0080..07FF ]. + // Big-endian: Given [ #### BBBB ], return whether BBBB is in range [ 0080..07FF ]. + + // TODO: I'd like to be able to write "(ushort)(value - 0x0080u) < 0x0780u" for the big-endian + // case, but the JIT doesn't currently emit 16-bit comparisons efficiently. + // Tracked as https://github.com/dotnet/coreclr/issues/18022. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && UnicodeUtility.IsInRangeInclusive(value, 0x0080_0000u, 0x07FF_FFFFu)) + || (!BitConverter.IsLittleEndian && ((value - 0x0080u) & 0xFFFFu) < 0x0780u); + } + + /// + /// Returns iff is a UTF-8 continuation byte; + /// i.e., has binary representation 10xxxxxx, where x is any bit. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsUtf8ContinuationByte(in byte value) + { + // This API takes its input as a readonly ref so that the JIT can emit "cmp ModRM" statements + // directly rather than bounce a temporary through a register. That is, we want the JIT to be + // able to emit a single "cmp byte ptr [data], C0h" statement if we're querying a memory location + // to see if it's a continuation byte. Data that's already enregistered will go through the + // normal "cmp reg, C0h" code paths, perhaps with some extra unnecessary "movzx" instructions. + // + // The below check takes advantage of the two's complement representation of negative numbers. + // [ 0b1000_0000, 0b1011_1111 ] is [ -127 (sbyte.MinValue), -65 ] + + return ((sbyte)value < -64); + } + + /// + /// Given a 32-bit integer that represents two packed UTF-16 characters, all in machine-endian order, + /// returns true iff the two characters represent a well-formed UTF-16 surrogate pair. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsWellFormedUtf16SurrogatePair(uint value) + { + // Little-endian: Given [ LLLL HHHH ], validate that LLLL in [ DC00..DFFF ] and HHHH in [ D800..DBFF ]. + // Big-endian: Given [ HHHH LLLL ], validate that HHHH in [ D800..DBFF ] and LLLL in [ DC00..DFFF ]. + // + // We're essentially performing a range check on each component of the input in parallel. The allowed range + // ends up being "< 0x0400" after the beginning of the allowed range is subtracted from each element. We + // can't perform the equivalent of two CMPs in parallel, but we can take advantage of the fact that 0x0400 + // is a whole power of 2, which means that a CMP is really just a glorified TEST operation. Two TESTs *can* + // be performed in parallel. The logic below then becomes 3 operations: "add/lea; test; jcc". + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value - 0xDC00_D800u) & 0xFC00_FC00u) == 0) + || (!BitConverter.IsLittleEndian && ((value - 0xD800_DC00u) & 0xFC00_FC00u) == 0); + } + + /// + /// Converts a DWORD from machine-endian to little-endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint ToLittleEndian(uint value) + { + if (BitConverter.IsLittleEndian) + { + return value; + } + else + { + return BinaryPrimitives.ReverseEndianness(value); + } + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the first two bytes of the buffer are + /// an overlong representation of a sequence that should be represented as one byte. + /// This method *does not* validate that the sequence matches the appropriate + /// 2-byte sequence mask (see ). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32BeginsWithOverlongUtf8TwoByteSequence(uint value) + { + // ASSUMPTION: Caller has already checked the '110yyyyy 10xxxxxx' mask of the input. + Debug.Assert(UInt32BeginsWithUtf8TwoByteMask(value)); + + // Per Table 3-7, first byte of two-byte sequence must be within range C2 .. DF. + // Since we already validated it's 80 <= ?? <= DF (per mask check earlier), now only need + // to check that it's < C2. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((byte)value < 0xC2u)) + || (!BitConverter.IsLittleEndian && (value < 0xC200_0000u)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the first four bytes of the buffer match + /// the UTF-8 4-byte sequence mask [ 11110www 10zzzzzz 10yyyyyy 10xxxxxx ]. This + /// method *does not* validate that the sequence is well-formed; the caller must + /// still perform overlong form or out-of-range checking. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32BeginsWithUtf8FourByteMask(uint value) + { + // The code in this method is equivalent to the code + // below but is slightly more optimized. + // + // if (BitConverter.IsLittleEndian) + // { + // const uint mask = 0xC0C0C0F8U; + // const uint comparand = 0x808080F0U; + // return ((value & mask) == comparand); + // } + // else + // { + // const uint mask = 0xF8C0C0C0U; + // const uint comparand = 0xF0808000U; + // return ((value & mask) == comparand); + // } + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (((value - 0x8080_80F0u) & 0xC0C0_C0F8u) == 0)) + || (!BitConverter.IsLittleEndian && (((value - 0xF080_8000u) & 0xF8C0_C0C0u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the first three bytes of the buffer match + /// the UTF-8 3-byte sequence mask [ 1110zzzz 10yyyyyy 10xxxxxx ]. This method *does not* + /// validate that the sequence is well-formed; the caller must still perform + /// overlong form or surrogate checking. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32BeginsWithUtf8ThreeByteMask(uint value) + { + // The code in this method is equivalent to the code + // below but is slightly more optimized. + // + // if (BitConverter.IsLittleEndian) + // { + // const uint mask = 0x00C0C0F0U; + // const uint comparand = 0x008080E0U; + // return ((value & mask) == comparand); + // } + // else + // { + // const uint mask = 0xF0C0C000U; + // const uint comparand = 0xE0808000U; + // return ((value & mask) == comparand); + // } + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (((value - 0x0080_80E0u) & 0x00C0_C0F0u) == 0)) + || (!BitConverter.IsLittleEndian && (((value - 0xE080_8000u) & 0xF0C0_C000u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the first two bytes of the buffer match + /// the UTF-8 2-byte sequence mask [ 110yyyyy 10xxxxxx ]. This method *does not* + /// validate that the sequence is well-formed; the caller must still perform + /// overlong form checking. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32BeginsWithUtf8TwoByteMask(uint value) + { + // The code in this method is equivalent to the code + // below but is slightly more optimized. + // + // if (BitConverter.IsLittleEndian) + // { + // const uint mask = 0x0000C0E0U; + // const uint comparand = 0x000080C0U; + // return ((value & mask) == comparand); + // } + // else + // { + // const uint mask = 0xE0C00000U; + // const uint comparand = 0xC0800000U; + // return ((value & mask) == comparand); + // } + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (((value - 0x0000_80C0u) & 0x0000_C0E0u) == 0)) + || (!BitConverter.IsLittleEndian && (((value - 0xC080_0000u) & 0xE0C0_0000u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the first two bytes of the buffer are + /// an overlong representation of a sequence that should be represented as one byte. + /// This method *does not* validate that the sequence matches the appropriate + /// 2-byte sequence mask (see ). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32EndsWithOverlongUtf8TwoByteSequence(uint value) + { + // ASSUMPTION: Caller has already checked the '110yyyyy 10xxxxxx' mask of the input. + Debug.Assert(UInt32EndsWithUtf8TwoByteMask(value)); + + // Per Table 3-7, first byte of two-byte sequence must be within range C2 .. DF. + // We already validated that it's 80 .. DF (per mask check earlier). + // C2 = 1100 0010 + // DF = 1101 1111 + // This means that we can AND the leading byte with the mask 0001 1110 (1E), + // and if the result is zero the sequence is overlong. + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value & 0x001E_0000u) == 0)) + || (!BitConverter.IsLittleEndian && ((value & 0x1E00u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the last two bytes of the buffer match + /// the UTF-8 2-byte sequence mask [ 110yyyyy 10xxxxxx ]. This method *does not* + /// validate that the sequence is well-formed; the caller must still perform + /// overlong form checking. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32EndsWithUtf8TwoByteMask(uint value) + { + // The code in this method is equivalent to the code + // below but is slightly more optimized. + // + // if (BitConverter.IsLittleEndian) + // { + // const uint mask = 0xC0E00000U; + // const uint comparand = 0x80C00000U; + // return ((value & mask) == comparand); + // } + // else + // { + // const uint mask = 0x0000E0C0U; + // const uint comparand = 0x0000C080U; + // return ((value & mask) == comparand); + // } + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && (((value - 0x80C0_0000u) & 0xC0E0_0000u) == 0)) + || (!BitConverter.IsLittleEndian && (((value - 0x0000_C080u) & 0x0000_E0C0u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD on a little-endian machine, + /// returns iff the first two bytes of the buffer are a well-formed + /// UTF-8 two-byte sequence. This wraps the mask check and the overlong check into a + /// single operation. Returns if running on a big-endian machine. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32BeginsWithValidUtf8TwoByteSequenceLittleEndian(uint value) + { + // Per Table 3-7, valid 2-byte sequences are [ C2..DF ] [ 80..BF ]. + // In little-endian, that would be represented as: + // [ ######## ######## 10xxxxxx 110yyyyy ]. + // Due to the little-endian representation we can perform a trick by ANDing the low + // WORD with the bitmask [ 11000000 11111111 ] and checking that the value is within + // the range [ 10000000_11000010, 10000000_11011111 ]. This performs both the + // 2-byte-sequence bitmask check and overlong form validation with one comparison. + + Debug.Assert(BitConverter.IsLittleEndian); + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && UnicodeUtility.IsInRangeInclusive(value & 0xC0FFu, 0x80C2u, 0x80DFu)) + || (!BitConverter.IsLittleEndian && false); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD on a little-endian machine, + /// returns iff the last two bytes of the buffer are a well-formed + /// UTF-8 two-byte sequence. This wraps the mask check and the overlong check into a + /// single operation. Returns if running on a big-endian machine. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32EndsWithValidUtf8TwoByteSequenceLittleEndian(uint value) + { + // See comments in UInt32BeginsWithValidUtf8TwoByteSequenceLittleEndian. + + Debug.Assert(BitConverter.IsLittleEndian); + + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && UnicodeUtility.IsInRangeInclusive(value & 0xC0FF_0000u, 0x80C2_0000u, 0x80DF_0000u)) + || (!BitConverter.IsLittleEndian && false); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the first byte of the buffer is ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32FirstByteIsAscii(uint value) + { + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value & 0x80u) == 0)) + || (!BitConverter.IsLittleEndian && ((int)value >= 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the fourth byte of the buffer is ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32FourthByteIsAscii(uint value) + { + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((int)value >= 0)) + || (!BitConverter.IsLittleEndian && ((value & 0x80u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the second byte of the buffer is ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32SecondByteIsAscii(uint value) + { + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value & 0x8000u) == 0)) + || (!BitConverter.IsLittleEndian && ((value & 0x0080_0000u) == 0)); + } + + /// + /// Given a UTF-8 buffer which has been read into a DWORD in machine endianness, + /// returns iff the third byte of the buffer is ASCII. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool UInt32ThirdByteIsAscii(uint value) + { + // Return statement is written this way to work around https://github.com/dotnet/coreclr/issues/914. + + return (BitConverter.IsLittleEndian && ((value & 0x0080_0000u) == 0)) + || (!BitConverter.IsLittleEndian && ((value & 0x8000u) == 0)); + } + + /// + /// Given a DWORD which represents a buffer of 4 ASCII bytes, widen each byte to a 16-bit WORD + /// and writes the resulting QWORD into the destination with machine endianness. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private static void Widen4AsciiBytesToCharsAndWrite(ref char outputBuffer, uint value) + { + if (Bmi2.X64.IsSupported) + { + // BMI2 will work regardless of the processor's endianness. + Unsafe.WriteUnaligned(ref Unsafe.As(ref outputBuffer), Bmi2.X64.ParallelBitDeposit(value, 0x00FF00FF_00FF00FFul)); + } + else + { + if (BitConverter.IsLittleEndian) + { + outputBuffer = (char)(byte)value; + value >>= 8; + Unsafe.Add(ref outputBuffer, 1) = (char)(byte)value; + value >>= 8; + Unsafe.Add(ref outputBuffer, 2) = (char)(byte)value; + value >>= 8; + Unsafe.Add(ref outputBuffer, 3) = (char)value; + } + else + { + Unsafe.Add(ref outputBuffer, 3) = (char)(byte)value; + value >>= 8; + Unsafe.Add(ref outputBuffer, 2) = (char)(byte)value; + value >>= 8; + Unsafe.Add(ref outputBuffer, 1) = (char)(byte)value; + value >>= 8; + outputBuffer = (char)value; + } + } + } + + /// + /// Given a DWORD which represents a buffer of 2 packed UTF-16 values in machine endianess, + /// converts those scalar values to their 3-byte UTF-8 representation and writes the + /// resulting 6 bytes to the destination buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteTwoUtf16CharsAsTwoUtf8ThreeByteSequences(ref byte outputBuffer, uint value) + { + Debug.Assert(IsFirstCharAtLeastThreeUtf8Bytes(value) && !IsFirstCharSurrogate(value), "First half of value should've been 0800..D7FF or E000..FFFF"); + Debug.Assert(IsSecondCharAtLeastThreeUtf8Bytes(value) && !IsSecondCharSurrogate(value), "Second half of value should've been 0800..D7FF or E000..FFFF"); + + if (BitConverter.IsLittleEndian) + { + // value = [ ZZZZYYYY YYXXXXXX zzzzyyyy yyxxxxxx ] + // want to write [ 1110ZZZZ 10xxxxxx 10yyyyyy 1110zzzz ] [ 10XXXXXX 10YYYYYY ] + + uint tempA = ((value << 2) & 0x3F00u) | ((value & 0x3Fu) << 16); // = [ 00000000 00xxxxxx 00yyyyyy 00000000 ] + uint tempB = ((value >> 4) & 0x0F00_0000u) | ((value >> 12) & 0x0Fu); // = [ 0000ZZZZ 00000000 00000000 0000zzzz ] + Unsafe.WriteUnaligned(ref outputBuffer, tempA + tempB + 0xE080_80E0u); // = [ 1110ZZZZ 10xxxxxx 10yyyyyy 1110zzzz ] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref outputBuffer, 4), (ushort)(((value >> 22) & 0x3Fu) + ((value >> 8) & 0x3F00u) + 0x8080u)); // = [ 10XXXXXX 10YYYYYY ] + } + else + { + // value = [ zzzzyyyy yyxxxxxx ZZZZYYYY YYXXXXXX ] + // want to write [ 1110zzzz ] [ 10yyyyyy ] [ 10xxxxxx ] [ 1110ZZZZ ] [ 10YYYYYY ] [ 10XXXXXX ] + + Unsafe.Add(ref outputBuffer, 5) = (byte)((value & 0x3Fu) | 0x80u); + Unsafe.Add(ref outputBuffer, 4) = (byte)(((value >>= 6) & 0x3Fu) | 0x80u); + Unsafe.Add(ref outputBuffer, 3) = (byte)(((value >>= 6) & 0x0Fu) | 0xE0u); + Unsafe.Add(ref outputBuffer, 2) = (byte)(((value >>= 4) & 0x3Fu) | 0x80u); + Unsafe.Add(ref outputBuffer, 1) = (byte)(((value >>= 6) & 0x3Fu) | 0x80u); + outputBuffer = (byte)((value >>= 6) | 0xE0u); + } + } + + + /// + /// Given a DWORD which represents a buffer of 2 packed UTF-16 values in machine endianess, + /// converts the first UTF-16 value to its 3-byte UTF-8 representation and writes the + /// resulting 3 bytes to the destination buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteFirstUtf16CharAsUtf8ThreeByteSequence(ref byte outputBuffer, uint value) + { + Debug.Assert(IsFirstCharAtLeastThreeUtf8Bytes(value) && !IsFirstCharSurrogate(value), "First half of value should've been 0800..D7FF or E000..FFFF"); + + if (BitConverter.IsLittleEndian) + { + // value = [ ######## ######## zzzzyyyy yyxxxxxx ] + // want to write [ 10yyyyyy 1110zzzz ] [ 10xxxxxx ] + + uint tempA = (value << 2) & 0x3F00u; // [ 00yyyyyy 00000000 ] + uint tempB = ((uint)(ushort)value >> 12); // [ 00000000 0000zzzz ] + Unsafe.WriteUnaligned(ref outputBuffer, (ushort)(tempA + tempB + 0x80E0u)); // [ 10yyyyyy 1110zzzz ] + Unsafe.Add(ref outputBuffer, 2) = (byte)((value & 0x3Fu) | ~0x7Fu); // [ 10xxxxxx ] + } + else + { + // value = [ zzzzyyyy yyxxxxxx ######## ######## ] + // want to write [ 1110zzzz ] [ 10yyyyyy ] [ 10xxxxxx ] + + Unsafe.Add(ref outputBuffer, 2) = (byte)(((value >>= 16) & 0x3Fu) | 0x80u); + Unsafe.Add(ref outputBuffer, 1) = (byte)(((value >>= 6) & 0x3Fu) | 0x80u); + outputBuffer = (byte)((value >>= 6) | 0xE0u); + } + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Transcoding.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Transcoding.cs new file mode 100644 index 000000000000..9536a77aea0d --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Transcoding.cs @@ -0,0 +1,1481 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Buffers; +using System.Buffers.Binary; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics.X86; +using Internal.Runtime.CompilerServices; + +#if BIT64 +using nint = System.Int64; +using nuint = System.UInt64; +#else // BIT64 +using nint = System.Int32; +using nuint = System.UInt32; +#endif // BIT64 + +namespace System.Text.Unicode +{ + internal static unsafe partial class Utf8Utility + { +#if DEBUG + static Utf8Utility() + { + Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); + Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); + + _ValidateAdditionalNIntDefinitions(); + } +#endif // DEBUG + + // On method return, pInputBufferRemaining and pOutputBufferRemaining will both point to where + // the next byte would have been consumed from / the next char would have been written to. + // inputLength in bytes, outputCharsRemaining in chars. + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + public static OperationStatus TranscodeToUtf16(byte* pInputBuffer, int inputLength, char* pOutputBuffer, int outputCharsRemaining, out byte* pInputBufferRemaining, out char* pOutputBufferRemaining) + { + Debug.Assert(inputLength >= 0, "Input length must not be negative."); + Debug.Assert(pInputBuffer != null || inputLength == 0, "Input length must be zero if input buffer pointer is null."); + + Debug.Assert(outputCharsRemaining >= 0, "Destination length must not be negative."); + Debug.Assert(pOutputBuffer != null || outputCharsRemaining == 0, "Destination length must be zero if destination buffer pointer is null."); + + // First, try vectorized conversion. + + { + nuint numElementsConverted = ASCIIUtility.WidenAsciiToUtf16(pInputBuffer, pOutputBuffer, (uint)Math.Min(inputLength, outputCharsRemaining)); + + pInputBuffer += numElementsConverted; + pOutputBuffer += numElementsConverted; + + // Quick check - did we just end up consuming the entire input buffer? + // If so, short-circuit the remainder of the method. + + if ((int)numElementsConverted == inputLength) + { + pInputBufferRemaining = pInputBuffer; + pOutputBufferRemaining = pOutputBuffer; + return OperationStatus.Done; + } + + inputLength -= (int)numElementsConverted; + outputCharsRemaining -= (int)numElementsConverted; + } + + if (inputLength < sizeof(uint)) + { + goto ProcessInputOfLessThanDWordSize; + } + + byte* pFinalPosWhereCanReadDWordFromInputBuffer = pInputBuffer + (uint)inputLength - 4; + + // Begin the main loop. + +#if DEBUG + byte* pLastBufferPosProcessed = null; // used for invariant checking in debug builds +#endif + + while (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + // Read 32 bits at a time. This is enough to hold any possible UTF8-encoded scalar. + + uint thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + AfterReadDWord: + +#if DEBUG + Debug.Assert(pLastBufferPosProcessed < pInputBuffer, "Algorithm should've made forward progress since last read."); + pLastBufferPosProcessed = pInputBuffer; +#endif + // First, check for the common case of all-ASCII bytes. + + if (ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)) + { + // We read an all-ASCII sequence. + + if (outputCharsRemaining < sizeof(uint)) + { + goto ProcessRemainingBytesSlow; // running out of space, but may be able to write some data + } + + Widen4AsciiBytesToCharsAndWrite(ref *pOutputBuffer, thisDWord); + pInputBuffer += 4; + pOutputBuffer += 4; + outputCharsRemaining -= 4; + + // If we saw a sequence of all ASCII, there's a good chance a significant amount of following data is also ASCII. + // Below is basically unrolled loops with poor man's vectorization. + + uint remainingInputBytes = (uint)(void*)Unsafe.ByteOffset(ref *pInputBuffer, ref *pFinalPosWhereCanReadDWordFromInputBuffer) + 4; + uint maxIters = Math.Min(remainingInputBytes, (uint)outputCharsRemaining) / (2 * sizeof(uint)); + uint secondDWord; + int i; + for (i = 0; (uint)i < maxIters; i++) + { + // Reading two DWORDs in parallel benchmarked faster than reading a single QWORD. + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + secondDWord = Unsafe.ReadUnaligned(pInputBuffer + sizeof(uint)); + + if (!ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord | secondDWord)) + { + goto LoopTerminatedEarlyDueToNonAsciiData; + } + + pInputBuffer += 8; + + Widen4AsciiBytesToCharsAndWrite(ref pOutputBuffer[0], thisDWord); + Widen4AsciiBytesToCharsAndWrite(ref pOutputBuffer[4], secondDWord); + + pOutputBuffer += 8; + } + + outputCharsRemaining -= 8 * i; + + continue; // need to perform a bounds check because we might be running out of data + + LoopTerminatedEarlyDueToNonAsciiData: + + if (ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)) + { + // The first DWORD contained all-ASCII bytes, so expand it. + + Widen4AsciiBytesToCharsAndWrite(ref *pOutputBuffer, thisDWord); + + // continue the outer loop from the second DWORD + + Debug.Assert(!ASCIIUtility.AllBytesInUInt32AreAscii(secondDWord)); + thisDWord = secondDWord; + + pInputBuffer += 4; + pOutputBuffer += 4; + outputCharsRemaining -= 4; + } + + outputCharsRemaining -= 8 * i; + + // We know that there's *at least* one DWORD of data remaining in the buffer. + // We also know that it's not all-ASCII. We can skip the logic at the beginning of the main loop. + + goto AfterReadDWordSkipAllBytesAsciiCheck; + } + + AfterReadDWordSkipAllBytesAsciiCheck: + + Debug.Assert(!ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)); // this should have been handled earlier + + // Next, try stripping off ASCII bytes one at a time. + // We only handle up to three ASCII bytes here since we handled the four ASCII byte case above. + + if (UInt32FirstByteIsAscii(thisDWord)) + { + if (outputCharsRemaining >= 3) + { + // Fast-track: we don't need to check the destination length for subsequent + // ASCII bytes since we know we can write them all now. + + uint thisDWordLittleEndian = ToLittleEndian(thisDWord); + + nuint adjustment = 1; + pOutputBuffer[0] = (char)(byte)thisDWordLittleEndian; + + if (UInt32SecondByteIsAscii(thisDWord)) + { + adjustment++; + thisDWordLittleEndian >>= 8; + pOutputBuffer[1] = (char)(byte)thisDWordLittleEndian; + + if (UInt32ThirdByteIsAscii(thisDWord)) + { + adjustment++; + thisDWordLittleEndian >>= 8; + pOutputBuffer[2] = (char)(byte)thisDWordLittleEndian; + } + } + + pInputBuffer += adjustment; + pOutputBuffer += adjustment; + outputCharsRemaining -= (int)adjustment; + } + else + { + // Slow-track: we need to make sure each individual write has enough + // of a buffer so that we don't overrun the destination. + + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; + } + + uint thisDWordLittleEndian = ToLittleEndian(thisDWord); + + pInputBuffer++; + *pOutputBuffer++ = (char)(byte)thisDWordLittleEndian; + outputCharsRemaining--; + + if (UInt32SecondByteIsAscii(thisDWord)) + { + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; + } + + pInputBuffer++; + thisDWordLittleEndian >>= 8; + *pOutputBuffer++ = (char)(byte)thisDWordLittleEndian; + + // We can perform a small optimization here. We know at this point that + // the output buffer is fully consumed (we read two ASCII bytes and wrote + // two ASCII chars, and we checked earlier that the destination buffer + // can't store a third byte). If the next byte is ASCII, we can jump straight + // to the return statement since the end-of-method logic only relies on the + // destination buffer pointer -- NOT the output chars remaining count -- being + // correct. If the next byte is not ASCII, we'll need to continue with the + // rest of the main loop, but we can set the buffer length directly to zero + // rather than decrementing it from 1 to 0. + + Debug.Assert(outputCharsRemaining == 1); + + if (UInt32ThirdByteIsAscii(thisDWord)) + { + goto OutputBufferTooSmall; + } + else + { + outputCharsRemaining = 0; + } + } + } + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessRemainingBytesSlow; // input buffer doesn't contain enough data to read a DWORD + } + else + { + // The input buffer at the current offset contains a non-ASCII byte. + // Read an entire DWORD and fall through to multi-byte consumption logic. + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + } + } + + BeforeProcessTwoByteSequence: + + // At this point, we know we're working with a multi-byte code unit, + // but we haven't yet validated it. + + // The masks and comparands are derived from the Unicode Standard, Table 3-6. + // Additionally, we need to check for valid byte sequences per Table 3-7. + + // Check the 2-byte case. + + if (UInt32BeginsWithUtf8TwoByteMask(thisDWord)) + { + // Per Table 3-7, valid sequences are: + // [ C2..DF ] [ 80..BF ] + + if (UInt32BeginsWithOverlongUtf8TwoByteSequence(thisDWord)) + { + goto Error; + } + + ProcessTwoByteSequenceSkipOverlongFormCheck: + + // Optimization: If this is a two-byte-per-character language like Cyrillic or Hebrew, + // there's a good chance that if we see one two-byte run then there's another two-byte + // run immediately after. Let's check that now. + + // On little-endian platforms, we can check for the two-byte UTF8 mask *and* validate that + // the value isn't overlong using a single comparison. On big-endian platforms, we'll need + // to validate the mask and validate that the sequence isn't overlong as two separate comparisons. + + if ((BitConverter.IsLittleEndian && UInt32EndsWithValidUtf8TwoByteSequenceLittleEndian(thisDWord)) + || (!BitConverter.IsLittleEndian && (UInt32EndsWithUtf8TwoByteMask(thisDWord) && !UInt32EndsWithOverlongUtf8TwoByteSequence(thisDWord)))) + { + // We have two runs of two bytes each. + + if (outputCharsRemaining < 2) + { + goto ProcessRemainingBytesSlow; // running out of output buffer + } + + Unsafe.WriteUnaligned(pOutputBuffer, ExtractTwoCharsPackedFromTwoAdjacentTwoByteSequences(thisDWord)); + + pInputBuffer += 4; + pOutputBuffer += 2; + outputCharsRemaining -= 2; + + if (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + // Optimization: If we read a long run of two-byte sequences, the next sequence is probably + // also two bytes. Check for that first before going back to the beginning of the loop. + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + if (BitConverter.IsLittleEndian) + { + if (UInt32BeginsWithValidUtf8TwoByteSequenceLittleEndian(thisDWord)) + { + // The next sequence is a valid two-byte sequence. + goto ProcessTwoByteSequenceSkipOverlongFormCheck; + } + } + else + { + if (UInt32BeginsWithUtf8TwoByteMask(thisDWord)) + { + if (UInt32BeginsWithOverlongUtf8TwoByteSequence(thisDWord)) + { + goto Error; // The next sequence purports to be a 2-byte sequence but is overlong. + } + + goto ProcessTwoByteSequenceSkipOverlongFormCheck; + } + } + + // If we reached this point, the next sequence is something other than a valid + // two-byte sequence, so go back to the beginning of the loop. + goto AfterReadDWord; + } + else + { + goto ProcessRemainingBytesSlow; // Running out of data - go down slow path + } + } + + // The buffer contains a 2-byte sequence followed by 2 bytes that aren't a 2-byte sequence. + // Unlikely that a 3-byte sequence would follow a 2-byte sequence, so perhaps remaining + // bytes are ASCII? + + uint charToWrite = ExtractCharFromFirstTwoByteSequence(thisDWord); // optimistically compute this now, but don't store until we know dest is large enough + + if (UInt32ThirdByteIsAscii(thisDWord)) + { + if (UInt32FourthByteIsAscii(thisDWord)) + { + if (outputCharsRemaining < 3) + { + goto ProcessRemainingBytesSlow; // running out of output buffer + } + + pOutputBuffer[0] = (char)charToWrite; + if (BitConverter.IsLittleEndian) + { + thisDWord >>= 16; + pOutputBuffer[1] = (char)(byte)thisDWord; + thisDWord >>= 8; + pOutputBuffer[2] = (char)thisDWord; + } + else + { + pOutputBuffer[2] = (char)(byte)thisDWord; + pOutputBuffer[1] = (char)(byte)(thisDWord >> 8); + } + pInputBuffer += 4; + pOutputBuffer += 3; + outputCharsRemaining -= 3; + + continue; // go back to original bounds check and check for ASCII + } + else + { + if (outputCharsRemaining < 2) + { + goto ProcessRemainingBytesSlow; // running out of output buffer + } + + pOutputBuffer[0] = (char)charToWrite; + pOutputBuffer[1] = (char)(byte)(thisDWord >> (BitConverter.IsLittleEndian ? 16 : 8)); + pInputBuffer += 3; + pOutputBuffer += 2; + outputCharsRemaining -= 2; + + // A two-byte sequence followed by an ASCII byte followed by a non-ASCII byte. + // Read in the next DWORD and jump directly to the start of the multi-byte processing block. + + if (pFinalPosWhereCanReadDWordFromInputBuffer < pInputBuffer) + { + goto ProcessRemainingBytesSlow; // Running out of data - go down slow path + } + else + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + goto BeforeProcessTwoByteSequence; + } + } + } + else + { + if (outputCharsRemaining == 0) + { + goto ProcessRemainingBytesSlow; // running out of output buffer + } + + pOutputBuffer[0] = (char)charToWrite; + pInputBuffer += 2; + pOutputBuffer += 1; + outputCharsRemaining--; + + if (pFinalPosWhereCanReadDWordFromInputBuffer < pInputBuffer) + { + goto ProcessRemainingBytesSlow; // Running out of data - go down slow path + } + else + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + goto BeforeProcessThreeByteSequence; // we know the next byte isn't ASCII, and it's not the start of a 2-byte sequence (this was checked above) + } + } + } + + // Check the 3-byte case. + + BeforeProcessThreeByteSequence: + + if (UInt32BeginsWithUtf8ThreeByteMask(thisDWord)) + { + ProcessThreeByteSequenceWithCheck: + + // We need to check for overlong or surrogate three-byte sequences. + // + // Per Table 3-7, valid sequences are: + // [ E0 ] [ A0..BF ] [ 80..BF ] + // [ E1..EC ] [ 80..BF ] [ 80..BF ] + // [ ED ] [ 80..9F ] [ 80..BF ] + // [ EE..EF ] [ 80..BF ] [ 80..BF ] + // + // Big-endian examples of using the above validation table: + // E0A0 = 1110 0000 1010 0000 => invalid (overlong ) patterns are 1110 0000 100# #### + // ED9F = 1110 1101 1001 1111 => invalid (surrogate) patterns are 1110 1101 101# #### + // If using the bitmask ......................................... 0000 1111 0010 0000 (=0F20), + // Then invalid (overlong) patterns match the comparand ......... 0000 0000 0000 0000 (=0000), + // And invalid (surrogate) patterns match the comparand ......... 0000 1101 0010 0000 (=0D20). + + if (BitConverter.IsLittleEndian) + { + // The "overlong or surrogate" check can be implemented using a single jump, but there's + // some overhead to moving the bits into the correct locations in order to perform the + // correct comparison, and in practice the processor's branch prediction capability is + // good enough that we shouldn't bother. So we'll use two jumps instead. + + // Can't extract this check into its own helper method because JITter produces suboptimal + // assembly, even with aggressive inlining. + + // Code below becomes 5 instructions: test, jz, lea, test, jz + + if (((thisDWord & 0x0000_200Fu) == 0) || (((thisDWord - 0x0000_200Du) & 0x0000_200Fu) == 0)) + { + goto Error; // overlong or surrogate + } + } + else + { + if (((thisDWord & 0x0F20_0000u) == 0) || (((thisDWord - 0x0D20_0000u) & 0x0F20_0000u) == 0)) + { + goto Error; // overlong or surrogate + } + } + + // At this point, we know the incoming scalar is well-formed. + + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; // not enough space in the destination buffer to write + } + + // As an optimization, on compatible platforms check if a second three-byte sequence immediately + // follows the one we just read, and if so use BSWAP and BMI2 to extract them together. + + if (Bmi2.X64.IsSupported) + { + Debug.Assert(BitConverter.IsLittleEndian, "BMI2 requires little-endian."); + + // First, check that the leftover byte from the original DWORD is in the range [ E0..EF ], which + // would indicate the potential start of a second three-byte sequence. + + if (((thisDWord - 0xE000_0000u) & 0xF000_0000u) == 0) + { + // The const '3' below is correct because pFinalPosWhereCanReadDWordFromInputBuffer represents + // the final place where we can safely perform a DWORD read, and we want to probe whether it's + // safe to read a DWORD beginning at address &pInputBuffer[3]. + + if (outputCharsRemaining > 1 && (nint)(void*)Unsafe.ByteOffset(ref *pInputBuffer, ref *pFinalPosWhereCanReadDWordFromInputBuffer) >= 3) + { + // We're going to attempt to read a second 3-byte sequence and write them both out simultaneously using PEXT. + // We need to check the continuation bit mask on the remaining two bytes (and we may as well check the leading + // byte mask again since it's free), then perform overlong + surrogate checks. If the overlong or surrogate + // checks fail, we'll fall through to the remainder of the logic which will transcode the original valid + // 3-byte UTF-8 sequence we read; and on the next iteration of the loop the validation routine will run again, + // fail, and redirect control flow to the error handling logic at the very end of this method. + + uint secondDWord = Unsafe.ReadUnaligned(pInputBuffer + 3); + + if (UInt32BeginsWithUtf8ThreeByteMask(secondDWord) + && ((secondDWord & 0x0000_200Fu) != 0) + && (((secondDWord - 0x0000_200Du) & 0x0000_200Fu) != 0)) + { + // combinedQWord = [ 1110ZZZZ 10YYYYYY 10XXXXXX ######## | 1110zzzz 10yyyyyy 10xxxxxx ######## ], where xyz are from first DWORD, XYZ are from second DWORD + ulong combinedQWord = ((ulong)BinaryPrimitives.ReverseEndianness(secondDWord) << 32) | BinaryPrimitives.ReverseEndianness(thisDWord); + thisDWord = secondDWord; // store this value in the correct local for the ASCII drain logic + + // extractedQWord = [ 00000000 00000000 00000000 00000000 | ZZZZYYYYYYXXXXXX zzzzyyyyyyxxxxxx ] + ulong extractedQWord = Bmi2.X64.ParallelBitExtract(combinedQWord, 0x0F3F3F00_0F3F3F00ul); + + Unsafe.WriteUnaligned(pOutputBuffer, (uint)extractedQWord); + pInputBuffer += 6; + pOutputBuffer += 2; + outputCharsRemaining -= 2; + + // Drain any ASCII data following the second three-byte sequence. + + goto CheckForAsciiByteAfterThreeByteSequence; + } + } + } + } + + // Couldn't extract 2x three-byte sequences together, just do this one by itself. + + *pOutputBuffer = (char)ExtractCharFromFirstThreeByteSequence(thisDWord); + pInputBuffer += 3; + pOutputBuffer += 1; + outputCharsRemaining -= 1; + + CheckForAsciiByteAfterThreeByteSequence: + + // Occasionally one-off ASCII characters like spaces, periods, or newlines will make their way + // in to the text. If this happens strip it off now before seeing if the next character + // consists of three code units. + + if (UInt32FourthByteIsAscii(thisDWord)) + { + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; + } + + if (BitConverter.IsLittleEndian) + { + *pOutputBuffer = (char)(thisDWord >> 24); + } + else + { + *pOutputBuffer = (char)(byte)thisDWord; + } + + pInputBuffer += 1; + pOutputBuffer += 1; + outputCharsRemaining -= 1; + } + + if (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + // Optimization: A three-byte character could indicate CJK text, which makes it likely + // that the character following this one is also CJK. We'll check for a three-byte sequence + // marker now and jump directly to three-byte sequence processing if we see one, skipping + // all of the logic at the beginning of the loop. + + if (UInt32BeginsWithUtf8ThreeByteMask(thisDWord)) + { + goto ProcessThreeByteSequenceWithCheck; // found a three-byte sequence marker; validate and consume + } + else + { + goto AfterReadDWord; // probably ASCII punctuation or whitespace + } + } + else + { + goto ProcessRemainingBytesSlow; // Running out of data - go down slow path + } + } + + // Assume the 4-byte case, but we need to validate. + + { + // We need to check for overlong or invalid (over U+10FFFF) four-byte sequences. + // + // Per Table 3-7, valid sequences are: + // [ F0 ] [ 90..BF ] [ 80..BF ] [ 80..BF ] + // [ F1..F3 ] [ 80..BF ] [ 80..BF ] [ 80..BF ] + // [ F4 ] [ 80..8F ] [ 80..BF ] [ 80..BF ] + + if (!UInt32BeginsWithUtf8FourByteMask(thisDWord)) + { + goto Error; + } + + // Now check for overlong / out-of-range sequences. + + if (BitConverter.IsLittleEndian) + { + // The DWORD we read is [ 10xxxxxx 10yyyyyy 10zzzzzz 11110www ]. + // We want to get the 'w' byte in front of the 'z' byte so that we can perform + // a single range comparison. We'll take advantage of the fact that the JITter + // can detect a ROR / ROL operation, then we'll just zero out the bytes that + // aren't involved in the range check. + + uint toCheck = thisDWord & 0x0000_FFFFu; + + // At this point, toCheck = [ 00000000 00000000 10zzzzzz 11110www ]. + + toCheck = BitOperations.RotateRight(toCheck, 8); + + // At this point, toCheck = [ 11110www 00000000 00000000 10zzzzzz ]. + + if (!UnicodeUtility.IsInRangeInclusive(toCheck, 0xF000_0090u, 0xF400_008Fu)) + { + goto Error; + } + } + else + { + if (!UnicodeUtility.IsInRangeInclusive(thisDWord, 0xF090_0000u, 0xF48F_FFFFu)) + { + goto Error; + } + } + + // Validation complete. + + if (outputCharsRemaining < 2) + { + // There's no point to falling back to the "drain the input buffer" logic, since we know + // we can't write anything to the destination. So we'll just exit immediately. + goto OutputBufferTooSmall; + } + + Unsafe.WriteUnaligned(pOutputBuffer, ExtractCharsFromFourByteSequence(thisDWord)); + + pInputBuffer += 4; + pOutputBuffer += 2; + outputCharsRemaining -= 2; + + continue; // go back to beginning of loop for processing + } + } + + ProcessRemainingBytesSlow: + inputLength = (int)(void*)Unsafe.ByteOffset(ref *pInputBuffer, ref *pFinalPosWhereCanReadDWordFromInputBuffer) + 4; + + ProcessInputOfLessThanDWordSize: + while (inputLength > 0) + { + uint firstByte = pInputBuffer[0]; + if (firstByte <= 0x7Fu) + { + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; // we have no hope of writing anything to the output + } + + // 1-byte (ASCII) case + *pOutputBuffer = (char)firstByte; + + pInputBuffer += 1; + pOutputBuffer += 1; + inputLength -= 1; + outputCharsRemaining -= 1; + continue; + } + + // Potentially the start of a multi-byte sequence? + + firstByte -= 0xC2u; + if ((byte)firstByte <= (0xDFu - 0xC2u)) + { + // Potentially a 2-byte sequence? + if (inputLength < 2) + { + goto InputBufferTooSmall; // out of data + } + + uint secondByte = pInputBuffer[1]; + if (!IsLowByteUtf8ContinuationByte(secondByte)) + { + goto Error; // 2-byte marker not followed by continuation byte + } + + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; // we have no hope of writing anything to the output + } + + uint asChar = (firstByte << 6) + secondByte + ((0xC2u - 0xC0u) << 6) - 0x80u; // remove UTF-8 markers from scalar + *pOutputBuffer = (char)asChar; + + pInputBuffer += 2; + pOutputBuffer += 1; + inputLength -= 2; + outputCharsRemaining -= 1; + continue; + } + else if ((byte)firstByte <= (0xEFu - 0xC2u)) + { + // Potentially a 3-byte sequence? + if (inputLength >= 3) + { + uint secondByte = pInputBuffer[1]; + uint thirdByte = pInputBuffer[2]; + if (!IsLowByteUtf8ContinuationByte(secondByte) || !IsLowByteUtf8ContinuationByte(thirdByte)) + { + goto Error; // 3-byte marker not followed by 2 continuation bytes + } + + // To speed up the validation logic below, we're not going to remove the UTF-8 markers from the partial char just yet. + // We account for this in the comparisons below. + + uint partialChar = (firstByte << 12) + (secondByte << 6); + if (partialChar < ((0xE0u - 0xC2u) << 12) + (0xA0u << 6)) + { + goto Error; // this is an overlong encoding; fail + } + + partialChar -= ((0xEDu - 0xC2u) << 12) + (0xA0u << 6); //if partialChar = 0, we're at beginning of UTF-16 surrogate code point range + if (partialChar < (0x0800u /* number of code points in UTF-16 surrogate code point range */)) + { + goto Error; // attempted to encode a UTF-16 surrogate code point; fail + } + + if (outputCharsRemaining == 0) + { + goto OutputBufferTooSmall; // we have no hope of writing anything to the output + } + + // Now restore the full scalar value. + + partialChar += thirdByte; + partialChar += 0xD800; // undo "move to beginning of UTF-16 surrogate code point range" from earlier, fold it with later adds + partialChar -= 0x80u; // remove third byte continuation marker + + *pOutputBuffer = (char)partialChar; + + pInputBuffer += 3; + pOutputBuffer += 1; + inputLength -= 3; + outputCharsRemaining -= 1; + continue; + } + else if (inputLength >= 2) + { + uint secondByte = pInputBuffer[1]; + if (!IsLowByteUtf8ContinuationByte(secondByte)) + { + goto Error; // 3-byte marker not followed by continuation byte + } + + // We can't build up the entire scalar value now, but we can check for overlong / surrogate representations + // from just the first two bytes. + + uint partialChar = (firstByte << 6) + secondByte; // don't worry about fixing up the UTF-8 markers; we'll account for it in the below comparison + if (partialChar < ((0xE0u - 0xC2u) << 6) + 0xA0u) + { + goto Error; // failed overlong check + } + if (UnicodeUtility.IsInRangeInclusive(partialChar, ((0xEDu - 0xC2u) << 6) + 0xA0u, ((0xEEu - 0xC2u) << 6) + 0x7Fu)) + { + goto Error; // failed surrogate check + } + } + + goto InputBufferTooSmall; // out of data + } + else if ((byte)firstByte <= (0xF4u - 0xC2u)) + { + // Potentially a 4-byte sequence? + + if (inputLength < 2) + { + goto InputBufferTooSmall; // ran out of data + } + + uint nextByte = pInputBuffer[1]; + if (!IsLowByteUtf8ContinuationByte(nextByte)) + { + goto Error; // 4-byte marker not followed by a continuation byte + } + + uint asPartialChar = (firstByte << 6) + nextByte; // don't worry about fixing up the UTF-8 markers; we'll account for it in the below comparison + if (!UnicodeUtility.IsInRangeInclusive(asPartialChar, ((0xF0u - 0xC2u) << 6) + 0x90u, ((0xF4u - 0xC2u) << 6) + 0x8Fu)) + { + goto Error; // failed overlong / out-of-range check + } + + if (inputLength < 3) + { + goto InputBufferTooSmall; // ran out of data + } + + if (!IsLowByteUtf8ContinuationByte(pInputBuffer[2])) + { + goto Error; // third byte in 4-byte sequence not a continuation byte + } + + if (inputLength < 4) + { + goto InputBufferTooSmall; // ran out of data + } + + if (!IsLowByteUtf8ContinuationByte(pInputBuffer[3])) + { + goto Error; // fourth byte in 4-byte sequence not a continuation byte + } + + // If we read a valid astral scalar value, the only way we could've fallen down this code path + // is that we didn't have enough output buffer to write the result. + + goto OutputBufferTooSmall; + } + else + { + goto Error; // didn't begin with [ C2 .. F4 ], so invalid multi-byte sequence header byte + } + } + + OperationStatus retVal = OperationStatus.Done; + goto ReturnCommon; + + InputBufferTooSmall: + retVal = OperationStatus.NeedMoreData; + goto ReturnCommon; + + OutputBufferTooSmall: + retVal = OperationStatus.DestinationTooSmall; + goto ReturnCommon; + + Error: + retVal = OperationStatus.InvalidData; + goto ReturnCommon; + + ReturnCommon: + pInputBufferRemaining = pInputBuffer; + pOutputBufferRemaining = pOutputBuffer; + return retVal; + } + + // On method return, pInputBufferRemaining and pOutputBufferRemaining will both point to where + // the next char would have been consumed from / the next byte would have been written to. + // inputLength in chars, outputBytesRemaining in bytes. + public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLength, byte* pOutputBuffer, int outputBytesRemaining, out char* pInputBufferRemaining, out byte* pOutputBufferRemaining) + { + const int CharsPerDWord = sizeof(uint) / sizeof(char); + + Debug.Assert(inputLength >= 0, "Input length must not be negative."); + Debug.Assert(pInputBuffer != null || inputLength == 0, "Input length must be zero if input buffer pointer is null."); + + Debug.Assert(outputBytesRemaining >= 0, "Destination length must not be negative."); + Debug.Assert(pOutputBuffer != null || outputBytesRemaining == 0, "Destination length must be zero if destination buffer pointer is null."); + + // First, try vectorized conversion. + + { + nuint numElementsConverted = ASCIIUtility.NarrowUtf16ToAscii(pInputBuffer, pOutputBuffer, (uint)Math.Min(inputLength, outputBytesRemaining)); + + pInputBuffer += numElementsConverted; + pOutputBuffer += numElementsConverted; + + // Quick check - did we just end up consuming the entire input buffer? + // If so, short-circuit the remainder of the method. + + if ((int)numElementsConverted == inputLength) + { + pInputBufferRemaining = pInputBuffer; + pOutputBufferRemaining = pOutputBuffer; + return OperationStatus.Done; + } + + inputLength -= (int)numElementsConverted; + outputBytesRemaining -= (int)numElementsConverted; + } + + if (inputLength < CharsPerDWord) + { + goto ProcessInputOfLessThanDWordSize; + } + + char* pFinalPosWhereCanReadDWordFromInputBuffer = pInputBuffer + (uint)inputLength - CharsPerDWord; + + // Begin the main loop. + +#if DEBUG + char* pLastBufferPosProcessed = null; // used for invariant checking in debug builds +#endif + + uint thisDWord; + + while (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + // Read 32 bits at a time. This is enough to hold any possible UTF16-encoded scalar. + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + AfterReadDWord: + +#if DEBUG + Debug.Assert(pLastBufferPosProcessed < pInputBuffer, "Algorithm should've made forward progress since last read."); + pLastBufferPosProcessed = pInputBuffer; +#endif + + // First, check for the common case of all-ASCII chars. + + if (Utf16Utility.AllCharsInUInt32AreAscii(thisDWord)) + { + // We read an all-ASCII sequence (2 chars). + + if (outputBytesRemaining < 2) + { + goto ProcessOneCharFromCurrentDWordAndFinish; // running out of space, but may be able to write some data + } + + // The high WORD of the local declared below might be populated with garbage + // as a result of our shifts below, but that's ok since we're only going to + // write the low WORD. + // + // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] + // (Same logic works regardless of endianness.) + uint valueToWrite = thisDWord | (thisDWord >> 8); + + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)valueToWrite); + + pInputBuffer += 2; + pOutputBuffer += 2; + outputBytesRemaining -= 2; + + // If we saw a sequence of all ASCII, there's a good chance a significant amount of following data is also ASCII. + // Below is basically unrolled loops with poor man's vectorization. + + uint inputCharsRemaining = (uint)(pFinalPosWhereCanReadDWordFromInputBuffer - pInputBuffer) + 2; + uint minElementsRemaining = (uint)Math.Min(inputCharsRemaining, outputBytesRemaining); + + if (Bmi2.X64.IsSupported) + { + Debug.Assert(BitConverter.IsLittleEndian, "BMI2 requires little-endian."); + const ulong PEXT_MASK = 0x00FF00FF_00FF00FFul; + + // Try reading and writing 8 elements per iteration. + uint maxIters = minElementsRemaining / 8; + ulong firstQWord, secondQWord; + int i; + for (i = 0; (uint)i < maxIters; i++) + { + firstQWord = Unsafe.ReadUnaligned(pInputBuffer); + secondQWord = Unsafe.ReadUnaligned(pInputBuffer + 4); + + if (!Utf16Utility.AllCharsInUInt64AreAscii(firstQWord | secondQWord)) + { + goto LoopTerminatedDueToNonAsciiData; + } + + Unsafe.WriteUnaligned(pOutputBuffer, (uint)Bmi2.X64.ParallelBitExtract(firstQWord, PEXT_MASK)); + Unsafe.WriteUnaligned(pOutputBuffer + 4, (uint)Bmi2.X64.ParallelBitExtract(secondQWord, PEXT_MASK)); + + pInputBuffer += 8; + pOutputBuffer += 8; + } + + outputBytesRemaining -= 8 * i; + + // Can we perform one more iteration, but reading & writing 4 elements instead of 8? + + if ((minElementsRemaining & 4) != 0) + { + secondQWord = Unsafe.ReadUnaligned(pInputBuffer); + + if (!Utf16Utility.AllCharsInUInt64AreAscii(secondQWord)) + { + goto LoopTerminatedDueToNonAsciiDataInSecondQWord; + } + + Unsafe.WriteUnaligned(pOutputBuffer, (uint)Bmi2.X64.ParallelBitExtract(secondQWord, PEXT_MASK)); + + pInputBuffer += 4; + pOutputBuffer += 4; + outputBytesRemaining -= 4; + } + + continue; // Go back to beginning of main loop, read data, check for ASCII + + LoopTerminatedDueToNonAsciiData: + + outputBytesRemaining -= 8 * i; + + // First, see if we can drain any ASCII data from the first QWORD. + + if (Utf16Utility.AllCharsInUInt64AreAscii(firstQWord)) + { + Unsafe.WriteUnaligned(pOutputBuffer, (uint)Bmi2.X64.ParallelBitExtract(firstQWord, PEXT_MASK)); + pInputBuffer += 4; + pOutputBuffer += 4; + outputBytesRemaining -= 4; + } + else + { + secondQWord = firstQWord; + } + + LoopTerminatedDueToNonAsciiDataInSecondQWord: + + Debug.Assert(!Utf16Utility.AllCharsInUInt64AreAscii(secondQWord)); // this condition should've been checked earlier + + thisDWord = (uint)secondQWord; + if (Utf16Utility.AllCharsInUInt32AreAscii(thisDWord)) + { + // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); + pInputBuffer += 2; + pOutputBuffer += 2; + outputBytesRemaining -= 2; + thisDWord = (uint)(secondQWord >> 32); + } + + goto AfterReadDWordSkipAllCharsAsciiCheck; + } + else + { + // Can't use BMI2 x64, so we'll only read and write 4 elements per iteration. + uint maxIters = minElementsRemaining / 4; + uint secondDWord; + int i; + for (i = 0; (uint)i < maxIters; i++) + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + secondDWord = Unsafe.ReadUnaligned(pInputBuffer + 2); + + if (!Utf16Utility.AllCharsInUInt32AreAscii(thisDWord | secondDWord)) + { + goto LoopTerminatedDueToNonAsciiData; + } + + // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] + // (Same logic works regardless of endianness.) + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); + Unsafe.WriteUnaligned(pOutputBuffer + 2, (ushort)(secondDWord | (secondDWord >> 8))); + + pInputBuffer += 4; + pOutputBuffer += 4; + } + + outputBytesRemaining -= 4 * i; + + continue; // Go back to beginning of main loop, read data, check for ASCII + + LoopTerminatedDueToNonAsciiData: + + outputBytesRemaining -= 4 * i; + + // First, see if we can drain any ASCII data from the first DWORD. + + if (Utf16Utility.AllCharsInUInt32AreAscii(thisDWord)) + { + // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] + // (Same logic works regardless of endianness.) + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); + pInputBuffer += 2; + pOutputBuffer += 2; + outputBytesRemaining -= 2; + thisDWord = secondDWord; + } + + goto AfterReadDWordSkipAllCharsAsciiCheck; + } + } + + AfterReadDWordSkipAllCharsAsciiCheck: + + Debug.Assert(!Utf16Utility.AllCharsInUInt32AreAscii(thisDWord)); // this should have been handled earlier + + // Next, try stripping off the first ASCII char if it exists. + // We don't check for a second ASCII char since that should have been handled above. + + if (IsFirstCharAscii(thisDWord)) + { + if (outputBytesRemaining == 0) + { + goto OutputBufferTooSmall; + } + + if (BitConverter.IsLittleEndian) + { + pOutputBuffer[0] = (byte)thisDWord; // extract [ ## ## 00 AA ] + } + else + { + pOutputBuffer[0] = (byte)(thisDWord >> 24); // extract [ AA 00 ## ## ] + } + + pInputBuffer += 1; + pOutputBuffer += 1; + outputBytesRemaining -= 1; + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessNextCharAndFinish; // input buffer doesn't contain enough data to read a DWORD + } + else + { + // The input buffer at the current offset contains a non-ASCII char. + // Read an entire DWORD and fall through to non-ASCII consumption logic. + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + } + } + + // At this point, we know the first char in the buffer is non-ASCII, but we haven't yet validated it. + + if (!IsFirstCharAtLeastThreeUtf8Bytes(thisDWord)) + { + TryConsumeMultipleTwoByteSequences: + + // For certain text (Greek, Cyrillic, ...), 2-byte sequences tend to be clustered. We'll try transcoding them in + // a tight loop without falling back to the main loop. + + if (IsSecondCharTwoUtf8Bytes(thisDWord)) + { + // We have two runs of two bytes each. + + if (outputBytesRemaining < 4) + { + goto ProcessOneCharFromCurrentDWordAndFinish; // running out of output buffer + } + + Unsafe.WriteUnaligned(pOutputBuffer, ExtractTwoUtf8TwoByteSequencesFromTwoPackedUtf16Chars(thisDWord)); + + pInputBuffer += 2; + pOutputBuffer += 4; + outputBytesRemaining -= 4; + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessNextCharAndFinish; // Running out of data - go down slow path + } + else + { + // Optimization: If we read a long run of two-byte sequences, the next sequence is probably + // also two bytes. Check for that first before going back to the beginning of the loop. + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + if (IsFirstCharTwoUtf8Bytes(thisDWord)) + { + // Validated we have a two-byte sequence coming up + goto TryConsumeMultipleTwoByteSequences; + } + + // If we reached this point, the next sequence is something other than a valid + // two-byte sequence, so go back to the beginning of the loop. + goto AfterReadDWord; + } + } + + if (outputBytesRemaining < 2) + { + goto OutputBufferTooSmall; + } + + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)ExtractUtf8TwoByteSequenceFromFirstUtf16Char(thisDWord)); + + // The buffer contains a 2-byte sequence followed by 2 bytes that aren't a 2-byte sequence. + // Unlikely that a 3-byte sequence would follow a 2-byte sequence, so perhaps remaining + // char is ASCII? + + if (IsSecondCharAscii(thisDWord)) + { + if (outputBytesRemaining >= 3) + { + if (BitConverter.IsLittleEndian) + { + thisDWord >>= 16; + } + pOutputBuffer[2] = (byte)thisDWord; + + pInputBuffer += 2; + pOutputBuffer += 3; + outputBytesRemaining -= 3; + + continue; // go back to original bounds check and check for ASCII + } + else + { + pInputBuffer += 1; + pOutputBuffer += 2; + goto OutputBufferTooSmall; + } + } + else + { + pInputBuffer += 1; + pOutputBuffer += 2; + outputBytesRemaining -= 2; + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessNextCharAndFinish; // Running out of data - go down slow path + } + else + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + goto BeforeProcessThreeByteSequence; // we know the next byte isn't ASCII, and it's not the start of a 2-byte sequence (this was checked above) + } + } + } + + // Check the 3-byte case. + + BeforeProcessThreeByteSequence: + + if (!IsFirstCharSurrogate(thisDWord)) + { + // Optimization: A three-byte character could indicate CJK text, which makes it likely + // that the character following this one is also CJK. We'll perform the check now + // rather than jumping to the beginning of the main loop. + + if (IsSecondCharAtLeastThreeUtf8Bytes(thisDWord)) + { + if (!IsSecondCharSurrogate(thisDWord)) + { + if (outputBytesRemaining < 6) + { + goto ConsumeSingleThreeByteRun; // not enough space - try consuming as much as we can + } + + WriteTwoUtf16CharsAsTwoUtf8ThreeByteSequences(ref *pOutputBuffer, thisDWord); + + pInputBuffer += 2; + pOutputBuffer += 6; + outputBytesRemaining -= 6; + + // Try to remain in the 3-byte processing loop if at all possible. + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessNextCharAndFinish; // Running out of data - go down slow path + } + else + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + if (IsFirstCharAtLeastThreeUtf8Bytes(thisDWord)) + { + goto BeforeProcessThreeByteSequence; + } + else + { + // Fall back to standard processing loop since we don't know how to optimize this. + goto AfterReadDWord; + } + } + } + } + + ConsumeSingleThreeByteRun: + + if (outputBytesRemaining < 3) + { + goto OutputBufferTooSmall; + } + + WriteFirstUtf16CharAsUtf8ThreeByteSequence(ref *pOutputBuffer, thisDWord); + + pInputBuffer += 1; + pOutputBuffer += 3; + outputBytesRemaining -= 3; + + // Occasionally one-off ASCII characters like spaces, periods, or newlines will make their way + // in to the text. If this happens strip it off now before seeing if the next character + // consists of three code units. + + if (IsSecondCharAscii(thisDWord)) + { + if (outputBytesRemaining == 0) + { + goto OutputBufferTooSmall; + } + + if (BitConverter.IsLittleEndian) + { + *pOutputBuffer = (byte)(thisDWord >> 16); + } + else + { + *pOutputBuffer = (byte)(thisDWord); + } + + pInputBuffer += 1; + pOutputBuffer += 1; + outputBytesRemaining -= 1; + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessNextCharAndFinish; // Running out of data - go down slow path + } + else + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + if (IsFirstCharAtLeastThreeUtf8Bytes(thisDWord)) + { + goto BeforeProcessThreeByteSequence; + } + else + { + // Fall back to standard processing loop since we don't know how to optimize this. + goto AfterReadDWord; + } + } + } + + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessNextCharAndFinish; // Running out of data - go down slow path + } + else + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + goto AfterReadDWordSkipAllCharsAsciiCheck; // we just checked above that this value isn't ASCII + } + } + + // Four byte sequence processing + + if (IsWellFormedUtf16SurrogatePair(thisDWord)) + { + if (outputBytesRemaining < 4) + { + goto OutputBufferTooSmall; + } + + Unsafe.WriteUnaligned(pOutputBuffer, ExtractFourUtf8BytesFromSurrogatePair(thisDWord)); + + pInputBuffer += 2; + pOutputBuffer += 4; + outputBytesRemaining -= 4; + + continue; // go back to beginning of loop for processing + } + + goto Error; // an ill-formed surrogate sequence: high not followed by low, or low not preceded by high + } + + ProcessNextCharAndFinish: + inputLength = (int)(pFinalPosWhereCanReadDWordFromInputBuffer - pInputBuffer) + CharsPerDWord; + + ProcessInputOfLessThanDWordSize: + Debug.Assert(inputLength < CharsPerDWord); + + if (inputLength == 0) + { + goto InputBufferFullyConsumed; + } + + uint thisChar = *pInputBuffer; + goto ProcessFinalChar; + + ProcessOneCharFromCurrentDWordAndFinish: + if (BitConverter.IsLittleEndian) + { + thisChar = thisDWord & 0xFFFFu; // preserve only the first char + } + else + { + thisChar = thisDWord >> 16; // preserve only the first char + } + + ProcessFinalChar: + { + if (thisChar <= 0x7Fu) + { + if (outputBytesRemaining == 0) + { + goto OutputBufferTooSmall; // we have no hope of writing anything to the output + } + + // 1-byte (ASCII) case + *pOutputBuffer = (byte)thisChar; + + pInputBuffer += 1; + pOutputBuffer += 1; + } + else if (thisChar < 0x0800u) + { + if (outputBytesRemaining < 2) + { + goto OutputBufferTooSmall; // we have no hope of writing anything to the output + } + + // 2-byte case + pOutputBuffer[1] = (byte)((thisChar & 0x3Fu) | unchecked((uint)(sbyte)0x80)); // [ 10xxxxxx ] + pOutputBuffer[0] = (byte)((thisChar >> 6) | unchecked((uint)(sbyte)0xC0)); // [ 110yyyyy ] + + pInputBuffer += 1; + pOutputBuffer += 2; + } + else if (!UnicodeUtility.IsSurrogateCodePoint(thisChar)) + { + if (outputBytesRemaining < 3) + { + goto OutputBufferTooSmall; // we have no hope of writing anything to the output + } + + // 3-byte case + pOutputBuffer[2] = (byte)((thisChar & 0x3Fu) | unchecked((uint)(sbyte)0x80)); // [ 10xxxxxx ] + pOutputBuffer[1] = (byte)(((thisChar >> 6) & 0x3Fu) | unchecked((uint)(sbyte)0x80)); // [ 10yyyyyy ] + pOutputBuffer[0] = (byte)((thisChar >> 12) | unchecked((uint)(sbyte)0xE0)); // [ 1110zzzz ] + + pInputBuffer += 1; + pOutputBuffer += 3; + } + else if (thisChar <= 0xDBFFu) + { + // UTF-16 high surrogate code point with no trailing data, report incomplete input buffer + goto InputBufferTooSmall; + } + else + { + // UTF-16 low surrogate code point with no leading data, report error + goto Error; + } + } + + // There are two ways we can end up here. Either we were running low on input data, + // or we were running low on space in the destination buffer. If we're running low on + // input data (label targets ProcessInputOfLessThanDWordSize and ProcessNextCharAndFinish), + // then the inputLength value is guaranteed to be between 0 and 1, and we should return Done. + // If we're running low on destination buffer space (label target ProcessOneCharFromCurrentDWordAndFinish), + // then we didn't modify inputLength since entering the main loop, which means it should + // still have a value of >= 2. So checking the value of inputLength is all we need to do to determine + // which of the two scenarios we're in. + + if (inputLength > 1) + { + goto OutputBufferTooSmall; + } + + InputBufferFullyConsumed: + OperationStatus retVal = OperationStatus.Done; + goto ReturnCommon; + + InputBufferTooSmall: + retVal = OperationStatus.NeedMoreData; + goto ReturnCommon; + + OutputBufferTooSmall: + retVal = OperationStatus.DestinationTooSmall; + goto ReturnCommon; + + Error: + retVal = OperationStatus.InvalidData; + goto ReturnCommon; + + ReturnCommon: + pInputBufferRemaining = pInputBuffer; + pOutputBufferRemaining = pOutputBuffer; + return retVal; + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Validation.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Validation.cs new file mode 100644 index 000000000000..b36dbb09c70f --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.Validation.cs @@ -0,0 +1,738 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Diagnostics; +using System.Numerics; +using System.Runtime.Intrinsics.X86; +using Internal.Runtime.CompilerServices; + +#if BIT64 +using nint = System.Int64; +using nuint = System.UInt64; +#else // BIT64 +using nint = System.Int32; +using nuint = System.UInt32; +#endif // BIT64 + +namespace System.Text.Unicode +{ + internal static unsafe partial class Utf8Utility + { +#if DEBUG + private static void _ValidateAdditionalNIntDefinitions() + { + Debug.Assert(sizeof(nint) == IntPtr.Size && nint.MinValue < 0, "nint is defined incorrectly."); + Debug.Assert(sizeof(nuint) == IntPtr.Size && nuint.MinValue == 0, "nuint is defined incorrectly."); + } +#endif // DEBUG + + // Returns &inputBuffer[inputLength] if the input buffer is valid. + /// + /// Given an input buffer of byte length , + /// returns a pointer to where the first invalid data appears in . + /// + /// + /// Returns a pointer to the end of if the buffer is well-formed. + /// + public static byte* GetPointerToFirstInvalidByte(byte* pInputBuffer, int inputLength, out int utf16CodeUnitCountAdjustment, out int scalarCountAdjustment) + { + Debug.Assert(inputLength >= 0, "Input length must not be negative."); + Debug.Assert(pInputBuffer != null || inputLength == 0, "Input length must be zero if input buffer pointer is null."); + + // First, try to drain off as many ASCII bytes as we can from the beginning. + + { + nuint numAsciiBytesCounted = ASCIIUtility.GetIndexOfFirstNonAsciiByte(pInputBuffer, (uint)inputLength); + pInputBuffer += numAsciiBytesCounted; + + // Quick check - did we just end up consuming the entire input buffer? + // If so, short-circuit the remainder of the method. + + inputLength -= (int)numAsciiBytesCounted; + if (inputLength == 0) + { + utf16CodeUnitCountAdjustment = 0; + scalarCountAdjustment = 0; + return pInputBuffer; + } + } + +#if DEBUG + // Keep these around for final validation at the end of the method. + byte* pOriginalInputBuffer = pInputBuffer; + int originalInputLength = inputLength; +#endif + + // Enregistered locals that we'll eventually out to our caller. + + int tempUtf16CodeUnitCountAdjustment = 0; + int tempScalarCountAdjustment = 0; + + if (inputLength < sizeof(uint)) + { + goto ProcessInputOfLessThanDWordSize; + } + + byte* pFinalPosWhereCanReadDWordFromInputBuffer = pInputBuffer + (uint)inputLength - sizeof(uint); + + // Begin the main loop. + +#if DEBUG + byte* pLastBufferPosProcessed = null; // used for invariant checking in debug builds +#endif + + while (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + // Read 32 bits at a time. This is enough to hold any possible UTF8-encoded scalar. + + uint thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + AfterReadDWord: + +#if DEBUG + Debug.Assert(pLastBufferPosProcessed < pInputBuffer, "Algorithm should've made forward progress since last read."); + pLastBufferPosProcessed = pInputBuffer; +#endif + + // First, check for the common case of all-ASCII bytes. + + if (ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)) + { + // We read an all-ASCII sequence. + + pInputBuffer += sizeof(uint); + + // If we saw a sequence of all ASCII, there's a good chance a significant amount of following data is also ASCII. + // Below is basically unrolled loops with poor man's vectorization. + + // Below check is "can I read at least five DWORDs from the input stream?" + // n.b. Since we incremented pInputBuffer above the below subtraction may result in a negative value, + // hence using nint instead of nuint. + + if ((nint)(void*)Unsafe.ByteOffset(ref *pInputBuffer, ref *pFinalPosWhereCanReadDWordFromInputBuffer) >= 4 * sizeof(uint)) + { + // We want reads in the inner loop to be aligned. So let's perform a quick + // ASCII check of the next 32 bits (4 bytes) now, and if that succeeds bump + // the read pointer up to the next aligned address. + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + if (!ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)) + { + goto AfterReadDWordSkipAllBytesAsciiCheck; + } + + pInputBuffer = (byte*)((nuint)(pInputBuffer + 4) & ~(nuint)3); + + // At this point, the input buffer offset points to an aligned DWORD. We also know that there's + // enough room to read at least four DWORDs from the buffer. (Heed the comment a few lines above: + // the original 'if' check confirmed that there were 5 DWORDs before the alignment check, and + // the alignment check consumes at most a single DWORD.) + + byte* pInputBufferFinalPosAtWhichCanSafelyLoop = pFinalPosWhereCanReadDWordFromInputBuffer - 3 * sizeof(uint); // can safely read 4 DWORDs here + uint mask; + + do + { + if (Sse2.IsSupported && Bmi1.IsSupported) + { + // pInputBuffer is 32-bit aligned but not necessary 128-bit aligned, so we're + // going to perform an unaligned load. We don't necessarily care about aligning + // this because we pessimistically assume we'll encounter non-ASCII data at some + // point in the not-too-distant future (otherwise we would've stayed entirely + // within the all-ASCII vectorized code at the entry to this method). + + mask = (uint)Sse2.MoveMask(Sse2.LoadVector128((byte*)pInputBuffer)); + if (mask != 0) + { + goto Sse2LoopTerminatedEarlyDueToNonAsciiData; + } + } + else + { + if (!ASCIIUtility.AllBytesInUInt32AreAscii(((uint*)pInputBuffer)[0] | ((uint*)pInputBuffer)[1])) + { + goto LoopTerminatedEarlyDueToNonAsciiDataInFirstPair; + } + + if (!ASCIIUtility.AllBytesInUInt32AreAscii(((uint*)pInputBuffer)[2] | ((uint*)pInputBuffer)[3])) + { + goto LoopTerminatedEarlyDueToNonAsciiDataInSecondPair; + } + } + + pInputBuffer += 4 * sizeof(uint); // consumed 4 DWORDs + } while (pInputBuffer <= pInputBufferFinalPosAtWhichCanSafelyLoop); + + continue; // need to perform a bounds check because we might be running out of data + + Sse2LoopTerminatedEarlyDueToNonAsciiData: + + Debug.Assert(BitConverter.IsLittleEndian); + Debug.Assert(Sse2.IsSupported); + Debug.Assert(Bmi1.IsSupported); + + // The 'mask' value will have a 0 bit for each ASCII byte we saw and a 1 bit + // for each non-ASCII byte we saw. We can count the number of ASCII bytes, + // bump our input counter by that amount, and resume processing from the + // "the first byte is no longer ASCII" portion of the main loop. + + Debug.Assert(mask != 0); + + pInputBuffer += Bmi1.TrailingZeroCount(mask); + if (pInputBuffer > pFinalPosWhereCanReadDWordFromInputBuffer) + { + goto ProcessRemainingBytesSlow; + } + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); // no longer guaranteed to be aligned + goto BeforeProcessTwoByteSequence; + + LoopTerminatedEarlyDueToNonAsciiDataInSecondPair: + + pInputBuffer += 2 * sizeof(uint); // consumed 2 DWORDs + + LoopTerminatedEarlyDueToNonAsciiDataInFirstPair: + + // We know that there's *at least* two DWORDs of data remaining in the buffer. + // We also know that one of them (or both of them) contains non-ASCII data somewhere. + // Let's perform a quick check here to bypass the logic at the beginning of the main loop. + + thisDWord = *(uint*)pInputBuffer; // still aligned here + if (ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)) + { + pInputBuffer += sizeof(uint); // consumed 1 more DWORD + thisDWord = *(uint*)pInputBuffer; // still aligned here + } + + goto AfterReadDWordSkipAllBytesAsciiCheck; + } + + continue; // not enough data remaining to unroll loop - go back to beginning with bounds checks + } + + AfterReadDWordSkipAllBytesAsciiCheck: + + Debug.Assert(!ASCIIUtility.AllBytesInUInt32AreAscii(thisDWord)); // this should have been handled earlier + + // Next, try stripping off ASCII bytes one at a time. + // We only handle up to three ASCII bytes here since we handled the four ASCII byte case above. + + { + uint numLeadingAsciiBytes = ASCIIUtility.CountNumberOfLeadingAsciiBytesFromUInt32WithSomeNonAsciiData(thisDWord); + pInputBuffer += numLeadingAsciiBytes; + + if (pFinalPosWhereCanReadDWordFromInputBuffer < pInputBuffer) + { + goto ProcessRemainingBytesSlow; // Input buffer doesn't contain enough data to read a DWORD + } + else + { + // The input buffer at the current offset contains a non-ASCII byte. + // Read an entire DWORD and fall through to multi-byte consumption logic. + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + } + } + + BeforeProcessTwoByteSequence: + + // At this point, we suspect we're working with a multi-byte code unit sequence, + // but we haven't yet validated it for well-formedness. + + // The masks and comparands are derived from the Unicode Standard, Table 3-6. + // Additionally, we need to check for valid byte sequences per Table 3-7. + + // Check the 2-byte case. + + thisDWord -= (BitConverter.IsLittleEndian) ? 0x0000_80C0u : 0xC080_0000u; + if ((thisDWord & (BitConverter.IsLittleEndian ? 0x0000_C0E0u : 0xE0C0_0000u)) == 0) + { + // Per Table 3-7, valid sequences are: + // [ C2..DF ] [ 80..BF ] + // + // Due to our modification of 'thisDWord' above, this becomes: + // [ 02..1F ] [ 00..3F ] + // + // We've already checked that the leading byte was originally in the range [ C0..DF ] + // and that the trailing byte was originally in the range [ 80..BF ], so now we only need + // to check that the modified leading byte is >= [ 02 ]. + + if ((BitConverter.IsLittleEndian && (byte)thisDWord < 0x02u) + || (!BitConverter.IsLittleEndian && thisDWord < 0x0200_0000u)) + { + goto Error; // overlong form - leading byte was [ C0 ] or [ C1 ] + } + + ProcessTwoByteSequenceSkipOverlongFormCheck: + + // Optimization: If this is a two-byte-per-character language like Cyrillic or Hebrew, + // there's a good chance that if we see one two-byte run then there's another two-byte + // run immediately after. Let's check that now. + + // On little-endian platforms, we can check for the two-byte UTF8 mask *and* validate that + // the value isn't overlong using a single comparison. On big-endian platforms, we'll need + // to validate the mask and validate that the sequence isn't overlong as two separate comparisons. + + if ((BitConverter.IsLittleEndian && UInt32EndsWithValidUtf8TwoByteSequenceLittleEndian(thisDWord)) + || (!BitConverter.IsLittleEndian && (UInt32EndsWithUtf8TwoByteMask(thisDWord) && !UInt32EndsWithOverlongUtf8TwoByteSequence(thisDWord)))) + { + // We have two runs of two bytes each. + pInputBuffer += 4; + tempUtf16CodeUnitCountAdjustment -= 2; // 4 UTF-8 code units -> 2 UTF-16 code units (and 2 scalars) + + if (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + // Optimization: If we read a long run of two-byte sequences, the next sequence is probably + // also two bytes. Check for that first before going back to the beginning of the loop. + + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + if (BitConverter.IsLittleEndian) + { + if (UInt32BeginsWithValidUtf8TwoByteSequenceLittleEndian(thisDWord)) + { + // The next sequence is a valid two-byte sequence. + goto ProcessTwoByteSequenceSkipOverlongFormCheck; + } + } + else + { + if (UInt32BeginsWithUtf8TwoByteMask(thisDWord)) + { + if (UInt32BeginsWithOverlongUtf8TwoByteSequence(thisDWord)) + { + goto Error; // The next sequence purports to be a 2-byte sequence but is overlong. + } + + goto ProcessTwoByteSequenceSkipOverlongFormCheck; + } + } + + // If we reached this point, the next sequence is something other than a valid + // two-byte sequence, so go back to the beginning of the loop. + goto AfterReadDWord; + } + else + { + goto ProcessRemainingBytesSlow; // Running out of data - go down slow path + } + } + + // The buffer contains a 2-byte sequence followed by 2 bytes that aren't a 2-byte sequence. + // Unlikely that a 3-byte sequence would follow a 2-byte sequence, so perhaps remaining + // bytes are ASCII? + + tempUtf16CodeUnitCountAdjustment--; // 2-byte sequence + (some number of ASCII bytes) -> 1 UTF-16 code units (and 1 scalar) [+ trailing] + + if (UInt32ThirdByteIsAscii(thisDWord)) + { + if (UInt32FourthByteIsAscii(thisDWord)) + { + pInputBuffer += 4; + } + else + { + pInputBuffer += 3; + + // A two-byte sequence followed by an ASCII byte followed by a non-ASCII byte. + // Read in the next DWORD and jump directly to the start of the multi-byte processing block. + + if (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + goto BeforeProcessTwoByteSequence; + } + } + } + else + { + pInputBuffer += 2; + } + + continue; + } + + // Check the 3-byte case. + // We need to restore the C0 leading byte we stripped out earlier, then we can strip out the expected E0 byte. + + thisDWord -= (BitConverter.IsLittleEndian) ? (0x0080_00E0u - 0x0000_00C0u) : (0xE000_8000u - 0xC000_0000u); + if ((thisDWord & (BitConverter.IsLittleEndian ? 0x00C0_C0F0u : 0xF0C0_C000u)) == 0) + { + ProcessThreeByteSequenceWithCheck: + + // We assume the caller has confirmed that the bit pattern is representative of a three-byte + // sequence, but it may still be overlong or surrogate. We need to check for these possibilities. + // + // Per Table 3-7, valid sequences are: + // [ E0 ] [ A0..BF ] [ 80..BF ] + // [ E1..EC ] [ 80..BF ] [ 80..BF ] + // [ ED ] [ 80..9F ] [ 80..BF ] + // [ EE..EF ] [ 80..BF ] [ 80..BF ] + // + // Big-endian examples of using the above validation table: + // E0A0 = 1110 0000 1010 0000 => invalid (overlong ) patterns are 1110 0000 100# #### + // ED9F = 1110 1101 1001 1111 => invalid (surrogate) patterns are 1110 1101 101# #### + // If using the bitmask ......................................... 0000 1111 0010 0000 (=0F20), + // Then invalid (overlong) patterns match the comparand ......... 0000 0000 0000 0000 (=0000), + // And invalid (surrogate) patterns match the comparand ......... 0000 1101 0010 0000 (=0D20). + // + // It's ok if the caller has manipulated 'thisDWord' (e.g., by subtracting 0xE0 or 0x80) + // as long as they haven't touched the bits we're about to use in our mask checking below. + + if (BitConverter.IsLittleEndian) + { + // The "overlong or surrogate" check can be implemented using a single jump, but there's + // some overhead to moving the bits into the correct locations in order to perform the + // correct comparison, and in practice the processor's branch prediction capability is + // good enough that we shouldn't bother. So we'll use two jumps instead. + + // Can't extract this check into its own helper method because JITter produces suboptimal + // assembly, even with aggressive inlining. + + // Code below becomes 5 instructions: test, jz, add, test, jz + + if (((thisDWord & 0x0000_200Fu) == 0) || (((thisDWord -= 0x0000_200Du) & 0x0000_200Fu) == 0)) + { + goto Error; // overlong or surrogate + } + } + else + { + if (((thisDWord & 0x0F20_0000u) == 0) || (((thisDWord -= 0x0D20_0000u) & 0x0F20_0000u) == 0)) + { + goto Error; // overlong or surrogate + } + } + + ProcessSingleThreeByteSequenceSkipOverlongAndSurrogateChecks: + + // Occasionally one-off ASCII characters like spaces, periods, or newlines will make their way + // in to the text. If this happens strip it off now before seeing if the next character + // consists of three code units. + + // Branchless: consume a 3-byte UTF-8 sequence and optionally an extra ASCII byte hanging off the end + + nint asciiAdjustment; + if (BitConverter.IsLittleEndian) + { + asciiAdjustment = (int)thisDWord >> 31; // smear most significant bit across entire value + } + else + { + asciiAdjustment = (nint)(sbyte)thisDWord >> 7; // smear most significant bit of least significant byte across entire value + } + + // asciiAdjustment = 0 if fourth byte is ASCII; -1 otherwise + + // Please *DO NOT* reorder the below two lines. It provides extra defense in depth in case this method + // is ever changed such that pInputBuffer becomes a 'ref byte' instead of a simple 'byte*'. It's valid + // to add 4 before backing up since we already checked previously that the input buffer contains at + // least a DWORD's worth of data, so we're not going to run past the end of the buffer where the GC can + // no longer track the reference. However, we can't back up before adding 4, since we might back up to + // before the start of the buffer, and the GC isn't guaranteed to be able to track this. + + pInputBuffer += 4; // optimistically, assume consumed a 3-byte UTF-8 sequence plus an extra ASCII byte + pInputBuffer += asciiAdjustment; // back up if we didn't actually consume an ASCII byte + + tempUtf16CodeUnitCountAdjustment -= 2; // 3 (or 4) UTF-8 bytes -> 1 (or 2) UTF-16 code unit (and 1 [or 2] scalar) + + SuccessfullyProcessedThreeByteSequence: + + if (IntPtr.Size >= 8 && BitConverter.IsLittleEndian) + { + // x64 little-endian optimization: A three-byte character could indicate CJK text, + // which makes it likely that the character following this one is also CJK. + // We'll try to process several three-byte sequences at a time. + + // The check below is really "can we read 9 bytes from the input buffer?" since 'pFinalPos...' is already offset + // n.b. The subtraction below could result in a negative value (since we advanced pInputBuffer above), so + // use nint instead of nuint. + + if ((nint)(pFinalPosWhereCanReadDWordFromInputBuffer - pInputBuffer) >= 5) + { + ulong thisQWord = Unsafe.ReadUnaligned(pInputBuffer); + + // Stage the next 32 bits into 'thisDWord' so that it's ready for us in case we need to jump backward + // to a previous location in the loop. This offers defense against reading main memory again (which may + // have been modified and could lead to a race condition). + + thisDWord = (uint)thisQWord; + + // Is this three 3-byte sequences in a row? + // thisQWord = [ 10yyyyyy 1110zzzz | 10xxxxxx 10yyyyyy 1110zzzz | 10xxxxxx 10yyyyyy 1110zzzz ] [ 10xxxxxx ] + // ---- CHAR 3 ---- --------- CHAR 2 --------- --------- CHAR 1 --------- -CHAR 3- + if ((thisQWord & 0xC0F0_C0C0_F0C0_C0F0ul) == 0x80E0_8080_E080_80E0ul && IsUtf8ContinuationByte(in pInputBuffer[8])) + { + // Saw a proper bitmask for three incoming 3-byte sequences, perform the + // overlong and surrogate sequence checking now. + + // Check the first character. + // If the first character is overlong or a surrogate, fail immediately. + + if ((((uint)thisQWord & 0x200Fu) == 0) || ((((uint)thisQWord - 0x200Du) & 0x200Fu) == 0)) + { + goto Error; + } + + // Check the second character. + // At this point, we now know the first three bytes represent a well-formed sequence. + // If there's an error beyond here, we'll jump back to the "process three known good bytes" + // logic. + + thisQWord >>= 24; + if ((((uint)thisQWord & 0x200Fu) == 0) || ((((uint)thisQWord - 0x200Du) & 0x200Fu) == 0)) + { + goto ProcessSingleThreeByteSequenceSkipOverlongAndSurrogateChecks; + } + + // Check the third character (we already checked that it's followed by a continuation byte). + + thisQWord >>= 24; + if ((((uint)thisQWord & 0x200Fu) == 0) || ((((uint)thisQWord - 0x200Du) & 0x200Fu) == 0)) + { + goto ProcessSingleThreeByteSequenceSkipOverlongAndSurrogateChecks; + } + + pInputBuffer += 9; + tempUtf16CodeUnitCountAdjustment -= 6; // 9 UTF-8 bytes -> 3 UTF-16 code units (and 3 scalars) + + goto SuccessfullyProcessedThreeByteSequence; + } + + // Is this two 3-byte sequences in a row? + // thisQWord = [ ######## ######## | 10xxxxxx 10yyyyyy 1110zzzz | 10xxxxxx 10yyyyyy 1110zzzz ] + // --------- CHAR 2 --------- --------- CHAR 1 --------- + if ((thisQWord & 0xC0C0_F0C0_C0F0ul) == 0x8080_E080_80E0ul) + { + // Saw a proper bitmask for two incoming 3-byte sequences, perform the + // overlong and surrogate sequence checking now. + + // Check the first character. + // If the first character is overlong or a surrogate, fail immediately. + + if ((((uint)thisQWord & 0x200Fu) == 0) || ((((uint)thisQWord - 0x200Du) & 0x200Fu) == 0)) + { + goto Error; + } + + // Check the second character. + // At this point, we now know the first three bytes represent a well-formed sequence. + // If there's an error beyond here, we'll jump back to the "process three known good bytes" + // logic. + + thisQWord >>= 24; + if ((((uint)thisQWord & 0x200Fu) == 0) || ((((uint)thisQWord - 0x200Du) & 0x200Fu) == 0)) + { + goto ProcessSingleThreeByteSequenceSkipOverlongAndSurrogateChecks; + } + + pInputBuffer += 6; + tempUtf16CodeUnitCountAdjustment -= 4; // 6 UTF-8 bytes -> 2 UTF-16 code units (and 2 scalars) + + // The next byte in the sequence didn't have a 3-byte marker, so it's probably + // an ASCII character. Jump back to the beginning of loop processing. + + continue; + } + + if (UInt32BeginsWithUtf8ThreeByteMask(thisDWord)) + { + // A single three-byte sequence. + goto ProcessThreeByteSequenceWithCheck; + } + else + { + // Not a three-byte sequence; perhaps ASCII? + goto AfterReadDWord; + } + } + } + + if (pInputBuffer <= pFinalPosWhereCanReadDWordFromInputBuffer) + { + thisDWord = Unsafe.ReadUnaligned(pInputBuffer); + + // Optimization: A three-byte character could indicate CJK text, which makes it likely + // that the character following this one is also CJK. We'll check for a three-byte sequence + // marker now and jump directly to three-byte sequence processing if we see one, skipping + // all of the logic at the beginning of the loop. + + if (UInt32BeginsWithUtf8ThreeByteMask(thisDWord)) + { + goto ProcessThreeByteSequenceWithCheck; // Found another [not yet validated] three-byte sequence; process + } + else + { + goto AfterReadDWord; // Probably ASCII punctuation or whitespace; go back to start of loop + } + } + else + { + goto ProcessRemainingBytesSlow; // Running out of data + } + } + + // Assume the 4-byte case, but we need to validate. + + if (BitConverter.IsLittleEndian) + { + thisDWord &= 0xC0C0_FFFFu; + + // After the above modifications earlier in this method, we expect 'thisDWord' + // to have the structure [ 10000000 00000000 00uuzzzz 00010uuu ]. We'll now + // perform two checks to confirm this. The first will verify the + // [ 10000000 00000000 00###### ######## ] structure by taking advantage of two's + // complement representation to perform a single *signed* integer check. + + if ((int)thisDWord > unchecked((int)0x8000_3FFF)) + { + goto Error; // didn't have three trailing bytes + } + + // Now we want to confirm that 0x01 <= uuuuu (otherwise this is an overlong encoding) + // and that uuuuu <= 0x10 (otherwise this is an out-of-range encoding). + + thisDWord = BitOperations.RotateRight(thisDWord, 8); + + // Now, thisDWord = [ 00010uuu 10000000 00000000 00uuzzzz ]. + // The check is now a simple add / cmp / jcc combo. + + if (!UnicodeUtility.IsInRangeInclusive(thisDWord, 0x1080_0010u, 0x1480_000Fu)) + { + goto Error; // overlong or out-of-range + } + } + else + { + thisDWord -= 0x80u; + + // After the above modifications earlier in this method, we expect 'thisDWord' + // to have the structure [ 00010uuu 00uuzzzz 00yyyyyy 00xxxxxx ]. We'll now + // perform two checks to confirm this. The first will verify the + // [ ######## 00###### 00###### 00###### ] structure. + + if ((thisDWord & 0x00C0_C0C0u) != 0) + { + goto Error; // didn't have three trailing bytes + } + + // Now we want to confirm that 0x01 <= uuuuu (otherwise this is an overlong encoding) + // and that uuuuu <= 0x10 (otherwise this is an out-of-range encoding). + // This is a simple range check. (We don't care about the low two bytes.) + + if (!UnicodeUtility.IsInRangeInclusive(thisDWord, 0x1010_0000u, 0x140F_FFFFu)) + { + goto Error; // overlong or out-of-range + } + } + + // Validation of 4-byte case complete. + + pInputBuffer += 4; + tempUtf16CodeUnitCountAdjustment -= 2; // 4 UTF-8 bytes -> 2 UTF-16 code units + tempScalarCountAdjustment--; // 2 UTF-16 code units -> 1 scalar + + continue; // go back to beginning of loop for processing + } + + goto ProcessRemainingBytesSlow; + + ProcessInputOfLessThanDWordSize: + + Debug.Assert(inputLength < 4); + nuint inputBufferRemainingBytes = (uint)inputLength; + goto ProcessSmallBufferCommon; + + ProcessRemainingBytesSlow: + + inputBufferRemainingBytes = (nuint)(void*)Unsafe.ByteOffset(ref *pInputBuffer, ref *pFinalPosWhereCanReadDWordFromInputBuffer) + 4; + + ProcessSmallBufferCommon: + + Debug.Assert(inputBufferRemainingBytes < 4); + while (inputBufferRemainingBytes > 0) + { + uint firstByte = pInputBuffer[0]; + + if ((byte)firstByte < 0x80u) + { + // 1-byte (ASCII) case + pInputBuffer++; + inputBufferRemainingBytes--; + continue; + } + else if (inputBufferRemainingBytes >= 2) + { + uint secondByte = pInputBuffer[1]; // typed as 32-bit since we perform arithmetic (not just comparisons) on this value + if ((byte)firstByte < 0xE0u) + { + // 2-byte case + if ((byte)firstByte >= 0xC2u && IsLowByteUtf8ContinuationByte(secondByte)) + { + pInputBuffer += 2; + tempUtf16CodeUnitCountAdjustment--; // 2 UTF-8 bytes -> 1 UTF-16 code unit (and 1 scalar) + inputBufferRemainingBytes -= 2; + continue; + } + } + else if (inputBufferRemainingBytes >= 3) + { + if ((byte)firstByte < 0xF0u) + { + if ((byte)firstByte == 0xE0u) + { + if (!UnicodeUtility.IsInRangeInclusive(secondByte, 0xA0u, 0xBFu)) + { + goto Error; // overlong encoding + } + } + else if ((byte)firstByte == 0xEDu) + { + if (!UnicodeUtility.IsInRangeInclusive(secondByte, 0x80u, 0x9Fu)) + { + goto Error; // would be a UTF-16 surrogate code point + } + } + else + { + if (!IsLowByteUtf8ContinuationByte(secondByte)) + { + goto Error; // first trailing byte doesn't have proper continuation marker + } + } + + if (IsUtf8ContinuationByte(in pInputBuffer[2])) + { + pInputBuffer += 3; + tempUtf16CodeUnitCountAdjustment -= 2; // 3 UTF-8 bytes -> 2 UTF-16 code units (and 2 scalars) + inputBufferRemainingBytes -= 3; + continue; + } + } + } + } + + // Error - no match. + + goto Error; + } + + // If we reached this point, we're out of data, and we saw no bad UTF8 sequence. + +#if DEBUG + // Quick check that for the success case we're going to fulfill our contract of returning &inputBuffer[inputLength]. + Debug.Assert(pOriginalInputBuffer + originalInputLength == pInputBuffer, "About to return an unexpected value."); +#endif + + Error: + + // Report back to our caller how far we got before seeing invalid data. + // (Also used for normal termination when falling out of the loop above.) + + utf16CodeUnitCountAdjustment = tempUtf16CodeUnitCountAdjustment; + scalarCountAdjustment = tempScalarCountAdjustment; + return pInputBuffer; + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.cs b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.cs index 6ee9ca05a659..053c55efcfdd 100644 --- a/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.cs +++ b/src/System.Private.CoreLib/shared/System/Text/Unicode/Utf8Utility.cs @@ -2,14 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal.Runtime.CompilerServices; namespace System.Text.Unicode { - internal static class Utf8Utility + internal static partial class Utf8Utility { /// /// The maximum number of bytes that can result from UTF-8 transcoding @@ -29,26 +32,16 @@ internal static class Utf8Utility /// comes first) is ASCII. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetIndexOfFirstInvalidUtf8Sequence(ReadOnlySpan utf8Data, out bool isAscii) + public unsafe static int GetIndexOfFirstInvalidUtf8Sequence(ReadOnlySpan utf8Data, out bool isAscii) { - // TODO_UTF8STRING: Replace this with the faster drop-in replacement when it's available (coreclr #21948). - - bool tempIsAscii = true; - int originalDataLength = utf8Data.Length; - - while (!utf8Data.IsEmpty) + fixed (byte* pUtf8Data = &MemoryMarshal.GetReference(utf8Data)) { - if (Rune.DecodeFromUtf8(utf8Data, out Rune result, out int bytesConsumed) != OperationStatus.Done) - { - break; - } + byte* pFirstInvalidByte = GetPointerToFirstInvalidByte(pUtf8Data, utf8Data.Length, out int utf16CodeUnitCountAdjustment, out _); + int index = (int)(void*)Unsafe.ByteOffset(ref *pUtf8Data, ref *pFirstInvalidByte); - tempIsAscii &= result.IsAscii; - utf8Data = utf8Data.Slice(bytesConsumed); + isAscii = (utf16CodeUnitCountAdjustment == 0); // If UTF-16 char count == UTF-8 byte count, it's ASCII. + return (index < utf8Data.Length) ? index : -1; } - - isAscii = tempIsAscii; - return (utf8Data.IsEmpty) ? -1 : (originalDataLength - utf8Data.Length); } #if FEATURE_UTF8STRING @@ -58,7 +51,7 @@ public static int GetIndexOfFirstInvalidUtf8Sequence(ReadOnlySpan utf8Data /// but where all invalid UTF-8 sequences have been replaced /// with U+FFD. /// - public static Utf8String ValidateAndFixupUtf8String(Utf8String value) + public static Utf8String? ValidateAndFixupUtf8String(Utf8String? value) { if (Utf8String.IsNullOrEmpty(value)) { diff --git a/src/System.Private.CoreLib/shared/System/Text/UnicodeDebug.cs b/src/System.Private.CoreLib/shared/System/Text/UnicodeDebug.cs index dedfbe2254cb..be999212edf5 100644 --- a/src/System.Private.CoreLib/shared/System/Text/UnicodeDebug.cs +++ b/src/System.Private.CoreLib/shared/System/Text/UnicodeDebug.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs index 870962c6b677..a652033cddc5 100644 --- a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs +++ b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable // // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused. // @@ -116,7 +117,7 @@ public override unsafe int GetByteCount(char[] chars, int index, int count) public override unsafe int GetByteCount(string s) { // Validate input - if (s==null) + if (s == null) throw new ArgumentNullException(nameof(s)); fixed (char* pChars = s) @@ -150,10 +151,10 @@ public override unsafe int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { if (s == null || bytes == null) - throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array); + throw new ArgumentNullException(s == null ? nameof(s) : nameof(bytes), SR.ArgumentNull_Array); if (charIndex < 0 || charCount < 0) - throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum); + throw new ArgumentOutOfRangeException(charIndex < 0 ? nameof(charIndex) : nameof(charCount), SR.ArgumentOutOfRange_NeedNonNegNum); if (s.Length - charIndex < charCount) throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount); @@ -353,8 +354,7 @@ public override unsafe string GetString(byte[] bytes, int index, int count) // // End of standard methods copied from EncodingNLS.cs // - - internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) + internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS? encoder) { Debug.Assert(chars != null, "[UnicodeEncoding.GetByteCount]chars!=null"); Debug.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0"); @@ -375,7 +375,7 @@ internal sealed override unsafe int GetByteCount(char* chars, int count, Encoder bool wasHereBefore = false; // For fallback we may need a fallback buffer - EncoderFallbackBuffer fallbackBuffer = null; + EncoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; if (encoder != null) @@ -391,7 +391,7 @@ internal sealed override unsafe int GetByteCount(char* chars, int count, Encoder { fallbackBuffer = encoder.FallbackBuffer; if (fallbackBuffer.Remaining > 0) - throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType())); + throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback!.GetType())); // TODO-NULLABLE: NullReferenceException // Set our internal fallback interesting things. fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false); @@ -648,7 +648,7 @@ internal sealed override unsafe int GetByteCount(char* chars, int count, Encoder } internal sealed override unsafe int GetBytes( - char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) + char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS? encoder) { Debug.Assert(chars != null, "[UnicodeEncoding.GetBytes]chars!=null"); Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetBytes]byteCount >=0"); @@ -666,7 +666,7 @@ internal sealed override unsafe int GetBytes( char* charStart = chars; // For fallback we may need a fallback buffer - EncoderFallbackBuffer fallbackBuffer = null; + EncoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; // Get our encoder, but don't clear it yet. @@ -680,7 +680,7 @@ internal sealed override unsafe int GetBytes( // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary fallbackBuffer = encoder.FallbackBuffer; if (fallbackBuffer.Remaining > 0 && encoder._throwOnOverflow) - throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType())); + throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback!.GetType())); // TODO-NULLABLE: NullReferenceException // Set our internal fallback interesting things. fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false); @@ -1004,12 +1004,12 @@ internal sealed override unsafe int GetBytes( return (int)(bytes - byteStart); } - internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) + internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS? baseDecoder) { Debug.Assert(bytes != null, "[UnicodeEncoding.GetCharCount]bytes!=null"); Debug.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0"); - UnicodeEncoding.Decoder decoder = (UnicodeEncoding.Decoder)baseDecoder; + UnicodeEncoding.Decoder? decoder = (UnicodeEncoding.Decoder?)baseDecoder; byte* byteEnd = bytes + count; byte* byteStart = bytes; @@ -1022,7 +1022,7 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder int charCount = count >> 1; // For fallback we may need a fallback buffer - DecoderFallbackBuffer fallbackBuffer = null; + DecoderFallbackBuffer? fallbackBuffer = null; if (decoder != null) { @@ -1152,7 +1152,7 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder // Get fallback for previous high surrogate // Note we have to reconstruct bytes because some may have been in decoder - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1193,7 +1193,7 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder // Get fallback for this low surrogate // Note we have to reconstruct bytes because some may have been in decoder - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1232,7 +1232,7 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder charCount--; // fall back the high surrogate. - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1272,7 +1272,7 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder { // No hanging high surrogates allowed, do fallback and remove count for it charCount--; - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1332,14 +1332,14 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder } internal sealed override unsafe int GetChars( - byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) + byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS? baseDecoder) { Debug.Assert(chars != null, "[UnicodeEncoding.GetChars]chars!=null"); Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetChars]byteCount >=0"); Debug.Assert(charCount >= 0, "[UnicodeEncoding.GetChars]charCount >=0"); Debug.Assert(bytes != null, "[UnicodeEncoding.GetChars]bytes!=null"); - UnicodeEncoding.Decoder decoder = (UnicodeEncoding.Decoder)baseDecoder; + UnicodeEncoding.Decoder? decoder = (UnicodeEncoding.Decoder?)baseDecoder; // Need last vars int lastByte = -1; @@ -1358,7 +1358,7 @@ internal sealed override unsafe int GetChars( } // For fallback we may need a fallback buffer - DecoderFallbackBuffer fallbackBuffer = null; + DecoderFallbackBuffer? fallbackBuffer = null; char* charsForFallback; byte* byteEnd = bytes + byteCount; @@ -1477,7 +1477,7 @@ internal sealed override unsafe int GetChars( { // Get fallback for previous high surrogate // Note we have to reconstruct bytes because some may have been in decoder - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1529,7 +1529,7 @@ internal sealed override unsafe int GetChars( // Expected a previous high surrogate // Get fallback for this low surrogate // Note we have to reconstruct bytes because some may have been in decoder - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1591,7 +1591,7 @@ internal sealed override unsafe int GetChars( else if (lastChar > 0) { // Had a high surrogate, expected a low surrogate, fall back the high surrogate. - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1656,7 +1656,7 @@ internal sealed override unsafe int GetChars( if (lastChar > 0) { // No hanging high surrogates allowed, do fallback and remove count for it - byte[] byteBuffer = null; + byte[]? byteBuffer = null; if (bigEndian) { byteBuffer = new byte[] @@ -1840,7 +1840,7 @@ public override int GetMaxCharCount(int byteCount) } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is UnicodeEncoding that) { diff --git a/src/System.Private.CoreLib/shared/System/Text/UnicodeUtility.cs b/src/System.Private.CoreLib/shared/System/Text/UnicodeUtility.cs index 065c938d81e9..acd92473ca29 100644 --- a/src/System.Private.CoreLib/shared/System/Text/UnicodeUtility.cs +++ b/src/System.Private.CoreLib/shared/System/Text/UnicodeUtility.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System.Text diff --git a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs index 31f51ce53e1b..5c95e29f12cd 100644 --- a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -11,7 +12,7 @@ namespace System.Text { internal ref partial struct ValueStringBuilder { - private char[] _arrayToReturnToPool; + private char[]? _arrayToReturnToPool; private Span _chars; private int _pos; @@ -82,7 +83,9 @@ public ref char this[int index] } } +#pragma warning disable CS8609 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 public override string ToString() +#pragma warning restore CS8609 { var s = _chars.Slice(0, _pos).ToString(); Dispose(); @@ -277,7 +280,7 @@ private void Grow(int additionalCapacityBeyondPos) _chars.CopyTo(poolArray); - char[] toReturn = _arrayToReturnToPool; + char[]? toReturn = _arrayToReturnToPool; _chars = _arrayToReturnToPool = poolArray; if (toReturn != null) { @@ -288,7 +291,7 @@ private void Grow(int additionalCapacityBeyondPos) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - char[] toReturn = _arrayToReturnToPool; + char[]? toReturn = _arrayToReturnToPool; this = default; // for safety, to avoid using pooled array if this instance is erroneously appended to again if (toReturn != null) { diff --git a/src/System.Private.CoreLib/shared/System/ThreadAttributes.cs b/src/System.Private.CoreLib/shared/System/ThreadAttributes.cs index 624873610778..33dd50a6a7a7 100644 --- a/src/System.Private.CoreLib/shared/System/ThreadAttributes.cs +++ b/src/System.Private.CoreLib/shared/System/ThreadAttributes.cs @@ -8,6 +8,7 @@ ** =============================================================================*/ +#nullable enable namespace System { [AttributeUsage(AttributeTargets.Method)] diff --git a/src/System.Private.CoreLib/shared/System/ThreadStaticAttribute.cs b/src/System.Private.CoreLib/shared/System/ThreadStaticAttribute.cs index c12ac1c18da2..f237ad17e8d0 100644 --- a/src/System.Private.CoreLib/shared/System/ThreadStaticAttribute.cs +++ b/src/System.Private.CoreLib/shared/System/ThreadStaticAttribute.cs @@ -13,6 +13,7 @@ ** ===========================================================*/ +#nullable enable using System; namespace System diff --git a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs index 4b46ab31286c..fb9790d69bb8 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @@ -394,8 +394,8 @@ internal static void OnValuesChanged(ExecutionContext? previousExecutionCtx, Exe if (previousChangeNotifications != null && nextChangeNotifications != null) { // Notifications can't exist without values - Debug.Assert(previousExecutionCtx!.m_localValues != null); // TODO-NULLABLE: Compiler can't see that we're only here when this is non-null - Debug.Assert(nextExecutionCtx!.m_localValues != null); // TODO-NULLABLE: Compiler can't see that we're only here when this is non-null + Debug.Assert(previousExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 + Debug.Assert(nextExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 // Both contexts have change notifications, check previousExecutionCtx first foreach (IAsyncLocal local in previousChangeNotifications) { @@ -429,7 +429,7 @@ internal static void OnValuesChanged(ExecutionContext? previousExecutionCtx, Exe else if (previousChangeNotifications != null) { // Notifications can't exist without values - Debug.Assert(previousExecutionCtx!.m_localValues != null); // TODO-NULLABLE: Compiler can't see that we're only here when this is non-null + Debug.Assert(previousExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 // No current values, so just check previous against null foreach (IAsyncLocal local in previousChangeNotifications) { @@ -443,9 +443,9 @@ internal static void OnValuesChanged(ExecutionContext? previousExecutionCtx, Exe else // Implied: nextChangeNotifications != null { // Notifications can't exist without values - Debug.Assert(nextExecutionCtx!.m_localValues != null); // TODO-NULLABLE: Compiler can't see that we're only here when this is non-null + Debug.Assert(nextExecutionCtx!.m_localValues != null); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 // No previous values, so just check current against null - foreach (IAsyncLocal local in nextChangeNotifications!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34665 + foreach (IAsyncLocal local in nextChangeNotifications!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 { nextExecutionCtx.m_localValues.TryGetValue(local, out object? currentValue); if (currentValue != null) @@ -545,7 +545,7 @@ internal static void SetLocalValue(IAsyncLocal local, object? newValue, bool nee { int newNotificationIndex = newChangeNotifications.Length; Array.Resize(ref newChangeNotifications, newNotificationIndex + 1); - newChangeNotifications[newNotificationIndex] = local; + newChangeNotifications![newNotificationIndex] = local; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Thread.cs b/src/System.Private.CoreLib/shared/System/Threading/Thread.cs index 3a64d0164a63..183f5b206d4b 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Thread.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Thread.cs @@ -323,7 +323,7 @@ private static class LocalDataStore public static LocalDataStoreSlot AllocateSlot() { - return new LocalDataStoreSlot(new ThreadLocal()); + return new LocalDataStoreSlot(new ThreadLocal()); } private static Dictionary EnsureNameToSlotMap() diff --git a/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs index 4e6ff27e30eb..19c043da5ad6 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs @@ -34,7 +34,7 @@ internal static class ThreadPoolGlobals public static readonly ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue(); /// Shim used to invoke of the supplied . - internal static readonly Action s_invokeAsyncStateMachineBox = state => + internal static readonly Action s_invokeAsyncStateMachineBox = state => { if (!(state is IAsyncStateMachineBox box)) { @@ -709,8 +709,9 @@ public ThreadPoolWorkQueueThreadLocals(ThreadPoolWorkQueue tpq) currentThread = Thread.CurrentThread; } - private void CleanUp() + ~ThreadPoolWorkQueueThreadLocals() { + // Transfer any pending workitems into the global queue so that they will be executed by another thread if (null != workStealingQueue) { if (null != workQueue) @@ -726,17 +727,6 @@ private void CleanUp() ThreadPoolWorkQueue.WorkStealingQueueList.Remove(workStealingQueue); } } - - ~ThreadPoolWorkQueueThreadLocals() - { - // Since the purpose of calling CleanUp is to transfer any pending workitems into the global - // queue so that they will be executed by another thread, there's no point in doing this cleanup - // if we're in the process of shutting down or unloading the AD. In those cases, the work won't - // execute anyway. And there are subtle race conditions involved there that would lead us to do the wrong - // thing anyway. So we'll only clean up if this is a "normal" finalization. - if (!Environment.HasShutdownStarted) - CleanUp(); - } } public delegate void WaitCallback(object? state); @@ -752,8 +742,7 @@ internal abstract class QueueUserWorkItemCallbackBase : IThreadPoolWorkItem ~QueueUserWorkItemCallbackBase() { Debug.Assert( - executed != 0 || Environment.HasShutdownStarted, - "A QueueUserWorkItemCallback was never called!"); + executed != 0, "A QueueUserWorkItemCallback was never called!"); } #endif diff --git a/src/System.Private.CoreLib/shared/System/Threading/Timer.cs b/src/System.Private.CoreLib/shared/System/Threading/Timer.cs index 66d01ac81ae1..19bdac6f7ada 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Timer.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Timer.cs @@ -678,17 +678,6 @@ public TimerHolder(TimerQueueTimer timer) ~TimerHolder() { - // If shutdown has started, another thread may be suspended while holding the timer lock. - // So we can't safely close the timer. - // - // Similarly, we should not close the timer during AD-unload's live-object finalization phase. - // A rude abort may have prevented us from releasing the lock. - // - // Note that in either case, the Timer still won't fire, because ThreadPool threads won't be - // allowed to run anymore. - if (Environment.HasShutdownStarted) - return; - _timer.Close(); } diff --git a/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Portable.cs b/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Portable.cs index 808ccc958fd0..ed6e90f915d2 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Portable.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Portable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Diagnostics; @@ -56,7 +57,7 @@ private bool SetTimer(uint actualDuration) { if (!_isScheduled) { - List timers = s_scheduledTimers; + List? timers = s_scheduledTimers; if (timers == null) { timers = InitializeScheduledTimerManager_Locked(); @@ -80,11 +81,11 @@ private bool SetTimer(uint actualDuration) private static void TimerThread() { AutoResetEvent timerEvent = s_timerEvent; - List timersToFire = s_scheduledTimersToFire; + List timersToFire = s_scheduledTimersToFire!; List timers; lock (timerEvent) { - timers = s_scheduledTimers; + timers = s_scheduledTimers!; } int shortestWaitDurationMs = Timeout.Infinite; diff --git a/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.cs new file mode 100644 index 000000000000..5421b9f43bfe --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Runtime.InteropServices; + +namespace System.Threading +{ + internal partial class TimerQueue + { + private static int TickCount + { + get + { + // We need to keep our notion of time synchronized with the calls to SleepEx that drive + // the underlying native timer. In Win8, SleepEx does not count the time the machine spends + // sleeping/hibernating. Environment.TickCount (GetTickCount) *does* count that time, + // so we will get out of sync with SleepEx if we use that method. + // + // So, on Win8, we use QueryUnbiasedInterruptTime instead; this does not count time spent + // in sleep/hibernate mode. + if (Environment.IsWindows8OrAbove) + { + ulong time100ns; + + bool result = Interop.Kernel32.QueryUnbiasedInterruptTime(out time100ns); + if (!result) + Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error()); + + // convert to 100ns to milliseconds, and truncate to 32 bits. + return (int)(uint)(time100ns / 10000); + } + else + { + return Environment.TickCount; + } + } + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/ThrowHelper.cs b/src/System.Private.CoreLib/shared/System/ThrowHelper.cs index 4185382497bf..53919101d92e 100644 --- a/src/System.Private.CoreLib/shared/System/ThrowHelper.cs +++ b/src/System.Private.CoreLib/shared/System/ThrowHelper.cs @@ -35,6 +35,7 @@ // multiple times for different instantiation. // +#nullable enable using System.Buffers; using System.Collections.Generic; using System.Diagnostics; @@ -120,16 +121,16 @@ internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count() internal static void ThrowWrongKeyTypeArgumentException(T key, Type targetType) { // Generic key to move the boxing to the right hand side of throw - throw GetWrongKeyTypeArgumentException((object)key, targetType); + throw GetWrongKeyTypeArgumentException((object?)key, targetType); } internal static void ThrowWrongValueTypeArgumentException(T value, Type targetType) { // Generic key to move the boxing to the right hand side of throw - throw GetWrongValueTypeArgumentException((object)value, targetType); + throw GetWrongValueTypeArgumentException((object?)value, targetType); } - private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object key) + private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object? key) { return new ArgumentException(SR.Format(SR.Argument_AddingDuplicateWithKey, key)); } @@ -137,13 +138,13 @@ private static ArgumentException GetAddingDuplicateWithKeyArgumentException(obje internal static void ThrowAddingDuplicateWithKeyArgumentException(T key) { // Generic key to move the boxing to the right hand side of throw - throw GetAddingDuplicateWithKeyArgumentException((object)key); + throw GetAddingDuplicateWithKeyArgumentException((object?)key); } internal static void ThrowKeyNotFoundException(T key) { // Generic key to move the boxing to the right hand side of throw - throw GetKeyNotFoundException((object)key); + throw GetKeyNotFoundException((object?)key); } internal static void ThrowArgumentException(ExceptionResource resource) @@ -311,7 +312,7 @@ internal static void ThrowInvalidOperationException_HandleIsNotPinned() throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotPinned); } - internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array array, int offset, int count) + internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array? array, int offset, int count) { throw GetArraySegmentCtorValidationFailedException(array, offset, count); } @@ -331,7 +332,7 @@ internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit() throw new ArgumentOutOfRangeException("symbol", SR.Argument_BadFormatSpecifier); } - private static Exception GetArraySegmentCtorValidationFailedException(Array array, int offset, int count) + private static Exception GetArraySegmentCtorValidationFailedException(Array? array, int offset, int count) { if (array == null) return new ArgumentNullException(nameof(array)); @@ -354,17 +355,17 @@ private static InvalidOperationException GetInvalidOperationException(ExceptionR return new InvalidOperationException(GetResourceString(resource)); } - private static ArgumentException GetWrongKeyTypeArgumentException(object key, Type targetType) + private static ArgumentException GetWrongKeyTypeArgumentException(object? key, Type targetType) { return new ArgumentException(SR.Format(SR.Arg_WrongType, key, targetType), nameof(key)); } - private static ArgumentException GetWrongValueTypeArgumentException(object value, Type targetType) + private static ArgumentException GetWrongValueTypeArgumentException(object? value, Type targetType) { return new ArgumentException(SR.Format(SR.Arg_WrongType, value, targetType), nameof(value)); } - private static KeyNotFoundException GetKeyNotFoundException(object key) + private static KeyNotFoundException GetKeyNotFoundException(object? key) { return new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key)); } @@ -399,7 +400,7 @@ private static InvalidOperationException GetInvalidOperationException_EnumCurren internal static void IfNullAndNullsAreIllegalThenThrow(object value, ExceptionArgument argName) { // Note that default(T) is not equal to null for value types except when T is Nullable. - if (!(default(T) == null) && value == null) + if (!(default(T)! == null) && value == null) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 ThrowHelper.ThrowArgumentNullException(argName); } diff --git a/src/System.Private.CoreLib/shared/System/TimeSpan.cs b/src/System.Private.CoreLib/shared/System/TimeSpan.cs index dd532a20350a..2f5c4ed61c19 100644 --- a/src/System.Private.CoreLib/shared/System/TimeSpan.cs +++ b/src/System.Private.CoreLib/shared/System/TimeSpan.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Text; -using System; -using System.Runtime; -using System.Runtime.CompilerServices; +#nullable enable using System.Globalization; namespace System @@ -178,7 +175,7 @@ public static int Compare(TimeSpan t1, TimeSpan t2) } // Returns a value less than zero if this object - public int CompareTo(object value) + public int CompareTo(object? value) { if (value == null) return 1; if (!(value is TimeSpan)) @@ -209,7 +206,7 @@ public TimeSpan Duration() return new TimeSpan(_ticks >= 0 ? _ticks : -_ticks); } - public override bool Equals(object value) + public override bool Equals(object? value) { if (value is TimeSpan) { @@ -316,27 +313,27 @@ public static TimeSpan Parse(string s) /* Constructs a TimeSpan from a string. Leading and trailing white space characters are allowed. */ return TimeSpanParse.Parse(s, null); } - public static TimeSpan Parse(string input, IFormatProvider formatProvider) + public static TimeSpan Parse(string input, IFormatProvider? formatProvider) { if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); return TimeSpanParse.Parse(input, formatProvider); } - public static TimeSpan Parse(ReadOnlySpan input, IFormatProvider formatProvider = null) + public static TimeSpan Parse(ReadOnlySpan input, IFormatProvider? formatProvider = null) { return TimeSpanParse.Parse(input, formatProvider); } - public static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider) + public static TimeSpan ParseExact(string input, string format, IFormatProvider? formatProvider) { if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format); return TimeSpanParse.ParseExact(input, format, formatProvider, TimeSpanStyles.None); } - public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider formatProvider) + public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider? formatProvider) { if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None); } - public static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles) + public static TimeSpan ParseExact(string input, string format, IFormatProvider? formatProvider, TimeSpanStyles styles) { ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); @@ -344,23 +341,23 @@ public static TimeSpan ParseExact(string input, string format, IFormatProvider f return TimeSpanParse.ParseExact(input, format, formatProvider, styles); } - public static TimeSpan ParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider formatProvider, TimeSpanStyles styles = TimeSpanStyles.None) + public static TimeSpan ParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, TimeSpanStyles styles = TimeSpanStyles.None) { ValidateStyles(styles, nameof(styles)); return TimeSpanParse.ParseExact(input, format, formatProvider, styles); } - public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles) + public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles) { ValidateStyles(styles, nameof(styles)); if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input); return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles); } - public static TimeSpan ParseExact(ReadOnlySpan input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles = TimeSpanStyles.None) + public static TimeSpan ParseExact(ReadOnlySpan input, string[] formats, IFormatProvider? formatProvider, TimeSpanStyles styles = TimeSpanStyles.None) { ValidateStyles(styles, nameof(styles)); return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles); } - public static bool TryParse(string s, out TimeSpan result) + public static bool TryParse(string? s, out TimeSpan result) { if (s == null) { @@ -374,7 +371,7 @@ public static bool TryParse(ReadOnlySpan s, out TimeSpan result) return TimeSpanParse.TryParse(s, null, out result); } - public static bool TryParse(string input, IFormatProvider formatProvider, out TimeSpan result) + public static bool TryParse(string? input, IFormatProvider? formatProvider, out TimeSpan result) { if (input == null) { @@ -383,11 +380,11 @@ public static bool TryParse(string input, IFormatProvider formatProvider, out Ti } return TimeSpanParse.TryParse(input, formatProvider, out result); } - public static bool TryParse(ReadOnlySpan input, IFormatProvider formatProvider, out TimeSpan result) + public static bool TryParse(ReadOnlySpan input, IFormatProvider? formatProvider, out TimeSpan result) { return TimeSpanParse.TryParse(input, formatProvider, out result); } - public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, out TimeSpan result) + public static bool TryParseExact(string? input, string? format, IFormatProvider? formatProvider, out TimeSpan result) { if (input == null || format == null) { @@ -397,11 +394,11 @@ public static bool TryParseExact(string input, string format, IFormatProvider fo return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result); } - public static bool TryParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider formatProvider, out TimeSpan result) + public static bool TryParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, out TimeSpan result) { return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result); } - public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, out TimeSpan result) + public static bool TryParseExact(string? input, string?[]? formats, IFormatProvider? formatProvider, out TimeSpan result) { if (input == null) { @@ -410,12 +407,12 @@ public static bool TryParseExact(string input, string[] formats, IFormatProvider } return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result); } - public static bool TryParseExact(ReadOnlySpan input, string[] formats, IFormatProvider formatProvider, out TimeSpan result) + public static bool TryParseExact(ReadOnlySpan input, string?[]? formats, IFormatProvider? formatProvider, out TimeSpan result) { return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result); } - public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) + public static bool TryParseExact(string? input, string? format, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result) { ValidateStyles(styles, nameof(styles)); if (input == null || format == null) @@ -427,12 +424,12 @@ public static bool TryParseExact(string input, string format, IFormatProvider fo return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result); } - public static bool TryParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) + public static bool TryParseExact(ReadOnlySpan input, ReadOnlySpan format, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result) { ValidateStyles(styles, nameof(styles)); return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result); } - public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) + public static bool TryParseExact(string? input, string?[]? formats, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result) { ValidateStyles(styles, nameof(styles)); if (input == null) @@ -443,7 +440,7 @@ public static bool TryParseExact(string input, string[] formats, IFormatProvider return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result); } - public static bool TryParseExact(ReadOnlySpan input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) + public static bool TryParseExact(ReadOnlySpan input, string?[]? formats, IFormatProvider? formatProvider, TimeSpanStyles styles, out TimeSpan result) { ValidateStyles(styles, nameof(styles)); return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result); @@ -452,16 +449,16 @@ public override string ToString() { return TimeSpanFormat.FormatC(this); } - public string ToString(string format) + public string ToString(string? format) { return TimeSpanFormat.Format(this, format, null); } - public string ToString(string format, IFormatProvider formatProvider) + public string ToString(string? format, IFormatProvider? formatProvider) { return TimeSpanFormat.Format(this, format, formatProvider); } - public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider formatProvider = null) + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? formatProvider = null) { return TimeSpanFormat.TryFormat(this, destination, out charsWritten, format, formatProvider); } diff --git a/src/System.Private.CoreLib/shared/System/TimeZone.cs b/src/System.Private.CoreLib/shared/System/TimeZone.cs index 010db8090f4d..20d2b613ab93 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZone.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZone.cs @@ -18,6 +18,7 @@ ** ============================================================*/ +#nullable enable using System; using System.Text; using System.Threading; @@ -29,10 +30,10 @@ namespace System [Obsolete("System.TimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo instead.")] public abstract class TimeZone { - private static volatile TimeZone currentTimeZone = null; + private static volatile TimeZone? currentTimeZone = null; // Private object for locking instead of locking on a public type for SQL reliability work. - private static object s_InternalSyncObject; + private static object? s_InternalSyncObject; private static object InternalSyncObject { get @@ -40,9 +41,9 @@ private static object InternalSyncObject if (s_InternalSyncObject == null) { object o = new object(); - Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); + Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); } - return s_InternalSyncObject; + return s_InternalSyncObject!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -57,7 +58,7 @@ public static TimeZone CurrentTimeZone { //Grabbing the cached value is required at the top of this function so that //we don't incur a race condition with the ResetTimeZone method below. - TimeZone tz = currentTimeZone; + TimeZone? tz = currentTimeZone; if (tz == null) { lock (InternalSyncObject) diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs index aceb7b90fb46..7d046bdc1015 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.Serialization; namespace System @@ -9,7 +10,7 @@ namespace System public sealed partial class TimeZoneInfo { [Serializable] - public sealed class AdjustmentRule : IEquatable, ISerializable, IDeserializationCallback + public sealed class AdjustmentRule : IEquatable, ISerializable, IDeserializationCallback { private static readonly TimeSpan DaylightDeltaAdjustment = TimeSpan.FromHours(24.0); private static readonly TimeSpan MaxDaylightDelta = TimeSpan.FromHours(12.0); @@ -44,7 +45,7 @@ public sealed class AdjustmentRule : IEquatable, ISerializable, (DaylightTransitionStart != default && DaylightTransitionStart.TimeOfDay != DateTime.MinValue) || (DaylightTransitionEnd != default && DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1)); - public bool Equals(AdjustmentRule other) => + public bool Equals(AdjustmentRule? other) => other != null && _dateStart == other._dateStart && _dateEnd == other._dateEnd && @@ -248,13 +249,13 @@ private AdjustmentRule(SerializationInfo info, StreamingContext context) throw new ArgumentNullException(nameof(info)); } - _dateStart = (DateTime)info.GetValue("DateStart", typeof(DateTime)); // Do not rename (binary serialization) - _dateEnd = (DateTime)info.GetValue("DateEnd", typeof(DateTime)); // Do not rename (binary serialization) - _daylightDelta = (TimeSpan)info.GetValue("DaylightDelta", typeof(TimeSpan)); // Do not rename (binary serialization) - _daylightTransitionStart = (TransitionTime)info.GetValue("DaylightTransitionStart", typeof(TransitionTime)); // Do not rename (binary serialization) - _daylightTransitionEnd = (TransitionTime)info.GetValue("DaylightTransitionEnd", typeof(TransitionTime)); // Do not rename (binary serialization) + _dateStart = (DateTime)info.GetValue("DateStart", typeof(DateTime))!; // Do not rename (binary serialization) + _dateEnd = (DateTime)info.GetValue("DateEnd", typeof(DateTime))!; // Do not rename (binary serialization) + _daylightDelta = (TimeSpan)info.GetValue("DaylightDelta", typeof(TimeSpan))!; // Do not rename (binary serialization) + _daylightTransitionStart = (TransitionTime)info.GetValue("DaylightTransitionStart", typeof(TransitionTime))!; // Do not rename (binary serialization) + _daylightTransitionEnd = (TransitionTime)info.GetValue("DaylightTransitionEnd", typeof(TransitionTime))!; // Do not rename (binary serialization) - object o = info.GetValueNoThrow("BaseUtcOffsetDelta", typeof(TimeSpan)); // Do not rename (binary serialization) + object? o = info.GetValueNoThrow("BaseUtcOffsetDelta", typeof(TimeSpan)); // Do not rename (binary serialization) if (o != null) { _baseUtcOffsetDelta = (TimeSpan)o; diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs index a0b92eaac9b7..7ccdc7cba8de 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Globalization; using System.Runtime.Serialization; @@ -104,7 +105,7 @@ public static TimeZoneInfo GetDeserializedTimeZoneInfo(string source) string displayName = s.GetNextStringValue(); string standardName = s.GetNextStringValue(); string daylightName = s.GetNextStringValue(); - AdjustmentRule[] rules = s.GetNextAdjustmentRuleArrayValue(); + AdjustmentRule[]? rules = s.GetNextAdjustmentRuleArrayValue(); try { @@ -373,13 +374,13 @@ private int GetNextInt32Value() /// /// Helper function to read an AdjustmentRule[] token. /// - private AdjustmentRule[] GetNextAdjustmentRuleArrayValue() + private AdjustmentRule[]? GetNextAdjustmentRuleArrayValue() { List rules = new List(1); int count = 0; // individual AdjustmentRule array elements do not require semicolons - AdjustmentRule rule = GetNextAdjustmentRuleValue(); + AdjustmentRule? rule = GetNextAdjustmentRuleValue(); while (rule != null) { rules.Add(rule); @@ -404,7 +405,7 @@ private AdjustmentRule[] GetNextAdjustmentRuleArrayValue() /// /// Helper function to read an AdjustmentRule token. /// - private AdjustmentRule GetNextAdjustmentRuleValue() + private AdjustmentRule? GetNextAdjustmentRuleValue() { // first verify the internal state of the object if (_state == State.EndOfLine) diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.TransitionTime.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.TransitionTime.cs index b93794262cdd..86e7002d7c2b 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.TransitionTime.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.TransitionTime.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.Serialization; namespace System @@ -30,7 +31,7 @@ public sealed partial class TimeZoneInfo public bool IsFixedDateRule => _isFixedDateRule; - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj is TransitionTime && Equals((TransitionTime)obj); public static bool operator ==(TransitionTime t1, TransitionTime t2) => t1.Equals(t2); @@ -143,12 +144,12 @@ private TransitionTime(SerializationInfo info, StreamingContext context) throw new ArgumentNullException(nameof(info)); } - _timeOfDay = (DateTime)info.GetValue("TimeOfDay", typeof(DateTime)); // Do not rename (binary serialization) - _month = (byte)info.GetValue("Month", typeof(byte)); // Do not rename (binary serialization) - _week = (byte)info.GetValue("Week", typeof(byte)); // Do not rename (binary serialization) - _day = (byte)info.GetValue("Day", typeof(byte)); // Do not rename (binary serialization) - _dayOfWeek = (DayOfWeek)info.GetValue("DayOfWeek", typeof(DayOfWeek)); // Do not rename (binary serialization) - _isFixedDateRule = (bool)info.GetValue("IsFixedDateRule", typeof(bool)); // Do not rename (binary serialization) + _timeOfDay = (DateTime)info.GetValue("TimeOfDay", typeof(DateTime))!; // Do not rename (binary serialization) + _month = (byte)info.GetValue("Month", typeof(byte))!; // Do not rename (binary serialization) + _week = (byte)info.GetValue("Week", typeof(byte))!; // Do not rename (binary serialization) + _day = (byte)info.GetValue("Day", typeof(byte))!; // Do not rename (binary serialization) + _dayOfWeek = (DayOfWeek)info.GetValue("DayOfWeek", typeof(DayOfWeek))!; // Do not rename (binary serialization) + _isFixedDateRule = (bool)info.GetValue("IsFixedDateRule", typeof(bool))!; // Do not rename (binary serialization) } } } diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs index 9ca9e9cc82b5..02543cca1126 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Collections.Generic; using System.Diagnostics; @@ -32,7 +33,7 @@ private TimeZoneInfo(byte[] data, string id, bool dstDisabled) string zoneAbbreviations; bool[] StandardTime; bool[] GmtTime; - string futureTransitionsPosixFormat; + string? futureTransitionsPosixFormat; // parse the raw TZif bytes; this method can throw ArgumentException when the data is malformed. TZif_ParseRaw(data, out t, out dts, out typeOfLocalTime, out transitionType, out zoneAbbreviations, out StandardTime, out GmtTime, out futureTransitionsPosixFormat); @@ -106,7 +107,7 @@ private TimeZoneInfo(byte[] data, string id, bool dstDisabled) ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out _supportsDaylightSavingTime); } - private unsafe void GetDisplayName(Interop.Globalization.TimeZoneDisplayNameType nameType, ref string displayName) + private unsafe void GetDisplayName(Interop.Globalization.TimeZoneDisplayNameType nameType, ref string? displayName) { if (GlobalizationMode.Invariant) { @@ -114,7 +115,7 @@ private unsafe void GetDisplayName(Interop.Globalization.TimeZoneDisplayNameType return; } - string timeZoneDisplayName; + string? timeZoneDisplayName; bool result = Interop.CallStringMethod( (buffer, locale, id, type) => { @@ -182,9 +183,7 @@ private static void PopulateAllSystemTimeZones(CachedData cachedData) string timeZoneDirectory = GetTimeZoneDirectory(); foreach (string timeZoneId in GetTimeZoneIds(timeZoneDirectory)) { - TimeZoneInfo value; - Exception ex; - TryGetTimeZone(timeZoneId, false, out value, out ex, cachedData, alwaysFallbackToLocalMachine: true); // populate the cache + TryGetTimeZone(timeZoneId, false, out _, out _, cachedData, alwaysFallbackToLocalMachine: true); // populate the cache } } @@ -202,7 +201,7 @@ private static TimeZoneInfo GetLocalTimeZone(CachedData cachedData) return GetLocalTimeZoneFromTzFile(); } - private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, out TimeZoneInfo value, out Exception e) + private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, out TimeZoneInfo? value, out Exception? e) { value = null; e = null; @@ -260,7 +259,7 @@ private static List GetTimeZoneIds(string timeZoneDirectory) { using (StreamReader sr = new StreamReader(Path.Combine(timeZoneDirectory, ZoneTabFileName), Encoding.UTF8)) { - string zoneTabFileLine; + string? zoneTabFileLine; while ((zoneTabFileLine = sr.ReadLine()) != null) { if (!string.IsNullOrEmpty(zoneTabFileLine) && zoneTabFileLine[0] != '#') @@ -309,11 +308,11 @@ private static List GetTimeZoneIds(string timeZoneDirectory) /// 3. Look for the data in GetTimeZoneDirectory()/localtime. /// 4. Use UTC if all else fails. /// - private static bool TryGetLocalTzFile(out byte[] rawData, out string id) + private static bool TryGetLocalTzFile(out byte[]? rawData, out string? id) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { rawData = null; id = null; - string tzVariable = GetTzEnvironmentVariable(); + string? tzVariable = GetTzEnvironmentVariable(); // If the env var is null, use the localtime file if (tzVariable == null) @@ -344,9 +343,9 @@ private static bool TryGetLocalTzFile(out byte[] rawData, out string id) return TryLoadTzFile(tzFilePath, ref rawData, ref id); } - private static string GetTzEnvironmentVariable() + private static string? GetTzEnvironmentVariable() { - string result = Environment.GetEnvironmentVariable(TimeZoneEnvironmentVariable); + string? result = Environment.GetEnvironmentVariable(TimeZoneEnvironmentVariable); if (!string.IsNullOrEmpty(result)) { if (result[0] == ':') @@ -359,7 +358,7 @@ private static string GetTzEnvironmentVariable() return result; } - private static bool TryLoadTzFile(string tzFilePath, ref byte[] rawData, ref string id) + private static bool TryLoadTzFile(string tzFilePath, ref byte[]? rawData, ref string? id) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (File.Exists(tzFilePath)) { @@ -388,15 +387,15 @@ private static bool TryLoadTzFile(string tzFilePath, ref byte[] rawData, ref str /// Finds the time zone id by using 'readlink' on the path to see if tzFilePath is /// a symlink to a file. /// - private static string FindTimeZoneIdUsingReadLink(string tzFilePath) + private static string? FindTimeZoneIdUsingReadLink(string tzFilePath) { - string id = null; + string? id = null; - string symlinkPath = Interop.Sys.ReadLink(tzFilePath); + string? symlinkPath = Interop.Sys.ReadLink(tzFilePath); if (symlinkPath != null) { // symlinkPath can be relative path, use Path to get the full absolute path. - symlinkPath = Path.GetFullPath(symlinkPath, Path.GetDirectoryName(tzFilePath)); + symlinkPath = Path.GetFullPath(symlinkPath, Path.GetDirectoryName(tzFilePath)!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 string timeZoneDirectory = GetTimeZoneDirectory(); if (symlinkPath.StartsWith(timeZoneDirectory, StringComparison.Ordinal)) @@ -408,7 +407,7 @@ private static string FindTimeZoneIdUsingReadLink(string tzFilePath) return id; } - private static string GetDirectoryEntryFullPath(ref Interop.Sys.DirectoryEntry dirent, string currentPath) + private static string? GetDirectoryEntryFullPath(ref Interop.Sys.DirectoryEntry dirent, string currentPath) { Span nameBuffer = stackalloc char[Interop.Sys.DirectoryEntry.NameBufferSize]; ReadOnlySpan direntName = dirent.GetName(nameBuffer); @@ -425,10 +424,10 @@ private static string GetDirectoryEntryFullPath(ref Interop.Sys.DirectoryEntry d /// private static unsafe void EnumerateFilesRecursively(string path, Predicate condition) { - List toExplore = null; // List used as a stack + List? toExplore = null; // List used as a stack int bufferSize = Interop.Sys.GetReadDirRBufferSize(); - byte[] dirBuffer = null; + byte[]? dirBuffer = null; try { dirBuffer = ArrayPool.Shared.Rent(bufferSize); @@ -450,7 +449,7 @@ private static unsafe void EnumerateFilesRecursively(string path, Predicate private static TimeZoneInfo GetLocalTimeZoneFromTzFile() { - byte[] rawData; - string id; - if (TryGetLocalTzFile(out rawData, out id)) + byte[]? rawData; + string? id; + if (TryGetLocalTzFile(out rawData, out id)) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { - TimeZoneInfo result = GetTimeZoneFromTzData(rawData, id); + TimeZoneInfo? result = GetTimeZoneFromTzData(rawData!, id!); if (result != null) { return result; @@ -629,7 +628,7 @@ private static TimeZoneInfo GetLocalTimeZoneFromTzFile() return Utc; } - private static TimeZoneInfo GetTimeZoneFromTzData(byte[] rawData, string id) + private static TimeZoneInfo? GetTimeZoneFromTzData(byte[] rawData, string id) { if (rawData != null) { @@ -652,7 +651,7 @@ private static TimeZoneInfo GetTimeZoneFromTzData(byte[] rawData, string id) private static string GetTimeZoneDirectory() { - string tzDirectory = Environment.GetEnvironmentVariable(TimeZoneDirectoryEnvironmentVariable); + string? tzDirectory = Environment.GetEnvironmentVariable(TimeZoneDirectoryEnvironmentVariable); if (tzDirectory == null) { @@ -693,8 +692,8 @@ public static TimeZoneInfo FindSystemTimeZoneById(string id) throw new TimeZoneNotFoundException(SR.Format(SR.TimeZoneNotFound_MissingData, id)); } - TimeZoneInfo value; - Exception e; + TimeZoneInfo? value; + Exception? e; TimeZoneInfoResult result; @@ -707,7 +706,7 @@ public static TimeZoneInfo FindSystemTimeZoneById(string id) if (result == TimeZoneInfoResult.Success) { - return value; + return value!; } else if (result == TimeZoneInfoResult.InvalidTimeZoneException) { @@ -862,8 +861,8 @@ internal static TimeSpan GetDateTimeNowUtcOffsetFromUtc(DateTime time, out bool // BSD July 18, 2003 BSD // // - private static void TZif_GenerateAdjustmentRules(out AdjustmentRule[] rules, TimeSpan baseUtcOffset, DateTime[] dts, byte[] typeOfLocalTime, - TZifType[] transitionType, bool[] StandardTime, bool[] GmtTime, string futureTransitionsPosixFormat) + private static void TZif_GenerateAdjustmentRules(out AdjustmentRule[]? rules, TimeSpan baseUtcOffset, DateTime[] dts, byte[] typeOfLocalTime, + TZifType[] transitionType, bool[] StandardTime, bool[] GmtTime, string? futureTransitionsPosixFormat) { rules = null; @@ -886,7 +885,7 @@ private static void TZif_GenerateAdjustmentRules(out AdjustmentRule[] rules, Tim } private static void TZif_GenerateAdjustmentRule(ref int index, TimeSpan timeZoneBaseUtcOffset, List rulesList, DateTime[] dts, - byte[] typeOfLocalTime, TZifType[] transitionTypes, bool[] StandardTime, bool[] GmtTime, string futureTransitionsPosixFormat) + byte[] typeOfLocalTime, TZifType[] transitionTypes, bool[] StandardTime, bool[] GmtTime, string? futureTransitionsPosixFormat) { // To generate AdjustmentRules, use the following approach: // The first AdjustmentRule will go from DateTime.MinValue to the first transition time greater than DateTime.MinValue. @@ -987,13 +986,13 @@ private static void TZif_GenerateAdjustmentRule(ref int index, TimeSpan timeZone if (!string.IsNullOrEmpty(futureTransitionsPosixFormat)) { - AdjustmentRule r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset); + AdjustmentRule? r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset); if (r != null) { if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r)) { - NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r); + NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } rulesList.Add(r); @@ -1078,7 +1077,7 @@ private static TZifType TZif_GetEarlyDateTransitionType(TZifType[] transitionTyp /// /// See http://man7.org/linux/man-pages/man3/tzset.3.html for the format and semantics of this POSX string. /// - private static AdjustmentRule TZif_CreateAdjustmentRuleForPosixFormat(string posixFormat, DateTime startTransitionDate, TimeSpan timeZoneBaseUtcOffset) + private static AdjustmentRule? TZif_CreateAdjustmentRuleForPosixFormat(string posixFormat, DateTime startTransitionDate, TimeSpan timeZoneBaseUtcOffset) { if (TZif_ParsePosixFormat(posixFormat, out ReadOnlySpan standardName, @@ -1506,15 +1505,15 @@ private static DateTime TZif_UnixTimeToDateTime(long unixTime) => DateTimeOffset.FromUnixTimeSeconds(unixTime).UtcDateTime; private static void TZif_ParseRaw(byte[] data, out TZifHead t, out DateTime[] dts, out byte[] typeOfLocalTime, out TZifType[] transitionType, - out string zoneAbbreviations, out bool[] StandardTime, out bool[] GmtTime, out string futureTransitionsPosixFormat) + out string zoneAbbreviations, out bool[] StandardTime, out bool[] GmtTime, out string? futureTransitionsPosixFormat) { // initialize the out parameters in case the TZifHead ctor throws - dts = null; - typeOfLocalTime = null; - transitionType = null; + dts = null!; + typeOfLocalTime = null!; + transitionType = null!; zoneAbbreviations = string.Empty; - StandardTime = null; - GmtTime = null; + StandardTime = null!; + GmtTime = null!; futureTransitionsPosixFormat = null; // read in the 44-byte TZ header containing the count/length fields diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs index 4de4ea50d7e9..416b2c81e7b8 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs @@ -1,992 +1,986 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; - -using Microsoft.Win32.SafeHandles; - -using Internal.Win32; -using Internal.Runtime.CompilerServices; - -using REG_TZI_FORMAT = Interop.Kernel32.REG_TZI_FORMAT; -using TIME_ZONE_INFORMATION = Interop.Kernel32.TIME_ZONE_INFORMATION; -using TIME_DYNAMIC_ZONE_INFORMATION = Interop.Kernel32.TIME_DYNAMIC_ZONE_INFORMATION; - -namespace System -{ - public sealed partial class TimeZoneInfo - { - // registry constants for the 'Time Zones' hive - // - private const string TimeZonesRegistryHive = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"; - private const string DisplayValue = "Display"; - private const string DaylightValue = "Dlt"; - private const string StandardValue = "Std"; - private const string MuiDisplayValue = "MUI_Display"; - private const string MuiDaylightValue = "MUI_Dlt"; - private const string MuiStandardValue = "MUI_Std"; - private const string TimeZoneInfoValue = "TZI"; - private const string FirstEntryValue = "FirstEntry"; - private const string LastEntryValue = "LastEntry"; - - private const int MaxKeyLength = 255; - - private sealed partial class CachedData - { - private static TimeZoneInfo GetCurrentOneYearLocal() - { - // load the data from the OS - TIME_ZONE_INFORMATION timeZoneInformation; - uint result = Interop.Kernel32.GetTimeZoneInformation(out timeZoneInformation); - return result == Interop.Kernel32.TIME_ZONE_ID_INVALID ? - CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId) : - GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled: false); - } - - private volatile OffsetAndRule _oneYearLocalFromUtc; - - public OffsetAndRule GetOneYearLocalFromUtc(int year) - { - OffsetAndRule oneYearLocFromUtc = _oneYearLocalFromUtc; - if (oneYearLocFromUtc == null || oneYearLocFromUtc.Year != year) - { - TimeZoneInfo currentYear = GetCurrentOneYearLocal(); - AdjustmentRule rule = currentYear._adjustmentRules == null ? null : currentYear._adjustmentRules[0]; - oneYearLocFromUtc = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule); - _oneYearLocalFromUtc = oneYearLocFromUtc; - } - return oneYearLocFromUtc; - } - } - - private sealed class OffsetAndRule - { - public readonly int Year; - public readonly TimeSpan Offset; - public readonly AdjustmentRule Rule; - - public OffsetAndRule(int year, TimeSpan offset, AdjustmentRule rule) - { - Year = year; - Offset = offset; - Rule = rule; - } - } - - /// - /// Returns a cloned array of AdjustmentRule objects - /// - public AdjustmentRule[] GetAdjustmentRules() - { - if (_adjustmentRules == null) - { - return Array.Empty(); - } - - return (AdjustmentRule[])_adjustmentRules.Clone(); - } - - private static void PopulateAllSystemTimeZones(CachedData cachedData) - { - Debug.Assert(Monitor.IsEntered(cachedData)); - - using (RegistryKey reg = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive, writable: false)) - { - if (reg != null) - { - foreach (string keyName in reg.GetSubKeyNames()) - { - TimeZoneInfo value; - Exception ex; - TryGetTimeZone(keyName, false, out value, out ex, cachedData); // populate the cache - } - } - } - } - - private TimeZoneInfo(in TIME_ZONE_INFORMATION zone, bool dstDisabled) - { - string standardName = zone.GetStandardName(); - if (standardName.Length == 0) - { - _id = LocalId; // the ID must contain at least 1 character - initialize _id to "Local" - } - else - { - _id = standardName; - } - _baseUtcOffset = new TimeSpan(0, -(zone.Bias), 0); - - if (!dstDisabled) - { - // only create the adjustment rule if DST is enabled - REG_TZI_FORMAT regZone = new REG_TZI_FORMAT(zone); - AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(regZone, DateTime.MinValue.Date, DateTime.MaxValue.Date, zone.Bias); - if (rule != null) - { - _adjustmentRules = new[] { rule }; - } - } - - ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out _supportsDaylightSavingTime); - _displayName = standardName; - _standardDisplayName = standardName; - _daylightDisplayName = zone.GetDaylightName(); - } - - /// - /// Helper function to check if the current TimeZoneInformation struct does not support DST. - /// This check returns true when the DaylightDate == StandardDate. - /// This check is only meant to be used for "Local". - /// - private static bool CheckDaylightSavingTimeNotSupported(in TIME_ZONE_INFORMATION timeZone) => - timeZone.DaylightDate.Equals(timeZone.StandardDate); - - /// - /// Converts a REG_TZI_FORMAT struct to an AdjustmentRule. - /// - private static AdjustmentRule CreateAdjustmentRuleFromTimeZoneInformation(in REG_TZI_FORMAT timeZoneInformation, DateTime startDate, DateTime endDate, int defaultBaseUtcOffset) - { - bool supportsDst = timeZoneInformation.StandardDate.Month != 0; - - if (!supportsDst) - { - if (timeZoneInformation.Bias == defaultBaseUtcOffset) - { - // this rule will not contain any information to be used to adjust dates. just ignore it - return null; - } - - return AdjustmentRule.CreateAdjustmentRule( - startDate, - endDate, - TimeSpan.Zero, // no daylight saving transition - TransitionTime.CreateFixedDateRule(DateTime.MinValue, 1, 1), - TransitionTime.CreateFixedDateRule(DateTime.MinValue.AddMilliseconds(1), 1, 1), - new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0), // Bias delta is all what we need from this rule - noDaylightTransitions: false); - } - - // - // Create an AdjustmentRule with TransitionTime objects - // - TransitionTime daylightTransitionStart; - if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionStart, readStartDate: true)) - { - return null; - } - - TransitionTime daylightTransitionEnd; - if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionEnd, readStartDate: false)) - { - return null; - } - - if (daylightTransitionStart.Equals(daylightTransitionEnd)) - { - // this happens when the time zone does support DST but the OS has DST disabled - return null; - } - - return AdjustmentRule.CreateAdjustmentRule( - startDate, - endDate, - new TimeSpan(0, -timeZoneInformation.DaylightBias, 0), - daylightTransitionStart, - daylightTransitionEnd, - new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0), - noDaylightTransitions: false); - } - - /// - /// Helper function that searches the registry for a time zone entry - /// that matches the TimeZoneInformation struct. - /// - private static string FindIdFromTimeZoneInformation(in TIME_ZONE_INFORMATION timeZone, out bool dstDisabled) - { - dstDisabled = false; - - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive, writable: false)) - { - if (key == null) - { - return null; - } - - foreach (string keyName in key.GetSubKeyNames()) - { - if (TryCompareTimeZoneInformationToRegistry(timeZone, keyName, out dstDisabled)) - { - return keyName; - } - } - } - - return null; - } - - /// - /// Helper function for retrieving the local system time zone. - /// May throw COMException, TimeZoneNotFoundException, InvalidTimeZoneException. - /// Assumes cachedData lock is taken. - /// - /// A new TimeZoneInfo instance. - private static TimeZoneInfo GetLocalTimeZone(CachedData cachedData) - { - Debug.Assert(Monitor.IsEntered(cachedData)); - - // - // Try using the "kernel32!GetDynamicTimeZoneInformation" API to get the "id" - // - var dynamicTimeZoneInformation = new TIME_DYNAMIC_ZONE_INFORMATION(); - - // call kernel32!GetDynamicTimeZoneInformation... - uint result = Interop.Kernel32.GetDynamicTimeZoneInformation(out dynamicTimeZoneInformation); - if (result == Interop.Kernel32.TIME_ZONE_ID_INVALID) - { - // return a dummy entry - return CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId); - } - - // check to see if we can use the key name returned from the API call - string dynamicTimeZoneKeyName = dynamicTimeZoneInformation.GetTimeZoneKeyName(); - if (dynamicTimeZoneKeyName.Length != 0) - { - TimeZoneInfo zone; - Exception ex; - - if (TryGetTimeZone(dynamicTimeZoneKeyName, dynamicTimeZoneInformation.DynamicDaylightTimeDisabled != 0, out zone, out ex, cachedData) == TimeZoneInfoResult.Success) - { - // successfully loaded the time zone from the registry - return zone; - } - } - - var timeZoneInformation = new TIME_ZONE_INFORMATION(dynamicTimeZoneInformation); - - // the key name was not returned or it pointed to a bogus entry - search for the entry ourselves - string id = FindIdFromTimeZoneInformation(timeZoneInformation, out bool dstDisabled); - - if (id != null) - { - TimeZoneInfo zone; - Exception ex; - if (TryGetTimeZone(id, dstDisabled, out zone, out ex, cachedData) == TimeZoneInfoResult.Success) - { - // successfully loaded the time zone from the registry - return zone; - } - } - - // We could not find the data in the registry. Fall back to using - // the data from the Win32 API - return GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled); - } - - /// - /// Helper function used by 'GetLocalTimeZone()' - this function wraps a bunch of - /// try/catch logic for handling the TimeZoneInfo private constructor that takes - /// a TIME_ZONE_INFORMATION structure. - /// - private static TimeZoneInfo GetLocalTimeZoneFromWin32Data(in TIME_ZONE_INFORMATION timeZoneInformation, bool dstDisabled) - { - // first try to create the TimeZoneInfo with the original 'dstDisabled' flag - try - { - return new TimeZoneInfo(timeZoneInformation, dstDisabled); - } - catch (ArgumentException) { } - catch (InvalidTimeZoneException) { } - - // if 'dstDisabled' was false then try passing in 'true' as a last ditch effort - if (!dstDisabled) - { - try - { - return new TimeZoneInfo(timeZoneInformation, dstDisabled: true); - } - catch (ArgumentException) { } - catch (InvalidTimeZoneException) { } - } - - // the data returned from Windows is completely bogus; return a dummy entry - return CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId); - } - - /// - /// Helper function for retrieving a TimeZoneInfo object by time_zone_name. - /// This function wraps the logic necessary to keep the private - /// SystemTimeZones cache in working order - /// - /// This function will either return a valid TimeZoneInfo instance or - /// it will throw 'InvalidTimeZoneException' / 'TimeZoneNotFoundException'. - /// - public static TimeZoneInfo FindSystemTimeZoneById(string id) - { - // Special case for Utc as it will not exist in the dictionary with the rest - // of the system time zones. There is no need to do this check for Local.Id - // since Local is a real time zone that exists in the dictionary cache - if (string.Equals(id, UtcId, StringComparison.OrdinalIgnoreCase)) - { - return Utc; - } - - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - if (id.Length == 0 || id.Length > MaxKeyLength || id.Contains('\0')) - { - throw new TimeZoneNotFoundException(SR.Format(SR.TimeZoneNotFound_MissingData, id)); - } - - TimeZoneInfo value; - Exception e; - - TimeZoneInfoResult result; - - CachedData cachedData = s_cachedData; - - lock (cachedData) - { - result = TryGetTimeZone(id, false, out value, out e, cachedData); - } - - if (result == TimeZoneInfoResult.Success) - { - return value; - } - else if (result == TimeZoneInfoResult.InvalidTimeZoneException) - { - throw new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_InvalidRegistryData, id), e); - } - else if (result == TimeZoneInfoResult.SecurityException) - { - throw new SecurityException(SR.Format(SR.Security_CannotReadRegistryData, id), e); - } - else - { - throw new TimeZoneNotFoundException(SR.Format(SR.TimeZoneNotFound_MissingData, id), e); - } - } - - // DateTime.Now fast path that avoids allocating an historically accurate TimeZoneInfo.Local and just creates a 1-year (current year) accurate time zone - internal static TimeSpan GetDateTimeNowUtcOffsetFromUtc(DateTime time, out bool isAmbiguousLocalDst) - { - bool isDaylightSavings = false; - isAmbiguousLocalDst = false; - TimeSpan baseOffset; - int timeYear = time.Year; - - OffsetAndRule match = s_cachedData.GetOneYearLocalFromUtc(timeYear); - baseOffset = match.Offset; - - if (match.Rule != null) - { - baseOffset = baseOffset + match.Rule.BaseUtcOffsetDelta; - if (match.Rule.HasDaylightSaving) - { - isDaylightSavings = GetIsDaylightSavingsFromUtc(time, timeYear, match.Offset, match.Rule, null, out isAmbiguousLocalDst, Local); - baseOffset += (isDaylightSavings ? match.Rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); - } - } - return baseOffset; - } - - /// - /// Converts a REG_TZI_FORMAT struct to a TransitionTime - /// - When the argument 'readStart' is true the corresponding daylightTransitionTimeStart field is read - /// - When the argument 'readStart' is false the corresponding dayightTransitionTimeEnd field is read - /// - private static bool TransitionTimeFromTimeZoneInformation(in REG_TZI_FORMAT timeZoneInformation, out TransitionTime transitionTime, bool readStartDate) - { - // - // SYSTEMTIME - - // - // If the time zone does not support daylight saving time or if the caller needs - // to disable daylight saving time, the wMonth member in the SYSTEMTIME structure - // must be zero. If this date is specified, the DaylightDate value in the - // TIME_ZONE_INFORMATION structure must also be specified. Otherwise, the system - // assumes the time zone data is invalid and no changes will be applied. - // - bool supportsDst = (timeZoneInformation.StandardDate.Month != 0); - - if (!supportsDst) - { - transitionTime = default; - return false; - } - - // - // SYSTEMTIME - - // - // * FixedDateRule - - // If the Year member is not zero, the transition date is absolute; it will only occur one time - // - // * FloatingDateRule - - // To select the correct day in the month, set the Year member to zero, the Hour and Minute - // members to the transition time, the DayOfWeek member to the appropriate weekday, and the - // Day member to indicate the occurence of the day of the week within the month (first through fifth). - // - // Using this notation, specify the 2:00a.m. on the first Sunday in April as follows: - // Hour = 2, - // Month = 4, - // DayOfWeek = 0, - // Day = 1. - // - // Specify 2:00a.m. on the last Thursday in October as follows: - // Hour = 2, - // Month = 10, - // DayOfWeek = 4, - // Day = 5. - // - if (readStartDate) - { - // - // read the "daylightTransitionStart" - // - if (timeZoneInformation.DaylightDate.Year == 0) - { - transitionTime = TransitionTime.CreateFloatingDateRule( - new DateTime(1, /* year */ - 1, /* month */ - 1, /* day */ - timeZoneInformation.DaylightDate.Hour, - timeZoneInformation.DaylightDate.Minute, - timeZoneInformation.DaylightDate.Second, - timeZoneInformation.DaylightDate.Milliseconds), - timeZoneInformation.DaylightDate.Month, - timeZoneInformation.DaylightDate.Day, /* Week 1-5 */ - (DayOfWeek)timeZoneInformation.DaylightDate.DayOfWeek); - } - else - { - transitionTime = TransitionTime.CreateFixedDateRule( - new DateTime(1, /* year */ - 1, /* month */ - 1, /* day */ - timeZoneInformation.DaylightDate.Hour, - timeZoneInformation.DaylightDate.Minute, - timeZoneInformation.DaylightDate.Second, - timeZoneInformation.DaylightDate.Milliseconds), - timeZoneInformation.DaylightDate.Month, - timeZoneInformation.DaylightDate.Day); - } - } - else - { - // - // read the "daylightTransitionEnd" - // - if (timeZoneInformation.StandardDate.Year == 0) - { - transitionTime = TransitionTime.CreateFloatingDateRule( - new DateTime(1, /* year */ - 1, /* month */ - 1, /* day */ - timeZoneInformation.StandardDate.Hour, - timeZoneInformation.StandardDate.Minute, - timeZoneInformation.StandardDate.Second, - timeZoneInformation.StandardDate.Milliseconds), - timeZoneInformation.StandardDate.Month, - timeZoneInformation.StandardDate.Day, /* Week 1-5 */ - (DayOfWeek)timeZoneInformation.StandardDate.DayOfWeek); - } - else - { - transitionTime = TransitionTime.CreateFixedDateRule( - new DateTime(1, /* year */ - 1, /* month */ - 1, /* day */ - timeZoneInformation.StandardDate.Hour, - timeZoneInformation.StandardDate.Minute, - timeZoneInformation.StandardDate.Second, - timeZoneInformation.StandardDate.Milliseconds), - timeZoneInformation.StandardDate.Month, - timeZoneInformation.StandardDate.Day); - } - } - - return true; - } - - /// - /// Helper function that takes: - /// 1. A string representing a time_zone_name registry key name. - /// 2. A REG_TZI_FORMAT struct containing the default rule. - /// 3. An AdjustmentRule[] out-parameter. - /// - private static bool TryCreateAdjustmentRules(string id, in REG_TZI_FORMAT defaultTimeZoneInformation, out AdjustmentRule[] rules, out Exception e, int defaultBaseUtcOffset) - { - rules = null; - e = null; - - try - { - // Optional, Dynamic Time Zone Registry Data - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - // - // HKLM - // Software - // Microsoft - // Windows NT - // CurrentVersion - // Time Zones - // - // Dynamic DST - // * "FirstEntry" REG_DWORD "1980" - // First year in the table. If the current year is less than this value, - // this entry will be used for DST boundaries - // * "LastEntry" REG_DWORD "2038" - // Last year in the table. If the current year is greater than this value, - // this entry will be used for DST boundaries" - // * "" REG_BINARY REG_TZI_FORMAT - // * "" REG_BINARY REG_TZI_FORMAT - // * "" REG_BINARY REG_TZI_FORMAT - // - using (RegistryKey dynamicKey = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id + "\\Dynamic DST", writable: false)) - { - if (dynamicKey == null) - { - AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation( - defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); - if (rule != null) - { - rules = new[] { rule }; - } - return true; - } - - // - // loop over all of the "\Dynamic DST" hive entries - // - // read FirstEntry {MinValue - (year1, 12, 31)} - // read MiddleEntry {(yearN, 1, 1) - (yearN, 12, 31)} - // read LastEntry {(yearN, 1, 1) - MaxValue } - - // read the FirstEntry and LastEntry key values (ex: "1980", "2038") - int first = (int)dynamicKey.GetValue(FirstEntryValue, -1); - int last = (int)dynamicKey.GetValue(LastEntryValue, -1); - - if (first == -1 || last == -1 || first > last) - { - return false; - } - - // read the first year entry - REG_TZI_FORMAT dtzi; - - if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, first.ToString(CultureInfo.InvariantCulture), out dtzi)) - { - return false; - } - - if (first == last) - { - // there is just 1 dynamic rule for this time zone. - AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); - if (rule != null) - { - rules = new[] { rule }; - } - return true; - } - - List rulesList = new List(1); - - // there are more than 1 dynamic rules for this time zone. - AdjustmentRule firstRule = CreateAdjustmentRuleFromTimeZoneInformation( - dtzi, - DateTime.MinValue.Date, // MinValue - new DateTime(first, 12, 31), // December 31, - defaultBaseUtcOffset); - - if (firstRule != null) - { - rulesList.Add(firstRule); - } - - // read the middle year entries - for (int i = first + 1; i < last; i++) - { - if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, i.ToString(CultureInfo.InvariantCulture), out dtzi)) - { - return false; - } - AdjustmentRule middleRule = CreateAdjustmentRuleFromTimeZoneInformation( - dtzi, - new DateTime(i, 1, 1), // January 01, - new DateTime(i, 12, 31), // December 31, - defaultBaseUtcOffset); - - if (middleRule != null) - { - rulesList.Add(middleRule); - } - } - - // read the last year entry - if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, last.ToString(CultureInfo.InvariantCulture), out dtzi)) - { - return false; - } - AdjustmentRule lastRule = CreateAdjustmentRuleFromTimeZoneInformation( - dtzi, - new DateTime(last, 1, 1), // January 01, - DateTime.MaxValue.Date, // MaxValue - defaultBaseUtcOffset); - - if (lastRule != null) - { - rulesList.Add(lastRule); - } - - // convert the List to an AdjustmentRule array - if (rulesList.Count != 0) - { - rules = rulesList.ToArray(); - } - } // end of: using (RegistryKey dynamicKey... - } - catch (InvalidCastException ex) - { - // one of the RegistryKey.GetValue calls could not be cast to an expected value type - e = ex; - return false; - } - catch (ArgumentOutOfRangeException ex) - { - e = ex; - return false; - } - catch (ArgumentException ex) - { - e = ex; - return false; - } - return true; - } - - private static unsafe bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi) - { - if (!(key.GetValue(name, null) is byte[] regValue) || regValue.Length != sizeof(REG_TZI_FORMAT)) - { - dtzi = default; - return false; - } - fixed (byte * pBytes = ®Value[0]) - dtzi = *(REG_TZI_FORMAT *)pBytes; - return true; - } - - /// - /// Helper function that compares the StandardBias and StandardDate portion a - /// TimeZoneInformation struct to a time zone registry entry. - /// - private static bool TryCompareStandardDate(in TIME_ZONE_INFORMATION timeZone, in REG_TZI_FORMAT registryTimeZoneInfo) => - timeZone.Bias == registryTimeZoneInfo.Bias && - timeZone.StandardBias == registryTimeZoneInfo.StandardBias && - timeZone.StandardDate.Equals(registryTimeZoneInfo.StandardDate); - - /// - /// Helper function that compares a TimeZoneInformation struct to a time zone registry entry. - /// - private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMATION timeZone, string id, out bool dstDisabled) - { - dstDisabled = false; - - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id, writable: false)) - { - if (key == null) - { - return false; - } - - REG_TZI_FORMAT registryTimeZoneInfo; - if (!TryGetTimeZoneEntryFromRegistry(key, TimeZoneInfoValue, out registryTimeZoneInfo)) - { - return false; - } - - // - // first compare the bias and standard date information between the data from the Win32 API - // and the data from the registry... - // - bool result = TryCompareStandardDate(timeZone, registryTimeZoneInfo); - - if (!result) - { - return false; - } - - result = dstDisabled || CheckDaylightSavingTimeNotSupported(timeZone) || - // - // since Daylight Saving Time is not "disabled", do a straight comparision between - // the Win32 API data and the registry data ... - // - (timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias && - timeZone.DaylightDate.Equals(registryTimeZoneInfo.DaylightDate)); - - // Finally compare the "StandardName" string value... - // - // we do not compare "DaylightName" as this TimeZoneInformation field may contain - // either "StandardName" or "DaylightName" depending on the time of year and current machine settings - // - if (result) - { - string registryStandardName = key.GetValue(StandardValue, string.Empty) as string; - result = string.Equals(registryStandardName, timeZone.GetStandardName(), StringComparison.Ordinal); - } - return result; - } - } - - /// - /// Helper function for retrieving a localized string resource via MUI. - /// The function expects a string in the form: "@resource.dll, -123" - /// - /// "resource.dll" is a language-neutral portable executable (LNPE) file in - /// the %windir%\system32 directory. The OS is queried to find the best-fit - /// localized resource file for this LNPE (ex: %windir%\system32\en-us\resource.dll.mui). - /// If a localized resource file exists, we LoadString resource ID "123" and - /// return it to our caller. - /// - private static string TryGetLocalizedNameByMuiNativeResource(string resource) - { - if (string.IsNullOrEmpty(resource)) - { - return string.Empty; - } - - // parse "@tzres.dll, -100" - // - // filePath = "C:\Windows\System32\tzres.dll" - // resourceId = -100 - // - string[] resources = resource.Split(','); - if (resources.Length != 2) - { - return string.Empty; - } - - string filePath; - int resourceId; - - // get the path to Windows\System32 - string system32 = Environment.SystemDirectory; - - // trim the string "@tzres.dll" => "tzres.dll" - string tzresDll = resources[0].TrimStart('@'); - - try - { - filePath = Path.Combine(system32, tzresDll); - } - catch (ArgumentException) - { - // there were probably illegal characters in the path - return string.Empty; - } - - if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out resourceId)) - { - return string.Empty; - } - resourceId = -resourceId; - - try - { - unsafe - { - char* fileMuiPath = stackalloc char[Interop.Kernel32.MAX_PATH]; - int fileMuiPathLength = Interop.Kernel32.MAX_PATH; - int languageLength = 0; - long enumerator = 0; - - bool succeeded = Interop.Kernel32.GetFileMUIPath( - Interop.Kernel32.MUI_PREFERRED_UI_LANGUAGES, - filePath, null /* language */, ref languageLength, - fileMuiPath, ref fileMuiPathLength, ref enumerator); - return succeeded ? - TryGetLocalizedNameByNativeResource(new string(fileMuiPath, 0, fileMuiPathLength), resourceId) : - string.Empty; - } - } - catch (EntryPointNotFoundException) - { - return string.Empty; - } - } - - /// - /// Helper function for retrieving a localized string resource via a native resource DLL. - /// The function expects a string in the form: "C:\Windows\System32\en-us\resource.dll" - /// - /// "resource.dll" is a language-specific resource DLL. - /// If the localized resource DLL exists, LoadString(resource) is returned. - /// - private static unsafe string TryGetLocalizedNameByNativeResource(string filePath, int resource) - { - using (SafeLibraryHandle handle = Interop.Kernel32.LoadLibraryEx(filePath, IntPtr.Zero, Interop.Kernel32.LOAD_LIBRARY_AS_DATAFILE)) - { - if (!handle.IsInvalid) - { - const int LoadStringMaxLength = 500; - char* localizedResource = stackalloc char[LoadStringMaxLength]; - - int charsWritten = Interop.User32.LoadString(handle, (uint)resource, localizedResource, LoadStringMaxLength); - if (charsWritten != 0) - { - return new string(localizedResource, 0, charsWritten); - } - } - } - - return string.Empty; - } - - /// - /// Helper function for retrieving the DisplayName, StandardName, and DaylightName from the registry - /// - /// The function first checks the MUI_ key-values, and if they exist, it loads the strings from the MUI - /// resource dll(s). When the keys do not exist, the function falls back to reading from the standard - /// key-values - /// - private static void GetLocalizedNamesByRegistryKey(RegistryKey key, out string displayName, out string standardName, out string daylightName) - { - displayName = string.Empty; - standardName = string.Empty; - daylightName = string.Empty; - - // read the MUI_ registry keys - string displayNameMuiResource = key.GetValue(MuiDisplayValue, string.Empty) as string; - string standardNameMuiResource = key.GetValue(MuiStandardValue, string.Empty) as string; - string daylightNameMuiResource = key.GetValue(MuiDaylightValue, string.Empty) as string; - - // try to load the strings from the native resource DLL(s) - if (!string.IsNullOrEmpty(displayNameMuiResource)) - { - displayName = TryGetLocalizedNameByMuiNativeResource(displayNameMuiResource); - } - - if (!string.IsNullOrEmpty(standardNameMuiResource)) - { - standardName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); - } - - if (!string.IsNullOrEmpty(daylightNameMuiResource)) - { - daylightName = TryGetLocalizedNameByMuiNativeResource(daylightNameMuiResource); - } - - // fallback to using the standard registry keys - if (string.IsNullOrEmpty(displayName)) - { - displayName = key.GetValue(DisplayValue, string.Empty) as string; - } - if (string.IsNullOrEmpty(standardName)) - { - standardName = key.GetValue(StandardValue, string.Empty) as string; - } - if (string.IsNullOrEmpty(daylightName)) - { - daylightName = key.GetValue(DaylightValue, string.Empty) as string; - } - } - - /// - /// Helper function that takes a string representing a time_zone_name registry key name - /// and returns a TimeZoneInfo instance. - /// - private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, out TimeZoneInfo value, out Exception e) - { - e = null; - - // Standard Time Zone Registry Data - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // HKLM - // Software - // Microsoft - // Windows NT - // CurrentVersion - // Time Zones - // - // * STD, REG_SZ "Standard Time Name" - // (For OS installed zones, this will always be English) - // * MUI_STD, REG_SZ "@tzres.dll,-1234" - // Indirect string to localized resource for Standard Time, - // add "%windir%\system32\" after "@" - // * DLT, REG_SZ "Daylight Time Name" - // (For OS installed zones, this will always be English) - // * MUI_DLT, REG_SZ "@tzres.dll,-1234" - // Indirect string to localized resource for Daylight Time, - // add "%windir%\system32\" after "@" - // * Display, REG_SZ "Display Name like (GMT-8:00) Pacific Time..." - // * MUI_Display, REG_SZ "@tzres.dll,-1234" - // Indirect string to localized resource for the Display, - // add "%windir%\system32\" after "@" - // * TZI, REG_BINARY REG_TZI_FORMAT - // - using (RegistryKey key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id, writable: false)) - { - if (key == null) - { - value = null; - return TimeZoneInfoResult.TimeZoneNotFoundException; - } - - REG_TZI_FORMAT defaultTimeZoneInformation; - if (!TryGetTimeZoneEntryFromRegistry(key, TimeZoneInfoValue, out defaultTimeZoneInformation)) - { - // the registry value could not be cast to a byte array - value = null; - return TimeZoneInfoResult.InvalidTimeZoneException; - } - - AdjustmentRule[] adjustmentRules; - if (!TryCreateAdjustmentRules(id, defaultTimeZoneInformation, out adjustmentRules, out e, defaultTimeZoneInformation.Bias)) - { - value = null; - return TimeZoneInfoResult.InvalidTimeZoneException; - } - - GetLocalizedNamesByRegistryKey(key, out string displayName, out string standardName, out string daylightName); - - try - { - value = new TimeZoneInfo( - id, - new TimeSpan(0, -(defaultTimeZoneInformation.Bias), 0), - displayName, - standardName, - daylightName, - adjustmentRules, - disableDaylightSavingTime: false); - - return TimeZoneInfoResult.Success; - } - catch (ArgumentException ex) - { - // TimeZoneInfo constructor can throw ArgumentException and InvalidTimeZoneException - value = null; - e = ex; - return TimeZoneInfoResult.InvalidTimeZoneException; - } - catch (InvalidTimeZoneException ex) - { - // TimeZoneInfo constructor can throw ArgumentException and InvalidTimeZoneException - value = null; - e = ex; - return TimeZoneInfoResult.InvalidTimeZoneException; - } - } - } - } -} +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Security; +using System.Text; +using System.Threading; + +using Microsoft.Win32.SafeHandles; + +using Internal.Win32; +using Internal.Runtime.CompilerServices; + +using REG_TZI_FORMAT = Interop.Kernel32.REG_TZI_FORMAT; +using TIME_ZONE_INFORMATION = Interop.Kernel32.TIME_ZONE_INFORMATION; +using TIME_DYNAMIC_ZONE_INFORMATION = Interop.Kernel32.TIME_DYNAMIC_ZONE_INFORMATION; + +namespace System +{ + public sealed partial class TimeZoneInfo + { + // registry constants for the 'Time Zones' hive + // + private const string TimeZonesRegistryHive = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"; + private const string DisplayValue = "Display"; + private const string DaylightValue = "Dlt"; + private const string StandardValue = "Std"; + private const string MuiDisplayValue = "MUI_Display"; + private const string MuiDaylightValue = "MUI_Dlt"; + private const string MuiStandardValue = "MUI_Std"; + private const string TimeZoneInfoValue = "TZI"; + private const string FirstEntryValue = "FirstEntry"; + private const string LastEntryValue = "LastEntry"; + + private const int MaxKeyLength = 255; + + private sealed partial class CachedData + { + private static TimeZoneInfo GetCurrentOneYearLocal() + { + // load the data from the OS + TIME_ZONE_INFORMATION timeZoneInformation; + uint result = Interop.Kernel32.GetTimeZoneInformation(out timeZoneInformation); + return result == Interop.Kernel32.TIME_ZONE_ID_INVALID ? + CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId) : + GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled: false); + } + + private volatile OffsetAndRule? _oneYearLocalFromUtc; + + public OffsetAndRule GetOneYearLocalFromUtc(int year) + { + OffsetAndRule? oneYearLocFromUtc = _oneYearLocalFromUtc; + if (oneYearLocFromUtc == null || oneYearLocFromUtc.Year != year) + { + TimeZoneInfo currentYear = GetCurrentOneYearLocal(); + AdjustmentRule? rule = currentYear._adjustmentRules == null ? null : currentYear._adjustmentRules[0]; + oneYearLocFromUtc = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule); + _oneYearLocalFromUtc = oneYearLocFromUtc; + } + return oneYearLocFromUtc; + } + } + + private sealed class OffsetAndRule + { + public readonly int Year; + public readonly TimeSpan Offset; + public readonly AdjustmentRule? Rule; + + public OffsetAndRule(int year, TimeSpan offset, AdjustmentRule? rule) + { + Year = year; + Offset = offset; + Rule = rule; + } + } + + /// + /// Returns a cloned array of AdjustmentRule objects + /// + public AdjustmentRule[] GetAdjustmentRules() + { + if (_adjustmentRules == null) + { + return Array.Empty(); + } + + return (AdjustmentRule[])_adjustmentRules.Clone(); + } + + private static void PopulateAllSystemTimeZones(CachedData cachedData) + { + Debug.Assert(Monitor.IsEntered(cachedData)); + + using (RegistryKey? reg = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive, writable: false)) + { + if (reg != null) + { + foreach (string keyName in reg.GetSubKeyNames()) + { + TryGetTimeZone(keyName, false, out _, out _, cachedData); // populate the cache + } + } + } + } + + private TimeZoneInfo(in TIME_ZONE_INFORMATION zone, bool dstDisabled) + { + string standardName = zone.GetStandardName(); + if (standardName.Length == 0) + { + _id = LocalId; // the ID must contain at least 1 character - initialize _id to "Local" + } + else + { + _id = standardName; + } + _baseUtcOffset = new TimeSpan(0, -(zone.Bias), 0); + + if (!dstDisabled) + { + // only create the adjustment rule if DST is enabled + REG_TZI_FORMAT regZone = new REG_TZI_FORMAT(zone); + AdjustmentRule? rule = CreateAdjustmentRuleFromTimeZoneInformation(regZone, DateTime.MinValue.Date, DateTime.MaxValue.Date, zone.Bias); + if (rule != null) + { + _adjustmentRules = new[] { rule }; + } + } + + ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out _supportsDaylightSavingTime); + _displayName = standardName; + _standardDisplayName = standardName; + _daylightDisplayName = zone.GetDaylightName(); + } + + /// + /// Helper function to check if the current TimeZoneInformation struct does not support DST. + /// This check returns true when the DaylightDate == StandardDate. + /// This check is only meant to be used for "Local". + /// + private static bool CheckDaylightSavingTimeNotSupported(in TIME_ZONE_INFORMATION timeZone) => + timeZone.DaylightDate.Equals(timeZone.StandardDate); + + /// + /// Converts a REG_TZI_FORMAT struct to an AdjustmentRule. + /// + private static AdjustmentRule? CreateAdjustmentRuleFromTimeZoneInformation(in REG_TZI_FORMAT timeZoneInformation, DateTime startDate, DateTime endDate, int defaultBaseUtcOffset) + { + bool supportsDst = timeZoneInformation.StandardDate.Month != 0; + + if (!supportsDst) + { + if (timeZoneInformation.Bias == defaultBaseUtcOffset) + { + // this rule will not contain any information to be used to adjust dates. just ignore it + return null; + } + + return AdjustmentRule.CreateAdjustmentRule( + startDate, + endDate, + TimeSpan.Zero, // no daylight saving transition + TransitionTime.CreateFixedDateRule(DateTime.MinValue, 1, 1), + TransitionTime.CreateFixedDateRule(DateTime.MinValue.AddMilliseconds(1), 1, 1), + new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0), // Bias delta is all what we need from this rule + noDaylightTransitions: false); + } + + // + // Create an AdjustmentRule with TransitionTime objects + // + TransitionTime daylightTransitionStart; + if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionStart, readStartDate: true)) + { + return null; + } + + TransitionTime daylightTransitionEnd; + if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionEnd, readStartDate: false)) + { + return null; + } + + if (daylightTransitionStart.Equals(daylightTransitionEnd)) + { + // this happens when the time zone does support DST but the OS has DST disabled + return null; + } + + return AdjustmentRule.CreateAdjustmentRule( + startDate, + endDate, + new TimeSpan(0, -timeZoneInformation.DaylightBias, 0), + daylightTransitionStart, + daylightTransitionEnd, + new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0), + noDaylightTransitions: false); + } + + /// + /// Helper function that searches the registry for a time zone entry + /// that matches the TimeZoneInformation struct. + /// + private static string? FindIdFromTimeZoneInformation(in TIME_ZONE_INFORMATION timeZone, out bool dstDisabled) + { + dstDisabled = false; + + using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive, writable: false)) + { + if (key == null) + { + return null; + } + + foreach (string keyName in key.GetSubKeyNames()) + { + if (TryCompareTimeZoneInformationToRegistry(timeZone, keyName, out dstDisabled)) + { + return keyName; + } + } + } + + return null; + } + + /// + /// Helper function for retrieving the local system time zone. + /// May throw COMException, TimeZoneNotFoundException, InvalidTimeZoneException. + /// Assumes cachedData lock is taken. + /// + /// A new TimeZoneInfo instance. + private static TimeZoneInfo GetLocalTimeZone(CachedData cachedData) + { + Debug.Assert(Monitor.IsEntered(cachedData)); + + // + // Try using the "kernel32!GetDynamicTimeZoneInformation" API to get the "id" + // + var dynamicTimeZoneInformation = new TIME_DYNAMIC_ZONE_INFORMATION(); + + // call kernel32!GetDynamicTimeZoneInformation... + uint result = Interop.Kernel32.GetDynamicTimeZoneInformation(out dynamicTimeZoneInformation); + if (result == Interop.Kernel32.TIME_ZONE_ID_INVALID) + { + // return a dummy entry + return CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId); + } + + // check to see if we can use the key name returned from the API call + string dynamicTimeZoneKeyName = dynamicTimeZoneInformation.GetTimeZoneKeyName(); + if (dynamicTimeZoneKeyName.Length != 0) + { + if (TryGetTimeZone(dynamicTimeZoneKeyName, dynamicTimeZoneInformation.DynamicDaylightTimeDisabled != 0, out TimeZoneInfo? zone, out _, cachedData) == TimeZoneInfoResult.Success) + { + // successfully loaded the time zone from the registry + return zone!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + } + } + + var timeZoneInformation = new TIME_ZONE_INFORMATION(dynamicTimeZoneInformation); + + // the key name was not returned or it pointed to a bogus entry - search for the entry ourselves + string? id = FindIdFromTimeZoneInformation(timeZoneInformation, out bool dstDisabled); + + if (id != null) + { + if (TryGetTimeZone(id, dstDisabled, out TimeZoneInfo? zone, out _, cachedData) == TimeZoneInfoResult.Success) + { + // successfully loaded the time zone from the registry + return zone!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + } + } + + // We could not find the data in the registry. Fall back to using + // the data from the Win32 API + return GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled); + } + + /// + /// Helper function used by 'GetLocalTimeZone()' - this function wraps a bunch of + /// try/catch logic for handling the TimeZoneInfo private constructor that takes + /// a TIME_ZONE_INFORMATION structure. + /// + private static TimeZoneInfo GetLocalTimeZoneFromWin32Data(in TIME_ZONE_INFORMATION timeZoneInformation, bool dstDisabled) + { + // first try to create the TimeZoneInfo with the original 'dstDisabled' flag + try + { + return new TimeZoneInfo(timeZoneInformation, dstDisabled); + } + catch (ArgumentException) { } + catch (InvalidTimeZoneException) { } + + // if 'dstDisabled' was false then try passing in 'true' as a last ditch effort + if (!dstDisabled) + { + try + { + return new TimeZoneInfo(timeZoneInformation, dstDisabled: true); + } + catch (ArgumentException) { } + catch (InvalidTimeZoneException) { } + } + + // the data returned from Windows is completely bogus; return a dummy entry + return CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId); + } + + /// + /// Helper function for retrieving a TimeZoneInfo object by time_zone_name. + /// This function wraps the logic necessary to keep the private + /// SystemTimeZones cache in working order + /// + /// This function will either return a valid TimeZoneInfo instance or + /// it will throw 'InvalidTimeZoneException' / 'TimeZoneNotFoundException'. + /// + public static TimeZoneInfo FindSystemTimeZoneById(string id) + { + // Special case for Utc as it will not exist in the dictionary with the rest + // of the system time zones. There is no need to do this check for Local.Id + // since Local is a real time zone that exists in the dictionary cache + if (string.Equals(id, UtcId, StringComparison.OrdinalIgnoreCase)) + { + return Utc; + } + + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + if (id.Length == 0 || id.Length > MaxKeyLength || id.Contains('\0')) + { + throw new TimeZoneNotFoundException(SR.Format(SR.TimeZoneNotFound_MissingData, id)); + } + + TimeZoneInfo? value; + Exception? e; + + TimeZoneInfoResult result; + + CachedData cachedData = s_cachedData; + + lock (cachedData) + { + result = TryGetTimeZone(id, false, out value, out e, cachedData); + } + + if (result == TimeZoneInfoResult.Success) + { + return value!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + } + else if (result == TimeZoneInfoResult.InvalidTimeZoneException) + { + throw new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_InvalidRegistryData, id), e); + } + else if (result == TimeZoneInfoResult.SecurityException) + { + throw new SecurityException(SR.Format(SR.Security_CannotReadRegistryData, id), e); + } + else + { + throw new TimeZoneNotFoundException(SR.Format(SR.TimeZoneNotFound_MissingData, id), e); + } + } + + // DateTime.Now fast path that avoids allocating an historically accurate TimeZoneInfo.Local and just creates a 1-year (current year) accurate time zone + internal static TimeSpan GetDateTimeNowUtcOffsetFromUtc(DateTime time, out bool isAmbiguousLocalDst) + { + bool isDaylightSavings = false; + isAmbiguousLocalDst = false; + TimeSpan baseOffset; + int timeYear = time.Year; + + OffsetAndRule match = s_cachedData.GetOneYearLocalFromUtc(timeYear); + baseOffset = match.Offset; + + if (match.Rule != null) + { + baseOffset = baseOffset + match.Rule.BaseUtcOffsetDelta; + if (match.Rule.HasDaylightSaving) + { + isDaylightSavings = GetIsDaylightSavingsFromUtc(time, timeYear, match.Offset, match.Rule, null, out isAmbiguousLocalDst, Local); + baseOffset += (isDaylightSavings ? match.Rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); + } + } + return baseOffset; + } + + /// + /// Converts a REG_TZI_FORMAT struct to a TransitionTime + /// - When the argument 'readStart' is true the corresponding daylightTransitionTimeStart field is read + /// - When the argument 'readStart' is false the corresponding dayightTransitionTimeEnd field is read + /// + private static bool TransitionTimeFromTimeZoneInformation(in REG_TZI_FORMAT timeZoneInformation, out TransitionTime transitionTime, bool readStartDate) + { + // + // SYSTEMTIME - + // + // If the time zone does not support daylight saving time or if the caller needs + // to disable daylight saving time, the wMonth member in the SYSTEMTIME structure + // must be zero. If this date is specified, the DaylightDate value in the + // TIME_ZONE_INFORMATION structure must also be specified. Otherwise, the system + // assumes the time zone data is invalid and no changes will be applied. + // + bool supportsDst = (timeZoneInformation.StandardDate.Month != 0); + + if (!supportsDst) + { + transitionTime = default; + return false; + } + + // + // SYSTEMTIME - + // + // * FixedDateRule - + // If the Year member is not zero, the transition date is absolute; it will only occur one time + // + // * FloatingDateRule - + // To select the correct day in the month, set the Year member to zero, the Hour and Minute + // members to the transition time, the DayOfWeek member to the appropriate weekday, and the + // Day member to indicate the occurence of the day of the week within the month (first through fifth). + // + // Using this notation, specify the 2:00a.m. on the first Sunday in April as follows: + // Hour = 2, + // Month = 4, + // DayOfWeek = 0, + // Day = 1. + // + // Specify 2:00a.m. on the last Thursday in October as follows: + // Hour = 2, + // Month = 10, + // DayOfWeek = 4, + // Day = 5. + // + if (readStartDate) + { + // + // read the "daylightTransitionStart" + // + if (timeZoneInformation.DaylightDate.Year == 0) + { + transitionTime = TransitionTime.CreateFloatingDateRule( + new DateTime(1, /* year */ + 1, /* month */ + 1, /* day */ + timeZoneInformation.DaylightDate.Hour, + timeZoneInformation.DaylightDate.Minute, + timeZoneInformation.DaylightDate.Second, + timeZoneInformation.DaylightDate.Milliseconds), + timeZoneInformation.DaylightDate.Month, + timeZoneInformation.DaylightDate.Day, /* Week 1-5 */ + (DayOfWeek)timeZoneInformation.DaylightDate.DayOfWeek); + } + else + { + transitionTime = TransitionTime.CreateFixedDateRule( + new DateTime(1, /* year */ + 1, /* month */ + 1, /* day */ + timeZoneInformation.DaylightDate.Hour, + timeZoneInformation.DaylightDate.Minute, + timeZoneInformation.DaylightDate.Second, + timeZoneInformation.DaylightDate.Milliseconds), + timeZoneInformation.DaylightDate.Month, + timeZoneInformation.DaylightDate.Day); + } + } + else + { + // + // read the "daylightTransitionEnd" + // + if (timeZoneInformation.StandardDate.Year == 0) + { + transitionTime = TransitionTime.CreateFloatingDateRule( + new DateTime(1, /* year */ + 1, /* month */ + 1, /* day */ + timeZoneInformation.StandardDate.Hour, + timeZoneInformation.StandardDate.Minute, + timeZoneInformation.StandardDate.Second, + timeZoneInformation.StandardDate.Milliseconds), + timeZoneInformation.StandardDate.Month, + timeZoneInformation.StandardDate.Day, /* Week 1-5 */ + (DayOfWeek)timeZoneInformation.StandardDate.DayOfWeek); + } + else + { + transitionTime = TransitionTime.CreateFixedDateRule( + new DateTime(1, /* year */ + 1, /* month */ + 1, /* day */ + timeZoneInformation.StandardDate.Hour, + timeZoneInformation.StandardDate.Minute, + timeZoneInformation.StandardDate.Second, + timeZoneInformation.StandardDate.Milliseconds), + timeZoneInformation.StandardDate.Month, + timeZoneInformation.StandardDate.Day); + } + } + + return true; + } + + /// + /// Helper function that takes: + /// 1. A string representing a time_zone_name registry key name. + /// 2. A REG_TZI_FORMAT struct containing the default rule. + /// 3. An AdjustmentRule[] out-parameter. + /// + private static bool TryCreateAdjustmentRules(string id, in REG_TZI_FORMAT defaultTimeZoneInformation, out AdjustmentRule[]? rules, out Exception? e, int defaultBaseUtcOffset) + { + rules = null; + e = null; + + try + { + // Optional, Dynamic Time Zone Registry Data + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + // + // HKLM + // Software + // Microsoft + // Windows NT + // CurrentVersion + // Time Zones + // + // Dynamic DST + // * "FirstEntry" REG_DWORD "1980" + // First year in the table. If the current year is less than this value, + // this entry will be used for DST boundaries + // * "LastEntry" REG_DWORD "2038" + // Last year in the table. If the current year is greater than this value, + // this entry will be used for DST boundaries" + // * "" REG_BINARY REG_TZI_FORMAT + // * "" REG_BINARY REG_TZI_FORMAT + // * "" REG_BINARY REG_TZI_FORMAT + // + using (RegistryKey? dynamicKey = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id + "\\Dynamic DST", writable: false)) + { + if (dynamicKey == null) + { + AdjustmentRule? rule = CreateAdjustmentRuleFromTimeZoneInformation( + defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); + if (rule != null) + { + rules = new[] { rule }; + } + return true; + } + + // + // loop over all of the "\Dynamic DST" hive entries + // + // read FirstEntry {MinValue - (year1, 12, 31)} + // read MiddleEntry {(yearN, 1, 1) - (yearN, 12, 31)} + // read LastEntry {(yearN, 1, 1) - MaxValue } + + // read the FirstEntry and LastEntry key values (ex: "1980", "2038") + int first = (int)dynamicKey.GetValue(FirstEntryValue, -1)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 + int last = (int)dynamicKey.GetValue(LastEntryValue, -1)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 + + if (first == -1 || last == -1 || first > last) + { + return false; + } + + // read the first year entry + REG_TZI_FORMAT dtzi; + + if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, first.ToString(CultureInfo.InvariantCulture), out dtzi)) + { + return false; + } + + if (first == last) + { + // there is just 1 dynamic rule for this time zone. + AdjustmentRule? rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset); + if (rule != null) + { + rules = new[] { rule }; + } + return true; + } + + List rulesList = new List(1); + + // there are more than 1 dynamic rules for this time zone. + AdjustmentRule? firstRule = CreateAdjustmentRuleFromTimeZoneInformation( + dtzi, + DateTime.MinValue.Date, // MinValue + new DateTime(first, 12, 31), // December 31, + defaultBaseUtcOffset); + + if (firstRule != null) + { + rulesList.Add(firstRule); + } + + // read the middle year entries + for (int i = first + 1; i < last; i++) + { + if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, i.ToString(CultureInfo.InvariantCulture), out dtzi)) + { + return false; + } + AdjustmentRule? middleRule = CreateAdjustmentRuleFromTimeZoneInformation( + dtzi, + new DateTime(i, 1, 1), // January 01, + new DateTime(i, 12, 31), // December 31, + defaultBaseUtcOffset); + + if (middleRule != null) + { + rulesList.Add(middleRule); + } + } + + // read the last year entry + if (!TryGetTimeZoneEntryFromRegistry(dynamicKey, last.ToString(CultureInfo.InvariantCulture), out dtzi)) + { + return false; + } + AdjustmentRule? lastRule = CreateAdjustmentRuleFromTimeZoneInformation( + dtzi, + new DateTime(last, 1, 1), // January 01, + DateTime.MaxValue.Date, // MaxValue + defaultBaseUtcOffset); + + if (lastRule != null) + { + rulesList.Add(lastRule); + } + + // convert the List to an AdjustmentRule array + if (rulesList.Count != 0) + { + rules = rulesList.ToArray(); + } + } // end of: using (RegistryKey dynamicKey... + } + catch (InvalidCastException ex) + { + // one of the RegistryKey.GetValue calls could not be cast to an expected value type + e = ex; + return false; + } + catch (ArgumentOutOfRangeException ex) + { + e = ex; + return false; + } + catch (ArgumentException ex) + { + e = ex; + return false; + } + return true; + } + + private static unsafe bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi) + { + if (!(key.GetValue(name, null) is byte[] regValue) || regValue.Length != sizeof(REG_TZI_FORMAT)) + { + dtzi = default; + return false; + } + fixed (byte * pBytes = ®Value[0]) + dtzi = *(REG_TZI_FORMAT *)pBytes; + return true; + } + + /// + /// Helper function that compares the StandardBias and StandardDate portion a + /// TimeZoneInformation struct to a time zone registry entry. + /// + private static bool TryCompareStandardDate(in TIME_ZONE_INFORMATION timeZone, in REG_TZI_FORMAT registryTimeZoneInfo) => + timeZone.Bias == registryTimeZoneInfo.Bias && + timeZone.StandardBias == registryTimeZoneInfo.StandardBias && + timeZone.StandardDate.Equals(registryTimeZoneInfo.StandardDate); + + /// + /// Helper function that compares a TimeZoneInformation struct to a time zone registry entry. + /// + private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMATION timeZone, string id, out bool dstDisabled) + { + dstDisabled = false; + + using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id, writable: false)) + { + if (key == null) + { + return false; + } + + REG_TZI_FORMAT registryTimeZoneInfo; + if (!TryGetTimeZoneEntryFromRegistry(key, TimeZoneInfoValue, out registryTimeZoneInfo)) + { + return false; + } + + // + // first compare the bias and standard date information between the data from the Win32 API + // and the data from the registry... + // + bool result = TryCompareStandardDate(timeZone, registryTimeZoneInfo); + + if (!result) + { + return false; + } + + result = dstDisabled || CheckDaylightSavingTimeNotSupported(timeZone) || + // + // since Daylight Saving Time is not "disabled", do a straight comparision between + // the Win32 API data and the registry data ... + // + (timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias && + timeZone.DaylightDate.Equals(registryTimeZoneInfo.DaylightDate)); + + // Finally compare the "StandardName" string value... + // + // we do not compare "DaylightName" as this TimeZoneInformation field may contain + // either "StandardName" or "DaylightName" depending on the time of year and current machine settings + // + if (result) + { + string? registryStandardName = key.GetValue(StandardValue, string.Empty) as string; + result = string.Equals(registryStandardName, timeZone.GetStandardName(), StringComparison.Ordinal); + } + return result; + } + } + + /// + /// Helper function for retrieving a localized string resource via MUI. + /// The function expects a string in the form: "@resource.dll, -123" + /// + /// "resource.dll" is a language-neutral portable executable (LNPE) file in + /// the %windir%\system32 directory. The OS is queried to find the best-fit + /// localized resource file for this LNPE (ex: %windir%\system32\en-us\resource.dll.mui). + /// If a localized resource file exists, we LoadString resource ID "123" and + /// return it to our caller. + /// + private static string TryGetLocalizedNameByMuiNativeResource(string resource) + { + if (string.IsNullOrEmpty(resource)) + { + return string.Empty; + } + + // parse "@tzres.dll, -100" + // + // filePath = "C:\Windows\System32\tzres.dll" + // resourceId = -100 + // + string[] resources = resource.Split(','); + if (resources.Length != 2) + { + return string.Empty; + } + + string filePath; + int resourceId; + + // get the path to Windows\System32 + string system32 = Environment.SystemDirectory; + + // trim the string "@tzres.dll" => "tzres.dll" + string tzresDll = resources[0].TrimStart('@'); + + try + { + filePath = Path.Combine(system32, tzresDll); + } + catch (ArgumentException) + { + // there were probably illegal characters in the path + return string.Empty; + } + + if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out resourceId)) + { + return string.Empty; + } + resourceId = -resourceId; + + try + { + unsafe + { + char* fileMuiPath = stackalloc char[Interop.Kernel32.MAX_PATH]; + int fileMuiPathLength = Interop.Kernel32.MAX_PATH; + int languageLength = 0; + long enumerator = 0; + + bool succeeded = Interop.Kernel32.GetFileMUIPath( + Interop.Kernel32.MUI_PREFERRED_UI_LANGUAGES, + filePath, null /* language */, ref languageLength, + fileMuiPath, ref fileMuiPathLength, ref enumerator); + return succeeded ? + TryGetLocalizedNameByNativeResource(new string(fileMuiPath, 0, fileMuiPathLength), resourceId) : + string.Empty; + } + } + catch (EntryPointNotFoundException) + { + return string.Empty; + } + } + + /// + /// Helper function for retrieving a localized string resource via a native resource DLL. + /// The function expects a string in the form: "C:\Windows\System32\en-us\resource.dll" + /// + /// "resource.dll" is a language-specific resource DLL. + /// If the localized resource DLL exists, LoadString(resource) is returned. + /// + private static unsafe string TryGetLocalizedNameByNativeResource(string filePath, int resource) + { + using (SafeLibraryHandle handle = Interop.Kernel32.LoadLibraryEx(filePath, IntPtr.Zero, Interop.Kernel32.LOAD_LIBRARY_AS_DATAFILE)) + { + if (!handle.IsInvalid) + { + const int LoadStringMaxLength = 500; + char* localizedResource = stackalloc char[LoadStringMaxLength]; + + int charsWritten = Interop.User32.LoadString(handle, (uint)resource, localizedResource, LoadStringMaxLength); + if (charsWritten != 0) + { + return new string(localizedResource, 0, charsWritten); + } + } + } + + return string.Empty; + } + + /// + /// Helper function for retrieving the DisplayName, StandardName, and DaylightName from the registry + /// + /// The function first checks the MUI_ key-values, and if they exist, it loads the strings from the MUI + /// resource dll(s). When the keys do not exist, the function falls back to reading from the standard + /// key-values + /// + private static void GetLocalizedNamesByRegistryKey(RegistryKey key, out string? displayName, out string? standardName, out string? daylightName) + { + displayName = string.Empty; + standardName = string.Empty; + daylightName = string.Empty; + + // read the MUI_ registry keys + string? displayNameMuiResource = key.GetValue(MuiDisplayValue, string.Empty) as string; + string? standardNameMuiResource = key.GetValue(MuiStandardValue, string.Empty) as string; + string? daylightNameMuiResource = key.GetValue(MuiDaylightValue, string.Empty) as string; + + // try to load the strings from the native resource DLL(s) + if (!string.IsNullOrEmpty(displayNameMuiResource)) + { + displayName = TryGetLocalizedNameByMuiNativeResource(displayNameMuiResource); + } + + if (!string.IsNullOrEmpty(standardNameMuiResource)) + { + standardName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); + } + + if (!string.IsNullOrEmpty(daylightNameMuiResource)) + { + daylightName = TryGetLocalizedNameByMuiNativeResource(daylightNameMuiResource); + } + + // fallback to using the standard registry keys + if (string.IsNullOrEmpty(displayName)) + { + displayName = key.GetValue(DisplayValue, string.Empty) as string; + } + if (string.IsNullOrEmpty(standardName)) + { + standardName = key.GetValue(StandardValue, string.Empty) as string; + } + if (string.IsNullOrEmpty(daylightName)) + { + daylightName = key.GetValue(DaylightValue, string.Empty) as string; + } + } + + /// + /// Helper function that takes a string representing a time_zone_name registry key name + /// and returns a TimeZoneInfo instance. + /// + private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, out TimeZoneInfo? value, out Exception? e) + { + e = null; + + // Standard Time Zone Registry Data + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + // HKLM + // Software + // Microsoft + // Windows NT + // CurrentVersion + // Time Zones + // + // * STD, REG_SZ "Standard Time Name" + // (For OS installed zones, this will always be English) + // * MUI_STD, REG_SZ "@tzres.dll,-1234" + // Indirect string to localized resource for Standard Time, + // add "%windir%\system32\" after "@" + // * DLT, REG_SZ "Daylight Time Name" + // (For OS installed zones, this will always be English) + // * MUI_DLT, REG_SZ "@tzres.dll,-1234" + // Indirect string to localized resource for Daylight Time, + // add "%windir%\system32\" after "@" + // * Display, REG_SZ "Display Name like (GMT-8:00) Pacific Time..." + // * MUI_Display, REG_SZ "@tzres.dll,-1234" + // Indirect string to localized resource for the Display, + // add "%windir%\system32\" after "@" + // * TZI, REG_BINARY REG_TZI_FORMAT + // + using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(TimeZonesRegistryHive + "\\" + id, writable: false)) + { + if (key == null) + { + value = null; + return TimeZoneInfoResult.TimeZoneNotFoundException; + } + + REG_TZI_FORMAT defaultTimeZoneInformation; + if (!TryGetTimeZoneEntryFromRegistry(key, TimeZoneInfoValue, out defaultTimeZoneInformation)) + { + // the registry value could not be cast to a byte array + value = null; + return TimeZoneInfoResult.InvalidTimeZoneException; + } + + AdjustmentRule[]? adjustmentRules; + if (!TryCreateAdjustmentRules(id, defaultTimeZoneInformation, out adjustmentRules, out e, defaultTimeZoneInformation.Bias)) + { + value = null; + return TimeZoneInfoResult.InvalidTimeZoneException; + } + + GetLocalizedNamesByRegistryKey(key, out string? displayName, out string? standardName, out string? daylightName); + + try + { + value = new TimeZoneInfo( + id, + new TimeSpan(0, -(defaultTimeZoneInformation.Bias), 0), + displayName, + standardName, + daylightName, + adjustmentRules, + disableDaylightSavingTime: false); + + return TimeZoneInfoResult.Success; + } + catch (ArgumentException ex) + { + // TimeZoneInfo constructor can throw ArgumentException and InvalidTimeZoneException + value = null; + e = ex; + return TimeZoneInfoResult.InvalidTimeZoneException; + } + catch (InvalidTimeZoneException ex) + { + // TimeZoneInfo constructor can throw ArgumentException and InvalidTimeZoneException + value = null; + e = ex; + return TimeZoneInfoResult.InvalidTimeZoneException; + } + } + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs index c7090d55dd66..28775985e8bc 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs @@ -1,2058 +1,2060 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.Serialization; -using System.Threading; - -namespace System -{ - // - // DateTime uses TimeZoneInfo under the hood for IsDaylightSavingTime, IsAmbiguousTime, and GetUtcOffset. - // These TimeZoneInfo APIs can throw ArgumentException when an Invalid-Time is passed in. To avoid this - // unwanted behavior in DateTime public APIs, DateTime internally passes the - // TimeZoneInfoOptions.NoThrowOnInvalidTime flag to internal TimeZoneInfo APIs. - // - // In the future we can consider exposing similar options on the public TimeZoneInfo APIs if there is enough - // demand for this alternate behavior. - // - [Flags] - internal enum TimeZoneInfoOptions - { - None = 1, - NoThrowOnInvalidTime = 2 - }; - - [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback - { - private enum TimeZoneInfoResult - { - Success = 0, - TimeZoneNotFoundException = 1, - InvalidTimeZoneException = 2, - SecurityException = 3 - }; - - private readonly string _id; - private readonly string _displayName; - private readonly string _standardDisplayName; - private readonly string _daylightDisplayName; - private readonly TimeSpan _baseUtcOffset; - private readonly bool _supportsDaylightSavingTime; - private readonly AdjustmentRule[] _adjustmentRules; - - // constants for TimeZoneInfo.Local and TimeZoneInfo.Utc - private const string UtcId = "UTC"; - private const string LocalId = "Local"; - - private static readonly TimeZoneInfo s_utcTimeZone = CreateCustomTimeZone(UtcId, TimeSpan.Zero, UtcId, UtcId); - - private static CachedData s_cachedData = new CachedData(); - - // - // All cached data are encapsulated in a helper class to allow consistent view even when the data are refreshed using ClearCachedData() - // - // For example, TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData. Without the consistent snapshot, - // there is a chance that the internal ConvertTime calls will throw since 'source' won't be reference equal to the new TimeZoneInfo.Local. - // - private sealed partial class CachedData - { - private volatile TimeZoneInfo _localTimeZone; - - private TimeZoneInfo CreateLocal() - { - lock (this) - { - TimeZoneInfo timeZone = _localTimeZone; - if (timeZone == null) - { - timeZone = GetLocalTimeZone(this); - - // this step is to break the reference equality - // between TimeZoneInfo.Local and a second time zone - // such as "Pacific Standard Time" - timeZone = new TimeZoneInfo( - timeZone._id, - timeZone._baseUtcOffset, - timeZone._displayName, - timeZone._standardDisplayName, - timeZone._daylightDisplayName, - timeZone._adjustmentRules, - disableDaylightSavingTime: false); - - _localTimeZone = timeZone; - } - return timeZone; - } - } - - public TimeZoneInfo Local - { - get - { - TimeZoneInfo timeZone = _localTimeZone; - if (timeZone == null) - { - timeZone = CreateLocal(); - } - return timeZone; - } - } - - /// - /// Helper function that returns the corresponding DateTimeKind for this TimeZoneInfo. - /// - public DateTimeKind GetCorrespondingKind(TimeZoneInfo timeZone) - { - // We check reference equality to see if 'this' is the same as - // TimeZoneInfo.Local or TimeZoneInfo.Utc. This check is needed to - // support setting the DateTime Kind property to 'Local' or - // 'Utc' on the ConverTime(...) return value. - // - // Using reference equality instead of value equality was a - // performance based design compromise. The reference equality - // has much greater performance, but it reduces the number of - // returned DateTime's that can be properly set as 'Local' or 'Utc'. - // - // For example, the user could be converting to the TimeZoneInfo returned - // by FindSystemTimeZoneById("Pacific Standard Time") and their local - // machine may be in Pacific time. If we used value equality to determine - // the corresponding Kind then this conversion would be tagged as 'Local'; - // where as we are currently tagging the returned DateTime as 'Unspecified' - // in this example. Only when the user passes in TimeZoneInfo.Local or - // TimeZoneInfo.Utc to the ConvertTime(...) methods will this check succeed. - // - return - ReferenceEquals(timeZone, s_utcTimeZone) ? DateTimeKind.Utc : - ReferenceEquals(timeZone, _localTimeZone) ? DateTimeKind.Local : - DateTimeKind.Unspecified; - } - - public Dictionary _systemTimeZones; - public ReadOnlyCollection _readOnlySystemTimeZones; - public bool _allSystemTimeZonesRead; - }; - - // used by GetUtcOffsetFromUtc (DateTime.Now, DateTime.ToLocalTime) for max/min whole-day range checks - private static readonly DateTime s_maxDateOnly = new DateTime(9999, 12, 31); - private static readonly DateTime s_minDateOnly = new DateTime(1, 1, 2); - - public string Id => _id; - - public string DisplayName => _displayName ?? string.Empty; - - public string StandardName => _standardDisplayName ?? string.Empty; - - public string DaylightName => _daylightDisplayName ?? string.Empty; - - public TimeSpan BaseUtcOffset => _baseUtcOffset; - - public bool SupportsDaylightSavingTime => _supportsDaylightSavingTime; - - /// - /// Returns an array of TimeSpan objects representing all of - /// possible UTC offset values for this ambiguous time. - /// - public TimeSpan[] GetAmbiguousTimeOffsets(DateTimeOffset dateTimeOffset) - { - if (!SupportsDaylightSavingTime) - { - throw new ArgumentException(SR.Argument_DateTimeOffsetIsNotAmbiguous, nameof(dateTimeOffset)); - } - - DateTime adjustedTime = ConvertTime(dateTimeOffset, this).DateTime; - - bool isAmbiguous = false; - int? ruleIndex; - AdjustmentRule rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime, out ruleIndex); - if (rule != null && rule.HasDaylightSaving) - { - DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); - isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime); - } - - if (!isAmbiguous) - { - throw new ArgumentException(SR.Argument_DateTimeOffsetIsNotAmbiguous, nameof(dateTimeOffset)); - } - - // the passed in dateTime is ambiguous in this TimeZoneInfo instance - TimeSpan[] timeSpans = new TimeSpan[2]; - - TimeSpan actualUtcOffset = _baseUtcOffset + rule.BaseUtcOffsetDelta; - - // the TimeSpan array must be sorted from least to greatest - if (rule.DaylightDelta > TimeSpan.Zero) - { - timeSpans[0] = actualUtcOffset; // FUTURE: + rule.StandardDelta; - timeSpans[1] = actualUtcOffset + rule.DaylightDelta; - } - else - { - timeSpans[0] = actualUtcOffset + rule.DaylightDelta; - timeSpans[1] = actualUtcOffset; // FUTURE: + rule.StandardDelta; - } - return timeSpans; - } - - /// - /// Returns an array of TimeSpan objects representing all of - /// possible UTC offset values for this ambiguous time. - /// - public TimeSpan[] GetAmbiguousTimeOffsets(DateTime dateTime) - { - if (!SupportsDaylightSavingTime) - { - throw new ArgumentException(SR.Argument_DateTimeIsNotAmbiguous, nameof(dateTime)); - } - - DateTime adjustedTime; - if (dateTime.Kind == DateTimeKind.Local) - { - CachedData cachedData = s_cachedData; - adjustedTime = ConvertTime(dateTime, cachedData.Local, this, TimeZoneInfoOptions.None, cachedData); - } - else if (dateTime.Kind == DateTimeKind.Utc) - { - CachedData cachedData = s_cachedData; - adjustedTime = ConvertTime(dateTime, s_utcTimeZone, this, TimeZoneInfoOptions.None, cachedData); - } - else - { - adjustedTime = dateTime; - } - - bool isAmbiguous = false; - int? ruleIndex; - AdjustmentRule rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime, out ruleIndex); - if (rule != null && rule.HasDaylightSaving) - { - DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); - isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime); - } - - if (!isAmbiguous) - { - throw new ArgumentException(SR.Argument_DateTimeIsNotAmbiguous, nameof(dateTime)); - } - - // the passed in dateTime is ambiguous in this TimeZoneInfo instance - TimeSpan[] timeSpans = new TimeSpan[2]; - TimeSpan actualUtcOffset = _baseUtcOffset + rule.BaseUtcOffsetDelta; - - // the TimeSpan array must be sorted from least to greatest - if (rule.DaylightDelta > TimeSpan.Zero) - { - timeSpans[0] = actualUtcOffset; // FUTURE: + rule.StandardDelta; - timeSpans[1] = actualUtcOffset + rule.DaylightDelta; - } - else - { - timeSpans[0] = actualUtcOffset + rule.DaylightDelta; - timeSpans[1] = actualUtcOffset; // FUTURE: + rule.StandardDelta; - } - return timeSpans; - } - - // note the time is already adjusted - private AdjustmentRule GetAdjustmentRuleForAmbiguousOffsets(DateTime adjustedTime, out int? ruleIndex) - { - AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime, out ruleIndex); - if (rule != null && rule.NoDaylightTransitions && !rule.HasDaylightSaving) - { - // When using NoDaylightTransitions rules, each rule is only for one offset. - // When looking for the Daylight savings rules, and we found the non-DST rule, - // then we get the rule right before this rule. - return GetPreviousAdjustmentRule(rule, ruleIndex); - } - - return rule; - } - - /// - /// Gets the AdjustmentRule that is immediately preceding the specified rule. - /// If the specified rule is the first AdjustmentRule, or it isn't in _adjustmentRules, - /// then the specified rule is returned. - /// - private AdjustmentRule GetPreviousAdjustmentRule(AdjustmentRule rule, int? ruleIndex) - { - Debug.Assert(rule.NoDaylightTransitions, "GetPreviousAdjustmentRule should only be used with NoDaylightTransitions rules."); - - if (ruleIndex.HasValue && 0 < ruleIndex.GetValueOrDefault() && ruleIndex.GetValueOrDefault() < _adjustmentRules.Length) - { - return _adjustmentRules[ruleIndex.GetValueOrDefault() - 1]; - } - - AdjustmentRule result = rule; - for (int i = 1; i < _adjustmentRules.Length; i++) - { - // use ReferenceEquals here instead of AdjustmentRule.Equals because - // ReferenceEquals is much faster. This is safe because all the callers - // of GetPreviousAdjustmentRule pass in a rule that was retrieved from - // _adjustmentRules. A different approach will be needed if this ever changes. - if (ReferenceEquals(rule, _adjustmentRules[i])) - { - result = _adjustmentRules[i - 1]; - break; - } - } - return result; - } - - /// - /// Returns the Universal Coordinated Time (UTC) Offset for the current TimeZoneInfo instance. - /// - public TimeSpan GetUtcOffset(DateTimeOffset dateTimeOffset) => - GetUtcOffsetFromUtc(dateTimeOffset.UtcDateTime, this); - - /// - /// Returns the Universal Coordinated Time (UTC) Offset for the current TimeZoneInfo instance. - /// - public TimeSpan GetUtcOffset(DateTime dateTime) => - GetUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime, s_cachedData); - - // Shortcut for TimeZoneInfo.Local.GetUtcOffset - internal static TimeSpan GetLocalUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags) - { - CachedData cachedData = s_cachedData; - return cachedData.Local.GetUtcOffset(dateTime, flags, cachedData); - } - - /// - /// Returns the Universal Coordinated Time (UTC) Offset for the current TimeZoneInfo instance. - /// - internal TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags) => - GetUtcOffset(dateTime, flags, s_cachedData); - - private TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags, CachedData cachedData) - { - if (dateTime.Kind == DateTimeKind.Local) - { - if (cachedData.GetCorrespondingKind(this) != DateTimeKind.Local) - { - // - // normal case of converting from Local to Utc and then getting the offset from the UTC DateTime - // - DateTime adjustedTime = ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags); - return GetUtcOffsetFromUtc(adjustedTime, this); - } - - // - // Fall through for TimeZoneInfo.Local.GetUtcOffset(date) - // to handle an edge case with Invalid-Times for DateTime formatting: - // - // Consider the invalid PST time "2007-03-11T02:00:00.0000000-08:00" - // - // By directly calling GetUtcOffset instead of converting to UTC and then calling GetUtcOffsetFromUtc - // the correct invalid offset of "-08:00" is returned. In the normal case of converting to UTC as an - // interim-step, the invalid time is adjusted into a *valid* UTC time which causes a change in output: - // - // 1) invalid PST time "2007-03-11T02:00:00.0000000-08:00" - // 2) converted to UTC "2007-03-11T10:00:00.0000000Z" - // 3) offset returned "2007-03-11T03:00:00.0000000-07:00" - // - } - else if (dateTime.Kind == DateTimeKind.Utc) - { - if (cachedData.GetCorrespondingKind(this) == DateTimeKind.Utc) - { - return _baseUtcOffset; - } - else - { - // - // passing in a UTC dateTime to a non-UTC TimeZoneInfo instance is a - // special Loss-Less case. - // - return GetUtcOffsetFromUtc(dateTime, this); - } - } - - return GetUtcOffset(dateTime, this, flags); - } - - /// - /// Returns true if the time is during the ambiguous time period - /// for the current TimeZoneInfo instance. - /// - public bool IsAmbiguousTime(DateTimeOffset dateTimeOffset) - { - if (!_supportsDaylightSavingTime) - { - return false; - } - - DateTimeOffset adjustedTime = ConvertTime(dateTimeOffset, this); - return IsAmbiguousTime(adjustedTime.DateTime); - } - - /// - /// Returns true if the time is during the ambiguous time period - /// for the current TimeZoneInfo instance. - /// - public bool IsAmbiguousTime(DateTime dateTime) => - IsAmbiguousTime(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime); - - /// - /// Returns true if the time is during the ambiguous time period - /// for the current TimeZoneInfo instance. - /// - internal bool IsAmbiguousTime(DateTime dateTime, TimeZoneInfoOptions flags) - { - if (!_supportsDaylightSavingTime) - { - return false; - } - - CachedData cachedData = s_cachedData; - DateTime adjustedTime = - dateTime.Kind == DateTimeKind.Local ? ConvertTime(dateTime, cachedData.Local, this, flags, cachedData) : - dateTime.Kind == DateTimeKind.Utc ? ConvertTime(dateTime, s_utcTimeZone, this, flags, cachedData) : - dateTime; - - int? ruleIndex; - AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime, out ruleIndex); - if (rule != null && rule.HasDaylightSaving) - { - DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); - return GetIsAmbiguousTime(adjustedTime, rule, daylightTime); - } - return false; - } - - /// - /// Returns true if the time is during Daylight Saving time for the current TimeZoneInfo instance. - /// - public bool IsDaylightSavingTime(DateTimeOffset dateTimeOffset) - { - bool isDaylightSavingTime; - GetUtcOffsetFromUtc(dateTimeOffset.UtcDateTime, this, out isDaylightSavingTime); - return isDaylightSavingTime; - } - - /// - /// Returns true if the time is during Daylight Saving time for the current TimeZoneInfo instance. - /// - public bool IsDaylightSavingTime(DateTime dateTime) => - IsDaylightSavingTime(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime, s_cachedData); - - /// - /// Returns true if the time is during Daylight Saving time for the current TimeZoneInfo instance. - /// - internal bool IsDaylightSavingTime(DateTime dateTime, TimeZoneInfoOptions flags) => - IsDaylightSavingTime(dateTime, flags, s_cachedData); - - private bool IsDaylightSavingTime(DateTime dateTime, TimeZoneInfoOptions flags, CachedData cachedData) - { - // - // dateTime.Kind is UTC, then time will be converted from UTC - // into current instance's timezone - // dateTime.Kind is Local, then time will be converted from Local - // into current instance's timezone - // dateTime.Kind is UnSpecified, then time is already in - // current instance's timezone - // - // Our DateTime handles ambiguous times, (one is in the daylight and - // one is in standard.) If a new DateTime is constructed during ambiguous - // time, it is defaulted to "Standard" (i.e. this will return false). - // For Invalid times, we will return false - - if (!_supportsDaylightSavingTime || _adjustmentRules == null) - { - return false; - } - - DateTime adjustedTime; - // - // handle any Local/Utc special cases... - // - if (dateTime.Kind == DateTimeKind.Local) - { - adjustedTime = ConvertTime(dateTime, cachedData.Local, this, flags, cachedData); - } - else if (dateTime.Kind == DateTimeKind.Utc) - { - if (cachedData.GetCorrespondingKind(this) == DateTimeKind.Utc) - { - // simple always false case: TimeZoneInfo.Utc.IsDaylightSavingTime(dateTime, flags); - return false; - } - else - { - // - // passing in a UTC dateTime to a non-UTC TimeZoneInfo instance is a - // special Loss-Less case. - // - bool isDaylightSavings; - GetUtcOffsetFromUtc(dateTime, this, out isDaylightSavings); - return isDaylightSavings; - } - } - else - { - adjustedTime = dateTime; - } - - // - // handle the normal cases... - // - int? ruleIndex; - AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime, out ruleIndex); - if (rule != null && rule.HasDaylightSaving) - { - DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); - return GetIsDaylightSavings(adjustedTime, rule, daylightTime, flags); - } - else - { - return false; - } - } - - /// - /// Returns true when dateTime falls into a "hole in time". - /// - public bool IsInvalidTime(DateTime dateTime) - { - bool isInvalid = false; - - if ((dateTime.Kind == DateTimeKind.Unspecified) || - (dateTime.Kind == DateTimeKind.Local && s_cachedData.GetCorrespondingKind(this) == DateTimeKind.Local)) - { - // only check Unspecified and (Local when this TimeZoneInfo instance is Local) - int? ruleIndex; - AdjustmentRule rule = GetAdjustmentRuleForTime(dateTime, out ruleIndex); - - if (rule != null && rule.HasDaylightSaving) - { - DaylightTimeStruct daylightTime = GetDaylightTime(dateTime.Year, rule, ruleIndex); - isInvalid = GetIsInvalidTime(dateTime, rule, daylightTime); - } - else - { - isInvalid = false; - } - } - - return isInvalid; - } - - /// - /// Clears data from static members. - /// - public static void ClearCachedData() - { - // Clear a fresh instance of cached data - s_cachedData = new CachedData(); - } - - /// - /// Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone. - /// - public static DateTimeOffset ConvertTimeBySystemTimeZoneId(DateTimeOffset dateTimeOffset, string destinationTimeZoneId) => - ConvertTime(dateTimeOffset, FindSystemTimeZoneById(destinationTimeZoneId)); - - /// - /// Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone. - /// - public static DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, string destinationTimeZoneId) => - ConvertTime(dateTime, FindSystemTimeZoneById(destinationTimeZoneId)); - - /// - /// Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone. - /// - public static DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, string sourceTimeZoneId, string destinationTimeZoneId) - { - if (dateTime.Kind == DateTimeKind.Local && string.Equals(sourceTimeZoneId, Local.Id, StringComparison.OrdinalIgnoreCase)) - { - // TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData. - // Take snapshot of cached data to guarantee this method will not be impacted by the ClearCachedData call. - // Without the snapshot, there is a chance that ConvertTime will throw since 'source' won't - // be reference equal to the new TimeZoneInfo.Local - // - CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Local, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData); - } - else if (dateTime.Kind == DateTimeKind.Utc && string.Equals(sourceTimeZoneId, Utc.Id, StringComparison.OrdinalIgnoreCase)) - { - return ConvertTime(dateTime, s_utcTimeZone, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, s_cachedData); - } - else - { - return ConvertTime(dateTime, FindSystemTimeZoneById(sourceTimeZoneId), FindSystemTimeZoneById(destinationTimeZoneId)); - } - } - - /// - /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone - /// - public static DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone) - { - if (destinationTimeZone == null) - { - throw new ArgumentNullException(nameof(destinationTimeZone)); - } - - // calculate the destination time zone offset - DateTime utcDateTime = dateTimeOffset.UtcDateTime; - TimeSpan destinationOffset = GetUtcOffsetFromUtc(utcDateTime, destinationTimeZone); - - // check for overflow - long ticks = utcDateTime.Ticks + destinationOffset.Ticks; - - return - ticks > DateTimeOffset.MaxValue.Ticks ? DateTimeOffset.MaxValue : - ticks < DateTimeOffset.MinValue.Ticks ? DateTimeOffset.MinValue : - new DateTimeOffset(ticks, destinationOffset); - } - - /// - /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone - /// - public static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) - { - if (destinationTimeZone == null) - { - throw new ArgumentNullException(nameof(destinationTimeZone)); - } - - // Special case to give a way clearing the cache without exposing ClearCachedData() - if (dateTime.Ticks == 0) - { - ClearCachedData(); - } - CachedData cachedData = s_cachedData; - TimeZoneInfo sourceTimeZone = dateTime.Kind == DateTimeKind.Utc ? s_utcTimeZone : cachedData.Local; - return ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); - } - - /// - /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone - /// - public static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone) => - ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, s_cachedData); - - /// - /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone - /// - internal static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags) => - ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, flags, s_cachedData); - - private static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags, CachedData cachedData) - { - if (sourceTimeZone == null) - { - throw new ArgumentNullException(nameof(sourceTimeZone)); - } - - if (destinationTimeZone == null) - { - throw new ArgumentNullException(nameof(destinationTimeZone)); - } - - DateTimeKind sourceKind = cachedData.GetCorrespondingKind(sourceTimeZone); - if (((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && (dateTime.Kind != DateTimeKind.Unspecified) && (dateTime.Kind != sourceKind)) - { - throw new ArgumentException(SR.Argument_ConvertMismatch, nameof(sourceTimeZone)); - } - - // - // check to see if the DateTime is in an invalid time range. This check - // requires the current AdjustmentRule and DaylightTime - which are also - // needed to calculate 'sourceOffset' in the normal conversion case. - // By calculating the 'sourceOffset' here we improve the - // performance for the normal case at the expense of the 'ArgumentException' - // case and Loss-less Local special cases. - // - int? sourceRuleIndex; - AdjustmentRule sourceRule = sourceTimeZone.GetAdjustmentRuleForTime(dateTime, out sourceRuleIndex); - TimeSpan sourceOffset = sourceTimeZone.BaseUtcOffset; - - if (sourceRule != null) - { - sourceOffset = sourceOffset + sourceRule.BaseUtcOffsetDelta; - if (sourceRule.HasDaylightSaving) - { - bool sourceIsDaylightSavings = false; - DaylightTimeStruct sourceDaylightTime = sourceTimeZone.GetDaylightTime(dateTime.Year, sourceRule, sourceRuleIndex); - - // 'dateTime' might be in an invalid time range since it is in an AdjustmentRule - // period that supports DST - if (((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && GetIsInvalidTime(dateTime, sourceRule, sourceDaylightTime)) - { - throw new ArgumentException(SR.Argument_DateTimeIsInvalid, nameof(dateTime)); - } - sourceIsDaylightSavings = GetIsDaylightSavings(dateTime, sourceRule, sourceDaylightTime, flags); - - // adjust the sourceOffset according to the Adjustment Rule / Daylight Saving Rule - sourceOffset += (sourceIsDaylightSavings ? sourceRule.DaylightDelta : TimeSpan.Zero /*FUTURE: sourceRule.StandardDelta*/); - } - } - - DateTimeKind targetKind = cachedData.GetCorrespondingKind(destinationTimeZone); - - // handle the special case of Loss-less Local->Local and UTC->UTC) - if (dateTime.Kind != DateTimeKind.Unspecified && sourceKind != DateTimeKind.Unspecified && sourceKind == targetKind) - { - return dateTime; - } - - long utcTicks = dateTime.Ticks - sourceOffset.Ticks; - - // handle the normal case by converting from 'source' to UTC and then to 'target' - bool isAmbiguousLocalDst; - DateTime targetConverted = ConvertUtcToTimeZone(utcTicks, destinationTimeZone, out isAmbiguousLocalDst); - - if (targetKind == DateTimeKind.Local) - { - // Because the ticks conversion between UTC and local is lossy, we need to capture whether the - // time is in a repeated hour so that it can be passed to the DateTime constructor. - return new DateTime(targetConverted.Ticks, DateTimeKind.Local, isAmbiguousLocalDst); - } - else - { - return new DateTime(targetConverted.Ticks, targetKind); - } - } - - /// - /// Converts the value of a DateTime object from Coordinated Universal Time (UTC) to the destinationTimeZone. - /// - public static DateTime ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone) => - ConvertTime(dateTime, s_utcTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, s_cachedData); - - /// - /// Converts the value of a DateTime object to Coordinated Universal Time (UTC). - /// - public static DateTime ConvertTimeToUtc(DateTime dateTime) - { - if (dateTime.Kind == DateTimeKind.Utc) - { - return dateTime; - } - CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, TimeZoneInfoOptions.None, cachedData); - } - - /// - /// Converts the value of a DateTime object to Coordinated Universal Time (UTC). - /// - internal static DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfoOptions flags) - { - if (dateTime.Kind == DateTimeKind.Utc) - { - return dateTime; - } - CachedData cachedData = s_cachedData; - return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags, cachedData); - } - - /// - /// Converts the value of a DateTime object to Coordinated Universal Time (UTC). - /// - public static DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfo sourceTimeZone) => - ConvertTime(dateTime, sourceTimeZone, s_utcTimeZone, TimeZoneInfoOptions.None, s_cachedData); - - /// - /// Returns value equality. Equals does not compare any localizable - /// String objects (DisplayName, StandardName, DaylightName). - /// - public bool Equals(TimeZoneInfo other) => - other != null && - string.Equals(_id, other._id, StringComparison.OrdinalIgnoreCase) && - HasSameRules(other); - - public override bool Equals(object obj) => Equals(obj as TimeZoneInfo); - - public static TimeZoneInfo FromSerializedString(string source) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - if (source.Length == 0) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidSerializedString, source), nameof(source)); - } - - return StringSerializer.GetDeserializedTimeZoneInfo(source); - } - - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(_id); - - /// - /// Returns a containing all valid TimeZone's - /// from the local machine. The entries in the collection are sorted by - /// . - /// This method does *not* throw TimeZoneNotFoundException or InvalidTimeZoneException. - /// - public static ReadOnlyCollection GetSystemTimeZones() - { - CachedData cachedData = s_cachedData; - - lock (cachedData) - { - if (cachedData._readOnlySystemTimeZones == null) - { - PopulateAllSystemTimeZones(cachedData); - cachedData._allSystemTimeZonesRead = true; - - List list; - if (cachedData._systemTimeZones != null) - { - // return a collection of the cached system time zones - list = new List(cachedData._systemTimeZones.Values); - } - else - { - // return an empty collection - list = new List(); - } - - // sort and copy the TimeZoneInfo's into a ReadOnlyCollection for the user - list.Sort((x, y) => - { - // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel - int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset); - return comparison == 0 ? string.CompareOrdinal(x.DisplayName, y.DisplayName) : comparison; - }); - - cachedData._readOnlySystemTimeZones = new ReadOnlyCollection(list); - } - } - return cachedData._readOnlySystemTimeZones; - } - - /// - /// Value equality on the "adjustmentRules" array - /// - public bool HasSameRules(TimeZoneInfo other) - { - if (other == null) - { - throw new ArgumentNullException(nameof(other)); - } - - // check the utcOffset and supportsDaylightSavingTime members - if (_baseUtcOffset != other._baseUtcOffset || - _supportsDaylightSavingTime != other._supportsDaylightSavingTime) - { - return false; - } - - bool sameRules; - AdjustmentRule[] currentRules = _adjustmentRules; - AdjustmentRule[] otherRules = other._adjustmentRules; - - sameRules = - (currentRules == null && otherRules == null) || - (currentRules != null && otherRules != null); - - if (!sameRules) - { - // AdjustmentRule array mismatch - return false; - } - - if (currentRules != null) - { - if (currentRules.Length != otherRules.Length) - { - // AdjustmentRule array length mismatch - return false; - } - - for (int i = 0; i < currentRules.Length; i++) - { - if (!(currentRules[i]).Equals(otherRules[i])) - { - // AdjustmentRule value-equality mismatch - return false; - } - } - } - return sameRules; - } - - /// - /// Returns a TimeZoneInfo instance that represents the local time on the machine. - /// Accessing this property may throw InvalidTimeZoneException or COMException - /// if the machine is in an unstable or corrupt state. - /// - public static TimeZoneInfo Local => s_cachedData.Local; - - // - // ToSerializedString - - // - // "TimeZoneInfo" := TimeZoneInfo Data;[AdjustmentRule Data 1];...;[AdjustmentRule Data N] - // - // "TimeZoneInfo Data" := <_id>;<_baseUtcOffset>;<_displayName>; - // <_standardDisplayName>;<_daylightDispayName>; - // - // "AdjustmentRule Data" := ;;; - // [TransitionTime Data DST Start] - // [TransitionTime Data DST End] - // - // "TransitionTime Data" += ;;;; - // - public string ToSerializedString() => StringSerializer.GetSerializedString(this); - - /// - /// Returns the : "(GMT-08:00) Pacific Time (US & Canada); Tijuana" - /// - public override string ToString() => DisplayName; - - /// - /// Returns a TimeZoneInfo instance that represents Universal Coordinated Time (UTC) - /// - public static TimeZoneInfo Utc => s_utcTimeZone; - - private TimeZoneInfo( - string id, - TimeSpan baseUtcOffset, - string displayName, - string standardDisplayName, - string daylightDisplayName, - AdjustmentRule[] adjustmentRules, - bool disableDaylightSavingTime) - { - bool adjustmentRulesSupportDst; - ValidateTimeZoneInfo(id, baseUtcOffset, adjustmentRules, out adjustmentRulesSupportDst); - - _id = id; - _baseUtcOffset = baseUtcOffset; - _displayName = displayName; - _standardDisplayName = standardDisplayName; - _daylightDisplayName = disableDaylightSavingTime ? null : daylightDisplayName; - _supportsDaylightSavingTime = adjustmentRulesSupportDst && !disableDaylightSavingTime; - _adjustmentRules = adjustmentRules; - } - - /// - /// Returns a simple TimeZoneInfo instance that does not support Daylight Saving Time. - /// - public static TimeZoneInfo CreateCustomTimeZone( - string id, - TimeSpan baseUtcOffset, - string displayName, - string standardDisplayName) - { - return new TimeZoneInfo( - id, - baseUtcOffset, - displayName, - standardDisplayName, - standardDisplayName, - adjustmentRules: null, - disableDaylightSavingTime: false); - } - - /// - /// Returns a TimeZoneInfo instance that may support Daylight Saving Time. - /// - public static TimeZoneInfo CreateCustomTimeZone( - string id, - TimeSpan baseUtcOffset, - string displayName, - string standardDisplayName, - string daylightDisplayName, - AdjustmentRule[] adjustmentRules) - { - return CreateCustomTimeZone( - id, - baseUtcOffset, - displayName, - standardDisplayName, - daylightDisplayName, - adjustmentRules, - disableDaylightSavingTime: false); - } - - /// - /// Returns a TimeZoneInfo instance that may support Daylight Saving Time. - /// - public static TimeZoneInfo CreateCustomTimeZone( - string id, - TimeSpan baseUtcOffset, - string displayName, - string standardDisplayName, - string daylightDisplayName, - AdjustmentRule[] adjustmentRules, - bool disableDaylightSavingTime) - { - if (!disableDaylightSavingTime && adjustmentRules?.Length > 0) - { - adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone(); - } - - return new TimeZoneInfo( - id, - baseUtcOffset, - displayName, - standardDisplayName, - daylightDisplayName, - adjustmentRules, - disableDaylightSavingTime); - } - - void IDeserializationCallback.OnDeserialization(object sender) - { - try - { - bool adjustmentRulesSupportDst; - ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out adjustmentRulesSupportDst); - - if (adjustmentRulesSupportDst != _supportsDaylightSavingTime) - { - throw new SerializationException(SR.Format(SR.Serialization_CorruptField, "SupportsDaylightSavingTime")); - } - } - catch (ArgumentException e) - { - throw new SerializationException(SR.Serialization_InvalidData, e); - } - catch (InvalidTimeZoneException e) - { - throw new SerializationException(SR.Serialization_InvalidData, e); - } - } - - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - - info.AddValue("Id", _id); // Do not rename (binary serialization) - info.AddValue("DisplayName", _displayName); // Do not rename (binary serialization) - info.AddValue("StandardName", _standardDisplayName); // Do not rename (binary serialization) - info.AddValue("DaylightName", _daylightDisplayName); // Do not rename (binary serialization) - info.AddValue("BaseUtcOffset", _baseUtcOffset); // Do not rename (binary serialization) - info.AddValue("AdjustmentRules", _adjustmentRules); // Do not rename (binary serialization) - info.AddValue("SupportsDaylightSavingTime", _supportsDaylightSavingTime); // Do not rename (binary serialization) - } - - private TimeZoneInfo(SerializationInfo info, StreamingContext context) - { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - - _id = (string)info.GetValue("Id", typeof(string)); // Do not rename (binary serialization) - _displayName = (string)info.GetValue("DisplayName", typeof(string)); // Do not rename (binary serialization) - _standardDisplayName = (string)info.GetValue("StandardName", typeof(string)); // Do not rename (binary serialization) - _daylightDisplayName = (string)info.GetValue("DaylightName", typeof(string)); // Do not rename (binary serialization) - _baseUtcOffset = (TimeSpan)info.GetValue("BaseUtcOffset", typeof(TimeSpan)); // Do not rename (binary serialization) - _adjustmentRules = (AdjustmentRule[])info.GetValue("AdjustmentRules", typeof(AdjustmentRule[])); // Do not rename (binary serialization) - _supportsDaylightSavingTime = (bool)info.GetValue("SupportsDaylightSavingTime", typeof(bool)); // Do not rename (binary serialization) - } - - private AdjustmentRule GetAdjustmentRuleForTime(DateTime dateTime, out int? ruleIndex) - { - AdjustmentRule result = GetAdjustmentRuleForTime(dateTime, dateTimeisUtc: false, ruleIndex: out ruleIndex); - Debug.Assert(result == null || ruleIndex.HasValue, "If an AdjustmentRule was found, ruleIndex should also be set."); - - return result; - } - - private AdjustmentRule GetAdjustmentRuleForTime(DateTime dateTime, bool dateTimeisUtc, out int? ruleIndex) - { - if (_adjustmentRules == null || _adjustmentRules.Length == 0) - { - ruleIndex = null; - return null; - } - - // Only check the whole-date portion of the dateTime for DateTimeKind.Unspecified rules - - // This is because the AdjustmentRule DateStart & DateEnd are stored as - // Date-only values {4/2/2006 - 10/28/2006} but actually represent the - // time span {4/2/2006@00:00:00.00000 - 10/28/2006@23:59:59.99999} - DateTime date = dateTimeisUtc ? - (dateTime + BaseUtcOffset).Date : - dateTime.Date; - - int low = 0; - int high = _adjustmentRules.Length - 1; - - while (low <= high) - { - int median = low + ((high - low) >> 1); - - AdjustmentRule rule = _adjustmentRules[median]; - AdjustmentRule previousRule = median > 0 ? _adjustmentRules[median - 1] : rule; - - int compareResult = CompareAdjustmentRuleToDateTime(rule, previousRule, dateTime, date, dateTimeisUtc); - if (compareResult == 0) - { - ruleIndex = median; - return rule; - } - else if (compareResult < 0) - { - low = median + 1; - } - else - { - high = median - 1; - } - } - - ruleIndex = null; - return null; - } - - /// - /// Determines if 'rule' is the correct AdjustmentRule for the given dateTime. - /// - /// - /// A value less than zero if rule is for times before dateTime. - /// Zero if rule is correct for dateTime. - /// A value greater than zero if rule is for times after dateTime. - /// - private int CompareAdjustmentRuleToDateTime(AdjustmentRule rule, AdjustmentRule previousRule, - DateTime dateTime, DateTime dateOnly, bool dateTimeisUtc) - { - bool isAfterStart; - if (rule.DateStart.Kind == DateTimeKind.Utc) - { - DateTime dateTimeToCompare = dateTimeisUtc ? - dateTime : - // use the previous rule to compute the dateTimeToCompare, since the time daylight savings "switches" - // is based on the previous rule's offset - ConvertToUtc(dateTime, previousRule.DaylightDelta, previousRule.BaseUtcOffsetDelta); - - isAfterStart = dateTimeToCompare >= rule.DateStart; - } - else - { - // if the rule's DateStart is Unspecified, then use the whole-date portion - isAfterStart = dateOnly >= rule.DateStart; - } - - if (!isAfterStart) - { - return 1; - } - - bool isBeforeEnd; - if (rule.DateEnd.Kind == DateTimeKind.Utc) - { - DateTime dateTimeToCompare = dateTimeisUtc ? - dateTime : - ConvertToUtc(dateTime, rule.DaylightDelta, rule.BaseUtcOffsetDelta); - - isBeforeEnd = dateTimeToCompare <= rule.DateEnd; - } - else - { - // if the rule's DateEnd is Unspecified, then use the whole-date portion - isBeforeEnd = dateOnly <= rule.DateEnd; - } - - return isBeforeEnd ? 0 : -1; - } - - /// - /// Converts the dateTime to UTC using the specified deltas. - /// - private DateTime ConvertToUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta) => - ConvertToFromUtc(dateTime, daylightDelta, baseUtcOffsetDelta, convertToUtc: true); - - /// - /// Converts the dateTime from UTC using the specified deltas. - /// - private DateTime ConvertFromUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta) => - ConvertToFromUtc(dateTime, daylightDelta, baseUtcOffsetDelta, convertToUtc: false); - - /// - /// Converts the dateTime to or from UTC using the specified deltas. - /// - private DateTime ConvertToFromUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta, bool convertToUtc) - { - TimeSpan offset = BaseUtcOffset + daylightDelta + baseUtcOffsetDelta; - if (convertToUtc) - { - offset = offset.Negate(); - } - - long ticks = dateTime.Ticks + offset.Ticks; - - return - ticks > DateTime.MaxValue.Ticks ? DateTime.MaxValue : - ticks < DateTime.MinValue.Ticks ? DateTime.MinValue : - new DateTime(ticks); - } - - /// - /// Helper function that converts a dateTime from UTC into the destinationTimeZone - /// - Returns DateTime.MaxValue when the converted value is too large. - /// - Returns DateTime.MinValue when the converted value is too small. - /// - private static DateTime ConvertUtcToTimeZone(long ticks, TimeZoneInfo destinationTimeZone, out bool isAmbiguousLocalDst) - { - // used to calculate the UTC offset in the destinationTimeZone - DateTime utcConverted = - ticks > DateTime.MaxValue.Ticks ? DateTime.MaxValue : - ticks < DateTime.MinValue.Ticks ? DateTime.MinValue : - new DateTime(ticks); - - // verify the time is between MinValue and MaxValue in the new time zone - TimeSpan offset = GetUtcOffsetFromUtc(utcConverted, destinationTimeZone, out isAmbiguousLocalDst); - ticks += offset.Ticks; - - return - ticks > DateTime.MaxValue.Ticks ? DateTime.MaxValue : - ticks < DateTime.MinValue.Ticks ? DateTime.MinValue : - new DateTime(ticks); - } - - /// - /// Helper function that returns a DaylightTime from a year and AdjustmentRule. - /// - private DaylightTimeStruct GetDaylightTime(int year, AdjustmentRule rule, int? ruleIndex) - { - TimeSpan delta = rule.DaylightDelta; - DateTime startTime; - DateTime endTime; - if (rule.NoDaylightTransitions) - { - // NoDaylightTransitions rules don't use DaylightTransition Start and End, instead - // the DateStart and DateEnd are UTC times that represent when daylight savings time changes. - // Convert the UTC times into adjusted time zone times. - - // use the previous rule to calculate the startTime, since the DST change happens w.r.t. the previous rule - AdjustmentRule previousRule = GetPreviousAdjustmentRule(rule, ruleIndex); - startTime = ConvertFromUtc(rule.DateStart, previousRule.DaylightDelta, previousRule.BaseUtcOffsetDelta); - - endTime = ConvertFromUtc(rule.DateEnd, rule.DaylightDelta, rule.BaseUtcOffsetDelta); - } - else - { - startTime = TransitionTimeToDateTime(year, rule.DaylightTransitionStart); - endTime = TransitionTimeToDateTime(year, rule.DaylightTransitionEnd); - } - return new DaylightTimeStruct(startTime, endTime, delta); - } - - /// - /// Helper function that checks if a given dateTime is in Daylight Saving Time (DST). - /// This function assumes the dateTime and AdjustmentRule are both in the same time zone. - /// - private static bool GetIsDaylightSavings(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime, TimeZoneInfoOptions flags) - { - if (rule == null) - { - return false; - } - - DateTime startTime; - DateTime endTime; - - if (time.Kind == DateTimeKind.Local) - { - // startTime and endTime represent the period from either the start of - // DST to the end and ***includes*** the potentially overlapped times - startTime = rule.IsStartDateMarkerForBeginningOfYear() ? - new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : - daylightTime.Start + daylightTime.Delta; - - endTime = rule.IsEndDateMarkerForEndOfYear() ? - new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : - daylightTime.End; - } - else - { - // startTime and endTime represent the period from either the start of DST to the end and - // ***does not include*** the potentially overlapped times - // - // -=-=-=-=-=- Pacific Standard Time -=-=-=-=-=-=- - // April 2, 2006 October 29, 2006 - // 2AM 3AM 1AM 2AM - // | +1 hr | | -1 hr | - // | | | | - // [========== DST ========>) - // - // -=-=-=-=-=- Some Weird Time Zone -=-=-=-=-=-=- - // April 2, 2006 October 29, 2006 - // 1AM 2AM 2AM 3AM - // | -1 hr | | +1 hr | - // | | | | - // [======== DST ========>) - // - bool invalidAtStart = rule.DaylightDelta > TimeSpan.Zero; - - startTime = rule.IsStartDateMarkerForBeginningOfYear() ? - new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : - daylightTime.Start + (invalidAtStart ? rule.DaylightDelta : TimeSpan.Zero); /* FUTURE: - rule.StandardDelta; */ - - endTime = rule.IsEndDateMarkerForEndOfYear() ? - new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : - daylightTime.End + (invalidAtStart ? -rule.DaylightDelta : TimeSpan.Zero); - } - - bool isDst = CheckIsDst(startTime, time, endTime, false, rule); - - // If this date was previously converted from a UTC date and we were able to detect that the local - // DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity. - if (isDst && time.Kind == DateTimeKind.Local) - { - // For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the - // clock back. It is theoretically possible to have a positive delta, (which would really be daylight - // reduction time), where you would have to wind the clock back in the begnning. - if (GetIsAmbiguousTime(time, rule, daylightTime)) - { - isDst = time.IsAmbiguousDaylightSavingTime(); - } - } - - return isDst; - } - - /// - /// Gets the offset that should be used to calculate DST start times from a UTC time. - /// - private TimeSpan GetDaylightSavingsStartOffsetFromUtc(TimeSpan baseUtcOffset, AdjustmentRule rule, int? ruleIndex) - { - if (rule.NoDaylightTransitions) - { - // use the previous rule to calculate the startTime, since the DST change happens w.r.t. the previous rule - AdjustmentRule previousRule = GetPreviousAdjustmentRule(rule, ruleIndex); - return baseUtcOffset + previousRule.BaseUtcOffsetDelta + previousRule.DaylightDelta; - } - else - { - return baseUtcOffset + rule.BaseUtcOffsetDelta; /* FUTURE: + rule.StandardDelta; */ - } - } - - /// - /// Gets the offset that should be used to calculate DST end times from a UTC time. - /// - private TimeSpan GetDaylightSavingsEndOffsetFromUtc(TimeSpan baseUtcOffset, AdjustmentRule rule) - { - // NOTE: even NoDaylightTransitions rules use this logic since DST ends w.r.t. the current rule - return baseUtcOffset + rule.BaseUtcOffsetDelta + rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */ - } - - /// - /// Helper function that checks if a given dateTime is in Daylight Saving Time (DST). - /// This function assumes the dateTime is in UTC and AdjustmentRule is in a different time zone. - /// - private static bool GetIsDaylightSavingsFromUtc(DateTime time, int year, TimeSpan utc, AdjustmentRule rule, int? ruleIndex, out bool isAmbiguousLocalDst, TimeZoneInfo zone) - { - isAmbiguousLocalDst = false; - - if (rule == null) - { - return false; - } - - // Get the daylight changes for the year of the specified time. - DaylightTimeStruct daylightTime = zone.GetDaylightTime(year, rule, ruleIndex); - - // The start and end times represent the range of universal times that are in DST for that year. - // Within that there is an ambiguous hour, usually right at the end, but at the beginning in - // the unusual case of a negative daylight savings delta. - // We need to handle the case if the current rule has daylight saving end by the end of year. If so, we need to check if next year starts with daylight saving on - // and get the actual daylight saving end time. Here is example for such case: - // Converting the UTC datetime "12/31/2011 8:00:00 PM" to "(UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)" zone. - // In 2011 the daylight saving will go through the end of the year. If we use the end of 2011 as the daylight saving end, - // that will fail the conversion because the UTC time +4 hours (3 hours for the zone UTC offset and 1 hour for daylight saving) will move us to the next year "1/1/2012 12:00 AM", - // checking against the end of 2011 will tell we are not in daylight saving which is wrong and the conversion will be off by one hour. - // Note we handle the similar case when rule year start with daylight saving and previous year end with daylight saving. - - bool ignoreYearAdjustment = false; - TimeSpan dstStartOffset = zone.GetDaylightSavingsStartOffsetFromUtc(utc, rule, ruleIndex); - DateTime startTime; - if (rule.IsStartDateMarkerForBeginningOfYear() && daylightTime.Start.Year > DateTime.MinValue.Year) - { - int? previousYearRuleIndex; - AdjustmentRule previousYearRule = zone.GetAdjustmentRuleForTime( - new DateTime(daylightTime.Start.Year - 1, 12, 31), - out previousYearRuleIndex); - if (previousYearRule != null && previousYearRule.IsEndDateMarkerForEndOfYear()) - { - DaylightTimeStruct previousDaylightTime = zone.GetDaylightTime( - daylightTime.Start.Year - 1, - previousYearRule, - previousYearRuleIndex); - startTime = previousDaylightTime.Start - utc - previousYearRule.BaseUtcOffsetDelta; - ignoreYearAdjustment = true; - } - else - { - startTime = new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) - dstStartOffset; - } - } - else - { - startTime = daylightTime.Start - dstStartOffset; - } - - TimeSpan dstEndOffset = zone.GetDaylightSavingsEndOffsetFromUtc(utc, rule); - DateTime endTime; - if (rule.IsEndDateMarkerForEndOfYear() && daylightTime.End.Year < DateTime.MaxValue.Year) - { - int? nextYearRuleIndex; - AdjustmentRule nextYearRule = zone.GetAdjustmentRuleForTime( - new DateTime(daylightTime.End.Year + 1, 1, 1), - out nextYearRuleIndex); - if (nextYearRule != null && nextYearRule.IsStartDateMarkerForBeginningOfYear()) - { - if (nextYearRule.IsEndDateMarkerForEndOfYear()) - { - // next year end with daylight saving on too - endTime = new DateTime(daylightTime.End.Year + 1, 12, 31) - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta; - } - else - { - DaylightTimeStruct nextdaylightTime = zone.GetDaylightTime( - daylightTime.End.Year + 1, - nextYearRule, - nextYearRuleIndex); - endTime = nextdaylightTime.End - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta; - } - ignoreYearAdjustment = true; - } - else - { - endTime = new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) - dstEndOffset; - } - } - else - { - endTime = daylightTime.End - dstEndOffset; - } - - DateTime ambiguousStart; - DateTime ambiguousEnd; - if (daylightTime.Delta.Ticks > 0) - { - ambiguousStart = endTime - daylightTime.Delta; - ambiguousEnd = endTime; - } - else - { - ambiguousStart = startTime; - ambiguousEnd = startTime - daylightTime.Delta; - } - - bool isDst = CheckIsDst(startTime, time, endTime, ignoreYearAdjustment, rule); - - // See if the resulting local time becomes ambiguous. This must be captured here or the - // DateTime will not be able to round-trip back to UTC accurately. - if (isDst) - { - isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd); - - if (!isAmbiguousLocalDst && ambiguousStart.Year != ambiguousEnd.Year) - { - // there exists an extreme corner case where the start or end period is on a year boundary and - // because of this the comparison above might have been performed for a year-early or a year-later - // than it should have been. - DateTime ambiguousStartModified; - DateTime ambiguousEndModified; - try - { - ambiguousStartModified = ambiguousStart.AddYears(1); - ambiguousEndModified = ambiguousEnd.AddYears(1); - isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd); - } - catch (ArgumentOutOfRangeException) { } - - if (!isAmbiguousLocalDst) - { - try - { - ambiguousStartModified = ambiguousStart.AddYears(-1); - ambiguousEndModified = ambiguousEnd.AddYears(-1); - isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd); - } - catch (ArgumentOutOfRangeException) { } - } - } - } - - return isDst; - } - - private static bool CheckIsDst(DateTime startTime, DateTime time, DateTime endTime, bool ignoreYearAdjustment, AdjustmentRule rule) - { - // NoDaylightTransitions AdjustmentRules should never get their year adjusted since they adjust the offset for the - // entire time period - which may be for multiple years - if (!ignoreYearAdjustment && !rule.NoDaylightTransitions) - { - int startTimeYear = startTime.Year; - int endTimeYear = endTime.Year; - - if (startTimeYear != endTimeYear) - { - endTime = endTime.AddYears(startTimeYear - endTimeYear); - } - - int timeYear = time.Year; - - if (startTimeYear != timeYear) - { - time = time.AddYears(startTimeYear - timeYear); - } - } - - if (startTime > endTime) - { - // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year. - // Note, the summer in the southern hemisphere begins late in the year. - return (time < endTime || time >= startTime); - } - else if (rule.NoDaylightTransitions) - { - // In NoDaylightTransitions AdjustmentRules, the startTime is always before the endTime, - // and both the start and end times are inclusive - return time >= startTime && time <= endTime; - } - else - { - // In northern hemisphere, the daylight saving time starts in the middle of the year. - return time >= startTime && time < endTime; - } - } - - /// - /// Returns true when the dateTime falls into an ambiguous time range. - /// - /// For example, in Pacific Standard Time on Sunday, October 29, 2006 time jumps from - /// 2AM to 1AM. This means the timeline on Sunday proceeds as follows: - /// 12AM ... [1AM ... 1:59:59AM -> 1AM ... 1:59:59AM] 2AM ... 3AM ... - /// - /// In this example, any DateTime values that fall into the [1AM - 1:59:59AM] range - /// are ambiguous; as it is unclear if these times are in Daylight Saving Time. - /// - private static bool GetIsAmbiguousTime(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime) - { - bool isAmbiguous = false; - if (rule == null || rule.DaylightDelta == TimeSpan.Zero) - { - return isAmbiguous; - } - - DateTime startAmbiguousTime; - DateTime endAmbiguousTime; - - // if at DST start we transition forward in time then there is an ambiguous time range at the DST end - if (rule.DaylightDelta > TimeSpan.Zero) - { - if (rule.IsEndDateMarkerForEndOfYear()) - { // year end with daylight on so there is no ambiguous time - return false; - } - startAmbiguousTime = daylightTime.End; - endAmbiguousTime = daylightTime.End - rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */ - } - else - { - if (rule.IsStartDateMarkerForBeginningOfYear()) - { // year start with daylight on so there is no ambiguous time - return false; - } - startAmbiguousTime = daylightTime.Start; - endAmbiguousTime = daylightTime.Start + rule.DaylightDelta; /* FUTURE: - rule.StandardDelta; */ - } - - isAmbiguous = (time >= endAmbiguousTime && time < startAmbiguousTime); - - if (!isAmbiguous && startAmbiguousTime.Year != endAmbiguousTime.Year) - { - // there exists an extreme corner case where the start or end period is on a year boundary and - // because of this the comparison above might have been performed for a year-early or a year-later - // than it should have been. - DateTime startModifiedAmbiguousTime; - DateTime endModifiedAmbiguousTime; - try - { - startModifiedAmbiguousTime = startAmbiguousTime.AddYears(1); - endModifiedAmbiguousTime = endAmbiguousTime.AddYears(1); - isAmbiguous = (time >= endModifiedAmbiguousTime && time < startModifiedAmbiguousTime); - } - catch (ArgumentOutOfRangeException) { } - - if (!isAmbiguous) - { - try - { - startModifiedAmbiguousTime = startAmbiguousTime.AddYears(-1); - endModifiedAmbiguousTime = endAmbiguousTime.AddYears(-1); - isAmbiguous = (time >= endModifiedAmbiguousTime && time < startModifiedAmbiguousTime); - } - catch (ArgumentOutOfRangeException) { } - } - } - return isAmbiguous; - } - - /// - /// Helper function that checks if a given DateTime is in an invalid time ("time hole") - /// A "time hole" occurs at a DST transition point when time jumps forward; - /// For example, in Pacific Standard Time on Sunday, April 2, 2006 time jumps from - /// 1:59:59.9999999 to 3AM. The time range 2AM to 2:59:59.9999999AM is the "time hole". - /// A "time hole" is not limited to only occurring at the start of DST, and may occur at - /// the end of DST as well. - /// - private static bool GetIsInvalidTime(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime) - { - bool isInvalid = false; - if (rule == null || rule.DaylightDelta == TimeSpan.Zero) - { - return isInvalid; - } - - DateTime startInvalidTime; - DateTime endInvalidTime; - - // if at DST start we transition forward in time then there is an ambiguous time range at the DST end - if (rule.DaylightDelta < TimeSpan.Zero) - { - // if the year ends with daylight saving on then there cannot be any time-hole's in that year. - if (rule.IsEndDateMarkerForEndOfYear()) - return false; - - startInvalidTime = daylightTime.End; - endInvalidTime = daylightTime.End - rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */ - } - else - { - // if the year starts with daylight saving on then there cannot be any time-hole's in that year. - if (rule.IsStartDateMarkerForBeginningOfYear()) - return false; - - startInvalidTime = daylightTime.Start; - endInvalidTime = daylightTime.Start + rule.DaylightDelta; /* FUTURE: - rule.StandardDelta; */ - } - - isInvalid = (time >= startInvalidTime && time < endInvalidTime); - - if (!isInvalid && startInvalidTime.Year != endInvalidTime.Year) - { - // there exists an extreme corner case where the start or end period is on a year boundary and - // because of this the comparison above might have been performed for a year-early or a year-later - // than it should have been. - DateTime startModifiedInvalidTime; - DateTime endModifiedInvalidTime; - try - { - startModifiedInvalidTime = startInvalidTime.AddYears(1); - endModifiedInvalidTime = endInvalidTime.AddYears(1); - isInvalid = (time >= startModifiedInvalidTime && time < endModifiedInvalidTime); - } - catch (ArgumentOutOfRangeException) { } - - if (!isInvalid) - { - try - { - startModifiedInvalidTime = startInvalidTime.AddYears(-1); - endModifiedInvalidTime = endInvalidTime.AddYears(-1); - isInvalid = (time >= startModifiedInvalidTime && time < endModifiedInvalidTime); - } - catch (ArgumentOutOfRangeException) { } - } - } - return isInvalid; - } - - /// - /// Helper function that calculates the UTC offset for a dateTime in a timeZone. - /// This function assumes that the dateTime is already converted into the timeZone. - /// - private static TimeSpan GetUtcOffset(DateTime time, TimeZoneInfo zone, TimeZoneInfoOptions flags) - { - TimeSpan baseOffset = zone.BaseUtcOffset; - int? ruleIndex; - AdjustmentRule rule = zone.GetAdjustmentRuleForTime(time, out ruleIndex); - - if (rule != null) - { - baseOffset = baseOffset + rule.BaseUtcOffsetDelta; - if (rule.HasDaylightSaving) - { - DaylightTimeStruct daylightTime = zone.GetDaylightTime(time.Year, rule, ruleIndex); - bool isDaylightSavings = GetIsDaylightSavings(time, rule, daylightTime, flags); - baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); - } - } - - return baseOffset; - } - - /// - /// Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone. - /// This function assumes that the dateTime is represented in UTC and has *not* already been converted into the timeZone. - /// - private static TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone) - { - bool isDaylightSavings; - return GetUtcOffsetFromUtc(time, zone, out isDaylightSavings); - } - - /// - /// Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone. - /// This function assumes that the dateTime is represented in UTC and has *not* already been converted into the timeZone. - /// - private static TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone, out bool isDaylightSavings) - { - bool isAmbiguousLocalDst; - return GetUtcOffsetFromUtc(time, zone, out isDaylightSavings, out isAmbiguousLocalDst); - } - - /// - /// Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone. - /// This function assumes that the dateTime is represented in UTC and has *not* already been converted into the timeZone. - /// - internal static TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone, out bool isDaylightSavings, out bool isAmbiguousLocalDst) - { - isDaylightSavings = false; - isAmbiguousLocalDst = false; - TimeSpan baseOffset = zone.BaseUtcOffset; - int year; - int? ruleIndex; - AdjustmentRule rule; - - if (time > s_maxDateOnly) - { - rule = zone.GetAdjustmentRuleForTime(DateTime.MaxValue, out ruleIndex); - year = 9999; - } - else if (time < s_minDateOnly) - { - rule = zone.GetAdjustmentRuleForTime(DateTime.MinValue, out ruleIndex); - year = 1; - } - else - { - rule = zone.GetAdjustmentRuleForTime(time, dateTimeisUtc: true, ruleIndex: out ruleIndex); - Debug.Assert(rule == null || ruleIndex.HasValue, - "If GetAdjustmentRuleForTime returned an AdjustmentRule, ruleIndex should also be set."); - - // As we get the associated rule using the adjusted targetTime, we should use the adjusted year (targetTime.Year) too as after adding the baseOffset, - // sometimes the year value can change if the input datetime was very close to the beginning or the end of the year. Examples of such cases: - // Libya Standard Time when used with the date 2011-12-31T23:59:59.9999999Z - // "W. Australia Standard Time" used with date 2005-12-31T23:59:00.0000000Z - DateTime targetTime = time + baseOffset; - year = targetTime.Year; - } - - if (rule != null) - { - baseOffset = baseOffset + rule.BaseUtcOffsetDelta; - if (rule.HasDaylightSaving) - { - isDaylightSavings = GetIsDaylightSavingsFromUtc(time, year, zone._baseUtcOffset, rule, ruleIndex, out isAmbiguousLocalDst, zone); - baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); - } - } - - return baseOffset; - } - - /// - /// Helper function that converts a year and TransitionTime into a DateTime. - /// - internal static DateTime TransitionTimeToDateTime(int year, TransitionTime transitionTime) - { - DateTime value; - DateTime timeOfDay = transitionTime.TimeOfDay; - - if (transitionTime.IsFixedDateRule) - { - // create a DateTime from the passed in year and the properties on the transitionTime - - // if the day is out of range for the month then use the last day of the month - int day = DateTime.DaysInMonth(year, transitionTime.Month); - - value = new DateTime(year, transitionTime.Month, (day < transitionTime.Day) ? day : transitionTime.Day, - timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond); - } - else - { - if (transitionTime.Week <= 4) - { - // - // Get the (transitionTime.Week)th Sunday. - // - value = new DateTime(year, transitionTime.Month, 1, - timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond); - - int dayOfWeek = (int)value.DayOfWeek; - int delta = (int)transitionTime.DayOfWeek - dayOfWeek; - if (delta < 0) - { - delta += 7; - } - delta += 7 * (transitionTime.Week - 1); - - if (delta > 0) - { - value = value.AddDays(delta); - } - } - else - { - // - // If TransitionWeek is greater than 4, we will get the last week. - // - int daysInMonth = DateTime.DaysInMonth(year, transitionTime.Month); - value = new DateTime(year, transitionTime.Month, daysInMonth, - timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond); - - // This is the day of week for the last day of the month. - int dayOfWeek = (int)value.DayOfWeek; - int delta = dayOfWeek - (int)transitionTime.DayOfWeek; - if (delta < 0) - { - delta += 7; - } - - if (delta > 0) - { - value = value.AddDays(-delta); - } - } - } - return value; - } - - /// - /// Helper function for retrieving a TimeZoneInfo object by time_zone_name. - /// - /// This function may return null. - /// - /// assumes cachedData lock is taken - /// - private static TimeZoneInfoResult TryGetTimeZone(string id, bool dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData, bool alwaysFallbackToLocalMachine = false) - { - Debug.Assert(Monitor.IsEntered(cachedData)); - - TimeZoneInfoResult result = TimeZoneInfoResult.Success; - e = null; - TimeZoneInfo match = null; - - // check the cache - if (cachedData._systemTimeZones != null) - { - if (cachedData._systemTimeZones.TryGetValue(id, out match)) - { - if (dstDisabled && match._supportsDaylightSavingTime) - { - // we found a cache hit but we want a time zone without DST and this one has DST data - value = CreateCustomTimeZone(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName); - } - else - { - value = new TimeZoneInfo(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName, - match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false); - } - return result; - } - } - - // Fall back to reading from the local machine when the cache is not fully populated. - // On UNIX, there may be some tzfiles that aren't in the zones.tab file, and thus aren't returned from GetSystemTimeZones(). - // If a caller asks for one of these zones before calling GetSystemTimeZones(), the time zone is returned successfully. But if - // GetSystemTimeZones() is called first, FindSystemTimeZoneById will throw TimeZoneNotFoundException, which is inconsistent. - // To fix this, when 'alwaysFallbackToLocalMachine' is true, even if _allSystemTimeZonesRead is true, try reading the tzfile - // from disk, but don't add the time zone to the list returned from GetSystemTimeZones(). These time zones will only be - // available if asked for directly. - if (!cachedData._allSystemTimeZonesRead || alwaysFallbackToLocalMachine) - { - result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData); - } - else - { - result = TimeZoneInfoResult.TimeZoneNotFoundException; - value = null; - } - - return result; - } - - private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData) - { - TimeZoneInfoResult result; - TimeZoneInfo match; - - result = TryGetTimeZoneFromLocalMachine(id, out match, out e); - - if (result == TimeZoneInfoResult.Success) - { - if (cachedData._systemTimeZones == null) - cachedData._systemTimeZones = new Dictionary(StringComparer.OrdinalIgnoreCase); - - cachedData._systemTimeZones.Add(id, match); - - if (dstDisabled && match._supportsDaylightSavingTime) - { - // we found a cache hit but we want a time zone without DST and this one has DST data - value = CreateCustomTimeZone(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName); - } - else - { - value = new TimeZoneInfo(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName, - match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false); - } - } - else - { - value = null; - } - - return result; - } - - /// - /// Helper function that performs all of the validation checks for the - /// factory methods and deserialization callback. - /// - private static void ValidateTimeZoneInfo(string id, TimeSpan baseUtcOffset, AdjustmentRule[] adjustmentRules, out bool adjustmentRulesSupportDst) - { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - - if (id.Length == 0) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidId, id), nameof(id)); - } - - if (UtcOffsetOutOfRange(baseUtcOffset)) - { - throw new ArgumentOutOfRangeException(nameof(baseUtcOffset), SR.ArgumentOutOfRange_UtcOffset); - } - - if (baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0) - { - throw new ArgumentException(SR.Argument_TimeSpanHasSeconds, nameof(baseUtcOffset)); - } - - adjustmentRulesSupportDst = false; - - // - // "adjustmentRules" can either be null or a valid array of AdjustmentRule objects. - // A valid array is one that does not contain any null elements and all elements - // are sorted in chronological order - // - - if (adjustmentRules != null && adjustmentRules.Length != 0) - { - adjustmentRulesSupportDst = true; - AdjustmentRule prev = null; - AdjustmentRule current = null; - for (int i = 0; i < adjustmentRules.Length; i++) - { - prev = current; - current = adjustmentRules[i]; - - if (current == null) - { - throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesNoNulls); - } - - if (!IsValidAdjustmentRuleOffest(baseUtcOffset, current)) - { - throw new InvalidTimeZoneException(SR.ArgumentOutOfRange_UtcOffsetAndDaylightDelta); - } - - if (prev != null && current.DateStart <= prev.DateEnd) - { - // verify the rules are in chronological order and the DateStart/DateEnd do not overlap - throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesOutOfOrder); - } - } - } - } - - private static readonly TimeSpan MaxOffset = TimeSpan.FromHours(14.0); - private static readonly TimeSpan MinOffset = -MaxOffset; - - /// - /// Helper function that validates the TimeSpan is within +/- 14.0 hours - /// - internal static bool UtcOffsetOutOfRange(TimeSpan offset) => - offset < MinOffset || offset > MaxOffset; - - private static TimeSpan GetUtcOffset(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule) - { - return baseUtcOffset - + adjustmentRule.BaseUtcOffsetDelta - + (adjustmentRule.HasDaylightSaving ? adjustmentRule.DaylightDelta : TimeSpan.Zero); - } - - /// - /// Helper function that performs adjustment rule validation - /// - private static bool IsValidAdjustmentRuleOffest(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule) - { - TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule); - return !UtcOffsetOutOfRange(utcOffset); - } - - /// - /// Normalize adjustment rule offset so that it is within valid range - /// This method should not be called at all but is here in case something changes in the future - /// or if really old time zones are present on the OS (no combination is known at the moment) - /// - private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, ref AdjustmentRule adjustmentRule) - { - // Certain time zones such as: - // Time Zone start date end date offset - // ----------------------------------------------------- - // America/Yakutat 0001-01-01 1867-10-18 14:41:00 - // America/Yakutat 1867-10-18 1900-08-20 14:41:00 - // America/Sitka 0001-01-01 1867-10-18 14:58:00 - // America/Sitka 1867-10-18 1900-08-20 14:58:00 - // Asia/Manila 0001-01-01 1844-12-31 -15:56:00 - // Pacific/Guam 0001-01-01 1845-01-01 -14:21:00 - // Pacific/Saipan 0001-01-01 1845-01-01 -14:21:00 - // - // have larger offset than currently supported by framework. - // If for whatever reason we find that time zone exceeding max - // offset of 14h this function will truncate it to the max valid offset. - // Updating max offset may cause problems with interacting with SQL server - // which uses SQL DATETIMEOFFSET field type which was originally designed to be - // bit-for-bit compatible with DateTimeOffset. - - TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule); - - // utc base offset delta increment - TimeSpan adjustment = TimeSpan.Zero; - - if (utcOffset > MaxOffset) - { - adjustment = MaxOffset - utcOffset; - } - else if (utcOffset < MinOffset) - { - adjustment = MinOffset - utcOffset; - } - - if (adjustment != TimeSpan.Zero) - { - adjustmentRule = AdjustmentRule.CreateAdjustmentRule( - adjustmentRule.DateStart, - adjustmentRule.DateEnd, - adjustmentRule.DaylightDelta, - adjustmentRule.DaylightTransitionStart, - adjustmentRule.DaylightTransitionEnd, - adjustmentRule.BaseUtcOffsetDelta + adjustment, - adjustmentRule.NoDaylightTransitions); - } - } - } -} +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.Serialization; +using System.Threading; + +namespace System +{ + // + // DateTime uses TimeZoneInfo under the hood for IsDaylightSavingTime, IsAmbiguousTime, and GetUtcOffset. + // These TimeZoneInfo APIs can throw ArgumentException when an Invalid-Time is passed in. To avoid this + // unwanted behavior in DateTime public APIs, DateTime internally passes the + // TimeZoneInfoOptions.NoThrowOnInvalidTime flag to internal TimeZoneInfo APIs. + // + // In the future we can consider exposing similar options on the public TimeZoneInfo APIs if there is enough + // demand for this alternate behavior. + // + [Flags] + internal enum TimeZoneInfoOptions + { + None = 1, + NoThrowOnInvalidTime = 2 + }; + + [Serializable] + [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + public sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback + { + private enum TimeZoneInfoResult + { + Success = 0, + TimeZoneNotFoundException = 1, + InvalidTimeZoneException = 2, + SecurityException = 3 + }; + + private readonly string _id; + private readonly string? _displayName; + private readonly string? _standardDisplayName; + private readonly string? _daylightDisplayName; + private readonly TimeSpan _baseUtcOffset; + private readonly bool _supportsDaylightSavingTime; + private readonly AdjustmentRule[]? _adjustmentRules; + + // constants for TimeZoneInfo.Local and TimeZoneInfo.Utc + private const string UtcId = "UTC"; + private const string LocalId = "Local"; + + private static readonly TimeZoneInfo s_utcTimeZone = CreateCustomTimeZone(UtcId, TimeSpan.Zero, UtcId, UtcId); + + private static CachedData s_cachedData = new CachedData(); + + // + // All cached data are encapsulated in a helper class to allow consistent view even when the data are refreshed using ClearCachedData() + // + // For example, TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData. Without the consistent snapshot, + // there is a chance that the internal ConvertTime calls will throw since 'source' won't be reference equal to the new TimeZoneInfo.Local. + // + private sealed partial class CachedData + { + private volatile TimeZoneInfo? _localTimeZone; + + private TimeZoneInfo CreateLocal() + { + lock (this) + { + TimeZoneInfo? timeZone = _localTimeZone; + if (timeZone == null) + { + timeZone = GetLocalTimeZone(this); + + // this step is to break the reference equality + // between TimeZoneInfo.Local and a second time zone + // such as "Pacific Standard Time" + timeZone = new TimeZoneInfo( + timeZone._id, + timeZone._baseUtcOffset, + timeZone._displayName, + timeZone._standardDisplayName, + timeZone._daylightDisplayName, + timeZone._adjustmentRules, + disableDaylightSavingTime: false); + + _localTimeZone = timeZone; + } + return timeZone; + } + } + + public TimeZoneInfo Local + { + get + { + TimeZoneInfo? timeZone = _localTimeZone; + if (timeZone == null) + { + timeZone = CreateLocal(); + } + return timeZone; + } + } + + /// + /// Helper function that returns the corresponding DateTimeKind for this TimeZoneInfo. + /// + public DateTimeKind GetCorrespondingKind(TimeZoneInfo? timeZone) + { + // We check reference equality to see if 'this' is the same as + // TimeZoneInfo.Local or TimeZoneInfo.Utc. This check is needed to + // support setting the DateTime Kind property to 'Local' or + // 'Utc' on the ConverTime(...) return value. + // + // Using reference equality instead of value equality was a + // performance based design compromise. The reference equality + // has much greater performance, but it reduces the number of + // returned DateTime's that can be properly set as 'Local' or 'Utc'. + // + // For example, the user could be converting to the TimeZoneInfo returned + // by FindSystemTimeZoneById("Pacific Standard Time") and their local + // machine may be in Pacific time. If we used value equality to determine + // the corresponding Kind then this conversion would be tagged as 'Local'; + // where as we are currently tagging the returned DateTime as 'Unspecified' + // in this example. Only when the user passes in TimeZoneInfo.Local or + // TimeZoneInfo.Utc to the ConvertTime(...) methods will this check succeed. + // + return + ReferenceEquals(timeZone, s_utcTimeZone) ? DateTimeKind.Utc : + ReferenceEquals(timeZone, _localTimeZone) ? DateTimeKind.Local : + DateTimeKind.Unspecified; + } + + public Dictionary? _systemTimeZones; + public ReadOnlyCollection? _readOnlySystemTimeZones; + public bool _allSystemTimeZonesRead; + }; + + // used by GetUtcOffsetFromUtc (DateTime.Now, DateTime.ToLocalTime) for max/min whole-day range checks + private static readonly DateTime s_maxDateOnly = new DateTime(9999, 12, 31); + private static readonly DateTime s_minDateOnly = new DateTime(1, 1, 2); + + public string Id => _id; + + public string DisplayName => _displayName ?? string.Empty; + + public string StandardName => _standardDisplayName ?? string.Empty; + + public string DaylightName => _daylightDisplayName ?? string.Empty; + + public TimeSpan BaseUtcOffset => _baseUtcOffset; + + public bool SupportsDaylightSavingTime => _supportsDaylightSavingTime; + + /// + /// Returns an array of TimeSpan objects representing all of + /// possible UTC offset values for this ambiguous time. + /// + public TimeSpan[] GetAmbiguousTimeOffsets(DateTimeOffset dateTimeOffset) + { + if (!SupportsDaylightSavingTime) + { + throw new ArgumentException(SR.Argument_DateTimeOffsetIsNotAmbiguous, nameof(dateTimeOffset)); + } + + DateTime adjustedTime = ConvertTime(dateTimeOffset, this).DateTime; + + bool isAmbiguous = false; + int? ruleIndex; + AdjustmentRule? rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime, out ruleIndex); + if (rule != null && rule.HasDaylightSaving) + { + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); + isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime); + } + + if (!isAmbiguous) + { + throw new ArgumentException(SR.Argument_DateTimeOffsetIsNotAmbiguous, nameof(dateTimeOffset)); + } + + // the passed in dateTime is ambiguous in this TimeZoneInfo instance + TimeSpan[] timeSpans = new TimeSpan[2]; + + TimeSpan actualUtcOffset = _baseUtcOffset + rule!.BaseUtcOffsetDelta; + + // the TimeSpan array must be sorted from least to greatest + if (rule.DaylightDelta > TimeSpan.Zero) + { + timeSpans[0] = actualUtcOffset; // FUTURE: + rule.StandardDelta; + timeSpans[1] = actualUtcOffset + rule.DaylightDelta; + } + else + { + timeSpans[0] = actualUtcOffset + rule.DaylightDelta; + timeSpans[1] = actualUtcOffset; // FUTURE: + rule.StandardDelta; + } + return timeSpans; + } + + /// + /// Returns an array of TimeSpan objects representing all of + /// possible UTC offset values for this ambiguous time. + /// + public TimeSpan[] GetAmbiguousTimeOffsets(DateTime dateTime) + { + if (!SupportsDaylightSavingTime) + { + throw new ArgumentException(SR.Argument_DateTimeIsNotAmbiguous, nameof(dateTime)); + } + + DateTime adjustedTime; + if (dateTime.Kind == DateTimeKind.Local) + { + CachedData cachedData = s_cachedData; + adjustedTime = ConvertTime(dateTime, cachedData.Local, this, TimeZoneInfoOptions.None, cachedData); + } + else if (dateTime.Kind == DateTimeKind.Utc) + { + CachedData cachedData = s_cachedData; + adjustedTime = ConvertTime(dateTime, s_utcTimeZone, this, TimeZoneInfoOptions.None, cachedData); + } + else + { + adjustedTime = dateTime; + } + + bool isAmbiguous = false; + int? ruleIndex; + AdjustmentRule? rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime, out ruleIndex); + if (rule != null && rule.HasDaylightSaving) + { + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); + isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime); + } + + if (!isAmbiguous) + { + throw new ArgumentException(SR.Argument_DateTimeIsNotAmbiguous, nameof(dateTime)); + } + + // the passed in dateTime is ambiguous in this TimeZoneInfo instance + TimeSpan[] timeSpans = new TimeSpan[2]; + TimeSpan actualUtcOffset = _baseUtcOffset + rule!.BaseUtcOffsetDelta; + + // the TimeSpan array must be sorted from least to greatest + if (rule.DaylightDelta > TimeSpan.Zero) + { + timeSpans[0] = actualUtcOffset; // FUTURE: + rule.StandardDelta; + timeSpans[1] = actualUtcOffset + rule.DaylightDelta; + } + else + { + timeSpans[0] = actualUtcOffset + rule.DaylightDelta; + timeSpans[1] = actualUtcOffset; // FUTURE: + rule.StandardDelta; + } + return timeSpans; + } + + // note the time is already adjusted + private AdjustmentRule? GetAdjustmentRuleForAmbiguousOffsets(DateTime adjustedTime, out int? ruleIndex) + { + AdjustmentRule? rule = GetAdjustmentRuleForTime(adjustedTime, out ruleIndex); + if (rule != null && rule.NoDaylightTransitions && !rule.HasDaylightSaving) + { + // When using NoDaylightTransitions rules, each rule is only for one offset. + // When looking for the Daylight savings rules, and we found the non-DST rule, + // then we get the rule right before this rule. + return GetPreviousAdjustmentRule(rule, ruleIndex); + } + + return rule; + } + + /// + /// Gets the AdjustmentRule that is immediately preceding the specified rule. + /// If the specified rule is the first AdjustmentRule, or it isn't in _adjustmentRules, + /// then the specified rule is returned. + /// + private AdjustmentRule GetPreviousAdjustmentRule(AdjustmentRule rule, int? ruleIndex) + { + Debug.Assert(rule.NoDaylightTransitions, "GetPreviousAdjustmentRule should only be used with NoDaylightTransitions rules."); + Debug.Assert(_adjustmentRules != null); + + if (ruleIndex.HasValue && 0 < ruleIndex.GetValueOrDefault() && ruleIndex.GetValueOrDefault() < _adjustmentRules.Length) + { + return _adjustmentRules[ruleIndex.GetValueOrDefault() - 1]; + } + + AdjustmentRule result = rule; + for (int i = 1; i < _adjustmentRules.Length; i++) + { + // use ReferenceEquals here instead of AdjustmentRule.Equals because + // ReferenceEquals is much faster. This is safe because all the callers + // of GetPreviousAdjustmentRule pass in a rule that was retrieved from + // _adjustmentRules. A different approach will be needed if this ever changes. + if (ReferenceEquals(rule, _adjustmentRules[i])) + { + result = _adjustmentRules[i - 1]; + break; + } + } + return result; + } + + /// + /// Returns the Universal Coordinated Time (UTC) Offset for the current TimeZoneInfo instance. + /// + public TimeSpan GetUtcOffset(DateTimeOffset dateTimeOffset) => + GetUtcOffsetFromUtc(dateTimeOffset.UtcDateTime, this); + + /// + /// Returns the Universal Coordinated Time (UTC) Offset for the current TimeZoneInfo instance. + /// + public TimeSpan GetUtcOffset(DateTime dateTime) => + GetUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime, s_cachedData); + + // Shortcut for TimeZoneInfo.Local.GetUtcOffset + internal static TimeSpan GetLocalUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags) + { + CachedData cachedData = s_cachedData; + return cachedData.Local.GetUtcOffset(dateTime, flags, cachedData); + } + + /// + /// Returns the Universal Coordinated Time (UTC) Offset for the current TimeZoneInfo instance. + /// + internal TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags) => + GetUtcOffset(dateTime, flags, s_cachedData); + + private TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags, CachedData cachedData) + { + if (dateTime.Kind == DateTimeKind.Local) + { + if (cachedData.GetCorrespondingKind(this) != DateTimeKind.Local) + { + // + // normal case of converting from Local to Utc and then getting the offset from the UTC DateTime + // + DateTime adjustedTime = ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags); + return GetUtcOffsetFromUtc(adjustedTime, this); + } + + // + // Fall through for TimeZoneInfo.Local.GetUtcOffset(date) + // to handle an edge case with Invalid-Times for DateTime formatting: + // + // Consider the invalid PST time "2007-03-11T02:00:00.0000000-08:00" + // + // By directly calling GetUtcOffset instead of converting to UTC and then calling GetUtcOffsetFromUtc + // the correct invalid offset of "-08:00" is returned. In the normal case of converting to UTC as an + // interim-step, the invalid time is adjusted into a *valid* UTC time which causes a change in output: + // + // 1) invalid PST time "2007-03-11T02:00:00.0000000-08:00" + // 2) converted to UTC "2007-03-11T10:00:00.0000000Z" + // 3) offset returned "2007-03-11T03:00:00.0000000-07:00" + // + } + else if (dateTime.Kind == DateTimeKind.Utc) + { + if (cachedData.GetCorrespondingKind(this) == DateTimeKind.Utc) + { + return _baseUtcOffset; + } + else + { + // + // passing in a UTC dateTime to a non-UTC TimeZoneInfo instance is a + // special Loss-Less case. + // + return GetUtcOffsetFromUtc(dateTime, this); + } + } + + return GetUtcOffset(dateTime, this, flags); + } + + /// + /// Returns true if the time is during the ambiguous time period + /// for the current TimeZoneInfo instance. + /// + public bool IsAmbiguousTime(DateTimeOffset dateTimeOffset) + { + if (!_supportsDaylightSavingTime) + { + return false; + } + + DateTimeOffset adjustedTime = ConvertTime(dateTimeOffset, this); + return IsAmbiguousTime(adjustedTime.DateTime); + } + + /// + /// Returns true if the time is during the ambiguous time period + /// for the current TimeZoneInfo instance. + /// + public bool IsAmbiguousTime(DateTime dateTime) => + IsAmbiguousTime(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime); + + /// + /// Returns true if the time is during the ambiguous time period + /// for the current TimeZoneInfo instance. + /// + internal bool IsAmbiguousTime(DateTime dateTime, TimeZoneInfoOptions flags) + { + if (!_supportsDaylightSavingTime) + { + return false; + } + + CachedData cachedData = s_cachedData; + DateTime adjustedTime = + dateTime.Kind == DateTimeKind.Local ? ConvertTime(dateTime, cachedData.Local, this, flags, cachedData) : + dateTime.Kind == DateTimeKind.Utc ? ConvertTime(dateTime, s_utcTimeZone, this, flags, cachedData) : + dateTime; + + int? ruleIndex; + AdjustmentRule? rule = GetAdjustmentRuleForTime(adjustedTime, out ruleIndex); + if (rule != null && rule.HasDaylightSaving) + { + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); + return GetIsAmbiguousTime(adjustedTime, rule, daylightTime); + } + return false; + } + + /// + /// Returns true if the time is during Daylight Saving time for the current TimeZoneInfo instance. + /// + public bool IsDaylightSavingTime(DateTimeOffset dateTimeOffset) + { + bool isDaylightSavingTime; + GetUtcOffsetFromUtc(dateTimeOffset.UtcDateTime, this, out isDaylightSavingTime); + return isDaylightSavingTime; + } + + /// + /// Returns true if the time is during Daylight Saving time for the current TimeZoneInfo instance. + /// + public bool IsDaylightSavingTime(DateTime dateTime) => + IsDaylightSavingTime(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime, s_cachedData); + + /// + /// Returns true if the time is during Daylight Saving time for the current TimeZoneInfo instance. + /// + internal bool IsDaylightSavingTime(DateTime dateTime, TimeZoneInfoOptions flags) => + IsDaylightSavingTime(dateTime, flags, s_cachedData); + + private bool IsDaylightSavingTime(DateTime dateTime, TimeZoneInfoOptions flags, CachedData cachedData) + { + // + // dateTime.Kind is UTC, then time will be converted from UTC + // into current instance's timezone + // dateTime.Kind is Local, then time will be converted from Local + // into current instance's timezone + // dateTime.Kind is UnSpecified, then time is already in + // current instance's timezone + // + // Our DateTime handles ambiguous times, (one is in the daylight and + // one is in standard.) If a new DateTime is constructed during ambiguous + // time, it is defaulted to "Standard" (i.e. this will return false). + // For Invalid times, we will return false + + if (!_supportsDaylightSavingTime || _adjustmentRules == null) + { + return false; + } + + DateTime adjustedTime; + // + // handle any Local/Utc special cases... + // + if (dateTime.Kind == DateTimeKind.Local) + { + adjustedTime = ConvertTime(dateTime, cachedData.Local, this, flags, cachedData); + } + else if (dateTime.Kind == DateTimeKind.Utc) + { + if (cachedData.GetCorrespondingKind(this) == DateTimeKind.Utc) + { + // simple always false case: TimeZoneInfo.Utc.IsDaylightSavingTime(dateTime, flags); + return false; + } + else + { + // + // passing in a UTC dateTime to a non-UTC TimeZoneInfo instance is a + // special Loss-Less case. + // + bool isDaylightSavings; + GetUtcOffsetFromUtc(dateTime, this, out isDaylightSavings); + return isDaylightSavings; + } + } + else + { + adjustedTime = dateTime; + } + + // + // handle the normal cases... + // + int? ruleIndex; + AdjustmentRule? rule = GetAdjustmentRuleForTime(adjustedTime, out ruleIndex); + if (rule != null && rule.HasDaylightSaving) + { + DaylightTimeStruct daylightTime = GetDaylightTime(adjustedTime.Year, rule, ruleIndex); + return GetIsDaylightSavings(adjustedTime, rule, daylightTime, flags); + } + else + { + return false; + } + } + + /// + /// Returns true when dateTime falls into a "hole in time". + /// + public bool IsInvalidTime(DateTime dateTime) + { + bool isInvalid = false; + + if ((dateTime.Kind == DateTimeKind.Unspecified) || + (dateTime.Kind == DateTimeKind.Local && s_cachedData.GetCorrespondingKind(this) == DateTimeKind.Local)) + { + // only check Unspecified and (Local when this TimeZoneInfo instance is Local) + int? ruleIndex; + AdjustmentRule? rule = GetAdjustmentRuleForTime(dateTime, out ruleIndex); + + if (rule != null && rule.HasDaylightSaving) + { + DaylightTimeStruct daylightTime = GetDaylightTime(dateTime.Year, rule, ruleIndex); + isInvalid = GetIsInvalidTime(dateTime, rule, daylightTime); + } + else + { + isInvalid = false; + } + } + + return isInvalid; + } + + /// + /// Clears data from static members. + /// + public static void ClearCachedData() + { + // Clear a fresh instance of cached data + s_cachedData = new CachedData(); + } + + /// + /// Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone. + /// + public static DateTimeOffset ConvertTimeBySystemTimeZoneId(DateTimeOffset dateTimeOffset, string destinationTimeZoneId) => + ConvertTime(dateTimeOffset, FindSystemTimeZoneById(destinationTimeZoneId)); + + /// + /// Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone. + /// + public static DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, string destinationTimeZoneId) => + ConvertTime(dateTime, FindSystemTimeZoneById(destinationTimeZoneId)); + + /// + /// Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone. + /// + public static DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, string sourceTimeZoneId, string destinationTimeZoneId) + { + if (dateTime.Kind == DateTimeKind.Local && string.Equals(sourceTimeZoneId, Local.Id, StringComparison.OrdinalIgnoreCase)) + { + // TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData. + // Take snapshot of cached data to guarantee this method will not be impacted by the ClearCachedData call. + // Without the snapshot, there is a chance that ConvertTime will throw since 'source' won't + // be reference equal to the new TimeZoneInfo.Local + // + CachedData cachedData = s_cachedData; + return ConvertTime(dateTime, cachedData.Local, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData); + } + else if (dateTime.Kind == DateTimeKind.Utc && string.Equals(sourceTimeZoneId, Utc.Id, StringComparison.OrdinalIgnoreCase)) + { + return ConvertTime(dateTime, s_utcTimeZone, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, s_cachedData); + } + else + { + return ConvertTime(dateTime, FindSystemTimeZoneById(sourceTimeZoneId), FindSystemTimeZoneById(destinationTimeZoneId)); + } + } + + /// + /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone + /// + public static DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone) + { + if (destinationTimeZone == null) + { + throw new ArgumentNullException(nameof(destinationTimeZone)); + } + + // calculate the destination time zone offset + DateTime utcDateTime = dateTimeOffset.UtcDateTime; + TimeSpan destinationOffset = GetUtcOffsetFromUtc(utcDateTime, destinationTimeZone); + + // check for overflow + long ticks = utcDateTime.Ticks + destinationOffset.Ticks; + + return + ticks > DateTimeOffset.MaxValue.Ticks ? DateTimeOffset.MaxValue : + ticks < DateTimeOffset.MinValue.Ticks ? DateTimeOffset.MinValue : + new DateTimeOffset(ticks, destinationOffset); + } + + /// + /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone + /// + public static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) + { + if (destinationTimeZone == null) + { + throw new ArgumentNullException(nameof(destinationTimeZone)); + } + + // Special case to give a way clearing the cache without exposing ClearCachedData() + if (dateTime.Ticks == 0) + { + ClearCachedData(); + } + CachedData cachedData = s_cachedData; + TimeZoneInfo sourceTimeZone = dateTime.Kind == DateTimeKind.Utc ? s_utcTimeZone : cachedData.Local; + return ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, cachedData); + } + + /// + /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone + /// + public static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone) => + ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, s_cachedData); + + /// + /// Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone + /// + internal static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags) => + ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, flags, s_cachedData); + + private static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags, CachedData cachedData) + { + if (sourceTimeZone == null) + { + throw new ArgumentNullException(nameof(sourceTimeZone)); + } + + if (destinationTimeZone == null) + { + throw new ArgumentNullException(nameof(destinationTimeZone)); + } + + DateTimeKind sourceKind = cachedData.GetCorrespondingKind(sourceTimeZone); + if (((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && (dateTime.Kind != DateTimeKind.Unspecified) && (dateTime.Kind != sourceKind)) + { + throw new ArgumentException(SR.Argument_ConvertMismatch, nameof(sourceTimeZone)); + } + + // + // check to see if the DateTime is in an invalid time range. This check + // requires the current AdjustmentRule and DaylightTime - which are also + // needed to calculate 'sourceOffset' in the normal conversion case. + // By calculating the 'sourceOffset' here we improve the + // performance for the normal case at the expense of the 'ArgumentException' + // case and Loss-less Local special cases. + // + int? sourceRuleIndex; + AdjustmentRule? sourceRule = sourceTimeZone.GetAdjustmentRuleForTime(dateTime, out sourceRuleIndex); + TimeSpan sourceOffset = sourceTimeZone.BaseUtcOffset; + + if (sourceRule != null) + { + sourceOffset = sourceOffset + sourceRule.BaseUtcOffsetDelta; + if (sourceRule.HasDaylightSaving) + { + bool sourceIsDaylightSavings = false; + DaylightTimeStruct sourceDaylightTime = sourceTimeZone.GetDaylightTime(dateTime.Year, sourceRule, sourceRuleIndex); + + // 'dateTime' might be in an invalid time range since it is in an AdjustmentRule + // period that supports DST + if (((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && GetIsInvalidTime(dateTime, sourceRule, sourceDaylightTime)) + { + throw new ArgumentException(SR.Argument_DateTimeIsInvalid, nameof(dateTime)); + } + sourceIsDaylightSavings = GetIsDaylightSavings(dateTime, sourceRule, sourceDaylightTime, flags); + + // adjust the sourceOffset according to the Adjustment Rule / Daylight Saving Rule + sourceOffset += (sourceIsDaylightSavings ? sourceRule.DaylightDelta : TimeSpan.Zero /*FUTURE: sourceRule.StandardDelta*/); + } + } + + DateTimeKind targetKind = cachedData.GetCorrespondingKind(destinationTimeZone); + + // handle the special case of Loss-less Local->Local and UTC->UTC) + if (dateTime.Kind != DateTimeKind.Unspecified && sourceKind != DateTimeKind.Unspecified && sourceKind == targetKind) + { + return dateTime; + } + + long utcTicks = dateTime.Ticks - sourceOffset.Ticks; + + // handle the normal case by converting from 'source' to UTC and then to 'target' + bool isAmbiguousLocalDst; + DateTime targetConverted = ConvertUtcToTimeZone(utcTicks, destinationTimeZone, out isAmbiguousLocalDst); + + if (targetKind == DateTimeKind.Local) + { + // Because the ticks conversion between UTC and local is lossy, we need to capture whether the + // time is in a repeated hour so that it can be passed to the DateTime constructor. + return new DateTime(targetConverted.Ticks, DateTimeKind.Local, isAmbiguousLocalDst); + } + else + { + return new DateTime(targetConverted.Ticks, targetKind); + } + } + + /// + /// Converts the value of a DateTime object from Coordinated Universal Time (UTC) to the destinationTimeZone. + /// + public static DateTime ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone) => + ConvertTime(dateTime, s_utcTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, s_cachedData); + + /// + /// Converts the value of a DateTime object to Coordinated Universal Time (UTC). + /// + public static DateTime ConvertTimeToUtc(DateTime dateTime) + { + if (dateTime.Kind == DateTimeKind.Utc) + { + return dateTime; + } + CachedData cachedData = s_cachedData; + return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, TimeZoneInfoOptions.None, cachedData); + } + + /// + /// Converts the value of a DateTime object to Coordinated Universal Time (UTC). + /// + internal static DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfoOptions flags) + { + if (dateTime.Kind == DateTimeKind.Utc) + { + return dateTime; + } + CachedData cachedData = s_cachedData; + return ConvertTime(dateTime, cachedData.Local, s_utcTimeZone, flags, cachedData); + } + + /// + /// Converts the value of a DateTime object to Coordinated Universal Time (UTC). + /// + public static DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfo sourceTimeZone) => + ConvertTime(dateTime, sourceTimeZone, s_utcTimeZone, TimeZoneInfoOptions.None, s_cachedData); + + /// + /// Returns value equality. Equals does not compare any localizable + /// String objects (DisplayName, StandardName, DaylightName). + /// + public bool Equals(TimeZoneInfo? other) => + other != null && + string.Equals(_id, other._id, StringComparison.OrdinalIgnoreCase) && + HasSameRules(other); + + public override bool Equals(object? obj) => Equals(obj as TimeZoneInfo); + + public static TimeZoneInfo FromSerializedString(string source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + if (source.Length == 0) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidSerializedString, source), nameof(source)); + } + + return StringSerializer.GetDeserializedTimeZoneInfo(source); + } + + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(_id); + + /// + /// Returns a containing all valid TimeZone's + /// from the local machine. The entries in the collection are sorted by + /// . + /// This method does *not* throw TimeZoneNotFoundException or InvalidTimeZoneException. + /// + public static ReadOnlyCollection GetSystemTimeZones() + { + CachedData cachedData = s_cachedData; + + lock (cachedData) + { + if (cachedData._readOnlySystemTimeZones == null) + { + PopulateAllSystemTimeZones(cachedData); + cachedData._allSystemTimeZonesRead = true; + + List list; + if (cachedData._systemTimeZones != null) + { + // return a collection of the cached system time zones + list = new List(cachedData._systemTimeZones.Values); + } + else + { + // return an empty collection + list = new List(); + } + + // sort and copy the TimeZoneInfo's into a ReadOnlyCollection for the user + list.Sort((x, y) => + { + // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel + int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset); + return comparison == 0 ? string.CompareOrdinal(x.DisplayName, y.DisplayName) : comparison; + }); + + cachedData._readOnlySystemTimeZones = new ReadOnlyCollection(list); + } + } + return cachedData._readOnlySystemTimeZones; + } + + /// + /// Value equality on the "adjustmentRules" array + /// + public bool HasSameRules(TimeZoneInfo other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + // check the utcOffset and supportsDaylightSavingTime members + if (_baseUtcOffset != other._baseUtcOffset || + _supportsDaylightSavingTime != other._supportsDaylightSavingTime) + { + return false; + } + + bool sameRules; + AdjustmentRule[]? currentRules = _adjustmentRules; + AdjustmentRule[]? otherRules = other._adjustmentRules; + + sameRules = + (currentRules == null && otherRules == null) || + (currentRules != null && otherRules != null); + + if (!sameRules) + { + // AdjustmentRule array mismatch + return false; + } + + if (currentRules != null) + { + if (currentRules.Length != otherRules!.Length) + { + // AdjustmentRule array length mismatch + return false; + } + + for (int i = 0; i < currentRules.Length; i++) + { + if (!(currentRules[i]).Equals(otherRules[i])) + { + // AdjustmentRule value-equality mismatch + return false; + } + } + } + return sameRules; + } + + /// + /// Returns a TimeZoneInfo instance that represents the local time on the machine. + /// Accessing this property may throw InvalidTimeZoneException or COMException + /// if the machine is in an unstable or corrupt state. + /// + public static TimeZoneInfo Local => s_cachedData.Local; + + // + // ToSerializedString - + // + // "TimeZoneInfo" := TimeZoneInfo Data;[AdjustmentRule Data 1];...;[AdjustmentRule Data N] + // + // "TimeZoneInfo Data" := <_id>;<_baseUtcOffset>;<_displayName>; + // <_standardDisplayName>;<_daylightDispayName>; + // + // "AdjustmentRule Data" := ;;; + // [TransitionTime Data DST Start] + // [TransitionTime Data DST End] + // + // "TransitionTime Data" += ;;;; + // + public string ToSerializedString() => StringSerializer.GetSerializedString(this); + + /// + /// Returns the : "(GMT-08:00) Pacific Time (US & Canada); Tijuana" + /// + public override string ToString() => DisplayName; + + /// + /// Returns a TimeZoneInfo instance that represents Universal Coordinated Time (UTC) + /// + public static TimeZoneInfo Utc => s_utcTimeZone; + + private TimeZoneInfo( + string id, + TimeSpan baseUtcOffset, + string? displayName, + string? standardDisplayName, + string? daylightDisplayName, + AdjustmentRule[]? adjustmentRules, + bool disableDaylightSavingTime) + { + bool adjustmentRulesSupportDst; + ValidateTimeZoneInfo(id, baseUtcOffset, adjustmentRules, out adjustmentRulesSupportDst); + + _id = id; + _baseUtcOffset = baseUtcOffset; + _displayName = displayName; + _standardDisplayName = standardDisplayName; + _daylightDisplayName = disableDaylightSavingTime ? null : daylightDisplayName; + _supportsDaylightSavingTime = adjustmentRulesSupportDst && !disableDaylightSavingTime; + _adjustmentRules = adjustmentRules; + } + + /// + /// Returns a simple TimeZoneInfo instance that does not support Daylight Saving Time. + /// + public static TimeZoneInfo CreateCustomTimeZone( + string id, + TimeSpan baseUtcOffset, + string? displayName, + string? standardDisplayName) + { + return new TimeZoneInfo( + id, + baseUtcOffset, + displayName, + standardDisplayName, + standardDisplayName, + adjustmentRules: null, + disableDaylightSavingTime: false); + } + + /// + /// Returns a TimeZoneInfo instance that may support Daylight Saving Time. + /// + public static TimeZoneInfo CreateCustomTimeZone( + string id, + TimeSpan baseUtcOffset, + string? displayName, + string? standardDisplayName, + string? daylightDisplayName, + AdjustmentRule[]? adjustmentRules) + { + return CreateCustomTimeZone( + id, + baseUtcOffset, + displayName, + standardDisplayName, + daylightDisplayName, + adjustmentRules, + disableDaylightSavingTime: false); + } + + /// + /// Returns a TimeZoneInfo instance that may support Daylight Saving Time. + /// + public static TimeZoneInfo CreateCustomTimeZone( + string id, + TimeSpan baseUtcOffset, + string? displayName, + string? standardDisplayName, + string? daylightDisplayName, + AdjustmentRule[]? adjustmentRules, + bool disableDaylightSavingTime) + { + if (!disableDaylightSavingTime && adjustmentRules?.Length > 0) + { + adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone(); + } + + return new TimeZoneInfo( + id, + baseUtcOffset, + displayName, + standardDisplayName, + daylightDisplayName, + adjustmentRules, + disableDaylightSavingTime); + } + + void IDeserializationCallback.OnDeserialization(object sender) + { + try + { + bool adjustmentRulesSupportDst; + ValidateTimeZoneInfo(_id, _baseUtcOffset, _adjustmentRules, out adjustmentRulesSupportDst); + + if (adjustmentRulesSupportDst != _supportsDaylightSavingTime) + { + throw new SerializationException(SR.Format(SR.Serialization_CorruptField, "SupportsDaylightSavingTime")); + } + } + catch (ArgumentException e) + { + throw new SerializationException(SR.Serialization_InvalidData, e); + } + catch (InvalidTimeZoneException e) + { + throw new SerializationException(SR.Serialization_InvalidData, e); + } + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + { + throw new ArgumentNullException(nameof(info)); + } + + info.AddValue("Id", _id); // Do not rename (binary serialization) + info.AddValue("DisplayName", _displayName); // Do not rename (binary serialization) + info.AddValue("StandardName", _standardDisplayName); // Do not rename (binary serialization) + info.AddValue("DaylightName", _daylightDisplayName); // Do not rename (binary serialization) + info.AddValue("BaseUtcOffset", _baseUtcOffset); // Do not rename (binary serialization) + info.AddValue("AdjustmentRules", _adjustmentRules); // Do not rename (binary serialization) + info.AddValue("SupportsDaylightSavingTime", _supportsDaylightSavingTime); // Do not rename (binary serialization) + } + + private TimeZoneInfo(SerializationInfo info, StreamingContext context) + { + if (info == null) + { + throw new ArgumentNullException(nameof(info)); + } + + _id = (string)info.GetValue("Id", typeof(string))!; // Do not rename (binary serialization) + _displayName = (string?)info.GetValue("DisplayName", typeof(string)); // Do not rename (binary serialization) + _standardDisplayName = (string?)info.GetValue("StandardName", typeof(string)); // Do not rename (binary serialization) + _daylightDisplayName = (string?)info.GetValue("DaylightName", typeof(string)); // Do not rename (binary serialization) + _baseUtcOffset = (TimeSpan)info.GetValue("BaseUtcOffset", typeof(TimeSpan))!; // Do not rename (binary serialization) + _adjustmentRules = (AdjustmentRule[]?)info.GetValue("AdjustmentRules", typeof(AdjustmentRule[])); // Do not rename (binary serialization) + _supportsDaylightSavingTime = (bool)info.GetValue("SupportsDaylightSavingTime", typeof(bool))!; // Do not rename (binary serialization) + } + + private AdjustmentRule? GetAdjustmentRuleForTime(DateTime dateTime, out int? ruleIndex) + { + AdjustmentRule? result = GetAdjustmentRuleForTime(dateTime, dateTimeisUtc: false, ruleIndex: out ruleIndex); + Debug.Assert(result == null || ruleIndex.HasValue, "If an AdjustmentRule was found, ruleIndex should also be set."); + + return result; + } + + private AdjustmentRule? GetAdjustmentRuleForTime(DateTime dateTime, bool dateTimeisUtc, out int? ruleIndex) + { + if (_adjustmentRules == null || _adjustmentRules.Length == 0) + { + ruleIndex = null; + return null; + } + + // Only check the whole-date portion of the dateTime for DateTimeKind.Unspecified rules - + // This is because the AdjustmentRule DateStart & DateEnd are stored as + // Date-only values {4/2/2006 - 10/28/2006} but actually represent the + // time span {4/2/2006@00:00:00.00000 - 10/28/2006@23:59:59.99999} + DateTime date = dateTimeisUtc ? + (dateTime + BaseUtcOffset).Date : + dateTime.Date; + + int low = 0; + int high = _adjustmentRules.Length - 1; + + while (low <= high) + { + int median = low + ((high - low) >> 1); + + AdjustmentRule rule = _adjustmentRules[median]; + AdjustmentRule previousRule = median > 0 ? _adjustmentRules[median - 1] : rule; + + int compareResult = CompareAdjustmentRuleToDateTime(rule, previousRule, dateTime, date, dateTimeisUtc); + if (compareResult == 0) + { + ruleIndex = median; + return rule; + } + else if (compareResult < 0) + { + low = median + 1; + } + else + { + high = median - 1; + } + } + + ruleIndex = null; + return null; + } + + /// + /// Determines if 'rule' is the correct AdjustmentRule for the given dateTime. + /// + /// + /// A value less than zero if rule is for times before dateTime. + /// Zero if rule is correct for dateTime. + /// A value greater than zero if rule is for times after dateTime. + /// + private int CompareAdjustmentRuleToDateTime(AdjustmentRule rule, AdjustmentRule previousRule, + DateTime dateTime, DateTime dateOnly, bool dateTimeisUtc) + { + bool isAfterStart; + if (rule.DateStart.Kind == DateTimeKind.Utc) + { + DateTime dateTimeToCompare = dateTimeisUtc ? + dateTime : + // use the previous rule to compute the dateTimeToCompare, since the time daylight savings "switches" + // is based on the previous rule's offset + ConvertToUtc(dateTime, previousRule.DaylightDelta, previousRule.BaseUtcOffsetDelta); + + isAfterStart = dateTimeToCompare >= rule.DateStart; + } + else + { + // if the rule's DateStart is Unspecified, then use the whole-date portion + isAfterStart = dateOnly >= rule.DateStart; + } + + if (!isAfterStart) + { + return 1; + } + + bool isBeforeEnd; + if (rule.DateEnd.Kind == DateTimeKind.Utc) + { + DateTime dateTimeToCompare = dateTimeisUtc ? + dateTime : + ConvertToUtc(dateTime, rule.DaylightDelta, rule.BaseUtcOffsetDelta); + + isBeforeEnd = dateTimeToCompare <= rule.DateEnd; + } + else + { + // if the rule's DateEnd is Unspecified, then use the whole-date portion + isBeforeEnd = dateOnly <= rule.DateEnd; + } + + return isBeforeEnd ? 0 : -1; + } + + /// + /// Converts the dateTime to UTC using the specified deltas. + /// + private DateTime ConvertToUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta) => + ConvertToFromUtc(dateTime, daylightDelta, baseUtcOffsetDelta, convertToUtc: true); + + /// + /// Converts the dateTime from UTC using the specified deltas. + /// + private DateTime ConvertFromUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta) => + ConvertToFromUtc(dateTime, daylightDelta, baseUtcOffsetDelta, convertToUtc: false); + + /// + /// Converts the dateTime to or from UTC using the specified deltas. + /// + private DateTime ConvertToFromUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta, bool convertToUtc) + { + TimeSpan offset = BaseUtcOffset + daylightDelta + baseUtcOffsetDelta; + if (convertToUtc) + { + offset = offset.Negate(); + } + + long ticks = dateTime.Ticks + offset.Ticks; + + return + ticks > DateTime.MaxValue.Ticks ? DateTime.MaxValue : + ticks < DateTime.MinValue.Ticks ? DateTime.MinValue : + new DateTime(ticks); + } + + /// + /// Helper function that converts a dateTime from UTC into the destinationTimeZone + /// - Returns DateTime.MaxValue when the converted value is too large. + /// - Returns DateTime.MinValue when the converted value is too small. + /// + private static DateTime ConvertUtcToTimeZone(long ticks, TimeZoneInfo destinationTimeZone, out bool isAmbiguousLocalDst) + { + // used to calculate the UTC offset in the destinationTimeZone + DateTime utcConverted = + ticks > DateTime.MaxValue.Ticks ? DateTime.MaxValue : + ticks < DateTime.MinValue.Ticks ? DateTime.MinValue : + new DateTime(ticks); + + // verify the time is between MinValue and MaxValue in the new time zone + TimeSpan offset = GetUtcOffsetFromUtc(utcConverted, destinationTimeZone, out isAmbiguousLocalDst); + ticks += offset.Ticks; + + return + ticks > DateTime.MaxValue.Ticks ? DateTime.MaxValue : + ticks < DateTime.MinValue.Ticks ? DateTime.MinValue : + new DateTime(ticks); + } + + /// + /// Helper function that returns a DaylightTime from a year and AdjustmentRule. + /// + private DaylightTimeStruct GetDaylightTime(int year, AdjustmentRule rule, int? ruleIndex) + { + TimeSpan delta = rule.DaylightDelta; + DateTime startTime; + DateTime endTime; + if (rule.NoDaylightTransitions) + { + // NoDaylightTransitions rules don't use DaylightTransition Start and End, instead + // the DateStart and DateEnd are UTC times that represent when daylight savings time changes. + // Convert the UTC times into adjusted time zone times. + + // use the previous rule to calculate the startTime, since the DST change happens w.r.t. the previous rule + AdjustmentRule previousRule = GetPreviousAdjustmentRule(rule, ruleIndex); + startTime = ConvertFromUtc(rule.DateStart, previousRule.DaylightDelta, previousRule.BaseUtcOffsetDelta); + + endTime = ConvertFromUtc(rule.DateEnd, rule.DaylightDelta, rule.BaseUtcOffsetDelta); + } + else + { + startTime = TransitionTimeToDateTime(year, rule.DaylightTransitionStart); + endTime = TransitionTimeToDateTime(year, rule.DaylightTransitionEnd); + } + return new DaylightTimeStruct(startTime, endTime, delta); + } + + /// + /// Helper function that checks if a given dateTime is in Daylight Saving Time (DST). + /// This function assumes the dateTime and AdjustmentRule are both in the same time zone. + /// + private static bool GetIsDaylightSavings(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime, TimeZoneInfoOptions flags) + { + if (rule == null) + { + return false; + } + + DateTime startTime; + DateTime endTime; + + if (time.Kind == DateTimeKind.Local) + { + // startTime and endTime represent the period from either the start of + // DST to the end and ***includes*** the potentially overlapped times + startTime = rule.IsStartDateMarkerForBeginningOfYear() ? + new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : + daylightTime.Start + daylightTime.Delta; + + endTime = rule.IsEndDateMarkerForEndOfYear() ? + new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : + daylightTime.End; + } + else + { + // startTime and endTime represent the period from either the start of DST to the end and + // ***does not include*** the potentially overlapped times + // + // -=-=-=-=-=- Pacific Standard Time -=-=-=-=-=-=- + // April 2, 2006 October 29, 2006 + // 2AM 3AM 1AM 2AM + // | +1 hr | | -1 hr | + // | | | | + // [========== DST ========>) + // + // -=-=-=-=-=- Some Weird Time Zone -=-=-=-=-=-=- + // April 2, 2006 October 29, 2006 + // 1AM 2AM 2AM 3AM + // | -1 hr | | +1 hr | + // | | | | + // [======== DST ========>) + // + bool invalidAtStart = rule.DaylightDelta > TimeSpan.Zero; + + startTime = rule.IsStartDateMarkerForBeginningOfYear() ? + new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : + daylightTime.Start + (invalidAtStart ? rule.DaylightDelta : TimeSpan.Zero); /* FUTURE: - rule.StandardDelta; */ + + endTime = rule.IsEndDateMarkerForEndOfYear() ? + new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : + daylightTime.End + (invalidAtStart ? -rule.DaylightDelta : TimeSpan.Zero); + } + + bool isDst = CheckIsDst(startTime, time, endTime, false, rule); + + // If this date was previously converted from a UTC date and we were able to detect that the local + // DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity. + if (isDst && time.Kind == DateTimeKind.Local) + { + // For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the + // clock back. It is theoretically possible to have a positive delta, (which would really be daylight + // reduction time), where you would have to wind the clock back in the begnning. + if (GetIsAmbiguousTime(time, rule, daylightTime)) + { + isDst = time.IsAmbiguousDaylightSavingTime(); + } + } + + return isDst; + } + + /// + /// Gets the offset that should be used to calculate DST start times from a UTC time. + /// + private TimeSpan GetDaylightSavingsStartOffsetFromUtc(TimeSpan baseUtcOffset, AdjustmentRule rule, int? ruleIndex) + { + if (rule.NoDaylightTransitions) + { + // use the previous rule to calculate the startTime, since the DST change happens w.r.t. the previous rule + AdjustmentRule previousRule = GetPreviousAdjustmentRule(rule, ruleIndex); + return baseUtcOffset + previousRule.BaseUtcOffsetDelta + previousRule.DaylightDelta; + } + else + { + return baseUtcOffset + rule.BaseUtcOffsetDelta; /* FUTURE: + rule.StandardDelta; */ + } + } + + /// + /// Gets the offset that should be used to calculate DST end times from a UTC time. + /// + private TimeSpan GetDaylightSavingsEndOffsetFromUtc(TimeSpan baseUtcOffset, AdjustmentRule rule) + { + // NOTE: even NoDaylightTransitions rules use this logic since DST ends w.r.t. the current rule + return baseUtcOffset + rule.BaseUtcOffsetDelta + rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */ + } + + /// + /// Helper function that checks if a given dateTime is in Daylight Saving Time (DST). + /// This function assumes the dateTime is in UTC and AdjustmentRule is in a different time zone. + /// + private static bool GetIsDaylightSavingsFromUtc(DateTime time, int year, TimeSpan utc, AdjustmentRule rule, int? ruleIndex, out bool isAmbiguousLocalDst, TimeZoneInfo zone) + { + isAmbiguousLocalDst = false; + + if (rule == null) + { + return false; + } + + // Get the daylight changes for the year of the specified time. + DaylightTimeStruct daylightTime = zone.GetDaylightTime(year, rule, ruleIndex); + + // The start and end times represent the range of universal times that are in DST for that year. + // Within that there is an ambiguous hour, usually right at the end, but at the beginning in + // the unusual case of a negative daylight savings delta. + // We need to handle the case if the current rule has daylight saving end by the end of year. If so, we need to check if next year starts with daylight saving on + // and get the actual daylight saving end time. Here is example for such case: + // Converting the UTC datetime "12/31/2011 8:00:00 PM" to "(UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)" zone. + // In 2011 the daylight saving will go through the end of the year. If we use the end of 2011 as the daylight saving end, + // that will fail the conversion because the UTC time +4 hours (3 hours for the zone UTC offset and 1 hour for daylight saving) will move us to the next year "1/1/2012 12:00 AM", + // checking against the end of 2011 will tell we are not in daylight saving which is wrong and the conversion will be off by one hour. + // Note we handle the similar case when rule year start with daylight saving and previous year end with daylight saving. + + bool ignoreYearAdjustment = false; + TimeSpan dstStartOffset = zone.GetDaylightSavingsStartOffsetFromUtc(utc, rule, ruleIndex); + DateTime startTime; + if (rule.IsStartDateMarkerForBeginningOfYear() && daylightTime.Start.Year > DateTime.MinValue.Year) + { + int? previousYearRuleIndex; + AdjustmentRule? previousYearRule = zone.GetAdjustmentRuleForTime( + new DateTime(daylightTime.Start.Year - 1, 12, 31), + out previousYearRuleIndex); + if (previousYearRule != null && previousYearRule.IsEndDateMarkerForEndOfYear()) + { + DaylightTimeStruct previousDaylightTime = zone.GetDaylightTime( + daylightTime.Start.Year - 1, + previousYearRule, + previousYearRuleIndex); + startTime = previousDaylightTime.Start - utc - previousYearRule.BaseUtcOffsetDelta; + ignoreYearAdjustment = true; + } + else + { + startTime = new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) - dstStartOffset; + } + } + else + { + startTime = daylightTime.Start - dstStartOffset; + } + + TimeSpan dstEndOffset = zone.GetDaylightSavingsEndOffsetFromUtc(utc, rule); + DateTime endTime; + if (rule.IsEndDateMarkerForEndOfYear() && daylightTime.End.Year < DateTime.MaxValue.Year) + { + int? nextYearRuleIndex; + AdjustmentRule? nextYearRule = zone.GetAdjustmentRuleForTime( + new DateTime(daylightTime.End.Year + 1, 1, 1), + out nextYearRuleIndex); + if (nextYearRule != null && nextYearRule.IsStartDateMarkerForBeginningOfYear()) + { + if (nextYearRule.IsEndDateMarkerForEndOfYear()) + { + // next year end with daylight saving on too + endTime = new DateTime(daylightTime.End.Year + 1, 12, 31) - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta; + } + else + { + DaylightTimeStruct nextdaylightTime = zone.GetDaylightTime( + daylightTime.End.Year + 1, + nextYearRule, + nextYearRuleIndex); + endTime = nextdaylightTime.End - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta; + } + ignoreYearAdjustment = true; + } + else + { + endTime = new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) - dstEndOffset; + } + } + else + { + endTime = daylightTime.End - dstEndOffset; + } + + DateTime ambiguousStart; + DateTime ambiguousEnd; + if (daylightTime.Delta.Ticks > 0) + { + ambiguousStart = endTime - daylightTime.Delta; + ambiguousEnd = endTime; + } + else + { + ambiguousStart = startTime; + ambiguousEnd = startTime - daylightTime.Delta; + } + + bool isDst = CheckIsDst(startTime, time, endTime, ignoreYearAdjustment, rule); + + // See if the resulting local time becomes ambiguous. This must be captured here or the + // DateTime will not be able to round-trip back to UTC accurately. + if (isDst) + { + isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd); + + if (!isAmbiguousLocalDst && ambiguousStart.Year != ambiguousEnd.Year) + { + // there exists an extreme corner case where the start or end period is on a year boundary and + // because of this the comparison above might have been performed for a year-early or a year-later + // than it should have been. + DateTime ambiguousStartModified; + DateTime ambiguousEndModified; + try + { + ambiguousStartModified = ambiguousStart.AddYears(1); + ambiguousEndModified = ambiguousEnd.AddYears(1); + isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd); + } + catch (ArgumentOutOfRangeException) { } + + if (!isAmbiguousLocalDst) + { + try + { + ambiguousStartModified = ambiguousStart.AddYears(-1); + ambiguousEndModified = ambiguousEnd.AddYears(-1); + isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd); + } + catch (ArgumentOutOfRangeException) { } + } + } + } + + return isDst; + } + + private static bool CheckIsDst(DateTime startTime, DateTime time, DateTime endTime, bool ignoreYearAdjustment, AdjustmentRule rule) + { + // NoDaylightTransitions AdjustmentRules should never get their year adjusted since they adjust the offset for the + // entire time period - which may be for multiple years + if (!ignoreYearAdjustment && !rule.NoDaylightTransitions) + { + int startTimeYear = startTime.Year; + int endTimeYear = endTime.Year; + + if (startTimeYear != endTimeYear) + { + endTime = endTime.AddYears(startTimeYear - endTimeYear); + } + + int timeYear = time.Year; + + if (startTimeYear != timeYear) + { + time = time.AddYears(startTimeYear - timeYear); + } + } + + if (startTime > endTime) + { + // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year. + // Note, the summer in the southern hemisphere begins late in the year. + return (time < endTime || time >= startTime); + } + else if (rule.NoDaylightTransitions) + { + // In NoDaylightTransitions AdjustmentRules, the startTime is always before the endTime, + // and both the start and end times are inclusive + return time >= startTime && time <= endTime; + } + else + { + // In northern hemisphere, the daylight saving time starts in the middle of the year. + return time >= startTime && time < endTime; + } + } + + /// + /// Returns true when the dateTime falls into an ambiguous time range. + /// + /// For example, in Pacific Standard Time on Sunday, October 29, 2006 time jumps from + /// 2AM to 1AM. This means the timeline on Sunday proceeds as follows: + /// 12AM ... [1AM ... 1:59:59AM -> 1AM ... 1:59:59AM] 2AM ... 3AM ... + /// + /// In this example, any DateTime values that fall into the [1AM - 1:59:59AM] range + /// are ambiguous; as it is unclear if these times are in Daylight Saving Time. + /// + private static bool GetIsAmbiguousTime(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime) + { + bool isAmbiguous = false; + if (rule == null || rule.DaylightDelta == TimeSpan.Zero) + { + return isAmbiguous; + } + + DateTime startAmbiguousTime; + DateTime endAmbiguousTime; + + // if at DST start we transition forward in time then there is an ambiguous time range at the DST end + if (rule.DaylightDelta > TimeSpan.Zero) + { + if (rule.IsEndDateMarkerForEndOfYear()) + { // year end with daylight on so there is no ambiguous time + return false; + } + startAmbiguousTime = daylightTime.End; + endAmbiguousTime = daylightTime.End - rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */ + } + else + { + if (rule.IsStartDateMarkerForBeginningOfYear()) + { // year start with daylight on so there is no ambiguous time + return false; + } + startAmbiguousTime = daylightTime.Start; + endAmbiguousTime = daylightTime.Start + rule.DaylightDelta; /* FUTURE: - rule.StandardDelta; */ + } + + isAmbiguous = (time >= endAmbiguousTime && time < startAmbiguousTime); + + if (!isAmbiguous && startAmbiguousTime.Year != endAmbiguousTime.Year) + { + // there exists an extreme corner case where the start or end period is on a year boundary and + // because of this the comparison above might have been performed for a year-early or a year-later + // than it should have been. + DateTime startModifiedAmbiguousTime; + DateTime endModifiedAmbiguousTime; + try + { + startModifiedAmbiguousTime = startAmbiguousTime.AddYears(1); + endModifiedAmbiguousTime = endAmbiguousTime.AddYears(1); + isAmbiguous = (time >= endModifiedAmbiguousTime && time < startModifiedAmbiguousTime); + } + catch (ArgumentOutOfRangeException) { } + + if (!isAmbiguous) + { + try + { + startModifiedAmbiguousTime = startAmbiguousTime.AddYears(-1); + endModifiedAmbiguousTime = endAmbiguousTime.AddYears(-1); + isAmbiguous = (time >= endModifiedAmbiguousTime && time < startModifiedAmbiguousTime); + } + catch (ArgumentOutOfRangeException) { } + } + } + return isAmbiguous; + } + + /// + /// Helper function that checks if a given DateTime is in an invalid time ("time hole") + /// A "time hole" occurs at a DST transition point when time jumps forward; + /// For example, in Pacific Standard Time on Sunday, April 2, 2006 time jumps from + /// 1:59:59.9999999 to 3AM. The time range 2AM to 2:59:59.9999999AM is the "time hole". + /// A "time hole" is not limited to only occurring at the start of DST, and may occur at + /// the end of DST as well. + /// + private static bool GetIsInvalidTime(DateTime time, AdjustmentRule rule, DaylightTimeStruct daylightTime) + { + bool isInvalid = false; + if (rule == null || rule.DaylightDelta == TimeSpan.Zero) + { + return isInvalid; + } + + DateTime startInvalidTime; + DateTime endInvalidTime; + + // if at DST start we transition forward in time then there is an ambiguous time range at the DST end + if (rule.DaylightDelta < TimeSpan.Zero) + { + // if the year ends with daylight saving on then there cannot be any time-hole's in that year. + if (rule.IsEndDateMarkerForEndOfYear()) + return false; + + startInvalidTime = daylightTime.End; + endInvalidTime = daylightTime.End - rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */ + } + else + { + // if the year starts with daylight saving on then there cannot be any time-hole's in that year. + if (rule.IsStartDateMarkerForBeginningOfYear()) + return false; + + startInvalidTime = daylightTime.Start; + endInvalidTime = daylightTime.Start + rule.DaylightDelta; /* FUTURE: - rule.StandardDelta; */ + } + + isInvalid = (time >= startInvalidTime && time < endInvalidTime); + + if (!isInvalid && startInvalidTime.Year != endInvalidTime.Year) + { + // there exists an extreme corner case where the start or end period is on a year boundary and + // because of this the comparison above might have been performed for a year-early or a year-later + // than it should have been. + DateTime startModifiedInvalidTime; + DateTime endModifiedInvalidTime; + try + { + startModifiedInvalidTime = startInvalidTime.AddYears(1); + endModifiedInvalidTime = endInvalidTime.AddYears(1); + isInvalid = (time >= startModifiedInvalidTime && time < endModifiedInvalidTime); + } + catch (ArgumentOutOfRangeException) { } + + if (!isInvalid) + { + try + { + startModifiedInvalidTime = startInvalidTime.AddYears(-1); + endModifiedInvalidTime = endInvalidTime.AddYears(-1); + isInvalid = (time >= startModifiedInvalidTime && time < endModifiedInvalidTime); + } + catch (ArgumentOutOfRangeException) { } + } + } + return isInvalid; + } + + /// + /// Helper function that calculates the UTC offset for a dateTime in a timeZone. + /// This function assumes that the dateTime is already converted into the timeZone. + /// + private static TimeSpan GetUtcOffset(DateTime time, TimeZoneInfo zone, TimeZoneInfoOptions flags) + { + TimeSpan baseOffset = zone.BaseUtcOffset; + int? ruleIndex; + AdjustmentRule? rule = zone.GetAdjustmentRuleForTime(time, out ruleIndex); + + if (rule != null) + { + baseOffset = baseOffset + rule.BaseUtcOffsetDelta; + if (rule.HasDaylightSaving) + { + DaylightTimeStruct daylightTime = zone.GetDaylightTime(time.Year, rule, ruleIndex); + bool isDaylightSavings = GetIsDaylightSavings(time, rule, daylightTime, flags); + baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); + } + } + + return baseOffset; + } + + /// + /// Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone. + /// This function assumes that the dateTime is represented in UTC and has *not* already been converted into the timeZone. + /// + private static TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone) + { + bool isDaylightSavings; + return GetUtcOffsetFromUtc(time, zone, out isDaylightSavings); + } + + /// + /// Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone. + /// This function assumes that the dateTime is represented in UTC and has *not* already been converted into the timeZone. + /// + private static TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone, out bool isDaylightSavings) + { + bool isAmbiguousLocalDst; + return GetUtcOffsetFromUtc(time, zone, out isDaylightSavings, out isAmbiguousLocalDst); + } + + /// + /// Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone. + /// This function assumes that the dateTime is represented in UTC and has *not* already been converted into the timeZone. + /// + internal static TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone, out bool isDaylightSavings, out bool isAmbiguousLocalDst) + { + isDaylightSavings = false; + isAmbiguousLocalDst = false; + TimeSpan baseOffset = zone.BaseUtcOffset; + int year; + int? ruleIndex; + AdjustmentRule? rule; + + if (time > s_maxDateOnly) + { + rule = zone.GetAdjustmentRuleForTime(DateTime.MaxValue, out ruleIndex); + year = 9999; + } + else if (time < s_minDateOnly) + { + rule = zone.GetAdjustmentRuleForTime(DateTime.MinValue, out ruleIndex); + year = 1; + } + else + { + rule = zone.GetAdjustmentRuleForTime(time, dateTimeisUtc: true, ruleIndex: out ruleIndex); + Debug.Assert(rule == null || ruleIndex.HasValue, + "If GetAdjustmentRuleForTime returned an AdjustmentRule, ruleIndex should also be set."); + + // As we get the associated rule using the adjusted targetTime, we should use the adjusted year (targetTime.Year) too as after adding the baseOffset, + // sometimes the year value can change if the input datetime was very close to the beginning or the end of the year. Examples of such cases: + // Libya Standard Time when used with the date 2011-12-31T23:59:59.9999999Z + // "W. Australia Standard Time" used with date 2005-12-31T23:59:00.0000000Z + DateTime targetTime = time + baseOffset; + year = targetTime.Year; + } + + if (rule != null) + { + baseOffset = baseOffset + rule.BaseUtcOffsetDelta; + if (rule.HasDaylightSaving) + { + isDaylightSavings = GetIsDaylightSavingsFromUtc(time, year, zone._baseUtcOffset, rule, ruleIndex, out isAmbiguousLocalDst, zone); + baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */); + } + } + + return baseOffset; + } + + /// + /// Helper function that converts a year and TransitionTime into a DateTime. + /// + internal static DateTime TransitionTimeToDateTime(int year, TransitionTime transitionTime) + { + DateTime value; + DateTime timeOfDay = transitionTime.TimeOfDay; + + if (transitionTime.IsFixedDateRule) + { + // create a DateTime from the passed in year and the properties on the transitionTime + + // if the day is out of range for the month then use the last day of the month + int day = DateTime.DaysInMonth(year, transitionTime.Month); + + value = new DateTime(year, transitionTime.Month, (day < transitionTime.Day) ? day : transitionTime.Day, + timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond); + } + else + { + if (transitionTime.Week <= 4) + { + // + // Get the (transitionTime.Week)th Sunday. + // + value = new DateTime(year, transitionTime.Month, 1, + timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond); + + int dayOfWeek = (int)value.DayOfWeek; + int delta = (int)transitionTime.DayOfWeek - dayOfWeek; + if (delta < 0) + { + delta += 7; + } + delta += 7 * (transitionTime.Week - 1); + + if (delta > 0) + { + value = value.AddDays(delta); + } + } + else + { + // + // If TransitionWeek is greater than 4, we will get the last week. + // + int daysInMonth = DateTime.DaysInMonth(year, transitionTime.Month); + value = new DateTime(year, transitionTime.Month, daysInMonth, + timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond); + + // This is the day of week for the last day of the month. + int dayOfWeek = (int)value.DayOfWeek; + int delta = dayOfWeek - (int)transitionTime.DayOfWeek; + if (delta < 0) + { + delta += 7; + } + + if (delta > 0) + { + value = value.AddDays(-delta); + } + } + } + return value; + } + + /// + /// Helper function for retrieving a TimeZoneInfo object by time_zone_name. + /// + /// This function may return null. + /// + /// assumes cachedData lock is taken + /// + private static TimeZoneInfoResult TryGetTimeZone(string id, bool dstDisabled, out TimeZoneInfo? value, out Exception? e, CachedData cachedData, bool alwaysFallbackToLocalMachine = false) + { + Debug.Assert(Monitor.IsEntered(cachedData)); + + TimeZoneInfoResult result = TimeZoneInfoResult.Success; + e = null; + TimeZoneInfo? match = null; + + // check the cache + if (cachedData._systemTimeZones != null) + { + if (cachedData._systemTimeZones.TryGetValue(id, out match)) + { + if (dstDisabled && match._supportsDaylightSavingTime) + { + // we found a cache hit but we want a time zone without DST and this one has DST data + value = CreateCustomTimeZone(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName); + } + else + { + value = new TimeZoneInfo(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName, + match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false); + } + return result; + } + } + + // Fall back to reading from the local machine when the cache is not fully populated. + // On UNIX, there may be some tzfiles that aren't in the zones.tab file, and thus aren't returned from GetSystemTimeZones(). + // If a caller asks for one of these zones before calling GetSystemTimeZones(), the time zone is returned successfully. But if + // GetSystemTimeZones() is called first, FindSystemTimeZoneById will throw TimeZoneNotFoundException, which is inconsistent. + // To fix this, when 'alwaysFallbackToLocalMachine' is true, even if _allSystemTimeZonesRead is true, try reading the tzfile + // from disk, but don't add the time zone to the list returned from GetSystemTimeZones(). These time zones will only be + // available if asked for directly. + if (!cachedData._allSystemTimeZonesRead || alwaysFallbackToLocalMachine) + { + result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData); + } + else + { + result = TimeZoneInfoResult.TimeZoneNotFoundException; + value = null; + } + + return result; + } + + private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool dstDisabled, out TimeZoneInfo? value, out Exception? e, CachedData cachedData) + { + TimeZoneInfoResult result; + TimeZoneInfo? match; + + result = TryGetTimeZoneFromLocalMachine(id, out match, out e); + + if (result == TimeZoneInfoResult.Success) + { + if (cachedData._systemTimeZones == null) + cachedData._systemTimeZones = new Dictionary(StringComparer.OrdinalIgnoreCase); + + cachedData._systemTimeZones.Add(id, match!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + + if (dstDisabled && match!._supportsDaylightSavingTime) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + { + // we found a cache hit but we want a time zone without DST and this one has DST data + value = CreateCustomTimeZone(match._id, match._baseUtcOffset, match._displayName, match._standardDisplayName); + } + else + { + value = new TimeZoneInfo(match!._id, match._baseUtcOffset, match._displayName, match._standardDisplayName, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 + match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false); + } + } + else + { + value = null; + } + + return result; + } + + /// + /// Helper function that performs all of the validation checks for the + /// factory methods and deserialization callback. + /// + private static void ValidateTimeZoneInfo(string id, TimeSpan baseUtcOffset, AdjustmentRule[]? adjustmentRules, out bool adjustmentRulesSupportDst) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + if (id.Length == 0) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidId, id), nameof(id)); + } + + if (UtcOffsetOutOfRange(baseUtcOffset)) + { + throw new ArgumentOutOfRangeException(nameof(baseUtcOffset), SR.ArgumentOutOfRange_UtcOffset); + } + + if (baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0) + { + throw new ArgumentException(SR.Argument_TimeSpanHasSeconds, nameof(baseUtcOffset)); + } + + adjustmentRulesSupportDst = false; + + // + // "adjustmentRules" can either be null or a valid array of AdjustmentRule objects. + // A valid array is one that does not contain any null elements and all elements + // are sorted in chronological order + // + + if (adjustmentRules != null && adjustmentRules.Length != 0) + { + adjustmentRulesSupportDst = true; + AdjustmentRule? prev = null; + AdjustmentRule? current = null; + for (int i = 0; i < adjustmentRules.Length; i++) + { + prev = current; + current = adjustmentRules[i]; + + if (current == null) + { + throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesNoNulls); + } + + if (!IsValidAdjustmentRuleOffest(baseUtcOffset, current)) + { + throw new InvalidTimeZoneException(SR.ArgumentOutOfRange_UtcOffsetAndDaylightDelta); + } + + if (prev != null && current.DateStart <= prev.DateEnd) + { + // verify the rules are in chronological order and the DateStart/DateEnd do not overlap + throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesOutOfOrder); + } + } + } + } + + private static readonly TimeSpan MaxOffset = TimeSpan.FromHours(14.0); + private static readonly TimeSpan MinOffset = -MaxOffset; + + /// + /// Helper function that validates the TimeSpan is within +/- 14.0 hours + /// + internal static bool UtcOffsetOutOfRange(TimeSpan offset) => + offset < MinOffset || offset > MaxOffset; + + private static TimeSpan GetUtcOffset(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule) + { + return baseUtcOffset + + adjustmentRule.BaseUtcOffsetDelta + + (adjustmentRule.HasDaylightSaving ? adjustmentRule.DaylightDelta : TimeSpan.Zero); + } + + /// + /// Helper function that performs adjustment rule validation + /// + private static bool IsValidAdjustmentRuleOffest(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule) + { + TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule); + return !UtcOffsetOutOfRange(utcOffset); + } + + /// + /// Normalize adjustment rule offset so that it is within valid range + /// This method should not be called at all but is here in case something changes in the future + /// or if really old time zones are present on the OS (no combination is known at the moment) + /// + private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, ref AdjustmentRule adjustmentRule) + { + // Certain time zones such as: + // Time Zone start date end date offset + // ----------------------------------------------------- + // America/Yakutat 0001-01-01 1867-10-18 14:41:00 + // America/Yakutat 1867-10-18 1900-08-20 14:41:00 + // America/Sitka 0001-01-01 1867-10-18 14:58:00 + // America/Sitka 1867-10-18 1900-08-20 14:58:00 + // Asia/Manila 0001-01-01 1844-12-31 -15:56:00 + // Pacific/Guam 0001-01-01 1845-01-01 -14:21:00 + // Pacific/Saipan 0001-01-01 1845-01-01 -14:21:00 + // + // have larger offset than currently supported by framework. + // If for whatever reason we find that time zone exceeding max + // offset of 14h this function will truncate it to the max valid offset. + // Updating max offset may cause problems with interacting with SQL server + // which uses SQL DATETIMEOFFSET field type which was originally designed to be + // bit-for-bit compatible with DateTimeOffset. + + TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule); + + // utc base offset delta increment + TimeSpan adjustment = TimeSpan.Zero; + + if (utcOffset > MaxOffset) + { + adjustment = MaxOffset - utcOffset; + } + else if (utcOffset < MinOffset) + { + adjustment = MinOffset - utcOffset; + } + + if (adjustment != TimeSpan.Zero) + { + adjustmentRule = AdjustmentRule.CreateAdjustmentRule( + adjustmentRule.DateStart, + adjustmentRule.DateEnd, + adjustmentRule.DaylightDelta, + adjustmentRule.DaylightTransitionStart, + adjustmentRule.DaylightTransitionEnd, + adjustmentRule.BaseUtcOffsetDelta + adjustment, + adjustmentRule.NoDaylightTransitions); + } + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Tuple.cs b/src/System.Private.CoreLib/shared/System/Tuple.cs index f9111b9b408a..cf996005129d 100644 --- a/src/System.Private.CoreLib/shared/System/Tuple.cs +++ b/src/System.Private.CoreLib/shared/System/Tuple.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -115,12 +116,12 @@ public Tuple(T1 item1) m_Item1 = item1; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -132,7 +133,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -185,7 +186,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -214,12 +215,12 @@ public Tuple(T1 item1, T2 item2) m_Item2 = item2; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -231,7 +232,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -292,7 +293,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -328,12 +329,12 @@ public Tuple(T1 item1, T2 item2, T3 item3) m_Item3 = item3; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -345,7 +346,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -412,7 +413,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -453,12 +454,12 @@ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4) m_Item4 = item4; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -470,7 +471,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -543,7 +544,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -589,12 +590,12 @@ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) m_Item5 = item5; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -606,7 +607,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -685,7 +686,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -736,12 +737,12 @@ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) m_Item6 = item6; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -753,7 +754,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -838,7 +839,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -894,12 +895,12 @@ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item m_Item7 = item7; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -911,7 +912,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -1002,7 +1003,7 @@ string ITupleInternal.ToString(StringBuilder sb) /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -1068,12 +1069,12 @@ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item m_Rest = rest; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null) return false; @@ -1085,7 +1086,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7) && comparer.Equals(m_Rest, objTuple.m_Rest); } - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default); } @@ -1140,7 +1141,7 @@ public override int GetHashCode() int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple - ITupleInternal t = (ITupleInternal)m_Rest; + ITupleInternal t = (ITupleInternal)m_Rest!; // TODO-NULLABLE-GENERIC if (t.Length >= 8) { return t.GetHashCode(comparer); } // In this case, the rest memeber has less than 8 elements so we need to combine some our elements with the elements in rest @@ -1193,7 +1194,7 @@ string ITupleInternal.ToString(StringBuilder sb) sb.Append(", "); sb.Append(m_Item7); sb.Append(", "); - return ((ITupleInternal)m_Rest).ToString(sb); + return ((ITupleInternal)m_Rest!).ToString(sb); // TODO-NULLABLE-GENERIC } /// @@ -1203,14 +1204,14 @@ int ITuple.Length { get { - return 7 + ((ITupleInternal)Rest).Length; + return 7 + ((ITupleInternal)Rest!).Length; // TODO-NULLABLE-GENERIC } } /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -1232,7 +1233,7 @@ object ITuple.this[int index] return Item7; } - return ((ITupleInternal)Rest)[index - 7]; + return ((ITupleInternal)Rest!)[index - 7]; // TODO-NULLABLE-GENERIC } } } diff --git a/src/System.Private.CoreLib/shared/System/TupleExtensions.cs b/src/System.Private.CoreLib/shared/System/TupleExtensions.cs index 106a88a08b6e..bf1aa07f9bbd 100644 --- a/src/System.Private.CoreLib/shared/System/TupleExtensions.cs +++ b/src/System.Private.CoreLib/shared/System/TupleExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; using System.Runtime.CompilerServices; diff --git a/src/System.Private.CoreLib/shared/System/Type.cs b/src/System.Private.CoreLib/shared/System/Type.cs index 8b19fbca52ac..d2a31cbf675b 100644 --- a/src/System.Private.CoreLib/shared/System/Type.cs +++ b/src/System.Private.CoreLib/shared/System/Type.cs @@ -281,8 +281,9 @@ public static TypeCode GetTypeCode(Type type) } protected virtual TypeCode GetTypeCodeImpl() { - if (this != UnderlyingSystemType && UnderlyingSystemType != null) - return Type.GetTypeCode(UnderlyingSystemType); + Type systemType = UnderlyingSystemType; + if (this != systemType && systemType != null) + return Type.GetTypeCode(systemType); return TypeCode.Object; } diff --git a/src/System.Private.CoreLib/shared/System/TypeCode.cs b/src/System.Private.CoreLib/shared/System/TypeCode.cs index 296198656b77..08216dc33bfa 100644 --- a/src/System.Private.CoreLib/shared/System/TypeCode.cs +++ b/src/System.Private.CoreLib/shared/System/TypeCode.cs @@ -21,6 +21,7 @@ // of an object is TypeCode.Object, a further instance-of check can be used to // determine if the object is one of these values. +#nullable enable namespace System { public enum TypeCode diff --git a/src/System.Private.CoreLib/shared/System/UIntPtr.cs b/src/System.Private.CoreLib/shared/System/UIntPtr.cs index 9197792e2aaf..c6372f0ee327 100644 --- a/src/System.Private.CoreLib/shared/System/UIntPtr.cs +++ b/src/System.Private.CoreLib/shared/System/UIntPtr.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -68,7 +69,7 @@ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext contex info.AddValue("value", ToUInt64()); } - public unsafe override bool Equals(object obj) + public unsafe override bool Equals(object? obj) { if (obj is UIntPtr) { diff --git a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs index c214afdc7113..5f4e0109c639 100644 --- a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs +++ b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public class UnhandledExceptionEventArgs : EventArgs diff --git a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs index 58f1eb5145d2..36ce061a409d 100644 --- a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs +++ b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { public delegate void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e); diff --git a/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs b/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs index 53323c32bc63..6ebbb8af421d 100644 --- a/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs +++ b/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.Serialization; namespace System @@ -16,7 +17,7 @@ public sealed class UnitySerializationHolder : ISerializable, IObjectReference { internal const int NullUnity = 0x0002; private readonly int _unityType; - private readonly string _data; + private readonly string? _data; /// /// A helper method that returns the SerializationInfo that a class utilizing diff --git a/src/System.Private.CoreLib/shared/System/ValueTuple.cs b/src/System.Private.CoreLib/shared/System/ValueTuple.cs index fdcead2def87..0fd476e00ff6 100644 --- a/src/System.Private.CoreLib/shared/System/ValueTuple.cs +++ b/src/System.Private.CoreLib/shared/System/ValueTuple.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -38,7 +39,7 @@ public struct ValueTuple /// /// The object to compare with this instance. /// if is a . - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple; } @@ -51,12 +52,12 @@ public bool Equals(ValueTuple other) return true; } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { return other is ValueTuple; } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -135,7 +136,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -330,7 +331,7 @@ public ValueTuple(T1 item1) /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -350,7 +351,7 @@ public bool Equals(ValueTuple other) return EqualityComparer.Default.Equals(Item1, other.Item1); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -359,7 +360,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) return comparer.Equals(Item1, objTuple.Item1); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -446,7 +447,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -505,7 +506,7 @@ public ValueTuple(T1 item1, T2 item2) /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -543,7 +544,7 @@ public bool Equals(ValueTuple other) /// implementation. If this method call returns , the method is /// called again and passed the values of the two instances. /// - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -553,7 +554,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Item2, objTuple.Item2); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -652,7 +653,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -720,7 +721,7 @@ public ValueTuple(T1 item1, T2 item2, T3 item3) /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -742,7 +743,7 @@ public bool Equals(ValueTuple other) && EqualityComparer.Default.Equals(Item3, other.Item3); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -753,7 +754,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Item3, objTuple.Item3); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -858,7 +859,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -935,7 +936,7 @@ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4) /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -958,7 +959,7 @@ public bool Equals(ValueTuple other) && EqualityComparer.Default.Equals(Item4, other.Item4); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -970,7 +971,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Item4, objTuple.Item4); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -1083,7 +1084,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -1169,7 +1170,7 @@ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -1193,7 +1194,7 @@ public bool Equals(ValueTuple other) && EqualityComparer.Default.Equals(Item5, other.Item5); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -1206,7 +1207,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Item5, objTuple.Item5); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -1327,7 +1328,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -1422,7 +1423,7 @@ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -1447,7 +1448,7 @@ public bool Equals(ValueTuple other) && EqualityComparer.Default.Equals(Item6, other.Item6); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -1461,7 +1462,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Item6, objTuple.Item6); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -1590,7 +1591,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -1694,7 +1695,7 @@ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -1720,7 +1721,7 @@ public bool Equals(ValueTuple other) && EqualityComparer.Default.Equals(Item7, other.Item7); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -1735,7 +1736,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Item7, objTuple.Item7); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -1872,7 +1873,7 @@ string IValueTupleInternal.ToStringEnd() /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -1991,7 +1992,7 @@ public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 /// Its components are equal to those of the current instance. Equality is determined by the default object equality comparer for each component. /// /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueTuple && Equals((ValueTuple)obj); } @@ -2018,7 +2019,7 @@ public bool Equals(ValueTuple other) && EqualityComparer.Default.Equals(Rest, other.Rest); } - bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) + bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) { if (other == null || !(other is ValueTuple)) return false; @@ -2034,7 +2035,7 @@ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) && comparer.Equals(Rest, objTuple.Rest); } - int IComparable.CompareTo(object other) + int IComparable.CompareTo(object? other) { if (other == null) return 1; @@ -2122,7 +2123,7 @@ int IStructuralComparable.CompareTo(object other, IComparer comparer) public override int GetHashCode() { // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple - IValueTupleInternal rest = Rest as IValueTupleInternal; + IValueTupleInternal? rest = Rest as IValueTupleInternal; if (rest == null) { return ValueTuple.CombineHashCodes(Item1?.GetHashCode() ?? 0, @@ -2198,7 +2199,7 @@ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) private int GetHashCodeCore(IEqualityComparer comparer) { // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple - IValueTupleInternal rest = Rest as IValueTupleInternal; + IValueTupleInternal? rest = Rest as IValueTupleInternal; if (rest == null) { return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), @@ -2256,7 +2257,7 @@ int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) /// public override string ToString() { - IValueTupleInternal rest = Rest as IValueTupleInternal; + IValueTupleInternal? rest = Rest as IValueTupleInternal; if (rest == null) { return "(" + Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")"; @@ -2269,7 +2270,7 @@ public override string ToString() string IValueTupleInternal.ToStringEnd() { - IValueTupleInternal rest = Rest as IValueTupleInternal; + IValueTupleInternal? rest = Rest as IValueTupleInternal; if (rest == null) { return Item1?.ToString() + ", " + Item2?.ToString() + ", " + Item3?.ToString() + ", " + Item4?.ToString() + ", " + Item5?.ToString() + ", " + Item6?.ToString() + ", " + Item7?.ToString() + ", " + Rest.ToString() + ")"; @@ -2287,7 +2288,7 @@ int ITuple.Length { get { - IValueTupleInternal rest = Rest as IValueTupleInternal; + IValueTupleInternal? rest = Rest as IValueTupleInternal; return rest == null ? 8 : 7 + rest.Length; } } @@ -2295,7 +2296,7 @@ int ITuple.Length /// /// Get the element at position . /// - object ITuple.this[int index] + object? ITuple.this[int index] { get { @@ -2317,7 +2318,7 @@ object ITuple.this[int index] return Item7; } - IValueTupleInternal rest = Rest as IValueTupleInternal; + IValueTupleInternal? rest = Rest as IValueTupleInternal; if (rest == null) { if (index == 7) diff --git a/src/System.Private.CoreLib/shared/System/Version.cs b/src/System.Private.CoreLib/shared/System/Version.cs index 359837f348c7..67ddf8597f3f 100644 --- a/src/System.Private.CoreLib/shared/System/Version.cs +++ b/src/System.Private.CoreLib/shared/System/Version.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; using System.Diagnostics; using System.Text; @@ -17,7 +18,7 @@ namespace System [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public sealed class Version : ICloneable, IComparable, IComparable, IEquatable, ISpanFormattable + public sealed class Version : ICloneable, IComparable, IComparable, IEquatable, ISpanFormattable { // AssemblyName depends on the order staying the same private readonly int _Major; // Do not rename (binary serialization) @@ -135,23 +136,22 @@ public short MinorRevision get { return (short)(_Revision & 0xFFFF); } } - public int CompareTo(object version) + public int CompareTo(object? version) { if (version == null) { return 1; } - Version v = version as Version; - if (v == null) + if (version is Version v) { - throw new ArgumentException(SR.Arg_MustBeVersion); + return CompareTo(v); } - return CompareTo(v); + throw new ArgumentException(SR.Arg_MustBeVersion); } - public int CompareTo(Version value) + public int CompareTo(Version? value) { return object.ReferenceEquals(value, this) ? 0 : @@ -163,12 +163,12 @@ public int CompareTo(Version value) 0; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as Version); } - public bool Equals(Version obj) + public bool Equals(Version? obj) { return object.ReferenceEquals(obj, this) || (!(obj is null) && @@ -230,7 +230,7 @@ public bool TryFormat(Span destination, int fieldCount, out int charsWritt return false; } - bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider provider) + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) { // format and provider are ignored. return TryFormat(destination, out charsWritten); @@ -301,13 +301,13 @@ public static Version Parse(string input) throw new ArgumentNullException(nameof(input)); } - return ParseVersion(input.AsSpan(), throwOnFailure: true); + return ParseVersion(input.AsSpan(), throwOnFailure: true)!; } public static Version Parse(ReadOnlySpan input) => - ParseVersion(input, throwOnFailure: true); + ParseVersion(input, throwOnFailure: true)!; - public static bool TryParse(string input, out Version result) + public static bool TryParse(string? input, out Version? result) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { if (input == null) { @@ -318,10 +318,10 @@ public static bool TryParse(string input, out Version result) return (result = ParseVersion(input.AsSpan(), throwOnFailure: false)) != null; } - public static bool TryParse(ReadOnlySpan input, out Version result) => + public static bool TryParse(ReadOnlySpan input, out Version? result) => (result = ParseVersion(input, throwOnFailure: false)) != null; - private static Version ParseVersion(ReadOnlySpan input, bool throwOnFailure) + private static Version? ParseVersion(ReadOnlySpan input, bool throwOnFailure) { // Find the separator between major and minor. It must exist. int majorEnd = input.IndexOf('.'); @@ -408,7 +408,7 @@ private static bool TryParseComponent(ReadOnlySpan component, string compo // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Version v1, Version v2) + public static bool operator ==(Version? v1, Version? v2) { // Test "right" first to allow branch elimination when inlined for null checks (== null) // so it can become a simple test @@ -422,31 +422,37 @@ private static bool TryParseComponent(ReadOnlySpan component, string compo return ReferenceEquals(v2, v1) ? true : v2.Equals(v1); } - public static bool operator !=(Version v1, Version v2) + public static bool operator !=(Version? v1, Version? v2) { return !(v1 == v2); } - public static bool operator <(Version v1, Version v2) + public static bool operator <(Version? v1, Version? v2) { - if ((object)v1 == null) - throw new ArgumentNullException(nameof(v1)); + if (v1 is null) + { + return !(v2 is null); + } + return (v1.CompareTo(v2) < 0); } - public static bool operator <=(Version v1, Version v2) + public static bool operator <=(Version? v1, Version? v2) { - if ((object)v1 == null) - throw new ArgumentNullException(nameof(v1)); + if (v1 is null) + { + return true; + } + return (v1.CompareTo(v2) <= 0); } - public static bool operator >(Version v1, Version v2) + public static bool operator >(Version? v1, Version? v2) { return (v2 < v1); } - public static bool operator >=(Version v1, Version v2) + public static bool operator >=(Version? v1, Version? v2) { return (v2 <= v1); } diff --git a/src/System.Private.CoreLib/shared/System/Void.cs b/src/System.Private.CoreLib/shared/System/Void.cs index 5162e6ad02ad..f0a7ddd3a025 100644 --- a/src/System.Private.CoreLib/shared/System/Void.cs +++ b/src/System.Private.CoreLib/shared/System/Void.cs @@ -7,6 +7,7 @@ // This class represents the void return type //////////////////////////////////////////////////////////////////////////////// +#nullable enable namespace System { // This class represents the void return type diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs index d1c6aa9bb7a4..e080a31f1b38 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections.Generic; using System.Diagnostics; @@ -23,9 +24,9 @@ namespace Internal.Runtime.InteropServices public interface IClassFactory { void CreateInstance( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, ref Guid riid, - [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + [MarshalAs(UnmanagedType.Interface)] out object? ppvObject); void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); } @@ -49,9 +50,9 @@ internal struct LICINFO internal interface IClassFactory2 : IClassFactory { new void CreateInstance( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, ref Guid riid, - [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + [MarshalAs(UnmanagedType.Interface)] out object? ppvObject); new void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); @@ -62,8 +63,8 @@ void RequestLicKey( [MarshalAs(UnmanagedType.BStr)] out string pBstrKey); void CreateInstanceLic( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, - [MarshalAs(UnmanagedType.Interface)] object pUnkReserved, + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object? pUnkReserved, ref Guid riid, [MarshalAs(UnmanagedType.BStr)] string bstrKey, [MarshalAs(UnmanagedType.Interface)] out object ppvObject); @@ -95,7 +96,7 @@ public static class ComActivator { // Collection of all ALCs used for COM activation. In the event we want to support // unloadable COM server ALCs, this will need to be changed. - private static Dictionary s_AssemblyLoadContexts = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + private static readonly Dictionary s_AssemblyLoadContexts = new Dictionary(StringComparer.InvariantCultureIgnoreCase); /// /// Entry point for unmanaged COM activation API from managed code @@ -149,9 +150,9 @@ public unsafe static int GetClassFactoryForTypeInternal(ref ComActivationContext { ClassId = cxtInt.ClassId, InterfaceId = cxtInt.InterfaceId, - AssemblyPath = Marshal.PtrToStringUni(new IntPtr(cxtInt.AssemblyPathBuffer)), - AssemblyName = Marshal.PtrToStringUni(new IntPtr(cxtInt.AssemblyNameBuffer)), - TypeName = Marshal.PtrToStringUni(new IntPtr(cxtInt.TypeNameBuffer)) + AssemblyPath = Marshal.PtrToStringUni(new IntPtr(cxtInt.AssemblyPathBuffer))!, + AssemblyName = Marshal.PtrToStringUni(new IntPtr(cxtInt.AssemblyNameBuffer))!, + TypeName = Marshal.PtrToStringUni(new IntPtr(cxtInt.TypeNameBuffer))! }; object cf = GetClassFactoryForType(cxt); @@ -235,12 +236,12 @@ public BasicClassFactory(Guid clsid, Type classType) _classType = classType; } - public static void ValidateInterfaceRequest(Type classType, ref Guid riid, object outer) + public static Type GetValidatedInterfaceType(Type classType, ref Guid riid, object? outer) { Debug.Assert(classType != null); if (riid == Marshal.IID_IUnknown) { - return; + return typeof(object); } // Aggregation can only be done when requesting IUnknown. @@ -250,23 +251,40 @@ public static void ValidateInterfaceRequest(Type classType, ref Guid riid, objec throw new COMException(string.Empty, CLASS_E_NOAGGREGATION); } - bool found = false; - // Verify the class implements the desired interface foreach (Type i in classType.GetInterfaces()) { if (i.GUID == riid) { - found = true; - break; + return i; } } - if (!found) + // E_NOINTERFACE + throw new InvalidCastException(); + } + + public static void ValidateObjectIsMarshallableAsInterface(object obj, Type interfaceType) + { + // If the requested "interface type" is type object then return + // because type object is always marshallable. + if (interfaceType == typeof(object)) { - // E_NOINTERFACE - throw new InvalidCastException(); + return; } + + Debug.Assert(interfaceType.IsInterface); + + // The intent of this call is to validate the interface can be + // marshalled to native code. An exception will be thrown if the + // type is unable to be marshalled to native code. + // Scenarios where this is relevant: + // - Interfaces that use Generics + // - Interfaces that define implementation + IntPtr ptr = Marshal.GetComInterfaceForObject(obj, interfaceType, CustomQueryInterfaceMode.Ignore); + + // Decrement the above 'Marshal.GetComInterfaceForObject()' + Marshal.Release(ptr); } public static object CreateAggregatedObject(object pUnkOuter, object comObject) @@ -282,22 +300,24 @@ public static object CreateAggregatedObject(object pUnkOuter, object comObject) finally { // Decrement the above 'Marshal.GetIUnknownForObject()' - Marshal.ReleaseComObject(pUnkOuter); + Marshal.Release(outerPtr); } } public void CreateInstance( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, ref Guid riid, - [MarshalAs(UnmanagedType.Interface)] out object ppvObject) + [MarshalAs(UnmanagedType.Interface)] out object? ppvObject) { - BasicClassFactory.ValidateInterfaceRequest(_classType, ref riid, pUnkOuter); + Type interfaceType = BasicClassFactory.GetValidatedInterfaceType(_classType, ref riid, pUnkOuter); - ppvObject = Activator.CreateInstance(_classType); + ppvObject = Activator.CreateInstance(_classType)!; if (pUnkOuter != null) { ppvObject = BasicClassFactory.CreateAggregatedObject(pUnkOuter, ppvObject); } + + BasicClassFactory.ValidateObjectIsMarshallableAsInterface(ppvObject, interfaceType); } public void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock) @@ -320,9 +340,9 @@ public LicenseClassFactory(Guid clsid, Type classType) } public void CreateInstance( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, ref Guid riid, - [MarshalAs(UnmanagedType.Interface)] out object ppvObject) + [MarshalAs(UnmanagedType.Interface)] out object? ppvObject) { CreateInstanceInner(pUnkOuter, ref riid, key: null, isDesignTime: true, out ppvObject); } @@ -351,8 +371,8 @@ public void RequestLicKey(int dwReserved, [MarshalAs(UnmanagedType.BStr)] out st } public void CreateInstanceLic( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, - [MarshalAs(UnmanagedType.Interface)] object pUnkReserved, + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object? pUnkReserved, ref Guid riid, [MarshalAs(UnmanagedType.BStr)] string bstrKey, [MarshalAs(UnmanagedType.Interface)] out object ppvObject) @@ -362,19 +382,21 @@ public void CreateInstanceLic( } private void CreateInstanceInner( - object pUnkOuter, + object? pUnkOuter, ref Guid riid, - string key, + string? key, bool isDesignTime, out object ppvObject) { - BasicClassFactory.ValidateInterfaceRequest(_classType, ref riid, pUnkOuter); + Type interfaceType = BasicClassFactory.GetValidatedInterfaceType(_classType, ref riid, pUnkOuter); ppvObject = _licenseProxy.AllocateAndValidateLicense(_classType, key, isDesignTime); if (pUnkOuter != null) { ppvObject = BasicClassFactory.CreateAggregatedObject(pUnkOuter, ppvObject); } + + BasicClassFactory.ValidateObjectIsMarshallableAsInterface(ppvObject, interfaceType); } } } @@ -408,8 +430,8 @@ internal sealed class LicenseInteropProxy private MethodInfo _licInfoHelperContains; // RCW Activation - private object _licContext; - private Type _targetRcwType; + private object? _licContext; + private Type? _targetRcwType; static LicenseInteropProxy() { @@ -468,15 +490,15 @@ public void GetLicInfo(Type type, out bool runtimeKeyAvail, out bool licVerified // Types are as follows: // LicenseContext, Type, out License, out string - object licContext = Activator.CreateInstance(_licInfoHelper); - var parameters = new object[] { licContext, type, /* out */ null, /* out */ null }; + object licContext = Activator.CreateInstance(_licInfoHelper)!; + var parameters = new object?[] { licContext, type, /* out */ null, /* out */ null }; bool isValid = (bool)_validateTypeAndReturnDetails.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null); if (!isValid) { return; } - var license = (IDisposable)parameters[2]; + var license = (IDisposable?)parameters[2]; if (license != null) { license.Dispose(); @@ -500,20 +522,20 @@ public string RequestLicKey(Type type) // Types are as follows: // LicenseContext, Type, out License, out string - var parameters = new object[] { /* use global LicenseContext */ null, type, /* out */ null, /* out */ null }; + var parameters = new object?[] { /* use global LicenseContext */ null, type, /* out */ null, /* out */ null }; bool isValid = (bool)_validateTypeAndReturnDetails.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null); if (!isValid) { throw new COMException(); //E_FAIL } - var license = (IDisposable)parameters[2]; + var license = (IDisposable?)parameters[2]; if (license != null) { license.Dispose(); } - string licenseKey = (string)parameters[3]; + var licenseKey = (string?)parameters[3]; if (licenseKey == null) { throw new COMException(); //E_FAIL @@ -532,9 +554,9 @@ public string RequestLicKey(Type type) // If we are being entered because of a call to ICF::CreateInstanceLic(), // "isDesignTime" will be "false" and "key" will point to a non-null // license key. - public object AllocateAndValidateLicense(Type type, string key, bool isDesignTime) + public object AllocateAndValidateLicense(Type type, string? key, bool isDesignTime) { - object[] parameters; + object?[] parameters; object licContext; if (isDesignTime) { @@ -543,7 +565,7 @@ public object AllocateAndValidateLicense(Type type, string key, bool isDesignTim } else { - parameters = new object[] { type, key }; + parameters = new object?[] { type, key }; licContext = _createRuntimeContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null); } @@ -566,12 +588,12 @@ public void GetCurrentContextInfo(RuntimeTypeHandle rth, out bool isDesignTime, // Types are as follows: // Type, out bool, out string -> LicenseContext - var parameters = new object[] { targetRcwTypeMaybe, /* out */ null, /* out */ null }; + var parameters = new object?[] { targetRcwTypeMaybe, /* out */ null, /* out */ null }; _licContext = _getCurrentContextInfo.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null); _targetRcwType = targetRcwTypeMaybe; - isDesignTime = (bool)parameters[1]; - bstrKey = Marshal.StringToBSTR((string)parameters[2]); + isDesignTime = (bool)parameters[1]!; + bstrKey = Marshal.StringToBSTR((string)parameters[2]!); } // The CLR invokes this when instantiating a licensed COM @@ -586,7 +608,7 @@ public void SaveKeyInCurrentContext(IntPtr bstrKey) } string key = Marshal.PtrToStringBSTR(bstrKey); - var parameters = new object[] { _targetRcwType, key }; + var parameters = new object?[] { _targetRcwType, key }; _setSavedLicenseKey.Invoke(_licContext, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null); } } diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs index 097f47a825c5..2353afa5a5ff 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs @@ -2,10 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; -using System.Diagnostics; -using System.IO; -using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Loader; @@ -23,9 +21,15 @@ public static class InMemoryAssemblyLoader /// The path to the assembly (as a pointer to a UTF-16 C string). public static unsafe void LoadInMemoryAssembly(IntPtr moduleHandle, IntPtr assemblyPath) { + string? assemblyPathString = Marshal.PtrToStringUni(assemblyPath); + if (assemblyPathString == null) + { + throw new ArgumentOutOfRangeException(nameof(assemblyPath)); + } + // We don't cache the ALCs here since each IJW assembly will call this method at most once // (the load process rewrites the stubs that call here to call the actual methods they're supposed to) - AssemblyLoadContext context = new IsolatedComponentLoadContext(Marshal.PtrToStringUni(assemblyPath)); + AssemblyLoadContext context = new IsolatedComponentLoadContext(assemblyPathString); context.LoadFromInMemoryModule(moduleHandle); } } diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/IsolatedComponentLoadContext.cs b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/IsolatedComponentLoadContext.cs index d78d7dd51c33..cfbf3c071c6e 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/IsolatedComponentLoadContext.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/IsolatedComponentLoadContext.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Reflection; using System.Runtime.Loader; @@ -13,18 +14,18 @@ namespace Internal.Runtime.InteropServices /// or IJW components loaded from native. It provides a load context that uses an to resolve the component's /// dependencies within the ALC and not pollute the default ALC. /// - internal class IsolatedComponentLoadContext : AssemblyLoadContext + internal sealed class IsolatedComponentLoadContext : AssemblyLoadContext { private readonly AssemblyDependencyResolver _resolver; - public IsolatedComponentLoadContext(string componentAssemblyPath) + public IsolatedComponentLoadContext(string componentAssemblyPath) : base($"IsolatedComponentLoadContext({componentAssemblyPath})") { _resolver = new AssemblyDependencyResolver(componentAssemblyPath); } - protected override Assembly Load(AssemblyName assemblyName) + protected override Assembly? Load(AssemblyName assemblyName) { - string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); + string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); if (assemblyPath != null) { return LoadFromAssemblyPath(assemblyPath); @@ -35,7 +36,7 @@ protected override Assembly Load(AssemblyName assemblyName) protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) { - string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); + string? libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); if (libraryPath != null) { return LoadUnmanagedDllFromPath(libraryPath); diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/WindowsRuntime/ActivationFactoryLoader.cs b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/WindowsRuntime/ActivationFactoryLoader.cs index eb1c584b6c0d..8f94666c6b51 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/WindowsRuntime/ActivationFactoryLoader.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/WindowsRuntime/ActivationFactoryLoader.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.InteropServices.WindowsRuntime; using System.Runtime.Loader; @@ -44,7 +42,7 @@ private static AssemblyLoadContext GetALC(string assemblyPath) public unsafe static int GetActivationFactory( char* componentPath, [MarshalAs(UnmanagedType.HString)] string typeName, - [MarshalAs(UnmanagedType.Interface)] out IActivationFactory activationFactory) + [MarshalAs(UnmanagedType.Interface)] out IActivationFactory? activationFactory) { activationFactory = null; try @@ -54,7 +52,7 @@ public unsafe static int GetActivationFactory( throw new ArgumentNullException(nameof(typeName)); } - AssemblyLoadContext context = GetALC(Marshal.PtrToStringUni((IntPtr)componentPath)); + AssemblyLoadContext context = GetALC(Marshal.PtrToStringUni((IntPtr)componentPath)!); Type winRTType = context.LoadTypeForWinRTTypeNameInContext(typeName); diff --git a/src/System.Private.CoreLib/src/Interop/Unix/Interop.Libraries.cs b/src/System.Private.CoreLib/src/Interop/Unix/Interop.Libraries.cs index da7cbf29d25b..c7f5b1d73696 100644 --- a/src/System.Private.CoreLib/src/Interop/Unix/Interop.Libraries.cs +++ b/src/System.Private.CoreLib/src/Interop/Unix/Interop.Libraries.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable internal static partial class Interop { internal static partial class Libraries diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/UnsafeNativeMethods.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/UnsafeNativeMethods.cs index 2f69f6350814..25e382b14bcb 100644 --- a/src/System.Private.CoreLib/src/Microsoft/Win32/UnsafeNativeMethods.cs +++ b/src/System.Private.CoreLib/src/Microsoft/Win32/UnsafeNativeMethods.cs @@ -14,181 +14,6 @@ namespace Microsoft.Win32 internal static class UnsafeNativeMethods { - internal static unsafe class ManifestEtw - { - // - // Constants error coded returned by ETW APIs - // - - // The event size is larger than the allowed maximum (64k - header). - internal const int ERROR_ARITHMETIC_OVERFLOW = 534; - - // Occurs when filled buffers are trying to flush to disk, - // but disk IOs are not happening fast enough. - // This happens when the disk is slow and event traffic is heavy. - // Eventually, there are no more free (empty) buffers and the event is dropped. - internal const int ERROR_NOT_ENOUGH_MEMORY = 8; - - internal const int ERROR_MORE_DATA = 0xEA; - internal const int ERROR_NOT_SUPPORTED = 50; - internal const int ERROR_INVALID_PARAMETER = 0x57; - - // - // ETW Methods - // - - internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0; - internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1; - internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2; - - // - // Callback - // - internal delegate void EtwEnableCallback( - [In] ref Guid sourceId, - [In] int isEnabled, - [In] byte level, - [In] long matchAnyKeywords, - [In] long matchAllKeywords, - [In] EVENT_FILTER_DESCRIPTOR* filterData, - [In] void* callbackContext - ); - - // - // Registration APIs - // - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern unsafe uint EventRegister( - [In] ref Guid providerId, - [In]EtwEnableCallback enableCallback, - [In]void* callbackContext, - [In][Out]ref long registrationHandle - ); - - // - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern uint EventUnregister([In] long registrationHandle); - - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteString", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern int EventWriteString( - [In] long registrationHandle, - [In] byte level, - [In] long keyword, - [In] string msg - ); - - [StructLayout(LayoutKind.Sequential)] - internal struct EVENT_FILTER_DESCRIPTOR - { - public long Ptr; - public int Size; - public int Type; - }; - - /// - /// Call the ETW native API EventWriteTransfer and checks for invalid argument error. - /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId. - /// So, for these cases we will retry the call with an empty Guid. - /// - internal static int EventWriteTransferWrapper(long registrationHandle, - ref EventDescriptor eventDescriptor, - Guid* activityId, - Guid* relatedActivityId, - int userDataCount, - EventProvider.EventData* userData) - { - int HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, relatedActivityId, userDataCount, userData); - if (HResult == ERROR_INVALID_PARAMETER && relatedActivityId == null) - { - Guid emptyGuid = Guid.Empty; - HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, &emptyGuid, userDataCount, userData); - } - - return HResult; - } - - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteTransfer", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - private static extern int EventWriteTransfer( - [In] long registrationHandle, - [In] ref EventDescriptor eventDescriptor, - [In] Guid* activityId, - [In] Guid* relatedActivityId, - [In] int userDataCount, - [In] EventProvider.EventData* userData - ); - - internal enum ActivityControl : uint - { - EVENT_ACTIVITY_CTRL_GET_ID = 1, - EVENT_ACTIVITY_CTRL_SET_ID = 2, - EVENT_ACTIVITY_CTRL_CREATE_ID = 3, - EVENT_ACTIVITY_CTRL_GET_SET_ID = 4, - EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5 - }; - - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventActivityIdControl", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern int EventActivityIdControl([In] ActivityControl ControlCode, [In][Out] ref Guid ActivityId); - - internal enum EVENT_INFO_CLASS - { - BinaryTrackInfo, - SetEnableAllKeywords, - SetTraits, - } - - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventSetInformation", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern int EventSetInformation( - [In] long registrationHandle, - [In] EVENT_INFO_CLASS informationClass, - [In] void* eventInformation, - [In] int informationLength); - - // Support for EnumerateTraceGuidsEx - internal enum TRACE_QUERY_INFO_CLASS - { - TraceGuidQueryList, - TraceGuidQueryInfo, - TraceGuidQueryProcess, - TraceStackTracingInfo, - MaxTraceSetInfoClass - }; - - internal struct TRACE_GUID_INFO - { - public int InstanceCount; - public int Reserved; - }; - - internal struct TRACE_PROVIDER_INSTANCE_INFO - { - public int NextOffset; - public int EnableCount; - public int Pid; - public int Flags; - }; - - internal struct TRACE_ENABLE_INFO - { - public int IsEnabled; - public byte Level; - public byte Reserved1; - public ushort LoggerId; - public int EnableProperty; - public int Reserved2; - public long MatchAnyKeyword; - public long MatchAllKeyword; - }; - - [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EnumerateTraceGuidsEx", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern int EnumerateTraceGuidsEx( - TRACE_QUERY_INFO_CLASS TraceQueryInfoClass, - void* InBuffer, - int InBufferSize, - void* OutBuffer, - int OutBufferSize, - ref int ReturnLength); - } - #if FEATURE_COMINTEROP [DllImport("api-ms-win-core-winrt-l1-1-0.dll", PreserveSig = true)] internal static extern int RoGetActivationFactory( diff --git a/src/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs b/src/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs index 4d11c16f7339..4ef4a342dd59 100644 --- a/src/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using System.Reflection; @@ -17,10 +18,10 @@ internal static unsafe void Setup(char** pNames, char** pValues, int count) } } - private static string GetBaseDirectoryCore() + private static string? GetBaseDirectoryCore() { // Fallback path for hosts that do not set APP_CONTEXT_BASE_DIRECTORY explicitly - string directory = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); + string? directory = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); if (directory != null && !PathInternal.EndsInDirectorySeparator(directory)) directory += Path.DirectorySeparatorChar; return directory; diff --git a/src/System.Private.CoreLib/src/System/ApplicationModel.Windows.cs b/src/System.Private.CoreLib/src/System/ApplicationModel.Windows.cs index ea1e01742433..1b49dec13f62 100644 --- a/src/System.Private.CoreLib/src/System/ApplicationModel.Windows.cs +++ b/src/System.Private.CoreLib/src/System/ApplicationModel.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/src/System/ArgIterator.cs b/src/System.Private.CoreLib/src/System/ArgIterator.cs index 72ea2548e21b..2c1f54ada8e1 100644 --- a/src/System.Private.CoreLib/src/System/ArgIterator.cs +++ b/src/System.Private.CoreLib/src/System/ArgIterator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { using System; @@ -128,7 +129,7 @@ public override int GetHashCode() } // Inherited from object - public override bool Equals(object o) + public override bool Equals(object? o) { throw new NotSupportedException(SR.NotSupported_NYI); } @@ -149,7 +150,7 @@ public void End() throw new PlatformNotSupportedException(SR.PlatformNotSupported_ArgIterator); // https://github.com/dotnet/coreclr/issues/9204 } - public override bool Equals(Object o) + public override bool Equals(Object? o) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ArgIterator); // https://github.com/dotnet/coreclr/issues/9204 } diff --git a/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs index 6600c5dfe759..2fe10540dce9 100644 --- a/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Array.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -29,10 +30,10 @@ public static unsafe Array CreateInstance(Type elementType, int length) if (length < 0) ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum(); - RuntimeType t = elementType.UnderlyingSystemType as RuntimeType; + RuntimeType? t = elementType!.UnderlyingSystemType as RuntimeType; // https://github.com/dotnet/csharplang/issues/538 if (t == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType); - return InternalCreate((void*)t.TypeHandle.Value, 1, &length, null); + return InternalCreate((void*)t!.TypeHandle.Value, 1, &length, null); // https://github.com/dotnet/csharplang/issues/538 } public static unsafe Array CreateInstance(Type elementType, int length1, int length2) @@ -44,13 +45,13 @@ public static unsafe Array CreateInstance(Type elementType, int length1, int len if (length2 < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - RuntimeType t = elementType.UnderlyingSystemType as RuntimeType; + RuntimeType? t = elementType!.UnderlyingSystemType as RuntimeType; // https://github.com/dotnet/csharplang/issues/538 if (t == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType); int* pLengths = stackalloc int[2]; pLengths[0] = length1; pLengths[1] = length2; - return InternalCreate((void*)t.TypeHandle.Value, 2, pLengths, null); + return InternalCreate((void*)t!.TypeHandle.Value, 2, pLengths, null); // https://github.com/dotnet/csharplang/issues/538 } public static unsafe Array CreateInstance(Type elementType, int length1, int length2, int length3) @@ -64,14 +65,14 @@ public static unsafe Array CreateInstance(Type elementType, int length1, int len if (length3 < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length3, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - RuntimeType t = elementType.UnderlyingSystemType as RuntimeType; + RuntimeType? t = elementType!.UnderlyingSystemType as RuntimeType; // https://github.com/dotnet/csharplang/issues/538 if (t == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType); int* pLengths = stackalloc int[3]; pLengths[0] = length1; pLengths[1] = length2; pLengths[2] = length3; - return InternalCreate((void*)t.TypeHandle.Value, 3, pLengths, null); + return InternalCreate((void*)t!.TypeHandle.Value, 3, pLengths, null); // https://github.com/dotnet/csharplang/issues/538 } public static unsafe Array CreateInstance(Type elementType, params int[] lengths) @@ -80,10 +81,10 @@ public static unsafe Array CreateInstance(Type elementType, params int[] lengths ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType); if (lengths == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths); - if (lengths.Length == 0) + if (lengths!.Length == 0) // https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank); - RuntimeType t = elementType.UnderlyingSystemType as RuntimeType; + RuntimeType? t = elementType!.UnderlyingSystemType as RuntimeType; // https://github.com/dotnet/csharplang/issues/538 if (t == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType); @@ -96,7 +97,7 @@ public static unsafe Array CreateInstance(Type elementType, params int[] lengths ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); fixed (int* pLengths = &lengths[0]) - return InternalCreate((void*)t.TypeHandle.Value, lengths.Length, pLengths, null); + return InternalCreate((void*)t!.TypeHandle.Value, lengths.Length, pLengths, null); // https://github.com/dotnet/csharplang/issues/538 } public static unsafe Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds) @@ -107,12 +108,12 @@ public static unsafe Array CreateInstance(Type elementType, int[] lengths, int[] ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths); if (lowerBounds == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lowerBounds); - if (lengths.Length != lowerBounds.Length) + if (lengths!.Length != lowerBounds!.Length) // https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RanksAndBounds); if (lengths.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank); - RuntimeType t = elementType.UnderlyingSystemType as RuntimeType; + RuntimeType? t = elementType!.UnderlyingSystemType as RuntimeType; // https://github.com/dotnet/csharplang/issues/538 if (t == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType); @@ -126,7 +127,7 @@ public static unsafe Array CreateInstance(Type elementType, int[] lengths, int[] fixed (int* pLengths = &lengths[0]) fixed (int* pLowerBounds = &lowerBounds[0]) - return InternalCreate((void*)t.TypeHandle.Value, lengths.Length, pLengths, pLowerBounds); + return InternalCreate((void*)t!.TypeHandle.Value, lengths.Length, pLengths, pLowerBounds); // https://github.com/dotnet/csharplang/issues/538 } [MethodImplAttribute(MethodImplOptions.InternalCall)] @@ -142,7 +143,7 @@ public static void Copy(Array sourceArray, Array destinationArray, int length) if (destinationArray == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray); - Copy(sourceArray, sourceArray.GetLowerBound(0), destinationArray, destinationArray.GetLowerBound(0), length, false); + Copy(sourceArray!, sourceArray!.GetLowerBound(0), destinationArray!, destinationArray!.GetLowerBound(0), length, false); // https://github.com/dotnet/csharplang/issues/538 } // Copies length elements from sourceArray, starting at sourceIndex, to @@ -178,7 +179,7 @@ public static unsafe void Clear(Array array, int index, int length) if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - ref byte p = ref GetRawArrayGeometry(array, out uint numComponents, out uint elementSize, out int lowerBound, out bool containsGCPointers); + ref byte p = ref GetRawArrayGeometry(array!, out uint numComponents, out uint elementSize, out int lowerBound, out bool containsGCPointers); // https://github.com/dotnet/csharplang/issues/538 int offset = index - lowerBound; @@ -198,11 +199,11 @@ public static unsafe void Clear(Array array, int index, int length) private static extern ref byte GetRawArrayGeometry(Array array, out uint numComponents, out uint elementSize, out int lowerBound, out bool containsGCPointers); // The various Get values... - public unsafe object GetValue(params int[] indices) + public unsafe object? GetValue(params int[] indices) { if (indices == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices); - if (Rank != indices.Length) + if (Rank != indices!.Length) // https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices); TypedReference elemref = new TypedReference(); @@ -211,7 +212,7 @@ public unsafe object GetValue(params int[] indices) return TypedReference.InternalToObject(&elemref); } - public unsafe object GetValue(int index) + public unsafe object? GetValue(int index) { if (Rank != 1) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray); @@ -221,7 +222,7 @@ public unsafe object GetValue(int index) return TypedReference.InternalToObject(&elemref); } - public unsafe object GetValue(int index1, int index2) + public unsafe object? GetValue(int index1, int index2) { if (Rank != 2) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need2DArray); @@ -235,7 +236,7 @@ public unsafe object GetValue(int index1, int index2) return TypedReference.InternalToObject(&elemref); } - public unsafe object GetValue(int index1, int index2, int index3) + public unsafe object? GetValue(int index1, int index2, int index3) { if (Rank != 3) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need3DArray); @@ -250,7 +251,7 @@ public unsafe object GetValue(int index1, int index2, int index3) return TypedReference.InternalToObject(&elemref); } - public unsafe void SetValue(object value, int index) + public unsafe void SetValue(object? value, int index) { if (Rank != 1) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray); @@ -260,7 +261,7 @@ public unsafe void SetValue(object value, int index) InternalSetValue(&elemref, value); } - public unsafe void SetValue(object value, int index1, int index2) + public unsafe void SetValue(object? value, int index1, int index2) { if (Rank != 2) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need2DArray); @@ -274,7 +275,7 @@ public unsafe void SetValue(object value, int index1, int index2) InternalSetValue(&elemref, value); } - public unsafe void SetValue(object value, int index1, int index2, int index3) + public unsafe void SetValue(object? value, int index1, int index2, int index3) { if (Rank != 3) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need3DArray); @@ -289,11 +290,11 @@ public unsafe void SetValue(object value, int index1, int index2, int index3) InternalSetValue(&elemref, value); } - public unsafe void SetValue(object value, params int[] indices) + public unsafe void SetValue(object? value, params int[] indices) { if (indices == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices); - if (Rank != indices.Length) + if (Rank != indices!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices); TypedReference elemref = new TypedReference(); @@ -302,8 +303,10 @@ public unsafe void SetValue(object value, params int[] indices) InternalSetValue(&elemref, value); } - private static void SortImpl(Array keys, Array items, int index, int length, IComparer comparer) + private static void SortImpl(Array keys, Array? items, int index, int length, IComparer comparer) { + Debug.Assert(comparer != null); + if (comparer == Comparer.Default) { bool r = TrySZSort(keys, items, index, index + length - 1); @@ -311,8 +314,8 @@ private static void SortImpl(Array keys, Array items, int index, int length, ICo return; } - object[] objKeys = keys as object[]; - object[] objItems = null; + object[]? objKeys = keys as object[]; + object[]? objItems = null; if (objKeys != null) objItems = items as object[]; if (objKeys != null && (items == null || objItems != null)) @@ -334,7 +337,7 @@ private static void SortImpl(Array keys, Array items, int index, int length, ICo // Ideally, we would like to use TypedReference.SetValue instead. Unfortunately, TypedReference.SetValue // always throws not-supported exception [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern unsafe void InternalSetValue(void* target, object value); + private static extern unsafe void InternalSetValue(void* target, object? value); public extern int Length { @@ -370,19 +373,19 @@ public extern int Rank internal extern int GetElementSize(); [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool TrySZBinarySearch(Array sourceArray, int sourceIndex, int count, object value, out int retVal); + private static extern bool TrySZBinarySearch(Array sourceArray, int sourceIndex, int count, object? value, out int retVal); [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool TrySZIndexOf(Array sourceArray, int sourceIndex, int count, object value, out int retVal); + private static extern bool TrySZIndexOf(Array sourceArray, int sourceIndex, int count, object? value, out int retVal); [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool TrySZLastIndexOf(Array sourceArray, int sourceIndex, int count, object value, out int retVal); + private static extern bool TrySZLastIndexOf(Array sourceArray, int sourceIndex, int count, object? value, out int retVal); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool TrySZReverse(Array array, int index, int count); [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool TrySZSort(Array keys, Array items, int left, int right); + private static extern bool TrySZSort(Array keys, Array? items, int left, int right); // if this is an array of value classes and that value class has a default constructor // then this calls this default constructor on every element in the value class array. @@ -527,4 +530,4 @@ private void RemoveAt(int index) ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection); } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs index 56f36de771f2..6835f5e4478b 100644 --- a/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/src/System/CLRConfig.cs b/src/System.Private.CoreLib/src/System/CLRConfig.cs index 5b14f282edea..76e38acb5c94 100644 --- a/src/System.Private.CoreLib/src/System/CLRConfig.cs +++ b/src/System.Private.CoreLib/src/System/CLRConfig.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Microsoft.Win32; diff --git a/src/System.Private.CoreLib/src/System/Char8.cs b/src/System.Private.CoreLib/src/System/Char8.cs index 7a71e2faa028..46789fa564ed 100644 --- a/src/System.Private.CoreLib/src/System/Char8.cs +++ b/src/System.Private.CoreLib/src/System/Char8.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { /// @@ -59,7 +60,7 @@ private Char8(byte value) public int CompareTo(Char8 other) => this._value.CompareTo(other._value); - public override bool Equals(object obj) => (obj is Char8 other) && (this == other); + public override bool Equals(object? obj) => (obj is Char8 other) && (this == other); public bool Equals(Char8 other) => this == other; public override int GetHashCode() => _value; diff --git a/src/System.Private.CoreLib/src/System/Currency.cs b/src/System.Private.CoreLib/src/System/Currency.cs index c9e8dc030eb8..e306989e585a 100644 --- a/src/System.Private.CoreLib/src/System/Currency.cs +++ b/src/System.Private.CoreLib/src/System/Currency.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System { internal struct Currency diff --git a/src/System.Private.CoreLib/src/System/DateTime.Unix.CoreCLR.cs b/src/System.Private.CoreLib/src/System/DateTime.Unix.CoreCLR.cs index 1fd1e9ca405c..c98834395116 100644 --- a/src/System.Private.CoreLib/src/System/DateTime.Unix.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/DateTime.Unix.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System @@ -19,4 +20,4 @@ public static DateTime UtcNow [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern long GetSystemTimeAsFileTime(); } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/src/System/DateTime.Windows.CoreCLR.cs b/src/System.Private.CoreLib/src/System/DateTime.Windows.CoreCLR.cs new file mode 100644 index 000000000000..5597c137ad06 --- /dev/null +++ b/src/System.Private.CoreLib/src/System/DateTime.Windows.CoreCLR.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System +{ + public readonly partial struct DateTime + { + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern bool ValidateSystemTime(Interop.Kernel32.SYSTEMTIME* time, bool localTime); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern bool FileTimeToSystemTime(long fileTime, FullSystemTime* time); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern void GetSystemTimeWithLeapSecondsHandling(FullSystemTime* time); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern bool SystemTimeToFileTime(Interop.Kernel32.SYSTEMTIME* time, long* fileTime); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern long GetSystemTimeAsFileTime(); + } +} diff --git a/src/System.Private.CoreLib/src/System/DateTime.Windows.cs b/src/System.Private.CoreLib/src/System/DateTime.Windows.cs deleted file mode 100644 index 9d0d0cd28c46..000000000000 --- a/src/System.Private.CoreLib/src/System/DateTime.Windows.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace System -{ - public readonly partial struct DateTime - { - internal static readonly bool s_systemSupportsLeapSeconds = SystemSupportsLeapSeconds(); - - public static DateTime UtcNow - { - get - { - if (s_systemSupportsLeapSeconds) - { - GetSystemTimeWithLeapSecondsHandling(out FullSystemTime time); - return CreateDateTimeFromSystemTime(in time); - } - - return new DateTime(((ulong)(GetSystemTimeAsFileTime() + FileTimeOffset)) | KindUtc); - } - } - - internal static bool IsValidTimeWithLeapSeconds(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) - { - DateTime dt = new DateTime(year, month, day); - FullSystemTime time = new FullSystemTime(year, month, dt.DayOfWeek, day, hour, minute, second); - - switch (kind) - { - case DateTimeKind.Local: return ValidateSystemTime(in time.systemTime, localTime: true); - case DateTimeKind.Utc: return ValidateSystemTime(in time.systemTime, localTime: false); - default: - return ValidateSystemTime(in time.systemTime, localTime: true) || ValidateSystemTime(in time.systemTime, localTime: false); - } - } - - internal static DateTime FromFileTimeLeapSecondsAware(long fileTime) - { - if (FileTimeToSystemTime(fileTime, out FullSystemTime time)) - { - return CreateDateTimeFromSystemTime(in time); - } - - throw new ArgumentOutOfRangeException("fileTime", SR.ArgumentOutOfRange_DateTimeBadTicks); - } - - internal static long ToFileTimeLeapSecondsAware(long ticks) - { - FullSystemTime time = new FullSystemTime(ticks); - if (SystemTimeToFileTime(in time.systemTime, out long fileTime)) - { - return fileTime + ticks % TicksPerMillisecond; - } - - throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_FileTimeInvalid); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static DateTime CreateDateTimeFromSystemTime(in FullSystemTime time) - { - long ticks = DateToTicks(time.systemTime.Year, time.systemTime.Month, time.systemTime.Day); - ticks += TimeToTicks(time.systemTime.Hour, time.systemTime.Minute, time.systemTime.Second); - ticks += time.systemTime.Milliseconds * TicksPerMillisecond; - ticks += time.hundredNanoSecond; - return new DateTime( ((UInt64)(ticks)) | KindUtc); - } - - private static unsafe bool SystemSupportsLeapSeconds() - { - Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION slsi; - - return Interop.NtDll.NtQuerySystemInformation( - Interop.NtDll.SystemLeapSecondInformation, - (void *) &slsi, - sizeof(Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION), - null) == 0 && slsi.Enabled; - } - - // FullSystemTime struct is the SYSTEMTIME struct with extra hundredNanoSecond field to store more precise time. - [StructLayout(LayoutKind.Sequential)] - internal struct FullSystemTime - { - internal Interop.Kernel32.SYSTEMTIME systemTime; - internal long hundredNanoSecond; - - internal FullSystemTime(int year, int month, DayOfWeek dayOfWeek, int day, int hour, int minute, int second) - { - systemTime.Year = (ushort) year; - systemTime.Month = (ushort) month; - systemTime.DayOfWeek = (ushort) dayOfWeek; - systemTime.Day = (ushort) day; - systemTime.Hour = (ushort) hour; - systemTime.Minute = (ushort) minute; - systemTime.Second = (ushort) second; - systemTime.Milliseconds = 0; - hundredNanoSecond = 0; - } - - internal FullSystemTime(long ticks) - { - DateTime dt = new DateTime(ticks); - - int year, month, day; - dt.GetDatePart(out year, out month, out day); - - systemTime.Year = (ushort) year; - systemTime.Month = (ushort) month; - systemTime.DayOfWeek = (ushort) dt.DayOfWeek; - systemTime.Day = (ushort) day; - systemTime.Hour = (ushort) dt.Hour; - systemTime.Minute = (ushort) dt.Minute; - systemTime.Second = (ushort) dt.Second; - systemTime.Milliseconds = (ushort) dt.Millisecond; - hundredNanoSecond = 0; - } - }; - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool ValidateSystemTime(in Interop.Kernel32.SYSTEMTIME time, bool localTime); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool FileTimeToSystemTime(long fileTime, out FullSystemTime time); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void GetSystemTimeWithLeapSecondsHandling(out FullSystemTime time); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool SystemTimeToFileTime(in Interop.Kernel32.SYSTEMTIME time, out long fileTime); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern long GetSystemTimeAsFileTime(); - } -} diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs index cda3c4e729ca..fbb83497a386 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs @@ -5,6 +5,7 @@ // The Debugger class is a part of the System.Diagnostics package // and is used for communicating with a debugger. +#nullable enable using System.Runtime.CompilerServices; namespace System.Diagnostics @@ -73,13 +74,13 @@ public static extern bool IsAttached // desired events are actually reported to the debugger. // // Constant representing the default category - public static readonly string DefaultCategory = null; + public static readonly string? DefaultCategory = null; // Posts a message for the attached debugger. If there is no // debugger attached, has no effect. The debugger may or may not // report the message depending on its settings. [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void Log(int level, string category, string message); + public static extern void Log(int level, string? category, string? message); // Checks to see if an attached debugger has logging enabled // diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/EditAndContinueHelper.cs b/src/System.Private.CoreLib/src/System/Diagnostics/EditAndContinueHelper.cs index 89aec101648c..9d3b1b23c540 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/EditAndContinueHelper.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/EditAndContinueHelper.cs @@ -11,7 +11,7 @@ ** =============================================================================*/ - +#nullable enable using System; namespace System.Diagnostics @@ -20,7 +20,7 @@ internal sealed class EditAndContinueHelper { #pragma warning disable 169 #pragma warning disable 414 // Field is not used from managed. - private object _objectReference; + private object? _objectReference; #pragma warning restore 414 #pragma warning restore 169 } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs index 9f05540610e1..d44ac64ad5b5 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.cs @@ -87,7 +87,6 @@ internal sealed class EventPipeConfiguration private uint m_circularBufferSizeInMB; private List m_providers; private TimeSpan m_minTimeBetweenSamples = TimeSpan.FromMilliseconds(1); - private ulong m_multiFileTraceLengthInSeconds = 0; internal EventPipeConfiguration( string outputFile, @@ -116,11 +115,6 @@ internal uint CircularBufferSizeInMB get { return m_circularBufferSizeInMB; } } - internal ulong MultiFileTraceLengthInSeconds - { - get { return m_multiFileTraceLengthInSeconds; } - } - internal EventPipeProviderConfiguration[] Providers { get { return m_providers.ToArray(); } @@ -168,11 +162,6 @@ internal void SetProfilerSamplingRate(TimeSpan minTimeBetweenSamples) m_minTimeBetweenSamples = minTimeBetweenSamples; } - - internal void SetMultiFileTraceLength(ulong traceLengthInSeconds) - { - m_multiFileTraceLengthInSeconds = traceLengthInSeconds; - } } internal static class EventPipe @@ -198,8 +187,7 @@ internal static void Enable(EventPipeConfiguration configuration) configuration.CircularBufferSizeInMB, (ulong)configuration.ProfilerSamplingRateInNanoseconds, providers, - (uint)providers.Length, - configuration.MultiFileTraceLengthInSeconds); + (uint)providers.Length); } internal static void Disable() @@ -219,8 +207,7 @@ internal static extern UInt64 Enable( uint circularBufferSizeInMB, ulong profilerSamplingRateInNanoseconds, EventPipeProviderConfiguration[] providers, - uint numProviders, - ulong multiFileTraceLengthInSeconds); + uint numProviders); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern void Disable(UInt64 sessionID); @@ -229,7 +216,7 @@ internal static extern UInt64 Enable( // These PInvokes are used by EventSource to interact with the EventPipe. // [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - internal static extern IntPtr CreateProvider(string providerName, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback callbackFunc); + internal static extern IntPtr CreateProvider(string providerName, Interop.Advapi32.EtwEnableCallback callbackFunc); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, long keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength); diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs index cac4ac1f5dfe..2711d5290abb 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeController.cs @@ -46,7 +46,6 @@ internal sealed class EventPipeController private const string ConfigKey_CircularMB = "CircularMB"; private const string ConfigKey_OutputPath = "OutputPath"; private const string ConfigKey_ProcessID = "ProcessID"; - private const string ConfigKey_MultiFileSec = "MultiFileSec"; // The default set of providers/keywords/levels. Used if an alternative configuration is not specified. private static EventPipeProviderConfiguration[] DefaultProviderConfiguration => new EventPipeProviderConfiguration[] @@ -170,7 +169,6 @@ private static EventPipeConfiguration BuildConfigFromFile(string configFilePath) string strProviderConfig = null; string strCircularMB = null; string strProcessID = null; - string strMultiFileSec = null; // Split the configuration entries by line. string[] configEntries = strConfigContents.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); @@ -200,10 +198,6 @@ private static EventPipeConfiguration BuildConfigFromFile(string configFilePath) { strProcessID = entryComponents[1]; } - else if (key.Equals(ConfigKey_MultiFileSec)) - { - strMultiFileSec = entryComponents[1]; - } } } @@ -224,13 +218,6 @@ private static EventPipeConfiguration BuildConfigFromFile(string configFilePath) throw new ArgumentNullException(nameof(outputPath)); } - // Check to see if MultiFileSec is specified. - ulong multiFileSec = 0; - if (!string.IsNullOrEmpty(strMultiFileSec)) - { - multiFileSec = Convert.ToUInt64(strMultiFileSec); - } - // Build the full path to the trace file. string traceFileName = BuildTraceFileName(); string outputFile = Path.Combine(outputPath, traceFileName); @@ -244,7 +231,6 @@ private static EventPipeConfiguration BuildConfigFromFile(string configFilePath) // Initialize a new configuration object. EventPipeConfiguration config = new EventPipeConfiguration(outputFile, circularMB); - config.SetMultiFileTraceLength(multiFileSec); // Set the provider configuration if specified. if (!string.IsNullOrEmpty(strProviderConfig)) diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs index 9f459891a705..1e152bcfcd52 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs @@ -110,7 +110,7 @@ private void CommitDispatchConfiguration() new EventPipeProviderConfiguration(NativeRuntimeEventSource.EventSourceName, (ulong) aggregatedKeywords, (uint) highestLevel, null) }; - m_sessionID = EventPipeInternal.Enable(null, 1024, 1, providerConfiguration, 1, 0); + m_sessionID = EventPipeInternal.Enable(null, 1024, 1, providerConfiguration, 1); Debug.Assert(m_sessionID != 0); // Get the session information that is required to properly dispatch events. diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs index 214788ebc3dd..16903c8aaa3a 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs @@ -19,7 +19,7 @@ internal sealed class EventPipeEventProvider : IEventProvider // Register an event provider. unsafe uint IEventProvider.EventRegister( EventSource eventSource, - UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback, + Interop.Advapi32.EtwEnableCallback enableCallback, void* callbackContext, ref long registrationHandle) { @@ -48,9 +48,9 @@ uint IEventProvider.EventUnregister(long registrationHandle) } // Write an event. - unsafe int IEventProvider.EventWriteTransferWrapper( + unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer( long registrationHandle, - ref EventDescriptor eventDescriptor, + in EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityId, Guid* relatedActivityId, @@ -63,7 +63,7 @@ unsafe int IEventProvider.EventWriteTransferWrapper( if (userDataCount == 0) { EventPipeInternal.WriteEventData(eventHandle, eventID, null, 0, activityId, relatedActivityId); - return 0; + return EventProvider.WriteEventErrorCode.NoError; } // If Channel == 11, this is a TraceLogging event. @@ -77,11 +77,11 @@ unsafe int IEventProvider.EventWriteTransferWrapper( } EventPipeInternal.WriteEventData(eventHandle, eventID, userData, (uint) userDataCount, activityId, relatedActivityId); } - return 0; + return EventProvider.WriteEventErrorCode.NoError; } // Get or set the per-thread activity ID. - int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId) + int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId) { return EventPipeInternal.EventActivityIdControl((uint)ControlCode, ref ActivityId); } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs deleted file mode 100644 index ae8650e020f1..000000000000 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using Microsoft.Reflection; -using Microsoft.Win32; - -namespace System.Diagnostics.Tracing -{ - public partial class EventSource - { - // ActivityID support (see also WriteEventWithRelatedActivityIdCore) - /// - /// When a thread starts work that is on behalf of 'something else' (typically another - /// thread or network request) it should mark the thread as working on that other work. - /// This API marks the current thread as working on activity 'activityID'. This API - /// should be used when the caller knows the thread's current activity (the one being - /// overwritten) has completed. Otherwise, callers should prefer the overload that - /// return the oldActivityThatWillContinue (below). - /// - /// All events created with the EventSource on this thread are also tagged with the - /// activity ID of the thread. - /// - /// It is common, and good practice after setting the thread to an activity to log an event - /// with a 'start' opcode to indicate that precise time/thread where the new activity - /// started. - /// - /// A Guid that represents the new activity with which to mark - /// the current thread - public static void SetCurrentThreadActivityId(Guid activityId) - { - if (TplEventSource.Log != null) - TplEventSource.Log.SetActivityId(activityId); - - // We ignore errors to keep with the convention that EventSources do not throw errors. - // Note we can't access m_throwOnWrites because this is a static method. -#if FEATURE_MANAGED_ETW -#if FEATURE_PERFTRACING - // Set the activity id via EventPipe. - EventPipeInternal.EventActivityIdControl( - (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, - ref activityId); -#endif // FEATURE_PERFTRACING -#if PLATFORM_WINDOWS - // Set the activity id via ETW. - UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( - UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, - ref activityId); -#endif // PLATFORM_WINDOWS -#endif // FEATURE_MANAGED_ETW - } - - /// - /// When a thread starts work that is on behalf of 'something else' (typically another - /// thread or network request) it should mark the thread as working on that other work. - /// This API marks the current thread as working on activity 'activityID'. It returns - /// whatever activity the thread was previously marked with. There is a convention that - /// callers can assume that callees restore this activity mark before the callee returns. - /// To encourage this, this API returns the old activity, so that it can be restored later. - /// - /// All events created with the EventSource on this thread are also tagged with the - /// activity ID of the thread. - /// - /// It is common, and good practice after setting the thread to an activity to log an event - /// with a 'start' opcode to indicate that precise time/thread where the new activity - /// started. - /// - /// A Guid that represents the new activity with which to mark - /// the current thread - /// The Guid that represents the current activity - /// which will continue at some point in the future, on the current thread - public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue) - { - oldActivityThatWillContinue = activityId; -#if FEATURE_MANAGED_ETW - // We ignore errors to keep with the convention that EventSources do not throw errors. - // Note we can't access m_throwOnWrites because this is a static method. - -#if FEATURE_PERFTRACING && PLATFORM_WINDOWS - EventPipeInternal.EventActivityIdControl( - (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID, - ref oldActivityThatWillContinue); -#elif FEATURE_PERFTRACING - EventPipeInternal.EventActivityIdControl( - (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, - ref oldActivityThatWillContinue); -#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS - -#if PLATFORM_WINDOWS - UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( - UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID, - ref oldActivityThatWillContinue); -#endif // PLATFORM_WINDOWS -#endif // FEATURE_MANAGED_ETW - - // We don't call the activityDying callback here because the caller has declared that - // it is not dying. - if (TplEventSource.Log != null) - TplEventSource.Log.SetActivityId(activityId); - } - - /// - /// Retrieves the ETW activity ID associated with the current thread. - /// - public static Guid CurrentThreadActivityId - { - get - { - // We ignore errors to keep with the convention that EventSources do not throw - // errors. Note we can't access m_throwOnWrites because this is a static method. - Guid retVal = new Guid(); -#if FEATURE_MANAGED_ETW -#if PLATFORM_WINDOWS - UnsafeNativeMethods.ManifestEtw.EventActivityIdControl( - UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, - ref retVal); -#elif FEATURE_PERFTRACING - EventPipeInternal.EventActivityIdControl( - (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID, - ref retVal); -#endif // PLATFORM_WINDOWS -#endif // FEATURE_MANAGED_ETW - return retVal; - } - } - - private int GetParameterCount(EventMetadata eventData) - { - return eventData.Parameters.Length; - } - - private Type GetDataType(EventMetadata eventData, int parameterId) - { - return eventData.Parameters[parameterId].ParameterType; - } - - private static string GetResourceString(string key, params object[] args) - { - return SR.Format(SR.GetResourceString(key), args); - } - - private static readonly bool m_EventSourcePreventRecursion = false; - } - - internal partial class ManifestBuilder - { - private string GetTypeNameHelper(Type type) - { - switch (type.GetTypeCode()) - { - case TypeCode.Boolean: - return "win:Boolean"; - case TypeCode.Byte: - return "win:UInt8"; - case TypeCode.Char: - case TypeCode.UInt16: - return "win:UInt16"; - case TypeCode.UInt32: - return "win:UInt32"; - case TypeCode.UInt64: - return "win:UInt64"; - case TypeCode.SByte: - return "win:Int8"; - case TypeCode.Int16: - return "win:Int16"; - case TypeCode.Int32: - return "win:Int32"; - case TypeCode.Int64: - return "win:Int64"; - case TypeCode.String: - return "win:UnicodeString"; - case TypeCode.Single: - return "win:Float"; - case TypeCode.Double: - return "win:Double"; - case TypeCode.DateTime: - return "win:FILETIME"; - default: - if (type == typeof(Guid)) - return "win:GUID"; - else if (type == typeof(IntPtr)) - return "win:Pointer"; - else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte)) - return "win:Binary"; - - ManifestError(Resources.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true); - return string.Empty; - } - } - } - - internal partial class EventProvider - { - internal unsafe int SetInformation( - UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass, - IntPtr data, - uint dataSize) - { - int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED; - - if (!m_setInformationMissing) - { - try - { - status = UnsafeNativeMethods.ManifestEtw.EventSetInformation( - m_regHandle, - eventInfoClass, - (void*)data, - (int)dataSize); - } - catch (TypeLoadException) - { - m_setInformationMissing = true; - } - } - - return status; - } - } - - internal static class Resources - { - internal static string GetResourceString(string key, params object[] args) - { - return SR.Format(SR.GetResourceString(key), args); - } - } -} diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/RuntimeEventSource.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/RuntimeEventSource.cs index d264910086a8..29b3781f4f09 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/RuntimeEventSource.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/RuntimeEventSource.cs @@ -43,13 +43,13 @@ protected override void OnEventCommand(System.Diagnostics.Tracing.EventCommandEv // overhead by at all times even when counters aren't enabled. // On disable, PollingCounters will stop polling for values so it should be fine to leave them around. - _cpuTimeCounter = _cpuTimeCounter ?? new PollingCounter("CPU Usage", this, () => RuntimeEventSourceHelper.GetCpuUsage()); - _workingSetCounter = _workingSetCounter ?? new PollingCounter("Working Set", this, () => Environment.WorkingSet); - _gcHeapSizeCounter = _gcHeapSizeCounter ?? new PollingCounter("GC Heap Size", this, () => GC.GetTotalMemory(false)); - _gen0GCCounter = _gen0GCCounter ?? new IncrementingPollingCounter("Gen 0 GC Count", this, () => GC.CollectionCount(0)); - _gen1GCCounter = _gen1GCCounter ?? new IncrementingPollingCounter("Gen 1 GC Count", this, () => GC.CollectionCount(1)); - _gen2GCCounter = _gen2GCCounter ?? new IncrementingPollingCounter("Gen 2 GC Count", this, () => GC.CollectionCount(2)); - _exceptionCounter = _exceptionCounter ?? new IncrementingPollingCounter("Exception Count", this, () => Exception.GetExceptionCount()); + _cpuTimeCounter = _cpuTimeCounter ?? new PollingCounter("cpu-usage", this, () => RuntimeEventSourceHelper.GetCpuUsage()) { DisplayName = "CPU Usage" }; + _workingSetCounter = _workingSetCounter ?? new PollingCounter("working-set", this, () => (double)(Environment.WorkingSet / 1000000)) { DisplayName = "Working Set" }; + _gcHeapSizeCounter = _gcHeapSizeCounter ?? new PollingCounter("gc-heap-size", this, () => (double)(GC.GetTotalMemory(false) / 1000000)) { DisplayName = "GC Heap Size" }; + _gen0GCCounter = _gen0GCCounter ?? new IncrementingPollingCounter("gen-0-gc-count", this, () => GC.CollectionCount(0)) { DisplayName = "Gen 0 GC Count", DisplayRateTimeScale = new TimeSpan(0, 1, 0) }; + _gen1GCCounter = _gen1GCCounter ?? new IncrementingPollingCounter("gen-1-gc-count", this, () => GC.CollectionCount(1)) { DisplayName = "Gen 1 GC Count", DisplayRateTimeScale = new TimeSpan(0, 1, 0) }; + _gen2GCCounter = _gen2GCCounter ?? new IncrementingPollingCounter("gen-2-gc-count", this, () => GC.CollectionCount(2)) { DisplayName = "Gen 2 GC Count", DisplayRateTimeScale = new TimeSpan(0, 1, 0) }; + _exceptionCounter = _exceptionCounter ?? new IncrementingPollingCounter("exception-count", this, () => Exception.GetExceptionCount()) { DisplayName = "Exception Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; } } } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs index 9afc1cf0d676..d26b5325e11b 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Threading; namespace System.Diagnostics.Tracing diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/ICustomDebuggerNotification.cs b/src/System.Private.CoreLib/src/System/Diagnostics/ICustomDebuggerNotification.cs index e7f41051f20e..46f5bb39610c 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/ICustomDebuggerNotification.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/ICustomDebuggerNotification.cs @@ -9,6 +9,7 @@ ** ===========================================================*/ +#nullable enable using System; namespace System.Diagnostics diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs index e78734fece4f..53bc4d2f3636 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Text; namespace System.Diagnostics diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs index 56b988754be2..0c520e4f41ab 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections; using System.Collections.Generic; @@ -23,41 +24,41 @@ namespace System.Diagnostics // VM\DebugDebugger.h. The binder will catch some of these layout problems. internal class StackFrameHelper { - private Thread targetThread; - private int[] rgiOffset; - private int[] rgiILOffset; + private Thread? targetThread; + private int[]? rgiOffset; + private int[]? rgiILOffset; #pragma warning disable 414 // dynamicMethods is an array of System.Resolver objects, used to keep // DynamicMethodDescs AND collectible LoaderAllocators alive for the lifetime of StackFrameHelper. - private object dynamicMethods; // Field is not used from managed. - - private IntPtr[] rgMethodHandle; - private string[] rgAssemblyPath; - private Assembly[] rgAssembly; - private IntPtr[] rgLoadedPeAddress; - private int[] rgiLoadedPeSize; - private IntPtr[] rgInMemoryPdbAddress; - private int[] rgiInMemoryPdbSize; + private object? dynamicMethods; // Field is not used from managed. + + private IntPtr[]? rgMethodHandle; + private string[]? rgAssemblyPath; + private Assembly?[]? rgAssembly; + private IntPtr[]? rgLoadedPeAddress; + private int[]? rgiLoadedPeSize; + private IntPtr[]? rgInMemoryPdbAddress; + private int[]? rgiInMemoryPdbSize; // if rgiMethodToken[i] == 0, then don't attempt to get the portable PDB source/info - private int[] rgiMethodToken; - private string[] rgFilename; - private int[] rgiLineNumber; - private int[] rgiColumnNumber; - private bool[] rgiLastFrameFromForeignExceptionStackTrace; + private int[]? rgiMethodToken; + private string?[]? rgFilename; + private int[]? rgiLineNumber; + private int[]? rgiColumnNumber; + private bool[]? rgiLastFrameFromForeignExceptionStackTrace; private int iFrameCount; #pragma warning restore 414 - private delegate void GetSourceLineInfoDelegate(Assembly assembly, string assemblyPath, IntPtr loadedPeAddress, + private delegate void GetSourceLineInfoDelegate(Assembly? assembly, string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset, - out string sourceFile, out int sourceLine, out int sourceColumn); + out string? sourceFile, out int sourceLine, out int sourceColumn); - private static GetSourceLineInfoDelegate s_getSourceLineInfo = null; + private static GetSourceLineInfoDelegate? s_getSourceLineInfo = null; [ThreadStatic] private static int t_reentrancy = 0; - public StackFrameHelper(Thread target) + public StackFrameHelper(Thread? target) { targetThread = target; rgMethodHandle = null; @@ -92,7 +93,7 @@ public StackFrameHelper(Thread target) // rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already // done by GetStackFramesInternal (on Windows for old PDB format). // - internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception) + internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception? exception) { StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception); @@ -108,7 +109,7 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce { if (s_getSourceLineInfo == null) { - Type symbolsType = Type.GetType( + Type? symbolsType = Type.GetType( "System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false); @@ -123,14 +124,14 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce typeof(int), typeof(int), typeof(int), typeof(string).MakeByRefType(), typeof(int).MakeByRefType(), typeof(int).MakeByRefType() }; - MethodInfo symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null); + MethodInfo? symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, parameterTypes, null); if (symbolsMethodInfo == null) { return; } // Create an instance of System.Diagnostics.Stacktrace.Symbols - object target = Activator.CreateInstance(symbolsType); + object? target = Activator.CreateInstance(symbolsType); // Create an instance delegate for the GetSourceLineInfo method GetSourceLineInfoDelegate getSourceLineInfo = (GetSourceLineInfoDelegate)symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target); @@ -144,11 +145,11 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce { // If there was some reason not to try get the symbols from the portable PDB reader like the module was // ENC or the source/line info was already retrieved, the method token is 0. - if (rgiMethodToken[index] != 0) + if (rgiMethodToken![index] != 0) { - s_getSourceLineInfo(rgAssembly[index], rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index], - rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index], - rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]); + s_getSourceLineInfo!(rgAssembly![index], rgAssemblyPath![index]!, rgLoadedPeAddress![index], rgiLoadedPeSize![index], + rgInMemoryPdbAddress![index], rgiInMemoryPdbSize![index], rgiMethodToken![index], + rgiILOffset![index], out rgFilename![index], out rgiLineNumber![index], out rgiColumnNumber![index]); } } } @@ -161,26 +162,26 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce } } - public virtual MethodBase GetMethodBase(int i) + public virtual MethodBase? GetMethodBase(int i) { // There may be a better way to do this. // we got RuntimeMethodHandles here and we need to go to MethodBase // but we don't know whether the reflection info has been initialized // or not. So we call GetMethods and GetConstructors on the type // and then we fetch the proper MethodBase!! - IntPtr mh = rgMethodHandle[i]; + IntPtr mh = rgMethodHandle![i]; if (mh == IntPtr.Zero) return null; - IRuntimeMethodInfo mhReal = RuntimeMethodHandle.GetTypicalMethodDefinition(new RuntimeMethodInfoStub(mh, this)); + IRuntimeMethodInfo? mhReal = RuntimeMethodHandle.GetTypicalMethodDefinition(new RuntimeMethodInfoStub(mh, this)); return RuntimeType.GetMethodBase(mhReal); } - public virtual int GetOffset(int i) { return rgiOffset[i]; } - public virtual int GetILOffset(int i) { return rgiILOffset[i]; } - public virtual string GetFilename(int i) { return rgFilename == null ? null : rgFilename[i]; } + public virtual int GetOffset(int i) { return rgiOffset![i]; } + public virtual int GetILOffset(int i) { return rgiILOffset![i]; } + public virtual string? GetFilename(int i) { return rgFilename == null ? null : rgFilename[i]; } public virtual int GetLineNumber(int i) { return rgiLineNumber == null ? 0 : rgiLineNumber[i]; } public virtual int GetColumnNumber(int i) { return rgiColumnNumber == null ? 0 : rgiColumnNumber[i]; } diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs index 5c8a8c5ac84e..a86f8bac12e4 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Threading; using System.Runtime.CompilerServices; using System.Reflection; @@ -11,7 +12,7 @@ namespace System.Diagnostics public partial class StackTrace { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception e); + internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception? e); internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames) { @@ -23,13 +24,13 @@ internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrame // System.Diagnostics functions for (int i = 0; i < iNumFrames; i++) { - MethodBase mb = StackF.GetMethodBase(i); + MethodBase? mb = StackF.GetMethodBase(i); if (mb != null) { - Type t = mb.DeclaringType; + Type? t = mb.DeclaringType; if (t == null) break; - string ns = t.Namespace; + string? ns = t.Namespace; if (ns == null) break; if (!string.Equals(ns, PackageName, StringComparison.Ordinal)) @@ -41,7 +42,7 @@ internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrame return iRetVal; } - private void InitializeForException(Exception exception, int skipFrames, bool fNeedFileInfo) + private void InitializeForException(Exception? exception, int skipFrames, bool fNeedFileInfo) { CaptureStackTrace(skipFrames, fNeedFileInfo, exception); } @@ -55,7 +56,7 @@ private void InitializeForCurrentThread(int skipFrames, bool fNeedFileInfo) /// Retrieves an object with stack trace information encoded. /// It leaves out the first "iSkip" lines of the stacktrace. /// - private void CaptureStackTrace(int skipFrames, bool fNeedFileInfo, Exception e) + private void CaptureStackTrace(int skipFrames, bool fNeedFileInfo, Exception? e) { _methodsToSkip = skipFrames; diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/ISymWriter.cs b/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/ISymWriter.cs index 31f81e1bed07..e8148203d612 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/ISymWriter.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/ISymWriter.cs @@ -12,11 +12,9 @@ ** ===========================================================*/ -using System; -using System.Text; +#nullable enable using System.Reflection; using System.Runtime.InteropServices; -using System.Runtime.Versioning; namespace System.Diagnostics.SymbolStore { @@ -26,7 +24,7 @@ internal interface ISymbolWriter // Define a source document. Guid's will be provided for the // languages, vendors, and document types that we currently know // about. - ISymbolDocumentWriter DefineDocument(string url, + ISymbolDocumentWriter? DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType); diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs b/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs index 15b3c7f4f770..9005156ce668 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs @@ -13,8 +13,7 @@ ===========================================================*/ // Only statics, does not need to be marked with the serializable attribute -using System; - +#nullable enable namespace System.Diagnostics.SymbolStore { internal enum SymAddressKind diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs b/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs index 238e3a524df1..52eb1bf3517b 100644 --- a/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs +++ b/src/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs @@ -10,9 +10,7 @@ ** ===========================================================*/ -using System; -using System.Runtime.InteropServices; - +#nullable enable namespace System.Diagnostics.SymbolStore { internal struct SymbolToken @@ -25,7 +23,7 @@ internal struct SymbolToken public override int GetHashCode() { return m_token; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is SymbolToken) return Equals((SymbolToken)obj); diff --git a/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs index d5fea8a7518d..1cab1c95c89b 100644 --- a/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -33,7 +34,7 @@ public static extern int ExitCode // to assign blame for crashes. Don't mess with this, such as by making it call // another managed helper method, unless you consult with some CLR Watson experts. [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void FailFast(string message); + public static extern void FailFast(string? message); // This overload of FailFast will allow you to specify the exception object // whose bucket details *could* be used when undergoing the failfast process. @@ -49,10 +50,10 @@ public static extern int ExitCode // IP for bucketing. If the exception object is not preallocated, it will use the bucket // details contained in the object (if any). [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void FailFast(string message, Exception exception); + public static extern void FailFast(string? message, Exception? exception); [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void FailFast(string message, Exception exception, string errorMessage); + public static extern void FailFast(string? message, Exception? exception, string? errorMessage); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string[] GetCommandLineArgsNative(); @@ -77,11 +78,8 @@ public static string[] GetCommandLineArgs() GetCommandLineArgsNative(); } - public static extern bool HasShutdownStarted - { - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } + // Unconditionally return false since .NET Core does not support object finalization during shutdown. + public static bool HasShutdownStarted => false; public static int ProcessorCount => GetProcessorCount(); @@ -91,7 +89,7 @@ public static extern bool HasShutdownStarted // If you change this method's signature then you must change the code that calls it // in excep.cpp and probably you will have to visit mscorlib.h to add the new signature // as well as metasig.h to create the new signature type - internal static string GetResourceStringLocal(string key) => SR.GetResourceString(key); + internal static string? GetResourceStringLocal(string key) => SR.GetResourceString(key); public static string StackTrace { @@ -105,40 +103,6 @@ public static extern int TickCount get; } -#if !FEATURE_PAL - internal static bool IsWindows8OrAbove => WindowsVersion.IsWindows8OrAbove; - - // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup - private static class WindowsVersion - { - // Cache the value in readonly static that can be optimized out by the JIT - internal readonly static bool IsWindows8OrAbove = GetIsWindows8OrAbove(); - - private static bool GetIsWindows8OrAbove() - { - ulong conditionMask = Interop.Kernel32.VerSetConditionMask(0, Interop.Kernel32.VER_MAJORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); - conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_MINORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); - conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMAJOR, Interop.Kernel32.VER_GREATER_EQUAL); - conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMINOR, Interop.Kernel32.VER_GREATER_EQUAL); - - // Windows 8 version is 6.2 - Interop.Kernel32.OSVERSIONINFOEX version = default; - unsafe - { - version.dwOSVersionInfoSize = sizeof(Interop.Kernel32.OSVERSIONINFOEX); - } - version.dwMajorVersion = 6; - version.dwMinorVersion = 2; - version.wServicePackMajor = 0; - version.wServicePackMinor = 0; - - return Interop.Kernel32.VerifyVersionInfoW(ref version, - Interop.Kernel32.VER_MAJORVERSION | Interop.Kernel32.VER_MINORVERSION | Interop.Kernel32.VER_SERVICEPACKMAJOR | Interop.Kernel32.VER_SERVICEPACKMINOR, - conditionMask); - } - } -#endif - #if FEATURE_COMINTEROP // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup private static class WinRT diff --git a/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs index c19aa643fc42..9faf29205bf2 100644 --- a/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs @@ -24,7 +24,7 @@ partial void RestoreRemoteStackTrace(SerializationInfo info, StreamingContext co // We use the no throw version since we could be deserializing a pre-V4 // exception object that may not have this entry. In such a case, we would // get null. - _watsonBuckets = (object)info.GetValueNoThrow("WatsonBuckets", typeof(byte[])); // Do not rename (binary serialization) + _watsonBuckets = info.GetValueNoThrow("WatsonBuckets", typeof(byte[])); // Do not rename (binary serialization) // If we are constructing a new exception after a cross-appdomain call... if (context.State == StreamingContextStates.CrossAppDomain) @@ -206,8 +206,8 @@ private static string GetStackTrace(bool needFileInfo, Exception e) StackTrace st = new StackTrace(this, fNeedFileInfo: false); if (st.FrameCount > 0) { - StackFrame sf = st.GetFrame(0); - MethodBase method = sf.GetMethod(); + StackFrame sf = st.GetFrame(0)!; + MethodBase method = sf.GetMethod()!; Module module = method.Module; @@ -465,7 +465,7 @@ internal static string GetMessageFromNativeResources(ExceptionMessageKind kind) { string? retMesg = null; GetMessageFromNativeResources(kind, JitHelpers.GetStringHandleOnStack(ref retMesg)); - return retMesg; + return retMesg!; } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] diff --git a/src/System.Private.CoreLib/src/System/GC.cs b/src/System.Private.CoreLib/src/System/GC.cs index 4485afe469ba..474f7bbe925a 100644 --- a/src/System.Private.CoreLib/src/System/GC.cs +++ b/src/System.Private.CoreLib/src/System/GC.cs @@ -13,8 +13,8 @@ ** ===========================================================*/ +#nullable enable using System.Runtime.CompilerServices; -using System.Globalization; using System.Runtime.InteropServices; using System.Diagnostics; @@ -60,6 +60,21 @@ internal static extern void GetMemoryInfo(out uint highMemLoadThreshold, out UIntPtr lastRecordedHeapSize, out UIntPtr lastRecordedFragmentation); + public static GCMemoryInfo GetGCMemoryInfo() + { + GetMemoryInfo(out uint highMemLoadThreshold, + out ulong totalPhysicalMem, + out uint lastRecordedMemLoad, + out UIntPtr lastRecordedHeapSize, + out UIntPtr lastRecordedFragmentation); + + return new GCMemoryInfo((long)((double)highMemLoadThreshold / 100 * totalPhysicalMem), + (long)((double)lastRecordedMemLoad / 100 * totalPhysicalMem), + (long)totalPhysicalMem, + (long)(ulong)lastRecordedHeapSize, + (long)(ulong)lastRecordedFragmentation); + } + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern int _StartNoGCRegion(long totalSize, bool lohSizeKnown, long lohSize, bool disallowFullBlockingGC); @@ -236,7 +251,7 @@ public static int CollectionCount(int generation) // If we insert a call to GC.KeepAlive(this) at the end of Problem(), then // Foo doesn't get finalized and the stream stays open. [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations - public static void KeepAlive(object obj) + public static void KeepAlive(object? obj) { } diff --git a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs index 95a54fd5e3b8..d1bc0f41772d 100644 --- a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs +++ b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Globalization { internal sealed partial class GlobalizationMode diff --git a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.cs b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.cs index 2738d5b4ba49..ebfa25f28c17 100644 --- a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.cs +++ b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Globalization { internal sealed partial class GlobalizationMode diff --git a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index 57f3581265e0..c1ad15f20975 100644 --- a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Globalization { internal sealed partial class GlobalizationMode @@ -18,7 +19,7 @@ internal static bool GetInvariantSwitchValue() if (!exist) { // Linux doesn't support environment variable names include dots - string switchValue = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); + string? switchValue = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); if (switchValue != null) { ret = bool.IsTrueStringIgnoreCase(switchValue) || switchValue.Equals("1"); diff --git a/src/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs b/src/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs index 9da8e35f29db..ebeab9a02bb0 100644 --- a/src/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs @@ -22,16 +22,16 @@ private FileLoadException(string? fileName, string? fusionLog, int hResult) internal static string FormatFileLoadExceptionMessage(string? fileName, int hResult) { - string? format = null; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 GetStringHandleOnStack needs to be attributed + string? format = null; GetFileLoadExceptionMessage(hResult, JitHelpers.GetStringHandleOnStack(ref format)); - string? message = null; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 GetStringHandleOnStack needs to be attributed + string? message = null; if (hResult == System.HResults.COR_E_BADEXEFORMAT) message = SR.Arg_BadImageFormatException; else GetMessageForHR(hResult, JitHelpers.GetStringHandleOnStack(ref message)); - return string.Format(format, fileName, message); + return string.Format(format!, fileName, message!); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 GetStringHandleOnStack needs to be attributed } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] diff --git a/src/System.Private.CoreLib/src/System/Internal.cs b/src/System.Private.CoreLib/src/System/Internal.cs index cc0b8283c0bd..88a349808929 100644 --- a/src/System.Private.CoreLib/src/System/Internal.cs +++ b/src/System.Private.CoreLib/src/System/Internal.cs @@ -11,6 +11,7 @@ ** ===========================================================*/ +#nullable disable // Code in this file isn't actually executed using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Collections.Generic; diff --git a/src/System.Private.CoreLib/src/System/Math.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Math.CoreCLR.cs index 149dd0670274..b33ae1e9093b 100644 --- a/src/System.Private.CoreLib/src/System/Math.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Math.CoreCLR.cs @@ -13,6 +13,7 @@ //This class contains only static members and doesn't require serialization. +#nullable enable using System.Runtime.CompilerServices; namespace System diff --git a/src/System.Private.CoreLib/src/System/MathF.CoreCLR.cs b/src/System.Private.CoreLib/src/System/MathF.CoreCLR.cs index 5ba0a9271cb2..ba575d954472 100644 --- a/src/System.Private.CoreLib/src/System/MathF.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/MathF.CoreCLR.cs @@ -10,6 +10,7 @@ //This class contains only static members and doesn't require serialization. +#nullable enable using System.Runtime.CompilerServices; namespace System diff --git a/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs index 4683b88632df..edc0c09cf1df 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs @@ -2,26 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; -using System.IO; -using System.Configuration.Assemblies; +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Serialization; using System.Runtime.Loader; +using System.Runtime.Serialization; using StackCrawlMark = System.Threading.StackCrawlMark; namespace System.Reflection { public abstract partial class Assembly : ICustomAttributeProvider, ISerializable { - // Locate an assembly by the long form of the assembly name. + // Locate an assembly by the long form of the assembly name. // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890" [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly Load(string assemblyString) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.InternalLoad(assemblyString, ref stackMark); + return RuntimeAssembly.InternalLoad(assemblyString, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } // Locate an assembly by its name. The name can be strong or @@ -33,14 +31,14 @@ public static Assembly Load(AssemblyName assemblyRef) throw new ArgumentNullException(nameof(assemblyRef)); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return Load(assemblyRef, ref stackMark, IntPtr.Zero); + return Load(assemblyRef, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } // Locate an assembly by its name. The name can be strong or // weak. The assembly is loaded into the domain of the caller. - internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stackMark, IntPtr ptrLoadContextBinder) + internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stackMark, AssemblyLoadContext? assemblyLoadContext) { - AssemblyName modifiedAssemblyRef = null; + AssemblyName? modifiedAssemblyRef = null; if (assemblyRef.CodeBase != null) { modifiedAssemblyRef = (AssemblyName)assemblyRef.Clone(); @@ -51,7 +49,7 @@ internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stack modifiedAssemblyRef = assemblyRef; } - return RuntimeAssembly.InternalLoadAssemblyName(modifiedAssemblyRef, ref stackMark, ptrLoadContextBinder); + return RuntimeAssembly.InternalLoadAssemblyName(modifiedAssemblyRef, ref stackMark, assemblyLoadContext); } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] @@ -59,9 +57,9 @@ internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stack internal static RuntimeAssembly GetExecutingAssembly(ref StackCrawlMark stackMark) { - RuntimeAssembly retAssembly = null; + RuntimeAssembly? retAssembly = null; GetExecutingAssemblyNative(JitHelpers.GetStackCrawlMarkHandle(ref stackMark), JitHelpers.GetObjectHandleOnStack(ref retAssembly)); - return retAssembly; + return retAssembly!; // TODO-NULLABLE: Confirm this can never be null } // Get the assembly that the current code is running from. @@ -88,12 +86,12 @@ public static Assembly GetCallingAssembly() // internal test hook private static bool s_forceNullEntryPoint = false; - public static Assembly GetEntryAssembly() + public static Assembly? GetEntryAssembly() { if (s_forceNullEntryPoint) return null; - RuntimeAssembly entryAssembly = null; + RuntimeAssembly? entryAssembly = null; GetEntryAssemblyNative(JitHelpers.GetObjectHandleOnStack(ref entryAssembly)); return entryAssembly; } diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs new file mode 100644 index 000000000000..e6bc0b7daacc --- /dev/null +++ b/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs @@ -0,0 +1,112 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System.Configuration.Assemblies; +using System.Globalization; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; + +namespace System.Reflection +{ + public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable + { + public AssemblyName(string assemblyName) + { + if (assemblyName == null) + throw new ArgumentNullException(nameof(assemblyName)); + if ((assemblyName.Length == 0) || + (assemblyName[0] == '\0')) + throw new ArgumentException(SR.Format_StringZeroLength); + + _name = assemblyName; + nInit(out RuntimeAssembly? dummy, false); + } + + internal AssemblyName(string? name, + byte[]? publicKey, + byte[]? publicKeyToken, + Version? version, + CultureInfo? cultureInfo, + AssemblyHashAlgorithm hashAlgorithm, + AssemblyVersionCompatibility versionCompatibility, + string? codeBase, + AssemblyNameFlags flags, + StrongNameKeyPair? keyPair) // Null if ref, matching Assembly if def + { + _name = name; + _publicKey = publicKey; + _publicKeyToken = publicKeyToken; + _version = version; + _cultureInfo = cultureInfo; + _hashAlgorithm = hashAlgorithm; + _versionCompatibility = versionCompatibility; + _codeBase = codeBase; + _flags = flags; + _strongNameKeyPair = keyPair; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern void nInit(out RuntimeAssembly? assembly, bool raiseResolveEvent); + + // This call opens and closes the file, but does not add the + // assembly to the domain. + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern AssemblyName nGetFileInformation(string s); + + internal static AssemblyName GetFileInformationCore(string assemblyFile) + { + string fullPath = Path.GetFullPath(assemblyFile); + return nGetFileInformation(fullPath); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern byte[] ComputePublicKeyToken(); + + internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) + { + ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _flags); + } + + internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags) + { + if (((uint)flags & 0xF0) == 0x70) + return ProcessorArchitecture.None; + + if ((pek & PortableExecutableKinds.PE32Plus) == PortableExecutableKinds.PE32Plus) + { + switch (ifm) + { + case ImageFileMachine.IA64: + return ProcessorArchitecture.IA64; + case ImageFileMachine.AMD64: + return ProcessorArchitecture.Amd64; + case ImageFileMachine.I386: + if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly) + return ProcessorArchitecture.MSIL; + break; + } + } + else + { + if (ifm == ImageFileMachine.I386) + { + if ((pek & PortableExecutableKinds.Required32Bit) == PortableExecutableKinds.Required32Bit) + return ProcessorArchitecture.X86; + + if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly) + return ProcessorArchitecture.MSIL; + + return ProcessorArchitecture.X86; + } + if (ifm == ImageFileMachine.ARM) + { + return ProcessorArchitecture.Arm; + } + } + return ProcessorArchitecture.None; + } + } +} diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs index c3da6cc3d929..ff3ccd617683 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs @@ -14,12 +14,9 @@ ===========================================================*/ -using System; -using System.Reflection; +using System.Buffers.Binary; using System.IO; using System.Text; -using System.Runtime.InteropServices; -using System.Globalization; using System.Diagnostics; namespace System.Reflection.Emit @@ -305,7 +302,7 @@ private static void VerifyTypeAndPassedObjectType(Type type, Type passedType, st } } - private void EmitType(BinaryWriter writer, Type type) + private static void EmitType(BinaryWriter writer, Type type) { if (type.IsPrimitive) { @@ -377,7 +374,7 @@ private void EmitType(BinaryWriter writer, Type type) } } - private void EmitString(BinaryWriter writer, string str) + private static void EmitString(BinaryWriter writer, string str) { // Strings are emitted with a length prefix in a compressed format (1, 2 or 4 bytes) as used internally by metadata. byte[] utf8Str = Encoding.UTF8.GetBytes(str); @@ -388,20 +385,16 @@ private void EmitString(BinaryWriter writer, string str) } else if (length <= 0x3fff) { - writer.Write((byte)((length >> 8) | 0x80)); - writer.Write((byte)(length & 0xff)); + writer.Write(BinaryPrimitives.ReverseEndianness((short)(length | 0x80_00))); } else { - writer.Write((byte)((length >> 24) | 0xc0)); - writer.Write((byte)((length >> 16) & 0xff)); - writer.Write((byte)((length >> 8) & 0xff)); - writer.Write((byte)(length & 0xff)); + writer.Write(BinaryPrimitives.ReverseEndianness(length | 0xC0_00_00_00)); } writer.Write(utf8Str); } - private void EmitValue(BinaryWriter writer, Type type, object value) + private static void EmitValue(BinaryWriter writer, Type type, object value) { if (type.IsEnum) { diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs index b47b305057d6..d26d97dcb770 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -7,6 +7,7 @@ namespace System.Reflection.Emit { using System; + using System.Buffers.Binary; using System.Globalization; using System.Diagnostics.SymbolStore; using System.Runtime.InteropServices; @@ -638,14 +639,8 @@ internal DynamicResolver(DynamicILInfo dynamicILInfo) } catch { - // We go over all DynamicMethodDesc during AppDomain shutdown and make sure - // that everything associated with them is released. So it is ok to skip reregistration - // for finalization during appdomain shutdown - if (!Environment.HasShutdownStarted) - { - // Try again later. - GC.ReRegisterForFinalize(this); - } + // Try again later. + GC.ReRegisterForFinalize(this); return; } @@ -666,12 +661,9 @@ private class DestroyScout // It is not safe to destroy the method if the managed resolver is alive. if (RuntimeMethodHandle.GetResolver(m_methodHandle) != null) { - if (!Environment.HasShutdownStarted) - { - // Somebody might have been holding a reference on us via weak handle. - // We will keep trying. It will be hopefully released eventually. - GC.ReRegisterForFinalize(this); - } + // Somebody might have been holding a reference on us via weak handle. + // We will keep trying. It will be hopefully released eventually. + GC.ReRegisterForFinalize(this); return; } @@ -732,10 +724,12 @@ internal override byte[] GetCodeInfo( if ((header & 0x40) != 0) // Fat { - byte[] size = new byte[4]; - for (int q = 0; q < 3; q++) - size[q] = m_exceptionHeader[q + 1]; - EHCount = (BitConverter.ToInt32(size, 0) - 4) / 24; + // Positions 1..3 of m_exceptionHeader are a 24-bit little-endian integer. + int size = m_exceptionHeader[3] << 16; + size |= m_exceptionHeader[2] << 8; + size |= m_exceptionHeader[1]; + + EHCount = (size - 4) / 24; } else EHCount = (m_exceptionHeader[1] - 2) / 12; diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index 6de54f362515..47c20c90fde6 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -4,20 +4,18 @@ // -using System; +using System.Buffers.Binary; +using System.Diagnostics; using System.Diagnostics.SymbolStore; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Reflection; -using System.Globalization; -using System.Diagnostics; -using System.Diagnostics.Contracts; namespace System.Reflection.Emit { public class ILGenerator { #region Const Members - private const int defaultSize = 16; + private const int DefaultSize = 16; private const int DefaultFixupArraySize = 8; private const int DefaultLabelArraySize = 4; private const int DefaultExceptionArraySize = 2; @@ -38,19 +36,6 @@ internal static T[] EnlargeArray(T[] incoming, int requiredSize) return temp; } - private static byte[] EnlargeArray(byte[] incoming) - { - return EnlargeArray(incoming, incoming.Length * 2); - } - - private static byte[] EnlargeArray(byte[] incoming, int requiredSize) - { - Debug.Assert(incoming != null); - - byte[] temp = new byte[requiredSize]; - Buffer.BlockCopy(incoming, 0, temp, 0, incoming.Length); - return temp; - } #endregion #region Internal Data Members @@ -84,15 +69,10 @@ private static byte[] EnlargeArray(byte[] incoming, int requiredSize) private int m_maxMidStack = 0; // Maximum stack size for a given basic block. private int m_maxMidStackCur = 0; // Running count of the maximum stack size for the current basic block. - internal int CurrExcStackCount - { - get { return m_currExcStackCount; } - } + internal int CurrExcStackCount => m_currExcStackCount; + + internal __ExceptionInfo[] CurrExcStack => m_currExcStack; - internal __ExceptionInfo[] CurrExcStack - { - get { return m_currExcStack; } - } #endregion #region Constructor @@ -107,14 +87,7 @@ internal ILGenerator(MethodInfo methodBuilder, int size) Debug.Assert(methodBuilder != null); Debug.Assert(methodBuilder is MethodBuilder || methodBuilder is DynamicMethod); - if (size < defaultSize) - { - m_ILStream = new byte[defaultSize]; - } - else - { - m_ILStream = new byte[size]; - } + m_ILStream = new byte[Math.Max(size, DefaultSize)]; m_length = 0; @@ -140,10 +113,7 @@ internal ILGenerator(MethodInfo methodBuilder, int size) // initialize local signature m_localCount = 0; MethodBuilder mb = m_methodBuilder as MethodBuilder; - if (mb == null) - m_localSignature = SignatureHelper.GetLocalVarSigHelper(null); - else - m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb.GetTypeBuilder().Module); + m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb?.GetTypeBuilder().Module); } #endregion @@ -161,16 +131,21 @@ internal virtual void RecordTokenFixup() internal void InternalEmit(OpCode opcode) { + short opcodeValue = opcode.Value; if (opcode.Size != 1) { - m_ILStream[m_length++] = (byte)(opcode.Value >> 8); + BinaryPrimitives.WriteInt16BigEndian(m_ILStream.AsSpan(m_length), opcodeValue); + m_length += 2; + } + else + { + m_ILStream[m_length++] = (byte)opcodeValue; } - - m_ILStream[m_length++] = (byte)opcode.Value; UpdateStackSize(opcode, opcode.StackChange()); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void UpdateStackSize(OpCode opcode, int stackchange) { // Updates internal variables for keeping track of the stack size @@ -223,57 +198,45 @@ internal byte[] BakeByteArray() // BakeByteArray is an internal function designed to be called by MethodBuilder to do // all of the fixups and return a new byte array representing the byte stream with labels resolved, etc. - int newSize; - int updateAddr; - byte[] newBytes; - if (m_currExcStackCount != 0) { throw new ArgumentException(SR.Argument_UnclosedExceptionBlock); } + if (m_length == 0) return null; - //Calculate the size of the new array. - newSize = m_length; - //Allocate space for the new array. - newBytes = new byte[newSize]; + byte[] newBytes = new byte[m_length]; //Copy the data from the old array - Buffer.BlockCopy(m_ILStream, 0, newBytes, 0, newSize); + Array.Copy(m_ILStream, 0, newBytes, 0, m_length); //Do the fixups. //This involves iterating over all of the labels and //replacing them with their proper values. for (int i = 0; i < m_fixupCount; i++) { - updateAddr = GetLabelPos(m_fixupData[i].m_fixupLabel) - (m_fixupData[i].m_fixupPos + m_fixupData[i].m_fixupInstSize); + __FixupData fixupData = m_fixupData[i]; + int updateAddr = GetLabelPos(fixupData.m_fixupLabel) - (fixupData.m_fixupPos + fixupData.m_fixupInstSize); //Handle single byte instructions //Throw an exception if they're trying to store a jump in a single byte instruction that doesn't fit. - if (m_fixupData[i].m_fixupInstSize == 1) + if (fixupData.m_fixupInstSize == 1) { //Verify that our one-byte arg will fit into a Signed Byte. if (updateAddr < sbyte.MinValue || updateAddr > sbyte.MaxValue) { - throw new NotSupportedException(SR.Format(SR.NotSupported_IllegalOneByteBranch, m_fixupData[i].m_fixupPos, updateAddr)); + throw new NotSupportedException(SR.Format(SR.NotSupported_IllegalOneByteBranch, fixupData.m_fixupPos, updateAddr)); } //Place the one-byte arg - if (updateAddr < 0) - { - newBytes[m_fixupData[i].m_fixupPos] = (byte)(256 + updateAddr); - } - else - { - newBytes[m_fixupData[i].m_fixupPos] = (byte)updateAddr; - } + newBytes[fixupData.m_fixupPos] = (byte)updateAddr; } else { //Place the four-byte arg - PutInteger4InArray(updateAddr, m_fixupData[i].m_fixupPos, newBytes); + BinaryPrimitives.WriteInt32LittleEndian(newBytes.AsSpan(fixupData.m_fixupPos), updateAddr); } } return newBytes; @@ -281,7 +244,6 @@ internal byte[] BakeByteArray() internal __ExceptionInfo[] GetExceptions() { - __ExceptionInfo[] temp; if (m_currExcStackCount != 0) { throw new NotSupportedException(SR.Argument_UnclosedExceptionBlock); @@ -292,7 +254,7 @@ internal __ExceptionInfo[] GetExceptions() return null; } - temp = new __ExceptionInfo[m_exceptionCount]; + var temp = new __ExceptionInfo[m_exceptionCount]; Array.Copy(m_exceptions, 0, temp, 0, m_exceptionCount); SortExceptions(temp); return temp; @@ -303,31 +265,22 @@ internal void EnsureCapacity(int size) // Guarantees an array capable of holding at least size elements. if (m_length + size >= m_ILStream.Length) { - if (m_length + size >= 2 * m_ILStream.Length) - { - m_ILStream = EnlargeArray(m_ILStream, m_length + size); - } - else - { - m_ILStream = EnlargeArray(m_ILStream); - } + IncreaseCapacity(size); } } - internal void PutInteger4(int value) + private void IncreaseCapacity(int size) { - m_length = PutInteger4InArray(value, m_length, m_ILStream); + byte[] temp = new byte[Math.Max(m_ILStream.Length * 2, m_length + size)]; + Array.Copy(m_ILStream, 0, temp, 0, m_ILStream.Length); + m_ILStream = temp; } - private static int PutInteger4InArray(int value, int startPos, byte[] array) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PutInteger4(int value) { - // Puts an Int32 onto the stream. This is an internal routine, so it does not do any error checking. - - array[startPos++] = (byte)value; - array[startPos++] = (byte)(value >> 8); - array[startPos++] = (byte)(value >> 16); - array[startPos++] = (byte)(value >> 24); - return startPos; + BinaryPrimitives.WriteInt32LittleEndian(m_ILStream.AsSpan(m_length), value); + m_length += 4; } private int GetLabelPos(Label lbl) @@ -360,11 +313,12 @@ private void AddFixup(Label lbl, int pos, int instSize) m_fixupData = EnlargeArray(m_fixupData); } - m_fixupData[m_fixupCount].m_fixupPos = pos; - m_fixupData[m_fixupCount].m_fixupLabel = lbl; - m_fixupData[m_fixupCount].m_fixupInstSize = instSize; - - m_fixupCount++; + m_fixupData[m_fixupCount++] = new __FixupData + { + m_fixupPos = pos, + m_fixupLabel = lbl, + m_fixupInstSize = instSize + }; } internal int GetMaxStackSize() @@ -428,17 +382,9 @@ public virtual void Emit(OpCode opcode, byte arg) public void Emit(OpCode opcode, sbyte arg) { // Puts opcode onto the stream of instructions followed by arg - EnsureCapacity(4); InternalEmit(opcode); - if (arg < 0) - { - m_ILStream[m_length++] = (byte)(256 + arg); - } - else - { - m_ILStream[m_length++] = (byte)arg; - } + m_ILStream[m_length++] = (byte)arg; } public virtual void Emit(OpCode opcode, short arg) @@ -446,8 +392,8 @@ public virtual void Emit(OpCode opcode, short arg) // Puts opcode onto the stream of instructions followed by arg EnsureCapacity(5); InternalEmit(opcode); - m_ILStream[m_length++] = (byte)arg; - m_ILStream[m_length++] = (byte)(arg >> 8); + BinaryPrimitives.WriteInt16LittleEndian(m_ILStream.AsSpan(m_length), arg); + m_length += 2; } public virtual void Emit(OpCode opcode, int arg) @@ -469,8 +415,6 @@ public virtual void Emit(OpCode opcode, MethodInfo meth) } else { - int stackchange = 0; - // Reflection doesn't distinguish between these two concepts: // 1. A generic method definition: Foo`1 // 2. A generic method definition instantiated over its own generic arguments: Foo`1 @@ -481,18 +425,16 @@ public virtual void Emit(OpCode opcode, MethodInfo meth) EnsureCapacity(7); InternalEmit(opcode); - UpdateStackSize(opcode, stackchange); + UpdateStackSize(opcode, 0); RecordTokenFixup(); PutInteger4(tk); } } - public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) { int stackchange = 0; - SignatureHelper sig; if (optionalParameterTypes != null) { if ((callingConvention & CallingConventions.VarArgs) == 0) @@ -503,10 +445,10 @@ public virtual void EmitCalli(OpCode opcode, CallingConventions callingConventio } ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; - sig = GetMemberRefSignature(callingConvention, - returnType, - parameterTypes, - optionalParameterTypes); + SignatureHelper sig = GetMemberRefSignature(callingConvention, + returnType, + parameterTypes, + optionalParameterTypes); EnsureCapacity(7); Emit(OpCodes.Calli); @@ -535,8 +477,6 @@ public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv { int stackchange = 0; int cParams = 0; - int i; - SignatureHelper sig; ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; @@ -545,14 +485,14 @@ public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv cParams = parameterTypes.Length; } - sig = SignatureHelper.GetMethodSigHelper( + SignatureHelper sig = SignatureHelper.GetMethodSigHelper( modBuilder, unmanagedCallConv, returnType); if (parameterTypes != null) { - for (i = 0; i < cParams; i++) + for (int i = 0; i < cParams; i++) { sig.AddArgument(parameterTypes[i]); } @@ -693,7 +633,7 @@ public virtual void Emit(OpCode opcode, Type cls) // by cls. The location of cls is recorded so that the token can be // patched if necessary when persisting the module to a PE. - int tempVal = 0; + int tempVal; ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; if (opcode == OpCodes.Ldtoken && cls != null && cls.IsGenericTypeDefinition) { @@ -717,40 +657,24 @@ public virtual void Emit(OpCode opcode, long arg) { EnsureCapacity(11); InternalEmit(opcode); - m_ILStream[m_length++] = (byte)arg; - m_ILStream[m_length++] = (byte)(arg >> 8); - m_ILStream[m_length++] = (byte)(arg >> 16); - m_ILStream[m_length++] = (byte)(arg >> 24); - m_ILStream[m_length++] = (byte)(arg >> 32); - m_ILStream[m_length++] = (byte)(arg >> 40); - m_ILStream[m_length++] = (byte)(arg >> 48); - m_ILStream[m_length++] = (byte)(arg >> 56); + BinaryPrimitives.WriteInt64LittleEndian(m_ILStream.AsSpan(m_length), arg); + m_length += 8; } - public unsafe virtual void Emit(OpCode opcode, float arg) + public virtual void Emit(OpCode opcode, float arg) { EnsureCapacity(7); InternalEmit(opcode); - uint tempVal = *(uint*)&arg; - m_ILStream[m_length++] = (byte)tempVal; - m_ILStream[m_length++] = (byte)(tempVal >> 8); - m_ILStream[m_length++] = (byte)(tempVal >> 16); - m_ILStream[m_length++] = (byte)(tempVal >> 24); + BinaryPrimitives.WriteInt32LittleEndian(m_ILStream.AsSpan(m_length), BitConverter.SingleToInt32Bits(arg)); + m_length += 4; } - public unsafe virtual void Emit(OpCode opcode, double arg) + public virtual void Emit(OpCode opcode, double arg) { EnsureCapacity(11); InternalEmit(opcode); - ulong tempVal = *(ulong*)&arg; - m_ILStream[m_length++] = (byte)tempVal; - m_ILStream[m_length++] = (byte)(tempVal >> 8); - m_ILStream[m_length++] = (byte)(tempVal >> 16); - m_ILStream[m_length++] = (byte)(tempVal >> 24); - m_ILStream[m_length++] = (byte)(tempVal >> 32); - m_ILStream[m_length++] = (byte)(tempVal >> 40); - m_ILStream[m_length++] = (byte)(tempVal >> 48); - m_ILStream[m_length++] = (byte)(tempVal >> 56); + BinaryPrimitives.WriteInt64LittleEndian(m_ILStream.AsSpan(m_length), BitConverter.DoubleToInt64Bits(arg)); + m_length += 8; } public virtual void Emit(OpCode opcode, Label label) @@ -765,15 +689,13 @@ public virtual void Emit(OpCode opcode, Label label) // verify this). Since branches are relative instructions, label will be replaced with the // correct offset to branch during the fixup process. - int tempVal = label.GetLabelValue(); EnsureCapacity(7); InternalEmit(opcode); if (OpCodes.TakesSingleByteArgument(opcode)) { - AddFixup(label, m_length, 1); - m_length++; + AddFixup(label, m_length++, 1); } else { @@ -897,10 +819,11 @@ public virtual void Emit(OpCode opcode, LocalBuilder local) if (opcode.OperandType == OperandType.InlineNone) return; - else if (!OpCodes.TakesSingleByteArgument(opcode)) + + if (!OpCodes.TakesSingleByteArgument(opcode)) { - m_ILStream[m_length++] = (byte)tempVal; - m_ILStream[m_length++] = (byte)(tempVal >> 8); + BinaryPrimitives.WriteInt16LittleEndian(m_ILStream.AsSpan(m_length), (short)tempVal); + m_length += 2; } else { @@ -970,8 +893,7 @@ public virtual void EndExceptionBlock() // Pop the current exception block __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; - m_currExcStack[m_currExcStackCount - 1] = null; - m_currExcStackCount--; + m_currExcStack[--m_currExcStackCount] = null; Label endLabel = current.GetEndLabel(); int state = current.GetCurrentState(); @@ -984,23 +906,21 @@ public virtual void EndExceptionBlock() if (state == __ExceptionInfo.State_Catch) { - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, endLabel); } else if (state == __ExceptionInfo.State_Finally || state == __ExceptionInfo.State_Fault) { - this.Emit(OpCodes.Endfinally); + Emit(OpCodes.Endfinally); } //Check if we've already set this label. //The only reason why we might have set this is if we have a finally block. - if (m_labelList[endLabel.GetLabelValue()] == -1) - { - MarkLabel(endLabel); - } - else - { - MarkLabel(current.GetFinallyEndLabel()); - } + + Label label = m_labelList[endLabel.GetLabelValue()] != -1 + ? current.m_finallyEndLabel + : endLabel; + + MarkLabel(label); current.Done(m_length); } @@ -1014,8 +934,7 @@ public virtual void BeginExceptFilterBlock() __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; - Label endLabel = current.GetEndLabel(); - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFilterAddr(m_length); } @@ -1037,7 +956,7 @@ public virtual void BeginCatchBlock(Type exceptionType) throw new ArgumentException(SR.Argument_ShouldNotSpecifyExceptionType); } - this.Emit(OpCodes.Endfilter); + Emit(OpCodes.Endfilter); } else { @@ -1047,8 +966,7 @@ public virtual void BeginCatchBlock(Type exceptionType) throw new ArgumentNullException(nameof(exceptionType)); } - Label endLabel = current.GetEndLabel(); - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, current.GetEndLabel()); } current.MarkCatchAddr(m_length, exceptionType); @@ -1063,8 +981,7 @@ public virtual void BeginFaultBlock() __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; // emit the leave for the clause before this one. - Label endLabel = current.GetEndLabel(); - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFaultAddr(m_length); } @@ -1082,18 +999,18 @@ public virtual void BeginFinallyBlock() if (state != __ExceptionInfo.State_Try) { // generate leave for any preceeding catch clause - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, endLabel); catchEndAddr = m_length; } MarkLabel(endLabel); - Label finallyEndLabel = this.DefineLabel(); + Label finallyEndLabel = DefineLabel(); current.SetFinallyEndLabel(finallyEndLabel); // generate leave for try clause - this.Emit(OpCodes.Leave, finallyEndLabel); + Emit(OpCodes.Leave, finallyEndLabel); if (catchEndAddr == 0) catchEndAddr = m_length; current.MarkFinallyAddr(m_length, catchEndAddr); @@ -1164,8 +1081,8 @@ public virtual void ThrowException(Type excType) { throw new ArgumentException(SR.Argument_MissingDefaultConstructor); } - this.Emit(OpCodes.Newobj, con); - this.Emit(OpCodes.Throw); + Emit(OpCodes.Newobj, con); + Emit(OpCodes.Throw); } private static Type GetConsoleType() @@ -1191,7 +1108,6 @@ public virtual void EmitWriteLine(LocalBuilder localBuilder) // one of the types for which Console.WriteLine implements overloads. (e.g. // we do *not* call ToString on the locals. - object cls; if (m_methodBuilder == null) { throw new ArgumentException(SR.InvalidOperation_BadILGeneratorUsage); @@ -1201,7 +1117,7 @@ public virtual void EmitWriteLine(LocalBuilder localBuilder) Emit(OpCodes.Call, prop); Emit(OpCodes.Ldloc, localBuilder); Type[] parameterTypes = new Type[1]; - cls = localBuilder.LocalType; + object cls = localBuilder.LocalType; if (cls is TypeBuilder || cls is EnumBuilder) { throw new ArgumentException(SR.NotSupported_OutputStreamUsingTypeBuilder); @@ -1223,8 +1139,6 @@ public virtual void EmitWriteLine(FieldInfo fld) // one of the types for which Console.WriteLine implements overloads. (e.g. // we do *not* call ToString on the fields. - object cls; - if (fld == null) { throw new ArgumentNullException(nameof(fld)); @@ -1243,7 +1157,7 @@ public virtual void EmitWriteLine(FieldInfo fld) Emit(OpCodes.Ldfld, fld); } Type[] parameterTypes = new Type[1]; - cls = fld.FieldType; + object cls = fld.FieldType; if (cls is TypeBuilder || cls is EnumBuilder) { throw new NotSupportedException(SR.NotSupported_OutputStreamUsingTypeBuilder); @@ -1270,8 +1184,6 @@ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned) // Declare a local of type "local". The current active lexical scope // will be the scope that local will live. - LocalBuilder localBuilder; - MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder; if (methodBuilder == null) throw new NotSupportedException(); @@ -1295,9 +1207,7 @@ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned) // add the localType to local signature m_localSignature.AddArgument(localType, pinned); - localBuilder = new LocalBuilder(m_localCount, localType, methodBuilder, pinned); - m_localCount++; - return localBuilder; + return new LocalBuilder(m_localCount++, localType, methodBuilder, pinned); } public virtual void UsingNamespace(string usingNamespace) @@ -1311,12 +1221,11 @@ public virtual void UsingNamespace(string usingNamespace) if (usingNamespace.Length == 0) throw new ArgumentException(SR.Argument_EmptyName, nameof(usingNamespace)); - int index; MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder; if (methodBuilder == null) throw new NotSupportedException(); - index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex(); + int index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex(); if (index == -1) { methodBuilder.m_localSymInfo.AddUsingNamespace(usingNamespace); @@ -1351,13 +1260,7 @@ public virtual void EndScope() m_ScopeTree.AddScopeInfo(ScopeAction.Close, m_length); } - public virtual int ILOffset - { - get - { - return m_length; - } - } + public virtual int ILOffset => m_length; #endregion @@ -1422,7 +1325,8 @@ private void MarkHelper( Type catchClass, // catch exception type int type) // kind of clause { - if (m_currentCatch >= m_catchAddr.Length) + int currentCatch = m_currentCatch; + if (currentCatch >= m_catchAddr.Length) { m_filterAddr = ILGenerator.EnlargeArray(m_filterAddr); m_catchAddr = ILGenerator.EnlargeArray(m_catchAddr); @@ -1432,33 +1336,33 @@ private void MarkHelper( } if (type == Filter) { - m_type[m_currentCatch] = type; - m_filterAddr[m_currentCatch] = catchorfilterAddr; - m_catchAddr[m_currentCatch] = -1; - if (m_currentCatch > 0) + m_type[currentCatch ] = type; + m_filterAddr[currentCatch ] = catchorfilterAddr; + m_catchAddr[currentCatch ] = -1; + if (currentCatch > 0) { - Debug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); - m_catchEndAddr[m_currentCatch - 1] = catchorfilterAddr; + Debug.Assert(m_catchEndAddr[currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); + m_catchEndAddr[currentCatch - 1] = catchorfilterAddr; } } else { // catch or Fault clause - m_catchClass[m_currentCatch] = catchClass; - if (m_type[m_currentCatch] != Filter) + m_catchClass[currentCatch ] = catchClass; + if (m_type[currentCatch ] != Filter) { - m_type[m_currentCatch] = type; + m_type[currentCatch ] = type; } - m_catchAddr[m_currentCatch] = catchorfilterAddr; - if (m_currentCatch > 0) + m_catchAddr[currentCatch ] = catchorfilterAddr; + if (currentCatch > 0) { - if (m_type[m_currentCatch] != Filter) + if (m_type[currentCatch ] != Filter) { - Debug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); - m_catchEndAddr[m_currentCatch - 1] = catchEndAddr; + Debug.Assert(m_catchEndAddr[currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); + m_catchEndAddr[currentCatch - 1] = catchEndAddr; } } - m_catchEndAddr[m_currentCatch] = -1; + m_catchEndAddr[currentCatch ] = -1; m_currentCatch++; } @@ -1492,11 +1396,9 @@ internal void MarkFinallyAddr(int finallyAddr, int endCatchAddr) { throw new ArgumentException(SR.Argument_TooManyFinallyClause); } - else - { - m_currentState = State_Finally; - m_endFinally = finallyAddr; - } + + m_currentState = State_Finally; + m_endFinally = finallyAddr; MarkHelper(finallyAddr, endCatchAddr, null, Finally); } @@ -1588,14 +1490,13 @@ internal bool IsInner(__ExceptionInfo exc) if (exc.m_catchEndAddr[exclast] < m_catchEndAddr[last]) return true; - else if (exc.m_catchEndAddr[exclast] == m_catchEndAddr[last]) - { - Debug.Assert(exc.GetEndAddress() != GetEndAddress(), - "exc.GetEndAddress() != GetEndAddress()"); - if (exc.GetEndAddress() > GetEndAddress()) - return true; - } - return false; + + if (exc.m_catchEndAddr[exclast] != m_catchEndAddr[last]) + return false; + Debug.Assert(exc.GetEndAddress() != GetEndAddress(), + "exc.GetEndAddress() != GetEndAddress()"); + + return exc.GetEndAddress() > GetEndAddress(); } // 0 indicates in a try block @@ -1616,10 +1517,10 @@ internal int GetCurrentState() /// OpenScope or CloseScope. m_iOffset records the offset where the action /// takes place. /// - internal enum ScopeAction + internal enum ScopeAction : sbyte { - Open = 0x0, - Close = 0x1, + Open = -0x1, + Close = 0x1 } internal sealed class ScopeTree @@ -1638,21 +1539,16 @@ internal ScopeTree() /// internal int GetCurrentActiveScopeIndex() { - int cClose = 0; - int i = m_iCount - 1; - if (m_iCount == 0) { return -1; } - for (; cClose > 0 || m_ScopeActions[i] == ScopeAction.Close; i--) + + int i = m_iCount - 1; + + for (int cClose = 0; cClose > 0 || m_ScopeActions[i] == ScopeAction.Close; i--) { - if (m_ScopeActions[i] == ScopeAction.Open) - { - cClose--; - } - else - cClose++; + cClose += (sbyte)m_ScopeActions[i]; } return i; @@ -1699,12 +1595,8 @@ internal void AddScopeInfo(ScopeAction sa, int iOffset) m_iOffsets[m_iCount] = iOffset; m_localSymInfos[m_iCount] = null; checked { m_iCount++; } - if (sa == ScopeAction.Open) - { - m_iOpenScopeCount++; - } - else - m_iOpenScopeCount--; + + m_iOpenScopeCount += -(sbyte)sa; } /// @@ -1740,8 +1632,7 @@ internal void EnsureCapacity() internal void EmitScopeTree(ISymbolWriter symWriter) { - int i; - for (i = 0; i < m_iCount; i++) + for (int i = 0; i < m_iCount; i++) { if (m_ScopeActions[i] == ScopeAction.Open) { @@ -1787,10 +1678,8 @@ internal void AddLineNumberInfo( int iEndLine, int iEndColumn) { - int i; - // make sure that arrays are large enough to hold addition info - i = FindDocument(document); + int i = FindDocument(document); Debug.Assert(i < m_DocumentCount, "Bad document look up!"); m_Documents[i].AddLineNumberInfo(document, iOffset, iStartLine, iStartColumn, iEndLine, iEndColumn); @@ -1800,14 +1689,12 @@ internal void AddLineNumberInfo( // the REDocument array. private int FindDocument(ISymbolDocumentWriter document) { - int i; - // This is an optimization. The chance that the previous line is coming from the same // document is very high. if (m_iLastFound < m_DocumentCount && m_Documents[m_iLastFound].m_document == document) return m_iLastFound; - for (i = 0; i < m_DocumentCount; i++) + for (int i = 0; i < m_DocumentCount; i++) { if (m_Documents[i].m_document == document) { @@ -1932,28 +1819,22 @@ private void EnsureCapacity() internal void EmitLineNumberInfo(ISymbolWriter symWriter) { - int[] iOffsetsTemp; - int[] iLinesTemp; - int[] iColumnsTemp; - int[] iEndLinesTemp; - int[] iEndColumnsTemp; - if (m_iLineNumberCount == 0) return; // reduce the array size to be exact - iOffsetsTemp = new int[m_iLineNumberCount]; + int[] iOffsetsTemp = new int[m_iLineNumberCount]; Array.Copy(m_iOffsets, 0, iOffsetsTemp, 0, m_iLineNumberCount); - iLinesTemp = new int[m_iLineNumberCount]; + int[] iLinesTemp = new int[m_iLineNumberCount]; Array.Copy(m_iLines, 0, iLinesTemp, 0, m_iLineNumberCount); - iColumnsTemp = new int[m_iLineNumberCount]; + int[] iColumnsTemp = new int[m_iLineNumberCount]; Array.Copy(m_iColumns, 0, iColumnsTemp, 0, m_iLineNumberCount); - iEndLinesTemp = new int[m_iLineNumberCount]; + int[] iEndLinesTemp = new int[m_iLineNumberCount]; Array.Copy(m_iEndLines, 0, iEndLinesTemp, 0, m_iLineNumberCount); - iEndColumnsTemp = new int[m_iLineNumberCount]; + int[] iEndColumnsTemp = new int[m_iLineNumberCount]; Array.Copy(m_iEndColumns, 0, iEndColumnsTemp, 0, m_iLineNumberCount); symWriter.DefineSequencePoints(m_document, iOffsetsTemp, iLinesTemp, iColumnsTemp, iEndLinesTemp, iEndColumnsTemp); diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ISymWrapperCore.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ISymWrapperCore.cs index 030132918569..69b283f1d339 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/ISymWrapperCore.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ISymWrapperCore.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Security; using System.Runtime.InteropServices; @@ -57,7 +58,7 @@ internal SymDocumentWriter(PunkSafeHandle pDocumentWriterSafeHandle) m_pDocumentWriterSafeHandle = pDocumentWriterSafeHandle; // The handle is actually a pointer to a native ISymUnmanagedDocumentWriter. m_pDocWriter = (ISymUnmanagedDocumentWriter*)m_pDocumentWriterSafeHandle.DangerousGetHandle(); - m_vtable = (ISymUnmanagedDocumentWriterVTable)(Marshal.PtrToStructure(m_pDocWriter->m_unmanagedVTable, typeof(ISymUnmanagedDocumentWriterVTable))); + m_vtable = (ISymUnmanagedDocumentWriterVTable)(Marshal.PtrToStructure(m_pDocWriter->m_unmanagedVTable, typeof(ISymUnmanagedDocumentWriterVTable)))!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 } //------------------------------------------------------------------------------ @@ -90,7 +91,7 @@ void ISymbolDocumentWriter.SetCheckSum(Guid algorithmId, byte[] checkSum) int hr = m_vtable.SetCheckSum(m_pDocWriter, algorithmId, (uint)checkSum.Length, checkSum); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -165,7 +166,7 @@ private SymWriter() //------------------------------------------------------------------------------ // DefineDocument() wrapper //------------------------------------------------------------------------------ - ISymbolDocumentWriter ISymbolWriter.DefineDocument(string url, + ISymbolDocumentWriter? ISymbolWriter.DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) @@ -175,7 +176,7 @@ ISymbolDocumentWriter ISymbolWriter.DefineDocument(string url, int hr = m_vtable.DefineDocument(m_pWriter, url, ref language, ref languageVendor, ref documentType, out psymUnmanagedDocumentWriter); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } if (psymUnmanagedDocumentWriter.IsInvalid) { @@ -192,7 +193,7 @@ void ISymbolWriter.OpenMethod(SymbolToken method) int hr = m_vtable.OpenMethod(m_pWriter, method.GetToken()); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -204,7 +205,7 @@ void ISymbolWriter.CloseMethod() int hr = m_vtable.CloseMethod(m_pWriter); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -259,10 +260,10 @@ void ISymbolWriter.DefineSequencePoints(ISymbolDocumentWriter document, // Regardless, this cast is important for security - we cannot allow our caller to provide // arbitrary instances of this interface. SymDocumentWriter docwriter = (SymDocumentWriter)document; - int hr = m_vtable.DefineSequencePoints(m_pWriter, docwriter.GetUnmanaged(), spCount, offsets, lines, columns, endLines, endColumns); + int hr = m_vtable.DefineSequencePoints(m_pWriter, docwriter.GetUnmanaged(), spCount!, offsets!, lines!, columns!, endLines!, endColumns!); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -275,7 +276,7 @@ int ISymbolWriter.OpenScope(int startOffset) int hr = m_vtable.OpenScope(m_pWriter, startOffset, out ret); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } return ret; } @@ -288,7 +289,7 @@ void ISymbolWriter.CloseScope(int endOffset) int hr = m_vtable.CloseScope(m_pWriter, endOffset); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -318,7 +319,7 @@ void ISymbolWriter.DefineLocalVariable(string name, endOffset); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -330,7 +331,7 @@ void ISymbolWriter.SetSymAttribute(SymbolToken parent, string name, byte[] data) int hr = m_vtable.SetSymAttribute(m_pWriter, parent.GetToken(), name, data.Length, data); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -342,7 +343,7 @@ void ISymbolWriter.UsingNamespace(string name) int hr = m_vtable.UsingNamespace(m_pWriter, name); if (hr < 0) { - throw Marshal.GetExceptionForHR(hr); + throw Marshal.GetExceptionForHR(hr)!; } } @@ -358,7 +359,7 @@ void ISymbolWriter.UsingNamespace(string name) internal void InternalSetUnderlyingWriter(IntPtr ppUnderlyingWriter) { m_pWriter = *((ISymUnmanagedWriter**)ppUnderlyingWriter); - m_vtable = (ISymUnmanagedWriterVTable)(Marshal.PtrToStructure(m_pWriter->m_unmanagedVTable, typeof(ISymUnmanagedWriterVTable))); + m_vtable = (ISymUnmanagedWriterVTable)(Marshal.PtrToStructure(m_pWriter->m_unmanagedVTable, typeof(ISymUnmanagedWriterVTable)))!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976 } //------------------------------------------------------------------------------ diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs index b9eecdb25cfc..c7333ebf88c4 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs @@ -6,6 +6,7 @@ using System.Text; using System; +using System.Buffers.Binary; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; @@ -483,8 +484,6 @@ private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst private void AddData(int data) { - // A managed representation of CorSigCompressData; - if (m_currSig + 4 > m_signature.Length) { m_signature = ExpandArray(m_signature); @@ -492,19 +491,17 @@ private void AddData(int data) if (data <= 0x7F) { - m_signature[m_currSig++] = (byte)(data & 0xFF); + m_signature[m_currSig++] = (byte)data; } - else if (data <= 0x3FFF) + else if (data <= 0x3F_FF) { - m_signature[m_currSig++] = (byte)((data >> 8) | 0x80); - m_signature[m_currSig++] = (byte)(data & 0xFF); + BinaryPrimitives.WriteInt16BigEndian(m_signature.AsSpan(m_currSig), (short)(data | 0x80_00)); + m_currSig += 2; } - else if (data <= 0x1FFFFFFF) + else if (data <= 0x1F_FF_FF_FF) { - m_signature[m_currSig++] = (byte)((data >> 24) | 0xC0); - m_signature[m_currSig++] = (byte)((data >> 16) & 0xFF); - m_signature[m_currSig++] = (byte)((data >> 8) & 0xFF); - m_signature[m_currSig++] = (byte)((data) & 0xFF); + BinaryPrimitives.WriteInt32BigEndian(m_signature.AsSpan(m_currSig), (int)(data | 0xC0_00_00_00)); + m_currSig += 4; } else { diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs index e611c604d77f..9d8cc65076a8 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs @@ -1979,8 +1979,6 @@ private TypeInfo CreateTypeNoLock() if (IsCreated()) return m_bakedRuntimeType; - ThrowIfCreated(); - if (m_typeInterfaces == null) m_typeInterfaces = new List(); diff --git a/src/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs b/src/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs index eb28f4e20912..2cd9c9687ffe 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Reflection { // diff --git a/src/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index 1119f07fa4ef..7d7d16b05229 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -41,19 +41,12 @@ internal sealed class LoaderAllocatorScout if (m_nativeLoaderAllocator == IntPtr.Zero) return; - // Assemblies and LoaderAllocators will be cleaned up during AppDomain shutdown in - // unmanaged code - // So it is ok to skip reregistration and cleanup for finalization during shutdown. - // We also avoid early finalization of LoaderAllocatorScout due to AD unload when the object was inside DelayedFinalizationList. - if (!Environment.HasShutdownStarted) + // Destroy returns false if the managed LoaderAllocator is still alive. + if (!Destroy(m_nativeLoaderAllocator)) { - // Destroy returns false if the managed LoaderAllocator is still alive. - if (!Destroy(m_nativeLoaderAllocator)) - { - // Somebody might have been holding a reference on us via weak handle. - // We will keep trying. It will be hopefully released eventually. - GC.ReRegisterForFinalize(this); - } + // Somebody might have been holding a reference on us via weak handle. + // We will keep trying. It will be hopefully released eventually. + GC.ReRegisterForFinalize(this); } } } diff --git a/src/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs b/src/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs index 2b6e5b2ffefc..5841e957b5a2 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Security; namespace System.Reflection.Metadata { diff --git a/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index 394a8f3c2235..16dc8ec474be 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -2,14 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.Diagnostics; using CultureInfo = System.Globalization.CultureInfo; -using System.Security; using System.IO; -using StringBuilder = System.Text.StringBuilder; using System.Configuration.Assemblies; using StackCrawlMark = System.Threading.StackCrawlMark; +using System.Runtime.Loader; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -23,8 +23,8 @@ internal class RuntimeAssembly : Assembly #region private data members private event ModuleResolveEventHandler _ModuleResolve; - private string m_fullname; - private object m_syncRoot; // Used to keep collectible types alive and as the syncroot for reflection.emit + private string? m_fullname; + private object? m_syncRoot; // Used to keep collectible types alive and as the syncroot for reflection.emit private IntPtr m_assembly; // slack for ptr datum on unmanaged side #endregion @@ -45,9 +45,9 @@ internal object SyncRoot { if (m_syncRoot == null) { - Interlocked.CompareExchange(ref m_syncRoot, new object(), null); + Interlocked.CompareExchange(ref m_syncRoot, new object(), null); } - return m_syncRoot; + return m_syncRoot!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } @@ -70,14 +70,14 @@ private static extern void GetCodeBase(RuntimeAssembly assembly, bool copiedName, StringHandleOnStack retString); - internal string GetCodeBase(bool copiedName) + internal string? GetCodeBase(bool copiedName) { - string codeBase = null; + string? codeBase = null; GetCodeBase(GetNativeHandle(), copiedName, JitHelpers.GetStringHandleOnStack(ref codeBase)); return codeBase; } - public override string CodeBase => GetCodeBase(false); + public override string? CodeBase => GetCodeBase(false); internal RuntimeAssembly GetNativeHandle() => this; @@ -86,11 +86,9 @@ internal string GetCodeBase(bool copiedName) // is returned. public override AssemblyName GetName(bool copiedName) { - AssemblyName an = new AssemblyName(); - - string codeBase = GetCodeBase(copiedName); + string? codeBase = GetCodeBase(copiedName); - an.Init(GetSimpleName(), + var an = new AssemblyName(GetSimpleName(), GetPublicKey(), null, // public key token GetVersion(), @@ -101,12 +99,12 @@ public override AssemblyName GetName(bool copiedName) GetFlags() | AssemblyNameFlags.PublicKey, null); // strong name key pair - Module manifestModule = ManifestModule; + Module? manifestModule = ManifestModule; if (manifestModule != null) { if (manifestModule.MDStreamVersion > 0x10000) { - ManifestModule.GetPEKind(out PortableExecutableKinds pek, out ImageFileMachine ifm); + manifestModule.GetPEKind(out PortableExecutableKinds pek, out ImageFileMachine ifm); an.SetProcArchIndex(pek, ifm); } } @@ -116,16 +114,16 @@ public override AssemblyName GetName(bool copiedName) [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetFullName(RuntimeAssembly assembly, StringHandleOnStack retString); - public override string FullName + public override string? FullName { get { // If called by Object.ToString(), return val may be NULL. if (m_fullname == null) { - string s = null; + string? s = null; GetFullName(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref s)); - Interlocked.CompareExchange(ref m_fullname, s, null); + Interlocked.CompareExchange(ref m_fullname, s, null); } return m_fullname; @@ -135,11 +133,11 @@ public override string FullName [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetEntryPoint(RuntimeAssembly assembly, ObjectHandleOnStack retMethod); - public override MethodInfo EntryPoint + public override MethodInfo? EntryPoint { get { - IRuntimeMethodInfo methodHandle = null; + IRuntimeMethodInfo? methodHandle = null; GetEntryPoint(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref methodHandle)); if (methodHandle == null) @@ -151,21 +149,30 @@ public override MethodInfo EntryPoint [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetType(RuntimeAssembly assembly, - string name, - bool throwOnError, - bool ignoreCase, - ObjectHandleOnStack type, - ObjectHandleOnStack keepAlive); + string name, + bool throwOnError, + bool ignoreCase, + ObjectHandleOnStack type, + ObjectHandleOnStack keepAlive, + ObjectHandleOnStack assemblyLoadContext); - public override Type GetType(string name, bool throwOnError, bool ignoreCase) + public override Type? GetType(string name, bool throwOnError, bool ignoreCase) { // throw on null strings regardless of the value of "throwOnError" if (name == null) throw new ArgumentNullException(nameof(name)); - RuntimeType type = null; - object keepAlive = null; - GetType(GetNativeHandle(), name, throwOnError, ignoreCase, JitHelpers.GetObjectHandleOnStack(ref type), JitHelpers.GetObjectHandleOnStack(ref keepAlive)); + RuntimeType? type = null; + object? keepAlive = null; + AssemblyLoadContext? assemblyLoadContextStack = AssemblyLoadContext.CurrentContextualReflectionContext; + + GetType(GetNativeHandle(), + name, + throwOnError, + ignoreCase, + JitHelpers.GetObjectHandleOnStack(ref type), + JitHelpers.GetObjectHandleOnStack(ref keepAlive), + JitHelpers.GetObjectHandleOnStack(ref assemblyLoadContextStack)); GC.KeepAlive(keepAlive); return type; @@ -176,9 +183,9 @@ public override Type GetType(string name, bool throwOnError, bool ignoreCase) public override Type[] GetExportedTypes() { - Type[] types = null; + Type[]? types = null; GetExportedTypes(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types)); - return types; + return types!; } public override IEnumerable DefinedTypes @@ -215,12 +222,12 @@ public override IEnumerable DefinedTypes out uint length); // Load a resource based on the NameSpace of the type. - public override Stream GetManifestResourceStream(Type type, string name) + public override Stream? GetManifestResourceStream(Type type, string name) { if (type == null && name == null) throw new ArgumentNullException(nameof(type)); - string nameSpace = type?.Namespace; + string? nameSpace = type?.Namespace; char c = Type.Delimiter; string resourceName = nameSpace != null && name != null ? @@ -230,7 +237,7 @@ public override Stream GetManifestResourceStream(Type type, string name) return GetManifestResourceStream(resourceName); } - public unsafe override Stream GetManifestResourceStream(string name) + public unsafe override Stream? GetManifestResourceStream(string name) { uint length = 0; byte* pbInMemoryResource = GetResource(GetNativeHandle(), name, out length); @@ -249,7 +256,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont throw new PlatformNotSupportedException(); } - public override Module ManifestModule + public override Module? ManifestModule { get { @@ -269,7 +276,7 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit) if (attributeType == null) throw new ArgumentNullException(nameof(attributeType)); - RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; + RuntimeType? attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); @@ -282,7 +289,7 @@ public override bool IsDefined(Type attributeType, bool inherit) if (attributeType == null) throw new ArgumentNullException(nameof(attributeType)); - RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; + RuntimeType? attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType; if (attributeRuntimeType == null) throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); @@ -295,9 +302,9 @@ public override IList GetCustomAttributesData() return CustomAttributeData.GetCustomAttributesInternal(this); } - internal static RuntimeAssembly InternalLoad(string assemblyString, ref StackCrawlMark stackMark) + internal static RuntimeAssembly InternalLoad(string assemblyString, ref StackCrawlMark stackMark, AssemblyLoadContext? assemblyLoadContext = null) { - RuntimeAssembly assembly; + RuntimeAssembly? assembly; AssemblyName an = CreateAssemblyName(assemblyString, out assembly); if (assembly != null) @@ -306,13 +313,13 @@ internal static RuntimeAssembly InternalLoad(string assemblyString, ref StackCra return assembly; } - return InternalLoadAssemblyName(an, ref stackMark); + return InternalLoadAssemblyName(an, ref stackMark, assemblyLoadContext); } // Creates AssemblyName. Fills assembly if AssemblyResolve event has been raised. internal static AssemblyName CreateAssemblyName( string assemblyString, - out RuntimeAssembly assemblyFromResolveEvent) + out RuntimeAssembly? assemblyFromResolveEvent) { if (assemblyString == null) throw new ArgumentNullException(nameof(assemblyString)); @@ -329,7 +336,7 @@ internal static AssemblyName CreateAssemblyName( return an; } - internal static RuntimeAssembly InternalLoadAssemblyName(AssemblyName assemblyRef, ref StackCrawlMark stackMark, IntPtr ptrLoadContextBinder = default) + internal static RuntimeAssembly InternalLoadAssemblyName(AssemblyName assemblyRef, ref StackCrawlMark stackMark, AssemblyLoadContext? assemblyLoadContext = null) { #if FEATURE_APPX if (ApplicationModel.IsUap) @@ -348,18 +355,18 @@ internal static RuntimeAssembly InternalLoadAssemblyName(AssemblyName assemblyRe assemblyRef.ProcessorArchitecture = ProcessorArchitecture.None; } - string codeBase = VerifyCodeBase(assemblyRef.CodeBase); + string? codeBase = VerifyCodeBase(assemblyRef.CodeBase); - return nLoad(assemblyRef, codeBase, null, ref stackMark, true, ptrLoadContextBinder); + return nLoad(assemblyRef, codeBase, null, ref stackMark, true, assemblyLoadContext); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern RuntimeAssembly nLoad(AssemblyName fileName, - string codeBase, - RuntimeAssembly assemblyContext, + string? codeBase, + RuntimeAssembly? assemblyContext, ref StackCrawlMark stackMark, bool throwOnFileNotFound, - IntPtr ptrLoadContextBinder); + AssemblyLoadContext? assemblyLoadContext = null); public override bool ReflectionOnly { @@ -374,18 +381,18 @@ public override bool ReflectionOnly [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetModule(RuntimeAssembly assembly, string name, ObjectHandleOnStack retModule); - public override Module GetModule(string name) + public override Module? GetModule(string name) { - Module retModule = null; + Module? retModule = null; GetModule(GetNativeHandle(), name, JitHelpers.GetObjectHandleOnStack(ref retModule)); return retModule; } // Returns the file in the File table of the manifest that matches the // given name. (Name should not include path.) - public override FileStream GetFile(string name) + public override FileStream? GetFile(string name) { - RuntimeModule m = (RuntimeModule)GetModule(name); + RuntimeModule? m = (RuntimeModule?)GetModule(name); if (m == null) return null; @@ -434,10 +441,10 @@ private static extern int GetManifestResourceInfo(RuntimeAssembly assembly, ObjectHandleOnStack assemblyRef, StringHandleOnStack retFileName); - public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) + public override ManifestResourceInfo? GetManifestResourceInfo(string resourceName) { - RuntimeAssembly retAssembly = null; - string fileName = null; + RuntimeAssembly? retAssembly = null; + string? fileName = null; int location = GetManifestResourceInfo(GetNativeHandle(), resourceName, JitHelpers.GetObjectHandleOnStack(ref retAssembly), JitHelpers.GetStringHandleOnStack(ref fileName)); @@ -456,11 +463,11 @@ public override string Location { get { - string location = null; + string? location = null; GetLocation(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref location)); - return location; + return location!; } } @@ -471,9 +478,9 @@ public override string ImageRuntimeVersion { get { - string s = null; + string? s = null; GetImageRuntimeVersion(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref s)); - return s; + return s!; } } @@ -493,7 +500,7 @@ public override long HostContext } } - private static string VerifyCodeBase(string codebase) + private static string? VerifyCodeBase(string? codebase) { if (codebase == null) return null; @@ -540,7 +547,7 @@ internal Version GetVersion() internal CultureInfo GetLocale() { - string locale = null; + string? locale = null; GetLocale(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref locale)); @@ -564,9 +571,9 @@ public override bool IsDynamic [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetSimpleName(RuntimeAssembly assembly, StringHandleOnStack retSimpleName); - internal string GetSimpleName() + internal string? GetSimpleName() { - string name = null; + string? name = null; GetSimpleName(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref name)); return name; } @@ -590,15 +597,15 @@ private AssemblyNameFlags GetFlags() [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetPublicKey(RuntimeAssembly assembly, ObjectHandleOnStack retPublicKey); - internal byte[] GetPublicKey() + internal byte[]? GetPublicKey() { - byte[] publicKey = null; + byte[]? publicKey = null; GetPublicKey(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref publicKey)); return publicKey; } // This method is called by the VM. - private RuntimeModule OnModuleResolveEvent(string moduleName) + private RuntimeModule? OnModuleResolveEvent(string moduleName) { ModuleResolveEventHandler moduleResolve = _ModuleResolve; if (moduleResolve == null) @@ -620,17 +627,17 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture) } // Useful for binding to a very specific version of a satellite assembly - public override Assembly GetSatelliteAssembly(CultureInfo culture, Version version) + public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { if (culture == null) throw new ArgumentNullException(nameof(culture)); - return InternalGetSatelliteAssembly(culture, version, true); + return InternalGetSatelliteAssembly(culture, version, throwOnFileNotFound: true)!; } [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod - internal Assembly InternalGetSatelliteAssembly(CultureInfo culture, - Version version, + internal Assembly? InternalGetSatelliteAssembly(CultureInfo culture, + Version? version, bool throwOnFileNotFound) { AssemblyName an = new AssemblyName(); @@ -649,7 +656,7 @@ internal Assembly InternalGetSatelliteAssembly(CultureInfo culture, // This stack crawl mark is never used because the requesting assembly is explicitly specified, // so the value could be anything. StackCrawlMark unused = default; - RuntimeAssembly retAssembly = nLoad(an, null, this, ref unused, throwOnFileNotFound, IntPtr.Zero); + RuntimeAssembly? retAssembly = nLoad(an, null, this, ref unused, throwOnFileNotFound); if (retAssembly == this) { @@ -673,9 +680,9 @@ private static extern void GetModules(RuntimeAssembly assembly, private RuntimeModule[] GetModulesInternal(bool loadIfNotFound, bool getResourceModules) { - RuntimeModule[] modules = null; + RuntimeModule[]? modules = null; GetModules(GetNativeHandle(), loadIfNotFound, getResourceModules, JitHelpers.GetObjectHandleOnStack(ref modules)); - return modules; + return modules!; } public override Module[] GetModules(bool getResourceModules) @@ -704,8 +711,8 @@ public sealed override Type[] GetForwardedTypes() for (int i = 0; i < enumResult.Length; i++) { MetadataToken mdtExternalType = enumResult[i]; - Type type = null; - Exception exception = null; + Type? type = null; + Exception? exception = null; ObjectHandleOnStack pType = JitHelpers.GetObjectHandleOnStack(ref type); try { @@ -719,7 +726,7 @@ public sealed override Type[] GetForwardedTypes() exception = e; } - Debug.Assert((type != null) != (exception != null)); // Exactly one of these must be non-null. + Debug.Assert((type != null) != (exception != null)); // Exactly one of these must be non-null. // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 if (type != null) { @@ -728,7 +735,7 @@ public sealed override Type[] GetForwardedTypes() } else { - exceptions.Add(exception); + exceptions.Add(exception!); } } diff --git a/src/System.Private.CoreLib/src/System/Reflection/RuntimeExceptionHandlingClause.cs b/src/System.Private.CoreLib/src/System/Reflection/RuntimeExceptionHandlingClause.cs index eff671ecdbe9..4d88f48249f6 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/RuntimeExceptionHandlingClause.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/RuntimeExceptionHandlingClause.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; namespace System.Reflection @@ -11,7 +12,7 @@ internal sealed class RuntimeExceptionHandlingClause : ExceptionHandlingClause // This class can only be created from inside the EE. private RuntimeExceptionHandlingClause() { } - private RuntimeMethodBody _methodBody; + private RuntimeMethodBody _methodBody = null!; private ExceptionHandlingClauseOptions _flags; private int _tryOffset; private int _tryLength; @@ -37,14 +38,14 @@ public override int FilterOffset } } - public override Type CatchType + public override Type? CatchType { get { if (_flags != ExceptionHandlingClauseOptions.Clause) throw new InvalidOperationException(SR.Arg_EHClauseNotClause); - Type type = null; + Type? type = null; if (!MetadataToken.IsNullToken(_catchMetadataToken)) { diff --git a/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs index 879186575fb8..43f9efdfb34f 100644 --- a/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; using System.Reflection; @@ -10,9 +11,9 @@ namespace System.Resources internal partial class ManifestBasedResourceGroveler { // Internal version of GetSatelliteAssembly that avoids throwing FileNotFoundException - private static Assembly InternalGetSatelliteAssembly(Assembly mainAssembly, + private static Assembly? InternalGetSatelliteAssembly(Assembly mainAssembly, CultureInfo culture, - Version version) + Version? version) { return ((RuntimeAssembly)mainAssembly).InternalGetSatelliteAssembly(culture, version, throwOnFileNotFound: false); } diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs index 299fb6046395..0ef2227d2627 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CrossLoaderAllocatorHashHelpers.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Runtime.InteropServices; namespace System.Runtime.CompilerServices @@ -31,7 +31,7 @@ internal class LAHashDependentHashTracker [StructLayout(LayoutKind.Sequential)] internal class LAHashKeyToTrackers { - object _trackerOrTrackerSet; - object _laLocalKeyValueStore; + object _trackerOrTrackerSet = null!; + object _laLocalKeyValueStore = null!; } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/DependentHandle.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/DependentHandle.cs index 35fa0780be07..aee0bf16daf2 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/DependentHandle.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/DependentHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { //========================================================================================= @@ -32,7 +33,7 @@ internal struct DependentHandle { private IntPtr _handle; - public DependentHandle(object primary, object secondary) => + public DependentHandle(object primary, object? secondary) => // no need to check for null result: nInitialize expected to throw OOM. _handle = nInitialize(primary, secondary); @@ -41,15 +42,15 @@ public DependentHandle(object primary, object secondary) => // Getting the secondary object is more expensive than getting the first so // we provide a separate primary-only accessor for those times we only want the // primary. - public object GetPrimary() => nGetPrimary(_handle); + public object? GetPrimary() => nGetPrimary(_handle); - public object GetPrimaryAndSecondary(out object secondary) => + public object? GetPrimaryAndSecondary(out object? secondary) => nGetPrimaryAndSecondary(_handle, out secondary); - public void SetPrimary(object primary) => + public void SetPrimary(object? primary) => nSetPrimary(_handle, primary); - public void SetSecondary(object secondary) => + public void SetSecondary(object? secondary) => nSetSecondary(_handle, secondary); // Forces dependentHandle back to non-allocated state (if not already there) @@ -65,19 +66,19 @@ public void Free() } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr nInitialize(object primary, object secondary); + private static extern IntPtr nInitialize(object primary, object? secondary); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object nGetPrimary(IntPtr dependentHandle); + private static extern object? nGetPrimary(IntPtr dependentHandle); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object nGetPrimaryAndSecondary(IntPtr dependentHandle, out object secondary); + private static extern object? nGetPrimaryAndSecondary(IntPtr dependentHandle, out object? secondary); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void nSetPrimary(IntPtr dependentHandle, object primary); + private static extern void nSetPrimary(IntPtr dependentHandle, object? primary); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void nSetSecondary(IntPtr dependentHandle, object secondary); + private static extern void nSetSecondary(IntPtr dependentHandle, object? secondary); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void nFree(IntPtr dependentHandle); diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs index 3699585226bd..96688bbc6d79 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/GCHeapHash.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Runtime.InteropServices; @@ -14,8 +15,8 @@ namespace System.Runtime.CompilerServices [StructLayout(LayoutKind.Sequential)] internal class GCHeapHash { - Array _data; + Array _data = null!; int _count; int _deletedCount; } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs index 9343915f3ec0..5d474e5816ed 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastableHelpers.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Runtime.CompilerServices { @@ -14,7 +13,7 @@ namespace System.Runtime.CompilerServices /// internal class ICastableHelpers { - internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, out Exception castError) + internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, out Exception? castError) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { return castable.IsInstanceOfInterface(new RuntimeTypeHandle(type), out castError); } @@ -24,4 +23,4 @@ internal static RuntimeType GetImplType(ICastable castable, RuntimeType interfac return castable.GetImplType(new RuntimeTypeHandle(interfaceType)).GetRuntimeType(); } } -} \ No newline at end of file +} diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.CoreCLR.cs index 69a7465dcf20..32921deed570 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Runtime.CompilerServices { public static partial class RuntimeFeature diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index 74bb384486f8..7c6f3c5d8f46 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; @@ -76,7 +77,7 @@ public static void PrepareMethod(RuntimeMethodHandle method) } } - public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation) + public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[]? instantiation) { unsafe { @@ -97,7 +98,7 @@ public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] public static extern int GetHashCode(object o); [MethodImplAttribute(MethodImplOptions.InternalCall)] - public new static extern bool Equals(object o1, object o2); + public new static extern bool Equals(object? o1, object? o2); public static int OffsetToStringData { @@ -136,9 +137,9 @@ public static int OffsetToStringData public static extern bool TryEnsureSufficientExecutionStack(); [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object userData); + public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object? userData); - internal static void ExecuteBackoutCodeHelper(object backoutCode, object userData, bool exceptionThrown) + internal static void ExecuteBackoutCodeHelper(object backoutCode, object? userData, bool exceptionThrown) { ((CleanupCode)backoutCode)(userData, exceptionThrown); } diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs index 3e386fa8b7e6..25745e178c30 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Runtime.CompilerServices { // We might want to make this inherited someday. But I suspect it shouldn't diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs index 10808216b0df..1eae91cd56f3 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/jithelpers.cs @@ -7,6 +7,7 @@ // Low-level Jit Helpers //////////////////////////////////////////////////////////////////////////////// +#nullable enable using System.Threading; using System.Diagnostics; using Internal.Runtime.CompilerServices; @@ -66,14 +67,14 @@ internal static unsafe class JitHelpers // Wraps object variable into a handle. Used to return managed strings from QCalls. // s has to be a local variable on the stack. - internal static StringHandleOnStack GetStringHandleOnStack(ref string s) + internal static StringHandleOnStack GetStringHandleOnStack(ref string? s) { return new StringHandleOnStack((IntPtr)Unsafe.AsPointer(ref s)); } // Wraps object variable into a handle. Used to pass managed object references in and out of QCalls. // o has to be a local variable on the stack. - internal static ObjectHandleOnStack GetObjectHandleOnStack(ref T o) where T : class + internal static ObjectHandleOnStack GetObjectHandleOnStack(ref T o) where T : class? { return new ObjectHandleOnStack((IntPtr)Unsafe.AsPointer(ref o)); } diff --git a/src/System.Private.CoreLib/src/System/Runtime/GCSettings.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/GCSettings.CoreCLR.cs index 1fbc1dc4f1de..e19a3b0f1b82 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/GCSettings.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/GCSettings.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; namespace System.Runtime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Attributes.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Attributes.cs deleted file mode 100644 index ed7a28d6f6f7..000000000000 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Attributes.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.InteropServices -{ - [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] - public sealed class TypeIdentifierAttribute : Attribute - { - public TypeIdentifierAttribute() { } - public TypeIdentifierAttribute(string scope, string identifier) { Scope_ = scope; Identifier_ = identifier; } - - public string Scope { get { return Scope_; } } - public string Identifier { get { return Identifier_; } } - - internal string Scope_; - internal string Identifier_; - } - - // To be used on methods that sink reverse P/Invoke calls. - // This attribute is a CoreCLR-only security measure, currently ignored by the desktop CLR. - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] - public sealed class AllowReversePInvokeCallsAttribute : Attribute - { - public AllowReversePInvokeCallsAttribute() - { - } - } - - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] - public sealed class DispIdAttribute : Attribute - { - internal int _val; - - public DispIdAttribute(int dispId) - { - _val = dispId; - } - - public int Value => _val; - } - - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class ComDefaultInterfaceAttribute : Attribute - { - internal Type _val; - - public ComDefaultInterfaceAttribute(Type defaultInterface) - { - _val = defaultInterface; - } - - public Type Value => _val; - } - - public enum ClassInterfaceType - { - None = 0, - AutoDispatch = 1, - AutoDual = 2 - } - - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, Inherited = false)] - public sealed class ClassInterfaceAttribute : Attribute - { - internal ClassInterfaceType _val; - - public ClassInterfaceAttribute(ClassInterfaceType classInterfaceType) - { - _val = classInterfaceType; - } - - public ClassInterfaceAttribute(short classInterfaceType) - { - _val = (ClassInterfaceType)classInterfaceType; - } - - public ClassInterfaceType Value => _val; - } - - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class ProgIdAttribute : Attribute - { - internal string _val; - - public ProgIdAttribute(string progId) - { - _val = progId; - } - - public string Value => _val; - } - - [AttributeUsage(AttributeTargets.Class, Inherited = true)] - public sealed class ComSourceInterfacesAttribute : Attribute - { - internal string _val; - - public ComSourceInterfacesAttribute(string sourceInterfaces) - { - _val = sourceInterfaces; - } - - public ComSourceInterfacesAttribute(Type sourceInterface) - { - _val = sourceInterface.FullName; - } - - public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2) - { - _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName; - } - - public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2, Type sourceInterface3) - { - _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName + "\0" + sourceInterface3.FullName; - } - - public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2, Type sourceInterface3, Type sourceInterface4) - { - _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName + "\0" + sourceInterface3.FullName + "\0" + sourceInterface4.FullName; - } - - public string Value => _val; - } - - [AttributeUsage(AttributeTargets.Interface, Inherited = false)] - public sealed class CoClassAttribute : Attribute - { - internal Type _CoClass; - - public CoClassAttribute(Type coClass) - { - _CoClass = coClass; - } - - public Type CoClass => _CoClass; - } -} diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsHelper.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsHelper.cs index a5d431dae20c..a462e93b2d1c 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsHelper.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsHelper.cs @@ -82,8 +82,7 @@ // means that the problem is already quite complex and we should not be dealing with it - see // ComEventsMethod.Invoke -using System; - +#nullable enable namespace System.Runtime.InteropServices { /// @@ -105,13 +104,13 @@ public static void Combine(object rcw, Guid iid, int dispid, Delegate d) { ComEventsInfo eventsInfo = ComEventsInfo.FromObject(rcw); - ComEventsSink sink = eventsInfo.FindSink(ref iid); + ComEventsSink? sink = eventsInfo.FindSink(ref iid); if (sink == null) { sink = eventsInfo.AddSink(ref iid); } - ComEventsMethod method = sink.FindMethod(dispid); + ComEventsMethod? method = sink.FindMethod(dispid); if (method == null) { method = sink.AddMethod(dispid); @@ -128,23 +127,23 @@ public static void Combine(object rcw, Guid iid, int dispid, Delegate d) /// identifier of the source interface used by COM object to fire events /// dispatch identifier of the method on the source interface /// delegate to remove from the invocation list - public static Delegate Remove(object rcw, Guid iid, int dispid, Delegate d) + public static Delegate? Remove(object rcw, Guid iid, int dispid, Delegate d) { lock (rcw) { - ComEventsInfo eventsInfo = ComEventsInfo.Find(rcw); + ComEventsInfo? eventsInfo = ComEventsInfo.Find(rcw); if (eventsInfo == null) { return null; } - ComEventsSink sink = eventsInfo.FindSink(ref iid); + ComEventsSink? sink = eventsInfo.FindSink(ref iid); if (sink == null) { return null; } - ComEventsMethod method = sink.FindMethod(dispid); + ComEventsMethod? method = sink.FindMethod(dispid); if (method == null) { return null; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsInfo.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsInfo.cs index 8b47683e849c..623d2412017b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsInfo.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsInfo.cs @@ -2,14 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using ComTypes = System.Runtime.InteropServices.ComTypes; - +#nullable enable namespace System.Runtime.InteropServices { internal class ComEventsInfo { - private ComEventsSink _sinks; + private ComEventsSink? _sinks; private object _rcw; private ComEventsInfo(object rcw) @@ -23,15 +21,15 @@ private ComEventsInfo(object rcw) _sinks = ComEventsSink.RemoveAll(_sinks); } - public static ComEventsInfo Find(object rcw) + public static ComEventsInfo? Find(object rcw) { - return (ComEventsInfo)Marshal.GetComObjectData(rcw, typeof(ComEventsInfo)); + return (ComEventsInfo?)Marshal.GetComObjectData(rcw, typeof(ComEventsInfo)); } // it is caller's responsibility to call this method under lock(rcw) public static ComEventsInfo FromObject(object rcw) { - ComEventsInfo eventsInfo = Find(rcw); + ComEventsInfo? eventsInfo = Find(rcw); if (eventsInfo == null) { eventsInfo = new ComEventsInfo(rcw); @@ -40,7 +38,7 @@ public static ComEventsInfo FromObject(object rcw) return eventsInfo; } - public ComEventsSink FindSink(ref Guid iid) + public ComEventsSink? FindSink(ref Guid iid) { return ComEventsSink.Find(_sinks, ref iid); } @@ -57,8 +55,8 @@ public ComEventsSink AddSink(ref Guid iid) // it is caller's responsibility to call this method under lock(rcw) internal ComEventsSink RemoveSink(ComEventsSink sink) { - _sinks = ComEventsSink.Remove(_sinks, sink); - return _sinks; + _sinks = ComEventsSink.Remove(_sinks!, sink); + return _sinks!; } } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsMethod.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsMethod.cs index ce36100d15f7..fcaadd762b95 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsMethod.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsMethod.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Text; -using System.Runtime.InteropServices; using System.Reflection; namespace System.Runtime.InteropServices @@ -30,7 +28,7 @@ public class DelegateWrapper { private bool _once = false; private int _expectedParamsCount; - private Type[] _cachedTargetTypes; + private Type?[]? _cachedTargetTypes; public DelegateWrapper(Delegate d) { @@ -39,7 +37,7 @@ public DelegateWrapper(Delegate d) public Delegate Delegate { get; set; } - public object Invoke(object[] args) + public object? Invoke(object[] args) { if (Delegate == null) { @@ -58,7 +56,7 @@ public object Invoke(object[] args) { if (_cachedTargetTypes[i] != null) { - args[i] = Enum.ToObject(_cachedTargetTypes[i], args[i]); + args[i] = Enum.ToObject(_cachedTargetTypes[i]!, args[i]); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 } } } @@ -73,10 +71,10 @@ private void PreProcessSignature() bool needToHandleCoercion = false; - var targetTypes = new List(); + var targetTypes = new List(); foreach (ParameterInfo pi in parameters) { - Type targetType = null; + Type? targetType = null; // recognize only 'ref Enum' signatures and cache // both enum type and the underlying type. @@ -106,14 +104,14 @@ private void PreProcessSignature() private List _delegateWrappers = new List(); private readonly int _dispid; - private ComEventsMethod _next; + private ComEventsMethod? _next; public ComEventsMethod(int dispid) { _dispid = dispid; } - public static ComEventsMethod Find(ComEventsMethod methods, int dispid) + public static ComEventsMethod? Find(ComEventsMethod? methods, int dispid) { while (methods != null && methods._dispid != dispid) { @@ -123,24 +121,25 @@ public static ComEventsMethod Find(ComEventsMethod methods, int dispid) return methods; } - public static ComEventsMethod Add(ComEventsMethod methods, ComEventsMethod method) + public static ComEventsMethod Add(ComEventsMethod? methods, ComEventsMethod method) { method._next = methods; return method; } - public static ComEventsMethod Remove(ComEventsMethod methods, ComEventsMethod method) + public static ComEventsMethod? Remove(ComEventsMethod methods, ComEventsMethod method) { Debug.Assert(methods != null, "removing method from empty methods collection"); Debug.Assert(method != null, "specify method is null"); if (methods == method) { - methods = methods._next; + return methods._next; } else { - ComEventsMethod current = methods; + ComEventsMethod? current = methods; + while (current != null && current._next != method) { current = current._next; @@ -150,9 +149,9 @@ public static ComEventsMethod Remove(ComEventsMethod methods, ComEventsMethod me { current._next = method._next; } - } - return methods; + return methods; + } } public bool Empty @@ -175,7 +174,7 @@ public void AddDelegate(Delegate d) { if (wrapper.Delegate.GetType() == d.GetType()) { - wrapper.Delegate = Delegate.Combine(wrapper.Delegate, d); + wrapper.Delegate = Delegate.Combine(wrapper.Delegate, d)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 return; } } @@ -191,7 +190,7 @@ public void RemoveDelegate(Delegate d) { // Find delegate wrapper index int removeIdx = -1; - DelegateWrapper wrapper = null; + DelegateWrapper? wrapper = null; for (int i = 0; i < _delegateWrappers.Count; i++) { DelegateWrapper wrapperMaybe = _delegateWrappers[i]; @@ -210,7 +209,7 @@ public void RemoveDelegate(Delegate d) } // Update wrapper or remove from collection - Delegate newDelegate = Delegate.Remove(wrapper.Delegate, d); + Delegate? newDelegate = Delegate.Remove(wrapper!.Delegate, d); if (newDelegate != null) { wrapper.Delegate = newDelegate; @@ -222,10 +221,10 @@ public void RemoveDelegate(Delegate d) } } - public object Invoke(object[] args) + public object? Invoke(object[] args) { Debug.Assert(!Empty); - object result = null; + object? result = null; lock (_delegateWrappers) { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsSink.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsSink.cs index c5262a655824..0a8780bbbe5b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsSink.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComEventsSink.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Diagnostics; -using Variant = System.Runtime.InteropServices.Variant; - namespace System.Runtime.InteropServices { /// @@ -16,10 +14,10 @@ namespace System.Runtime.InteropServices internal class ComEventsSink : IDispatch, ICustomQueryInterface { private Guid _iidSourceItf; - private ComTypes.IConnectionPoint _connectionPoint; + private ComTypes.IConnectionPoint? _connectionPoint; private int _cookie; - private ComEventsMethod _methods; - private ComEventsSink _next; + private ComEventsMethod? _methods; + private ComEventsSink? _next; public ComEventsSink(object rcw, Guid iid) { @@ -27,9 +25,9 @@ public ComEventsSink(object rcw, Guid iid) this.Advise(rcw); } - public static ComEventsSink Find(ComEventsSink sinks, ref Guid iid) + public static ComEventsSink? Find(ComEventsSink? sinks, ref Guid iid) { - ComEventsSink sink = sinks; + ComEventsSink? sink = sinks; while (sink != null && sink._iidSourceItf != iid) { sink = sink._next; @@ -38,13 +36,13 @@ public static ComEventsSink Find(ComEventsSink sinks, ref Guid iid) return sink; } - public static ComEventsSink Add(ComEventsSink sinks, ComEventsSink sink) + public static ComEventsSink Add(ComEventsSink? sinks, ComEventsSink sink) { sink._next = sinks; return sink; } - public static ComEventsSink RemoveAll(ComEventsSink sinks) + public static ComEventsSink? RemoveAll(ComEventsSink? sinks) { while (sinks != null) { @@ -55,18 +53,20 @@ public static ComEventsSink RemoveAll(ComEventsSink sinks) return null; } - public static ComEventsSink Remove(ComEventsSink sinks, ComEventsSink sink) + public static ComEventsSink? Remove(ComEventsSink sinks, ComEventsSink sink) { Debug.Assert(sinks != null, "removing event sink from empty sinks collection"); Debug.Assert(sink != null, "specify event sink is null"); + ComEventsSink? toReturn = sinks; + if (sink == sinks) { - sinks = sinks._next; + toReturn = sinks._next; } else { - ComEventsSink current = sinks; + ComEventsSink? current = sinks; while (current != null && current._next != sink) { current = current._next; @@ -80,16 +80,16 @@ public static ComEventsSink Remove(ComEventsSink sinks, ComEventsSink sink) sink.Unadvise(); - return sinks; + return toReturn; } - public ComEventsMethod RemoveMethod(ComEventsMethod method) + public ComEventsMethod? RemoveMethod(ComEventsMethod method) { - _methods = ComEventsMethod.Remove(_methods, method); + _methods = ComEventsMethod.Remove(_methods!, method); return _methods; } - public ComEventsMethod FindMethod(int dispid) + public ComEventsMethod? FindMethod(int dispid) { return ComEventsMethod.Find(_methods, dispid); } @@ -148,7 +148,7 @@ unsafe void IDispatch.Invoke( IntPtr pExcepInfo, IntPtr puArgErr) { - ComEventsMethod method = FindMethod(dispid); + ComEventsMethod? method = FindMethod(dispid); if (method == null) { return; @@ -158,7 +158,7 @@ unsafe void IDispatch.Invoke( // arguments marshalling. see code:ComEventsHelper#ComEventsArgsMarshalling const int InvalidIdx = -1; - object [] args = new object[pDispParams.cArgs]; + object[] args = new object[pDispParams.cArgs]; int [] byrefsMap = new int[pDispParams.cArgs]; bool [] usedArgs = new bool[pDispParams.cArgs]; @@ -173,7 +173,7 @@ unsafe void IDispatch.Invoke( { pos = namedArgs[i]; ref Variant pvar = ref GetVariant(ref vars[i]); - args[pos] = pvar.ToObject(); + args[pos] = pvar.ToObject()!; usedArgs[pos] = true; int byrefIdx = InvalidIdx; @@ -196,7 +196,7 @@ unsafe void IDispatch.Invoke( } ref Variant pvar = ref GetVariant(ref vars[pDispParams.cArgs - 1 - i]); - args[pos] = pvar.ToObject(); + args[pos] = pvar.ToObject()!; int byrefIdx = InvalidIdx; if (pvar.IsByRef) @@ -210,7 +210,7 @@ unsafe void IDispatch.Invoke( } // Do the actual delegate invocation - object result = method.Invoke(args); + object? result = method.Invoke(args); // convert result to VARIANT if (pVarResult != IntPtr.Zero) @@ -250,7 +250,7 @@ private void Advise(object rcw) ComTypes.IConnectionPointContainer cpc = (ComTypes.IConnectionPointContainer)rcw; ComTypes.IConnectionPoint cp; - cpc.FindConnectionPoint(ref _iidSourceItf, out cp); + cpc.FindConnectionPoint(ref _iidSourceItf, out cp!); object sinkObject = this; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs index e541960cae71..68efabcd79a9 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information -using System; +#nullable enable namespace System.Runtime.InteropServices.ComTypes { /*========================================================================== diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.CoreCLR.cs index 803504a0573c..d2a65f4d3e5f 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ComDataHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ComDataHelpers.cs index c3989872e443..c6c8dab3e1cb 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ComDataHelpers.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ComDataHelpers.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Text; - +#nullable enable namespace System.Runtime.InteropServices.CustomMarshalers { internal static class ComDataHelpers @@ -22,7 +19,7 @@ public static TView GetOrCreateManagedViewFromComData(object comObject managedView = createCallback((T)comObject); if (!Marshal.SetComObjectData(comObject, key, managedView)) { - managedView = (TView)Marshal.GetComObjectData(comObject, key); + managedView = (TView)Marshal.GetComObjectData(comObject, key)!; } return managedView; } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs index d43b68252d5f..670aea6f09a7 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Collections; using System.Runtime.InteropServices.ComTypes; @@ -34,7 +34,7 @@ public IEnumVARIANT Clone() } } - public int Next(int celt, object[] rgVar, IntPtr pceltFetched) + public int Next(int celt, object?[] rgVar, IntPtr pceltFetched) { int numElements = 0; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs index b3d319a53b41..93058a34ef9f 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; namespace System.Runtime.InteropServices.CustomMarshalers @@ -10,7 +11,7 @@ internal class EnumerableToDispatchMarshaler : ICustomMarshaler { private static readonly EnumerableToDispatchMarshaler s_enumerableToDispatchMarshaler = new EnumerableToDispatchMarshaler(); - public static ICustomMarshaler GetInstance(string cookie) => s_enumerableToDispatchMarshaler; + public static ICustomMarshaler GetInstance(string? cookie) => s_enumerableToDispatchMarshaler; private EnumerableToDispatchMarshaler() { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs index 67bb393c676b..298833256e63 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs @@ -2,11 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Runtime.InteropServices.ComTypes; -using Variant = System.Runtime.InteropServices.Variant; - namespace System.Runtime.InteropServices.CustomMarshalers { internal class EnumerableViewOfDispatch : ICustomAdapter, System.Collections.IEnumerable @@ -42,7 +41,7 @@ public IEnumerator GetEnumerator() IntPtr.Zero); } - object resultAsObject = result.ToObject(); + object? resultAsObject = result.ToObject(); if (!(resultAsObject is IEnumVARIANT enumVariant)) { throw new InvalidOperationException(SR.InvalidOp_InvalidNewEnumVariant); diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs index fddc0c70ba75..6e5e7b149606 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Collections; -using System.Collections.Generic; using System.Runtime.InteropServices.ComTypes; -using System.Text; namespace System.Runtime.InteropServices.CustomMarshalers { @@ -14,7 +12,7 @@ internal class EnumeratorToEnumVariantMarshaler : ICustomMarshaler { private static readonly EnumeratorToEnumVariantMarshaler s_enumeratorToEnumVariantMarshaler = new EnumeratorToEnumVariantMarshaler(); - public static ICustomMarshaler GetInstance(string cookie) => s_enumeratorToEnumVariantMarshaler; + public static ICustomMarshaler GetInstance(string? cookie) => s_enumeratorToEnumVariantMarshaler; private EnumeratorToEnumVariantMarshaler() { @@ -68,7 +66,7 @@ public object MarshalNativeToManaged(IntPtr pNativeData) return enumVariantView.Enumerator; } - return comObject as IEnumerator; + return (comObject as IEnumerator)!; } return ComDataHelpers.GetOrCreateManagedViewFromComData(comObject, var => new EnumeratorViewOfEnumVariant(var)); diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs index b5ef969ac1bf..bb2839d258c6 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs @@ -2,11 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Collections; -using System.Collections.Generic; using System.Runtime.InteropServices.ComTypes; -using System.Text; namespace System.Runtime.InteropServices.CustomMarshalers { @@ -15,7 +13,7 @@ internal class EnumeratorViewOfEnumVariant : ICustomAdapter, IEnumerator private readonly IEnumVARIANT _enumVariantObject; private bool _fetchedLastObject; private object[] _nextArray = new object[1]; - private object _current; + private object? _current; public EnumeratorViewOfEnumVariant(IEnumVARIANT enumVariantObject) { @@ -24,7 +22,7 @@ public EnumeratorViewOfEnumVariant(IEnumVARIANT enumVariantObject) _current = null; } - public object Current => _current; + public object? Current => _current; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 public unsafe bool MoveNext() { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ExpandoToDispatchExMarshaler.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ExpandoToDispatchExMarshaler.cs index 3cd8292e5bb5..30b55cc81c29 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ExpandoToDispatchExMarshaler.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/ExpandoToDispatchExMarshaler.cs @@ -2,19 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.InteropServices.ComTypes; -using System.Text; - +#nullable enable namespace System.Runtime.InteropServices.CustomMarshalers { internal class ExpandoToDispatchExMarshaler : ICustomMarshaler { private static readonly ExpandoToDispatchExMarshaler s_ExpandoToDispatchExMarshaler = new ExpandoToDispatchExMarshaler(); - public static ICustomMarshaler GetInstance(string cookie) => s_ExpandoToDispatchExMarshaler; + public static ICustomMarshaler GetInstance(string? cookie) => s_ExpandoToDispatchExMarshaler; private ExpandoToDispatchExMarshaler() { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/TypeToTypeInfoMarshaler.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/TypeToTypeInfoMarshaler.cs index eeae079d73ae..eda7c8507158 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/TypeToTypeInfoMarshaler.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/TypeToTypeInfoMarshaler.cs @@ -2,19 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.InteropServices.ComTypes; -using System.Text; - +#nullable enable namespace System.Runtime.InteropServices.CustomMarshalers { internal class TypeToTypeInfoMarshaler : ICustomMarshaler { private static readonly TypeToTypeInfoMarshaler s_typeToTypeInfoMarshaler = new TypeToTypeInfoMarshaler(); - public static ICustomMarshaler GetInstance(string cookie) => s_typeToTypeInfoMarshaler; + public static ICustomMarshaler GetInstance(string? cookie) => s_typeToTypeInfoMarshaler; private TypeToTypeInfoMarshaler() { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Expando/IExpando.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Expando/IExpando.cs index 909aac1a69f1..8939b5266c9f 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Expando/IExpando.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Expando/IExpando.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; namespace System.Runtime.InteropServices.Expando diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs index 6e09a0c3f7ce..357653420b32 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; #if BIT64 using nint = System.Int64; @@ -15,7 +16,7 @@ namespace System.Runtime.InteropServices public partial struct GCHandle { [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr InternalAlloc(object value, GCHandleType type); + private static extern IntPtr InternalAlloc(object? value, GCHandleType type); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void InternalFree(IntPtr handle); @@ -30,9 +31,9 @@ internal static unsafe object InternalGet(IntPtr handle) => #endif [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void InternalSet(IntPtr handle, object value); + private static extern void InternalSet(IntPtr handle, object? value); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern object InternalCompareExchange(IntPtr handle, object value, object oldValue); + internal static extern object? InternalCompareExchange(IntPtr handle, object? value, object? oldValue); } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs index fbe70fed7375..128487842a5b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.Collections.Generic; using System.Text; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IException.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IException.cs index 895aa5478195..012f0c7d808b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IException.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IException.cs @@ -13,6 +13,7 @@ ** =============================================================================*/ +#nullable enable namespace System.Runtime.InteropServices { using System; using System.Reflection; @@ -29,7 +30,7 @@ internal interface _Exception // implementations of get_InnerException to be provided by the base class. It works only if Exception.get_InnerException // is virtual. // - Exception InnerException { + Exception? InnerException { get; } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs index e399ad61008b..a45efb42ba9c 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs @@ -2,19 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; +#nullable enable using System.Reflection; -using System.Security; -using System.Text; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; -using Microsoft.Win32; -using System.Diagnostics; using System.Runtime.InteropServices.ComTypes; using System.StubHelpers; -using Internal.Runtime.CompilerServices; - namespace System.Runtime.InteropServices { /// @@ -35,13 +29,14 @@ public static partial class Marshal public static IntPtr OffsetOf(Type t, string fieldName) { - if (t == null) + if (t is null) { throw new ArgumentNullException(nameof(t)); } FieldInfo f = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - if (f == null) + + if (f is null) { throw new ArgumentException(SR.Format(SR.Argument_OffsetOfFieldNotFound, t.FullName), nameof(fieldName)); } @@ -86,7 +81,7 @@ public static long ReadInt64([MarshalAs(UnmanagedType.AsAny), In] object ptr, in private static unsafe T ReadValueSlow(object ptr, int ofs, Func readValueHelper) { // Consumers of this method are documented to throw AccessViolationException on any AV - if (ptr == null) + if (ptr is null) { throw new AccessViolationException(); } @@ -140,7 +135,7 @@ public static void WriteInt64(object ptr, int ofs, long val) private static unsafe void WriteValueSlow(object ptr, int ofs, T val, Action writeValueHelper) { // Consumers of this method are documented to throw AccessViolationException on any AV - if (ptr == null) + if (ptr is null) { throw new AccessViolationException(); } @@ -223,7 +218,7 @@ private static object PtrToStructureHelper(IntPtr ptr, Type structureType) public static extern void DestroyStructure(IntPtr ptr, Type structuretype); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool IsPinnable(object obj); + internal static extern bool IsPinnable(object? obj); #if FEATURE_COMINTEROP /// @@ -232,7 +227,7 @@ private static object PtrToStructureHelper(IntPtr ptr, Type structureType) /// public static IntPtr GetHINSTANCE(Module m) { - if (m == null) + if (m is null) { throw new ArgumentNullException(nameof(m)); } @@ -306,14 +301,14 @@ public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb) /// up an IErrorInfo for the exception. /// [MethodImpl(MethodImplOptions.InternalCall)] - public static extern int GetHRForException(Exception e); + public static extern int GetHRForException(Exception? e); /// /// Given a managed object that wraps an ITypeInfo, return its name. /// public static string GetTypeInfoName(ITypeInfo typeInfo) { - if (typeInfo == null) + if (typeInfo is null) { throw new ArgumentNullException(nameof(typeInfo)); } @@ -354,7 +349,8 @@ public static string GetTypeInfoName(ITypeInfo typeInfo) return GetComInterfaceForObjectNative(o, T, false, true); } - public static IntPtr GetComInterfaceForObject(T o) => GetComInterfaceForObject(o, typeof(TInterface)); + // TODO-NULLABLE-GENERIC: T cannot be null + public static IntPtr GetComInterfaceForObject(T o) => GetComInterfaceForObject(o!, typeof(TInterface)); /// /// Return the IUnknown* representing the interface for the Object. @@ -394,7 +390,8 @@ public static string GetTypeInfoName(ITypeInfo typeInfo) public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) { - return CreateAggregatedObject(pOuter, (object)o); + // TODO-NULLABLE-GENERIC: T cannot be null + return CreateAggregatedObject(pOuter, (object)o!); } [MethodImpl(MethodImplOptions.InternalCall)] @@ -459,9 +456,9 @@ public static void FreeBSTR(IntPtr ptr) } } - public static IntPtr StringToBSTR(string s) + public static IntPtr StringToBSTR(string? s) { - if (s == null) + if (s is null) { return IntPtr.Zero; } @@ -493,7 +490,7 @@ public static string PtrToStringBSTR(IntPtr ptr) /// public static int ReleaseComObject(object o) { - if (o == null) + if (o is null) { // Match .NET Framework behaviour. throw new NullReferenceException(); @@ -515,7 +512,7 @@ public static int ReleaseComObject(object o) /// public static int FinalReleaseComObject(object o) { - if (o == null) + if (o is null) { throw new ArgumentNullException(nameof(o)); } @@ -531,13 +528,13 @@ public static int FinalReleaseComObject(object o) [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void InternalFinalReleaseComObject(object o); - public static object GetComObjectData(object obj, object key) + public static object? GetComObjectData(object obj, object key) { - if (obj == null) + if (obj is null) { throw new ArgumentNullException(nameof(obj)); } - if (key == null) + if (key is null) { throw new ArgumentNullException(nameof(key)); } @@ -560,13 +557,13 @@ public static object GetComObjectData(object obj, object key) /// false if the data could not be added because there already was data for the /// specified key. /// - public static bool SetComObjectData(object obj, object key, object data) + public static bool SetComObjectData(object obj, object key, object? data) { - if (obj == null) + if (obj is null) { throw new ArgumentNullException(nameof(obj)); } - if (key == null) + if (key is null) { throw new ArgumentNullException(nameof(key)); } @@ -587,9 +584,9 @@ public static bool SetComObjectData(object obj, object key, object data) /// This method takes the given COM object and wraps it in an object /// of the specified type. The type must be derived from __ComObject. /// - public static object CreateWrapperOfType(object o, Type t) + public static object? CreateWrapperOfType(object? o, Type t) { - if (t == null) + if (t is null) { throw new ArgumentNullException(nameof(t)); } @@ -606,7 +603,7 @@ public static object CreateWrapperOfType(object o, Type t) throw new ArgumentException(SR.Argument_TypeIsWinRTType, nameof(t)); } - if (o == null) + if (o is null) { return null; } @@ -627,8 +624,8 @@ public static object CreateWrapperOfType(object o, Type t) } // Check to see if we already have a cached wrapper for this type. - object Wrapper = GetComObjectData(o, t); - if (Wrapper == null) + object? Wrapper = GetComObjectData(o, t); + if (Wrapper is null) { // Create the wrapper for the specified type. Wrapper = InternalCreateWrapperOfType(o, t); @@ -646,7 +643,8 @@ public static object CreateWrapperOfType(object o, Type t) public static TWrapper CreateWrapperOfType(T o) { - return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper)); + // TODO-NULLABLE-GENERIC: T can be null + return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper))!; } [MethodImpl(MethodImplOptions.InternalCall)] @@ -668,34 +666,33 @@ public static TWrapper CreateWrapperOfType(T o) public static extern int /* ULONG */ Release(IntPtr /* IUnknown */ pUnk); [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void GetNativeVariantForObject(object obj, /* VARIANT * */ IntPtr pDstNativeVariant); + public static extern void GetNativeVariantForObject(object? obj, /* VARIANT * */ IntPtr pDstNativeVariant); public static void GetNativeVariantForObject(T obj, IntPtr pDstNativeVariant) { - GetNativeVariantForObject((object)obj, pDstNativeVariant); + // TODO-NULLABLE-GENERIC: T can be null + GetNativeVariantForObject((object)obj!, pDstNativeVariant); } [MethodImpl(MethodImplOptions.InternalCall)] - public static extern object GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant); + public static extern object? GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant); public static T GetObjectForNativeVariant(IntPtr pSrcNativeVariant) { - return (T)GetObjectForNativeVariant(pSrcNativeVariant); + // TODO-NULLABLE-GENERIC: T can be null + return (T)GetObjectForNativeVariant(pSrcNativeVariant)!; } [MethodImpl(MethodImplOptions.InternalCall)] - public static extern object[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars); + public static extern object?[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars); + // TODO-NULLABLE-GENERIC: T[] contents can be null public static T[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { - object[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars); - T[] result = null; + object?[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars); - if (objects != null) - { - result = new T[objects.Length]; - Array.Copy(objects, 0, result, 0, objects.Length); - } + T[]? result = new T[objects.Length]; + Array.Copy(objects, 0, result, 0, objects.Length); return result; } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs index ca70d5d8735e..fd0318e0211e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; @@ -179,7 +180,7 @@ public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) /// Therefore, this table uses weak assembly pointers to indirectly achieve /// similar behavior. /// - private static ConditionalWeakTable s_nativeDllResolveMap = null; + private static ConditionalWeakTable? s_nativeDllResolveMap; /// /// Set a callback for resolving native library imports from an assembly. @@ -210,7 +211,7 @@ public static void SetDllImportResolver(Assembly assembly, DllImportResolver res try { - s_nativeDllResolveMap.Add(assembly, resolver); + s_nativeDllResolveMap!.Add(assembly, resolver); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } catch (ArgumentException) { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Variant.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Variant.cs index c726255c1ae0..f9c17251697e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Variant.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Variant.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; namespace System.Runtime.InteropServices @@ -227,7 +228,7 @@ unsafe public void CopyFromIndirect(object value) /// Get the managed object representing the Variant. /// /// - public object ToObject() + public object? ToObject() { // Check the simple case upfront if (IsEmpty) @@ -644,7 +645,7 @@ public string AsBstr // VT_UNKNOWN - public object AsUnknown + public object? AsUnknown { get { @@ -672,7 +673,7 @@ public object AsUnknown // VT_DISPATCH - public object AsDispatch + public object? AsDispatch { get { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs index b8376e445fb6..1441639dd6a6 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs @@ -2,8 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { // DefaultInterfaceAttribute marks a WinRT class (or interface group) that has its default interface specified. diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs index ce4be3415e7c..201e23b6e4cc 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs @@ -2,16 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime; -using System.Security; -using System.Collections; -using System.Collections.Generic; +#nullable enable using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs index 6542f5cf26c4..5ac54b7d41cf 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs @@ -2,16 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime; -using System.Security; -using System.Collections; -using System.Collections.Generic; +#nullable enable using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -32,7 +24,7 @@ private BindableVectorToListAdapter() } // object this[int index] { get } - internal object Indexer_Get(int index) + internal object? Indexer_Get(int index) { if (index < 0) throw new ArgumentOutOfRangeException(nameof(index)); @@ -154,7 +146,7 @@ internal void RemoveAt(int index) // Helpers: - private static object GetAt(IBindableVector _this, uint index) + private static object? GetAt(IBindableVector _this, uint index) { try { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs index 92c78f9ea2d5..2575794355e3 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections.Generic; using System.Diagnostics; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs index 67711511dfe7..b02365ef1669 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; -using System.Security; using Internal.Runtime.CompilerServices; @@ -65,7 +62,7 @@ public bool IsNumericScalar } } - public override string ToString() + public override string? ToString() { if (_data != null) { @@ -326,7 +323,7 @@ private T[] CoerceArrayValue(PropertyType unboxType) { try { - coercedArray[i] = CoerceScalarValue(scalarType, dataArray.GetValue(i)); + coercedArray[i] = CoerceScalarValue(scalarType, dataArray.GetValue(i)!); } catch (InvalidCastException elementCastException) { @@ -379,7 +376,7 @@ private static T CoerceScalarValue(PropertyType type, object value) { if (numericScalar.Item1 == typeof(T)) { - return (T)Convert.ChangeType(value, typeof(T), System.Globalization.CultureInfo.InvariantCulture); + return (T)Convert.ChangeType(value, typeof(T), System.Globalization.CultureInfo.InvariantCulture)!; } } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs index 8b9e7f17870d..e1061bd08d0e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs @@ -2,13 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections; using System.Diagnostics; -using System.Reflection; -using System.Security; namespace System.Runtime.InteropServices.WindowsRuntime { @@ -17,7 +13,7 @@ internal sealed class CLRIReferenceImpl : CLRIPropertyValueImpl, IReference. Need to QI for IReference with the appropriate GUID, call @@ -55,7 +51,7 @@ internal static object UnboxHelper(object wrapper) Debug.Assert(wrapper != null); IReference reference = (IReference)wrapper; Debug.Assert(reference != null, "CLRIReferenceImpl::UnboxHelper - QI'ed for IReference<" + typeof(T) + ">, but that failed."); - return reference.Value; + return reference.Value!; // TODO-NULLABLE-GENERIC } } @@ -83,7 +79,7 @@ public T[] Value get { return _value; } } - public override string ToString() + public override string? ToString() { if (_value != null) { @@ -296,11 +292,11 @@ internal static object CreateIReference(object obj) if (propType.HasValue) { Type specificType = typeof(CLRIReferenceImpl<>).MakeGenericType(type); - return Activator.CreateInstance(specificType, new object[] { propType.GetValueOrDefault(), obj }); + return Activator.CreateInstance(specificType, new object[] { propType.GetValueOrDefault(), obj })!; } Debug.Fail("We should not see non-WinRT type here"); - return null; + return null!; } internal static object CreateIReferenceArray(Array obj) @@ -367,7 +363,7 @@ internal static object CreateIReferenceArray(Array obj) if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)) { - object[] objArray = new object[obj.Length]; + object?[] objArray = new object?[obj.Length]; for (int i = 0; i < objArray.Length; i++) { objArray[i] = obj.GetValue(i); @@ -389,7 +385,7 @@ internal static object CreateIReferenceArray(Array obj) { // All WinRT value type will be Property.Other Type specificType = typeof(CLRIReferenceArrayImpl<>).MakeGenericType(type); - return Activator.CreateInstance(specificType, new object[] { propType.GetValueOrDefault(), obj }); + return Activator.CreateInstance(specificType, new object[] { propType.GetValueOrDefault(), obj })!; } else { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs index a21d6a03b6ba..03e0760e188b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs @@ -2,13 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; - namespace System.Runtime.InteropServices.WindowsRuntime { @@ -100,6 +97,7 @@ public TValue Lookup(TKey key) if (!found) { + Debug.Assert(key != null); Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString())); e.HResult = HResults.E_BOUNDS; throw e; @@ -131,7 +129,7 @@ public IEnumerator> GetEnumerator() return new IKeyValuePairEnumerator(items, firstItemIndex, lastItemIndex); } - public void Split(out IMapView firstPartition, out IMapView secondPartition) + public void Split(out IMapView? firstPartition, out IMapView? secondPartition) { if (Count < 2) { @@ -150,12 +148,12 @@ public void Split(out IMapView firstPartition, out IMapView searchKey = new KeyValuePair(key, default); + KeyValuePair searchKey = new KeyValuePair(key, default!); // TODO-NULLABLE-GENERIC int index = Array.BinarySearch(items, firstItemIndex, Count, searchKey, keyValuePairComparator); if (index < 0) { - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } @@ -208,7 +206,7 @@ public IKeyValuePair Current } } - object IEnumerator.Current + object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { get { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs index 6874148191aa..10d663b1baed 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs @@ -2,17 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; +#nullable enable using System.Reflection; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Runtime.Serialization; -using System.StubHelpers; -using System.Globalization; namespace System.Runtime.InteropServices.WindowsRuntime { @@ -88,7 +79,7 @@ public void SetValue(object target, object value, object indexValue) InvokeInternal(target, new object[] { indexValue, value }, false); } - private object InvokeInternal(object target, object[] args, bool getValue) + private object InvokeInternal(object target, object[]? args, bool getValue) { // Forward to the right object if we are dealing with a proxy if (target is IGetProxyTarget proxy) @@ -114,7 +105,7 @@ private object InvokeInternal(object target, object[] args, bool getValue) accessor, accessor.DeclaringType.FullName)); - RuntimeMethodInfo rtMethod = accessor as RuntimeMethodInfo; + RuntimeMethodInfo? rtMethod = accessor as RuntimeMethodInfo; if (rtMethod == null) throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo); diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs index 2751209638b1..70e046d7ed04 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -106,7 +106,7 @@ public bool MoveNext() return enumeration.MoveNext(); } - object IEnumerator.Current + object? IEnumerator.Current { get { return ((IEnumerator)this).Current; } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs index 53a889e65175..b78fef6918bc 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs @@ -2,17 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Reflection; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -41,6 +34,7 @@ internal V Lookup(K key) if (!keyFound) { + Debug.Assert(key != null); Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString())); e.HResult = HResults.E_BOUNDS; throw e; @@ -95,6 +89,7 @@ internal void Remove(K key) if (!removed) { + Debug.Assert(key != null); Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString())); e.HResult = HResults.E_BOUNDS; throw e; diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs index b1d9c8cb3a8b..eb851610e67a 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs @@ -2,13 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.WindowsRuntime; - namespace System.Runtime.InteropServices.WindowsRuntime { @@ -113,7 +110,7 @@ public bool MoveNext() return enumeration.MoveNext(); } - object IEnumerator.Current + object? IEnumerator.Current { get { return ((IEnumerator)this).Current; } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs index 5299af3b93ec..bde80a9b665b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs @@ -2,14 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -44,14 +40,14 @@ private EnumerableToBindableIterableAdapter() Debug.Fail("This class is never instantiated"); } - internal sealed class NonGenericToGenericEnumerator : IEnumerator + internal sealed class NonGenericToGenericEnumerator : IEnumerator { private IEnumerator enumerator; public NonGenericToGenericEnumerator(IEnumerator enumerator) { this.enumerator = enumerator; } - public object Current { get { return enumerator.Current; } } + public object? Current { get { return enumerator.Current; } } public bool MoveNext() { return enumerator.MoveNext(); } public void Reset() { enumerator.Reset(); } public void Dispose() { } @@ -61,7 +57,7 @@ public void Dispose() { } internal IBindableIterator First_Stub() { IEnumerable _this = Unsafe.As(this); - return new EnumeratorToIteratorAdapter(new NonGenericToGenericEnumerator(_this.GetEnumerator())); + return new EnumeratorToIteratorAdapter(new NonGenericToGenericEnumerator(_this.GetEnumerator())); } } @@ -99,11 +95,11 @@ public T Current } } - object IBindableIterator.Current + object? IBindableIterator.Current { get { - return (object)((IIterator)this).Current; + return ((IIterator)this).Current; } } @@ -154,7 +150,7 @@ public int GetMany(T[] items) if (typeof(T) == typeof(string)) { - string[] stringItems = items as string[]; + string[] stringItems = (items as string[])!; // Fill the rest of the array with string.Empty to avoid marshaling failure for (int i = index; i < items.Length; ++i) diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs index 0fb88950391e..a69a1a824c87 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections.Generic; using System.Diagnostics; using System.Threading; @@ -20,7 +18,7 @@ public sealed class EventRegistrationTokenTable where T : class // Cached multicast delegate which will invoke all of the currently registered delegates. This // will be accessed frequently in common coding paterns, so we don't want to calculate it repeatedly. - private volatile T m_invokeList; + private volatile T m_invokeList = null!; // TODO-NULLABLE-GENERIC public EventRegistrationTokenTable() { @@ -47,7 +45,7 @@ public T InvocationList { // The value being set replaces any of the existing values m_tokens.Clear(); - m_invokeList = null; + m_invokeList = null!; // TODO-NULLABLE-GENERIC if (value != null) { @@ -85,9 +83,9 @@ private EventRegistrationToken AddEventHandlerNoLock(T handler) m_tokens[token] = handler; // Update the current invocation list to include the newly added delegate - Delegate invokeList = (Delegate)(object)m_invokeList; + Delegate? invokeList = (Delegate?)(object?)m_invokeList; invokeList = MulticastDelegate.Combine(invokeList, (Delegate)(object)handler); - m_invokeList = (T)(object)invokeList; + m_invokeList = (T)(object?)invokeList!; // TODO-NULLABLE-GENERIC return token; } @@ -236,19 +234,19 @@ private void RemoveEventHandlerNoLock(EventRegistrationToken token) m_tokens.Remove(token); // Update the current invocation list to remove the delegate - Delegate invokeList = (Delegate)(object)m_invokeList; - invokeList = MulticastDelegate.Remove(invokeList, (Delegate)(object)handler); - m_invokeList = (T)(object)invokeList; + Delegate? invokeList = (Delegate?)(object?)m_invokeList; + invokeList = MulticastDelegate.Remove(invokeList, (Delegate?)(object?)handler); + m_invokeList = (T)(object?)invokeList!; // TODO-NULLABLE-GENERIC } } - public static EventRegistrationTokenTable GetOrCreateEventRegistrationTokenTable(ref EventRegistrationTokenTable refEventTable) + public static EventRegistrationTokenTable GetOrCreateEventRegistrationTokenTable(ref EventRegistrationTokenTable? refEventTable) { if (refEventTable == null) { Interlocked.CompareExchange(ref refEventTable, new EventRegistrationTokenTable(), null); } - return refEventTable; + return refEventTable!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs index 0ce01f86534e..578d219e5374 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs @@ -2,11 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime.InteropServices; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { [ComImport] diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs index 7891fd466650..8b85d5c413b9 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs @@ -2,13 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Diagnostics; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs index 07fb8f171a3b..30075ccfa31b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { [ComImport] diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs index 56cc2f6a4d93..78d399b7e3e6 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs @@ -2,17 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.StubHelpers; using System.Reflection; using System.Diagnostics; -using System.Runtime.InteropServices; using System.Collections; using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Security; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -26,7 +21,7 @@ internal static class ICustomPropertyProviderImpl // Creates a ICustomProperty implementation for Jupiter // Called from ICustomPropertyProvider_GetProperty from within runtime // - internal static ICustomProperty CreateProperty(object target, string propertyName) + internal static ICustomProperty? CreateProperty(object target, string propertyName) { Debug.Assert(target != null); Debug.Assert(propertyName != null); @@ -49,18 +44,18 @@ internal static ICustomProperty CreateProperty(object target, string propertyNam // Creates a ICustomProperty implementation for Jupiter // Called from ICustomPropertyProvider_GetIndexedProperty from within runtime // - internal static unsafe ICustomProperty CreateIndexedProperty(object target, string propertyName, TypeNameNative* pIndexedParamType) + internal static unsafe ICustomProperty? CreateIndexedProperty(object target, string propertyName, TypeNameNative* pIndexedParamType) { Debug.Assert(target != null); Debug.Assert(propertyName != null); - Type indexedParamType = null; + Type? indexedParamType = null; SystemTypeMarshaler.ConvertToManaged(pIndexedParamType, ref indexedParamType); return CreateIndexedProperty(target, propertyName, indexedParamType); } - internal static ICustomProperty CreateIndexedProperty(object target, string propertyName, Type indexedParamType) + internal static ICustomProperty? CreateIndexedProperty(object target, string propertyName, Type? indexedParamType) { Debug.Assert(target != null); Debug.Assert(propertyName != null); @@ -74,7 +69,7 @@ internal static ICustomProperty CreateIndexedProperty(object target, string prop BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, // default binder null, // ignore return type - new Type[] { indexedParamType }, // indexed parameter type + new Type?[] { indexedParamType }, // indexed parameter type null // ignore type modifier ); @@ -186,7 +181,7 @@ internal static object CreateInstance(object target) // // override ToString() to make sure callers get correct IStringable.ToString() behavior in native code // - public override string ToString() + public override string? ToString() { return WindowsRuntime.IStringableHelper.ToString(_target); } @@ -241,9 +236,9 @@ public IEnumerator GetEnumerator() // // IBindableVector implementation (forwards to IBindableVector / IVector) // - object IBindableVector.GetAt(uint index) + object? IBindableVector.GetAt(uint index) { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -260,7 +255,7 @@ uint IBindableVector.Size { get { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -276,7 +271,7 @@ uint IBindableVector.Size IBindableVectorView IBindableVector.GetView() { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -298,7 +293,7 @@ public IVectorViewToIBindableVectorViewAdapter(IVectorView vectorView) _vectorView = vectorView; } - object IBindableVectorView.GetAt(uint index) + object? IBindableVectorView.GetAt(uint index) { return _vectorView.GetAt(index); } @@ -324,7 +319,7 @@ IBindableIterator IBindableIterable.First() bool IBindableVector.IndexOf(object value, out uint index) { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -339,7 +334,7 @@ bool IBindableVector.IndexOf(object value, out uint index) void IBindableVector.SetAt(uint index, object value) { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -354,7 +349,7 @@ void IBindableVector.SetAt(uint index, object value) void IBindableVector.InsertAt(uint index, object value) { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -369,7 +364,7 @@ void IBindableVector.InsertAt(uint index, object value) void IBindableVector.RemoveAt(uint index) { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -384,7 +379,7 @@ void IBindableVector.RemoveAt(uint index) void IBindableVector.Append(object value) { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -399,7 +394,7 @@ void IBindableVector.Append(object value) void IBindableVector.RemoveAtEnd() { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -414,7 +409,7 @@ void IBindableVector.RemoveAtEnd() void IBindableVector.Clear() { - IBindableVector bindableVector = GetIBindableVectorNoThrow(); + IBindableVector? bindableVector = GetIBindableVectorNoThrow(); if (bindableVector != null) { // IBindableVector -> IBindableVector @@ -427,7 +422,7 @@ void IBindableVector.Clear() } } - private IBindableVector GetIBindableVectorNoThrow() + private IBindableVector? GetIBindableVectorNoThrow() { if ((_flags & InterfaceForwardingSupport.IBindableVector) != 0) return Unsafe.As(_target); @@ -447,9 +442,9 @@ private IVector_Raw GetVectorOfT() // // IBindableVectorView implementation (forwarding to IBindableVectorView or IVectorView) // - object IBindableVectorView.GetAt(uint index) + object? IBindableVectorView.GetAt(uint index) { - IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow(); + IBindableVectorView? bindableVectorView = GetIBindableVectorViewNoThrow(); if (bindableVectorView != null) return bindableVectorView.GetAt(index); else @@ -460,7 +455,7 @@ uint IBindableVectorView.Size { get { - IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow(); + IBindableVectorView? bindableVectorView = GetIBindableVectorViewNoThrow(); if (bindableVectorView != null) return bindableVectorView.Size; else @@ -470,7 +465,7 @@ uint IBindableVectorView.Size bool IBindableVectorView.IndexOf(object value, out uint index) { - IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow(); + IBindableVectorView? bindableVectorView = GetIBindableVectorViewNoThrow(); if (bindableVectorView != null) return bindableVectorView.IndexOf(value, out index); else @@ -479,7 +474,7 @@ bool IBindableVectorView.IndexOf(object value, out uint index) IBindableIterator IBindableIterable.First() { - IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow(); + IBindableVectorView? bindableVectorView = GetIBindableVectorViewNoThrow(); if (bindableVectorView != null) return bindableVectorView.First(); else @@ -494,11 +489,11 @@ public IteratorOfTToIteratorAdapter(IIterator iterator) { _iterator = iterator; } public bool HasCurrent { get { return _iterator.HasCurrent; } } - public object Current { get { return (object)_iterator.Current; } } + public object? Current { get { return _iterator.Current; } } public bool MoveNext() { return _iterator.MoveNext(); } } - private IBindableVectorView GetIBindableVectorViewNoThrow() + private IBindableVectorView? GetIBindableVectorViewNoThrow() { if ((_flags & InterfaceForwardingSupport.IBindableVectorView) != 0) return Unsafe.As(_target); diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs index a44591245f3d..94a00d31b56d 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections.Generic; // Windows.Foundation.Collections.IIterable`1 cannot be referenced from managed code because it's hidden diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs index 00d622b711bf..27ebdfb222cf 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { [ComImport] @@ -33,7 +30,7 @@ bool HasCurrent [Guid("6a1d6c07-076d-49f2-8314-f52c9c9a8331")] internal interface IBindableIterator { - object Current + object? Current { get; } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs index 02dff54eac4e..0f684be62737 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections.Generic; // Windows.Foundation.Collections.IMap`2, IMapView`2, and IKeyValuePair`2 cannot be referenced from @@ -35,7 +33,7 @@ internal interface IMapView : IIterable> V Lookup(K key); uint Size { get; } bool HasKey(K key); - void Split(out IMapView first, out IMapView second); + void Split(out IMapView? first, out IMapView? second); } [ComImport] diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs index 3a8086096b7c..d81cb6c4c95c 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs @@ -2,15 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -79,7 +74,7 @@ internal bool TryGetValue(K key, out V value) // throw an exception from Lookup. if (!_this.HasKey(key)) { - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } @@ -92,7 +87,7 @@ internal bool TryGetValue(K key, out V value) { if (HResults.E_BOUNDS == ex.HResult) { - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } throw; @@ -199,7 +194,7 @@ public bool MoveNext() return enumeration.MoveNext(); } - object IEnumerator.Current + object? IEnumerator.Current { get { return ((IEnumerator)this).Current; } } @@ -298,7 +293,7 @@ public bool MoveNext() return enumeration.MoveNext(); } - object IEnumerator.Current + object? IEnumerator.Current { get { return ((IEnumerator)this).Current; } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs index aefa7be4d1db..5ad32eaf380e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs index 01e8f7b44c8e..0e80f0a56daf 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs @@ -2,15 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -40,6 +34,7 @@ internal V Lookup(K key) if (!keyFound) { + Debug.Assert(key != null); Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString())); e.HResult = HResults.E_BOUNDS; throw e; @@ -63,7 +58,7 @@ internal bool HasKey(K key) } // void Split(out IMapView first, out IMapView second) - internal void Split(out IMapView first, out IMapView second) + internal void Split(out IMapView? first, out IMapView? second) { IReadOnlyDictionary _this = Unsafe.As>(this); diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs index 6269f2e20010..d608a8aef827 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs @@ -2,15 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -108,7 +102,7 @@ internal uint GetMany(uint startIndex, T[] items) if (typeof(T) == typeof(string)) { - string[] stringItems = items as string[]; + string[] stringItems = (items as string[])!; // Fill in the rest of the array with string.Empty to avoid marshaling failure for (uint i = itemCount; i < items.Length; ++i) diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs index d0101dafc9ca..844f866ede79 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { [ComImport] diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs index 03faef0adbd3..db8dc3842ed1 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { [ComImport] diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs index f00a7d350450..70872391135a 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections.Generic; // Windows.Foundation.Collections.IVector`1 and IVectorView`1 cannot be referenced from managed @@ -66,7 +64,7 @@ internal interface IVectorView : IIterable [WindowsRuntimeImport] internal interface IBindableVector : IBindableIterable { - object GetAt(uint index); + object? GetAt(uint index); uint Size { get; } IBindableVectorView GetView(); bool IndexOf(object value, out uint index); @@ -83,7 +81,7 @@ internal interface IBindableVector : IBindableIterable [WindowsRuntimeImport] internal interface IBindableVectorView : IBindableIterable { - object GetAt(uint index); + object? GetAt(uint index); uint Size { get; } bool IndexOf(object value, out uint index); } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs index f6667acf72ff..0bc7d04b1806 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs @@ -2,15 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs index d49836c46a24..ad8ec67e2c29 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs @@ -2,15 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Security; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -72,24 +67,24 @@ private BindableIterableToEnumerableAdapter() Debug.Fail("This class is never instantiated"); } - private sealed class NonGenericToGenericIterator : IIterator + private sealed class NonGenericToGenericIterator : IIterator { private IBindableIterator iterator; public NonGenericToGenericIterator(IBindableIterator iterator) { this.iterator = iterator; } - public object Current { get { return iterator.Current; } } + public object? Current { get { return iterator.Current; } } public bool HasCurrent { get { return iterator.HasCurrent; } } public bool MoveNext() { return iterator.MoveNext(); } - public int GetMany(object[] items) { throw new NotSupportedException(); } + public int GetMany(object?[] items) { throw new NotSupportedException(); } } // This method is invoked when GetEnumerator is called on a WinRT-backed implementation of IEnumerable. internal IEnumerator GetEnumerator_Stub() { IBindableIterable _this = Unsafe.As(this); - return new IteratorToEnumeratorAdapter(new NonGenericToGenericIterator(_this.First())); + return new IteratorToEnumeratorAdapter(new NonGenericToGenericIterator(_this.First())); } } @@ -104,7 +99,7 @@ internal sealed class IteratorToEnumeratorAdapter : IEnumerator { private IIterator m_iterator; private bool m_hadCurrent; - private T m_current; + private T m_current = default!; // TODO-NULLABLE-GENERIC private bool m_isInitialized; internal IteratorToEnumeratorAdapter(IIterator iterator) @@ -129,7 +124,7 @@ public T Current } } - object IEnumerator.Current + object? IEnumerator.Current { get { diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs index 08eb22b8e9de..828fc15e2988 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs @@ -2,17 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Reflection; +#nullable enable using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs index 98beaf22f238..048435a0f04f 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs @@ -2,16 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Reflection; +#nullable enable using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime { @@ -47,12 +39,12 @@ private static void EnsureIndexInt32(uint index, int listCapacity) public IBindableIterator First() { IEnumerator enumerator = list.GetEnumerator(); - return new EnumeratorToIteratorAdapter(new EnumerableToBindableIterableAdapter.NonGenericToGenericEnumerator(enumerator)); + return new EnumeratorToIteratorAdapter(new EnumerableToBindableIterableAdapter.NonGenericToGenericEnumerator(enumerator)); } // IBindableVectorView implementation: - public object GetAt(uint index) + public object? GetAt(uint index) { EnsureIndexInt32(index, list.Count); diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs index 657eac0bfc82..9773d69ba685 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs @@ -2,17 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Reflection; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -230,7 +223,7 @@ private static uint GetManyHelper(IList sourceList, uint startIndex, T[] i if (typeof(T) == typeof(string)) { - string[] stringItems = items as string[]; + string[] stringItems = (items as string[])!; // Fill in rest of the array with string.Empty to avoid marshaling failure for (uint i = itemCount; i < items.Length; ++i) diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs index 82ef71c783fd..ab6fc315beeb 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs @@ -2,12 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Reflection; -using System.Runtime.InteropServices; -using System.Security; using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -50,7 +46,7 @@ public object ActivateInstance() { try { - return Activator.CreateInstance(m_type); + return Activator.CreateInstance(m_type)!; } catch (MissingMethodException) { @@ -59,7 +55,7 @@ public object ActivateInstance() } catch (TargetInvocationException e) { - throw e.InnerException; + throw e.InnerException!; } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs index 487ebd160abd..c36fe91d09fd 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs @@ -2,15 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs index 8bd202042aba..10f2061d8a55 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs @@ -2,15 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime @@ -125,7 +119,7 @@ internal bool TryGetValue(K key, out V value) IMap _this = Unsafe.As>(this); if (!_this.HasKey(key)) { - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } @@ -136,7 +130,7 @@ internal bool TryGetValue(K key, out V value) } catch (KeyNotFoundException) { - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } } diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs index 290f927d0d94..eb7022367a03 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs @@ -2,15 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; +#nullable enable using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs index 201f4b132b97..f4abc61d0443 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs @@ -2,12 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Runtime.InteropServices; -using System.Security; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { #if BIT64 diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs index f083eb29b86f..5588fafe06dd 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs @@ -2,14 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Globalization; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { // Note this is a copy of the PropertyType enumeration from Windows.Foundation.winmd diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs index 2a6208f1bba1..0c555fe0020f 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs @@ -11,11 +11,8 @@ ** ===========================================================*/ -using System; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.WindowsRuntime; +#nullable enable using System.Runtime.CompilerServices; -using System.Security; namespace System.Runtime.InteropServices.WindowsRuntime { @@ -30,7 +27,7 @@ internal interface IStringable internal class IStringableHelper { - internal static string ToString(object obj) + internal static string? ToString(object obj) { if (obj is IGetProxyTarget proxy) obj = proxy.GetTarget(); @@ -97,9 +94,9 @@ public override string ToString() internal extern IntPtr GetRedirectedEqualsMD(); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern bool RedirectEquals(object obj, IntPtr pMD); + internal extern bool RedirectEquals(object? obj, IntPtr pMD); - public override bool Equals(object obj) + public override bool Equals(object? obj) { IntPtr pMD = GetRedirectedEqualsMD(); if (pMD == IntPtr.Zero) diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs index bda5168814a4..f7d44ffeaace 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs @@ -2,15 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; -using System.Collections.Generic; +#nullable enable using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs index 18c3596d49a2..704a45fb279a 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs @@ -2,15 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; -using System.Collections.Generic; +#nullable enable using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs index bc87efa6dcb2..f76f33169925 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs @@ -2,15 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Security; -using System.Collections; -using System.Collections.Generic; +#nullable enable using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.InteropServices.WindowsRuntime diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs index 1f6e373842cb..fb5c1163e16c 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; - +#nullable enable namespace System.Runtime.InteropServices.WindowsRuntime { // WindowsFoundationEventHandler a copy of the definition for the Windows.Foundation.EventHandler delegate diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs index 5a151e7de216..3b0fd3581d8e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs @@ -2,16 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; +#nullable enable using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Threading; -using System.Security; namespace System.Runtime.InteropServices.WindowsRuntime { @@ -43,7 +39,7 @@ public static void AddEventHandler(Func addMethod, // They have completely different implementation because native side has its own unique problem to solve - // there could be more than one RCW for the same COM object // it would be more confusing and less-performant if we were to merge them together - object target = removeMethod.Target; + object? target = removeMethod.Target; if (target == null || Marshal.IsComObject(target)) NativeOrStaticEventRegistrationImpl.AddEventHandler(addMethod, removeMethod, handler); else @@ -68,7 +64,7 @@ public static void RemoveEventHandler(Action removeMe // They have completely different implementation because native side has its own unique problem to solve - // there could be more than one RCW for the same COM object // it would be more confusing and less-performant if we were to merge them together - object target = removeMethod.Target; + object? target = removeMethod.Target; if (target == null || Marshal.IsComObject(target)) NativeOrStaticEventRegistrationImpl.RemoveEventHandler(removeMethod, handler); else @@ -84,7 +80,7 @@ public static void RemoveAllEventHandlers(Action removeM // They have completely different implementation because native side has its own unique problem to solve - // there could be more than one RCW for the same COM object // it would be more confusing and less-performant if we were to merge them together - object target = removeMethod.Target; + object? target = removeMethod.Target; if (target == null || Marshal.IsComObject(target)) NativeOrStaticEventRegistrationImpl.RemoveAllEventHandlers(removeMethod); else @@ -124,7 +120,7 @@ internal static int GetRegistrationTokenCacheSize() internal struct EventRegistrationTokenList { private EventRegistrationToken firstToken; // Optimization for common case where there is only one token - private List restTokens; // Rest of the tokens + private List? restTokens; // Rest of the tokens internal EventRegistrationTokenList(EventRegistrationToken token) { @@ -215,6 +211,8 @@ internal static void AddEventHandler(Func addMetho { Debug.Assert(addMethod != null); Debug.Assert(removeMethod != null); + Debug.Assert(removeMethod.Target != null); + Debug.Assert(handler != null); // Add the method, and make a note of the token -> delegate mapping. object instance = removeMethod.Target; @@ -250,14 +248,14 @@ private static Dictionary GetEventRegistrati lock (s_eventRegistrations) { - Dictionary> instanceMap = null; + Dictionary>? instanceMap = null; if (!s_eventRegistrations.TryGetValue(instance, out instanceMap)) { instanceMap = new Dictionary>(); s_eventRegistrations.Add(instance, instanceMap); } - Dictionary tokens = null; + Dictionary? tokens = null; if (!instanceMap.TryGetValue(removeMethod.Method, out tokens)) { tokens = new Dictionary(); @@ -271,6 +269,8 @@ private static Dictionary GetEventRegistrati internal static void RemoveEventHandler(Action removeMethod, T handler) { Debug.Assert(removeMethod != null); + Debug.Assert(removeMethod.Target != null); + Debug.Assert(handler != null); object instance = removeMethod.Target; Dictionary registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod); @@ -312,6 +312,7 @@ internal static void RemoveEventHandler(Action remove internal static void RemoveAllEventHandlers(Action removeMethod) { Debug.Assert(removeMethod != null); + Debug.Assert(removeMethod.Target != null); object instance = removeMethod.Target; Dictionary registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod); @@ -522,7 +523,7 @@ internal struct EventCacheEntry // Get InstanceKey to use in the cache private static object GetInstanceKey(Action removeMethod) { - object target = removeMethod.Target; + object? target = removeMethod.Target; Debug.Assert(target == null || Marshal.IsComObject(target), "Must be null or a RCW"); if (target == null) return removeMethod.Method.DeclaringType; @@ -531,7 +532,7 @@ private static object GetInstanceKey(Action removeMethod return (object)Marshal.GetRawIUnknownForComObjectNoAddRef(target); } - private static object FindEquivalentKeyUnsafe(ConditionalWeakTable registrationTable, object handler, out EventRegistrationTokenListWithCount tokens) + private static object? FindEquivalentKeyUnsafe(ConditionalWeakTable registrationTable, object handler, out EventRegistrationTokenListWithCount? tokens) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { foreach (KeyValuePair item in registrationTable) { @@ -549,6 +550,8 @@ internal static void AddEventHandler(Func addMetho Action removeMethod, T handler) { + Debug.Assert(handler != null); + // The instanceKey will be IUnknown * of the target object object instanceKey = GetInstanceKey(removeMethod); @@ -562,7 +565,7 @@ internal static void AddEventHandler(Func addMetho try { - EventRegistrationTokenListWithCount tokens; + EventRegistrationTokenListWithCount? tokens; // // The whole add/remove code has to be protected by a reader/writer lock @@ -572,7 +575,7 @@ internal static void AddEventHandler(Func addMetho try { // Add the method, and make a note of the delegate -> token mapping. - TokenListCount tokenListCount; + TokenListCount? tokenListCount; ConditionalWeakTable registrationTokens = GetOrCreateEventRegistrationTokenTable(instanceKey, removeMethod, out tokenListCount); lock (registrationTokens) { @@ -589,7 +592,7 @@ internal static void AddEventHandler(Func addMetho // will be added into B's token list, but once we unsubscribe B, we might end up removing // the last token in C, and that may lead to crash. // - object key = FindEquivalentKeyUnsafe(registrationTokens, handler, out tokens); + object? key = FindEquivalentKeyUnsafe(registrationTokens, handler, out tokens); if (key == null) { tokens = new EventRegistrationTokenListWithCount(tokenListCount, token); @@ -597,7 +600,7 @@ internal static void AddEventHandler(Func addMetho } else { - tokens.Push(token); + tokens!.Push(token); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } tokenAdded = true; @@ -625,7 +628,7 @@ internal static void AddEventHandler(Func addMetho } } - private static ConditionalWeakTable GetEventRegistrationTokenTableNoCreate(object instance, Action removeMethod, out TokenListCount tokenListCount) + private static ConditionalWeakTable? GetEventRegistrationTokenTableNoCreate(object instance, Action removeMethod, out TokenListCount? tokenListCount) { Debug.Assert(instance != null); Debug.Assert(removeMethod != null); @@ -638,11 +641,11 @@ private static ConditionalWeakTable Debug.Assert(instance != null); Debug.Assert(removeMethod != null); - return GetEventRegistrationTokenTableInternal(instance, removeMethod, out tokenListCount, /* createIfNotFound = */ true); + return GetEventRegistrationTokenTableInternal(instance, removeMethod, out tokenListCount!, /* createIfNotFound = */ true)!; } // Get the event registration token table for an event. These are indexed by the remove method of the event. - private static ConditionalWeakTable GetEventRegistrationTokenTableInternal(object instance, Action removeMethod, out TokenListCount tokenListCount, bool createIfNotFound) + private static ConditionalWeakTable? GetEventRegistrationTokenTableInternal(object instance, Action removeMethod, out TokenListCount? tokenListCount, bool createIfNotFound) { Debug.Assert(instance != null); Debug.Assert(removeMethod != null); @@ -681,6 +684,8 @@ private static ConditionalWeakTable internal static void RemoveEventHandler(Action removeMethod, T handler) { + Debug.Assert(handler != null); + object instanceKey = GetInstanceKey(removeMethod); EventRegistrationToken token; @@ -692,8 +697,8 @@ internal static void RemoveEventHandler(Action remove s_eventCacheRWLock.AcquireReaderLock(Timeout.Infinite); try { - TokenListCount tokenListCount; - ConditionalWeakTable registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod, out tokenListCount); + TokenListCount? tokenListCount; + ConditionalWeakTable? registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod, out tokenListCount); if (registrationTokens == null) { // We have no information regarding this particular instance (IUnknown*/type) - just return @@ -704,7 +709,7 @@ internal static void RemoveEventHandler(Action remove lock (registrationTokens) { - EventRegistrationTokenListWithCount tokens; + EventRegistrationTokenListWithCount? tokens; // Note: // When unsubscribing events, we allow subscribing the event using a different delegate @@ -713,7 +718,7 @@ internal static void RemoveEventHandler(Action remove // It actually doesn't matter which delegate - as long as it matches // Note that inside TryGetValueWithValueEquality we assumes that any delegate // with the same value equality would have the same hash code - object key = FindEquivalentKeyUnsafe(registrationTokens, handler, out tokens); + object? key = FindEquivalentKeyUnsafe(registrationTokens, handler, out tokens); Debug.Assert((key != null && tokens != null) || (key == null && tokens == null), "key and tokens must be both null or non-null"); if (tokens == null) @@ -738,7 +743,7 @@ internal static void RemoveEventHandler(Action remove // NOTE: We should not check whether registrationTokens has 0 entries and remove it from the cache // (just like managed event implementation), because this might have raced with the finalizer of // EventRegistrationTokenList - registrationTokens.Remove(key); + registrationTokens.Remove(key!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2388 } Log("[WinRT_Eventing] Event unsubscribed for managed instance = " + instanceKey + ", handler = " + handler + ", token = " + token.Value + "\n"); @@ -768,8 +773,7 @@ internal static void RemoveAllEventHandlers(Action remov s_eventCacheRWLock.AcquireReaderLock(Timeout.Infinite); try { - TokenListCount tokenListCount; - ConditionalWeakTable registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod, out tokenListCount); + ConditionalWeakTable? registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod, out _); if (registrationTokens == null) { // We have no information regarding this particular instance (IUnknown*/type) - just return @@ -838,8 +842,8 @@ internal class MyReaderWriterLock private uint numReadWaiters; // maximum number of threads that can be doing a WaitOne on the readEvent // conditions we wait on. - private EventWaitHandle writeEvent; // threads waiting to acquire a write lock go here. - private EventWaitHandle readEvent; // threads waiting to acquire a read lock go here (will be released in bulk) + private EventWaitHandle? writeEvent; // threads waiting to acquire a write lock go here. + private EventWaitHandle? readEvent; // threads waiting to acquire a read lock go here (will be released in bulk) internal MyReaderWriterLock() { @@ -918,7 +922,7 @@ internal void ReleaseWriterLock() /// while holding a spin lock). If all goes well, reenter the lock and /// set 'waitEvent' /// - private void LazyCreateEvent(ref EventWaitHandle waitEvent, bool makeAutoResetEvent) + private void LazyCreateEvent(ref EventWaitHandle? waitEvent, bool makeAutoResetEvent) { Debug.Assert(myLock != 0, "Lock must be held"); Debug.Assert(waitEvent == null, "Wait event must be null"); @@ -973,15 +977,17 @@ private void ExitAndWakeUpAppropriateWaiters() if (owners == 0 && numWriteWaiters > 0) { ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock) - writeEvent.Set(); // release one writer. + writeEvent!.Set(); // release one writer. Must be non-null if there were waiters. } else if (owners >= 0 && numReadWaiters != 0) { ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock) - readEvent.Set(); // release all readers. + readEvent!.Set(); // release all readers. Must be non-null if there were waiters. } else + { ExitMyLock(); + } } private void EnterMyLock() @@ -1054,12 +1060,12 @@ internal static unsafe string HStringToString(IntPtr hstring) } } - internal static Exception GetExceptionForHR(int hresult, Exception innerException, string messageResource) + internal static Exception GetExceptionForHR(int hresult, Exception? innerException, string? messageResource) { - Exception e = null; + Exception? e = null; if (innerException != null) { - string message = innerException.Message; + string? message = innerException.Message; if (message == null && messageResource != null) { message = SR.GetResourceString(messageResource); @@ -1068,7 +1074,7 @@ internal static Exception GetExceptionForHR(int hresult, Exception innerExceptio } else { - string message = (messageResource != null ? SR.GetResourceString(messageResource): null); + string? message = (messageResource != null ? SR.GetResourceString(messageResource): null); e = new Exception(message); } @@ -1076,7 +1082,7 @@ internal static Exception GetExceptionForHR(int hresult, Exception innerExceptio return e; } - internal static Exception GetExceptionForHR(int hresult, Exception innerException) + internal static Exception GetExceptionForHR(int hresult, Exception? innerException) { return GetExceptionForHR(hresult, innerException, null); } @@ -1122,7 +1128,7 @@ private static void RoReportUnhandledError(IRestrictedErrorInfo error) /// for the application to be invoked to process the error. /// /// true if the error was reported, false if not (ie running on Win8) - internal static bool ReportUnhandledError(Exception e) + internal static bool ReportUnhandledError(Exception? e) { // Only report to the WinRT global exception handler in modern apps if (!ApplicationModel.IsUap) diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs index b36266f769ad..fe1dc917117e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs @@ -2,16 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// - -using System; -using System.Collections.Generic; +#nullable enable using System.Collections.ObjectModel; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security; namespace System.Runtime.InteropServices.WindowsRuntime { @@ -19,9 +11,9 @@ internal static class WindowsRuntimeMetadata { private static EventHandler DesignerNamespaceResolve; - internal static string[] OnDesignerNamespaceResolve(string namespaceName) + internal static string[]? OnDesignerNamespaceResolve(string namespaceName) { - EventHandler eventHandler = DesignerNamespaceResolve; + EventHandler? eventHandler = DesignerNamespaceResolve; if (eventHandler != null) { foreach (EventHandler handler in eventHandler.GetInvocationList()) diff --git a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyDependencyResolver.cs b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyDependencyResolver.cs index 68a9bb8f5485..4fcff0af9861 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyDependencyResolver.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyDependencyResolver.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. + +#nullable enable using System.Collections.Generic; using System.IO; using System.Reflection; @@ -29,9 +31,14 @@ public sealed class AssemblyDependencyResolver public AssemblyDependencyResolver(string componentAssemblyPath) { - string assemblyPathsList = null; - string nativeSearchPathsList = null; - string resourceSearchPathsList = null; + if (componentAssemblyPath == null) + { + throw new ArgumentNullException(nameof(componentAssemblyPath)); + } + + string? assemblyPathsList = null; + string? nativeSearchPathsList = null; + string? resourceSearchPathsList = null; int returnCode = 0; StringBuilder errorMessage = new StringBuilder(); @@ -93,17 +100,22 @@ public AssemblyDependencyResolver(string componentAssemblyPath) _assemblyPaths = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (string assemblyPath in assemblyPaths) { - _assemblyPaths.Add(Path.GetFileNameWithoutExtension(assemblyPath), assemblyPath); + _assemblyPaths.Add(Path.GetFileNameWithoutExtension(assemblyPath)!, assemblyPath); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } _nativeSearchPaths = SplitPathsList(nativeSearchPathsList); _resourceSearchPaths = SplitPathsList(resourceSearchPathsList); - _assemblyDirectorySearchPaths = new string[1] { Path.GetDirectoryName(componentAssemblyPath) }; + _assemblyDirectorySearchPaths = new string[1] { Path.GetDirectoryName(componentAssemblyPath)! }; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } - public string ResolveAssemblyToPath(AssemblyName assemblyName) + public string? ResolveAssemblyToPath(AssemblyName assemblyName) { + if (assemblyName == null) + { + throw new ArgumentNullException(nameof(assemblyName)); + } + // Determine if the assembly name is for a satellite assembly or not // This is the same logic as in AssemblyBinder::BindByTpaList in CoreCLR // - If the culture name is non-empty and it's not 'neutral' @@ -130,7 +142,7 @@ public string ResolveAssemblyToPath(AssemblyName assemblyName) } } } - else + else if (assemblyName.Name != null) { // Load code assembly - simply look it up in the dictionary by its simple name. if (_assemblyPaths.TryGetValue(assemblyName.Name, out string assemblyPath)) @@ -148,8 +160,13 @@ public string ResolveAssemblyToPath(AssemblyName assemblyName) return null; } - public string ResolveUnmanagedDllToPath(string unmanagedDllName) + public string? ResolveUnmanagedDllToPath(string unmanagedDllName) { + if (unmanagedDllName == null) + { + throw new ArgumentNullException(nameof(unmanagedDllName)); + } + string[] searchPaths; if (unmanagedDllName.Contains(Path.DirectorySeparatorChar)) { @@ -180,7 +197,7 @@ public string ResolveUnmanagedDllToPath(string unmanagedDllName) return null; } - private static string[] SplitPathsList(string pathsList) + private static string[] SplitPathsList(string? pathsList) { if (pathsList == null) { diff --git a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 5cabe5158ea8..45a2c7f65b43 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections.Generic; using System.IO; using System.Reflection; @@ -28,21 +29,21 @@ public partial class AssemblyLoadContext internal static extern void InternalStartProfile(string profile, IntPtr ptrNativeAssemblyLoadContext); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - private static extern void LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, string ilPath, string niPath, ObjectHandleOnStack retAssembly); + private static extern void LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, string? ilPath, string? niPath, ObjectHandleOnStack retAssembly); [MethodImpl(MethodImplOptions.InternalCall)] public static extern Assembly[] GetLoadedAssemblies(); - private Assembly InternalLoadFromPath(string assemblyPath, string nativeImagePath) + private Assembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) { - RuntimeAssembly loadedAssembly = null; + RuntimeAssembly? loadedAssembly = null; LoadFromPath(_nativeAssemblyLoadContext, assemblyPath, nativeImagePath, JitHelpers.GetObjectHandleOnStack(ref loadedAssembly)); - return loadedAssembly; + return loadedAssembly!; } internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySpan arrSymbols) { - RuntimeAssembly loadedAssembly = null; + RuntimeAssembly? loadedAssembly = null; fixed (byte* ptrAssembly = arrAssembly, ptrSymbols = arrSymbols) { @@ -50,7 +51,7 @@ internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySp new IntPtr(ptrSymbols), arrSymbols.Length, JitHelpers.GetObjectHandleOnStack(ref loadedAssembly)); } - return loadedAssembly; + return loadedAssembly!; } #if !FEATURE_PAL @@ -71,21 +72,21 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) { VerifyIsAlive(); - RuntimeAssembly loadedAssembly = null; + RuntimeAssembly? loadedAssembly = null; LoadFromInMemoryModuleInternal( _nativeAssemblyLoadContext, moduleHandle, JitHelpers.GetObjectHandleOnStack(ref loadedAssembly)); - return loadedAssembly; + return loadedAssembly!; } } #endif // This method is invoked by the VM when using the host-provided assembly load context // implementation. - private static Assembly Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + private static Assembly? Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target); + AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; return context.ResolveUsingLoad(assemblyName); } @@ -94,17 +95,17 @@ private static Assembly Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyNa // after trying assembly resolution via Load override and TPA load context without success. private static Assembly ResolveUsingResolvingEvent(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target); + AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; // Invoke the AssemblyResolve event callbacks if wired up return context.ResolveUsingEvent(assemblyName); } - private Assembly GetFirstResolvedAssembly(AssemblyName assemblyName) + private Assembly? GetFirstResolvedAssembly(AssemblyName assemblyName) { - Assembly resolvedAssembly = null; + Assembly? resolvedAssembly = null; - Func assemblyResolveHandler = Resolving; + Func assemblyResolveHandler = _resolving; if (assemblyResolveHandler != null) { @@ -122,31 +123,37 @@ private Assembly GetFirstResolvedAssembly(AssemblyName assemblyName) return null; } - private Assembly ValidateAssemblyNameWithSimpleName(Assembly assembly, string requestedSimpleName) + private Assembly ValidateAssemblyNameWithSimpleName(Assembly assembly, string? requestedSimpleName) { // Get the name of the loaded assembly - string loadedSimpleName = null; + string? loadedSimpleName = null; // Derived type's Load implementation is expected to use one of the LoadFrom* methods to get the assembly // which is a RuntimeAssembly instance. However, since Assembly type can be used build any other artifact (e.g. AssemblyBuilder), // we need to check for RuntimeAssembly. - RuntimeAssembly rtLoadedAssembly = assembly as RuntimeAssembly; + RuntimeAssembly? rtLoadedAssembly = assembly as RuntimeAssembly; if (rtLoadedAssembly != null) { loadedSimpleName = rtLoadedAssembly.GetSimpleName(); } // The simple names should match at the very least - if (string.IsNullOrEmpty(loadedSimpleName) || (!requestedSimpleName.Equals(loadedSimpleName, StringComparison.InvariantCultureIgnoreCase))) + if (string.IsNullOrEmpty(requestedSimpleName)) + { + throw new ArgumentException(SR.ArgumentNull_AssemblyNameName); + } + if (string.IsNullOrEmpty(loadedSimpleName) || !requestedSimpleName.Equals(loadedSimpleName, StringComparison.InvariantCultureIgnoreCase)) + { throw new InvalidOperationException(SR.Argument_CustomAssemblyLoadContextRequestedNameMismatch); + } return assembly; } - private Assembly ResolveUsingLoad(AssemblyName assemblyName) + private Assembly? ResolveUsingLoad(AssemblyName assemblyName) { - string simpleName = assemblyName.Name; - Assembly assembly = Load(assemblyName); + string? simpleName = assemblyName.Name; + Assembly? assembly = Load(assemblyName); if (assembly != null) { @@ -158,10 +165,10 @@ private Assembly ResolveUsingLoad(AssemblyName assemblyName) private Assembly ResolveUsingEvent(AssemblyName assemblyName) { - string simpleName = assemblyName.Name; + string? simpleName = assemblyName.Name; // Invoke the AssemblyResolve event callbacks if wired up - Assembly assembly = GetFirstResolvedAssembly(assemblyName); + Assembly? assembly = GetFirstResolvedAssembly(assemblyName); if (assembly != null) { assembly = ValidateAssemblyNameWithSimpleName(assembly, simpleName); @@ -184,7 +191,7 @@ private Assembly ResolveUsingEvent(AssemblyName assemblyName) // implementation. private static IntPtr ResolveUnmanagedDll(string unmanagedDllName, IntPtr gchManagedAssemblyLoadContext) { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target); + AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; return context.LoadUnmanagedDll(unmanagedDllName); } @@ -192,7 +199,7 @@ private static IntPtr ResolveUnmanagedDll(string unmanagedDllName, IntPtr gchMan // after trying all other means of resolution. private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Assembly assembly, IntPtr gchManagedAssemblyLoadContext) { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target); + AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; return context.GetResolvedUnmanagedDll(assembly, unmanagedDllName); } @@ -200,7 +207,7 @@ private IntPtr GetResolvedUnmanagedDll(Assembly assembly, string unmanagedDllNam { IntPtr resolvedDll = IntPtr.Zero; - Func dllResolveHandler = ResolvingUnmanagedDll; + Func dllResolveHandler = _resolvingUnmanagedDll; if (dllResolveHandler != null) { @@ -232,9 +239,9 @@ internal Type LoadTypeForWinRTTypeNameInContext(string typeName) { VerifyIsAlive(); - Type type = null; + Type? type = null; LoadTypeForWinRTTypeNameInContextInternal(_nativeAssemblyLoadContext, typeName, JitHelpers.GetObjectHandleOnStack(ref type)); - return type; + return type!; } } @@ -242,16 +249,16 @@ internal Type LoadTypeForWinRTTypeNameInContext(string typeName) private static extern IntPtr GetLoadContextForAssembly(RuntimeAssembly assembly); // Returns the load context in which the specified assembly has been loaded - public static AssemblyLoadContext GetLoadContext(Assembly assembly) + public static AssemblyLoadContext? GetLoadContext(Assembly assembly) { if (assembly == null) { throw new ArgumentNullException(nameof(assembly)); } - AssemblyLoadContext loadContextForAssembly = null; + AssemblyLoadContext? loadContextForAssembly = null; - RuntimeAssembly rtAsm = assembly as RuntimeAssembly; + RuntimeAssembly? rtAsm = assembly as RuntimeAssembly; // We only support looking up load context for runtime assemblies. if (rtAsm != null) @@ -266,7 +273,7 @@ public static AssemblyLoadContext GetLoadContext(Assembly assembly) } else { - loadContextForAssembly = (AssemblyLoadContext)(GCHandle.FromIntPtr(ptrAssemblyLoadContext).Target); + loadContextForAssembly = (AssemblyLoadContext)(GCHandle.FromIntPtr(ptrAssemblyLoadContext).Target)!; } } @@ -292,24 +299,24 @@ private static void OnAssemblyLoad(RuntimeAssembly assembly) } // This method is called by the VM. - private static RuntimeAssembly OnResourceResolve(RuntimeAssembly assembly, string resourceName) + private static RuntimeAssembly? OnResourceResolve(RuntimeAssembly assembly, string resourceName) { return InvokeResolveEvent(ResourceResolve, assembly, resourceName); } // This method is called by the VM - private static RuntimeAssembly OnTypeResolve(RuntimeAssembly assembly, string typeName) + private static RuntimeAssembly? OnTypeResolve(RuntimeAssembly assembly, string typeName) { return InvokeResolveEvent(TypeResolve, assembly, typeName); } // This method is called by the VM. - private static RuntimeAssembly OnAssemblyResolve(RuntimeAssembly assembly, string assemblyFullName) + private static RuntimeAssembly? OnAssemblyResolve(RuntimeAssembly assembly, string assemblyFullName) { return InvokeResolveEvent(AssemblyResolve, assembly, assemblyFullName); } - private static RuntimeAssembly InvokeResolveEvent(ResolveEventHandler eventHandler, RuntimeAssembly assembly, string name) + private static RuntimeAssembly? InvokeResolveEvent(ResolveEventHandler eventHandler, RuntimeAssembly assembly, string name) { if (eventHandler == null) return null; @@ -319,7 +326,7 @@ private static RuntimeAssembly InvokeResolveEvent(ResolveEventHandler eventHandl foreach (ResolveEventHandler handler in eventHandler.GetInvocationList()) { Assembly asm = handler(null /* AppDomain */, args); - RuntimeAssembly ret = GetRuntimeAssembly(asm); + RuntimeAssembly? ret = GetRuntimeAssembly(asm); if (ret != null) return ret; } @@ -327,7 +334,7 @@ private static RuntimeAssembly InvokeResolveEvent(ResolveEventHandler eventHandl return null; } - private static RuntimeAssembly GetRuntimeAssembly(Assembly asm) + private static RuntimeAssembly? GetRuntimeAssembly(Assembly asm) { return asm == null ? null : diff --git a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 7ce8c53f2207..2d71035e1f17 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/System.Private.CoreLib/src/System/Runtime/Versioning/CompatibilitySwitch.cs b/src/System.Private.CoreLib/src/System/Runtime/Versioning/CompatibilitySwitch.cs index 3410f020bec5..b87a6a6148d9 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/Versioning/CompatibilitySwitch.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/Versioning/CompatibilitySwitch.cs @@ -1,7 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; + +#nullable enable using System.Globalization; using System.Runtime.CompilerServices; @@ -21,12 +22,12 @@ internal static class CompatibilitySwitch * * These apis are for internal use only for FX assemblies. It has not been decided if they can be used by OOB components due to EULA restrictions */ - internal static string GetValueInternal(string compatibilitySwitchName) + internal static string? GetValueInternal(string compatibilitySwitchName) { return GetValueInternalCall(compatibilitySwitchName, false); } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string GetValueInternalCall(string compatibilitySwitchName, bool onlyDB); + private static extern string? GetValueInternalCall(string compatibilitySwitchName, bool onlyDB); } } diff --git a/src/System.Private.CoreLib/src/System/RuntimeArgumentHandle.cs b/src/System.Private.CoreLib/src/System/RuntimeArgumentHandle.cs index 2066ed71eb6e..5cc72381e1b3 100644 --- a/src/System.Private.CoreLib/src/System/RuntimeArgumentHandle.cs +++ b/src/System.Private.CoreLib/src/System/RuntimeArgumentHandle.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -using System; - +#nullable enable namespace System { // This value type is used for constructing System.ArgIterator. diff --git a/src/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/System.Private.CoreLib/src/System/RuntimeHandles.cs index 56694c63b818..a2da2be1dfd6 100644 --- a/src/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Loader; using System.Runtime.Serialization; using System.Threading; @@ -414,17 +415,17 @@ internal IRuntimeMethodInfo GetDefaultConstructor() [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetTypeByName(string name, bool throwOnError, bool ignoreCase, StackCrawlMarkHandle stackMark, - IntPtr pPrivHostBinder, + ObjectHandleOnStack assemblyLoadContext, bool loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive); // Wrapper function to reduce the need for ifdefs. internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark, bool loadTypeFromPartialName) { - return GetTypeByName(name, throwOnError, ignoreCase, ref stackMark, IntPtr.Zero, loadTypeFromPartialName); + return GetTypeByName(name, throwOnError, ignoreCase, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext, loadTypeFromPartialName); } internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark, - IntPtr pPrivHostBinder, + AssemblyLoadContext assemblyLoadContext, bool loadTypeFromPartialName) { if (name == null || name.Length == 0) @@ -438,9 +439,10 @@ internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool i RuntimeType type = null; object keepAlive = null; + AssemblyLoadContext assemblyLoadContextStack = assemblyLoadContext; GetTypeByName(name, throwOnError, ignoreCase, JitHelpers.GetStackCrawlMarkHandle(ref stackMark), - pPrivHostBinder, + JitHelpers.GetObjectHandleOnStack(ref assemblyLoadContextStack), loadTypeFromPartialName, JitHelpers.GetObjectHandleOnStack(ref type), JitHelpers.GetObjectHandleOnStack(ref keepAlive)); GC.KeepAlive(keepAlive); diff --git a/src/System.Private.CoreLib/src/System/Security/DynamicSecurityMethodAttribute.cs b/src/System.Private.CoreLib/src/System/Security/DynamicSecurityMethodAttribute.cs index 83be902a2c59..06bb6a278ed7 100644 --- a/src/System.Private.CoreLib/src/System/Security/DynamicSecurityMethodAttribute.cs +++ b/src/System.Private.CoreLib/src/System/Security/DynamicSecurityMethodAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace System.Security diff --git a/src/System.Private.CoreLib/src/System/StartupHookProvider.cs b/src/System.Private.CoreLib/src/System/StartupHookProvider.cs index 051b379b24b2..68568178e4e4 100644 --- a/src/System.Private.CoreLib/src/System/StartupHookProvider.cs +++ b/src/System.Private.CoreLib/src/System/StartupHookProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.IO; using System.Reflection; @@ -28,7 +29,7 @@ private static void ProcessStartupHooks() // Initialize tracing before any user code can be called. System.Diagnostics.Tracing.EventPipeController.Initialize(); - string startupHooksVariable = (string)AppContext.GetData("STARTUP_HOOKS"); + string? startupHooksVariable = (string?)AppContext.GetData("STARTUP_HOOKS"); if (startupHooksVariable == null) { return; @@ -121,7 +122,7 @@ private static void CallStartupHook(StartupHookNameOrPath startupHook) catch (Exception assemblyLoadException) { throw new ArgumentException( - SR.Format(SR.Argument_StartupHookAssemblyLoadFailed, startupHook.Path ?? startupHook.AssemblyName.ToString()), + SR.Format(SR.Argument_StartupHookAssemblyLoadFailed, startupHook.Path ?? startupHook.AssemblyName!.ToString()), assemblyLoadException); } diff --git a/src/System.Private.CoreLib/src/System/StubHelpers.cs b/src/System.Private.CoreLib/src/System/StubHelpers.cs index 7fc7db154ef9..e28e536dee7b 100644 --- a/src/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/System.Private.CoreLib/src/System/StubHelpers.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - +#nullable enable namespace System.StubHelpers { using System.Text; @@ -103,7 +103,7 @@ internal static unsafe IntPtr ConvertToNative(int flags, string strManaged, IntP return (IntPtr)pbNativeBuffer; } - internal static unsafe string ConvertToManaged(IntPtr cstr) + internal static unsafe string? ConvertToManaged(IntPtr cstr) { if (IntPtr.Zero == cstr) return null; @@ -155,7 +155,7 @@ internal static unsafe IntPtr ConvertToNative(int flags, string strManaged, IntP return (IntPtr)pbNativeBuffer; } - internal static unsafe string ConvertToManaged(IntPtr cstr) + internal static unsafe string? ConvertToManaged(IntPtr cstr) { if (IntPtr.Zero == cstr) return null; @@ -277,7 +277,7 @@ internal static unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeB } } - internal static unsafe string ConvertToManaged(IntPtr bstr) + internal static unsafe string? ConvertToManaged(IntPtr bstr) { if (IntPtr.Zero == bstr) { @@ -371,7 +371,7 @@ internal static unsafe IntPtr ConvertToNative(string strManaged, bool fBestFit, return new IntPtr(pNative); } - internal static unsafe string ConvertToManaged(IntPtr pNative, int cch) + internal static unsafe string? ConvertToManaged(IntPtr pNative, int cch) { if (IntPtr.Zero == pNative) { @@ -399,7 +399,7 @@ internal static IntPtr ConvertToNative(int flags, string strManaged) return IntPtr.Zero; } - byte[] bytes = null; + byte[]? bytes = null; int nb = 0; if (strManaged.Length > 0) @@ -410,7 +410,7 @@ internal static IntPtr ConvertToNative(int flags, string strManaged) return Interop.OleAut32.SysAllocStringByteLen(bytes, (uint)nb); } - internal static unsafe string ConvertToManaged(IntPtr bstr) + internal static unsafe string? ConvertToManaged(IntPtr bstr) { if (IntPtr.Zero == bstr) { @@ -442,7 +442,7 @@ internal static IntPtr ConvertToNative(string strManaged) return IntPtr.Zero; } - internal static string ConvertToManaged(IntPtr bstr) + internal static string? ConvertToManaged(IntPtr bstr) { Debug.Fail("NYI"); return null; @@ -695,7 +695,7 @@ internal static class MngdHiddenLengthArrayMarshaler [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome); - internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -707,7 +707,7 @@ internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[ } } - internal static unsafe void ConvertContentsToNative_Type(ref System.Type[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToNative_Type(ref System.Type[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -719,7 +719,7 @@ internal static unsafe void ConvertContentsToNative_Type(ref System.Type[] manag } } - internal static unsafe void ConvertContentsToNative_Exception(ref Exception[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToNative_Exception(ref Exception[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -731,7 +731,7 @@ internal static unsafe void ConvertContentsToNative_Exception(ref Exception[] ma } } - internal static unsafe void ConvertContentsToNative_Nullable(ref Nullable[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToNative_Nullable(ref Nullable[]? managedArray, IntPtr pNativeHome) where T : struct { if (managedArray != null) @@ -744,7 +744,7 @@ internal static unsafe void ConvertContentsToNative_Nullable(ref Nullable[ } } - internal static unsafe void ConvertContentsToNative_KeyValuePair(ref KeyValuePair[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToNative_KeyValuePair(ref KeyValuePair[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -762,7 +762,7 @@ internal static unsafe void ConvertContentsToNative_KeyValuePair(ref KeyVa [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome); - internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -774,7 +774,7 @@ internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset } } - internal static unsafe void ConvertContentsToManaged_Type(ref System.Type[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToManaged_Type(ref System.Type?[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -786,7 +786,7 @@ internal static unsafe void ConvertContentsToManaged_Type(ref System.Type[] mana } } - internal static unsafe void ConvertContentsToManaged_Exception(ref Exception[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToManaged_Exception(ref Exception?[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -798,7 +798,7 @@ internal static unsafe void ConvertContentsToManaged_Exception(ref Exception[] m } } - internal static unsafe void ConvertContentsToManaged_Nullable(ref Nullable[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToManaged_Nullable(ref Nullable[]? managedArray, IntPtr pNativeHome) where T : struct { if (managedArray != null) @@ -811,7 +811,7 @@ internal static unsafe void ConvertContentsToManaged_Nullable(ref Nullable } } - internal static unsafe void ConvertContentsToManaged_KeyValuePair(ref KeyValuePair[] managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToManaged_KeyValuePair(ref KeyValuePair[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { @@ -883,10 +883,10 @@ private enum BackPropAction private BackPropAction backPropAction; // The managed layout type for BackPropAction.Layout. - private Type layoutType; + private Type? layoutType; // Cleanup list to be destroyed when clearing the native view (for layouts with SafeHandles). - private CleanupWorkListElement cleanupWorkList; + private CleanupWorkListElement? cleanupWorkList; [Flags] internal enum AsAnyFlags @@ -1129,8 +1129,8 @@ internal IntPtr ConvertToNative(object pManagedHome, int dwFlags) } else { - string strValue; - StringBuilder sbValue; + string? strValue; + StringBuilder? sbValue; if ((strValue = pManagedHome as string) != null) { @@ -1333,7 +1333,7 @@ internal static unsafe void ConvertToNative(System.Type managedType, TypeNameNat Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1)); } - internal static unsafe void ConvertToManaged(TypeNameNative* pNativeType, ref System.Type managedType) + internal static unsafe void ConvertToManaged(TypeNameNative* pNativeType, ref System.Type? managedType) { if (!Environment.IsWinRTSupported) { @@ -1389,14 +1389,14 @@ internal static int ConvertToNative(Exception ex) return ex.HResult; } - internal static Exception ConvertToManaged(int hr) + internal static Exception? ConvertToManaged(int hr) { if (!Environment.IsWinRTSupported) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT); } - Exception e = null; + Exception? e = null; if (hr < 0) { e = StubHelpers.InternalGetCOMHRExceptionObject(hr, IntPtr.Zero, null, /* fForWinRT */ true); @@ -1458,13 +1458,13 @@ internal struct NativeVariant internal abstract class CleanupWorkListElement { - private CleanupWorkListElement m_Next; + private CleanupWorkListElement? m_Next; protected abstract void DestroyCore(); public void Destroy() { DestroyCore(); - CleanupWorkListElement next = m_Next; + CleanupWorkListElement? next = m_Next; while (next != null) { next.DestroyCore(); @@ -1569,7 +1569,7 @@ internal static void AddToCleanupList(ref CleanupWorkListElement pCleanupWorkLis CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element); } - internal static void DestroyCleanupList(ref CleanupWorkListElement pCleanupWorkList) + internal static void DestroyCleanupList(ref CleanupWorkListElement? pCleanupWorkList) { if (pCleanupWorkList != null) { @@ -1604,7 +1604,7 @@ internal static Exception GetCOMHRExceptionObject_WinRT(int hr, IntPtr pCPCMD, o } [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern Exception InternalGetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis, bool fForWinRT); + internal static extern Exception InternalGetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object? pThis, bool fForWinRT); #endif // FEATURE_COMINTEROP @@ -1623,7 +1623,7 @@ internal static IntPtr SafeHandleAddRef(SafeHandle pHandle, ref bool success) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.pHandle, ExceptionResource.ArgumentNull_SafeHandle); } - pHandle.DangerousAddRef(ref success); + pHandle!.DangerousAddRef(ref success); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 return pHandle.DangerousGetHandle(); } @@ -1637,7 +1637,7 @@ internal static void SafeHandleRelease(SafeHandle pHandle) try { - pHandle.DangerousRelease(); + pHandle!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } catch { @@ -1725,7 +1725,7 @@ internal static void CheckStringLength(uint length) } [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkListElement pCleanupWorkList); + internal static extern unsafe void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkListElement? pCleanupWorkList); [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern unsafe void FmtClassUpdateCLRInternal(object obj, byte* pNative); [MethodImplAttribute(MethodImplOptions.InternalCall)] diff --git a/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs index 63afe45f32b3..8434707b847b 100644 --- a/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable +using System.Diagnostics; + namespace System.Text { public partial class StringBuilder @@ -113,7 +116,7 @@ internal unsafe void InternalCopy(IntPtr dest, int len) bool isLastChunk = true; byte* dstPtr = (byte*)dest.ToPointer(); - StringBuilder currentSrc = FindChunkForByte(len); + StringBuilder? currentSrc = FindChunkForByte(len); do { @@ -132,6 +135,7 @@ internal unsafe void InternalCopy(IntPtr dest, int len) Buffer.Memcpy(dstPtr + chunkOffsetInBytes, srcPtr, chunkLengthInBytes); } } + currentSrc = currentSrc.m_ChunkPrevious; } while (currentSrc != null); diff --git a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs index 26e1bd6bee0c..fd7f1dd962a1 100644 --- a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs +++ b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPoolPreAllocatedOverlapped.cs @@ -78,12 +78,7 @@ public void Dispose() ~PreAllocatedOverlapped() { - // - // During shutdown, don't automatically clean up, because this instance may still be - // reachable/usable by other code. - // - if (!Environment.HasShutdownStarted) - Dispose(); + Dispose(); } unsafe void IDeferredDisposable.OnFinalRelease(bool disposed) diff --git a/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs index 6e8306b74a33..ca173d10683a 100644 --- a/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs @@ -14,37 +14,6 @@ internal partial class TimerQueue { #region interface to native per-AppDomain timer -#if !FEATURE_PAL - private static int TickCount - { - get - { - // We need to keep our notion of time synchronized with the calls to SleepEx that drive - // the underlying native timer. In Win8, SleepEx does not count the time the machine spends - // sleeping/hibernating. Environment.TickCount (GetTickCount) *does* count that time, - // so we will get out of sync with SleepEx if we use that method. - // - // So, on Win8, we use QueryUnbiasedInterruptTime instead; this does not count time spent - // in sleep/hibernate mode. - if (Environment.IsWindows8OrAbove) - { - ulong time100ns; - - bool result = Interop.Kernel32.QueryUnbiasedInterruptTime(out time100ns); - if (!result) - throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error()); - - // convert to 100ns to milliseconds, and truncate to 32 bits. - return (int)(uint)(time100ns / 10000); - } - else - { - return Environment.TickCount; - } - } - } -#endif - // We use a SafeHandle to ensure that the native timer is destroyed when the AppDomain is unloaded. private sealed class AppDomainTimerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid { diff --git a/src/System.Private.CoreLib/src/System/TypeLoadException.CoreCLR.cs b/src/System.Private.CoreLib/src/System/TypeLoadException.CoreCLR.cs index 90f969ac9e6c..612066914b54 100644 --- a/src/System.Private.CoreLib/src/System/TypeLoadException.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/TypeLoadException.CoreCLR.cs @@ -43,7 +43,7 @@ private void SetMessageField() string? format = null; GetTypeLoadExceptionMessage(_resourceId, JitHelpers.GetStringHandleOnStack(ref format)); - _message = string.Format(format, _className, _assemblyName, _messageArg); + _message = string.Format(format!, _className, _assemblyName, _messageArg); } } } diff --git a/src/System.Private.CoreLib/src/System/TypeNameParser.cs b/src/System.Private.CoreLib/src/System/TypeNameParser.cs index 3cd904e8a245..4c96d786fb3a 100644 --- a/src/System.Private.CoreLib/src/System/TypeNameParser.cs +++ b/src/System.Private.CoreLib/src/System/TypeNameParser.cs @@ -6,12 +6,13 @@ using System.Diagnostics; using System.IO; using System.Reflection; -using System.Security; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Runtime.Versioning; +using System.Security; using System.Text; using System.Threading; -using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System @@ -192,7 +193,7 @@ private static Assembly ResolveAssembly(string asmName, Func AsBytes(this ReadOnlySpan text) /// The target . /// Returns default when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsBytes(this Utf8String text) + public static ReadOnlySpan AsBytes(this Utf8String? text) { if (text == null) return default; @@ -42,7 +43,7 @@ public static ReadOnlySpan AsBytes(this Utf8String text) /// Thrown when the specified index is not in range (<0 or >text.Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsBytes(this Utf8String text, int start) + public static ReadOnlySpan AsBytes(this Utf8String? text, int start) { if (text == null) { @@ -68,7 +69,7 @@ public static ReadOnlySpan AsBytes(this Utf8String text, int start) /// Thrown when the specified index or is not in range. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsBytes(this Utf8String text, int start, int length) + public static ReadOnlySpan AsBytes(this Utf8String? text, int start, int length) { if (text == null) { @@ -95,7 +96,7 @@ public static ReadOnlySpan AsBytes(this Utf8String text, int start, int le /// The target . /// Returns default when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsSpan(this Utf8String text) + public static ReadOnlySpan AsSpan(this Utf8String? text) { if (text == null) return default; @@ -113,7 +114,7 @@ public static ReadOnlySpan AsSpan(this Utf8String text) /// Thrown when the specified index is not in range (<0 or >text.Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsSpan(this Utf8String text, int start) + public static ReadOnlySpan AsSpan(this Utf8String? text, int start) { if (text == null) { @@ -139,7 +140,7 @@ public static ReadOnlySpan AsSpan(this Utf8String text, int start) /// Thrown when the specified index or is not in range. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan AsSpan(this Utf8String text, int start, int length) + public static ReadOnlySpan AsSpan(this Utf8String? text, int start, int length) { if (text == null) { @@ -163,7 +164,7 @@ public static ReadOnlySpan AsSpan(this Utf8String text, int start, int le /// Creates a new over the portion of the target . /// The target . /// Returns default when is null. - public static ReadOnlyMemory AsMemory(this Utf8String text) + public static ReadOnlyMemory AsMemory(this Utf8String? text) { if (text == null) return default; @@ -178,7 +179,7 @@ public static ReadOnlyMemory AsMemory(this Utf8String text) /// /// Thrown when the specified index is not in range (<0 or >text.Length). /// - public static ReadOnlyMemory AsMemory(this Utf8String text, int start) + public static ReadOnlyMemory AsMemory(this Utf8String? text, int start) { if (text == null) { @@ -196,7 +197,7 @@ public static ReadOnlyMemory AsMemory(this Utf8String text, int start) /// Creates a new over the portion of the target . /// The target . /// The index at which to begin this slice. - public static ReadOnlyMemory AsMemory(this Utf8String text, Index startIndex) + public static ReadOnlyMemory AsMemory(this Utf8String? text, Index startIndex) { if (text == null) { @@ -221,7 +222,7 @@ public static ReadOnlyMemory AsMemory(this Utf8String text, Index startIn /// /// Thrown when the specified index or is not in range. /// - public static ReadOnlyMemory AsMemory(this Utf8String text, int start, int length) + public static ReadOnlyMemory AsMemory(this Utf8String? text, int start, int length) { if (text == null) { @@ -245,7 +246,7 @@ public static ReadOnlyMemory AsMemory(this Utf8String text, int start, in /// Creates a new over the portion of the target . /// The target . /// The range used to indicate the start and length of the sliced string. - public static ReadOnlyMemory AsMemory(this Utf8String text, Range range) + public static ReadOnlyMemory AsMemory(this Utf8String? text, Range range) { if (text == null) { @@ -265,7 +266,7 @@ public static ReadOnlyMemory AsMemory(this Utf8String text, Range range) /// Creates a new over the portion of the target . /// The target . /// Returns default when is null. - public static ReadOnlyMemory AsMemoryBytes(this Utf8String text) + public static ReadOnlyMemory AsMemoryBytes(this Utf8String? text) { if (text == null) return default; @@ -280,7 +281,7 @@ public static ReadOnlyMemory AsMemoryBytes(this Utf8String text) /// /// Thrown when the specified index is not in range (<0 or >text.Length). /// - public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, int start) + public static ReadOnlyMemory AsMemoryBytes(this Utf8String? text, int start) { if (text == null) { @@ -298,7 +299,7 @@ public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, int start /// Creates a new over the portion of the target . /// The target . /// The index at which to begin this slice. - public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, Index startIndex) + public static ReadOnlyMemory AsMemoryBytes(this Utf8String? text, Index startIndex) { if (text == null) { @@ -323,7 +324,7 @@ public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, Index sta /// /// Thrown when the specified index or is not in range. /// - public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, int start, int length) + public static ReadOnlyMemory AsMemoryBytes(this Utf8String? text, int start, int length) { if (text == null) { @@ -347,7 +348,7 @@ public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, int start /// Creates a new over the portion of the target . /// The target . /// The range used to indicate the start and length of the sliced string. - public static ReadOnlyMemory AsMemoryBytes(this Utf8String text, Range range) + public static ReadOnlyMemory AsMemoryBytes(this Utf8String? text, Range range) { if (text == null) { diff --git a/src/System.Private.CoreLib/src/System/Utf8String.Construction.cs b/src/System.Private.CoreLib/src/System/Utf8String.Construction.cs index 9ecd44f3ae4a..4cf302e218dc 100644 --- a/src/System.Private.CoreLib/src/System/Utf8String.Construction.cs +++ b/src/System.Private.CoreLib/src/System/Utf8String.Construction.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -49,7 +50,7 @@ private Utf8String Ctor(ReadOnlySpan value) Utf8String newString = FastAllocate(value.Length); Buffer.Memmove(ref newString.DangerousGetMutableReference(), ref MemoryMarshal.GetReference(value), (uint)value.Length); - return Utf8Utility.ValidateAndFixupUtf8String(newString); + return Utf8Utility.ValidateAndFixupUtf8String(newString)!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } /// @@ -60,7 +61,7 @@ private Utf8String Ctor(ReadOnlySpan value) /// Invalid code unit sequences are replaced with U+FFFD in the resulting . /// [MethodImpl(MethodImplOptions.InternalCall)] - public extern Utf8String(byte[] value, int startIndex, int length); + public extern Utf8String(byte[]? value, int startIndex, int length); #if PROJECTN [DependencyReductionRoot] @@ -68,7 +69,7 @@ private Utf8String Ctor(ReadOnlySpan value) #if !CORECLR static #endif - private Utf8String Ctor(byte[] value, int startIndex, int length) => Ctor(new ReadOnlySpan(value, startIndex, length)); + private Utf8String Ctor(byte[]? value, int startIndex, int length) => Ctor(new ReadOnlySpan(value, startIndex, length)); /// /// Creates a instance from existing null-terminated UTF-8 data. @@ -135,7 +136,7 @@ private Utf8String Ctor(ReadOnlySpan value) /// Invalid code unit sequences are replaced with U+FFFD in the resulting . /// [MethodImpl(MethodImplOptions.InternalCall)] - public extern Utf8String(char[] value, int startIndex, int length); + public extern Utf8String(char[]? value, int startIndex, int length); #if PROJECTN [DependencyReductionRoot] @@ -143,7 +144,7 @@ private Utf8String Ctor(ReadOnlySpan value) #if !CORECLR static #endif - private Utf8String Ctor(char[] value, int startIndex, int length) => Ctor(new ReadOnlySpan(value, startIndex, length)); + private Utf8String Ctor(char[]? value, int startIndex, int length) => Ctor(new ReadOnlySpan(value, startIndex, length)); /// /// Creates a instance from existing null-terminated UTF-16 data. @@ -180,7 +181,7 @@ private unsafe Utf8String Ctor(char* value) /// Invalid code unit sequences are replaced with U+FFFD in the resulting . /// [MethodImpl(MethodImplOptions.InternalCall)] - public extern Utf8String(string value); + public extern Utf8String(string? value); #if PROJECTN [DependencyReductionRoot] @@ -188,7 +189,7 @@ private unsafe Utf8String Ctor(char* value) #if !CORECLR static #endif - private Utf8String Ctor(string value) => Ctor(value.AsSpan()); + private Utf8String Ctor(string? value) => Ctor(value.AsSpan()); /* * HELPER METHODS diff --git a/src/System.Private.CoreLib/src/System/Utf8String.Manipulation.cs b/src/System.Private.CoreLib/src/System/Utf8String.Manipulation.cs index 9ca72f172982..2caed617c1a7 100644 --- a/src/System.Private.CoreLib/src/System/Utf8String.Manipulation.cs +++ b/src/System.Private.CoreLib/src/System/Utf8String.Manipulation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; @@ -76,12 +77,12 @@ public Utf8String Substring(int startIndex, int length) return InternalSubstring(startIndex, length); } + // Slice intended to be used by the compiler only to provide indexer with range parameter functionality. + // Developers should be using Substring method instead. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Utf8String Substring(Range range) - { - (int start, int length) = range.GetOffsetAndLength(Length); - return Substring(start, length); - } + [ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)] + public Utf8String Slice(int startIndex, int length) => Substring(startIndex, length); + [StackTraceHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/System.Private.CoreLib/src/System/Utf8String.Searching.cs b/src/System.Private.CoreLib/src/System/Utf8String.Searching.cs index 0373cdd4fd17..e607d02a4bce 100644 --- a/src/System.Private.CoreLib/src/System/Utf8String.Searching.cs +++ b/src/System.Private.CoreLib/src/System/Utf8String.Searching.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; using System.Text; using System.Text.Unicode; diff --git a/src/System.Private.CoreLib/src/System/Utf8String.cs b/src/System.Private.CoreLib/src/System/Utf8String.cs index 855183023931..69bd196b3d09 100644 --- a/src/System.Private.CoreLib/src/System/Utf8String.cs +++ b/src/System.Private.CoreLib/src/System/Utf8String.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -13,7 +14,7 @@ namespace System /// /// Represents an immutable string of UTF-8 code units. /// - public sealed partial class Utf8String : IEquatable + public sealed partial class Utf8String : IEquatable { /* * STATIC FIELDS @@ -36,22 +37,22 @@ public sealed partial class Utf8String : IEquatable /// /// Compares two instances for equality using a comparer. /// - public static bool operator ==(Utf8String left, Utf8String right) => Equals(left, right); + public static bool operator ==(Utf8String? left, Utf8String? right) => Equals(left, right); /// /// Compares two instances for inequality using a comparer. /// - public static bool operator !=(Utf8String left, Utf8String right) => !Equals(left, right); + public static bool operator !=(Utf8String? left, Utf8String? right) => !Equals(left, right); /// /// Projects a instance as a . /// - public static explicit operator ReadOnlySpan(Utf8String value) => value.AsBytes(); + public static explicit operator ReadOnlySpan(Utf8String? value) => value.AsBytes(); /// /// Projects a instance as a . /// - public static implicit operator ReadOnlySpan(Utf8String value) => value.AsSpan(); + public static implicit operator ReadOnlySpan(Utf8String? value) => value.AsSpan(); /* * INSTANCE PROPERTIES @@ -84,25 +85,6 @@ public Char8 this[int index] } } - /// - /// Gets the at the specified position. - /// - public Char8 this[Index index] - { - get - { - // Just like String, we don't allow indexing into the null terminator itself. - - int actualIndex = index.GetOffset(Length); - return this[actualIndex]; - } - } - - /// - /// Gets a substring of this based on the provided . - /// - public Utf8String this[Range range] => Substring(range); - /* * METHODS */ @@ -129,7 +111,7 @@ internal ref byte DangerousGetMutableReference(int index) /// /// Performs an equality comparison using a comparer. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is Utf8String other && this.Equals(other); } @@ -137,7 +119,7 @@ public override bool Equals(object obj) /// /// Performs an equality comparison using a comparer. /// - public bool Equals(Utf8String value) + public bool Equals(Utf8String? value) { // First, a very quick check for referential equality. @@ -156,7 +138,7 @@ public bool Equals(Utf8String value) /// /// Compares two instances using a comparer. /// - public static bool Equals(Utf8String left, Utf8String right) + public static bool Equals(Utf8String? left, Utf8String? right) { // First, a very quick check for referential equality. @@ -198,7 +180,7 @@ public override int GetHashCode() /// Returns if is or zero length; /// otherwise. /// - public static bool IsNullOrEmpty(Utf8String value) + public static bool IsNullOrEmpty(Utf8String? value) { // Copied from String.IsNullOrEmpty. See that method for detailed comments on why this pattern is used. return (value is null || 0u >= (uint)value.Length) ? true : false; diff --git a/src/System.Private.CoreLib/src/System/Variant.cs b/src/System.Private.CoreLib/src/System/Variant.cs index 385a44ffbace..f8da7e34a742 100644 --- a/src/System.Private.CoreLib/src/System/Variant.cs +++ b/src/System.Private.CoreLib/src/System/Variant.cs @@ -11,6 +11,7 @@ ** ===========================================================*/ +#nullable enable using System; using System.Reflection; using System.Threading; @@ -27,7 +28,7 @@ internal struct Variant { //Do Not change the order of these fields. //They are mapped to the native VariantData * data structure. - private object m_objref; + private object? m_objref; private int m_data1; private int m_data2; private int m_flags; @@ -265,7 +266,7 @@ public Variant(decimal val) m_data2 = 0; } - public Variant(object obj) + public Variant(object? obj) { m_data1 = 0; m_data2 = 0; @@ -365,7 +366,7 @@ internal int CVType } } - public object ToObject() + public object? ToObject() { switch (CVType) { @@ -422,7 +423,7 @@ public object ToObject() // managed variants as an intermediate type. internal static void MarshalHelperConvertObjectToVariant(object o, ref Variant v) { - IConvertible ic = o as IConvertible; + IConvertible? ic = o as IConvertible; if (o == null) { @@ -520,7 +521,7 @@ internal static void MarshalHelperConvertObjectToVariant(object o, ref Variant v // Helper code for marshaling VARIANTS to managed objects (we use // managed variants as an intermediate type. - internal static object MarshalHelperConvertVariantToObject(ref Variant v) + internal static object? MarshalHelperConvertVariantToObject(ref Variant v) { return v.ToObject(); } diff --git a/src/System.Private.CoreLib/src/System/WeakReference.cs b/src/System.Private.CoreLib/src/System/WeakReference.cs index da0b1a284a83..70001035ec18 100644 --- a/src/System.Private.CoreLib/src/System/WeakReference.cs +++ b/src/System.Private.CoreLib/src/System/WeakReference.cs @@ -9,6 +9,7 @@ ** ===========================================================*/ +#nullable enable using System; using System.Runtime.Serialization; using System.Security; @@ -37,14 +38,14 @@ protected WeakReference() // Creates a new WeakReference that keeps track of target. // Assumes a Short Weak Reference (ie TrackResurrection is false.) // - public WeakReference(object target) + public WeakReference(object? target) : this(target, false) { } //Creates a new WeakReference that keeps track of target. // - public WeakReference(object target, bool trackResurrection) + public WeakReference(object? target, bool trackResurrection) { Create(target, trackResurrection); } @@ -56,7 +57,7 @@ protected WeakReference(SerializationInfo info, StreamingContext context) throw new ArgumentNullException(nameof(info)); } - object target = info.GetValue("TrackedObject", typeof(object)); // Do not rename (binary serialization) + object? target = info.GetValue("TrackedObject", typeof(object)); // Do not rename (binary serialization) bool trackResurrection = info.GetBoolean("TrackResurrection"); // Do not rename (binary serialization) Create(target, trackResurrection); @@ -83,7 +84,7 @@ public virtual bool TrackResurrection //Gets the Object stored in the handle if it's accessible. // Or sets it. // - public extern virtual object Target + public extern virtual object? Target { [MethodImplAttribute(MethodImplOptions.InternalCall)] get; @@ -111,7 +112,7 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void Create(object target, bool trackResurrection); + private extern void Create(object? target, bool trackResurrection); [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern bool IsTrackResurrection(); diff --git a/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs b/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs index 15f6daf07a4d..d1c75ce64385 100644 --- a/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs +++ b/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs @@ -9,6 +9,7 @@ ** ===========================================================*/ +#nullable enable using System; using System.Runtime.Serialization; using System.Security; @@ -22,7 +23,7 @@ namespace System [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // This class is sealed to mitigate security issues caused by Object::MemberwiseClone. public sealed class WeakReference : ISerializable - where T : class + where T : class? { // If you fix bugs here, please fix them in WeakReference at the same time. @@ -51,7 +52,7 @@ internal WeakReference(SerializationInfo info, StreamingContext context) throw new ArgumentNullException(nameof(info)); } - T target = (T)info.GetValue("TrackedObject", typeof(T)); // Do not rename (binary serialization) + T target = (T)info.GetValue("TrackedObject", typeof(T))!; // Do not rename (binary serialization) // TODO-NULLABLE-GENERIC bool trackResurrection = info.GetBoolean("TrackResurrection"); // Do not rename (binary serialization) Create(target, trackResurrection); diff --git a/src/System.Private.CoreLib/src/System/__Canon.cs b/src/System.Private.CoreLib/src/System/__Canon.cs index 7fbfa758bcfc..5bc4d56079e8 100644 --- a/src/System.Private.CoreLib/src/System/__Canon.cs +++ b/src/System.Private.CoreLib/src/System/__Canon.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace System diff --git a/src/System.Private.CoreLib/src/System/__ComObject.cs b/src/System.Private.CoreLib/src/System/__ComObject.cs index 0aeb39167d8d..0d1d3d147e8c 100644 --- a/src/System.Private.CoreLib/src/System/__ComObject.cs +++ b/src/System.Private.CoreLib/src/System/__ComObject.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Collections; using System.Runtime.InteropServices; using System.Runtime.InteropServices.WindowsRuntime; @@ -15,7 +16,7 @@ namespace System /// internal class __ComObject : MarshalByRefObject { - private Hashtable m_ObjectToDataMap; // Do not rename (runtime relies on this name). + private Hashtable? m_ObjectToDataMap; // Do not rename (runtime relies on this name). /// /// Default constructor - can't instantiate this directly. @@ -42,15 +43,15 @@ public override string ToString() } } - return base.ToString(); + return base.ToString()!; } /// /// Retrieves the data associated with the specified if such data exists. /// - internal object GetData(object key) + internal object? GetData(object key) { - object data = null; + object? data = null; // Synchronize access to the map. lock (this) @@ -69,7 +70,7 @@ internal object GetData(object key) /// /// Sets the data for the specified key on the current __ComObject. /// - internal bool SetData(object key, object data) + internal bool SetData(object key, object? data) { bool bAdded = false; @@ -104,7 +105,7 @@ internal void ReleaseAllData() // If the map hasn't been allocated, then there is nothing to do. if (m_ObjectToDataMap != null) { - foreach (object o in m_ObjectToDataMap.Values) + foreach (object? o in m_ObjectToDataMap.Values) { // Note: the value could be an object[] // We are fine for now as object[] doesn't implement IDisposable nor derive from __ComObject @@ -130,7 +131,7 @@ internal void ReleaseAllData() internal object GetEventProvider(RuntimeType t) { // Check to see if we already have a cached event provider for this type. - object provider = GetData(t); + object? provider = GetData(t); if (provider != null) { return provider; @@ -147,7 +148,7 @@ internal object GetEventProvider(RuntimeType t) private object CreateEventProvider(RuntimeType t) { // Create the event provider for the specified type. - object EvProvider = Activator.CreateInstance(t, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new object[] { this }, null); + object EvProvider = Activator.CreateInstance(t, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new object[] { this }, null)!; // Attempt to cache the wrapper on the object. if (!SetData(t, EvProvider)) @@ -159,7 +160,7 @@ private object CreateEventProvider(RuntimeType t) } // Another thead already cached the wrapper so use that one instead. - EvProvider = GetData(t); + EvProvider = GetData(t)!; } return EvProvider; diff --git a/src/ToolBox/SOS/Strike/sos.cpp b/src/ToolBox/SOS/Strike/sos.cpp index bf84e1d8af2d..4aacc2a2e774 100644 --- a/src/ToolBox/SOS/Strike/sos.cpp +++ b/src/ToolBox/SOS/Strike/sos.cpp @@ -795,6 +795,11 @@ namespace sos } } + GCHeap::~GCHeap() + { + delete [] mHeaps; + } + ObjectIterator GCHeap::WalkHeap(TADDR start, TADDR stop) const { return ObjectIterator(mHeaps, mNumHeaps, start, stop); diff --git a/src/ToolBox/SOS/Strike/sos.h b/src/ToolBox/SOS/Strike/sos.h index 80608dd37170..4d154ef76f6a 100644 --- a/src/ToolBox/SOS/Strike/sos.h +++ b/src/ToolBox/SOS/Strike/sos.h @@ -752,6 +752,8 @@ namespace sos */ GCHeap(); + ~GCHeap(); + /* Returns an ObjectIterator which allows you to walk the objects on the managed heap. * This ObjectIterator is valid for the duration of the GCHeap's lifetime. Note that * if you specify an address at which you wish to start walking the heap it need diff --git a/src/ToolBox/SOS/lldbplugin/services.cpp b/src/ToolBox/SOS/lldbplugin/services.cpp index f5ec14d08d2d..aeca0208425b 100644 --- a/src/ToolBox/SOS/lldbplugin/services.cpp +++ b/src/ToolBox/SOS/lldbplugin/services.cpp @@ -10,8 +10,8 @@ #define CONVERT_FROM_SIGN_EXTENDED(offset) ((ULONG_PTR)(offset)) -ULONG g_currentThreadIndex = -1; -ULONG g_currentThreadSystemId = -1; +ULONG g_currentThreadIndex = (ULONG)-1; +ULONG g_currentThreadSystemId = (ULONG)-1; char *g_coreclrDirectory; LLDBServices::LLDBServices(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject, lldb::SBProcess *process, lldb::SBThread *thread) : @@ -587,7 +587,7 @@ LLDBServices::Disassemble( size = instruction.GetByteSize(); data = instruction.GetData(target); - for (int i = 0; i < size && bufferSize > 0; i++) + for (ULONG i = 0; i < size && bufferSize > 0; i++) { byte = data.GetUnsignedInt8(error, i); if (error.Fail()) @@ -689,7 +689,7 @@ LLDBServices::GetContextStackTrace( } frame = thread.GetFrameAtIndex(0); - for (int i = 0; i < thread.GetNumFrames(); i++) + for (uint32_t i = 0; i < thread.GetNumFrames(); i++) { if (!frame.IsValid() || (cFrames > framesSize) || ((char *)currentContext > ((char *)frameContexts + frameContextsSize))) { @@ -1367,7 +1367,7 @@ LLDBServices::GetCurrentThreadId( // This is allow the a valid current TID to be returned to // workaround a bug in lldb on core dumps. - if (g_currentThreadIndex != -1) + if (g_currentThreadIndex != (ULONG)-1) { *id = g_currentThreadIndex; return S_OK; @@ -1413,7 +1413,7 @@ LLDBServices::GetCurrentThreadSystemId( // This is allow the a valid current TID to be returned to // workaround a bug in lldb on core dumps. - if (g_currentThreadSystemId != -1) + if (g_currentThreadSystemId != (ULONG)-1) { *sysId = g_currentThreadSystemId; return S_OK; @@ -1447,7 +1447,7 @@ LLDBServices::GetThreadIdBySystemId( // If we have a "fake" thread OS (system) id and a fake thread index, // we need to return fake thread index. - if (g_currentThreadSystemId == sysId && g_currentThreadIndex != -1) + if (g_currentThreadSystemId == sysId && g_currentThreadIndex != (ULONG)-1) { id = g_currentThreadIndex; } @@ -1495,7 +1495,7 @@ LLDBServices::GetThreadContextById( // If we have a "fake" thread OS (system) id and a fake thread index, // use the fake thread index to get the context. - if (g_currentThreadSystemId == threadID && g_currentThreadIndex != -1) + if (g_currentThreadSystemId == threadID && g_currentThreadIndex != (ULONG)-1) { thread = process.GetThreadByIndexID(g_currentThreadIndex); } diff --git a/src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp b/src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp index c7d6a1ba2519..67911e4d1065 100644 --- a/src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp +++ b/src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp @@ -23,7 +23,7 @@ class setsostidCommand : public lldb::SBCommandPluginInterface { if (arguments[0] == NULL) { - if (g_currentThreadSystemId == -1 || g_currentThreadIndex == -1) + if (g_currentThreadSystemId == (ULONG)-1 || g_currentThreadIndex == (ULONG)-1) { result.Printf("sos OS tid not mapped\n"); } @@ -33,8 +33,8 @@ class setsostidCommand : public lldb::SBCommandPluginInterface } } else if (strcmp(arguments[0], "-clear") == 0) { - g_currentThreadIndex = -1; - g_currentThreadSystemId = -1; + g_currentThreadIndex = (ULONG)-1; + g_currentThreadSystemId = (ULONG)-1; result.Printf("Cleared sos OS tid/index\n"); } else if (arguments[1] == NULL) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index a6b284488a9b..ebe7808ee5c6 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -2535,8 +2535,8 @@ void MethodContext::recGetArgType(CORINFO_SIG_INFO* sig, GetArgType = new LightWeightMap(); GetArgTypeValue key; - ZeroMemory(&key, sizeof(GetArgType)); // We use the input structs as a key and use memcmp to compare.. so - // we need to zero out padding too + ZeroMemory(&key, sizeof(key)); // We use the input structs as a key and use memcmp to compare.. so + // we need to zero out padding too // Only setting values for things the EE seems to pay attention to... this is necessary since some of the values // are unset and fail our precise comparisons ... key.flags = (DWORD)sig->flags; diff --git a/src/binder/textualidentityparser.cpp b/src/binder/textualidentityparser.cpp index 7cd454518770..1e2711b388cb 100644 --- a/src/binder/textualidentityparser.cpp +++ b/src/binder/textualidentityparser.cpp @@ -61,9 +61,6 @@ namespace BINDER_SPACE { const int iPublicKeyTokenLength = 8; - const int iPublicKeyMinLength = 0; - const int iPublicKeyMaxLength = 2048; - const int iVersionMax = 65535; const int iVersionParts = 4; @@ -143,10 +140,7 @@ namespace BINDER_SPACE inline BOOL ValidatePublicKey(SString &publicKey) { - - return ((publicKey.GetCount() >= (iPublicKeyMinLength * 2)) && - (publicKey.GetCount() <= (iPublicKeyMaxLength * 2)) && - ValidateHex(publicKey)); + return ValidateHex(publicKey); } const struct { diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index 12397a330ebe..ce47c14e1ba8 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -325,13 +325,14 @@ INT32 QCALLTYPE SystemNative::GetProcessorCount() BEGIN_QCALL; +#ifndef FEATURE_PAL CPUGroupInfo::EnsureInitialized(); if(CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) { processorCount = CPUGroupInfo::GetNumActiveProcessors(); } - +#endif // !FEATURE_PAL // Processor count will be 0 if CPU groups are disabled/not supported if(processorCount == 0) { @@ -355,18 +356,6 @@ INT32 QCALLTYPE SystemNative::GetProcessorCount() return processorCount; } -FCIMPL0(FC_BOOL_RET, SystemNative::HasShutdownStarted) -{ - FCALL_CONTRACT; - - // Return true if the EE has started to shutdown and is now going to - // aggressively finalize objects referred to by static variables OR - // if someone is unloading the current AppDomain AND we have started - // finalizing objects referred to by static variables. - FC_RETURN_BOOL(g_fEEShutDown & ShutDown_Finalize2); -} -FCIMPLEND - // FailFast is supported in BCL.small as internal to support failing fast in places where EEE used to be thrown. // // Static message buffer used by SystemNative::FailFast to avoid reliance on a diff --git a/src/classlibnative/bcltype/system.h b/src/classlibnative/bcltype/system.h index 803f1dfca80c..95670a382cec 100644 --- a/src/classlibnative/bcltype/system.h +++ b/src/classlibnative/bcltype/system.h @@ -69,9 +69,8 @@ class SystemNative static FCDECL3(VOID, FailFastWithExceptionAndSource, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE, StringObject* errorSourceUNSAFE); // Returns the number of logical processors that can be used by managed code - static INT32 QCALLTYPE GetProcessorCount(); + static INT32 QCALLTYPE GetProcessorCount(); - static FCDECL0(FC_BOOL_RET, HasShutdownStarted); static FCDECL0(FC_BOOL_RET, IsServerGC); #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 42aa3009ea2e..e1864c81f729 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -423,6 +423,41 @@ class ActivationContext ULONG_PTR _actCookie; }; +class ClrInstanceDetails +{ + static void * _currentClrInstance; + static unsigned int _currentAppDomainId; + +public: // static + static HRESULT GetDetails(void **clrInstance, unsigned int *appDomainId) + { + *clrInstance = _currentClrInstance; + *appDomainId = _currentAppDomainId; + return S_OK; + } + +public: + ClrInstanceDetails(void *clrInstance, unsigned int appDomainId) + { + _currentClrInstance = clrInstance; + _currentAppDomainId = appDomainId; + } + + ~ClrInstanceDetails() + { + _currentClrInstance = nullptr; + _currentAppDomainId = 0; + } +}; + +void * ClrInstanceDetails::_currentClrInstance; +unsigned int ClrInstanceDetails::_currentAppDomainId; + +extern "C" __declspec(dllexport) HRESULT __cdecl GetCurrentClrDetails(void **clrInstance, unsigned int *appDomainId) +{ + return ClrInstanceDetails::GetDetails(clrInstance, appDomainId); +} + bool TryLoadHostPolicy(StackSString& hostPolicyPath) { const WCHAR *hostpolicyName = W("hostpolicy.dll"); @@ -666,6 +701,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo { ActivationContext cxt{ log, managedAssemblyFullName.GetUnicode() }; + ClrInstanceDetails current{ host, domainId }; hr = host->ExecuteAssembly(domainId, managedAssemblyFullName, argc - 1, (argc - 1) ? &(argv[1]) : NULL, &exitCode); if (FAILED(hr)) diff --git a/src/coreclr/hosts/coreshim/CoreShim.cpp b/src/coreclr/hosts/coreshim/CoreShim.cpp index 7a5c3a1d1c5f..238e40fb87d2 100644 --- a/src/coreclr/hosts/coreshim/CoreShim.cpp +++ b/src/coreclr/hosts/coreshim/CoreShim.cpp @@ -334,6 +334,7 @@ HRESULT coreclr::CreateTpaList(_Inout_ std::string &tpaList, _In_opt_z_ const WC coreclr::coreclr(_Inout_ AutoModule hmod) : _hmod{ std::move(hmod) } + , _attached{ false } , _clrInst{ nullptr } , _appDomainId{ std::numeric_limits::max() } { @@ -349,7 +350,7 @@ coreclr::coreclr(_Inout_ AutoModule hmod) coreclr::~coreclr() { - if (_clrInst != nullptr) + if (_clrInst != nullptr && !_attached) { HRESULT hr = _shutdown(_clrInst, _appDomainId); assert(SUCCEEDED(hr)); @@ -370,6 +371,21 @@ HRESULT coreclr::Initialize( appDomainName = "CoreShim"; HRESULT hr; + + // Check if this is hosted scenario - launched via CoreRun.exe + HMODULE mod = ::GetModuleHandleW(W("CoreRun.exe")); + if (mod != NULL) + { + using GetCurrentClrDetailsFunc = HRESULT(*)(void **clrInstance, unsigned int *appDomainId); + auto getCurrentClrDetails = (GetCurrentClrDetailsFunc)::GetProcAddress(mod, "GetCurrentClrDetails"); + RETURN_IF_FAILED(getCurrentClrDetails(&_clrInst, &_appDomainId)); + if (_clrInst != nullptr) + { + _attached = true; + return S_OK; + } + } + try { const std::wstring exePathW = GetExePath(); diff --git a/src/coreclr/hosts/coreshim/CoreShim.h b/src/coreclr/hosts/coreshim/CoreShim.h index d4c8b0aa6be7..5875b457bc50 100644 --- a/src/coreclr/hosts/coreshim/CoreShim.h +++ b/src/coreclr/hosts/coreshim/CoreShim.h @@ -174,6 +174,7 @@ class coreclr private: AutoModule _hmod; + bool _attached; void *_clrInst; uint32_t _appDomainId; diff --git a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp index 1a6bf118c47f..fb155f69bb53 100644 --- a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp +++ b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp @@ -466,11 +466,6 @@ int ExecuteManagedAssembly( } } } - - if (dlclose(coreclrLib) != 0) - { - fprintf(stderr, "Warning - dlclose failed\n"); - } } else { diff --git a/src/corefx/System.Globalization.Native/pal_collation.c b/src/corefx/System.Globalization.Native/pal_collation.c index a8c94cfb71fa..b8d451730da3 100644 --- a/src/corefx/System.Globalization.Native/pal_collation.c +++ b/src/corefx/System.Globalization.Native/pal_collation.c @@ -439,11 +439,15 @@ const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t opti TCollatorMap* map = (TCollatorMap*)malloc(sizeof(TCollatorMap)); map->key = options; - void* entry = tsearch(map, &pSortHandle->collatorsPerOptionRoot, TreeComparer); - if ((*(TCollatorMap**)entry) == map) + // tfind on glibc is significantly faster than tsearch and we expect + // to hit the cache here often so it's benefitial to prefer lookup time + // over addition time + void* entry = tfind(map, &pSortHandle->collatorsPerOptionRoot, TreeComparer); + if (entry == NULL) { pCollator = CloneCollatorWithOptions(pSortHandle->regular, options, pErr); map->UCollator = pCollator; + tsearch(map, &pSortHandle->collatorsPerOptionRoot, TreeComparer); } else { diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp index 2941714a75f1..4f878cc73fa1 100644 --- a/src/debug/daccess/dacdbiimpl.cpp +++ b/src/debug/daccess/dacdbiimpl.cpp @@ -2238,7 +2238,7 @@ TypeHandle DacDbiInterfaceImpl::TypeDataWalk::FnPtrTypeArg(DebuggerIPCE_TypeArgD { // allocate space to store a list of type handles, one for the return type and one for each // of the parameter types of the function to which the FnPtr type refers. - NewHolder pInst(new TypeHandle[sizeof(TypeHandle) * pFnPtrTypeInfo->numTypeArgs]); + NewArrayHolder pInst(new TypeHandle[sizeof(TypeHandle) * pFnPtrTypeInfo->numTypeArgs]); if (ReadLoadedTypeHandles(retrieveWhich, pFnPtrTypeInfo->numTypeArgs, pInst)) { @@ -3058,7 +3058,7 @@ TypeHandle DacDbiInterfaceImpl::GetExactClassTypeHandle(DebuggerIPCE_ExpandedTyp ThrowHR(E_OUTOFMEMORY); } - NewHolder pInst(new TypeHandle[allocSize.Value()]); + NewArrayHolder pInst(new TypeHandle[allocSize.Value()]); // convert the type information for each parameter to its corresponding type handle // and store it in the list @@ -3093,7 +3093,7 @@ TypeHandle DacDbiInterfaceImpl::GetExactFnPtrTypeHandle(ArgInfoList * pArgInfo) { ThrowHR(E_OUTOFMEMORY); } - NewHolder pInst(new TypeHandle[allocSize.Value()]); + NewArrayHolder pInst(new TypeHandle[allocSize.Value()]); // convert the type information for each parameter to its corresponding type handle // and store it in the list diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index d7d90413d73f..761dec18dda1 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -9106,6 +9106,17 @@ mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt ) } #endif +#else //!FEATURE_PREJIT +//dummy implementation for dac +HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase, + LPCWSTR name, + IXCLRDataDisplay* display, + IXCLRLibrarySupport* support, + IXCLRDisassemblySupport* dis) +{ + return E_FAIL; +} +#endif //FEATURE_PREJIT /* REVISIT_TODO Mon 10/10/2005 * Here is where it gets bad. There is no DAC build of gcdump, so instead @@ -9151,16 +9162,3 @@ mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt ) #pragma warning(default:4244) #pragma warning(default:4189) #endif // __MSC_VER - - -#else //!FEATURE_PREJIT -//dummy implementation for dac -HRESULT ClrDataAccess::DumpNativeImage(CLRDATA_ADDRESS loadedBase, - LPCWSTR name, - IXCLRDataDisplay * display, - IXCLRLibrarySupport * support, - IXCLRDisassemblySupport * dis) -{ - return E_FAIL; -} -#endif //FEATURE_PREJIT diff --git a/src/debug/daccess/nidump.h b/src/debug/daccess/nidump.h index a19f61a07d75..f09bb8602b48 100644 --- a/src/debug/daccess/nidump.h +++ b/src/debug/daccess/nidump.h @@ -13,9 +13,7 @@ //some DPTR definitions that aren't elsewhere in the source typedef DPTR(const COR_SIGNATURE) PTR_CCOR_SIGNATURE; typedef DPTR(IMAGE_SECTION_HEADER) PTR_IMAGE_SECTION_HEADER; -typedef DPTR(CerNgenRootTable) PTR_CerNgenRootTable; typedef DPTR(struct CerRoot) PTR_CerRoot; -typedef DPTR(MethodContextElement) PTR_MethodContextElement; typedef DPTR(DictionaryEntry) PTR_DictionaryEntry; typedef DPTR(GuidInfo) PTR_GuidInfo; #if defined(FEATURE_COMINTEROP) @@ -186,9 +184,6 @@ class NativeImageDumper void DumpTypes( PTR_Module module ); - void DumpNgenRootTable( PTR_CerNgenRootTable table, const char * name, - unsigned offset, unsigned fieldSize ); - void DumpMethodTable( PTR_MethodTable mt, const char * name, PTR_Module module ); diff --git a/src/debug/debug-pal/win/diagnosticsipc.cpp b/src/debug/debug-pal/win/diagnosticsipc.cpp index 5467581f4a14..ef65f232a661 100644 --- a/src/debug/debug-pal/win/diagnosticsipc.cpp +++ b/src/debug/debug-pal/win/diagnosticsipc.cpp @@ -73,7 +73,7 @@ IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const return new IpcStream(hPipe); } -void IpcStream::DiagnosticsIpc::Unlink(ErrorCallback callback) +void IpcStream::DiagnosticsIpc::Unlink(ErrorCallback) { } diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp index 1536f8c9189e..36b4b3a6320b 100644 --- a/src/debug/di/process.cpp +++ b/src/debug/di/process.cpp @@ -7300,7 +7300,7 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size, if (bufferCopy != NULL) { memmove(buffer, bufferCopy, size); - delete bufferCopy; + delete [] bufferCopy; } } @@ -9578,7 +9578,7 @@ void Ls_Rs_BaseBuffer::CopyLSDataToRSWorker(ICorDebugDataTarget * pTarget) ThrowHR(E_INVALIDARG); } - NewHolder pData(new BYTE[cbCacheSize]); + NewArrayHolder pData(new BYTE[cbCacheSize]); ULONG32 cbRead; HRESULT hrRead = pTarget->ReadVirtual(PTR_TO_CORDB_ADDRESS(m_pbLS), pData, cbCacheSize , &cbRead); diff --git a/src/debug/di/rstype.cpp b/src/debug/di/rstype.cpp index a85ab0dcc48c..8b7c29482087 100644 --- a/src/debug/di/rstype.cpp +++ b/src/debug/di/rstype.cpp @@ -1549,7 +1549,7 @@ HRESULT CordbType::InitInstantiationTypeHandle(BOOL fForceInit) { ThrowHR(E_INVALIDARG); } - NewHolder pArgTypeData(new DebuggerIPCE_BasicTypeData[bufferSize.Value()]); + NewArrayHolder pArgTypeData(new DebuggerIPCE_BasicTypeData[bufferSize.Value()]); // We will have already called Init on each of the type parameters further above. Now we build a // list of type information for each type parameter. diff --git a/src/dlls/mscordac/mscordac_unixexports.src b/src/dlls/mscordac/mscordac_unixexports.src index 17d9c0bfb93e..fbe7d0090a2b 100644 --- a/src/dlls/mscordac/mscordac_unixexports.src +++ b/src/dlls/mscordac/mscordac_unixexports.src @@ -30,6 +30,8 @@ nativeStringResourceTable_mscorrc_debug #PAL__flushall #PAL_free #PAL_fwprintf +#PAL_GetLogicalCpuCountFromOS +#PAL_GetNumaProcessorNode #PAL_GetPALDirectoryW #PAL_GetResourceString #PAL_get_stdout @@ -112,7 +114,6 @@ nativeStringResourceTable_mscorrc_debug #GetCurrentDirectoryW #GetCurrentProcess #GetCurrentProcessId -#GetCurrentProcessorNumberEx #GetCurrentThreadId #GetEnvironmentVariableA #GetEnvironmentVariableW @@ -120,14 +121,11 @@ nativeStringResourceTable_mscorrc_debug #GetFileAttributesW #GetFileSize #GetFullPathNameW -#GetLogicalProcessorInformationEx #GetLastError #GetLongPathNameW #GetModuleFileNameW #GetNumaHighestNodeNumber -#GetNumaProcessorNodeEx #GetProcAddress -#GetProcessAffinityMask #GetProcessHeap #GetShortPathNameW #GetStdHandle @@ -137,7 +135,6 @@ nativeStringResourceTable_mscorrc_debug #GetTempFileNameW #GetTempPathA #GetTempPathW -#GetThreadGroupAffinity #HeapAlloc #HeapFree #HeapSetInformation @@ -173,7 +170,6 @@ nativeStringResourceTable_mscorrc_debug #SetFilePointer #SetLastError #SetErrorMode -#SetThreadGroupAffinity #Sleep #SleepEx #SwitchToThread diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc index c733f694ee76..3576b48b0471 100644 --- a/src/dlls/mscorrc/mscorrc.rc +++ b/src/dlls/mscorrc/mscorrc.rc @@ -913,8 +913,9 @@ BEGIN IDS_EE_COM_INVISIBLE_PARENT "Type '%1' has a ComVisible(false) parent '%2' in its hierarchy, therefore QueryInterface calls for IDispatch or class interfaces are disallowed." - IDS_EE_COMIMPORT_METHOD_NO_INTERFACE "Method '%1' in ComImport class '%2' must implement an interface method." IDS_EE_ATTEMPT_TO_CREATE_GENERIC_CCW "Generic types cannot be marshaled to COM interface pointers." + IDS_EE_ATTEMPT_TO_CREATE_NON_ABSTRACT_CCW "Types with non-abstract methods cannot be marshaled to COM interface pointers." + IDS_EE_COMIMPORT_METHOD_NO_INTERFACE "Method '%1' in ComImport class '%2' must implement an interface method." IDS_CLASSLOAD_BAD_METHOD_COUNT "Metadata method count does not match method enumeration length for type '%1' from assembly '%2'." IDS_CLASSLOAD_BAD_FIELD_COUNT "Metadata field count does not match field enumeration length for type '%1' from assembly '%2'." diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h index f11aa12fecb6..01982d324c59 100644 --- a/src/dlls/mscorrc/resource.h +++ b/src/dlls/mscorrc/resource.h @@ -440,7 +440,7 @@ #define IDS_EE_PROFILING_FAILURE 0x1aa8 #define IDS_EE_ATTEMPT_TO_CREATE_GENERIC_CCW 0x1aa9 - +#define IDS_EE_ATTEMPT_TO_CREATE_NON_ABSTRACT_CCW 0x1aaa #define IDS_EE_COMIMPORT_METHOD_NO_INTERFACE 0x1aab #define IDS_EE_OUT_OF_MEMORY_WITHIN_RANGE 0x1aac #define IDS_EE_ARRAY_DIMENSIONS_EXCEEDED 0x1aad diff --git a/src/gc/CMakeLists.txt b/src/gc/CMakeLists.txt index d92834bd5c32..1e59ebaa2679 100644 --- a/src/gc/CMakeLists.txt +++ b/src/gc/CMakeLists.txt @@ -84,7 +84,8 @@ if(WIN32) set (GC_LINK_LIBRARIES ${STATIC_MT_CRT_LIB} ${STATIC_MT_VCRT_LIB} - kernel32.lib) + kernel32.lib + advapi32.lib) else() set (GC_LINK_LIBRARIES) endif(WIN32) diff --git a/src/gc/env/gcenv.os.h b/src/gc/env/gcenv.os.h index 4f86cd75ea13..7fa1ba706216 100644 --- a/src/gc/env/gcenv.os.h +++ b/src/gc/env/gcenv.os.h @@ -167,11 +167,18 @@ class AffinitySet public: + static const size_t BitsetDataSize = MAX_SUPPORTED_CPUS / BitsPerBitsetEntry; + AffinitySet() { memset(m_bitset, 0, sizeof(m_bitset)); } + uintptr_t* GetBitsetData() + { + return m_bitset; + } + // Check if the set contains a processor bool Contains(size_t cpuIndex) const { @@ -275,6 +282,13 @@ class GCToOSInterface // true if it has succeeded, false if it has failed static bool VirtualCommit(void *address, size_t size, uint16_t node = NUMA_NODE_UNDEFINED); + // Reserve and Commit virtual memory range for Large Pages + // Parameters: + // size - size of the virtual memory range + // Return: + // Address of the allocated memory + static void* VirtualReserveAndCommitLargePages(size_t size); + // Decomit virtual memory range. // Parameters: // address - starting virtual address @@ -470,9 +484,6 @@ class GCToOSInterface // Is NUMA support available static bool CanEnableGCNumaAware(); - // Gets the NUMA node for the processor - static bool GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no); - // Get processor number and optionally its NUMA node number for the specified heap number // Parameters: // heap_number - heap number to get the result for diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index 0dc7e369827d..9e0356b5ff2f 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -2403,6 +2403,7 @@ void qsort1(uint8_t** low, uint8_t** high, unsigned int depth); #endif //USE_INTROSORT void* virtual_alloc (size_t size); +void* virtual_alloc (size_t size, bool use_large_pages_p); void virtual_free (void* add, size_t size); /* per heap static initialization */ @@ -2818,6 +2819,7 @@ GCSpinLock gc_heap::gc_lock; size_t gc_heap::eph_gen_starts_size = 0; heap_segment* gc_heap::segment_standby_list; +size_t gc_heap::use_large_pages_p = 0; size_t gc_heap::last_gc_index = 0; #ifdef SEG_MAPPING_TABLE size_t gc_heap::min_segment_size = 0; @@ -4263,7 +4265,7 @@ typedef struct initial_memory_details memory_details; -BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_heaps) +BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_heaps, bool use_large_pages_p) { BOOL reserve_success = FALSE; @@ -4304,7 +4306,7 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h size_t requestedMemory = memory_details.block_count * (normal_size + large_size); - uint8_t* allatonce_block = (uint8_t*)virtual_alloc (requestedMemory); + uint8_t* allatonce_block = (uint8_t*)virtual_alloc (requestedMemory, use_large_pages_p); if (allatonce_block) { g_gc_lowest_address = allatonce_block; @@ -4324,10 +4326,10 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h // try to allocate 2 blocks uint8_t* b1 = 0; uint8_t* b2 = 0; - b1 = (uint8_t*)virtual_alloc (memory_details.block_count * normal_size); + b1 = (uint8_t*)virtual_alloc (memory_details.block_count * normal_size, use_large_pages_p); if (b1) { - b2 = (uint8_t*)virtual_alloc (memory_details.block_count * large_size); + b2 = (uint8_t*)virtual_alloc (memory_details.block_count * large_size, use_large_pages_p); if (b2) { memory_details.allocation_pattern = initial_memory_details::TWO_STAGE; @@ -4360,7 +4362,7 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t num_h memory_details.block_size_normal : memory_details.block_size_large); current_block->memory_base = - (uint8_t*)virtual_alloc (block_size); + (uint8_t*)virtual_alloc (block_size, use_large_pages_p); if (current_block->memory_base == 0) { // Free the blocks that we've allocated so far @@ -4468,6 +4470,11 @@ heap_segment* get_initial_segment (size_t size, int h_number) } void* virtual_alloc (size_t size) +{ + return virtual_alloc(size, false); +} + +void* virtual_alloc (size_t size, bool use_large_pages_p) { size_t requested_size = size; @@ -4488,7 +4495,8 @@ void* virtual_alloc (size_t size) flags = VirtualReserveFlags::WriteWatch; } #endif // !FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - void* prgmem = GCToOSInterface::VirtualReserve (requested_size, card_size * card_word_width, flags); + + void* prgmem = use_large_pages_p ? GCToOSInterface::VirtualReserveAndCommitLargePages(requested_size) : GCToOSInterface::VirtualReserve(requested_size, card_size * card_word_width, flags); void *aligned_mem = prgmem; // We don't want (prgmem + size) to be right at the end of the address space @@ -5466,9 +5474,10 @@ bool gc_heap::virtual_commit (void* address, size_t size, int h_number, bool* ha } // If it's a valid heap number it means it's commiting for memory on the GC heap. - bool commit_succeeded_p = ((h_number >= 0) ? - virtual_alloc_commit_for_heap (address, size, h_number) : - GCToOSInterface::VirtualCommit(address, size)); + // In addition if large pages is enabled, we set commit_succeeded_p to true because memory is already committed. + bool commit_succeeded_p = ((h_number >= 0) ? (use_large_pages_p ? true : + virtual_alloc_commit_for_heap (address, size, h_number)) : + GCToOSInterface::VirtualCommit(address, size)); if (!commit_succeeded_p && heap_hard_limit) { @@ -8800,10 +8809,6 @@ class seg_free_spaces #endif //_DEBUG uint8_t* fit (uint8_t* old_loc, -#ifdef SHORT_PLUGS - BOOL set_padding_on_saved_p, - mark* pinned_plug_entry, -#endif //SHORT_PLUGS size_t plug_size REQD_ALIGN_AND_OFFSET_DCL) { @@ -8827,11 +8832,11 @@ class seg_free_spaces size_t plug_size_to_fit = plug_size; // best fit is only done for gen1 to gen2 and we do not pad in gen2. - int pad_in_front = 0; - -#ifdef SHORT_PLUGS - plug_size_to_fit += (pad_in_front ? Align(min_obj_size) : 0); -#endif //SHORT_PLUGS + // however we must account for requirements of large alignment. + // which may result in realignment padding. +#ifdef RESPECT_LARGE_ALIGNMENT + plug_size_to_fit += switch_alignment_size(FALSE); +#endif //RESPECT_LARGE_ALIGNMENT int plug_power2 = index_of_highest_set_bit (round_up_power2 (plug_size_to_fit + Align(min_obj_size))); ptrdiff_t i; @@ -8871,29 +8876,17 @@ class seg_free_spaces { size_t free_space_size = 0; pad = 0; -#ifdef SHORT_PLUGS - BOOL short_plugs_padding_p = FALSE; -#endif //SHORT_PLUGS + BOOL realign_padding_p = FALSE; if (bucket_free_space[i].is_plug) { mark* m = (mark*)(bucket_free_space[i].start); uint8_t* plug_free_space_start = pinned_plug (m) - pinned_len (m); - -#ifdef SHORT_PLUGS - if ((pad_in_front & USE_PADDING_FRONT) && - (((plug_free_space_start - pin_allocation_context_start_region (m))==0) || - ((plug_free_space_start - pin_allocation_context_start_region (m))>=DESIRED_PLUG_LENGTH))) - { - pad = Align (min_obj_size); - short_plugs_padding_p = TRUE; - } -#endif //SHORT_PLUGS - if (!((old_loc == 0) || same_large_alignment_p (old_loc, plug_free_space_start+pad))) + if (!((old_loc == 0) || same_large_alignment_p (old_loc, plug_free_space_start))) { - pad += switch_alignment_size (pad != 0); + pad += switch_alignment_size (FALSE); realign_padding_p = TRUE; } @@ -8920,14 +8913,6 @@ class seg_free_spaces index_of_highest_set_bit (new_free_space_size))); #endif //SIMPLE_DPRINTF -#ifdef SHORT_PLUGS - if (short_plugs_padding_p) - { - pin_allocation_context_start_region (m) = plug_free_space_start; - set_padding_in_expand (old_loc, set_padding_on_saved_p, pinned_plug_entry); - } -#endif //SHORT_PLUGS - if (realign_padding_p) { set_node_realigned (old_loc); @@ -9219,7 +9204,7 @@ heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, int h heap_segment_mem (new_segment) = start; heap_segment_used (new_segment) = start; heap_segment_reserved (new_segment) = new_pages + size; - heap_segment_committed (new_segment) = new_pages + initial_commit; + heap_segment_committed (new_segment) = (use_large_pages_p ? heap_segment_reserved(new_segment) : (new_pages + initial_commit)); init_heap_segment (new_segment); dprintf (2, ("Creating heap segment %Ix", (size_t)new_segment)); return new_segment; @@ -9310,6 +9295,8 @@ void gc_heap::reset_heap_segment_pages (heap_segment* seg) void gc_heap::decommit_heap_segment_pages (heap_segment* seg, size_t extra_space) { + if (use_large_pages_p) + return; uint8_t* page_start = align_on_page (heap_segment_allocated(seg)); size_t size = heap_segment_committed (seg) - page_start; extra_space = align_on_page (extra_space); @@ -10019,12 +10006,15 @@ HRESULT gc_heap::initialize_gc (size_t segment_size, block_count = 1; #endif //MULTIPLE_HEAPS + use_large_pages_p = false; + if (heap_hard_limit) { check_commit_cs.Initialize(); + use_large_pages_p = GCConfig::GetGCLargePages(); } - if (!reserve_initial_memory(segment_size,heap_size,block_count)) + if (!reserve_initial_memory(segment_size,heap_size,block_count,use_large_pages_p)) return E_OUTOFMEMORY; #ifdef CARD_BUNDLE @@ -14122,10 +14112,6 @@ uint8_t* gc_heap::allocate_in_expanded_heap (generation* gen, dprintf (SEG_REUSE_LOG_1, ("reallocating 0x%Ix in expanded heap, size: %Id", old_loc, size)); return bestfit_seg->fit (old_loc, -#ifdef SHORT_PLUGS - set_padding_on_saved_p, - pinned_plug_entry, -#endif //SHORT_PLUGS size REQD_ALIGN_AND_OFFSET_ARG); } @@ -19319,7 +19305,7 @@ BOOL gc_heap::background_process_mark_overflow (BOOL concurrent_p) uint8_t** tmp = new (nothrow) uint8_t* [new_size]; if (tmp) { - delete background_mark_stack_array; + delete [] background_mark_stack_array; background_mark_stack_array = tmp; background_mark_stack_array_length = new_size; background_mark_stack_tos = background_mark_stack_array; diff --git a/src/gc/gc.h b/src/gc/gc.h index 225aa6ba58bc..ecf2e1faf0ab 100644 --- a/src/gc/gc.h +++ b/src/gc/gc.h @@ -141,8 +141,6 @@ extern "C" uint32_t g_num_processors; extern VOLATILE(int32_t) g_fSuspensionPending; -extern uint32_t g_yieldProcessorScalingFactor; - ::IGCHandleManager* CreateGCHandleManager(); namespace WKS { diff --git a/src/gc/gccommon.cpp b/src/gc/gccommon.cpp index c8a15964c7d4..e882431fefb5 100644 --- a/src/gc/gccommon.cpp +++ b/src/gc/gccommon.cpp @@ -37,8 +37,6 @@ uint32_t* g_gc_card_table; VOLATILE(int32_t) g_fSuspensionPending = 0; -uint32_t g_yieldProcessorScalingFactor = 1; - #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES uint32_t* g_gc_card_bundle_table; #endif diff --git a/src/gc/gcconfig.h b/src/gc/gcconfig.h index 95252adfc20e..ea3a89eb8c8d 100644 --- a/src/gc/gcconfig.h +++ b/src/gc/gcconfig.h @@ -74,6 +74,7 @@ class GCConfigStringHolder "Specifies the name of the GC config log file") \ BOOL_CONFIG(GCNumaAware, "GCNumaAware", true, "Enables numa allocations in the GC") \ BOOL_CONFIG(GCCpuGroup, "GCCpuGroup", false, "Enables CPU groups in the GC") \ + BOOL_CONFIG(GCLargePages, "GCLargePages", false, "Enables using Large Pages in the GC") \ INT_CONFIG(HeapVerifyLevel, "HeapVerify", HEAPVERIFY_NONE, \ "When set verifies the integrity of the managed heap on entry and exit of each GC") \ INT_CONFIG(LOHCompactionMode, "GCLOHCompact", 0, "Specifies the LOH compaction mode") \ diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h index 9744eb0f38b7..4c2a2fbf5202 100644 --- a/src/gc/gcinterface.h +++ b/src/gc/gcinterface.h @@ -246,8 +246,6 @@ enum GCEventKeyword | GCEventKeyword_GCHandlePrivate | GCEventKeyword_GCHeapDump | GCEventKeyword_GCSampledObjectAllocationHigh - | GCEventKeyword_GCHeapDump - | GCEventKeyword_GCSampledObjectAllocationHigh | GCEventKeyword_GCHeapSurvivalAndMovement | GCEventKeyword_GCHeapCollect | GCEventKeyword_GCHeapAndTypeNames diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h index 9f863e6bb0d1..b13cd24fa47a 100644 --- a/src/gc/gcpriv.h +++ b/src/gc/gcpriv.h @@ -3145,6 +3145,10 @@ class gc_heap PER_HEAP_ISOLATED size_t current_total_committed_gc_own; + // This is if large pages should be used. + PER_HEAP_ISOLATED + size_t use_large_pages_p; + PER_HEAP_ISOLATED size_t last_gc_index; @@ -4559,14 +4563,3 @@ size_t gcard_of (uint8_t* object) { return (size_t)(object) / card_size; } - -inline -void YieldProcessorScalingFactor() -{ - unsigned int n = g_yieldProcessorScalingFactor; - _ASSERTE(n != 0); - do - { - YieldProcessor(); - } while (--n != 0); -} diff --git a/src/gc/sample/CMakeLists.txt b/src/gc/sample/CMakeLists.txt index 5a02d0262e13..6eb4b27f2228 100644 --- a/src/gc/sample/CMakeLists.txt +++ b/src/gc/sample/CMakeLists.txt @@ -24,6 +24,14 @@ set(SOURCES ../softwarewritewatch.cpp ) +if(WIN32) + set (GC_LINK_LIBRARIES + ${STATIC_MT_CRT_LIB} + ${STATIC_MT_VCRT_LIB} + kernel32.lib + advapi32.lib) +endif(WIN32) + if(WIN32) list(APPEND SOURCES ../windows/gcenv.windows.cpp) @@ -36,3 +44,7 @@ endif() _add_executable(gcsample ${SOURCES} ) + +if(WIN32) + target_link_libraries(gcsample ${GC_LINK_LIBRARIES}) +endif() \ No newline at end of file diff --git a/src/gc/unix/config.h.in b/src/gc/unix/config.h.in index f43709a393cf..99866cdadc50 100644 --- a/src/gc/unix/config.h.in +++ b/src/gc/unix/config.h.in @@ -9,6 +9,7 @@ #cmakedefine01 HAVE_SYS_MMAN_H #cmakedefine01 HAVE_PTHREAD_THREADID_NP #cmakedefine01 HAVE_PTHREAD_GETTHREADID_NP +#cmakedefine01 HAVE_MAP_HUGETLB #cmakedefine01 HAVE_SCHED_GETCPU #cmakedefine01 HAVE_NUMA_H #cmakedefine01 HAVE_VM_ALLOCATE diff --git a/src/gc/unix/configure.cmake b/src/gc/unix/configure.cmake index 7eb9053bcaed..2e317666127f 100644 --- a/src/gc/unix/configure.cmake +++ b/src/gc/unix/configure.cmake @@ -24,6 +24,15 @@ check_cxx_source_compiles(" } " HAVE_PTHREAD_GETTHREADID_NP) +check_cxx_source_compiles(" + #include + + int main() + { + return MAP_HUGETLB; + } + " HAVE_MAP_HUGETLB) + check_cxx_source_runs(" #include diff --git a/src/gc/unix/gcenv.unix.cpp b/src/gc/unix/gcenv.unix.cpp index 07706d722711..edddee16ce24 100644 --- a/src/gc/unix/gcenv.unix.cpp +++ b/src/gc/unix/gcenv.unix.cpp @@ -55,14 +55,41 @@ #include "globals.h" #include "cgroup.h" +#if HAVE_NUMA_H + +#include +#include +#include + +// List of all functions from the numa library that are used +#define FOR_ALL_NUMA_FUNCTIONS \ + PER_FUNCTION_BLOCK(mbind) \ + PER_FUNCTION_BLOCK(numa_available) \ + PER_FUNCTION_BLOCK(numa_max_node) \ + PER_FUNCTION_BLOCK(numa_node_of_cpu) + +// Declare pointers to all the used numa functions +#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +// Redefine all calls to numa functions as calls through pointers that are set +// to the functions of libnuma in the initialization. +#define mbind(...) mbind_ptr(__VA_ARGS__) +#define numa_available() numa_available_ptr() +#define numa_max_node() numa_max_node_ptr() +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) + +#endif // HAVE_NUMA_H + #if defined(_ARM_) || defined(_ARM64_) #define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF #else #define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_ONLN #endif -// The cached number of logical CPUs observed. -static uint32_t g_logicalCpuCount = 0; +// The cached total number of CPUs that can be used in the OS. +static uint32_t g_totalCpuCount = 0; // The cached number of CPUs available for the current process. static uint32_t g_currentProcessCpuCount = 0; @@ -109,6 +136,74 @@ uint32_t g_pageSizeUnixInl = 0; AffinitySet g_processAffinitySet; +#if HAVE_CPUSET_T +typedef cpuset_t cpu_set_t; +#endif + +// The highest NUMA node available +int g_highestNumaNode = 0; +// Is numa available +bool g_numaAvailable = false; + +void* g_numaHandle = nullptr; + +#if HAVE_NUMA_H +#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK +#endif // HAVE_NUMA_H + + +// Initialize data structures for getting and setting thread affinities to processors and +// querying NUMA related processor information. +// On systems with no NUMA support, it behaves as if there was a single NUMA node with +// a single group of processors. +void NUMASupportInitialize() +{ +#if HAVE_NUMA_H + g_numaHandle = dlopen("libnuma.so", RTLD_LAZY); + if (g_numaHandle == 0) + { + g_numaHandle = dlopen("libnuma.so.1", RTLD_LAZY); + } + if (g_numaHandle != 0) + { + dlsym(g_numaHandle, "numa_allocate_cpumask"); +#define PER_FUNCTION_BLOCK(fn) \ + fn##_ptr = (decltype(fn)*)dlsym(g_numaHandle, #fn); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + + if (numa_available() == -1) + { + dlclose(g_numaHandle); + } + else + { + g_numaAvailable = true; + g_highestNumaNode = numa_max_node(); + } + } +#endif // HAVE_NUMA_H + if (!g_numaAvailable) + { + // No NUMA + g_highestNumaNode = 0; + } +} + +// Cleanup of the NUMA support data structures +void NUMASupportCleanup() +{ +#if HAVE_NUMA_H + if (g_numaAvailable) + { + dlclose(g_numaHandle); + } +#endif // HAVE_NUMA_H +} + // Initialize the interface implementation // Return: // true if it has succeeded, false if it has failed @@ -125,7 +220,7 @@ bool GCToOSInterface::Initialize() return false; } - g_logicalCpuCount = cpuCount; + g_totalCpuCount = cpuCount; // // support for FlusProcessWriteBuffers @@ -194,7 +289,7 @@ bool GCToOSInterface::Initialize() if (st == 0) { - for (size_t i = 0; i < g_logicalCpuCount; i++) + for (size_t i = 0; i < g_totalCpuCount; i++) { if (CPU_ISSET(i, &cpuSet)) { @@ -212,15 +307,23 @@ bool GCToOSInterface::Initialize() #else // HAVE_SCHED_GETAFFINITY - g_currentProcessCpuCount = g_logicalCpuCount; + g_currentProcessCpuCount = g_totalCpuCount; - for (size_t i = 0; i < g_logicalCpuCount; i++) + for (size_t i = 0; i < g_totalCpuCount; i++) { g_processAffinitySet.Add(i); } #endif // HAVE_SCHED_GETAFFINITY + uint32_t cpuLimit; + if (GetCpuLimit(&cpuLimit) && cpuLimit < g_currentProcessCpuCount) + { + g_currentProcessCpuCount = cpuLimit; + } + + NUMASupportInitialize(); + return true; } @@ -235,6 +338,7 @@ void GCToOSInterface::Shutdown() munmap(g_helperPage, OS_PAGE_SIZE); CleanupCGroup(); + NUMASupportCleanup(); } // Get numeric id of the current thread if possible on the @@ -379,7 +483,7 @@ void GCToOSInterface::YieldThread(uint32_t switchCount) // flags - flags to control special settings like write watching // Return: // Starting virtual address of the reserved range -void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags) +static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags, uint32_t hugePagesFlag = 0) { assert(!(flags & VirtualReserveFlags::WriteWatch) && "WriteWatch not supported on Unix"); if (alignment == 0) @@ -388,7 +492,7 @@ void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t fl } size_t alignedSize = size + (alignment - OS_PAGE_SIZE); - void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); + void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, MAP_ANON | MAP_PRIVATE | hugePagesFlag, -1, 0); if (pRetVal != NULL) { @@ -413,6 +517,18 @@ void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t fl return pRetVal; } +// Reserve virtual memory range. +// Parameters: +// size - size of the virtual memory range +// alignment - requested memory alignment, 0 means no specific alignment requested +// flags - flags to control special settings like write watching +// Return: +// Starting virtual address of the reserved range +void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags) +{ + return VirtualReserveInner(size, alignment, flags); +} + // Release virtual memory range previously reserved using VirtualReserve // Parameters: // address - starting virtual address @@ -426,6 +542,28 @@ bool GCToOSInterface::VirtualRelease(void* address, size_t size) return (ret == 0); } +// Commit virtual memory range. +// Parameters: +// size - size of the virtual memory range +// Return: +// Starting virtual address of the committed range +void* GCToOSInterface::VirtualReserveAndCommitLargePages(size_t size) +{ +#if HAVE_MAP_HUGETLB + uint32_t largePagesFlag = MAP_HUGETLB; +#else + uint32_t largePagesFlag = 0; +#endif + + void* pRetVal = VirtualReserveInner(size, OS_PAGE_SIZE, 0, largePagesFlag); + if (VirtualCommit(pRetVal, size, NUMA_NODE_UNDEFINED)) + { + return pRetVal; + } + + return nullptr; +} + // Commit virtual memory range. It must be part of a range reserved using VirtualReserve. // Parameters: // address - starting virtual address @@ -434,8 +572,29 @@ bool GCToOSInterface::VirtualRelease(void* address, size_t size) // true if it has succeeded, false if it has failed bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node) { - assert(node == NUMA_NODE_UNDEFINED && "Numa allocation is not ported to local GC on unix yet"); - return mprotect(address, size, PROT_WRITE | PROT_READ) == 0; + bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0; + +#if HAVE_NUMA_H + if (success && g_numaAvailable && (node != NUMA_NODE_UNDEFINED)) + { + if ((int)node <= g_highestNumaNode) + { + int usedNodeMaskBits = g_highestNumaNode + 1; + int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); + unsigned long nodeMask[nodeMaskLength]; + memset(nodeMask, 0, sizeof(nodeMask)); + + int index = node / sizeof(unsigned long); + nodeMask[index] = ((unsigned long)1) << (node & (sizeof(unsigned long) - 1)); + + int st = mbind(address, size, MPOL_PREFERRED, nodeMask, usedNodeMaskBits, 0); + assert(st == 0); + // If the mbind fails, we still return the allocated memory since the node is just a hint + } + } +#endif // HAVE_NUMA_H + + return success; } // Decomit virtual memory range. @@ -736,18 +895,12 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() { // Calculated in GCToOSInterface::Initialize using // sysconf(_SC_NPROCESSORS_ONLN) - return g_logicalCpuCount; + return g_totalCpuCount; } bool GCToOSInterface::CanEnableGCNumaAware() { - return false; -} - -bool GCToOSInterface::GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no) -{ - assert(!"Numa has not been ported to local GC for unix"); - return false; + return g_numaAvailable; } // Get processor number and optionally its NUMA node number for the specified heap number @@ -762,22 +915,21 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n bool success = false; uint16_t availableProcNumber = 0; - for (size_t procNumber = 0; procNumber < g_logicalCpuCount; procNumber++) + for (size_t procNumber = 0; procNumber < g_totalCpuCount; procNumber++) { if (g_processAffinitySet.Contains(procNumber)) { if (availableProcNumber == heap_number) { *proc_no = procNumber; - +#if HAVE_NUMA_H if (GCToOSInterface::CanEnableGCNumaAware()) { - if (!GCToOSInterface::GetNumaProcessorNode(procNumber, node_no)) - { - *node_no = NUMA_NODE_UNDEFINED; - } + int result = numa_node_of_cpu(procNumber); + *node_no = (result >= 0) ? (uint16_t)result : NUMA_NODE_UNDEFINED; } else +#endif // HAVE_NUMA_H { *node_no = NUMA_NODE_UNDEFINED; } diff --git a/src/gc/windows/gcenv.windows.cpp b/src/gc/windows/gcenv.windows.cpp index fa13e544f565..5f6a0ff2916f 100644 --- a/src/gc/windows/gcenv.windows.cpp +++ b/src/gc/windows/gcenv.windows.cpp @@ -27,6 +27,8 @@ static size_t g_RestrictedPhysicalMemoryLimit = (size_t)UINTPTR_MAX; // memory on the machine/in the container, we need to restrict by the VM. static bool g_UseRestrictedVirtualMemory = false; +static bool g_SeLockMemoryPrivilegeAcquired = false; + static AffinitySet g_processAffinitySet; typedef BOOL (WINAPI *PIS_PROCESS_IN_JOB)(HANDLE processHandle, HANDLE jobHandle, BOOL* result); @@ -114,6 +116,42 @@ DWORD LCM(DWORD u, DWORD v) } #endif +bool InitLargePagesPrivilege() +{ + TOKEN_PRIVILEGES tp; + LUID luid; + if (!LookupPrivilegeValueW(nullptr, SE_LOCK_MEMORY_NAME, &luid)) + { + return false; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + HANDLE token; + if (!OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) + { + return false; + } + + BOOL retVal = AdjustTokenPrivileges(token, FALSE, &tp, 0, nullptr, 0); + DWORD gls = GetLastError(); + CloseHandle(token); + + if (!retVal) + { + return false; + } + + if (gls != 0) + { + return false; + } + + return true; +} + bool InitCPUGroupInfoArray() { #if (defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)) @@ -699,6 +737,31 @@ bool GCToOSInterface::VirtualRelease(void* address, size_t size) return !!::VirtualFree(address, 0, MEM_RELEASE); } +// Commit virtual memory range. +// Parameters: +// size - size of the virtual memory range +// Return: +// Starting virtual address of the committed range +void* GCToOSInterface::VirtualReserveAndCommitLargePages(size_t size) +{ + void* pRetVal = nullptr; + + if (!g_SeLockMemoryPrivilegeAcquired) + { + if (!InitLargePagesPrivilege()) + { + return nullptr; + } + + g_SeLockMemoryPrivilegeAcquired = true; + } + + SIZE_T largePageMinimum = GetLargePageMinimum(); + size = (size + (largePageMinimum - 1)) & ~(largePageMinimum - 1); + + return ::VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); +} + // Commit virtual memory range. It must be part of a range reserved using VirtualReserve. // Parameters: // address - starting virtual address @@ -1223,19 +1286,6 @@ bool GCToOSInterface::CanEnableGCNumaAware() return g_fEnableGCNumaAware; } -bool GCToOSInterface::GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no) -{ - GroupProcNo groupProcNo(proc_no); - - PROCESSOR_NUMBER procNumber; - procNumber.Group = groupProcNo.GetGroup(); - procNumber.Number = (BYTE)groupProcNo.GetProcIndex(); - procNumber.Reserved = 0; - - assert(g_fEnableGCNumaAware); - return ::GetNumaProcessorNodeEx(&procNumber, node_no) != FALSE; -} - // Get processor number and optionally its NUMA node number for the specified heap number // Parameters: // heap_number - heap number to get the result for @@ -1247,53 +1297,66 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n { bool success = false; - if (CanEnableGCCPUGroups()) + // Locate heap_number-th available processor + uint16_t procIndex; + size_t cnt = heap_number; + for (uint16_t i = 0; i < GCToOSInterface::GetTotalProcessorCount(); i++) { - uint16_t gn, gpn; - GetGroupForProcessor((uint16_t)heap_number, &gn, &gpn); - - *proc_no = GroupProcNo(gn, gpn).GetCombinedValue(); - - if (GCToOSInterface::CanEnableGCNumaAware()) + if (g_processAffinitySet.Contains(i)) { - if (!GCToOSInterface::GetNumaProcessorNode(*proc_no, node_no)) + if (cnt == 0) { - *node_no = NUMA_NODE_UNDEFINED; + procIndex = i; + success = true; + break; } + + cnt--; + } + } + + if (success) + { + WORD gn, gpn; + + if (CanEnableGCCPUGroups()) + { + GetGroupForProcessor(procIndex, &gn, &gpn); } else - { // no numa setting, each cpu group is treated as a node - *node_no = gn; + { + gn = GroupProcNo::NoGroup; + gpn = procIndex; } - success = true; - } - else - { - int bit_number = 0; - uint8_t proc_number = 0; - for (uintptr_t mask = 1; mask != 0; mask <<= 1) + GroupProcNo groupProcNo(gn, gpn); + *proc_no = groupProcNo.GetCombinedValue(); + + if (GCToOSInterface::CanEnableGCNumaAware()) { - if (g_processAffinitySet.Contains(proc_number)) + PROCESSOR_NUMBER procNumber; + + if (CanEnableGCCPUGroups()) { - if (bit_number == heap_number) - { - *proc_no = GroupProcNo(GroupProcNo::NoGroup, proc_number).GetCombinedValue(); + procNumber.Group = gn; + } + else + { + // Get the current processor group + GetCurrentProcessorNumberEx(&procNumber); + } - if (GCToOSInterface::CanEnableGCNumaAware()) - { - if (!GCToOSInterface::GetNumaProcessorNode(proc_number, node_no)) - { - *node_no = NUMA_NODE_UNDEFINED; - } - } + procNumber.Number = (BYTE)gpn; + procNumber.Reserved = 0; - success = true; - break; - } - bit_number++; + if (!GetNumaProcessorNodeEx(&procNumber, node_no)) + { + *node_no = NUMA_NODE_UNDEFINED; } - proc_number++; + } + else + { // no numa setting, each cpu group is treated as a node + *node_no = groupProcNo.GetGroup(); } } diff --git a/src/ilasm/assembler.cpp b/src/ilasm/assembler.cpp index 93198a521d01..38d83d083e29 100644 --- a/src/ilasm/assembler.cpp +++ b/src/ilasm/assembler.cpp @@ -1780,7 +1780,7 @@ mdToken Assembler::MakeMemberRef(mdToken cr, __in __nullterminated char* pszMemb } } //if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,mr)); - delete pszMemberName; + delete [] pszMemberName; delete sig; } return mr; @@ -2164,7 +2164,7 @@ void Assembler::EmitBytes(BYTE *p, unsigned len) memcpy(pb,m_pOutputBuffer,m_CurPC); - delete m_pOutputBuffer; + delete [] m_pOutputBuffer; m_pOutputBuffer = pb; m_pCurOutputPos = &m_pOutputBuffer[m_CurPC]; m_pEndOutputPos = &m_pOutputBuffer[newlen]; diff --git a/src/inc/MSCOREE.IDL b/src/inc/MSCOREE.IDL index 93e404281669..ce368f3f80a6 100644 --- a/src/inc/MSCOREE.IDL +++ b/src/inc/MSCOREE.IDL @@ -204,7 +204,6 @@ typedef enum // Stop bypasses finalizer run. eFastExitProcess, eRudeExitProcess, - eDisableRuntime, MaxPolicyAction } EPolicyAction; diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h index c8f7461d8784..61258ae09c9e 100644 --- a/src/inc/clrconfigvalues.h +++ b/src/inc/clrconfigvalues.h @@ -110,11 +110,6 @@ CONFIG_DWORD_INFO(INTERNAL_ADTakeDHSnapShot, W("ADTakeDHSnapShot"), 0, "Supersed CONFIG_DWORD_INFO(INTERNAL_ADTakeSnapShot, W("ADTakeSnapShot"), 0, "Superseded by test hooks") CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_EnableFullDebug, W("EnableFullDebug"), "Heavy-weight checking for AD boundary violations (AD leaks)") -// For the proposal and discussion on why finalizers are not run on shutdown by default anymore in CoreCLR, see the API review: -// https://github.com/dotnet/corefx/issues/5205 -#define DEFAULT_FinalizeOnShutdown (0) -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_FinalizeOnShutdown, W("FinalizeOnShutdown"), DEFAULT_FinalizeOnShutdown, "When enabled, on shutdown, blocks all user threads and calls finalizers for all finalizable objects, including live objects") - /// /// ARM /// @@ -150,7 +145,6 @@ CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDumpToken, W("BreakOnDumpToken"), 0xfffffff RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnEELoad, W("BreakOnEELoad"), 0, "", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO(INTERNAL_BreakOnEEShutdown, W("BreakOnEEShutdown"), 0, "") CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnExceptionInGetThrowable, W("BreakOnExceptionInGetThrowable"), 0, "", CLRConfig::REGUTIL_default) -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BreakOnFinalizeTimeOut, W("BreakOnFinalizeTimeOut"), 0, "Triggers a debug break on the finalizer thread when it has exceeded the maximum wait time") CONFIG_DWORD_INFO(INTERNAL_BreakOnFindMethod, W("BreakOnFindMethod"), 0, "Breaks in findMethodInternal when it searches for the specified token.") CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnFirstPass, W("BreakOnFirstPass"), 0, "", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnHR, W("BreakOnHR"), 0, "Debug.cpp, IfFailxxx use this macro to stop if hr matches ", CLRConfig::REGUTIL_default) @@ -158,7 +152,6 @@ CONFIG_STRING_INFO(INTERNAL_BreakOnInstantiation, W("BreakOnInstantiation"), "Ve CONFIG_STRING_INFO(INTERNAL_BreakOnInteropStubSetup, W("BreakOnInteropStubSetup"), "Throws an assert when marshaling stub for the given method is about to be built.") CONFIG_STRING_INFO_EX(INTERNAL_BreakOnInteropVTableBuild, W("BreakOnInteropVTableBuild"), "Specifies a type name for which an assert should be thrown when building interop v-table.", CLRConfig::REGUTIL_default) CONFIG_STRING_INFO(INTERNAL_BreakOnMethodName, W("BreakOnMethodName"), "Very useful for debugging method override placement code.") -RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnNGenRegistryAccessCount, W("BreakOnNGenRegistryAccessCount"), 0, "Breaks on the Nth' root store write", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnNotify, W("BreakOnNotify"), 0, "", CLRConfig::REGUTIL_default) RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnRetailAssert, W("BreakOnRetailAssert"), 0, "Used for debugging \"retail\" asserts (fatal errors)", CLRConfig::REGUTIL_default) CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnSecondPass, W("BreakOnSecondPass"), 0, "", CLRConfig::REGUTIL_default) @@ -330,6 +323,7 @@ RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimit, W("GCHeapHardLimit"), "Specifies the maximum commit size for the GC heap") RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimitPercent, W("GCHeapHardLimitPercent"), "Specifies the GC heap usage as a percentage of the total memory") RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCHeapAffinitizeRanges, W("GCHeapAffinitizeRanges"), "Specifies list of processors for Server GC threads. The format is a comma separated list of processor numbers or ranges of processor numbers. Example: 1,3,5,7-9,12") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCLargePages, W("GCLargePages"), "Specifies whether large pages should be used when a heap hard limit is set") /// /// IBC diff --git a/src/inc/corcompile.h b/src/inc/corcompile.h index 38ae5c1ede65..5f39c65f79f6 100644 --- a/src/inc/corcompile.h +++ b/src/inc/corcompile.h @@ -18,10 +18,6 @@ #ifndef _COR_COMPILE_H_ #define _COR_COMPILE_H_ -#ifndef FEATURE_PREJIT -#error FEATURE_PREJIT is required for this file -#endif // FEATURE_PREJIT - #if !defined(_TARGET_X86_) || defined(FEATURE_PAL) #ifndef WIN64EXCEPTIONS #define WIN64EXCEPTIONS diff --git a/src/inc/corpriv.h b/src/inc/corpriv.h index 81143e6019de..07be47c38cdb 100644 --- a/src/inc/corpriv.h +++ b/src/inc/corpriv.h @@ -96,10 +96,7 @@ enum MDInternalImportFlags MDInternalImport_TrustedNativeImage = 2, // The image is a native image, and so its format can be trusted MDInternalImport_ILMetaData = 4, // Open the IL metadata, even if this is a native image MDInternalImport_TrustedNativeImage_and_IL = MDInternalImport_TrustedNativeImage | MDInternalImport_ILMetaData, - MDInternalImport_NativeImageInstall = 0x100, // The image is a native image that is being installed into NIC #endif - MDInternalImport_CheckLongPath =8, // also check long version of the path - MDInternalImport_CheckShortPath =0x10, // also check long version of the path MDInternalImport_OnlyLookInCache =0x20, // Only look in the cache. (If the cache does not have the image already loaded, return NULL) }; // enum MDInternalImportFlags diff --git a/src/inc/daccess.h b/src/inc/daccess.h index 71a7d01344c3..e4deab920774 100644 --- a/src/inc/daccess.h +++ b/src/inc/daccess.h @@ -620,8 +620,10 @@ typedef struct _DacGlobals ULONG fn__ThePreStubPatchLabel; ULONG fn__PrecodeFixupThunk; +#ifdef FEATURE_PREJIT ULONG fn__StubDispatchFixupStub; - ULONG fn__StubDispatchFixupPatchLabel;; + ULONG fn__StubDispatchFixupPatchLabel; +#endif #ifdef FEATURE_COMINTEROP ULONG fn__Unknown_AddRef; ULONG fn__Unknown_AddRefSpecial; diff --git a/src/inc/formattype.cpp b/src/inc/formattype.cpp index 3de456ecc5c7..fcbfadf6aeb4 100644 --- a/src/inc/formattype.cpp +++ b/src/inc/formattype.cpp @@ -86,7 +86,7 @@ static void appendStrNum(CQuickBytes *out, int num) { appendStr(out, buff); } -const PCCOR_SIGNATURE PrettyPrintSignature( +PCCOR_SIGNATURE PrettyPrintSignature( PCCOR_SIGNATURE typePtr, // type to convert, unsigned typeLen, // the lenght of 'typePtr' const char* name, // can be "", the name of the method for this sig 0 means local var sig @@ -184,7 +184,7 @@ const char* PrettyPrintSig( // Converts a com signature to a printable signature. // Note that return value is pointing at the CQuickBytes buffer, -const PCCOR_SIGNATURE PrettyPrintSignature( +PCCOR_SIGNATURE PrettyPrintSignature( PCCOR_SIGNATURE typePtr, // type to convert, unsigned typeLen, // the lenght of 'typePtr' const char* name, // can be "", the name of the method for this sig 0 means local var sig diff --git a/src/inc/jithelpers.h b/src/inc/jithelpers.h index 2b362a779f3b..d7a82286cae2 100644 --- a/src/inc/jithelpers.h +++ b/src/inc/jithelpers.h @@ -298,7 +298,11 @@ JITHELPER(CORINFO_HELP_EE_PINVOKE_FIXUP, NDirectImportThunk, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#ifdef FEATURE_PREJIT JITHELPER(CORINFO_HELP_EE_VSD_FIXUP, StubDispatchFixupStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_EE_VSD_FIXUP, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#endif JITHELPER(CORINFO_HELP_EE_EXTERNAL_FIXUP, ExternalMethodFixupStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_EE_VTABLE_FIXUP, VirtualMethodFixupStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) diff --git a/src/inc/outstring.h b/src/inc/outstring.h index 5cf0236350c4..167ef9ad151a 100644 --- a/src/inc/outstring.h +++ b/src/inc/outstring.h @@ -36,7 +36,7 @@ class OutString { end = &start[initialAlloc]; } - ~OutString() { delete start; } + ~OutString() { delete [] start; } // shortcut for printing decimal OutString& operator<<(int i) { return(dec(i)); } diff --git a/src/inc/pedecoder.h b/src/inc/pedecoder.h index 91990d28921e..37051d96fd46 100644 --- a/src/inc/pedecoder.h +++ b/src/inc/pedecoder.h @@ -38,14 +38,7 @@ #include "cor.h" #include "corhdr.h" -#ifdef FEATURE_PREJIT #include "corcompile.h" -#else // FEATURE_PREJIT -typedef DPTR(struct COR_ILMETHOD) PTR_COR_ILMETHOD; -struct CORCOMPILE_HEADER { int dummy_field; }; -typedef DPTR(struct CORCOMPILE_HEADER) PTR_CORCOMPILE_HEADER; -#define CORCOMPILE_IS_POINTER_TAGGED(fixup) (false) -#endif // FEATURE_PREJIT #include "readytorun.h" typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER; @@ -305,6 +298,8 @@ class PEDecoder // Debug directory access, returns NULL if no such entry PTR_IMAGE_DEBUG_DIRECTORY GetDebugDirectoryEntry(UINT index) const; + PTR_CVOID GetNativeManifestMetadata(COUNT_T* pSize = NULL) const; + #ifdef FEATURE_PREJIT CHECK CheckNativeHeaderVersion() const; @@ -322,7 +317,6 @@ class PEDecoder PCODE GetNativeColdCode(COUNT_T * pSize = NULL) const; CORCOMPILE_METHOD_PROFILE_LIST *GetNativeProfileDataList(COUNT_T *pSize = NULL) const; - PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL) const; const void *GetNativePreferredBase() const; BOOL GetNativeILHasSecurityDirectory() const; BOOL GetNativeILIsIbcOptimized() const; diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h index 5b222b1ab969..cf4b8ddf1293 100644 --- a/src/inc/utilcode.h +++ b/src/inc/utilcode.h @@ -1331,10 +1331,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, // Allocate free memory with specific alignment // LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment); - -//****************************************************************************** -// Returns the number of processors that a process has been configured to run on -//****************************************************************************** + class NumaNodeInfo { private: @@ -1350,10 +1347,16 @@ class NumaNodeInfo static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size, DWORD allocType, DWORD prot, DWORD node); +#ifndef FEATURE_PAL static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no); +#else // !FEATURE_PAL + static BOOL GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no); +#endif // !FEATURE_PAL #endif }; +#ifndef FEATURE_PAL + struct CPU_Group_Info { WORD nr_active; // at most 64 @@ -1413,9 +1416,15 @@ class CPUGroupInfo } }; -int GetCurrentProcessCpuCount(); DWORD_PTR GetCurrentProcessCpuMask(); +#endif // !FEATURE_PAL + +//****************************************************************************** +// Returns the number of processors that a process has been configured to run on +//****************************************************************************** +int GetCurrentProcessCpuCount(); + uint32_t GetOsPageSize(); diff --git a/src/jit/CMakeLists.txt b/src/jit/CMakeLists.txt index 013b8974ed67..4334cd8ee254 100644 --- a/src/jit/CMakeLists.txt +++ b/src/jit/CMakeLists.txt @@ -275,7 +275,7 @@ else() clr_unknown_arch() endif() -set( SOURCES +set(SOURCES ${JIT_SOURCES} ${JIT_HEADERS} ${JIT_RESOURCES} @@ -291,34 +291,19 @@ convert_to_absolute_path(JIT_ARM_SOURCES ${JIT_ARM_SOURCES}) convert_to_absolute_path(JIT_I386_SOURCES ${JIT_I386_SOURCES}) convert_to_absolute_path(JIT_ARM64_SOURCES ${JIT_ARM64_SOURCES}) + if(WIN32) add_precompiled_header(jitpch.h ../jitpch.cpp SOURCES) - - # Create .def file containing a list of exports preceeded by - # 'EXPORTS'. The file "ClrJit.exports" already contains the list, so we - # massage it into the correct format here to create "ClrJit.exports.def". + set(CLRJIT_EXPORTS ${CMAKE_CURRENT_LIST_DIR}/ClrJit.exports) set(JIT_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/ClrJit.exports.def) - set(JIT_EXPORTS_FILE_TEMP ${JIT_EXPORTS_FILE}.txt) - file(READ "ClrJit.exports" exports_list) - file(WRITE ${JIT_EXPORTS_FILE_TEMP} "LIBRARY CLRJIT\n") - file(APPEND ${JIT_EXPORTS_FILE_TEMP} "EXPORTS\n") - file(APPEND ${JIT_EXPORTS_FILE_TEMP} ${exports_list}) - - # Copy the file only if it has changed. - execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${JIT_EXPORTS_FILE_TEMP} ${JIT_EXPORTS_FILE}) + preprocess_def_file (${CLRJIT_EXPORTS} ${JIT_EXPORTS_FILE}) set(SHARED_LIB_SOURCES ${SOURCES} ${JIT_EXPORTS_FILE}) else() - set(JIT_EXPORTS_IN_FILE ${CMAKE_CURRENT_BINARY_DIR}/clrjit.exports.in) - file(READ "${CMAKE_CURRENT_LIST_DIR}/ClrJit.exports" jit_exports) - file(READ "${CMAKE_CURRENT_LIST_DIR}/ClrJit.PAL.exports" pal_exports) - file(WRITE ${JIT_EXPORTS_IN_FILE} ${jit_exports}) - file(APPEND ${JIT_EXPORTS_IN_FILE} "\n") - file(APPEND ${JIT_EXPORTS_IN_FILE} ${pal_exports}) + set(CLRJIT_EXPORTS ${CMAKE_CURRENT_LIST_DIR}/ClrJit.PAL.exports) set(JIT_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/clrjit.exports) - generate_exports_file(${JIT_EXPORTS_IN_FILE} ${JIT_EXPORTS_FILE}) + generate_exports_file(${CLRJIT_EXPORTS} ${JIT_EXPORTS_FILE}) if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD) # This is required to force using our own PAL, not one that we are loaded with. diff --git a/src/jit/ClrJit.PAL.exports b/src/jit/ClrJit.PAL.exports index c6b4e8ec5772..f53923fa68c8 100644 --- a/src/jit/ClrJit.PAL.exports +++ b/src/jit/ClrJit.PAL.exports @@ -1,3 +1,6 @@ +getJit +jitStartup +sxsJitStartup DllMain PAL_RegisterModule PAL_UnregisterModule diff --git a/src/jit/ClrJit.exports b/src/jit/ClrJit.exports index 0126e63b4d3f..60a223bab183 100644 --- a/src/jit/ClrJit.exports +++ b/src/jit/ClrJit.exports @@ -1,3 +1,8 @@ -getJit -jitStartup -sxsJitStartup +; Licensed to the .NET Foundation under one or more agreements. +; The .NET Foundation licenses this file to you under the MIT license. +; See the LICENSE file in the project root for more information. + +EXPORTS + getJit + jitStartup + sxsJitStartup diff --git a/src/jit/armelnonjit/CMakeLists.txt b/src/jit/armelnonjit/CMakeLists.txt index 6bfde4c8fa10..cccba304da05 100644 --- a/src/jit/armelnonjit/CMakeLists.txt +++ b/src/jit/armelnonjit/CMakeLists.txt @@ -41,6 +41,8 @@ if(WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=armelnonjit.dll) endif(WIN32) +set_source_files_properties(${JIT_EXPORTS_FILE} PROPERTIES GENERATED TRUE) + add_library_clr(armelnonjit SHARED ${SHARED_LIB_SOURCES} diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp index 8bb8ce4418ae..cd1b90ffa2cb 100644 --- a/src/jit/assertionprop.cpp +++ b/src/jit/assertionprop.cpp @@ -75,7 +75,7 @@ void Compiler::optAddCopies() // We only add copies for non temp local variables // that have a single def and that can possibly be enregistered - if (varDsc->lvIsTemp || !varDsc->lvSingleDef || !varTypeCanReg(typ)) + if (varDsc->lvIsTemp || !varDsc->lvSingleDef || !varTypeIsEnregisterable(typ)) { continue; } @@ -2388,8 +2388,8 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) } // We want to use the Normal ValueNumber when checking for constants. - ValueNum vnCns = vnStore->VNConservativeNormalValue(tree->gtVNPair); - ValueNum vnLib = vnStore->VNLiberalNormalValue(tree->gtVNPair); + ValueNumPair vnPair = tree->gtVNPair; + ValueNum vnCns = vnStore->VNConservativeNormalValue(vnPair); // Check if node evaluates to a constant. if (!vnStore->IsVNConstant(vnCns)) @@ -2397,7 +2397,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) return nullptr; } - GenTree* newTree = tree; + GenTree* conValTree = nullptr; switch (vnStore->TypeOfVN(vnCns)) { case TYP_FLOAT: @@ -2407,20 +2407,13 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) if (tree->TypeGet() == TYP_INT) { // Same sized reinterpretation of bits to integer - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = *(reinterpret_cast(&value)); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewIconNode(*(reinterpret_cast(&value))); } else { // Implicit assignment conversion to float or double assert(varTypeIsFloating(tree->TypeGet())); - - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = value; - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(value, tree->TypeGet()); } break; } @@ -2431,21 +2424,13 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) if (tree->TypeGet() == TYP_LONG) { - // Same sized reinterpretation of bits to long - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_NATIVELONG); - tree->gtIntConCommon.SetLngValue(*(reinterpret_cast(&value))); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewLconNode(*(reinterpret_cast(&value))); } else { // Implicit assignment conversion to float or double assert(varTypeIsFloating(tree->TypeGet())); - - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = value; - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(value, tree->TypeGet()); } break; } @@ -2460,9 +2445,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) // to be recorded as a relocation with the VM. if (!opts.compReloc) { - newTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); - newTree->gtVNPair = ValueNumPair(vnLib, vnCns); - newTree = optPrepareTreeForReplacement(tree, newTree); + conValTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); } } else @@ -2472,18 +2455,12 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) { case TYP_INT: // Implicit assignment conversion to smaller integer - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = (int)value; - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewIconNode(static_cast(value)); break; case TYP_LONG: // Same type no conversion required - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_NATIVELONG); - tree->gtIntConCommon.SetLngValue(value); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewLconNode(value); break; case TYP_FLOAT: @@ -2494,32 +2471,27 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) case TYP_DOUBLE: // Same sized reinterpretation of bits to double - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = *(reinterpret_cast(&value)); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(*(reinterpret_cast(&value))); break; default: - return nullptr; + // Do not support such optimization. + break; } } } break; case TYP_REF: - if (tree->TypeGet() != TYP_REF) + { + assert(vnStore->ConstantValue(vnCns) == 0); + // Support onle ref(ref(0)), do not support other forms (e.g byref(ref(0)). + if (tree->TypeGet() == TYP_REF) { - return nullptr; + conValTree = gtNewIconNode(0, TYP_REF); } - - assert(vnStore->ConstantValue(vnCns) == 0); - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = 0; - tree->ClearIconHandleMask(); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); - break; + } + break; case TYP_INT: { @@ -2531,9 +2503,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) // to be recorded as a relocation with the VM. if (!opts.compReloc) { - newTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); - newTree->gtVNPair = ValueNumPair(vnLib, vnCns); - newTree = optPrepareTreeForReplacement(tree, newTree); + conValTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); } } else @@ -2544,27 +2514,17 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) case TYP_REF: case TYP_INT: // Same type no conversion required - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = value; - tree->ClearIconHandleMask(); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewIconNode(static_cast(value)); break; case TYP_LONG: // Implicit assignment conversion to larger integer - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_NATIVELONG); - tree->gtIntConCommon.SetLngValue(value); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewLconNode(static_cast(value)); break; case TYP_FLOAT: // Same sized reinterpretation of bits to float - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = *(reinterpret_cast(&value)); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(*(reinterpret_cast(&value)), TYP_FLOAT); break; case TYP_DOUBLE: @@ -2574,16 +2534,45 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) break; default: - return nullptr; + // Do not support (e.g. bool(const int)). + break; } } } break; + case TYP_BYREF: + // Do not support const byref optimization. + break; + default: - return nullptr; + // We do not record constants of other types. + unreached(); + break; + } + + if (conValTree != nullptr) + { + // Were able to optimize. + conValTree->gtVNPair = vnPair; + GenTree* sideEffList = optExtractSideEffListFromConst(tree); + if (sideEffList != nullptr) + { + // Replace as COMMA(side_effects, const value tree); + assert((sideEffList->gtFlags & GTF_SIDE_EFFECT) != 0); + return gtNewOperNode(GT_COMMA, conValTree->TypeGet(), sideEffList, conValTree); + } + else + { + // No side effects, replace as const value tree. + return conValTree; + } + } + else + { + // Was not able to optimize. + return nullptr; } - return newTree; } /******************************************************************************************************* @@ -3897,7 +3886,8 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTreeStmt* stmt) { - noway_assert(newTree != nullptr); + assert(newTree != nullptr); + assert(tree != nullptr); if (stmt == nullptr) { @@ -3908,33 +3898,22 @@ GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenT noway_assert(!optLocalAssertionProp); // If newTree == tree then we modified the tree in-place otherwise we have to - // locate our parent node and update it so that it points to newTree + // locate our parent node and update it so that it points to newTree. if (newTree != tree) { GenTree** link = gtFindLink(stmt, tree); -#ifdef DEBUG - if (link == nullptr) - { - noway_assert(!"gtFindLink failed!"); - printf("\nCould not find parent of:\n"); - gtDispTree(tree); - printf("\nIn this stmt:\n"); - gtDispTree(stmt); - } -#endif noway_assert(link != nullptr); - noway_assert(tree != nullptr); - if (link != nullptr) - { - // Replace the old operand with the newTree - *link = newTree; - // We only need to ensure that the gtNext field is set as it is used to traverse - // to the next node in the tree. We will re-morph this entire statement in - // optAssertionPropMain(). It will reset the gtPrev and gtNext links for all nodes. + // Replace the old operand with the newTree + *link = newTree; - newTree->gtNext = tree->gtNext; - } + // We only need to ensure that the gtNext field is set as it is used to traverse + // to the next node in the tree. We will re-morph this entire statement in + // optAssertionPropMain(). It will reset the gtPrev and gtNext links for all nodes. + newTree->gtNext = tree->gtNext; + + // Old tree should not be referenced anymore. + DEBUG_DESTROY_NODE(tree); } } @@ -4648,79 +4627,45 @@ struct VNAssertionPropVisitorInfo }; //------------------------------------------------------------------------------ -// optPrepareTreeForReplacement +// optExtractSideEffListFromConst // Extracts side effects from a tree so it can be replaced with a comma -// separated list of side effects + a new tree. +// separated list of side effects + a const tree. // // Note: -// The old and new trees may be the same. In this case, the tree will be -// appended to the side-effect list (if present) and returned. +// The caller expects that the root of the tree has no side effects and it +// won't be extracted. Otherwise the resulting comma tree would be bigger +// than the tree before optimization. // // Arguments: -// oldTree - The tree node to be dropped from the stmt expr. -// newTree - The tree node to append to the side effect list from "oldTree". +// tree - The tree node with constant value to extrace side-effects from. // // Return Value: -// Returns a comma separated list of side-effects present in the "oldTree". -// When "newTree" is non-null: -// 1. When side-effects are present in oldTree, newTree will be appended to the -// comma separated list. -// 2. When no side effects are present, then returns the "newTree" without -// any list. -// When "newTree" is null: -// 1. Returns the extracted side-effects from "oldTree" +// 1. Returns the extracted side-effects from "tree" // 2. When no side-effects are present, returns null. // -// Description: -// Either the "newTree" is returned when no side effects are present or a comma -// separated side effect list with "newTree" is returned. // -GenTree* Compiler::optPrepareTreeForReplacement(GenTree* oldTree, GenTree* newTree) +GenTree* Compiler::optExtractSideEffListFromConst(GenTree* tree) { - // If we have side effects, extract them and append newTree to the list. - GenTree* sideEffList = nullptr; - if ((oldTree->gtFlags & GTF_SIDE_EFFECT) != 0) - { - bool ignoreRoot = false; + assert(vnStore->IsVNConstant(vnStore->VNConservativeNormalValue(tree->gtVNPair))); - if (oldTree == newTree) - { - // If the caller passed the same tree as both old and new then it means - // that it expects that the root of the tree has no side effects and it - // won't be extracted. Otherwise the resulting comma tree would be invalid, - // having both op1 and op2 point to the same tree. - // - // Do a sanity check to ensure persistent side effects aren't discarded and - // tell gtExtractSideEffList to ignore the root of the tree. - assert(!gtNodeHasSideEffects(oldTree, GTF_PERSISTENT_SIDE_EFFECTS)); - // - // Exception side effects may be ignored if the root is known to be a constant - // (e.g. VN may evaluate a DIV/MOD node to a constant and the node may still - // have GTF_EXCEPT set, even if it does not actually throw any exceptions). - assert(!gtNodeHasSideEffects(oldTree, GTF_EXCEPT) || - vnStore->IsVNConstant(vnStore->VNConservativeNormalValue(oldTree->gtVNPair))); - - ignoreRoot = true; - } - - gtExtractSideEffList(oldTree, &sideEffList, GTF_SIDE_EFFECT, ignoreRoot); - } + GenTree* sideEffList = nullptr; - if (sideEffList != nullptr) + // If we have side effects, extract them. + if ((tree->gtFlags & GTF_SIDE_EFFECT) != 0) { - noway_assert((sideEffList->gtFlags & GTF_SIDE_EFFECT) != 0); + // Do a sanity check to ensure persistent side effects aren't discarded and + // tell gtExtractSideEffList to ignore the root of the tree. + assert(!gtNodeHasSideEffects(tree, GTF_PERSISTENT_SIDE_EFFECTS)); - if (newTree != nullptr) - { - newTree = gtNewOperNode(GT_COMMA, newTree->TypeGet(), sideEffList, newTree); - } - else - { - newTree = sideEffList; - } + // Exception side effects may be ignored because the root is known to be a constant + // (e.g. VN may evaluate a DIV/MOD node to a constant and the node may still + // have GTF_EXCEPT set, even if it does not actually throw any exceptions). + bool ignoreRoot = true; + + gtExtractSideEffList(tree, &sideEffList, GTF_SIDE_EFFECT, ignoreRoot); } - return newTree; + return sideEffList; } //------------------------------------------------------------------------------ @@ -4779,7 +4724,7 @@ GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test) } // Prepare the tree for replacement so any side effects can be extracted. - GenTree* sideEffList = optPrepareTreeForReplacement(test, nullptr); + GenTree* sideEffList = optExtractSideEffListFromConst(relop); // Transform the relop's operands to be both zeroes. ValueNum vnZero = vnStore->VNZeroForType(TYP_INT); diff --git a/src/jit/codegen.h b/src/jit/codegen.h index d490057374f0..cde0fad72e86 100644 --- a/src/jit/codegen.h +++ b/src/jit/codegen.h @@ -1211,6 +1211,14 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genReturn(GenTree* treeNode); +#if defined(_TARGET_XARCH_) + void genStackPointerConstantAdjustmentWithProbe(ssize_t spDelta, bool hideSpChangeFromEmitter, regNumber regTmp); + void genStackPointerConstantAdjustmentLoopWithProbe(ssize_t spDelta, + bool hideSpChangeFromEmitter, + regNumber regTmp); + void genStackPointerDynamicAdjustmentWithProbe(regNumber regSpDelta, regNumber regTmp); +#endif // defined(_TARGET_XARCH_) + void genLclHeap(GenTree* tree); bool genIsRegCandidateLocal(GenTree* tree) diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp index 4668aaf5b87b..da678dc17b04 100644 --- a/src/jit/codegenarm64.cpp +++ b/src/jit/codegenarm64.cpp @@ -49,8 +49,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // attr - operation size and GC attribute // reg1, reg2 - first and second register operands // imm - immediate value (third operand when it fits) -// tmpReg - temp register to use when the 'imm' doesn't fit -// inUnwindRegion - true if we are in a prolog/epilog region with unwind codes +// tmpReg - temp register to use when the 'imm' doesn't fit. Can be REG_NA +// if caller knows for certain the constant will fit. +// inUnwindRegion - true if we are in a prolog/epilog region with unwind codes. +// Default: false. // // Return Value: // returns true if the immediate was too large and tmpReg was used and modified. @@ -2021,10 +2023,10 @@ void CodeGen::genSimpleReturn(GenTree* treeNode) GenTree* op1 = treeNode->gtGetOp1(); var_types targetType = treeNode->TypeGet(); - assert(!isStructReturn(treeNode)); + assert(targetType != TYP_STRUCT); assert(targetType != TYP_VOID); - regNumber retReg = varTypeIsFloating(treeNode) ? REG_FLOATRET : REG_INTRET; + regNumber retReg = varTypeUsesFloatArgReg(treeNode) ? REG_FLOATRET : REG_INTRET; bool movRequired = (op1->gtRegNum != retReg); @@ -2146,7 +2148,8 @@ void CodeGen::genLclHeap(GenTree* tree) { assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain // aligned - inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE); + genInstrWithConstant(INS_add, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, + rsGetRsvdReg()); stackAdjustment += compiler->lvaOutgoingArgSpaceSize; } @@ -2301,12 +2304,12 @@ void CodeGen::genLclHeap(GenTree* tree) { assert((stackAdjustment % STACK_ALIGN) == 0); // This must be true for the stack to remain aligned assert(stackAdjustment > 0); - getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, (int)stackAdjustment); + genInstrWithConstant(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, (ssize_t)stackAdjustment, rsGetRsvdReg()); // Return the stackalloc'ed address in result register. // TargetReg = SP + stackAdjustment. // - getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, targetReg, REG_SPBASE, (int)stackAdjustment); + genInstrWithConstant(INS_add, EA_PTRSIZE, targetReg, REG_SPBASE, (ssize_t)stackAdjustment, rsGetRsvdReg()); } else // stackAdjustment == 0 { @@ -3872,7 +3875,14 @@ void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode) simdNode->gtSIMDBaseType != TYP_SHORT && simdNode->gtSIMDBaseType != TYP_BYTE && simdNode->gtSIMDBaseType != TYP_UINT && simdNode->gtSIMDBaseType != TYP_ULONG) { - noway_assert(!"SIMD intrinsic with unsupported base type."); + // We don't need a base type for the Upper Save & Restore intrinsics, and we may find + // these implemented over lclVars created by CSE without full handle information (and + // therefore potentially without a base type). + if ((simdNode->gtSIMDIntrinsicID != SIMDIntrinsicUpperSave) && + (simdNode->gtSIMDIntrinsicID != SIMDIntrinsicUpperRestore)) + { + noway_assert(!"SIMD intrinsic with unsupported base type."); + } } switch (simdNode->gtSIMDIntrinsicID) @@ -4534,7 +4544,7 @@ void CodeGen::genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode) emitAttr attr = (simdNode->gtSIMDSize > 8) ? EA_16BYTE : EA_8BYTE; insOpts opt = genGetSimdInsOpt(attr, baseType); - // TODO-ARM64-CQ Contain integer constants where posible + // TODO-ARM64-CQ Contain integer constants where possible regNumber tmpFloatReg = simdNode->GetSingleTempReg(RBM_ALLFLOAT); diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp index 55b3f0a7ba95..23802ff20731 100644 --- a/src/jit/codegenarmarch.cpp +++ b/src/jit/codegenarmarch.cpp @@ -704,6 +704,22 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) varNode = addrNode->AsLclVarCommon(); addrNode = nullptr; } + else // addrNode is used + { + // Generate code to load the address that we need into a register + genConsumeAddress(addrNode); + addrReg = addrNode->gtRegNum; + +#ifdef _TARGET_ARM64_ + // If addrReg equal to loReg, swap(loReg, hiReg) + // This reduces code complexity by only supporting one addrReg overwrite case + if (loReg == addrReg) + { + loReg = hiReg; + hiReg = addrReg; + } +#endif // _TARGET_ARM64_ + } } // Either varNode or addrNOde must have been setup above, @@ -714,24 +730,19 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) BYTE* gcPtrs = gcPtrArray; unsigned gcPtrCount; // The count of GC pointers in the struct - int structSize; + unsigned structSize; bool isHfa; - // This is the varNum for our load operations, - // only used when we have a multireg struct with a LclVar source - unsigned varNumInp = BAD_VAR_NUM; - #ifdef _TARGET_ARM_ // On ARM32, size of reference map can be larger than MAX_ARG_REG_COUNT gcPtrs = treeNode->gtGcPtrs; gcPtrCount = treeNode->gtNumberReferenceSlots; #endif // Setup the structSize, isHFa, and gcPtrCount - if (varNode != nullptr) + if (source->OperGet() == GT_LCL_VAR) { - varNumInp = varNode->gtLclNum; - assert(varNumInp < compiler->lvaCount); - LclVarDsc* varDsc = &compiler->lvaTable[varNumInp]; + assert(varNode != nullptr); + LclVarDsc* varDsc = compiler->lvaGetDesc(varNode); // This struct also must live in the stack frame // And it can't live in a register (SIMD) @@ -747,29 +758,40 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) gcPtrs[i] = varDsc->lvGcLayout[i]; #endif // _TARGET_ARM_ } - else // addrNode is used + else // we must have a GT_OBJ { - assert(addrNode != nullptr); + assert(source->OperGet() == GT_OBJ); - // Generate code to load the address that we need into a register - genConsumeAddress(addrNode); - addrReg = addrNode->gtRegNum; + // If the source is an OBJ node then we need to use the type information + // it provides (size and GC layout) even if the node wraps a lclvar. Due + // to struct reinterpretation (e.g. Unsafe.As) it is possible that + // the OBJ node has a different type than the lclvar. + CORINFO_CLASS_HANDLE objClass = source->gtObj.gtClass; -#ifdef _TARGET_ARM64_ - // If addrReg equal to loReg, swap(loReg, hiReg) - // This reduces code complexity by only supporting one addrReg overwrite case - if (loReg == addrReg) + structSize = compiler->info.compCompHnd->getClassSize(objClass); + + // The codegen code below doesn't have proper support for struct sizes + // that are not multiple of the slot size. Call arg morphing handles this + // case by copying non-local values to temporary local variables. + // More generally, we can always round up the struct size when the OBJ node + // wraps a local variable because the local variable stack allocation size + // is also rounded up to be a multiple of the slot size. + if (varNode != nullptr) { - loReg = hiReg; - hiReg = addrReg; + structSize = roundUp(structSize, TARGET_POINTER_SIZE); + } + else + { + assert((structSize % TARGET_POINTER_SIZE) == 0); } -#endif // _TARGET_ARM64_ - CORINFO_CLASS_HANDLE objClass = source->gtObj.gtClass; + isHfa = compiler->IsHfa(objClass); - structSize = compiler->info.compCompHnd->getClassSize(objClass); - isHfa = compiler->IsHfa(objClass); #ifdef _TARGET_ARM64_ + // On ARM32, Lowering places the correct GC layout information in the + // GenTreePutArgStk node and the code above already use that. On ARM64, + // this information is not available (in order to keep GenTreePutArgStk + // nodes small) and we need to retrieve it from the VM here. gcPtrCount = compiler->info.compCompHnd->getClassGClayout(objClass, &gcPtrs[0]); #endif } @@ -806,8 +828,8 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) if (varNode != nullptr) { // Load from our varNumImp source - emit->emitIns_R_R_S_S(INS_ldp, emitTypeSize(type0), emitTypeSize(type1), loReg, hiReg, varNumInp, - structOffset); + emit->emitIns_R_R_S_S(INS_ldp, emitTypeSize(type0), emitTypeSize(type1), loReg, hiReg, + varNode->GetLclNum(), structOffset); } else { @@ -841,7 +863,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) if (varNode != nullptr) { // Load from our varNumImp source - emit->emitIns_R_S(INS_ldr, emitTypeSize(type), loReg, varNumInp, structOffset); + emit->emitIns_R_S(INS_ldr, emitTypeSize(type), loReg, varNode->GetLclNum(), structOffset); } else { @@ -880,7 +902,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) if (varNode != nullptr) { // Load from our varNumImp source - emit->emitIns_R_S(ins_Load(nextType), nextAttr, loReg, varNumInp, structOffset); + emit->emitIns_R_S(ins_Load(nextType), nextAttr, loReg, varNode->GetLclNum(), structOffset); } else { @@ -2355,7 +2377,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call) } else { - assert(!varTypeIsStruct(call)); + assert(call->gtType != TYP_STRUCT); if (call->gtType == TYP_REF) { @@ -2509,9 +2531,13 @@ void CodeGen::genCallInstruction(GenTreeCall* call) // TCB in REG_PINVOKE_TCB. fgMorphCall() sets the correct argument registers. returnReg = REG_PINVOKE_TCB; } + else if (compiler->opts.compUseSoftFP) + { + returnReg = REG_INTRET; + } else #endif // _TARGET_ARM_ - if (varTypeIsFloating(returnType) && !compiler->opts.compUseSoftFP) + if (varTypeUsesFloatArgReg(returnType)) { returnReg = REG_FLOATRET; } @@ -3501,8 +3527,13 @@ bool CodeGen::isStructReturn(GenTree* treeNode) // For the GT_RET_FILT, the return is always // a bool or a void, for the end of a finally block. noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT); + var_types returnType = treeNode->TypeGet(); - return varTypeIsStruct(treeNode); +#ifdef _TARGET_ARM64_ + return varTypeIsStruct(returnType) && (compiler->info.compRetNativeType == TYP_STRUCT); +#else + return varTypeIsStruct(returnType); +#endif } //------------------------------------------------------------------------ @@ -3849,7 +3880,9 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni // Generate: // - // mov rOffset, -pageSize + // mov rOffset, -pageSize // On arm, this turns out to be "movw r1, 0xf000; sxth r1, r1". + // // We could save 4 bytes in the prolog by using "movs r1, 0" at the + // // runtime expense of running a useless first loop iteration. // mov rLimit, -frameSize // loop: // ldr rTemp, [sp + rOffset] // rTemp = wzr on ARM64 diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index 0ec2ba74e7e0..a5746c3f3d2b 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -3305,7 +3305,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere { // A struct might be passed partially in XMM register for System V calls. // So a single arg might use both register files. - if (isFloatRegType(regType) != doingFloat) + if (emitter::isFloatReg(varDsc->lvArgReg) != doingFloat) { continue; } @@ -10158,7 +10158,11 @@ bool Compiler::IsMultiRegReturnedType(CORINFO_CLASS_HANDLE hClass) structPassingKind howToReturnStruct; var_types returnType = getReturnTypeForStruct(hClass, &howToReturnStruct); +#ifdef _TARGET_ARM64_ + return (varTypeIsStruct(returnType) && (howToReturnStruct != SPK_PrimitiveType)); +#else return (varTypeIsStruct(returnType)); +#endif } //---------------------------------------------- @@ -10167,11 +10171,7 @@ bool Compiler::IsMultiRegReturnedType(CORINFO_CLASS_HANDLE hClass) bool Compiler::IsHfa(CORINFO_CLASS_HANDLE hClass) { -#ifdef FEATURE_HFA - return varTypeIsFloating(GetHfaType(hClass)); -#else - return false; -#endif + return varTypeIsValidHfaType(GetHfaType(hClass)); } bool Compiler::IsHfa(GenTree* tree) @@ -10204,7 +10204,19 @@ var_types Compiler::GetHfaType(CORINFO_CLASS_HANDLE hClass) { #ifdef FEATURE_HFA CorInfoType corType = info.compCompHnd->getHFAType(hClass); - if (corType != CORINFO_TYPE_UNDEF) +#if defined(_TARGET_ARM64_) && defined(FEATURE_SIMD) + if (corType == CORINFO_TYPE_VALUECLASS) + { + // This is a vector type. + // HVAs are only supported on ARM64, and only for homogeneous aggregates of 8 or 16 byte vectors. + // For 8-byte vectors corType will be returned as CORINFO_TYPE_DOUBLE. + result = TYP_SIMD16; + // This type may not appear elsewhere, but it will occupy a floating point register. + compFloatingPointUsed = true; + } + else +#endif // _TARGET_ARM64_ && FEATURE_SIMD + if (corType != CORINFO_TYPE_UNDEF) { result = JITtype2varType(corType); } diff --git a/src/jit/codegenlinear.cpp b/src/jit/codegenlinear.cpp index 9661d43bd49d..c2e1c74647f1 100644 --- a/src/jit/codegenlinear.cpp +++ b/src/jit/codegenlinear.cpp @@ -1646,7 +1646,7 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArg unsigned thisFieldOffset = argOffset + fieldListPtr->gtFieldOffset; getEmitter()->emitIns_S_R(ins_Store(type), attr, reg, outArgVarNum, thisFieldOffset); - // We can't write beyound the arg area + // We can't write beyond the arg area assert((thisFieldOffset + EA_SIZE_IN_BYTES(attr)) <= compiler->lvaLclSize(outArgVarNum)); } } diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index 014011b3d455..a7c01a78f7e7 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -1133,9 +1133,9 @@ void CodeGen::genStructReturn(GenTree* treeNode) unsigned regCount = retTypeDesc.GetReturnRegCount(); assert(regCount == MAX_RET_REG_COUNT); - if (varTypeIsEnregisterableStruct(op1)) + if (varTypeIsEnregisterable(op1)) { - // Right now the only enregistrable structs supported are SIMD vector types. + // Right now the only enregisterable structs supported are SIMD vector types. assert(varTypeIsSIMD(op1)); assert(op1->isUsedFromReg()); @@ -2171,7 +2171,8 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni return; } - const target_size_t pageSize = compiler->eeGetPageSize(); + const target_size_t pageSize = compiler->eeGetPageSize(); + target_size_t lastTouchDelta = 0; // What offset from the final SP was the last probe? if (frameSize == REGSIZE_BYTES) { @@ -2182,19 +2183,25 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni { // Frame size is (0x0008..0x1000) inst_RV_IV(INS_sub, REG_SPBASE, frameSize, EA_PTRSIZE); + lastTouchDelta = frameSize; } else if (frameSize < compiler->getVeryLargeFrameSize()) { + lastTouchDelta = frameSize; + // Frame size is (0x1000..0x3000) getEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, -(int)pageSize); + lastTouchDelta -= pageSize; if (frameSize >= 0x2000) { getEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, -2 * (int)pageSize); + lastTouchDelta -= pageSize; } inst_RV_IV(INS_sub, REG_SPBASE, frameSize, EA_PTRSIZE); + assert(lastTouchDelta == frameSize % pageSize); } else { @@ -2230,6 +2237,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni // The encoding differs based on the architecture and what register is // used (namely, using RAX has a smaller encoding). // + // xor eax,eax // loop: // For x86 // test [esp + eax], eax 3 @@ -2264,7 +2272,11 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni // Branch backwards to start of loop inst_IV(INS_jge, bytesForBackwardJump); + + lastTouchDelta = frameSize % pageSize; + #else // _TARGET_UNIX_ + // Code size for each instruction. We need this because the // backward branch is hard-coded with the number of bytes to branch. // The encoding differs based on the architecture and what register is @@ -2317,6 +2329,9 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni inst_IV(INS_jge, bytesForBackwardJump); // Branch backwards to start of loop getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_SPBASE, initReg, frameSize); // restore stack pointer + + lastTouchDelta = 0; // The loop code above actually over-probes: it always probes beyond the final SP we need. + #endif // _TARGET_UNIX_ *pInitRegZeroed = false; // The initReg does not contain zero @@ -2332,7 +2347,18 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni inst_RV_IV(INS_sub, REG_SPBASE, frameSize, EA_PTRSIZE); } + if (lastTouchDelta + STACK_PROBE_BOUNDARY_THRESHOLD_BYTES > pageSize) + { + // We haven't probed almost a complete page. If the next action on the stack might subtract from SP + // first, before touching the current SP, then we do one more probe at the very bottom. This can + // happen on x86, for example, when we copy an argument to the stack using a "SUB ESP; REP MOV" + // strategy. + + getEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, 0); + } + compiler->unwindAllocStack(frameSize); + #ifdef USING_SCOPE_INFO if (!doubleAlignOrFramePointerUsed()) { @@ -2341,6 +2367,172 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni #endif // USING_SCOPE_INFO } +//------------------------------------------------------------------------ +// genStackPointerConstantAdjustmentWithProbe: add a specified constant value to the stack pointer, +// and probe the stack as appropriate. Should only be called as a helper for +// genStackPointerConstantAdjustmentLoopWithProbe. +// +// Arguments: +// spDelta - the value to add to SP. Must be negative or zero. If zero, the probe happens, +// but the stack pointer doesn't move. +// hideSpChangeFromEmitter - if true, hide the SP adjustment from the emitter. This only applies to x86, +// and requires that `regTmp` be valid. +// regTmp - an available temporary register. Will be trashed. Only used on x86. +// Must be REG_NA on non-x86 platforms. +// +// Return Value: +// None. +// +void CodeGen::genStackPointerConstantAdjustmentWithProbe(ssize_t spDelta, + bool hideSpChangeFromEmitter, + regNumber regTmp) +{ + assert(spDelta < 0); + assert((target_size_t)(-spDelta) <= compiler->eeGetPageSize()); + + getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); + + if (hideSpChangeFromEmitter) + { + // For x86, some cases don't want to use "sub ESP" because we don't want the emitter to track the adjustment + // to ESP. So do the work in the count register. + // TODO-CQ: manipulate ESP directly, to share code, reduce #ifdefs, and improve CQ. This would require + // creating a way to temporarily turn off the emitter's tracking of ESP, maybe marking instrDescs as "don't + // track". + assert(regTmp != REG_NA); + inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL); + inst_RV_IV(INS_sub, regTmp, -spDelta, EA_PTRSIZE); + inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL); + } + else + { + assert(regTmp == REG_NA); + inst_RV_IV(INS_sub, REG_SPBASE, -spDelta, EA_PTRSIZE); + } +} + +//------------------------------------------------------------------------ +// genStackPointerConstantAdjustmentLoopWithProbe: Add a specified constant value to the stack pointer, +// and probe the stack as appropriate. Generates one probe per page, up to the total amount required. +// This will generate a sequence of probes in-line. It is required for the case where we need to expose +// (not hide) the stack level adjustment. We can't use the dynamic loop in that case, because the total +// stack adjustment would not be visible to the emitter. It would be possible to use this version for +// multiple hidden constant stack level adjustments but we don't do that currently (we use the loop +// version in genStackPointerDynamicAdjustmentWithProbe instead). +// +// Arguments: +// spDelta - the value to add to SP. Must be negative. +// hideSpChangeFromEmitter - if true, hide the SP adjustment from the emitter. This only applies to x86, +// and requires that `regTmp` be valid. +// regTmp - an available temporary register. Will be trashed. Only used on x86. +// Must be REG_NA on non-x86 platforms. +// +// Return Value: +// None. +// +void CodeGen::genStackPointerConstantAdjustmentLoopWithProbe(ssize_t spDelta, + bool hideSpChangeFromEmitter, + regNumber regTmp) +{ + assert(spDelta < 0); + + const target_size_t pageSize = compiler->eeGetPageSize(); + + ssize_t spRemainingDelta = spDelta; + do + { + ssize_t spOneDelta = -(ssize_t)min((target_size_t)-spRemainingDelta, pageSize); + genStackPointerConstantAdjustmentWithProbe(spOneDelta, hideSpChangeFromEmitter, regTmp); + spRemainingDelta -= spOneDelta; + } while (spRemainingDelta < 0); + + // What offset from the final SP was the last probe? This depends on the fact that + // genStackPointerConstantAdjustmentWithProbe() probes first, then does "SUB SP". + target_size_t lastTouchDelta = (target_size_t)(-spDelta) % pageSize; + if ((lastTouchDelta == 0) || (lastTouchDelta + STACK_PROBE_BOUNDARY_THRESHOLD_BYTES > pageSize)) + { + // We haven't probed almost a complete page. If lastTouchDelta==0, then spDelta was an exact + // multiple of pageSize, which means we last probed exactly one page back. Otherwise, we probed + // the page, but very far from the end. If the next action on the stack might subtract from SP + // first, before touching the current SP, then we do one more probe at the very bottom. This can + // happen on x86, for example, when we copy an argument to the stack using a "SUB ESP; REP MOV" + // strategy. + + getEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, 0); + } +} + +//------------------------------------------------------------------------ +// genStackPointerDynamicAdjustmentWithProbe: add a register value to the stack pointer, +// and probe the stack as appropriate. +// +// Note that for x86, we hide the ESP adjustment from the emitter. To do that, currently, +// requires a temporary register and extra code. +// +// Arguments: +// regSpDelta - the register value to add to SP. The value in this register must be negative. +// This register might be trashed. +// regTmp - an available temporary register. Will be trashed. Only used on x86. +// Must be REG_NA on non-x86 platforms. +// +// Return Value: +// None. +// +void CodeGen::genStackPointerDynamicAdjustmentWithProbe(regNumber regSpDelta, regNumber regTmp) +{ + assert(regSpDelta != REG_NA); + assert(regTmp != REG_NA); + + // Tickle the pages to ensure that ESP is always valid and is + // in sync with the "stack guard page". Note that in the worst + // case ESP is on the last byte of the guard page. Thus you must + // touch ESP-0 first not ESP-0x1000. + // + // Another subtlety is that you don't want ESP to be exactly on the + // boundary of the guard page because PUSH is predecrement, thus + // call setup would not touch the guard page but just beyond it. + // + // Note that we go through a few hoops so that ESP never points to + // illegal pages at any time during the tickling process + // + // add regSpDelta, ESP // reg now holds ultimate ESP + // jb loop // result is smaller than original ESP (no wrap around) + // xor regSpDelta, regSpDelta // Overflow, pick lowest possible number + // loop: + // test ESP, [ESP+0] // tickle the page + // mov regTmp, ESP + // sub regTmp, eeGetPageSize() + // mov ESP, regTmp + // cmp ESP, regSpDelta + // jae loop + // mov ESP, regSpDelta + + BasicBlock* loop = genCreateTempLabel(); + + inst_RV_RV(INS_add, regSpDelta, REG_SPBASE, TYP_I_IMPL); + inst_JMP(EJ_jb, loop); + + instGen_Set_Reg_To_Zero(EA_PTRSIZE, regSpDelta); + + genDefineTempLabel(loop); + + // Tickle the decremented value. Note that it must be done BEFORE the update of ESP since ESP might already + // be on the guard page. It is OK to leave the final value of ESP on the guard page. + getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); + + // Subtract a page from ESP. This is a trick to avoid the emitter trying to track the + // decrement of the ESP - we do the subtraction in another reg instead of adjusting ESP directly. + inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL); + inst_RV_IV(INS_sub, regTmp, compiler->eeGetPageSize(), EA_PTRSIZE); + inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL); + + inst_RV_RV(INS_cmp, REG_SPBASE, regSpDelta, TYP_I_IMPL); + inst_JMP(EJ_jae, loop); + + // Move the final value to ESP + inst_RV_RV(INS_mov, REG_SPBASE, regSpDelta); +} + //------------------------------------------------------------------------ // genLclHeap: Generate code for localloc. // @@ -2380,8 +2572,7 @@ void CodeGen::genLclHeap(GenTree* tree) noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes noway_assert(genStackLevel == 0); // Can't have anything on the stack - unsigned stackAdjustment = 0; - BasicBlock* loop = nullptr; + unsigned stackAdjustment = 0; // compute the amount of memory to allocate to properly STACK_ALIGN. size_t amount = 0; @@ -2503,9 +2694,11 @@ void CodeGen::genLclHeap(GenTree* tree) !compiler->info.compInitMem && (amount < compiler->eeGetPageSize()); // must be < not <= #ifdef _TARGET_X86_ - bool needRegCntRegister = true; + bool needRegCntRegister = true; + bool hideSpChangeFromEmitter = true; #else // !_TARGET_X86_ - bool needRegCntRegister = !doNoInitLessThanOnePageAlloc; + bool needRegCntRegister = !doNoInitLessThanOnePageAlloc; + bool hideSpChangeFromEmitter = false; #endif // !_TARGET_X86_ if (needRegCntRegister) @@ -2529,23 +2722,9 @@ void CodeGen::genLclHeap(GenTree* tree) // Since the size is less than a page, simply adjust ESP. // ESP might already be in the guard page, so we must touch it BEFORE // the alloc, not after. - CLANG_FORMAT_COMMENT_ANCHOR; - -#ifdef _TARGET_X86_ - // For x86, we don't want to use "sub ESP" because we don't want the emitter to track the adjustment - // to ESP. So do the work in the count register. - // TODO-CQ: manipulate ESP directly, to share code, reduce #ifdefs, and improve CQ. This would require - // creating a way to temporarily turn off the emitter's tracking of ESP, maybe marking instrDescs as "don't - // track". - inst_RV_RV(INS_mov, regCnt, REG_SPBASE, TYP_I_IMPL); - getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); - inst_RV_IV(INS_sub, regCnt, amount, EA_PTRSIZE); - inst_RV_RV(INS_mov, REG_SPBASE, regCnt, TYP_I_IMPL); -#else // !_TARGET_X86_ - getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); - inst_RV_IV(INS_sub, REG_SPBASE, amount, EA_PTRSIZE); -#endif // !_TARGET_X86_ + assert(amount < compiler->eeGetPageSize()); // must be < not <= + genStackPointerConstantAdjustmentLoopWithProbe(-(ssize_t)amount, hideSpChangeFromEmitter, regCnt); goto ALLOC_DONE; } @@ -2561,7 +2740,6 @@ void CodeGen::genLclHeap(GenTree* tree) genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG); } - loop = genCreateTempLabel(); if (compiler->info.compInitMem) { // At this point 'regCnt' is set to the number of loop iterations for this loop, if each @@ -2572,6 +2750,7 @@ void CodeGen::genLclHeap(GenTree* tree) assert(genIsValidIntReg(regCnt)); // Loop: + BasicBlock* loop = genCreateTempLabel(); genDefineTempLabel(loop); static_assert_no_msg((STACK_ALIGN % REGSIZE_BYTES) == 0); @@ -2590,62 +2769,12 @@ void CodeGen::genLclHeap(GenTree* tree) else { // At this point 'regCnt' is set to the total number of bytes to localloc. - // - // We don't need to zero out the allocated memory. However, we do have - // to tickle the pages to ensure that ESP is always valid and is - // in sync with the "stack guard page". Note that in the worst - // case ESP is on the last byte of the guard page. Thus you must - // touch ESP+0 first not ESP+x01000. - // - // Another subtlety is that you don't want ESP to be exactly on the - // boundary of the guard page because PUSH is predecrement, thus - // call setup would not touch the guard page but just beyond it - // - // Note that we go through a few hoops so that ESP never points to - // illegal pages at any time during the tickling process - // - // neg REGCNT - // add REGCNT, ESP // reg now holds ultimate ESP - // jb loop // result is smaller than orignial ESP (no wrap around) - // xor REGCNT, REGCNT, // Overflow, pick lowest possible number - // loop: - // test ESP, [ESP+0] // tickle the page - // mov REGTMP, ESP - // sub REGTMP, eeGetPageSize() - // mov ESP, REGTMP - // cmp ESP, REGCNT - // jae loop - // - // mov ESP, REG - // end: - inst_RV(INS_NEG, regCnt, TYP_I_IMPL); - inst_RV_RV(INS_add, regCnt, REG_SPBASE, TYP_I_IMPL); - inst_JMP(EJ_jb, loop); - - instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt); - - genDefineTempLabel(loop); - - // Tickle the decremented value, and move back to ESP, - // note that it has to be done BEFORE the update of ESP since - // ESP might already be on the guard page. It is OK to leave - // the final value of ESP on the guard page - getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0); + // Negate this value before calling the function to adjust the stack (which + // adds to ESP). - // This is a harmless trick to avoid the emitter trying to track the - // decrement of the ESP - we do the subtraction in another reg instead - // of adjusting ESP directly. + inst_RV(INS_NEG, regCnt, TYP_I_IMPL); regNumber regTmp = tree->GetSingleTempReg(); - - inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL); - inst_RV_IV(INS_sub, regTmp, compiler->eeGetPageSize(), EA_PTRSIZE); - inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL); - - inst_RV_RV(INS_cmp, REG_SPBASE, regCnt, TYP_I_IMPL); - inst_JMP(EJ_jae, loop); - - // Move the final value to ESP - inst_RV_RV(INS_mov, REG_SPBASE, regCnt); + genStackPointerDynamicAdjustmentWithProbe(regCnt, regTmp); } ALLOC_DONE: @@ -7508,7 +7637,27 @@ bool CodeGen::genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk) else { m_pushStkArg = false; - inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE); + + // If argSize is large, we need to probe the stack like we do in the prolog (genAllocLclFrame) + // or for localloc (genLclHeap), to ensure we touch the stack pages sequentially, and don't miss + // the stack guard pages. The prolog probes, but we don't know at this point how much higher + // the last probed stack pointer value is. We default a threshold. Any size below this threshold + // we are guaranteed the stack has been probed. Above this threshold, we don't know. The threshold + // should be high enough to cover all common cases. Increasing the threshold means adding a few + // more "lowest address of stack" probes in the prolog. Since this is relatively rare, add it to + // stress modes. + + if ((argSize >= ARG_STACK_PROBE_THRESHOLD_BYTES) || + compiler->compStressCompile(Compiler::STRESS_GENERIC_VARN, 5)) + { + genStackPointerConstantAdjustmentLoopWithProbe(-(ssize_t)argSize, /* hideSpChangeFromEmitter */ false, + REG_NA); + } + else + { + inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE); + } + AddStackLevel(argSize); return true; } diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index e005a77c2900..378d83bd1ff9 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -573,8 +573,8 @@ bool Compiler::isSingleFloat32Struct(CORINFO_CLASS_HANDLE clsHnd) // of size 'structSize'. // We examine 'clsHnd' to check the GC layout of the struct and // return TYP_REF for structs that simply wrap an object. -// If the struct is a one element HFA, we will return the -// proper floating point type. +// If the struct is a one element HFA/HVA, we will return the +// proper floating point or vector type. // // Arguments: // structSize - the size of the struct type, cannot be zero @@ -592,13 +592,64 @@ bool Compiler::isSingleFloat32Struct(CORINFO_CLASS_HANDLE clsHnd) // same way as any other 8-byte struct // For ARM32 if we have an HFA struct that wraps a 64-bit double // we will return TYP_DOUBLE. +// For vector calling conventions, a vector is considered a "primitive" +// type, as it is passed in a single register. // var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS_HANDLE clsHnd, bool isVarArg) { assert(structSize != 0); - var_types useType; + var_types useType = TYP_UNKNOWN; +// Start by determining if we have an HFA/HVA with a single element. +#ifdef FEATURE_HFA +#if defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) + // Arm64 Windows VarArg methods arguments will not classify HFA types, they will need to be treated + // as if they are not HFA types. + if (!isVarArg) +#endif // defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) + { + switch (structSize) + { + case 4: + case 8: +#ifdef _TARGET_ARM64_ + case 16: +#endif // _TARGET_ARM64_ + { + var_types hfaType; +#ifdef ARM_SOFTFP + // For ARM_SOFTFP, HFA is unsupported so we need to check in another way. + // This matters only for size-4 struct because bigger structs would be processed with RetBuf. + if (isSingleFloat32Struct(clsHnd)) + { + hfaType = TYP_FLOAT; + } +#else // !ARM_SOFTFP + hfaType = GetHfaType(clsHnd); +#endif // ARM_SOFTFP + // We're only interested in the case where the struct size is equal to the size of the hfaType. + if (varTypeIsValidHfaType(hfaType)) + { + if (genTypeSize(hfaType) == structSize) + { + useType = hfaType; + } + else + { + return TYP_UNKNOWN; + } + } + } + } + if (useType != TYP_UNKNOWN) + { + return useType; + } + } +#endif // FEATURE_HFA + + // Now deal with non-HFA/HVA structs. switch (structSize) { case 1: @@ -618,15 +669,8 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS #ifdef _TARGET_64BIT_ case 4: - if (IsHfa(clsHnd)) - { - // A structSize of 4 with IsHfa, it must be an HFA of one float - useType = TYP_FLOAT; - } - else - { - useType = TYP_INT; - } + // We dealt with the one-float HFA above. All other 4-byte structs are handled as INT. + useType = TYP_INT; break; #if !defined(_TARGET_XARCH_) || defined(UNIX_AMD64_ABI) @@ -640,86 +684,13 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS #endif // _TARGET_64BIT_ case TARGET_POINTER_SIZE: -#ifdef ARM_SOFTFP - // For ARM_SOFTFP, HFA is unsupported so we need to check in another way - // This matters only for size-4 struct cause bigger structs would be processed with RetBuf - if (isSingleFloat32Struct(clsHnd)) -#else // !ARM_SOFTFP - if (IsHfa(clsHnd) -#if defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) - // Arm64 Windows VarArg methods arguments will not - // classify HFA types, they will need to be treated - // as if they are not HFA types. - && !isVarArg -#endif // defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) - ) -#endif // ARM_SOFTFP - { -#ifdef _TARGET_64BIT_ - var_types hfaType = GetHfaType(clsHnd); - - // A structSize of 8 with IsHfa, we have two possiblities: - // An HFA of one double or an HFA of two floats - // - // Check and exclude the case of an HFA of two floats - if (hfaType == TYP_DOUBLE) - { - // We have an HFA of one double - useType = TYP_DOUBLE; - } - else - { - assert(hfaType == TYP_FLOAT); - - // We have an HFA of two floats - // This should be passed or returned in two FP registers - useType = TYP_UNKNOWN; - } -#else // a 32BIT target - // A structSize of 4 with IsHfa, it must be an HFA of one float - useType = TYP_FLOAT; -#endif // _TARGET_64BIT_ - } - else - { - BYTE gcPtr = 0; - // Check if this pointer-sized struct is wrapping a GC object - info.compCompHnd->getClassGClayout(clsHnd, &gcPtr); - useType = getJitGCType(gcPtr); - } - break; - -#ifdef _TARGET_ARM_ - case 8: - if (IsHfa(clsHnd)) - { - var_types hfaType = GetHfaType(clsHnd); - - // A structSize of 8 with IsHfa, we have two possiblities: - // An HFA of one double or an HFA of two floats - // - // Check and exclude the case of an HFA of two floats - if (hfaType == TYP_DOUBLE) - { - // We have an HFA of one double - useType = TYP_DOUBLE; - } - else - { - assert(hfaType == TYP_FLOAT); - - // We have an HFA of two floats - // This should be passed or returned in two FP registers - useType = TYP_UNKNOWN; - } - } - else - { - // We don't have an HFA - useType = TYP_UNKNOWN; - } - break; -#endif // _TARGET_ARM_ + { + BYTE gcPtr = 0; + // Check if this pointer-sized struct is wrapping a GC object + info.compCompHnd->getClassGClayout(clsHnd, &gcPtr); + useType = getJitGCType(gcPtr); + } + break; default: useType = TYP_UNKNOWN; @@ -733,7 +704,7 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS // getArgTypeForStruct: // Get the type that is used to pass values of the given struct type. // If you have already retrieved the struct size then it should be -// passed as the optional third argument, as this allows us to avoid +// passed as the optional fourth argument, as this allows us to avoid // an extra call to getClassSize(clsHnd) // // Arguments: @@ -802,11 +773,11 @@ var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, else #endif // UNIX_AMD64_ABI - // The largest primitive type is 8 bytes (TYP_DOUBLE) + // The largest arg passed in a single register is MAX_PASS_SINGLEREG_BYTES, // so we can skip calling getPrimitiveTypeForStruct when we // have a struct that is larger than that. // - if (structSize <= sizeof(double)) + if (structSize <= MAX_PASS_SINGLEREG_BYTES) { // We set the "primitive" useType based upon the structSize // and also examine the clsHnd to see if it is an HFA of count one @@ -829,14 +800,21 @@ var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, // if (structSize <= MAX_PASS_MULTIREG_BYTES) { - // Structs that are HFA's are passed by value in multiple registers - if (IsHfa(clsHnd) + // Structs that are HFA/HVA's are passed by value in multiple registers. + // Arm64 Windows VarArg methods arguments will not classify HFA/HVA types, they will need to be treated + // as if they are not HFA/HVA types. + var_types hfaType; #if defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) - && !isVarArg // Arm64 Windows VarArg methods arguments will not - // classify HFA types, they will need to be treated - // as if they are not HFA types. -#endif // defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) - ) + if (isVarArg) + { + hfaType = TYP_UNDEF; + } + else +#endif // defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) + { + hfaType = GetHfaType(clsHnd); + } + if (varTypeIsValidHfaType(hfaType)) { // HFA's of count one should have been handled by getPrimitiveTypeForStruct assert(GetHfaCount(clsHnd) >= 2); @@ -851,7 +829,6 @@ var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, { #ifdef UNIX_AMD64_ABI - // The case of (structDesc.eightByteCount == 1) should have already been handled if ((structDesc.eightByteCount > 1) || !structDesc.passedInRegisters) { @@ -1035,10 +1012,10 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, // Check for cases where a small struct is returned in a register // via a primitive type. // - // The largest primitive type is 8 bytes (TYP_DOUBLE) + // The largest "primitive type" is MAX_PASS_SINGLEREG_BYTES // so we can skip calling getPrimitiveTypeForStruct when we // have a struct that is larger than that. - if (canReturnInRegister && (useType == TYP_UNKNOWN) && (structSize <= sizeof(double))) + if (canReturnInRegister && (useType == TYP_UNKNOWN) && (structSize <= MAX_PASS_SINGLEREG_BYTES)) { // We set the "primitive" useType based upon the structSize // and also examine the clsHnd to see if it is an HFA of count one @@ -1070,7 +1047,7 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, // because when HFA are enabled, normally we would use two FP registers to pass or return it // // But if we don't have support for multiple register return types, we have to change this. - // Since we what we have an 8-byte struct (float + float) we change useType to TYP_I_IMPL + // Since what we have is an 8-byte struct (float + float) we change useType to TYP_I_IMPL // so that the struct is returned instead using an 8-byte integer register. // if ((FEATURE_MULTIREG_RET == 0) && (useType == TYP_UNKNOWN) && (structSize == (2 * sizeof(float))) && IsHfa(clsHnd)) diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 24153d6f51c3..b091c929c998 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -134,6 +134,61 @@ const unsigned FLG_CCTOR = (CORINFO_FLG_CONSTRUCTOR | CORINFO_FLG_STATIC); const int BAD_STK_OFFS = 0xBAADF00D; // for LclVarDsc::lvStkOffs #endif +//------------------------------------------------------------------------ +// HFA info shared by LclVarDsc and fgArgTabEntry +//------------------------------------------------------------------------ +#ifdef FEATURE_HFA +enum HfaElemKind : unsigned int +{ + HFA_ELEM_NONE, + HFA_ELEM_FLOAT, + HFA_ELEM_DOUBLE, + HFA_ELEM_SIMD16 +}; +inline bool IsHfa(HfaElemKind kind) +{ + return kind != HFA_ELEM_NONE; +} +inline var_types HfaTypeFromElemKind(HfaElemKind kind) +{ + switch (kind) + { + case HFA_ELEM_FLOAT: + return TYP_FLOAT; + case HFA_ELEM_DOUBLE: + return TYP_DOUBLE; +#ifdef FEATURE_SIMD + case HFA_ELEM_SIMD16: + return TYP_SIMD16; +#endif + case HFA_ELEM_NONE: + return TYP_UNDEF; + default: + assert(!"Invalid HfaElemKind"); + return TYP_UNDEF; + } +} +inline HfaElemKind HfaElemKindFromType(var_types type) +{ + switch (type) + { + case TYP_FLOAT: + return HFA_ELEM_FLOAT; + case TYP_DOUBLE: + return HFA_ELEM_DOUBLE; +#ifdef FEATURE_SIMD + case TYP_SIMD16: + return HFA_ELEM_SIMD16; +#endif + case TYP_UNDEF: + return HFA_ELEM_NONE; + default: + assert(!"Invalid HFA Type"); + return HFA_ELEM_NONE; + } +} +#endif // FEATURE_HFA + // The following holds the Local var info (scope information) typedef const char* VarName; // Actual ASCII string struct VarScopeDsc @@ -555,8 +610,12 @@ class LclVarDsc unsigned char lvHasILStoreOp : 1; // there is at least one STLOC or STARG on this local unsigned char lvHasMultipleILStoreOp : 1; // there is more than one STLOC on this local - unsigned char lvIsTemp : 1; // Short-lifetime compiler temp (if lvIsParam is false), or implicit byref parameter - // (if lvIsParam is true) + unsigned char lvIsTemp : 1; // Short-lifetime compiler temp + +#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + unsigned char lvIsImplicitByRef : 1; // Set if the argument is an implicit byref. +#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + #if OPT_BOOL_OPS unsigned char lvIsBoolean : 1; // set if variable is boolean #endif @@ -595,11 +654,8 @@ class LclVarDsc unsigned char lvIsMultiRegRet : 1; // true if this is a multireg LclVar struct assigned from a multireg call #ifdef FEATURE_HFA - unsigned char _lvIsHfa : 1; // Is this a struct variable who's class handle is an HFA type - unsigned char _lvIsHfaRegArg : 1; // Is this a HFA argument variable? // TODO-CLEANUP: Remove this and replace - // with (lvIsRegArg && lvIsHfa()) - unsigned char _lvHfaTypeIsFloat : 1; // Is the HFA type float or double? -#endif // FEATURE_HFA + HfaElemKind _lvHfaElemKind : 2; // What kind of an HFA this is (HFA_ELEM_NONE if it is not an HFA). +#endif // FEATURE_HFA #ifdef DEBUG // TODO-Cleanup: See the note on lvSize() - this flag is only in use by asserts that are checking for struct @@ -666,70 +722,60 @@ class LclVarDsc bool lvIsHfa() const { #ifdef FEATURE_HFA - return _lvIsHfa; + return IsHfa(_lvHfaElemKind); #else return false; #endif } - void lvSetIsHfa() - { -#ifdef FEATURE_HFA - _lvIsHfa = true; -#endif - } - bool lvIsHfaRegArg() const { #ifdef FEATURE_HFA - return _lvIsHfaRegArg; + return lvIsRegArg && lvIsHfa(); #else return false; #endif } - void lvSetIsHfaRegArg(bool value = true) - { -#ifdef FEATURE_HFA - _lvIsHfaRegArg = value; -#endif - } - - bool lvHfaTypeIsFloat() const - { -#ifdef FEATURE_HFA - return _lvHfaTypeIsFloat; -#else - return false; -#endif - } - - void lvSetHfaTypeIsFloat(bool value) - { -#ifdef FEATURE_HFA - _lvHfaTypeIsFloat = value; -#endif - } - - // on Arm64 - Returns 1-4 indicating the number of register slots used by the HFA - // on Arm32 - Returns the total number of single FP register slots used by the HFA, max is 8 + //------------------------------------------------------------------------------ + // lvHfaSlots: Get the number of slots used by an HFA local + // + // Return Value: + // On Arm64 - Returns 1-4 indicating the number of register slots used by the HFA + // On Arm32 - Returns the total number of single FP register slots used by the HFA, max is 8 // unsigned lvHfaSlots() const { assert(lvIsHfa()); assert(varTypeIsStruct(lvType)); + unsigned slots = 0; #ifdef _TARGET_ARM_ - return lvExactSize / sizeof(float); -#else // _TARGET_ARM64_ - if (lvHfaTypeIsFloat()) - { - return lvExactSize / sizeof(float); - } - else + slots = lvExactSize / sizeof(float); + assert(slots <= 8); +#elif defined(_TARGET_ARM64_) + switch (_lvHfaElemKind) { - return lvExactSize / sizeof(double); + case HFA_ELEM_NONE: + assert(!"lvHfaSlots called for non-HFA"); + break; + case HFA_ELEM_FLOAT: + assert((lvExactSize % 4) == 0); + slots = lvExactSize >> 2; + break; + case HFA_ELEM_DOUBLE: + assert((lvExactSize % 8) == 0); + slots = lvExactSize >> 3; + break; + case HFA_ELEM_SIMD16: + assert((lvExactSize % 16) == 0); + slots = lvExactSize >> 4; + break; + default: + unreached(); } + assert(slots <= 4); #endif // _TARGET_ARM64_ + return slots; } // lvIsMultiRegArgOrRet() @@ -750,7 +796,7 @@ class LclVarDsc regNumberSmall _lvOtherReg; // Used for "upper half" of long var. #endif // !defined(_TARGET_64BIT_) - regNumberSmall _lvArgReg; // The register in which this argument is passed. + regNumberSmall _lvArgReg; // The (first) register in which this argument is passed. #if FEATURE_MULTIREG_ARGS regNumberSmall _lvOtherArgReg; // Used for the second part of the struct passed in a register. @@ -915,7 +961,7 @@ class LclVarDsc private: unsigned short m_lvRefCnt; // unweighted (real) reference count. For implicit by reference - // parameters, this gets hijacked from fgMarkImplicitByRefArgs + // parameters, this gets hijacked from fgResetImplicitByRefRefCount // through fgMarkDemotedImplicitByRefArgs, to provide a static // appearance count (computed during address-exposed analysis) // that fgMakeOutgoingStructArgCopy consults during global morph @@ -1030,14 +1076,22 @@ class LclVarDsc { return isFloatRegType(lvType) || lvIsHfaRegArg(); } + var_types GetHfaType() const { - return lvIsHfa() ? (lvHfaTypeIsFloat() ? TYP_FLOAT : TYP_DOUBLE) : TYP_UNDEF; +#ifdef FEATURE_HFA + assert(lvIsHfa()); + return HfaTypeFromElemKind(_lvHfaElemKind); +#else + return TYP_UNDEF; +#endif // FEATURE_HFA } + void SetHfaType(var_types type) { - assert(varTypeIsFloating(type)); - lvSetHfaTypeIsFloat(type == TYP_FLOAT); +#ifdef FEATURE_HFA + _lvHfaElemKind = HfaElemKindFromType(type); +#endif // FEATURE_HFA } var_types lvaArgType(); @@ -1487,8 +1541,7 @@ struct fgArgTabEntry bool _isSplit : 1; // True when this argument is split between the registers and OutArg area #endif // FEATURE_ARG_SPLIT #ifdef FEATURE_HFA - bool _isHfaArg : 1; // True when the argument is an HFA type. - bool _isDoubleHfa : 1; // True when the argument is an HFA, with an element type of DOUBLE. + HfaElemKind _hfaElemKind : 2; // What kind of an HFA this is (HFA_ELEM_NONE if it is not an HFA). #endif bool isLateArg() @@ -1569,7 +1622,7 @@ struct fgArgTabEntry bool getIsHfaArg() { #ifdef FEATURE_HFA - return _isHfaArg; + return IsHfa(_hfaElemKind); #else return false; #endif @@ -1579,23 +1632,23 @@ struct fgArgTabEntry bool getIsHfaRegArg() { #ifdef FEATURE_HFA - return _isHfaArg && isPassedInRegisters(); + return IsHfa(_hfaElemKind) && isPassedInRegisters(); #else return false; #endif } - __declspec(property(get = getHfaType)) var_types hfaType; - var_types getHfaType() + __declspec(property(get = GetHfaType)) var_types hfaType; + var_types GetHfaType() { #ifdef FEATURE_HFA - return _isHfaArg ? (_isDoubleHfa ? TYP_DOUBLE : TYP_FLOAT) : TYP_UNDEF; + return HfaTypeFromElemKind(_hfaElemKind); #else return TYP_UNDEF; -#endif +#endif // FEATURE_HFA } - void setHfaType(var_types type, unsigned hfaSlots) + void SetHfaType(var_types type, unsigned hfaSlots) { #ifdef FEATURE_HFA if (type != TYP_UNDEF) @@ -1607,29 +1660,33 @@ struct fgArgTabEntry // Note that hfaSlots is the number of registers we will use. For ARM, that is twice // the number of "double registers". unsigned numHfaRegs = hfaSlots; - if (isPassedInRegisters()) - { #ifdef _TARGET_ARM_ - if (type == TYP_DOUBLE) - { - // Must be an even number of registers. - assert((numRegs & 1) == 0); - numHfaRegs = hfaSlots / 2; - } + if (type == TYP_DOUBLE) + { + // Must be an even number of registers. + assert((numRegs & 1) == 0); + numHfaRegs = hfaSlots / 2; + } #endif // _TARGET_ARM_ - if (_isHfaArg) + + if (!isHfaArg) + { + // We haven't previously set this; do so now. + _hfaElemKind = HfaElemKindFromType(type); + if (isPassedInRegisters()) { - // This should already be set correctly. - assert(numRegs == numHfaRegs); - assert(_isDoubleHfa == (type == TYP_DOUBLE)); + numRegs = numHfaRegs; } - else + } + else + { + // We've already set this; ensure that it's consistent. + if (isPassedInRegisters()) { - numRegs = numHfaRegs; + assert(numRegs == numHfaRegs); } + assert(type == HfaTypeFromElemKind(_hfaElemKind)); } - _isDoubleHfa = (type == TYP_DOUBLE); - _isHfaArg = true; } #endif // FEATURE_HFA } @@ -1701,22 +1758,32 @@ struct fgArgTabEntry { unsigned size = getSlotCount(); #ifdef FEATURE_HFA -#ifdef _TARGET_ARM_ - // We counted the number of regs, but if they are DOUBLE hfa regs we have to double the size. - if (isHfaRegArg && (hfaType == TYP_DOUBLE)) + if (isHfaRegArg) { - assert(!isSplit); - size <<= 1; - } +#ifdef _TARGET_ARM_ + // We counted the number of regs, but if they are DOUBLE hfa regs we have to double the size. + if (hfaType == TYP_DOUBLE) + { + assert(!isSplit); + size <<= 1; + } #elif defined(_TARGET_ARM64_) - // We counted the number of regs, but if they are FLOAT hfa regs we have to halve the size. - if (isHfaRegArg && (hfaType == TYP_FLOAT)) - { - // Round up in case of odd HFA count. - size = (size + 1) >> 1; - } + // We counted the number of regs, but if they are FLOAT hfa regs we have to halve the size, + // or if they are SIMD16 vector hfa regs we have to double the size. + if (hfaType == TYP_FLOAT) + { + // Round up in case of odd HFA count. + size = (size + 1) >> 1; + } +#ifdef FEATURE_SIMD + else if (hfaType == TYP_SIMD16) + { + size <<= 1; + } +#endif // FEATURE_SIMD #endif // _TARGET_ARM64_ -#endif + } +#endif // FEATURE_HFA return size; } @@ -2864,11 +2931,13 @@ class Compiler #ifdef DEBUG void gtDispNode(GenTree* tree, IndentStack* indentStack, __in_z const char* msg, bool isLIR); - void gtDispVN(GenTree* tree); void gtDispConst(GenTree* tree); void gtDispLeaf(GenTree* tree, IndentStack* indentStack); void gtDispNodeName(GenTree* tree); void gtDispRegVal(GenTree* tree); + void gtDispZeroFieldSeq(GenTree* tree); + void gtDispVN(GenTree* tree); + void gtDispCommonEndLine(GenTree* tree); enum IndentInfo { @@ -3285,16 +3354,16 @@ class Compiler BOOL lvaIsOriginalThisReadOnly(); // return TRUE if there is no place in the code // that writes to arg0 - // Struct parameters that are passed by reference are marked as both lvIsParam and lvIsTemp - // (this is an overload of lvIsTemp because there are no temp parameters). // For x64 this is 3, 5, 6, 7, >8 byte structs that are passed by reference. // For ARM64, this is structs larger than 16 bytes that are passed by reference. bool lvaIsImplicitByRefLocal(unsigned varNum) { #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) - LclVarDsc* varDsc = &(lvaTable[varNum]); - if (varDsc->lvIsParam && varDsc->lvIsTemp) + LclVarDsc* varDsc = lvaGetDesc(varNum); + if (varDsc->lvIsImplicitByRef) { + assert(varDsc->lvIsParam); + assert(varTypeIsStruct(varDsc) || (varDsc->lvType == TYP_BYREF)); return true; } @@ -5606,8 +5675,8 @@ class Compiler void fgMorphStructField(GenTree* tree, GenTree* parent); void fgMorphLocalField(GenTree* tree, GenTree* parent); - // Identify which parameters are implicit byrefs, and flag their LclVarDscs. - void fgMarkImplicitByRefArgs(); + // Reset the refCount for implicit byrefs. + void fgResetImplicitByRefRefCount(); // Change implicit byrefs' types from struct to pointer, and for any that were // promoted, create new promoted struct temps. @@ -6722,7 +6791,7 @@ class Compiler fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree); GenTree* optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test); GenTree* optVNConstantPropOnTree(BasicBlock* block, GenTree* tree); - GenTree* optPrepareTreeForReplacement(GenTree* extractTree, GenTree* replaceTree); + GenTree* optExtractSideEffListFromConst(GenTree* tree); AssertionIndex GetAssertionCount() { @@ -7612,6 +7681,17 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Should we support SIMD intrinsics? bool featureSIMD; + // Should we recognize SIMD types? + // We always do this on ARM64 to support HVA types. + bool supportSIMDTypes() + { +#ifdef _TARGET_ARM64_ + return true; +#else + return featureSIMD; +#endif + } + // Have we identified any SIMD types? // This is currently used by struct promotion to avoid getting type information for a struct // field to see if it is a SIMD type, if we haven't seen any SIMD types or operations in diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp index 901a58ec9e35..9b1054272274 100644 --- a/src/jit/compiler.hpp +++ b/src/jit/compiler.hpp @@ -1756,8 +1756,15 @@ inline void LclVarDsc::incRefCnts(BasicBlock::weight_t weight, Compiler* comp, R if (weight != 0) { // We double the weight of internal temps - // - if (lvIsTemp && (weight * 2 > weight)) + + bool doubleWeight = lvIsTemp; + +#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + // and, for the time being, implict byref params + doubleWeight |= lvIsImplicitByRef; +#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + + if (doubleWeight && (weight * 2 > weight)) { weight *= 2; } @@ -2919,7 +2926,7 @@ inline regNumber genMapFloatRegArgNumToRegNum(unsigned argNum) __forceinline regNumber genMapRegArgNumToRegNum(unsigned argNum, var_types type) { - if (varTypeIsFloating(type)) + if (varTypeUsesFloatArgReg(type)) { return genMapFloatRegArgNumToRegNum(argNum); } @@ -2957,7 +2964,7 @@ inline regMaskTP genMapFloatRegArgNumToRegMask(unsigned argNum) __forceinline regMaskTP genMapArgNumToRegMask(unsigned argNum, var_types type) { regMaskTP result; - if (varTypeIsFloating(type)) + if (varTypeUsesFloatArgReg(type)) { result = genMapFloatRegArgNumToRegMask(argNum); #ifdef _TARGET_ARM_ @@ -3076,7 +3083,7 @@ inline unsigned genMapFloatRegNumToRegArgNum(regNumber regNum) inline unsigned genMapRegNumToRegArgNum(regNumber regNum, var_types type) { - if (varTypeIsFloating(type)) + if (varTypeUsesFloatArgReg(type)) { return genMapFloatRegNumToRegArgNum(regNum); } diff --git a/src/jit/dll/CMakeLists.txt b/src/jit/dll/CMakeLists.txt index 636ca8d7f85a..9e930de69d24 100644 --- a/src/jit/dll/CMakeLists.txt +++ b/src/jit/dll/CMakeLists.txt @@ -1,5 +1,7 @@ project(ClrJit) +set_source_files_properties(${JIT_EXPORTS_FILE} PROPERTIES GENERATED TRUE) + if(CLR_CMAKE_PLATFORM_UNIX) add_compile_options(-fPIC) diff --git a/src/jit/emit.h b/src/jit/emit.h index 1308531a9085..b429920c38d3 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -1374,7 +1374,7 @@ class emitter void emitDispClsVar(CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, bool reloc = false); void emitDispFrameRef(int varx, int disp, int offs, bool asmfm); void emitDispInsOffs(unsigned offs, bool doffs); - void emitDispInsHex(BYTE* code, size_t sz); + void emitDispInsHex(instrDesc* id, BYTE* code, size_t sz); #else // !DEBUG #define emitVarRefOffs 0 diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp index 3d7089bb8a13..9e36efb4df59 100644 --- a/src/jit/emitarm.cpp +++ b/src/jit/emitarm.cpp @@ -6778,7 +6778,7 @@ void emitter::emitDispGC(emitAttr attr) * Display (optionally) the instruction encoding in hex */ -void emitter::emitDispInsHex(BYTE* code, size_t sz) +void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) { // We do not display the instruction hex if we want diff-able disassembly if (!emitComp->opts.disDiffable) @@ -6791,6 +6791,27 @@ void emitter::emitDispInsHex(BYTE* code, size_t sz) { printf(" %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2)))); } + else + { + assert(sz == 0); + + // At least display the encoding size of the instruction, even if not displaying its actual encoding. + insSize isz = emitInsSize(id->idInsFmt()); + switch (isz) + { + case ISZ_16BIT: + printf(" 2B"); + break; + case ISZ_32BIT: + printf(" 4B"); + break; + case ISZ_48BIT: + printf(" 6B"); + break; + default: + unreached(); + } + } } } @@ -6822,7 +6843,7 @@ void emitter::emitDispInsHelp( /* Display the instruction hex code */ - emitDispInsHex(code, sz); + emitDispInsHex(id, code, sz); printf(" "); diff --git a/src/jit/emitarm64.cpp b/src/jit/emitarm64.cpp index afd5cf44e2a5..7f0c0df9768d 100644 --- a/src/jit/emitarm64.cpp +++ b/src/jit/emitarm64.cpp @@ -8422,9 +8422,8 @@ BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, inst { // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr assert(fmt == IF_LARGEADR); - ssize_t relPageAddr = - (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12; - dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg); + ssize_t relPageAddr = computeRelPageAddr((size_t)dstAddr, (size_t)srcAddr); + dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg); // add x, x, page offs -- compute address = page addr + page offs ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits @@ -8524,8 +8523,7 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) { // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr assert(fmt == IF_LARGELDC); - ssize_t relPageAddr = - (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12; + ssize_t relPageAddr = computeRelPageAddr((size_t)dstAddr, (size_t)srcAddr); if (isVectorRegister(dstReg)) { // Update addrReg with the reserved integer register @@ -10698,7 +10696,7 @@ void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, boo * Display (optionally) the instruction encoding in hex */ -void emitter::emitDispInsHex(BYTE* code, size_t sz) +void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) { // We do not display the instruction hex if we want diff-able disassembly if (!emitComp->opts.disDiffable) @@ -10709,6 +10707,7 @@ void emitter::emitDispInsHex(BYTE* code, size_t sz) } else { + assert(sz == 0); printf(" "); } } @@ -10742,7 +10741,7 @@ void emitter::emitDispIns( /* Display the instruction hex code */ - emitDispInsHex(pCode, sz); + emitDispInsHex(id, pCode, sz); printf(" "); diff --git a/src/jit/emitarm64.h b/src/jit/emitarm64.h index fefee04f343a..2a24b16041d8 100644 --- a/src/jit/emitarm64.h +++ b/src/jit/emitarm64.h @@ -669,6 +669,12 @@ static bool isValidImmCond(ssize_t imm); static bool isValidImmCondFlags(ssize_t imm); static bool isValidImmCondFlagsImm5(ssize_t imm); +// Computes page "delta" between two addresses +inline static ssize_t computeRelPageAddr(size_t dstAddr, size_t srcAddr) +{ + return (dstAddr >> 12) - (srcAddr >> 12); +} + /************************************************************************/ /* The public entry points to output instructions */ /************************************************************************/ diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index 6052b9749363..f7b3c5baa499 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -8049,7 +8049,7 @@ void emitter::emitDispShift(instruction ins, int cnt) * Display (optionally) the bytes for the instruction encoding in hex */ -void emitter::emitDispInsHex(BYTE* code, size_t sz) +void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) { // We do not display the instruction hex if we want diff-able disassembly if (!emitComp->opts.disDiffable) @@ -8216,7 +8216,7 @@ void emitter::emitDispIns( { /* Display the instruction hex code */ - emitDispInsHex(code, sz); + emitDispInsHex(id, code, sz); } /* Display the instruction name */ diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 3075cf3bc12d..236302cca5ae 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -20066,6 +20066,18 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 * printf(" "); + // + // Display natural loop number + // + if (block->bbNatLoopNum == BasicBlock::NOT_IN_LOOP) + { + printf(" "); + } + else + { + printf("%2d ", block->bbNatLoopNum); + } + // // Display block IL range // @@ -20326,11 +20338,11 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, // clang-format off printf("\n"); - printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n", + printf("------%*s-------------------------------------%*s--------------------------%*s----------------------------------------\n", padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); - printf("BBnum %*sBBid ref try hnd %s weight %*s%s [IL range] [jump]%*s [EH region] [flags]\n", + printf("BBnum %*sBBid ref try hnd %s weight %*s%s lp [IL range] [jump]%*s [EH region] [flags]\n", padWidth, "", fgCheapPredsValid ? "cheap preds" : (fgComputePredsDone ? "preds " @@ -20340,7 +20352,7 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, : ""), maxBlockNumWidth, "" ); - printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n", + printf("------%*s-------------------------------------%*s--------------------------%*s----------------------------------------\n", padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); @@ -20364,17 +20376,19 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, if (block == fgFirstColdBlock) { - printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~" - "~~~~~~~~~~~~~~~~\n", - padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~"); + printf( + "~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~" + "~~~~~~~~~~~~~~~~\n", + padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~"); } #if FEATURE_EH_FUNCLETS if (block == fgFirstFuncletBB) { - printf("++++++%*s+++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++" - "++++++++++++++++ funclets follow\n", - padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++"); + printf( + "++++++%*s+++++++++++++++++++++++++++++++++++++%*s++++++++++++++++++++++++++%*s++++++++++++++++++++++++" + "++++++++++++++++ funclets follow\n", + padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++"); } #endif // FEATURE_EH_FUNCLETS @@ -20386,9 +20400,10 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, } } - printf("------%*s-------------------------------------%*s-----------------------%*s--------------------------------" - "--------\n", - padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); + printf( + "------%*s-------------------------------------%*s--------------------------%*s--------------------------------" + "--------\n", + padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); if (dumpTrees) { @@ -23258,7 +23273,7 @@ GenTreeStmt* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo) if (varTypeIsStruct(argType)) { structHnd = gtGetStructHandleIfPresent(argNode); - noway_assert(structHnd != NO_CLASS_HANDLE); + noway_assert((structHnd != NO_CLASS_HANDLE) || (argType != TYP_STRUCT)); } // Unsafe value cls check is not needed for diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 833d115cb2cc..9e58db0df4fe 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -7943,15 +7943,15 @@ GenTree* Compiler::gtGetThisArg(GenTreeCall* call) if (call->gtCallLateArgs) { - regNumber thisReg = REG_ARG_0; unsigned argNum = 0; fgArgTabEntry* thisArgTabEntry = gtArgEntryByArgNum(call, argNum); GenTree* result = thisArgTabEntry->node; -#if !FEATURE_FIXED_OUT_ARGS - GenTree* lateArgs = call->gtCallLateArgs; - regList list = call->regArgList; - int index = 0; +#if !FEATURE_FIXED_OUT_ARGS && defined(DEBUG) + regNumber thisReg = REG_ARG_0; + GenTree* lateArgs = call->gtCallLateArgs; + regList list = call->regArgList; + int index = 0; while (lateArgs != NULL) { assert(lateArgs->gtOper == GT_LIST); @@ -7959,16 +7959,13 @@ GenTree* Compiler::gtGetThisArg(GenTreeCall* call) regNumber curArgReg = list[index]; if (curArgReg == thisReg) { - if (optAssertionPropagatedCurrentStmt) - result = lateArgs->gtOp.gtOp1; - assert(result == lateArgs->gtOp.gtOp1); } lateArgs = lateArgs->gtOp.gtOp2; index++; } -#endif +#endif // !FEATURE_FIXED_OUT_ARGS && defined(DEBUG) return result; } } @@ -9223,6 +9220,29 @@ void Compiler::gtDispNodeName(GenTree* tree) } } +//------------------------------------------------------------------------ +// gtDispZeroFieldSeq: If this node has a zero fieldSeq annotation +// then print this Field Sequence +// +void Compiler::gtDispZeroFieldSeq(GenTree* tree) +{ + NodeToFieldSeqMap* map = GetZeroOffsetFieldMap(); + + // THe most common case is having no entries in this map + if (map->GetCount() > 0) + { + FieldSeqNode* fldSeq = nullptr; + if (map->Lookup(tree, &fldSeq)) + { + printf(" Zero"); + gtDispFieldSeq(fldSeq); + } + } +} + +//------------------------------------------------------------------------ +// gtDispVN: Utility function that prints a tree's ValueNumber: gtVNPair +// void Compiler::gtDispVN(GenTree* tree) { if (tree->gtVNPair.GetLiberal() != ValueNumStore::NoVN) @@ -9233,6 +9253,22 @@ void Compiler::gtDispVN(GenTree* tree) } } +//------------------------------------------------------------------------ +// gtDispCommonEndLine +// Utility function that prints the following node information +// 1: The associated zero field sequence (if any) +// 2. The register assigned to this node (if any) +// 2. The value number assigned (if any) +// 3. A newline character +// +void Compiler::gtDispCommonEndLine(GenTree* tree) +{ + gtDispZeroFieldSeq(tree); + gtDispRegVal(tree); + gtDispVN(tree); + printf("\n"); +} + //------------------------------------------------------------------------ // gtDispNode: Print a tree to jitstdout. // @@ -10192,8 +10228,6 @@ void Compiler::gtDispConst(GenTree* tree) default: assert(!"unexpected constant node"); } - - gtDispRegVal(tree); } void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn) @@ -10445,8 +10479,6 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) default: assert(!"don't know how to display tree leaf node"); } - - gtDispRegVal(tree); } //------------------------------------------------------------------------ @@ -10509,14 +10541,14 @@ void Compiler::gtDispTree(GenTree* tree, if (IsUninitialized(tree)) { /* Value used to initalize nodes */ - printf("Uninitialized tree node!"); + printf("Uninitialized tree node!\n"); return; } if (tree->gtOper >= GT_COUNT) { gtDispNode(tree, indentStack, msg, isLIR); - printf("Bogus operator!"); + printf("Bogus operator!\n"); return; } @@ -10526,8 +10558,8 @@ void Compiler::gtDispTree(GenTree* tree, { gtDispNode(tree, indentStack, msg, isLIR); gtDispLeaf(tree, indentStack); - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (tree->OperIsLocalStore() && !topOnly) { gtDispChild(tree->gtOp.gtOp1, indentStack, IINone); @@ -10574,8 +10606,7 @@ void Compiler::gtDispTree(GenTree* tree, if (tree->OperGet() == GT_PHI) { gtDispNode(tree, indentStack, msg, isLIR); - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly) { @@ -10816,9 +10847,7 @@ void Compiler::gtDispTree(GenTree* tree, } #endif // FEATURE_HW_INTRINSICS - gtDispRegVal(tree); - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly && tree->gtOp.gtOp1) { @@ -10869,18 +10898,13 @@ void Compiler::gtDispTree(GenTree* tree, printf(" %s", eeGetFieldName(tree->gtField.gtFldHnd), 0); } + gtDispCommonEndLine(tree); + if (tree->gtField.gtFldObj && !topOnly) { - gtDispVN(tree); - printf("\n"); gtDispChild(tree->gtField.gtFldObj, indentStack, IIArcBottom); } - else - { - gtDispRegVal(tree); - gtDispVN(tree); - printf("\n"); - } + break; case GT_CALL: @@ -10915,12 +10939,7 @@ void Compiler::gtDispTree(GenTree* tree, printf(" (exactContextHnd=0x%p)", dspPtr(call->gtInlineCandidateInfo->exactContextHnd)); } - gtDispVN(call); - if (call->IsMultiRegCall()) - { - gtDispRegVal(call); - } - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly) { @@ -10991,8 +11010,7 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_ARR_ELEM: - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly) { @@ -11008,8 +11026,8 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_ARR_OFFSET: - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { gtDispChild(tree->gtArrOffs.gtOffset, indentStack, IIArc, nullptr, topOnly); @@ -11019,8 +11037,8 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_CMPXCHG: - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { gtDispChild(tree->gtCmpXchg.gtOpLocation, indentStack, IIArc, nullptr, topOnly); @@ -11036,8 +11054,8 @@ void Compiler::gtDispTree(GenTree* tree, #ifdef FEATURE_HW_INTRINSICS case GT_HW_INTRINSIC_CHK: #endif // FEATURE_HW_INTRINSICS - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { gtDispChild(tree->gtBoundsChk.gtIndex, indentStack, IIArc, nullptr, topOnly); @@ -11055,8 +11073,8 @@ void Compiler::gtDispTree(GenTree* tree, { printf(" (init)"); } - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { if (tree->gtDynBlk.Data() != nullptr) @@ -12902,7 +12920,8 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp) return nullptr; } - GenTree* flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_REMOVE_BUT_NOT_NARROW); + // Do likewise with flagOp. + GenTree* flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_DONT_REMOVE); if (flagVal == nullptr) { // Note we may fail here if the flag operand comes from @@ -12911,19 +12930,29 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp) return nullptr; } + // Only proceed when both box sources have the same actual type. + // (this rules out long/int mismatches) + if (genActualType(thisVal->TypeGet()) != genActualType(flagVal->TypeGet())) + { + JITDUMP("bailing, pre-boxed values have different types\n"); + return nullptr; + } + // Yes, both boxes can be cleaned up. Optimize. JITDUMP("Optimizing call to Enum.HasFlag\n"); - // Undo the boxing of thisOp and prepare to operate directly - // on the original enum values. + // Undo the boxing of the Ops and prepare to operate directly + // on the pre-boxed values. thisVal = gtTryRemoveBoxUpstreamEffects(thisOp, BR_REMOVE_BUT_NOT_NARROW); + flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_REMOVE_BUT_NOT_NARROW); - // Our trial removal above should guarantee successful removal here. + // Our trial removals above should guarantee successful removals here. assert(thisVal != nullptr); + assert(flagVal != nullptr); + assert(genActualType(thisVal->TypeGet()) == genActualType(flagVal->TypeGet())); - // We should have a consistent view of the type - var_types type = thisVal->TypeGet(); - assert(type == flagVal->TypeGet()); + // Type to use for optimized check + var_types type = genActualType(thisVal->TypeGet()); // The thisVal and flagVal trees come from earlier statements. // @@ -17653,7 +17682,8 @@ GenTreeSIMD* Compiler::gtNewSIMDNode( assert(op1 != nullptr); SetOpLclRelatedToSIMDIntrinsic(op1); - return new (this, GT_SIMD) GenTreeSIMD(type, op1, simdIntrinsicID, baseType, size); + GenTreeSIMD* simdNode = new (this, GT_SIMD) GenTreeSIMD(type, op1, simdIntrinsicID, baseType, size); + return simdNode; } GenTreeSIMD* Compiler::gtNewSIMDNode( @@ -17663,7 +17693,8 @@ GenTreeSIMD* Compiler::gtNewSIMDNode( SetOpLclRelatedToSIMDIntrinsic(op1); SetOpLclRelatedToSIMDIntrinsic(op2); - return new (this, GT_SIMD) GenTreeSIMD(type, op1, op2, simdIntrinsicID, baseType, size); + GenTreeSIMD* simdNode = new (this, GT_SIMD) GenTreeSIMD(type, op1, op2, simdIntrinsicID, baseType, size); + return simdNode; } //------------------------------------------------------------------- @@ -18035,7 +18066,7 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HA case Compiler::SPK_PrimitiveType: { assert(returnType != TYP_UNKNOWN); - assert(!varTypeIsStruct(returnType)); + assert(returnType != TYP_STRUCT); m_regType[0] = returnType; break; } @@ -18046,7 +18077,7 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HA var_types hfaType = comp->GetHfaType(retClsHnd); // We should have an hfa struct type - assert(varTypeIsFloating(hfaType)); + assert(varTypeIsValidHfaType(hfaType)); // Note that the retail build issues a warning about a potential divsion by zero without this Max function unsigned elemSize = Max((unsigned)1, EA_SIZE_IN_BYTES(emitActualTypeSize(hfaType))); diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 5d45427a395b..b294748b67c8 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -3532,6 +3532,9 @@ struct GenTreeCall final : public GenTree return varTypeIsLong(gtType); #elif FEATURE_MULTIREG_RET && defined(_TARGET_ARM_) return varTypeIsLong(gtType) || (varTypeIsStruct(gtType) && !HasRetBufArg()); +#elif defined(FEATURE_HFA) && defined(_TARGET_ARM64_) + // SIMD types are returned in vector regs on ARM64. + return (gtType == TYP_STRUCT) && !HasRetBufArg(); #elif FEATURE_MULTIREG_RET return varTypeIsStruct(gtType) && !HasRetBufArg(); #else diff --git a/src/jit/hwintrinsicArm64.cpp b/src/jit/hwintrinsicArm64.cpp index 98b495623855..dec60383bd2e 100644 --- a/src/jit/hwintrinsicArm64.cpp +++ b/src/jit/hwintrinsicArm64.cpp @@ -214,8 +214,8 @@ GenTree* Compiler::addRangeCheckIfNeeded(GenTree* immOp, unsigned int max, bool { assert(immOp != nullptr); - // Need to range check only if we're must expand and don't have an appropriate constant - if (mustExpand && (!immOp->IsCnsIntOrI() || (immOp->AsIntConCommon()->IconValue() < max))) + // Need to range check only if we're must expand. + if (mustExpand) { GenTree* upperBoundNode = new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, max); GenTree* index = nullptr; @@ -463,20 +463,40 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, return gtNewSimdHWIntrinsicNode(simdType, op1, intrinsic, simdBaseType, simdSizeBytes); case HWIntrinsicInfo::SimdExtractOp: - op2 = - addRangeCheckIfNeeded(impPopStack().val, getSIMDVectorLength(simdSizeBytes, simdBaseType), mustExpand); + { + int vectorLength = getSIMDVectorLength(simdSizeBytes, simdBaseType); + op2 = impStackTop().val; + if (!mustExpand && (!op2->IsCnsIntOrI() || op2->AsIntConCommon()->IconValue() >= vectorLength)) + { + // This is either an out-of-range constant or a non-constant. + // We won't expand it; it will be handled recursively, at which point 'mustExpand' + // will be true. + return nullptr; + } + op2 = impPopStack().val; + op2 = addRangeCheckIfNeeded(op2, vectorLength, mustExpand); op1 = impSIMDPopStack(simdType); return gtNewScalarHWIntrinsicNode(JITtype2varType(sig->retType), op1, op2, intrinsic); - + } case HWIntrinsicInfo::SimdInsertOp: + { + int vectorLength = getSIMDVectorLength(simdSizeBytes, simdBaseType); + op2 = impStackTop(1).val; + if (!mustExpand && (!op2->IsCnsIntOrI() || op2->AsIntConCommon()->IconValue() >= vectorLength)) + { + // This is either an out-of-range constant or a non-constant. + // We won't expand it; it will be handled recursively, at which point 'mustExpand' + // will be true. + return nullptr; + } op3 = impPopStack().val; - op2 = - addRangeCheckIfNeeded(impPopStack().val, getSIMDVectorLength(simdSizeBytes, simdBaseType), mustExpand); + op2 = impPopStack().val; + op2 = addRangeCheckIfNeeded(op2, vectorLength, mustExpand); op1 = impSIMDPopStack(simdType); return gtNewSimdHWIntrinsicNode(simdType, op1, op2, op3, intrinsic, simdBaseType, simdSizeBytes); - + } case HWIntrinsicInfo::Sha1HashOp: op3 = impSIMDPopStack(simdType); op2 = impPopStack().val; diff --git a/src/jit/hwintrinsiccodegenxarch.cpp b/src/jit/hwintrinsiccodegenxarch.cpp index c5f583a44be7..2866e76ae8c4 100644 --- a/src/jit/hwintrinsiccodegenxarch.cpp +++ b/src/jit/hwintrinsiccodegenxarch.cpp @@ -395,7 +395,7 @@ void CodeGen::genHWIntrinsic_R_RM(GenTreeHWIntrinsic* node, instruction ins, emi if (op2 != nullptr) { - // The Compare*OrderedScalar and Compare*UnorderedScalar intrinsics come down this + // The CompareScalarOrdered* and CompareScalarUnordered* intrinsics come down this // code path. They are all MultiIns, as the return value comes from the flags and // we have two operands instead. @@ -1390,8 +1390,8 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) switch (intrinsicId) { - case NI_SSE_CompareEqualOrderedScalar: - case NI_SSE_CompareEqualUnorderedScalar: + case NI_SSE_CompareScalarOrderedEqual: + case NI_SSE_CompareScalarUnorderedEqual: { assert(baseType == TYP_FLOAT); regNumber tmpReg = node->GetSingleTempReg(); @@ -1408,8 +1408,8 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE_CompareGreaterThanOrderedScalar: - case NI_SSE_CompareGreaterThanUnorderedScalar: + case NI_SSE_CompareScalarOrderedGreaterThan: + case NI_SSE_CompareScalarUnorderedGreaterThan: { assert(baseType == TYP_FLOAT); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType); @@ -1420,8 +1420,8 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE_CompareGreaterThanOrEqualOrderedScalar: - case NI_SSE_CompareGreaterThanOrEqualUnorderedScalar: + case NI_SSE_CompareScalarOrderedGreaterThanOrEqual: + case NI_SSE_CompareScalarUnorderedGreaterThanOrEqual: { assert(baseType == TYP_FLOAT); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType); @@ -1432,8 +1432,8 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE_CompareLessThanOrderedScalar: - case NI_SSE_CompareLessThanUnorderedScalar: + case NI_SSE_CompareScalarOrderedLessThan: + case NI_SSE_CompareScalarUnorderedLessThan: { assert(baseType == TYP_FLOAT); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType); @@ -1444,8 +1444,8 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE_CompareLessThanOrEqualOrderedScalar: - case NI_SSE_CompareLessThanOrEqualUnorderedScalar: + case NI_SSE_CompareScalarOrderedLessThanOrEqual: + case NI_SSE_CompareScalarUnorderedLessThanOrEqual: { assert(baseType == TYP_FLOAT); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, node->gtSIMDBaseType); @@ -1456,8 +1456,8 @@ void CodeGen::genSSEIntrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE_CompareNotEqualOrderedScalar: - case NI_SSE_CompareNotEqualUnorderedScalar: + case NI_SSE_CompareScalarOrderedNotEqual: + case NI_SSE_CompareScalarUnorderedNotEqual: { assert(baseType == TYP_FLOAT); regNumber tmpReg = node->GetSingleTempReg(); @@ -1569,8 +1569,8 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_CompareEqualOrderedScalar: - case NI_SSE2_CompareEqualUnorderedScalar: + case NI_SSE2_CompareScalarOrderedEqual: + case NI_SSE2_CompareScalarUnorderedEqual: { assert(baseType == TYP_DOUBLE); regNumber tmpReg = node->GetSingleTempReg(); @@ -1587,8 +1587,8 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_CompareGreaterThanOrderedScalar: - case NI_SSE2_CompareGreaterThanUnorderedScalar: + case NI_SSE2_CompareScalarOrderedGreaterThan: + case NI_SSE2_CompareScalarUnorderedGreaterThan: { assert(baseType == TYP_DOUBLE); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); @@ -1599,8 +1599,8 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_CompareGreaterThanOrEqualOrderedScalar: - case NI_SSE2_CompareGreaterThanOrEqualUnorderedScalar: + case NI_SSE2_CompareScalarOrderedGreaterThanOrEqual: + case NI_SSE2_CompareScalarUnorderedGreaterThanOrEqual: { assert(baseType == TYP_DOUBLE); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); @@ -1611,8 +1611,8 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_CompareLessThanOrderedScalar: - case NI_SSE2_CompareLessThanUnorderedScalar: + case NI_SSE2_CompareScalarOrderedLessThan: + case NI_SSE2_CompareScalarUnorderedLessThan: { assert(baseType == TYP_DOUBLE); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); @@ -1623,8 +1623,8 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_CompareLessThanOrEqualOrderedScalar: - case NI_SSE2_CompareLessThanOrEqualUnorderedScalar: + case NI_SSE2_CompareScalarOrderedLessThanOrEqual: + case NI_SSE2_CompareScalarUnorderedLessThanOrEqual: { assert(baseType == TYP_DOUBLE); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); @@ -1635,8 +1635,8 @@ void CodeGen::genSSE2Intrinsic(GenTreeHWIntrinsic* node) break; } - case NI_SSE2_CompareNotEqualOrderedScalar: - case NI_SSE2_CompareNotEqualUnorderedScalar: + case NI_SSE2_CompareScalarOrderedNotEqual: + case NI_SSE2_CompareScalarUnorderedNotEqual: { assert(baseType == TYP_DOUBLE); instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); diff --git a/src/jit/hwintrinsiclistxarch.h b/src/jit/hwintrinsiclistxarch.h index ffb4754af2cc..433744ca31c6 100644 --- a/src/jit/hwintrinsiclistxarch.h +++ b/src/jit/hwintrinsiclistxarch.h @@ -79,41 +79,41 @@ HARDWARE_INTRINSIC(SSE_AddScalar, "AddScalar", HARDWARE_INTRINSIC(SSE_And, "And", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE_AndNot, "AndNot", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andnps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE_CompareEqual, "CompareEqual", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_CompareEqualScalar, "CompareEqualScalar", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarOrderedEqual, "CompareScalarOrderedEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarEqual, "CompareScalarEqual", SSE, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnorderedEqual, "CompareScalarUnorderedEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareGreaterThan, "CompareGreaterThan", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanScalar, "CompareGreaterThanScalar", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarOrderedGreaterThan, "CompareScalarOrderedGreaterThan", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarGreaterThan, "CompareScalarGreaterThan", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnorderedGreaterThan, "CompareScalarUnorderedGreaterThan", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqual, "CompareGreaterThanOrEqual", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualScalar, "CompareGreaterThanOrEqualScalar", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarOrderedGreaterThanOrEqual, "CompareScalarOrderedGreaterThanOrEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarGreaterThanOrEqual, "CompareScalarGreaterThanOrEqual", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnorderedGreaterThanOrEqual, "CompareScalarUnorderedGreaterThanOrEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareLessThan, "CompareLessThan", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_CompareLessThanScalar, "CompareLessThanScalar", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarOrderedLessThan, "CompareScalarOrderedLessThan", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarLessThan, "CompareScalarLessThan", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnorderedLessThan, "CompareScalarUnorderedLessThan", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqual, "CompareLessThanOrEqual", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualScalar, "CompareLessThanOrEqualScalar", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarOrderedLessThanOrEqual, "CompareScalarOrderedLessThanOrEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarLessThanOrEqual, "CompareScalarLessThanOrEqual", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnorderedLessThanOrEqual, "CompareScalarUnorderedLessThanOrEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareNotEqual, "CompareNotEqual", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE_CompareNotEqualScalar, "CompareNotEqualScalar", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarOrderedNotEqual, "CompareScalarOrderedNotEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE_CompareScalarNotEqual, "CompareScalarNotEqual", SSE, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnorderedNotEqual, "CompareScalarUnorderedNotEqual", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomiss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_CompareNotGreaterThan, "CompareNotGreaterThan", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanScalar, "CompareNotGreaterThanScalar", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarNotGreaterThan, "CompareScalarNotGreaterThan", SSE, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanOrEqual, "CompareNotGreaterThanOrEqual", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareNotGreaterThanOrEqualScalar, "CompareNotGreaterThanOrEqualScalar", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarNotGreaterThanOrEqual, "CompareScalarNotGreaterThanOrEqual", SSE, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareNotLessThan, "CompareNotLessThan", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareNotLessThanScalar, "CompareNotLessThanScalar", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarNotLessThan, "CompareScalarNotLessThan", SSE, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareNotLessThanOrEqual, "CompareNotLessThanOrEqual", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareNotLessThanOrEqualScalar, "CompareNotLessThanOrEqualScalar", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarNotLessThanOrEqual, "CompareScalarNotLessThanOrEqual", SSE, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareOrdered, "CompareOrdered", SSE, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareOrderedScalar, "CompareOrderedScalar", SSE, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarOrdered, "CompareScalarOrdered", SSE, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_CompareUnordered, "CompareUnordered", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpps, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE_CompareUnorderedScalar, "CompareUnorderedScalar", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE_CompareScalarUnordered, "CompareScalarUnordered", SSE, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpss, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_ConvertToInt32, "ConvertToInt32", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE_ConvertScalarToVector128Single, "ConvertScalarToVector128Single", SSE, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) @@ -180,41 +180,41 @@ HARDWARE_INTRINSIC(SSE2_And, "And", HARDWARE_INTRINSIC(SSE2_AndNot, "AndNot", SSE2, -1, 16, 2, {INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_pandn, INS_invalid, INS_andnpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_Average, "Average", SSE2, -1, 16, 2, {INS_invalid, INS_pavgb, INS_invalid, INS_pavgw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative) HARDWARE_INTRINSIC(SSE2_CompareEqual, "CompareEqual", SSE2, 0, 16, 2, {INS_pcmpeqb, INS_pcmpeqb, INS_pcmpeqw, INS_pcmpeqw, INS_pcmpeqd, INS_pcmpeqd, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2_CompareEqualOrderedScalar, "CompareEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareEqualScalar, "CompareEqualScalar", SSE2, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareEqualUnorderedScalar, "CompareEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrderedEqual, "CompareScalarOrderedEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarEqual, "CompareScalarEqual", SSE2, 0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnorderedEqual, "CompareScalarUnorderedEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareGreaterThan, "CompareGreaterThan", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrderedScalar, "CompareGreaterThanOrderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanScalar, "CompareGreaterThanScalar", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanUnorderedScalar, "CompareGreaterThanUnorderedScalar", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrderedGreaterThan, "CompareScalarOrderedGreaterThan", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarGreaterThan, "CompareScalarGreaterThan", SSE2, 6, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnorderedGreaterThan, "CompareScalarUnorderedGreaterThan", SSE2, -1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqual, "CompareGreaterThanOrEqual", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualOrderedScalar, "CompareGreaterThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualScalar, "CompareGreaterThanOrEqualScalar", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareGreaterThanOrEqualUnorderedScalar, "CompareGreaterThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrderedGreaterThanOrEqual, "CompareScalarOrderedGreaterThanOrEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarGreaterThanOrEqual, "CompareScalarGreaterThanOrEqual", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnorderedGreaterThanOrEqual, "CompareScalarUnorderedGreaterThanOrEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareLessThan, "CompareLessThan", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_Special, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrderedScalar, "CompareLessThanOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareLessThanScalar, "CompareLessThanScalar", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareLessThanUnorderedScalar, "CompareLessThanUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrderedLessThan, "CompareScalarOrderedLessThan", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarLessThan, "CompareScalarLessThan", SSE2, 1, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnorderedLessThan, "CompareScalarUnorderedLessThan", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqual, "CompareLessThanOrEqual", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualOrderedScalar, "CompareLessThanOrEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualScalar, "CompareLessThanOrEqualScalar", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareLessThanOrEqualUnorderedScalar, "CompareLessThanOrEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrderedLessThanOrEqual, "CompareScalarOrderedLessThanOrEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarLessThanOrEqual, "CompareScalarLessThanOrEqual", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnorderedLessThanOrEqual, "CompareScalarUnorderedLessThanOrEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareNotEqual, "CompareNotEqual", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(SSE2_CompareNotEqualOrderedScalar, "CompareNotEqualOrderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_CompareNotEqualScalar, "CompareNotEqualScalar", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(SSE2_CompareNotEqualUnorderedScalar, "CompareNotEqualUnorderedScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrderedNotEqual, "CompareScalarOrderedNotEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_comisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_CompareScalarNotEqual, "CompareScalarNotEqual", SSE2, 4, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnorderedNotEqual, "CompareScalarUnorderedNotEqual", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ucomisd}, HW_Category_SIMDScalar, HW_Flag_Commutative|HW_Flag_MultiIns|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThan, "CompareNotGreaterThan", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanScalar, "CompareNotGreaterThanScalar", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarNotGreaterThan, "CompareScalarNotGreaterThan", SSE2, 2, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanOrEqual, "CompareNotGreaterThanOrEqual", SSE2, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareNotGreaterThanOrEqualScalar, "CompareNotGreaterThanOrEqualScalar", SSE2, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarNotGreaterThanOrEqual, "CompareScalarNotGreaterThanOrEqual", SSE2, 1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareNotLessThan, "CompareNotLessThan", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareNotLessThanScalar, "CompareNotLessThanScalar", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarNotLessThan, "CompareScalarNotLessThan", SSE2, 5, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareNotLessThanOrEqual, "CompareNotLessThanOrEqual", SSE2, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareNotLessThanOrEqualScalar, "CompareNotLessThanOrEqualScalar", SSE2, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarNotLessThanOrEqual, "CompareScalarNotLessThanOrEqual", SSE2, 6, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareOrdered, "CompareOrdered", SSE2, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareOrderedScalar, "CompareOrderedScalar", SSE2, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarOrdered, "CompareScalarOrdered", SSE2, 7, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_CompareUnordered, "CompareUnordered", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(SSE2_CompareUnorderedScalar, "CompareUnorderedScalar", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(SSE2_CompareScalarUnordered, "CompareScalarUnordered", SSE2, 3, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmpsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) HARDWARE_INTRINSIC(SSE2_ConvertToInt32, "ConvertToInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_ConvertToInt32WithTruncation, "ConvertToInt32WithTruncation", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_ConvertToUInt32, "ConvertToUInt32", SSE2, -1, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) @@ -269,7 +269,7 @@ HARDWARE_INTRINSIC(SSE2_StoreAlignedNonTemporal, "StoreAligne HARDWARE_INTRINSIC(SSE2_StoreHigh, "StoreHigh", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movhpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_StoreLow, "StoreLow", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movq, INS_movq, INS_invalid, INS_movlpd}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_StoreNonTemporal, "StoreNonTemporal", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE2_StoreScalar, "StoreScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsdsse2}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_StoreScalar, "StoreScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movq, INS_movq, INS_invalid, INS_movsdsse2}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(SSE2_Subtract, "Subtract", SSE2, -1, 16, 2, {INS_psubb, INS_psubb, INS_psubw, INS_psubw, INS_psubd, INS_psubd, INS_psubq, INS_psubq, INS_invalid, INS_subpd}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_SubtractSaturate, "SubtractSaturate", SSE2, -1, 16, 2, {INS_psubsb, INS_psubusb, INS_psubsw, INS_psubusw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(SSE2_SubtractScalar, "SubtractScalar", SSE2, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_subsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits) @@ -474,12 +474,9 @@ HARDWARE_INTRINSIC(AVX2_CompareGreaterThan, "CompareGrea HARDWARE_INTRINSIC(AVX2_ExtractVector128, "ExtractVector128", AVX2, -1, 32, 2, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM) HARDWARE_INTRINSIC(AVX2_ConvertToInt32, "ConvertToInt32", AVX2, -1, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) HARDWARE_INTRINSIC(AVX2_ConvertToUInt32, "ConvertToUInt32", AVX2, -1, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov_xmm2i, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX2_ConvertToVector256Int16, "ConvertToVector256Int16", AVX2, -1, 32, 1, {INS_pmovsxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2_ConvertToVector256UInt16, "ConvertToVector256UInt16", AVX2, -1, 32, 1, {INS_invalid, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2_ConvertToVector256Int32, "ConvertToVector256Int32", AVX2, -1, 32, 1, {INS_pmovsxbd, INS_invalid, INS_pmovsxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2_ConvertToVector256UInt32, "ConvertToVector256UInt32", AVX2, -1, 32, 1, {INS_invalid, INS_pmovzxbd, INS_invalid, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2_ConvertToVector256Int64, "ConvertToVector256Int64", AVX2, -1, 32, 1, {INS_pmovsxbq, INS_invalid, INS_pmovsxwq, INS_invalid, INS_pmovsxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AVX2_ConvertToVector256UInt64, "ConvertToVector256UInt64", AVX2, -1, 32, 1, {INS_invalid, INS_pmovzxbq, INS_invalid, INS_pmovzxwq, INS_invalid, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX2_ConvertToVector256Int16, "ConvertToVector256Int16", AVX2, -1, 32, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX2_ConvertToVector256Int32, "ConvertToVector256Int32", AVX2, -1, 32, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AVX2_ConvertToVector256Int64, "ConvertToVector256Int64", AVX2, -1, 32, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(AVX2_GatherVector128, "GatherVector128", AVX2, -1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_SpecialCodeGen|HW_Flag_NoContainment) HARDWARE_INTRINSIC(AVX2_GatherVector256, "GatherVector256", AVX2, -1, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment) HARDWARE_INTRINSIC(AVX2_GatherMaskVector128, "GatherMaskVector128", AVX2, -1, 16, 5, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment) diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 8600bf304cc5..db6b6df5718f 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -1217,7 +1217,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, // If it is a multi-reg struct return, don't change the oper to GT_LCL_FLD. // That is, the IR will be of the form lclVar = call for multi-reg return // - GenTree* lcl = destAddr->gtOp.gtOp1; + GenTreeLclVar* lcl = destAddr->gtOp.gtOp1->AsLclVar(); if (src->AsCall()->HasMultiRegRetVal()) { // Mark the struct LclVar as used in a MultiReg return context @@ -1227,7 +1227,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, lcl->gtFlags |= GTF_DONT_CSE; lvaTable[lcl->gtLclVarCommon.gtLclNum].lvIsMultiRegRet = true; } - else // The call result is not a multireg return + else if (lcl->gtType != src->gtType) { // We change this to a GT_LCL_FLD (from a GT_ADDR of a GT_LCL_VAR) lcl->ChangeOper(GT_LCL_FLD); @@ -1532,7 +1532,7 @@ var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, #ifdef FEATURE_SIMD // Check to see if this is a SIMD type. - if (featureSIMD && !mayContainGCPtrs) + if (supportSIMDTypes() && !mayContainGCPtrs) { unsigned originalSize = info.compCompHnd->getClassSize(structHnd); @@ -9022,13 +9022,16 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re // This LCL_VAR stays as a TYP_STRUCT unsigned lclNum = op->gtLclVarCommon.gtLclNum; - // Make sure this struct type is not struct promoted - lvaTable[lclNum].lvIsMultiRegRet = true; + if (!lvaIsImplicitByRefLocal(lclNum)) + { + // Make sure this struct type is not struct promoted + lvaTable[lclNum].lvIsMultiRegRet = true; - // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns. - op->gtFlags |= GTF_DONT_CSE; + // TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns. + op->gtFlags |= GTF_DONT_CSE; - return op; + return op; + } } if (op->gtOper == GT_CALL) @@ -9057,7 +9060,7 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op, CORINFO_CLASS_HANDLE re { // It is possible that we now have a lclVar of scalar type. // If so, don't transform it to GT_LCL_FLD. - if (varTypeIsStruct(lvaTable[op->AsLclVar()->gtLclNum].lvType)) + if (lvaTable[op->AsLclVar()->gtLclNum].lvType != info.compRetNativeType) { op->ChangeOper(GT_LCL_FLD); } @@ -18929,22 +18932,28 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo) var_types type = (var_types)eeGetArgType(localsSig, &methInfo->locals, &isPinned); lclVarInfo[i + argCnt].lclHasLdlocaOp = false; - lclVarInfo[i + argCnt].lclIsPinned = isPinned; lclVarInfo[i + argCnt].lclTypeInfo = type; if (varTypeIsGC(type)) { + if (isPinned) + { + JITDUMP("Inlinee local #%02u is pinned\n", i); + lclVarInfo[i + argCnt].lclIsPinned = true; + + // Pinned locals may cause inlines to fail. + inlineResult->Note(InlineObservation::CALLEE_HAS_PINNED_LOCALS); + if (inlineResult->IsFailure()) + { + return; + } + } + pInlineInfo->numberOfGcRefLocals++; } - - if (isPinned) + else if (isPinned) { - // Pinned locals may cause inlines to fail. - inlineResult->Note(InlineObservation::CALLEE_HAS_PINNED_LOCALS); - if (inlineResult->IsFailure()) - { - return; - } + JITDUMP("Ignoring pin on inlinee local #%02u -- not a GC type\n", i); } lclVarInfo[i + argCnt].lclVerTypeInfo = verParseArgSigToTypeInfo(&methInfo->locals, localsSig); @@ -18983,7 +18992,7 @@ void Compiler::impInlineInitVars(InlineInfo* pInlineInfo) if ((!foundSIMDType || (type == TYP_STRUCT)) && isSIMDorHWSIMDClass(&(lclVarInfo[i + argCnt].lclVerTypeInfo))) { foundSIMDType = true; - if (featureSIMD && type == TYP_STRUCT) + if (supportSIMDTypes() && type == TYP_STRUCT) { var_types structType = impNormStructType(lclVarInfo[i + argCnt].lclVerTypeInfo.GetClassHandle()); lclVarInfo[i + argCnt].lclTypeInfo = structType; diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 6f34e24f32f7..6b26b5de125e 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -124,7 +124,7 @@ void Compiler::lvaInitTypeRef() info.compILargsCount = info.compArgsCount; #ifdef FEATURE_SIMD - if (featureSIMD && (info.compRetNativeType == TYP_STRUCT)) + if (supportSIMDTypes() && (info.compRetNativeType == TYP_STRUCT)) { var_types structType = impNormStructType(info.compMethodInfo->args.retTypeClass); info.compRetType = structType; @@ -149,7 +149,7 @@ void Compiler::lvaInitTypeRef() if ((howToReturnStruct == SPK_PrimitiveType) || (howToReturnStruct == SPK_EnclosingType)) { assert(returnType != TYP_UNKNOWN); - assert(!varTypeIsStruct(returnType)); + assert(returnType != TYP_STRUCT); info.compRetNativeType = returnType; @@ -255,7 +255,19 @@ void Compiler::lvaInitTypeRef() lvaInitVarDsc(varDsc, varNum, corInfoType, typeHnd, localsSig, &info.compMethodInfo->locals); - varDsc->lvPinned = ((corInfoTypeWithMod & CORINFO_TYPE_MOD_PINNED) != 0); + if ((corInfoTypeWithMod & CORINFO_TYPE_MOD_PINNED) != 0) + { + if ((corInfoType == CORINFO_TYPE_CLASS) || (corInfoType == CORINFO_TYPE_BYREF)) + { + JITDUMP("Setting lvPinned for V%02u\n", varNum); + varDsc->lvPinned = 1; + } + else + { + JITDUMP("Ignoring pin for non-GC type V%02u\n", varNum); + } + } + varDsc->lvOnFrame = true; // The final home for this local variable might be our local stack frame if (corInfoType == CORINFO_TYPE_CLASS) @@ -397,7 +409,7 @@ void Compiler::lvaInitThisPtr(InitVarDscInfo* varDscInfo) { varDsc->lvType = TYP_BYREF; #ifdef FEATURE_SIMD - if (featureSIMD) + if (supportSIMDTypes()) { var_types simdBaseType = TYP_UNKNOWN; var_types type = impNormStructType(info.compClassHnd, nullptr, nullptr, &simdBaseType); @@ -505,7 +517,7 @@ void Compiler::lvaInitRetBuffArg(InitVarDscInfo* varDscInfo) } } #ifdef FEATURE_SIMD - else if (featureSIMD && varTypeIsSIMD(info.compRetType)) + else if (supportSIMDTypes() && varTypeIsSIMD(info.compRetType)) { varDsc->lvSIMDType = true; varDsc->lvBaseType = @@ -598,8 +610,9 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo) // If the argType is a struct, then check if it is an HFA if (varTypeIsStruct(argType)) { - hfaType = GetHfaType(typeHnd); // set to float or double if it is an HFA, otherwise TYP_UNDEF - isHfaArg = varTypeIsFloating(hfaType); + // hfaType is set to float, double or SIMD type if it is an HFA, otherwise TYP_UNDEF. + hfaType = GetHfaType(typeHnd); + isHfaArg = varTypeIsValidHfaType(hfaType); } } else if (info.compIsVarArgs) @@ -616,11 +629,12 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo) if (isHfaArg) { - // We have an HFA argument, so from here on out treat the type as a float or double. + // We have an HFA argument, so from here on out treat the type as a float, double or vector. // The orginal struct type is available by using origArgType // We also update the cSlots to be the number of float/double fields in the HFA argType = hfaType; - cSlots = varDsc->lvHfaSlots(); + varDsc->SetHfaType(hfaType); + cSlots = varDsc->lvHfaSlots(); } // The number of slots that must be enregistered if we are to consider this argument enregistered. // This is normally the same as cSlots, since we normally either enregister the entire object, @@ -818,18 +832,31 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo) if (isHfaArg) { // We need to save the fact that this HFA is enregistered - varDsc->lvSetIsHfa(); - varDsc->lvSetIsHfaRegArg(); - varDsc->SetHfaType(hfaType); - varDsc->lvIsMultiRegArg = (varDsc->lvHfaSlots() > 1); + // Note that we can have HVAs of SIMD types even if we are not recognizing intrinsics. + // In that case, we won't have normalized the vector types on the varDsc, so if we have a single vector + // register, we need to set the type now. Otherwise, later we'll assume this is passed by reference. + if (varDsc->lvHfaSlots() != 1) + { + varDsc->lvIsMultiRegArg = true; + } } varDsc->lvIsRegArg = 1; #if FEATURE_MULTIREG_ARGS +#ifdef _TARGET_ARM64_ + if (argType == TYP_STRUCT) + { + varDsc->lvArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum, TYP_I_IMPL); + if (cSlots == 2) + { + varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_I_IMPL); + varDscInfo->hasMultiSlotStruct = true; + } + } +#elif defined(UNIX_AMD64_ABI) if (varTypeIsStruct(argType)) { -#if defined(UNIX_AMD64_ABI) varDsc->lvArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum, firstEightByteType); // If there is a second eightbyte, get a register for it too and map the arg to the reg number. @@ -844,17 +871,13 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo) { varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(secondAllocatedRegArgNum, secondEightByteType); } -#else // ARM32 or ARM64 + } +#else // ARM32 + if (varTypeIsStruct(argType)) + { varDsc->lvArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum, TYP_I_IMPL); -#ifdef _TARGET_ARM64_ - if (cSlots == 2) - { - varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_I_IMPL); - varDscInfo->hasMultiSlotStruct = true; - } -#endif // _TARGET_ARM64_ -#endif // defined(UNIX_AMD64_ABI) } +#endif // ARM32 else #endif // FEATURE_MULTIREG_ARGS { @@ -879,14 +902,13 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo) isFloat = varTypeIsFloating(firstEightByteType); } else -#else +#endif // !UNIX_AMD64_ABI { isFloat = varTypeIsFloating(argType); } -#endif // !UNIX_AMD64_ABI #if defined(UNIX_AMD64_ABI) - if (varTypeIsStruct(argType)) + if (varTypeIsStruct(argType)) { // Print both registers, just to be clear if (firstEightByteType == TYP_UNDEF) @@ -1270,7 +1292,15 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, varDsc->lvStructGcCount = 1; } - // Set the lvType (before this point it is TYP_UNDEF). +#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + varDsc->lvIsImplicitByRef = 0; +#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + +// Set the lvType (before this point it is TYP_UNDEF). + +#ifdef FEATURE_HFA + varDsc->SetHfaType(TYP_UNDEF); +#endif if ((varTypeIsStruct(type))) { lvaSetStruct(varNum, typeHnd, typeHnd != nullptr, !tiVerificationNeeded); @@ -2149,6 +2179,10 @@ void Compiler::StructPromotionHelper::PromoteStructVar(unsigned lclNum) fieldVarDsc->lvParentLcl = lclNum; fieldVarDsc->lvIsParam = varDsc->lvIsParam; #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + + // Reset the implicitByRef flag. + fieldVarDsc->lvIsImplicitByRef = 0; + // Do we have a parameter that can be enregistered? // if (varDsc->lvIsRegArg) @@ -2476,11 +2510,12 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool varDsc->lvExactSize = info.compCompHnd->getHeapClassSize(typeHnd); } - size_t lvSize = varDsc->lvSize(); - assert((lvSize % TARGET_POINTER_SIZE) == - 0); // The struct needs to be a multiple of TARGET_POINTER_SIZE bytes for getClassGClayout() to be valid. - varDsc->lvGcLayout = getAllocator(CMK_LvaTable).allocate(lvSize / TARGET_POINTER_SIZE); - unsigned numGCVars; + // Normalize struct types, and fill in GC info for all types + unsigned lvSize = varDsc->lvSize(); + // The struct needs to be a multiple of TARGET_POINTER_SIZE bytes for getClassGClayout() to be valid. + assert((lvSize % TARGET_POINTER_SIZE) == 0); + varDsc->lvGcLayout = getAllocator(CMK_LvaTable).allocate(lvSize / TARGET_POINTER_SIZE); + unsigned numGCVars = 0; var_types simdBaseType = TYP_UNKNOWN; if (isValueClass) { @@ -2496,10 +2531,27 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool { numGCVars = 7; } + varDsc->lvStructGcCount = numGCVars; if (isValueClass) { + +#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + // Mark implicit byref struct parameters + if (varDsc->lvIsParam && !varDsc->lvIsStructField) + { + structPassingKind howToReturnStruct; + getArgTypeForStruct(typeHnd, &howToReturnStruct, this->info.compIsVarArgs, varDsc->lvExactSize); + + if (howToReturnStruct == SPK_ByReference) + { + JITDUMP("Marking V%02i as a byref parameter\n", varNum); + varDsc->lvIsImplicitByRef = 1; + } + } +#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + #if FEATURE_SIMD if (simdBaseType != TYP_UNKNOWN) { @@ -2513,10 +2565,9 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool if (varDsc->lvExactSize <= MAX_PASS_MULTIREG_BYTES) { var_types hfaType = GetHfaType(typeHnd); // set to float or double if it is an HFA, otherwise TYP_UNDEF - if (varTypeIsFloating(hfaType)) + if (varTypeIsValidHfaType(hfaType)) { - varDsc->_lvIsHfa = true; - varDsc->lvSetHfaTypeIsFloat(hfaType == TYP_FLOAT); + varDsc->SetHfaType(hfaType); // hfa variables can never contain GC pointers assert(varDsc->lvStructGcCount == 0); @@ -2588,8 +2639,7 @@ void Compiler::lvaSetStructUsedAsVarArg(unsigned varNum) LclVarDsc* varDsc = &lvaTable[varNum]; // For varargs methods incoming and outgoing arguments should not be treated // as HFA. - varDsc->_lvIsHfa = false; - varDsc->_lvHfaTypeIsFloat = false; + varDsc->SetHfaType(TYP_UNDEF); #endif // defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) #endif // FEATURE_HFA } @@ -6913,16 +6963,9 @@ void Compiler::lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t r } } - if (varDsc->lvIsHfaRegArg()) + if (varDsc->lvIsHfa()) { - if (varDsc->lvHfaTypeIsFloat()) - { - printf(" (enregistered HFA: float) "); - } - else - { - printf(" (enregistered HFA: double)"); - } + printf(" HFA(%s) ", varTypeName(varDsc->GetHfaType())); } if (varDsc->lvDoNotEnregister) diff --git a/src/jit/linuxnonjit/CMakeLists.txt b/src/jit/linuxnonjit/CMakeLists.txt index 6093b888332e..bcd11cf3f217 100644 --- a/src/jit/linuxnonjit/CMakeLists.txt +++ b/src/jit/linuxnonjit/CMakeLists.txt @@ -27,6 +27,8 @@ if(WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=linuxnonjit.dll) endif(WIN32) +set_source_files_properties(${JIT_EXPORTS_FILE} PROPERTIES GENERATED TRUE) + add_library_clr(linuxnonjit SHARED ${SHARED_LIB_SOURCES} diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index a2f7080a9d40..75c354dc3884 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -5691,10 +5691,11 @@ void Lowering::ContainCheckRet(GenTreeOp* ret) { GenTreeLclVarCommon* lclVarCommon = op1->AsLclVarCommon(); LclVarDsc* varDsc = &(comp->lvaTable[lclVarCommon->gtLclNum]); - assert(varDsc->lvIsMultiRegRet); + // This must be a multi-reg return or an HFA of a single element. + assert(varDsc->lvIsMultiRegRet || (varDsc->lvIsHfa() && varTypeIsValidHfaType(varDsc->lvType))); // Mark var as contained if not enregistrable. - if (!varTypeIsEnregisterableStruct(op1)) + if (!varTypeIsEnregisterable(op1)) { MakeSrcContained(ret, op1); } diff --git a/src/jit/lowerarmarch.cpp b/src/jit/lowerarmarch.cpp index 3e0d636e9921..adfc34ae94d5 100644 --- a/src/jit/lowerarmarch.cpp +++ b/src/jit/lowerarmarch.cpp @@ -892,6 +892,11 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { MakeSrcContained(node, op2); +#if 0 + // This is currently not supported downstream. The following (at least) need to be modifed: + // GenTree::isContainableHWIntrinsic() needs to handle this. + // CodeGen::genConsumRegs() + // GenTree* op3 = argList->Rest()->Rest()->Current(); // In the HW intrinsics C# API there is no direct way to specify a vector element to element mov @@ -909,6 +914,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) MakeSrcContained(node, op3); } } +#endif } break; diff --git a/src/jit/lowerxarch.cpp b/src/jit/lowerxarch.cpp index df0959015d51..9a1f223d8fca 100644 --- a/src/jit/lowerxarch.cpp +++ b/src/jit/lowerxarch.cpp @@ -2972,14 +2972,14 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { switch (intrinsicId) { - case NI_SSE_CompareLessThanOrderedScalar: - case NI_SSE_CompareLessThanUnorderedScalar: - case NI_SSE_CompareLessThanOrEqualOrderedScalar: - case NI_SSE_CompareLessThanOrEqualUnorderedScalar: - case NI_SSE2_CompareLessThanOrderedScalar: - case NI_SSE2_CompareLessThanUnorderedScalar: - case NI_SSE2_CompareLessThanOrEqualOrderedScalar: - case NI_SSE2_CompareLessThanOrEqualUnorderedScalar: + case NI_SSE_CompareScalarOrderedLessThan: + case NI_SSE_CompareScalarUnorderedLessThan: + case NI_SSE_CompareScalarOrderedLessThanOrEqual: + case NI_SSE_CompareScalarUnorderedLessThanOrEqual: + case NI_SSE2_CompareScalarOrderedLessThan: + case NI_SSE2_CompareScalarUnorderedLessThan: + case NI_SSE2_CompareScalarOrderedLessThanOrEqual: + case NI_SSE2_CompareScalarUnorderedLessThanOrEqual: { // We need to swap the operands for CompareLessThanOrEqual node->gtOp1 = op2; @@ -2990,7 +2990,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) default: { - // TODO-XArch-CQ: The Compare*OrderedScalar and Compare*UnorderedScalar methods + // TODO-XArch-CQ: The CompareScalarOrdered* and CompareScalarUnordered* methods // are commutative if you also inverse the intrinsic. break; } diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index 9d4344f02800..2e431aad6a8c 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -740,7 +740,7 @@ BasicBlock* LinearScan::getNextCandidateFromWorkList() } //------------------------------------------------------------------------ -// setBlockSequence:Determine the block order for register allocation. +// setBlockSequence: Determine the block order for register allocation. // // Arguments: // None @@ -756,9 +756,16 @@ BasicBlock* LinearScan::getNextCandidateFromWorkList() void LinearScan::setBlockSequence() { - // Reset the "visited" flag on each block. + assert(!blockSequencingDone); // The method should be called only once. + compiler->EnsureBasicBlockEpoch(); +#ifdef DEBUG + blockEpoch = compiler->GetCurBasicBlockEpoch(); +#endif // DEBUG + + // Initialize the "visited" blocks set. bbVisitedSet = BlockSetOps::MakeEmpty(compiler); + BlockSet readySet(BlockSetOps::MakeEmpty(compiler)); BlockSet predSet(BlockSetOps::MakeEmpty(compiler)); @@ -1094,10 +1101,14 @@ BasicBlock* LinearScan::startBlockSequence() { setBlockSequence(); } + else + { + clearVisitedBlocks(); + } + BasicBlock* curBB = compiler->fgFirstBB; curBBSeqNum = 0; curBBNum = curBB->bbNum; - clearVisitedBlocks(); assert(blockSequence[0] == compiler->fgFirstBB); markBlockVisited(curBB); return curBB; @@ -1172,8 +1183,6 @@ void LinearScan::doLinearScan() enregisterLocalVars = false; } - unsigned lsraBlockEpoch = compiler->GetCurBasicBlockEpoch(); - splitBBNumToTargetBBNumMap = nullptr; // This is complicated by the fact that physical registers have refs associated @@ -1189,7 +1198,6 @@ void LinearScan::doLinearScan() DBEXEC(VERBOSE, lsraDumpIntervals("after buildIntervals")); - clearVisitedBlocks(); initVarRegMaps(); allocateRegisters(); allocationPassComplete = true; @@ -1197,6 +1205,9 @@ void LinearScan::doLinearScan() resolveRegisters(); compiler->EndPhase(PHASE_LINEAR_SCAN_RESOLVE); + assert(blockSequencingDone); // Should do at least one traversal. + assert(blockEpoch == compiler->GetCurBasicBlockEpoch()); + #if TRACK_LSRA_STATS if ((JitConfig.DisplayLsraStats() != 0) #ifdef DEBUG @@ -1211,7 +1222,6 @@ void LinearScan::doLinearScan() DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_POST)); compiler->compLSRADone = true; - noway_assert(lsraBlockEpoch = compiler->GetCurBasicBlockEpoch()); } //------------------------------------------------------------------------ @@ -1415,7 +1425,7 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc) // or enregistered, on x86 -- it is believed that we can enregister pinned (more properly, "pinning") // references when using the general GC encoding. unsigned lclNum = (unsigned)(varDsc - compiler->lvaTable); - if (varDsc->lvAddrExposed || !varTypeIsEnregisterableStruct(varDsc)) + if (varDsc->lvAddrExposed || !varTypeIsEnregisterable(varDsc)) { #ifdef DEBUG Compiler::DoNotEnregisterReason dner = Compiler::DNER_AddrExposed; @@ -5774,36 +5784,41 @@ void LinearScan::allocateRegisters() // The interval could be dead if this is a user variable, or if the // node is being evaluated for side effects, or a call whose result // is not used, etc. - if (currentRefPosition->lastUse || currentRefPosition->nextRefPosition == nullptr) + // If this is an UpperVector we'll neither free it nor preference it + // (it will be freed when it is used). + if (!currentInterval->IsUpperVector()) { - assert(currentRefPosition->isIntervalRef()); - - if (refType != RefTypeExpUse && currentRefPosition->nextRefPosition == nullptr) + if (currentRefPosition->lastUse || currentRefPosition->nextRefPosition == nullptr) { - if (currentRefPosition->delayRegFree) + assert(currentRefPosition->isIntervalRef()); + + if (refType != RefTypeExpUse && currentRefPosition->nextRefPosition == nullptr) { - delayRegsToFree |= assignedRegBit; + if (currentRefPosition->delayRegFree) + { + delayRegsToFree |= assignedRegBit; - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED)); + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED)); + } + else + { + regsToFree |= assignedRegBit; + + INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE)); + } } else { - regsToFree |= assignedRegBit; - - INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE)); + currentInterval->isActive = false; } - } - else - { - currentInterval->isActive = false; - } - // Update the register preferences for the relatedInterval, if this is 'preferencedToDef'. - // Don't propagate to subsequent relatedIntervals; that will happen as they are allocated, and we - // don't know yet whether the register will be retained. - if (currentInterval->relatedInterval != nullptr) - { - currentInterval->relatedInterval->updateRegisterPreferences(assignedRegBit); + // Update the register preferences for the relatedInterval, if this is 'preferencedToDef'. + // Don't propagate to subsequent relatedIntervals; that will happen as they are allocated, and we + // don't know yet whether the register will be retained. + if (currentInterval->relatedInterval != nullptr) + { + currentInterval->relatedInterval->updateRegisterPreferences(assignedRegBit); + } } } diff --git a/src/jit/lsra.h b/src/jit/lsra.h index e03b6f9e6f89..c5477bf9e125 100644 --- a/src/jit/lsra.h +++ b/src/jit/lsra.h @@ -1397,6 +1397,10 @@ class LinearScan : public LinearScanInterface int compareBlocksForSequencing(BasicBlock* block1, BasicBlock* block2, bool useBlockWeights); BasicBlockList* blockSequenceWorkList; bool blockSequencingDone; +#ifdef DEBUG + // LSRA must not change number of blocks and blockEpoch that it initializes at start. + unsigned blockEpoch; +#endif // DEBUG void addToBlockSequenceWorkList(BlockSet sequencedBlockSet, BasicBlock* block, BlockSet& predSet); void removeFromBlockSequenceWorkList(BasicBlockList* listNode, BasicBlockList* prevNode); BasicBlock* getNextCandidateFromWorkList(); diff --git a/src/jit/lsraarmarch.cpp b/src/jit/lsraarmarch.cpp index 251bf53ab267..9a54c3227978 100644 --- a/src/jit/lsraarmarch.cpp +++ b/src/jit/lsraarmarch.cpp @@ -208,7 +208,7 @@ int LinearScan::BuildCall(GenTreeCall* call) assert(retTypeDesc != nullptr); dstCandidates = retTypeDesc->GetABIReturnRegs(); } - else if (varTypeIsFloating(registerType)) + else if (varTypeUsesFloatArgReg(registerType)) { dstCandidates = RBM_FLOATRET; } diff --git a/src/jit/lsrabuild.cpp b/src/jit/lsrabuild.cpp index da1fa8f7d37b..1b0f61ddcca2 100644 --- a/src/jit/lsrabuild.cpp +++ b/src/jit/lsrabuild.cpp @@ -1841,15 +1841,7 @@ void LinearScan::updateRegStateForArg(LclVarDsc* argDsc) { RegState* intRegState = &compiler->codeGen->intRegState; RegState* floatRegState = &compiler->codeGen->floatRegState; - // In the case of AMD64 we'll still use the floating point registers - // to model the register usage for argument on vararg calls, so - // we will ignore the varargs condition to determine whether we use - // XMM registers or not for setting up the call. - bool isFloat = (isFloatRegType(argDsc->lvType) -#ifndef _TARGET_AMD64_ - && !compiler->info.compIsVarArgs -#endif - && !compiler->opts.compUseSoftFP); + bool isFloat = emitter::isFloatReg(argDsc->lvArgReg); if (argDsc->lvIsHfaRegArg()) { @@ -3070,6 +3062,15 @@ int LinearScan::BuildReturn(GenTree* tree) regMaskTP useCandidates = RBM_NONE; #if FEATURE_MULTIREG_RET +#ifdef _TARGET_ARM64_ + if (varTypeIsSIMD(tree)) + { + useCandidates = allSIMDRegs(); + BuildUse(op1, useCandidates); + return 1; + } +#endif // !_TARGET_ARM64_ + if (varTypeIsStruct(tree)) { // op1 has to be either an lclvar or a multi-reg returning call @@ -3209,7 +3210,7 @@ int LinearScan::BuildPutArgReg(GenTreeUnOp* node) GenTreeObj* obj = op1->AsObj(); GenTree* addr = obj->Addr(); unsigned size = obj->gtBlkSize; - assert(size <= TARGET_POINTER_SIZE); + assert(size <= MAX_PASS_SINGLEREG_BYTES); if (addr->OperIsLocalAddr()) { // We don't need a source register. diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp index a1e56aac0f30..5f1094ee4f1d 100644 --- a/src/jit/lsraxarch.cpp +++ b/src/jit/lsraxarch.cpp @@ -2457,14 +2457,14 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) break; } - case NI_SSE_CompareEqualOrderedScalar: - case NI_SSE_CompareEqualUnorderedScalar: - case NI_SSE_CompareNotEqualOrderedScalar: - case NI_SSE_CompareNotEqualUnorderedScalar: - case NI_SSE2_CompareEqualOrderedScalar: - case NI_SSE2_CompareEqualUnorderedScalar: - case NI_SSE2_CompareNotEqualOrderedScalar: - case NI_SSE2_CompareNotEqualUnorderedScalar: + case NI_SSE_CompareScalarOrderedEqual: + case NI_SSE_CompareScalarUnorderedEqual: + case NI_SSE_CompareScalarOrderedNotEqual: + case NI_SSE_CompareScalarUnorderedNotEqual: + case NI_SSE2_CompareScalarOrderedEqual: + case NI_SSE2_CompareScalarUnorderedEqual: + case NI_SSE2_CompareScalarOrderedNotEqual: + case NI_SSE2_CompareScalarUnorderedNotEqual: { buildInternalIntRegisterDefForNode(intrinsicTree, allByteRegs()); setInternalRegsDelayFree = true; diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 2369d1eda53d..6e4c8a836642 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -828,6 +828,7 @@ void fgArgTabEntry::Dump() { printf("fgArgTabEntry[arg %u", argNum); printf(" %d.%s", node->gtTreeID, GenTree::OpName(node->gtOper)); + printf(" %s", varTypeName(argType)); if (regNum != REG_STK) { printf(", %u reg%s:", numRegs, numRegs == 1 ? "" : "s"); @@ -867,7 +868,7 @@ void fgArgTabEntry::Dump() } if (isHfaRegArg) { - printf(", isHfa"); + printf(", isHfa(%s)", varTypeName(GetHfaType())); } if (isBackFilled) { @@ -1140,6 +1141,7 @@ fgArgTabEntry* fgArgInfo::AddRegArg(unsigned argNum, curArgTabEntry->argNum = argNum; curArgTabEntry->node = node; + curArgTabEntry->argType = node->TypeGet(); curArgTabEntry->parent = parent; curArgTabEntry->slotNum = 0; curArgTabEntry->numRegs = numRegs; @@ -1153,7 +1155,7 @@ fgArgTabEntry* fgArgInfo::AddRegArg(unsigned argNum, curArgTabEntry->needPlace = false; curArgTabEntry->processed = false; #ifdef FEATURE_HFA - curArgTabEntry->_isHfaArg = false; + curArgTabEntry->_hfaElemKind = HFA_ELEM_NONE; #endif curArgTabEntry->isBackFilled = false; curArgTabEntry->isNonStandard = false; @@ -1213,6 +1215,7 @@ fgArgTabEntry* fgArgInfo::AddStkArg(unsigned argNum, curArgTabEntry->setRegNum(0, REG_STK); curArgTabEntry->argNum = argNum; curArgTabEntry->node = node; + curArgTabEntry->argType = node->TypeGet(); curArgTabEntry->parent = parent; curArgTabEntry->slotNum = nextSlotNum; curArgTabEntry->numRegs = 0; @@ -1226,7 +1229,7 @@ fgArgTabEntry* fgArgInfo::AddStkArg(unsigned argNum, curArgTabEntry->needPlace = false; curArgTabEntry->processed = false; #ifdef FEATURE_HFA - curArgTabEntry->_isHfaArg = false; + curArgTabEntry->_hfaElemKind = HFA_ELEM_NONE; #endif curArgTabEntry->isBackFilled = false; curArgTabEntry->isNonStandard = false; @@ -2300,12 +2303,16 @@ void fgArgInfo::EvalArgsToTemps() { setupArg = compiler->fgMorphCopyBlock(setupArg); #if defined(_TARGET_ARMARCH_) || defined(UNIX_AMD64_ABI) - // This scalar LclVar widening step is only performed for ARM and AMD64 unix. - // - CORINFO_CLASS_HANDLE clsHnd = compiler->lvaGetStruct(tmpVarNum); - unsigned structSize = varDsc->lvExactSize; + if (lclVarType == TYP_STRUCT) + { + // This scalar LclVar widening step is only performed for ARM architectures. + // + CORINFO_CLASS_HANDLE clsHnd = compiler->lvaGetStruct(tmpVarNum); + unsigned structSize = varDsc->lvExactSize; - scalarType = compiler->getPrimitiveTypeForStruct(structSize, clsHnd, curArgTabEntry->isVararg); + scalarType = + compiler->getPrimitiveTypeForStruct(structSize, clsHnd, curArgTabEntry->isVararg); + } #endif // _TARGET_ARMARCH_ || defined (UNIX_AMD64_ABI) } @@ -2391,7 +2398,7 @@ void fgArgInfo::EvalArgsToTemps() #else // !defined(_TARGET_AMD64_) || defined(UNIX_AMD64_ABI) - if (varTypeIsStruct(defArg)) + if (defArg->TypeGet() == TYP_STRUCT) { clsHnd = compiler->gtGetStructHandleIfPresent(defArg); noway_assert(clsHnd != NO_CLASS_HANDLE); @@ -3079,7 +3086,7 @@ void Compiler::fgInitArgInfo(GenTreeCall* call) #ifdef FEATURE_HFA hfaType = GetHfaType(argx); - isHfaArg = varTypeIsFloating(hfaType); + isHfaArg = varTypeIsValidHfaType(hfaType); #if defined(_TARGET_WINDOWS_) && defined(_TARGET_ARM64_) // Make sure for vararg methods isHfaArg is not true. @@ -3628,7 +3635,7 @@ void Compiler::fgInitArgInfo(GenTreeCall* call) #ifdef FEATURE_HFA if (isHfaArg) { - newArgEntry->setHfaType(hfaType, hfaSlots); + newArgEntry->SetHfaType(hfaType, hfaSlots); } #endif // FEATURE_HFA newArgEntry->SetMultiRegNums(); @@ -3872,7 +3879,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) { if (isPow2(passingSize)) { - canTransform = true; + canTransform = (!argEntry->isHfaArg || (passingSize == genTypeSize(argEntry->GetHfaType()))); } #if defined(_TARGET_ARM64_) || defined(UNIX_AMD64_ABI) @@ -3957,15 +3964,16 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) } else { - // We have a struct argument that's less than pointer size, and it is either a power of 2, + // We have a struct argument that fits into a register, and it is either a power of 2, // or a local. - // Change our GT_OBJ into a GT_IND of the correct type. + // Change our argument, as needed, into a value of the appropriate type. CLANG_FORMAT_COMMENT_ANCHOR; #ifdef _TARGET_ARM_ assert((size == 1) || ((structBaseType == TYP_DOUBLE) && (size == 2))); #else - assert(size == 1); + assert((size == 1) || + (varTypeIsSIMD(structBaseType) && size == (genTypeSize(structBaseType) / REGSIZE_BYTES))); #endif assert((structBaseType != TYP_STRUCT) && (genTypeSize(structBaseType) >= originalSize)); @@ -4012,7 +4020,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) // we will use the first and only promoted field argObj->gtLclVarCommon.SetLclNum(varDsc->lvFieldLclStart); - if (varTypeCanReg(fieldVarDsc->TypeGet()) && + if (varTypeIsEnregisterable(fieldVarDsc->TypeGet()) && (genTypeSize(fieldVarDsc->TypeGet()) == originalSize)) { // Just use the existing field's type @@ -4025,7 +4033,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) argObj->ChangeOper(GT_LCL_FLD); argObj->gtType = structBaseType; } - assert(varTypeCanReg(argObj->TypeGet())); + assert(varTypeIsEnregisterable(argObj->TypeGet())); assert(copyBlkClass == NO_CLASS_HANDLE); } else @@ -4043,7 +4051,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) copyBlkClass = objClass; } } - else if (!varTypeIsIntegralOrI(varDsc->TypeGet())) + else if (genActualType(varDsc->TypeGet()) != structBaseType) { // Not a promoted struct, so just swizzle the type by using GT_LCL_FLD argObj->ChangeOper(GT_LCL_FLD); @@ -4055,44 +4063,41 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) // Not a GT_LCL_VAR, so we can just change the type on the node argObj->gtType = structBaseType; } - assert(varTypeCanReg(argObj->TypeGet()) || - ((copyBlkClass != NO_CLASS_HANDLE) && varTypeCanReg(structBaseType))); - - size = 1; + assert(varTypeIsEnregisterable(argObj->TypeGet()) || + ((copyBlkClass != NO_CLASS_HANDLE) && varTypeIsEnregisterable(structBaseType))); } #endif // !_TARGET_X86_ #ifndef UNIX_AMD64_ABI // We still have a struct unless we converted the GT_OBJ into a GT_IND above... - if (varTypeIsStruct(structBaseType) && !argEntry->passedByRef) + if (isHfaArg && passUsingFloatRegs) { - if (isHfaArg && passUsingFloatRegs) - { - size = argEntry->numRegs; - } - else - { - // If the valuetype size is not a multiple of TARGET_POINTER_SIZE, - // we must copyblk to a temp before doing the obj to avoid - // the obj reading memory past the end of the valuetype - CLANG_FORMAT_COMMENT_ANCHOR; + size = argEntry->numRegs; + } + else if (structBaseType == TYP_STRUCT) + { + // If the valuetype size is not a multiple of TARGET_POINTER_SIZE, + // we must copyblk to a temp before doing the obj to avoid + // the obj reading memory past the end of the valuetype + CLANG_FORMAT_COMMENT_ANCHOR; - if (roundupSize > originalSize) - { - copyBlkClass = objClass; + if (roundupSize > originalSize) + { + copyBlkClass = objClass; - // There are a few special cases where we can omit using a CopyBlk - // where we normally would need to use one. + // There are a few special cases where we can omit using a CopyBlk + // where we normally would need to use one. - if (argObj->gtObj.gtOp1->IsLocalAddrExpr() != nullptr) // Is the source a LclVar? - { - copyBlkClass = NO_CLASS_HANDLE; - } + if (argObj->OperIs(GT_OBJ) && + argObj->AsObj()->gtGetOp1()->IsLocalAddrExpr() != nullptr) // Is the source a LclVar? + { + copyBlkClass = NO_CLASS_HANDLE; } - - size = roundupSize / TARGET_POINTER_SIZE; // Normalize size to number of pointer sized items } + + size = roundupSize / TARGET_POINTER_SIZE; // Normalize size to number of pointer sized items } + #endif // !UNIX_AMD64_ABI } } @@ -4159,7 +4164,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) #if FEATURE_MULTIREG_ARGS if (isStructArg) { - if (size > 1 || isHfaArg) + if (((argEntry->numRegs + argEntry->numSlots) > 1) || (isHfaArg && argx->TypeGet() == TYP_STRUCT)) { hasMultiregStructArgs = true; } @@ -4376,11 +4381,37 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call) } unsigned size = (fgEntryPtr->numRegs + fgEntryPtr->numSlots); - if ((size > 1) || fgEntryPtr->isHfaArg) + if ((size > 1) || (fgEntryPtr->isHfaArg && argx->TypeGet() == TYP_STRUCT)) { foundStructArg = true; if (varTypeIsStruct(argx) && !argx->OperIs(GT_FIELD_LIST)) { + if (fgEntryPtr->isHfaArg) + { + var_types hfaType = fgEntryPtr->hfaType; + unsigned structSize; + if (argx->OperIs(GT_OBJ)) + { + structSize = argx->AsObj()->gtBlkSize; + } + else + { + assert(argx->OperIs(GT_LCL_VAR)); + structSize = lvaGetDesc(argx->AsLclVar()->gtLclNum)->lvExactSize; + } + assert(structSize > 0); + if (structSize == genTypeSize(hfaType)) + { + if (argx->OperIs(GT_OBJ)) + { + fgMorphBlkToInd(argx->AsObj(), hfaType); + } + else + { + argx->gtType = hfaType; + } + } + } arg = fgMorphMultiregStructArg(arg, fgEntryPtr); // Did we replace 'argx' with a new tree? @@ -4490,14 +4521,19 @@ GenTree* Compiler::fgMorphMultiregStructArg(GenTree* arg, fgArgTabEntry* fgEntry #if FEATURE_MULTIREG_ARGS // Examine 'arg' and setup argValue objClass and structSize // - CORINFO_CLASS_HANDLE objClass = gtGetStructHandleIfPresent(arg); - GenTree* argValue = arg; // normally argValue will be arg, but see right below - unsigned structSize = 0; + CORINFO_CLASS_HANDLE objClass = gtGetStructHandleIfPresent(arg); + noway_assert(objClass != NO_CLASS_HANDLE); + GenTree* argValue = arg; // normally argValue will be arg, but see right below + unsigned structSize = 0; - if (arg->OperGet() == GT_OBJ) + if (arg->TypeGet() != TYP_STRUCT) + { + structSize = genTypeSize(arg->TypeGet()); + assert(structSize == info.compCompHnd->getClassSize(objClass)); + } + else if (arg->OperGet() == GT_OBJ) { GenTreeObj* argObj = arg->AsObj(); - objClass = argObj->gtClass; structSize = argObj->Size(); assert(structSize == info.compCompHnd->getClassSize(objClass)); @@ -4527,7 +4563,6 @@ GenTree* Compiler::fgMorphMultiregStructArg(GenTree* arg, fgArgTabEntry* fgEntry } else { - objClass = gtGetStructHandleIfPresent(arg); structSize = info.compCompHnd->getClassSize(objClass); } noway_assert(objClass != NO_CLASS_HANDLE); @@ -4538,8 +4573,8 @@ GenTree* Compiler::fgMorphMultiregStructArg(GenTree* arg, fgArgTabEntry* fgEntry unsigned elemSize = 0; var_types type[MAX_ARG_REG_COUNT] = {}; // TYP_UNDEF = 0 - hfaType = GetHfaType(objClass); // set to float or double if it is an HFA, otherwise TYP_UNDEF - if (varTypeIsFloating(hfaType) + hfaType = fgEntryPtr->hfaType; + if (varTypeIsValidHfaType(hfaType) #if !defined(_HOST_UNIX_) && defined(_TARGET_ARM64_) && !fgEntryPtr->isVararg #endif // !defined(_HOST_UNIX_) && defined(_TARGET_ARM64_) @@ -4657,8 +4692,13 @@ GenTree* Compiler::fgMorphMultiregStructArg(GenTree* arg, fgArgTabEntry* fgEntry #endif // !defined(_HOST_UNIX_) && defined(_TARGET_ARM64_) ) { - // We have a HFA struct - noway_assert(elemType == (varDsc->lvHfaTypeIsFloat() ? TYP_FLOAT : TYP_DOUBLE)); + // We have a HFA struct. + // Note that GetHfaType may not be the same as elemType, since TYP_SIMD8 is handled the same as TYP_DOUBLE. + var_types useElemType = elemType; +#if defined(_TARGET_ARM64_) & defined(FEATURE_SIMD) + useElemType = (elemType == TYP_SIMD8) ? TYP_DOUBLE : useElemType; +#endif // _TARGET_ARM64_ && FEATURE_SIMD + noway_assert(useElemType == varDsc->GetHfaType()); noway_assert(elemSize == genTypeSize(elemType)); noway_assert(elemCount == (varDsc->lvExactSize / elemSize)); noway_assert(elemSize * elemCount == varDsc->lvExactSize); @@ -5291,7 +5331,7 @@ void Compiler::fgFixupStructReturn(GenTree* callNode) #if FEATURE_MULTIREG_RET // Either we don't have a struct now or if struct, then it is a struct returned in regs or in return buffer. - assert(!varTypeIsStruct(call) || call->HasMultiRegRetVal() || callHasRetBuffArg); + assert((call->gtType != TYP_STRUCT) || call->HasMultiRegRetVal() || callHasRetBuffArg); #else // !FEATURE_MULTIREG_RET // No more struct returns assert(call->TypeGet() != TYP_STRUCT); @@ -6607,7 +6647,8 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) } noway_assert(tree->gtOper == GT_IND); - GenTree* res = fgMorphSmpOp(tree); + // Pass down the current mac; if non null we are computing an address + GenTree* res = fgMorphSmpOp(tree, mac); if (fldOffset == 0 && res->OperGet() == GT_IND) { @@ -7103,7 +7144,7 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee) #elif defined(_TARGET_ARM64_) // ARM64 var_types hfaType = GetHfaType(argx); - bool isHfaArg = varTypeIsFloating(hfaType); + bool isHfaArg = varTypeIsValidHfaType(hfaType); size_t size = 1; if (isHfaArg) @@ -11886,6 +11927,10 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) switch (tree->gtOper) { case GT_ADDR: + // A non-null mac here implies this node is part of an address computation. + // If so, we need to pass the existing mac down to the child node. + // + // Otherwise, use a new mac. if (subMac1 == nullptr) { subMac1 = &subIndMac1; @@ -11901,7 +11946,15 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) case GT_BLK: case GT_DYN_BLK: case GT_IND: - subMac1 = &subIndMac1; + // A non-null mac here implies this node is part of an address computation (the tree parent is + // GT_ADDR). + // If so, we need to pass the existing mac down to the child node. + // + // Otherwise, use a new mac. + if (subMac1 == nullptr) + { + subMac1 = &subIndMac1; + } break; default: break; @@ -11936,16 +11989,16 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } } - // If gtOp1 is a GT_FIELD, we need to pass down the mac if - // its parent is GT_ADDR, since the address of the field + // If op1 is a GT_FIELD or indir, we need to pass down the mac if + // its parent is GT_ADDR, since the address of op1 // is part of an ongoing address computation. Otherwise // op1 represents the value of the field and so any address // calculations it does are in a new context. - if ((op1->gtOper == GT_FIELD) && (tree->gtOper != GT_ADDR)) + if (((op1->gtOper == GT_FIELD) || op1->OperIsIndir()) && (tree->gtOper != GT_ADDR)) { subMac1 = nullptr; - // The impact of this field's value to any ongoing + // The impact of op1's value to any ongoing // address computation is handled below when looking // at op2. } @@ -12046,11 +12099,11 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) break; } - // If gtOp2 is a GT_FIELD, we must be taking its value, + // If op2 is a GT_FIELD or indir, we must be taking its value, // so it should evaluate its address in a new context. - if (op2->gtOper == GT_FIELD) + if ((op2->gtOper == GT_FIELD) || op2->OperIsIndir()) { - // The impact of this field's value to any ongoing + // The impact of op2's value to any ongoing // address computation is handled above when looking // at op1. mac = nullptr; @@ -12938,24 +12991,31 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) op1->gtOp.gtOp2->gtOper == GT_CNS_INT && op2->gtOp.gtOp2->gtOper == GT_CNS_INT && !op1->gtOverflow() && !op2->gtOverflow()) { - cns1 = op1->gtOp.gtOp2; - cns2 = op2->gtOp.gtOp2; - cns1->gtIntCon.gtIconVal += cns2->gtIntCon.gtIconVal; -#ifdef _TARGET_64BIT_ - if (cns1->TypeGet() == TYP_INT) + // Don't create a byref pointer that may point outside of the ref object. + // If a GC happens, the byref won't get updated. This can happen if one + // of the int components is negative. It also requires the address generation + // be in a fully-interruptible code region. + if (!varTypeIsGC(op1->gtOp.gtOp1->TypeGet()) && !varTypeIsGC(op2->gtOp.gtOp1->TypeGet())) { - // we need to properly re-sign-extend or truncate after adding two int constants above - cns1->AsIntCon()->TruncateOrSignExtend32(); - } + cns1 = op1->gtOp.gtOp2; + cns2 = op2->gtOp.gtOp2; + cns1->gtIntCon.gtIconVal += cns2->gtIntCon.gtIconVal; +#ifdef _TARGET_64BIT_ + if (cns1->TypeGet() == TYP_INT) + { + // we need to properly re-sign-extend or truncate after adding two int constants above + cns1->AsIntCon()->TruncateOrSignExtend32(); + } #endif //_TARGET_64BIT_ - tree->gtOp.gtOp2 = cns1; - DEBUG_DESTROY_NODE(cns2); + tree->gtOp.gtOp2 = cns1; + DEBUG_DESTROY_NODE(cns2); - op1->gtOp.gtOp2 = op2->gtOp.gtOp1; - op1->gtFlags |= (op1->gtOp.gtOp2->gtFlags & GTF_ALL_EFFECT); - DEBUG_DESTROY_NODE(op2); - op2 = tree->gtOp.gtOp2; + op1->gtOp.gtOp2 = op2->gtOp.gtOp1; + op1->gtFlags |= (op1->gtOp.gtOp2->gtFlags & GTF_ALL_EFFECT); + DEBUG_DESTROY_NODE(op2); + op2 = tree->gtOp.gtOp2; + } } if (op2->IsCnsIntOrI() && varTypeIsIntegralOrI(typ)) @@ -13983,39 +14043,36 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree) if (fgGlobalMorph && (oper == GT_ADD) && !tree->gtOverflow() && (op1->gtOper == GT_ADD) && !op1->gtOverflow() && varTypeIsIntegralOrI(typ)) { + GenTree* ad1 = op1->gtOp.gtOp1; GenTree* ad2 = op1->gtOp.gtOp2; - if (op2->OperIsConst() == 0 && ad2->OperIsConst() != 0) - { - // This takes - // + (tree) - // / \. - // / \. - // / \. - // + (op1) op2 - // / \. - // \. - // ad2 + if (!op2->OperIsConst() && ad2->OperIsConst()) + { + // This takes + // + (tree) + // / \. + // / \. + // / \. + // + (op1) op2 + // / \. + // / \. + // ad1 ad2 // - // And it swaps ad2 and op2. If (op2) is varTypeIsGC, then this implies that (tree) is - // varTypeIsGC. If (op1) is not, then when we swap (ad2) and (op2), then we have a TYP_INT node - // (op1) with a child that is varTypeIsGC. If we encounter that situation, make (op1) the same - // type as (tree). - // - // Also, if (ad2) is varTypeIsGC then (tree) must also be (since op1 is), so no fixing is - // necessary + // and it swaps ad2 and op2. - if (varTypeIsGC(op2->TypeGet())) + // Don't create a byref pointer that may point outside of the ref object. + // If a GC happens, the byref won't get updated. This can happen if one + // of the int components is negative. It also requires the address generation + // be in a fully-interruptible code region. + if (!varTypeIsGC(ad1->TypeGet()) && !varTypeIsGC(op2->TypeGet())) { - noway_assert(varTypeIsGC(typ)); - op1->gtType = typ; - } - tree->gtOp2 = ad2; + tree->gtOp2 = ad2; - op1->gtOp.gtOp2 = op2; - op1->gtFlags |= op2->gtFlags & GTF_ALL_EFFECT; + op1->gtOp.gtOp2 = op2; + op1->gtFlags |= op2->gtFlags & GTF_ALL_EFFECT; - op2 = tree->gtOp2; + op2 = tree->gtOp2; + } } } @@ -17008,9 +17065,8 @@ void Compiler::fgMorph() fgUpdateFinallyTargetFlags(); /* For x64 and ARM64 we need to mark irregular parameters */ - lvaRefCountState = RCS_EARLY; - fgMarkImplicitByRefArgs(); + fgResetImplicitByRefRefCount(); /* Promote struct locals if necessary */ fgPromoteStructs(); @@ -17401,12 +17457,10 @@ void Compiler::fgMorphLocalField(GenTree* tree, GenTree* parent) // The field must be an enregisterable type; otherwise it would not be a promoted field. // The tree type may not match, e.g. for return types that have been morphed, but both // must be enregisterable types. - // TODO-Cleanup: varTypeCanReg should presumably return true for SIMD types, but - // there may be places where that would violate existing assumptions. var_types treeType = tree->TypeGet(); var_types fieldType = fldVarDsc->TypeGet(); - assert((varTypeCanReg(treeType) || varTypeIsSIMD(treeType)) && - (varTypeCanReg(fieldType) || varTypeIsSIMD(fieldType))); + assert((varTypeIsEnregisterable(treeType) || varTypeIsSIMD(treeType)) && + (varTypeIsEnregisterable(fieldType) || varTypeIsSIMD(fieldType))); tree->ChangeOper(GT_LCL_VAR); assert(tree->gtLclVarCommon.gtLclNum == fieldLclIndex); @@ -17440,58 +17494,29 @@ void Compiler::fgMorphLocalField(GenTree* tree, GenTree* parent) } //------------------------------------------------------------------------ -// fgMarkImplicitByRefArgs: Identify any by-value struct parameters which are "implicit by-reference"; -// i.e. which the ABI requires to be passed by making a copy in the caller and -// passing its address to the callee. Mark their `LclVarDsc`s such that -// `lvaIsImplicitByRefLocal` will return true for them. +// fgResetImplicitByRefRefCount: Clear the ref count field of all implicit byrefs -void Compiler::fgMarkImplicitByRefArgs() +void Compiler::fgResetImplicitByRefRefCount() { #if (defined(_TARGET_AMD64_) && !defined(UNIX_AMD64_ABI)) || defined(_TARGET_ARM64_) #ifdef DEBUG if (verbose) { - printf("\n*************** In fgMarkImplicitByRefs()\n"); + printf("\n*************** In fgResetImplicitByRefRefCount()\n"); } #endif // DEBUG - for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) + for (unsigned lclNum = 0; lclNum < info.compArgsCount; ++lclNum) { - LclVarDsc* varDsc = &lvaTable[lclNum]; + LclVarDsc* varDsc = lvaGetDesc(lclNum); - if (varDsc->lvIsParam && varTypeIsStruct(varDsc)) + if (varDsc->lvIsImplicitByRef) { - size_t size; - - if (varDsc->lvSize() > REGSIZE_BYTES) - { - size = varDsc->lvSize(); - } - else - { - CORINFO_CLASS_HANDLE typeHnd = varDsc->lvVerTypeInfo.GetClassHandle(); - size = info.compCompHnd->getClassSize(typeHnd); - } - -#if defined(_TARGET_AMD64_) - if (size > REGSIZE_BYTES || (size & (size - 1)) != 0) -#elif defined(_TARGET_ARM64_) - if ((size > TARGET_POINTER_SIZE) && !lvaIsMultiregStruct(varDsc, this->info.compIsVarArgs)) -#endif - { - // Previously nobody was ever setting lvIsParam and lvIsTemp on the same local - // So I am now using it to indicate that this is one of the weird implicit - // by ref locals. - // The address taken cleanup will look for references to locals marked like - // this, and transform them appropriately. - varDsc->lvIsTemp = 1; - - // Clear the ref count field; fgMarkAddressTakenLocals will increment it per - // appearance of implicit-by-ref param so that call arg morphing can do an - // optimization for single-use implicit-by-ref params whose single use is as - // an outgoing call argument. - varDsc->setLvRefCnt(0, RCS_EARLY); - } + // Clear the ref count field; fgMarkAddressTakenLocals will increment it per + // appearance of implicit-by-ref param so that call arg morphing can do an + // optimization for single-use implicit-by-ref params whose single use is as + // an outgoing call argument. + varDsc->setLvRefCnt(0, RCS_EARLY); } } @@ -17623,8 +17648,7 @@ void Compiler::fgRetypeImplicitByRefArgs() // the parameter which is really a pointer to the struct. fieldVarDsc->lvIsRegArg = false; fieldVarDsc->lvIsMultiRegArg = false; - fieldVarDsc->lvSetIsHfaRegArg(false); - fieldVarDsc->lvArgReg = REG_NA; + fieldVarDsc->lvArgReg = REG_NA; #if FEATURE_MULTIREG_ARGS fieldVarDsc->lvOtherArgReg = REG_NA; #endif diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp index 431f4d5ab1e6..7749e928ba5f 100644 --- a/src/jit/optimizer.cpp +++ b/src/jit/optimizer.cpp @@ -6885,26 +6885,36 @@ bool Compiler::optHoistLoopExprsForTree(GenTree* tree, // Tree must be a suitable CSE candidate for us to be able to hoist it. treeIsHoistable &= optIsCSEcandidate(tree); - // If it's a call, it must be a helper call, and be pure. - // Further, if it may run a cctor, it must be labeled as "Hoistable" - // (meaning it won't run a cctor because the class is not precise-init). - if (treeIsHoistable && tree->OperGet() == GT_CALL) + if (treeIsHoistable) { - GenTreeCall* call = tree->AsCall(); - if (call->gtCallType != CT_HELPER) + // We cannot hoist an r-value of TYP_STRUCT + // as they currently do not carry full descriptors of the struct type + if (tree->TypeGet() == TYP_STRUCT) { treeIsHoistable = false; } - else + + // If it's a call, it must be a helper call, and be pure. + // Further, if it may run a cctor, it must be labeled as "Hoistable" + // (meaning it won't run a cctor because the class is not precise-init). + if (tree->OperGet() == GT_CALL) { - CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); - if (!s_helperCallProperties.IsPure(helpFunc)) + GenTreeCall* call = tree->AsCall(); + if (call->gtCallType != CT_HELPER) { treeIsHoistable = false; } - else if (s_helperCallProperties.MayRunCctor(helpFunc) && (call->gtFlags & GTF_CALL_HOISTABLE) == 0) + else { - treeIsHoistable = false; + CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); + if (!s_helperCallProperties.IsPure(helpFunc)) + { + treeIsHoistable = false; + } + else if (s_helperCallProperties.MayRunCctor(helpFunc) && (call->gtFlags & GTF_CALL_HOISTABLE) == 0) + { + treeIsHoistable = false; + } } } } diff --git a/src/jit/protojit/CMakeLists.txt b/src/jit/protojit/CMakeLists.txt index 79fd9aed9164..b5d4e08cfced 100644 --- a/src/jit/protojit/CMakeLists.txt +++ b/src/jit/protojit/CMakeLists.txt @@ -13,6 +13,8 @@ if(WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=protojit.dll) endif(WIN32) +set_source_files_properties(${JIT_EXPORTS_FILE} PROPERTIES GENERATED TRUE) + add_library_clr(protojit SHARED ${SHARED_LIB_SOURCES} diff --git a/src/jit/protononjit/CMakeLists.txt b/src/jit/protononjit/CMakeLists.txt index dc6a595e69f4..f921763e259a 100644 --- a/src/jit/protononjit/CMakeLists.txt +++ b/src/jit/protononjit/CMakeLists.txt @@ -39,6 +39,8 @@ if(WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=protononjit.dll) endif(WIN32) +set_source_files_properties(${JIT_EXPORTS_FILE} PROPERTIES GENERATED TRUE) + add_library_clr(protononjit SHARED ${SHARED_LIB_SOURCES} diff --git a/src/jit/rationalize.cpp b/src/jit/rationalize.cpp index cf5f44acd130..e22621206ae1 100644 --- a/src/jit/rationalize.cpp +++ b/src/jit/rationalize.cpp @@ -75,8 +75,8 @@ void copyFlags(GenTree* dst, GenTree* src, unsigned mask) void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk) { #ifdef FEATURE_SIMD - // No lowering is needed for non-SIMD nodes, so early out if featureSIMD is not enabled. - if (!comp->featureSIMD) + // No lowering is needed for non-SIMD nodes, so early out if SIMD types are not supported. + if (!comp->supportSIMDTypes()) { return; } @@ -771,7 +771,7 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge #ifdef FEATURE_SIMD case GT_SIMD: { - noway_assert(comp->featureSIMD); + noway_assert(comp->supportSIMDTypes()); GenTreeSIMD* simdNode = node->AsSIMD(); unsigned simdSize = simdNode->gtSIMDSize; var_types simdType = comp->getSIMDTypeForSize(simdSize); diff --git a/src/jit/register_arg_convention.h b/src/jit/register_arg_convention.h index 28f29b7c13c3..ad20b4a0f543 100644 --- a/src/jit/register_arg_convention.h +++ b/src/jit/register_arg_convention.h @@ -58,7 +58,7 @@ struct InitVarDscInfo // return ref to current register arg for this type unsigned& regArgNum(var_types type) { - return varTypeIsFloating(type) ? floatRegArgNum : intRegArgNum; + return varTypeUsesFloatArgReg(type) ? floatRegArgNum : intRegArgNum; } // Allocate a set of contiguous argument registers. "type" is either an integer @@ -110,7 +110,7 @@ struct InitVarDscInfo // return max register arg for this type unsigned maxRegArgNum(var_types type) { - return varTypeIsFloating(type) ? maxFloatRegArgNum : maxIntRegArgNum; + return varTypeUsesFloatArgReg(type) ? maxFloatRegArgNum : maxIntRegArgNum; } bool enoughAvailRegs(var_types type, unsigned numRegs = 1); diff --git a/src/jit/scopeinfo.cpp b/src/jit/scopeinfo.cpp index be6fb8ce6c7f..d396b333a460 100644 --- a/src/jit/scopeinfo.cpp +++ b/src/jit/scopeinfo.cpp @@ -301,14 +301,17 @@ void CodeGenInterface::siVarLoc::siFillStackVarLoc( // size is not 1, 2, 4 or 8 bytes in size. During fgMorph, the compiler modifies // the IR to comply with the ABI and therefore changes the type of the lclVar // that holds the struct from TYP_STRUCT to TYP_BYREF but it gives us a hint that - // this is still a struct by setting the lvIsTemp flag. + // this is still a struct by setting the lvIsImplicitByref flag. // The same is true for ARM64 and structs > 16 bytes. - // (See Compiler::fgMarkImplicitByRefArgs in Morph.cpp for further detail) + // + // See lvaSetStruct for further detail. + // // Now, the VM expects a special enum for these type of local vars: VLT_STK_BYREF // to accomodate for this situation. - if (varDsc->lvType == TYP_BYREF && varDsc->lvIsTemp) + if (varDsc->lvIsImplicitByRef) { assert(varDsc->lvIsParam); + assert(varDsc->lvType == TYP_BYREF); this->vlType = VLT_STK_BYREF; } else diff --git a/src/jit/simd.cpp b/src/jit/simd.cpp index b4cecb3e2046..81494b02361c 100644 --- a/src/jit/simd.cpp +++ b/src/jit/simd.cpp @@ -121,7 +121,7 @@ int Compiler::getSIMDTypeAlignment(var_types simdType) // var_types Compiler::getBaseTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, unsigned* sizeBytes /*= nullptr */) { - assert(featureSIMD); + assert(supportSIMDTypes()); if (m_simdHandleCache == nullptr) { diff --git a/src/jit/simdcodegenxarch.cpp b/src/jit/simdcodegenxarch.cpp index 6982a1b7d63b..a340fb090de5 100644 --- a/src/jit/simdcodegenxarch.cpp +++ b/src/jit/simdcodegenxarch.cpp @@ -3089,7 +3089,7 @@ void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode) assert(srcReg != REG_NA); if (srcReg != REG_STK) { - getEmitter()->emitIns_R_R_I(INS_vinsertf128, EA_32BYTE, lclVarReg, srcReg, 0x01); + getEmitter()->emitIns_R_R_R_I(INS_vinsertf128, EA_32BYTE, lclVarReg, lclVarReg, srcReg, 0x01); } else { @@ -3099,7 +3099,7 @@ void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode) assert(varDsc->lvOnFrame); // We will load this from the upper 16 bytes of this localVar's home. int offs = 16; - getEmitter()->emitIns_R_S_I(INS_vinsertf128, EA_32BYTE, lclVarReg, varNum, offs, 0x01); + getEmitter()->emitIns_R_R_S_I(INS_vinsertf128, EA_32BYTE, lclVarReg, lclVarReg, varNum, offs, 0x01); } } diff --git a/src/jit/standalone/CMakeLists.txt b/src/jit/standalone/CMakeLists.txt index 5f32d49c4f1e..f893ddc667ad 100644 --- a/src/jit/standalone/CMakeLists.txt +++ b/src/jit/standalone/CMakeLists.txt @@ -12,6 +12,8 @@ if(WIN32) add_definitions(-DFX_VER_INTERNALNAME_STR=clrjit.dll) endif(WIN32) +set_source_files_properties(${JIT_EXPORTS_FILE} PROPERTIES GENERATED TRUE) + add_library_clr(clrjit SHARED ${SHARED_LIB_SOURCES} diff --git a/src/jit/target.h b/src/jit/target.h index 561db79c6ae5..a225d1a4bb1c 100644 --- a/src/jit/target.h +++ b/src/jit/target.h @@ -246,6 +246,7 @@ typedef unsigned char regNumberSmall; #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register + #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). #define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments (note this seems wrong as MAX_ARG_REG_COUNT is 2) #define MAX_RET_MULTIREG_BYTES 8 // Maximum size of a struct that could be returned in more than one register @@ -488,6 +489,15 @@ typedef unsigned char regNumberSmall; #define INS_stosp INS_stosd #define INS_r_stosp INS_r_stosd + // Any stack pointer adjustments larger than this (in bytes) when setting up outgoing call arguments + // requires a stack probe. Set it large enough so all normal stack arguments don't get a probe. + #define ARG_STACK_PROBE_THRESHOLD_BYTES 1024 + + // The number of bytes from the end the last probed page that must also be probed, to allow for some + // small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word + // on the stack guard page, and must be touched before any further "SUB SP". + #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES ARG_STACK_PROBE_THRESHOLD_BYTES + #elif defined(_TARGET_AMD64_) // TODO-AMD64-CQ: Fine tune the following xxBlk threshold values: @@ -531,6 +541,7 @@ typedef unsigned char regNumberSmall; #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. #define FEATURE_SET_FLAGS 0 // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set + #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). #ifdef UNIX_AMD64_ABI #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register @@ -889,6 +900,9 @@ typedef unsigned char regNumberSmall; #define INS_stosp INS_stosq #define INS_r_stosp INS_r_stosq + // AMD64 uses FEATURE_FIXED_OUT_ARGS so this can be zero. + #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 + #elif defined(_TARGET_ARM_) // TODO-ARM-CQ: Use shift for division by power of 2 @@ -912,6 +926,7 @@ typedef unsigned char regNumberSmall; #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register (including passing HFAs) #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register (including HFA returns) #define FEATURE_STRUCT_CLASSIFIER 0 // Uses a classifier function to determine is structs are passed/returned in more than one register + #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). #define MAX_PASS_MULTIREG_BYTES 32 // Maximum size of a struct that could be passed in more than one register (Max is an HFA of 4 doubles) #define MAX_RET_MULTIREG_BYTES 32 // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 4 doubles) #define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 floats or doubles using an HFA) @@ -1219,9 +1234,10 @@ typedef unsigned char regNumberSmall; #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register #define FEATURE_STRUCT_CLASSIFIER 0 // Uses a classifier function to determine is structs are passed/returned in more than one register - #define MAX_PASS_MULTIREG_BYTES 32 // Maximum size of a struct that could be passed in more than one register (max is 4 doubles using an HFA) - #define MAX_RET_MULTIREG_BYTES 32 // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 4 doubles) - #define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 floats or doubles using an HFA) + #define MAX_PASS_SINGLEREG_BYTES 16 // Maximum size of a struct passed in a single register (16-byte vector). + #define MAX_PASS_MULTIREG_BYTES 64 // Maximum size of a struct that could be passed in more than one register (max is 4 16-byte vectors using an HVA) + #define MAX_RET_MULTIREG_BYTES 64 // Maximum size of a struct that could be returned in more than one register (Max is an HVA of 4 16-byte vectors) + #define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 128-bit vectors using an HVA) #define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. #define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers @@ -1331,7 +1347,7 @@ typedef unsigned char regNumberSmall; // x12: trashed // x14: incremented by 8 // x15: trashed - // x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP (currently non-Windows) + // x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP // CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): // On entry: // x13: the source address (points to object reference to write) @@ -1341,11 +1357,10 @@ typedef unsigned char regNumberSmall; // x13: incremented by 8 // x14: incremented by 8 // x15: trashed - // x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP (currently non-Windows) + // x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP // // Note that while x17 (ip1) is currently only trashed under FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP, - // currently only set for non-Windows, it is expected to be set in the future for Windows, and for R2R. - // So simply always consider it trashed, to avoid later breaking changes. + // it is expected to be set in the future for R2R. Consider it trashed to avoid later breaking changes. #define REG_WRITE_BARRIER_DST REG_R14 #define RBM_WRITE_BARRIER_DST RBM_R14 @@ -1944,10 +1959,10 @@ inline regNumber regNextOfType(regNumber reg, var_types type) * Type checks */ -inline bool isFloatRegType(int /* s/b "var_types" */ type) +inline bool isFloatRegType(var_types type) { #if CPU_HAS_FP_SUPPORT - return type == TYP_DOUBLE || type == TYP_FLOAT; + return varTypeUsesFloatReg(type); #else return false; #endif diff --git a/src/jit/unwind.h b/src/jit/unwind.h index a78df32f1f50..06396f2a9af7 100644 --- a/src/jit/unwind.h +++ b/src/jit/unwind.h @@ -20,8 +20,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // You can increase this "max" number if necessary. #if defined(_TARGET_ARM_) -const unsigned MAX_PROLOG_SIZE_BYTES = 40; -const unsigned MAX_EPILOG_SIZE_BYTES = 40; +const unsigned MAX_PROLOG_SIZE_BYTES = 44; +const unsigned MAX_EPILOG_SIZE_BYTES = 44; #define UWC_END 0xFF // "end" unwind code #define UW_MAX_FRAGMENT_SIZE_BYTES (1U << 19) #define UW_MAX_CODE_WORDS_COUNT 15 // Max number that can be encoded in the "Code Words" field of the .pdata record diff --git a/src/jit/vartype.h b/src/jit/vartype.h index 04793ea86830..83824ac13576 100644 --- a/src/jit/vartype.h +++ b/src/jit/vartype.h @@ -174,9 +174,9 @@ inline bool varTypeIsI(T vt) } template -inline bool varTypeCanReg(T vt) +inline bool varTypeIsEnregisterable(T vt) { - return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_I | VTF_FLT)) != 0); + return (TypeGet(vt) != TYP_STRUCT); } template @@ -271,9 +271,56 @@ inline bool varTypeIsStruct(T vt) } template -inline bool varTypeIsEnregisterableStruct(T vt) +inline bool varTypeUsesFloatReg(T vt) { - return (TypeGet(vt) != TYP_STRUCT); + // Note that not all targets support SIMD, but if they don't, varTypeIsSIMD will + // always return false. + return varTypeIsFloating(vt) || varTypeIsSIMD(vt); +} + +template +inline bool varTypeUsesFloatArgReg(T vt) +{ +#ifdef _TARGET_ARM64_ + // Arm64 passes SIMD types in floating point registers. + return varTypeUsesFloatReg(vt); +#else + // Other targets pass them as regular structs - by reference or by value. + return varTypeIsFloating(vt); +#endif +} + +//------------------------------------------------------------------------ +// varTypeIsValidHfaType: Determine if the type is a valid HFA type +// +// Arguments: +// vt - the type of interest +// +// Return Value: +// Returns true iff the type is a valid HFA type. +// +// Notes: +// This should only be called with the return value from GetHfaType(). +// The only valid values are TYP_UNDEF, for which this returns false, +// TYP_FLOAT, TYP_DOUBLE, or (ARM64-only) TYP_SIMD*. +// +template +inline bool varTypeIsValidHfaType(T vt) +{ +#ifdef FEATURE_HFA + bool isValid = (TypeGet(vt) != TYP_UNDEF); + if (isValid) + { +#ifdef _TARGET_ARM64_ + assert(varTypeUsesFloatReg(vt)); +#else // !_TARGET_ARM64_ + assert(varTypeIsFloating(vt)); +#endif // !_TARGET_ARM64_ + } + return isValid; +#else // !FEATURE_HFA + return false; +#endif // !FEATURE_HFA } /*****************************************************************************/ diff --git a/src/md/inc/metamodelrw.h b/src/md/inc/metamodelrw.h index c2d24db8a5f9..d2debc751790 100644 --- a/src/md/inc/metamodelrw.h +++ b/src/md/inc/metamodelrw.h @@ -790,7 +790,7 @@ class CMiniMdRW : public CMiniMdTemplate // They are constant, FieldMarshal, MethodSemantics, ClassLayout, FieldLayout, ImplMap, FieldRVA, NestedClass, and MethodImpl CLookUpHash * m_pLookUpHashs[TBL_COUNT]; -#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE) +#if !defined(DACCESS_COMPILE) MapSHash m_StringPoolOffsetHash; #endif diff --git a/src/md/runtime/mdinternalro.cpp b/src/md/runtime/mdinternalro.cpp index d16d2b02eb6e..a4f59a37b205 100644 --- a/src/md/runtime/mdinternalro.cpp +++ b/src/md/runtime/mdinternalro.cpp @@ -2172,7 +2172,7 @@ HRESULT MDInternalRO::GetPropertyInfoForMethodDef( // Result. // Lazy initialization of m_pMethodSemanticsMap if ((ridMax > 10) && (m_pMethodSemanticsMap == NULL)) { - NewHolder pMethodSemanticsMap = new (nothrow) CMethodSemanticsMap[ridMax]; + NewArrayHolder pMethodSemanticsMap = new (nothrow) CMethodSemanticsMap[ridMax]; if (pMethodSemanticsMap != NULL) { // Fill the table in MethodSemantics order. diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 66d83f1c4219..f4a726e89f53 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -2449,6 +2449,11 @@ DWORD PALAPI PAL_GetLogicalCpuCountFromOS(VOID); +PALIMPORT +DWORD +PALAPI +PAL_GetTotalCpuCount(VOID); + PALIMPORT size_t PALAPI @@ -2558,6 +2563,7 @@ SetErrorMode( #define MEM_MAPPED 0x40000 #define MEM_TOP_DOWN 0x100000 #define MEM_WRITE_WATCH 0x200000 +#define MEM_LARGE_PAGES 0x20000000 #define MEM_RESERVE_EXECUTABLE 0x40000000 // reserve memory using executable memory allocator PALIMPORT @@ -3995,88 +4001,6 @@ CreatePipe( // NUMA related APIs // -typedef enum _PROCESSOR_CACHE_TYPE { - CacheUnified, - CacheInstruction, - CacheData, - CacheTrace -} PROCESSOR_CACHE_TYPE; - -typedef struct _PROCESSOR_NUMBER { - WORD Group; - BYTE Number; - BYTE Reserved; -} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; - -typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { - RelationProcessorCore, - RelationNumaNode, - RelationCache, - RelationProcessorPackage, - RelationGroup, - RelationAll = 0xffff -} LOGICAL_PROCESSOR_RELATIONSHIP; - -typedef ULONG_PTR KAFFINITY; - -#define ANYSIZE_ARRAY 1 - -typedef struct _GROUP_AFFINITY { - KAFFINITY Mask; - WORD Group; - WORD Reserved[3]; -} GROUP_AFFINITY, *PGROUP_AFFINITY; - -typedef struct _PROCESSOR_GROUP_INFO { - BYTE MaximumProcessorCount; - BYTE ActiveProcessorCount; - BYTE Reserved[38]; - KAFFINITY ActiveProcessorMask; -} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO; - -typedef struct _PROCESSOR_RELATIONSHIP { - BYTE Flags; - BYTE EfficiencyClass; - BYTE Reserved[21]; - WORD GroupCount; - GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; -} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP; - -typedef struct _GROUP_RELATIONSHIP { - WORD MaximumGroupCount; - WORD ActiveGroupCount; - BYTE Reserved[20]; - PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY]; -} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; - -typedef struct _NUMA_NODE_RELATIONSHIP { - DWORD NodeNumber; - BYTE Reserved[20]; - GROUP_AFFINITY GroupMask; -} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; - -typedef struct _CACHE_RELATIONSHIP { - BYTE Level; - BYTE Associativity; - WORD LineSize; - DWORD CacheSize; - PROCESSOR_CACHE_TYPE Type; - BYTE Reserved[20]; - GROUP_AFFINITY GroupMask; -} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; - -typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - DWORD Size; - union { - PROCESSOR_RELATIONSHIP Processor; - NUMA_NODE_RELATIONSHIP NumaNode; - CACHE_RELATIONSHIP Cache; - GROUP_RELATIONSHIP Group; - }; -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; - - PALIMPORT BOOL PALAPI @@ -4087,10 +4011,7 @@ GetNumaHighestNodeNumber( PALIMPORT BOOL PALAPI -GetNumaProcessorNodeEx( - IN PPROCESSOR_NUMBER Processor, - OUT PUSHORT NodeNumber -); +PAL_GetNumaProcessorNode(WORD procNo, WORD* node); PALIMPORT LPVOID @@ -4107,61 +4028,12 @@ VirtualAllocExNuma( PALIMPORT BOOL PALAPI -GetLogicalProcessorInformationEx( - IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, - OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - IN OUT PDWORD ReturnedLength -); - -PALIMPORT -DWORD_PTR -PALAPI -SetThreadAffinityMask( - IN HANDLE hThread, - IN DWORD_PTR dwThreadAffinityMask -); - -PALIMPORT -BOOL -PALAPI -SetThreadGroupAffinity( - IN HANDLE hThread, - IN const GROUP_AFFINITY *GroupAffinity, - OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity -); +PAL_SetCurrentThreadAffinity(WORD procNo); PALIMPORT BOOL PALAPI -GetThreadGroupAffinity( - IN HANDLE hThread, - OUT PGROUP_AFFINITY GroupAffinity -); - -PALIMPORT -VOID -PALAPI -GetCurrentProcessorNumberEx( - OUT PPROCESSOR_NUMBER ProcNumber -); - -PALIMPORT -BOOL -PALAPI -GetProcessAffinityMask( - IN HANDLE hProcess, - OUT PDWORD_PTR lpProcessAffinityMask, - OUT PDWORD_PTR lpSystemAffinityMask -); - -PALIMPORT -BOOL -PALAPI -SetThreadIdealProcessorEx( - IN HANDLE hThread, - IN PPROCESSOR_NUMBER lpIdealProcessor, - OUT PPROCESSOR_NUMBER lpPreviousIdealProcessor -); +PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); // // The types of events that can be logged. diff --git a/src/pal/prebuilt/inc/mscoree.h b/src/pal/prebuilt/inc/mscoree.h index 42a97c00960e..ab7bbb0d0c71 100644 --- a/src/pal/prebuilt/inc/mscoree.h +++ b/src/pal/prebuilt/inc/mscoree.h @@ -229,8 +229,7 @@ enum __MIDL___MIDL_itf_mscoree_0000_0000_0009 eExitProcess = ( eRudeUnloadAppDomain + 1 ) , eFastExitProcess = ( eExitProcess + 1 ) , eRudeExitProcess = ( eFastExitProcess + 1 ) , - eDisableRuntime = ( eRudeExitProcess + 1 ) , - MaxPolicyAction = ( eDisableRuntime + 1 ) + MaxPolicyAction = (eRudeExitProcess + 1 ) } EPolicyAction; diff --git a/src/pal/src/misc/sysinfo.cpp b/src/pal/src/misc/sysinfo.cpp index 2c14949b9578..1a1a12f02ffd 100644 --- a/src/pal/src/misc/sysinfo.cpp +++ b/src/pal/src/misc/sysinfo.cpp @@ -95,24 +95,13 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC); #endif #endif // __APPLE__ - DWORD PALAPI -PAL_GetLogicalCpuCountFromOS() +PAL_GetTotalCpuCount() { int nrcpus = 0; -#if HAVE_SCHED_GETAFFINITY - - cpu_set_t cpuSet; - int st = sched_getaffinity(0, sizeof(cpu_set_t), &cpuSet); - if (st != 0) - { - ASSERT("sched_getaffinity failed (%d)\n", errno); - } - - nrcpus = CPU_COUNT(&cpuSet); -#elif HAVE_SYSCONF +#if HAVE_SYSCONF #if defined(_ARM_) || defined(_ARM64_) #define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF @@ -139,11 +128,36 @@ PAL_GetLogicalCpuCountFromOS() { ASSERT("sysctl failed for HW_NCPU (%d)\n", errno); } +#else // HAVE_SYSCONF +#error "Don't know how to get total CPU count on this platform" #endif // HAVE_SYSCONF return nrcpus; } +DWORD +PALAPI +PAL_GetLogicalCpuCountFromOS() +{ + int nrcpus = 0; + +#if HAVE_SCHED_GETAFFINITY + + cpu_set_t cpuSet; + int st = sched_getaffinity(0, sizeof(cpu_set_t), &cpuSet); + if (st != 0) + { + ASSERT("sched_getaffinity failed (%d)\n", errno); + } + + nrcpus = CPU_COUNT(&cpuSet); +#else // HAVE_SCHED_GETAFFINITY + nrcpus = PAL_GetTotalCpuCount(); +#endif // HAVE_SCHED_GETAFFINITY + + return nrcpus; +} + /*++ Function: GetSystemInfo diff --git a/src/pal/src/numa/numa.cpp b/src/pal/src/numa/numa.cpp index 9283a044da54..4fb2bdb6310b 100644 --- a/src/pal/src/numa/numa.cpp +++ b/src/pal/src/numa/numa.cpp @@ -25,11 +25,6 @@ SET_DEFAULT_DEBUG_CHANNEL(NUMA); #include "pal/corunix.hpp" #include "pal/thread.hpp" -#if HAVE_PTHREAD_NP_H -#include -#endif - -#include #include #ifdef __FreeBSD__ #include @@ -43,37 +38,6 @@ SET_DEFAULT_DEBUG_CHANNEL(NUMA); using namespace CorUnix; -#if HAVE_CPUSET_T -typedef cpuset_t cpu_set_t; -#endif - -// CPU affinity descriptor -struct CpuAffinity -{ - // NUMA node - BYTE Node; - // CPU number relative to the group the CPU is in - BYTE Number; - // CPU group - WORD Group; -}; - -// Array mapping global CPU index to its affinity -CpuAffinity *g_cpuToAffinity = NULL; - -// Array mapping CPU group and index in the group to the global CPU index -short *g_groupAndIndexToCpu = NULL; -// Array mapping CPU group to the corresponding affinity mask of the CPUs in the group -KAFFINITY *g_groupToCpuMask = NULL; -// Array mapping CPU group to the number of processors in the group -BYTE *g_groupToCpuCount = NULL; - -// Total number of processors in the system -int g_cpuCount = 0; -// Total number of possible processors in the system -int g_possibleCpuCount = 0; -// Total number of CPU groups -int g_groupCount = 0; // The highest NUMA node available int g_highestNumaNode = 0; // Is numa available @@ -87,92 +51,6 @@ FOR_ALL_NUMA_FUNCTIONS #undef PER_FUNCTION_BLOCK #endif // HAVE_NUMA_H -static const int MaxCpusPerGroup = 8 * sizeof(KAFFINITY); -static const WORD NO_GROUP = 0xffff; - -/*++ -Function: - FreeLookupArrays - -Free CPU and group lookup arrays ---*/ -VOID -FreeLookupArrays() -{ - free(g_groupAndIndexToCpu); - free(g_cpuToAffinity); - free(g_groupToCpuMask); - free(g_groupToCpuCount); - - g_groupAndIndexToCpu = NULL; - g_cpuToAffinity = NULL; - g_groupToCpuMask = NULL; - g_groupToCpuCount = NULL; -} - -/*++ -Function: - AllocateLookupArrays - -Allocate CPU and group lookup arrays -Return TRUE if the allocation succeeded ---*/ -BOOL -AllocateLookupArrays() -{ - g_groupAndIndexToCpu = (short*)malloc(g_groupCount * MaxCpusPerGroup * sizeof(short)); - if (g_groupAndIndexToCpu == NULL) - { - goto FAILED; - } - - g_cpuToAffinity = (CpuAffinity*)malloc(g_possibleCpuCount * sizeof(CpuAffinity)); - if (g_cpuToAffinity == NULL) - { - goto FAILED; - } - - g_groupToCpuMask = (KAFFINITY*)malloc(g_groupCount * sizeof(KAFFINITY)); - if (g_groupToCpuMask == NULL) - { - goto FAILED; - } - - g_groupToCpuCount = (BYTE*)malloc(g_groupCount * sizeof(BYTE)); - if (g_groupToCpuCount == NULL) - { - goto FAILED; - } - - memset(g_groupAndIndexToCpu, 0xff, g_groupCount * MaxCpusPerGroup * sizeof(short)); - memset(g_cpuToAffinity, 0xff, g_possibleCpuCount * sizeof(CpuAffinity)); - memset(g_groupToCpuMask, 0, g_groupCount * sizeof(KAFFINITY)); - memset(g_groupToCpuCount, 0, g_groupCount * sizeof(BYTE)); - - return TRUE; - -FAILED: - FreeLookupArrays(); - - return FALSE; -} - -/*++ -Function: - GetFullAffinityMask - -Get affinity mask for the specified number of processors with all -the processors enabled. ---*/ -KAFFINITY GetFullAffinityMask(int cpuCount) -{ - if ((size_t)cpuCount < sizeof(KAFFINITY) * 8) - { - return ((KAFFINITY)1 << (cpuCount)) - 1; - } - - return ~(KAFFINITY)0; -} /*++ Function: @@ -208,73 +86,6 @@ FOR_ALL_NUMA_FUNCTIONS else { g_numaAvailable = true; - - struct bitmask *mask = numa_allocate_cpumask(); - int numaNodesCount = numa_max_node() + 1; - - g_possibleCpuCount = numa_num_possible_cpus(); - g_cpuCount = 0; - g_groupCount = 0; - - for (int i = 0; i < numaNodesCount; i++) - { - int st = numa_node_to_cpus(i, mask); - // The only failure that can happen is that the mask is not large enough - // but that cannot happen since the mask was allocated by numa_allocate_cpumask - _ASSERTE(st == 0); - unsigned int nodeCpuCount = numa_bitmask_weight(mask); - g_cpuCount += nodeCpuCount; - unsigned int nodeGroupCount = (nodeCpuCount + MaxCpusPerGroup - 1) / MaxCpusPerGroup; - g_groupCount += nodeGroupCount; - } - - if (!AllocateLookupArrays()) - { - dlclose(numaHandle); - return FALSE; - } - - WORD currentGroup = 0; - int currentGroupCpus = 0; - - for (int i = 0; i < numaNodesCount; i++) - { - int st = numa_node_to_cpus(i, mask); - // The only failure that can happen is that the mask is not large enough - // but that cannot happen since the mask was allocated by numa_allocate_cpumask - _ASSERTE(st == 0); - unsigned int nodeCpuCount = numa_bitmask_weight(mask); - unsigned int nodeGroupCount = (nodeCpuCount + MaxCpusPerGroup - 1) / MaxCpusPerGroup; - for (int j = 0; j < g_possibleCpuCount; j++) - { - if (numa_bitmask_isbitset(mask, j)) - { - if (currentGroupCpus == MaxCpusPerGroup) - { - g_groupToCpuCount[currentGroup] = MaxCpusPerGroup; - g_groupToCpuMask[currentGroup] = GetFullAffinityMask(MaxCpusPerGroup); - currentGroupCpus = 0; - currentGroup++; - } - g_cpuToAffinity[j].Node = i; - g_cpuToAffinity[j].Group = currentGroup; - g_cpuToAffinity[j].Number = currentGroupCpus; - g_groupAndIndexToCpu[currentGroup * MaxCpusPerGroup + currentGroupCpus] = j; - currentGroupCpus++; - } - } - - if (currentGroupCpus != 0) - { - g_groupToCpuCount[currentGroup] = currentGroupCpus; - g_groupToCpuMask[currentGroup] = GetFullAffinityMask(currentGroupCpus); - currentGroupCpus = 0; - currentGroup++; - } - } - - numa_free_cpumask(mask); - g_highestNumaNode = numa_max_node(); } } @@ -282,21 +93,7 @@ FOR_ALL_NUMA_FUNCTIONS if (!g_numaAvailable) { // No NUMA - g_possibleCpuCount = PAL_GetLogicalCpuCountFromOS(); - g_cpuCount = PAL_GetLogicalCpuCountFromOS(); - g_groupCount = 1; g_highestNumaNode = 0; - - if (!AllocateLookupArrays()) - { - return FALSE; - } - - for (int i = 0; i < g_possibleCpuCount; i++) - { - g_cpuToAffinity[i].Number = i; - g_cpuToAffinity[i].Group = 0; - } } return TRUE; @@ -311,7 +108,6 @@ Cleanup of the NUMA support data structures VOID NUMASupportCleanup() { - FreeLookupArrays(); #if HAVE_NUMA_H if (g_numaAvailable) { @@ -346,493 +142,35 @@ GetNumaHighestNodeNumber( /*++ Function: - GetNumaProcessorNodeEx + PAL_GetNumaProcessorNode -See MSDN doc. ---*/ -BOOL -PALAPI -GetNumaProcessorNodeEx( - IN PPROCESSOR_NUMBER Processor, - OUT PUSHORT NodeNumber -) -{ - PERF_ENTRY(GetNumaProcessorNodeEx); - ENTRY("GetNumaProcessorNodeEx(Processor=%p, NodeNumber=%p)\n", Processor, NodeNumber); - - BOOL success = FALSE; +Abstract + Get NUMA node of a processor - if ((Processor->Group < g_groupCount) && - (Processor->Number < MaxCpusPerGroup) && - (Processor->Reserved == 0)) - { - short cpu = g_groupAndIndexToCpu[Processor->Group * MaxCpusPerGroup + Processor->Number]; - if (cpu != -1) - { - *NodeNumber = g_cpuToAffinity[cpu].Node; - success = TRUE; - } - } +Parameters: + procNo - number of the processor to get the NUMA node for + node - the resulting NUMA node - if (!success) - { - *NodeNumber = 0xffff; - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("GetNumaProcessorNodeEx returns BOOL %d\n", success); - PERF_EXIT(GetNumaProcessorNodeEx); - - return success; -} - -/*++ -Function: - GetLogicalProcessorInformationEx - -See MSDN doc. +Return value: + TRUE if the function was able to get the NUMA node, FALSE if it has failed. --*/ BOOL PALAPI -GetLogicalProcessorInformationEx( - IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, - OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - IN OUT PDWORD ReturnedLength -) -{ - PERF_ENTRY(GetLogicalProcessorInformationEx); - ENTRY("GetLogicalProcessorInformationEx(RelationshipType=%d, Buffer=%p, ReturnedLength=%p)\n", RelationshipType, Buffer, ReturnedLength); - - BOOL success = FALSE; - - if (RelationshipType == RelationGroup) - { - size_t requiredSize = __builtin_offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group); - requiredSize += __builtin_offsetof(GROUP_RELATIONSHIP, GroupInfo); - requiredSize += g_groupCount * sizeof(PROCESSOR_GROUP_INFO); - - if (*ReturnedLength >= requiredSize) - { - Buffer->Relationship = RelationGroup; - Buffer->Size = requiredSize; - Buffer->Group.MaximumGroupCount = g_groupCount; - Buffer->Group.ActiveGroupCount = g_groupCount; - for (int i = 0; i < g_groupCount; i++) - { - Buffer->Group.GroupInfo[i].MaximumProcessorCount = MaxCpusPerGroup; - Buffer->Group.GroupInfo[i].ActiveProcessorCount = g_groupToCpuCount[i]; - Buffer->Group.GroupInfo[i].ActiveProcessorMask = g_groupToCpuMask[i]; - } - - success = TRUE; - } - else - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - } - - *ReturnedLength = requiredSize; - } - else - { - // We only support the group relationship - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("GetLogicalProcessorInformationEx returns BOOL %d\n", success); - PERF_EXIT(GetLogicalProcessorInformationEx); - - return success; -} - -/*++ -Function: - GetThreadGroupAffinityInternal - -Get the group affinity for the specified pthread ---*/ -BOOL -GetThreadGroupAffinityInternal( - IN pthread_t thread, - OUT PGROUP_AFFINITY GroupAffinity -) +PAL_GetNumaProcessorNode(WORD procNo, WORD* node) { - BOOL success = FALSE; - -#if HAVE_PTHREAD_GETAFFINITY_NP - cpu_set_t cpuSet; - - int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st == 0) - { - WORD group = NO_GROUP; - KAFFINITY mask = 0; - - for (int i = 0; i < g_possibleCpuCount; i++) - { - if (CPU_ISSET(i, &cpuSet)) - { - WORD g = g_cpuToAffinity[i].Group; - // Unless the thread affinity was already set by SetThreadGroupAffinity, it is possible that - // the current thread has affinity with processors from multiple groups. So we report just the - // first group we find. - if (group == NO_GROUP || g == group) - { - group = g; - mask |= ((KAFFINITY)1) << g_cpuToAffinity[i].Number; - } - } - } - - GroupAffinity->Group = group; - GroupAffinity->Mask = mask; - success = TRUE; - } - else - { - SetLastError(ERROR_GEN_FAILURE); - } -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's return a group affinity - // with all the CPUs on the system. - GroupAffinity->Group = 0; - GroupAffinity->Mask = GetFullAffinityMask(g_possibleCpuCount); - success = TRUE; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - - return success; -} - -/*++ -Function: - GetThreadGroupAffinity - -See MSDN doc. ---*/ -BOOL -PALAPI -GetThreadGroupAffinity( - IN HANDLE hThread, - OUT PGROUP_AFFINITY GroupAffinity -) -{ - PERF_ENTRY(GetThreadGroupAffinity); - ENTRY("GetThreadGroupAffinity(hThread=%p, GroupAffinity=%p)\n", hThread, GroupAffinity); - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return FALSE; - } - - BOOL success = GetThreadGroupAffinityInternal( - pTargetThread->GetPThreadSelf(), GroupAffinity); - LOGEXIT("GetThreadGroupAffinity returns BOOL %d\n", success); - PERF_EXIT(GetThreadGroupAffinity); - - return success; -} - - -/*++ -Function: - SetThreadGroupAffinity - -See MSDN doc. ---*/ -BOOL -PALAPI -SetThreadGroupAffinity( - IN HANDLE hThread, - IN const GROUP_AFFINITY *GroupAffinity, - OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity -) -{ - PERF_ENTRY(SetThreadGroupAffinity); - ENTRY("SetThreadGroupAffinity(hThread=%p, GroupAffinity=%p, PreviousGroupAffinity=%p)\n", hThread, GroupAffinity, PreviousGroupAffinity); - - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return FALSE; - } - - pthread_t thread = pTargetThread->GetPThreadSelf(); - - if (PreviousGroupAffinity != NULL) - { - GetThreadGroupAffinityInternal(thread, PreviousGroupAffinity); - } - -#if HAVE_PTHREAD_GETAFFINITY_NP - int groupStartIndex = GroupAffinity->Group * MaxCpusPerGroup; - KAFFINITY mask = 1; - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - - for (int i = 0; i < MaxCpusPerGroup; i++, mask <<= 1) - { - if (GroupAffinity->Mask & mask) - { - int cpu = g_groupAndIndexToCpu[groupStartIndex + i]; - if (cpu != -1) - { - CPU_SET(cpu, &cpuSet); - } - } - } - - int st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st != 0) - { - switch (st) - { - case EINVAL: - // There is no processor in the mask that is allowed to execute the process - SetLastError(ERROR_INVALID_PARAMETER); - break; - case ESRCH: - SetLastError(ERROR_INVALID_HANDLE); - break; - default: - SetLastError(ERROR_GEN_FAILURE); - break; - } - } - - BOOL success = (st == 0); -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's ignore the request - BOOL success = TRUE; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - - LOGEXIT("SetThreadGroupAffinity returns BOOL %d\n", success); - PERF_EXIT(SetThreadGroupAffinity); - - return success; -} - -/*++ -Function: - SetThreadAffinityMask - -See MSDN doc. ---*/ -DWORD_PTR -PALAPI -SetThreadAffinityMask( - IN HANDLE hThread, - IN DWORD_PTR dwThreadAffinityMask -) -{ - PERF_ENTRY(SetThreadAffinityMask); - ENTRY("SetThreadAffinityMask(hThread=%p, dwThreadAffinityMask=%p)\n", hThread, dwThreadAffinityMask); - - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return 0; - } - - pthread_t thread = pTargetThread->GetPThreadSelf(); - -#if HAVE_PTHREAD_GETAFFINITY_NP - cpu_set_t prevCpuSet; - CPU_ZERO(&prevCpuSet); - KAFFINITY prevMask = 0; - - int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &prevCpuSet); - - if (st == 0) - { - for (int i = 0; i < std::min(8 * (int)sizeof(KAFFINITY), g_possibleCpuCount); i++) - { - if (CPU_ISSET(i, &prevCpuSet)) - { - prevMask |= ((KAFFINITY)1) << i; - } - } - } - - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - - int cpu = 0; - while (dwThreadAffinityMask) - { - if (dwThreadAffinityMask & 1) - { - CPU_SET(cpu, &cpuSet); - } - cpu++; - dwThreadAffinityMask >>= 1; - } - - st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st != 0) - { - switch (st) - { - case EINVAL: - // There is no processor in the mask that is allowed to execute the - // process - SetLastError(ERROR_INVALID_PARAMETER); - break; - case ESRCH: - SetLastError(ERROR_INVALID_HANDLE); - break; - default: - SetLastError(ERROR_GEN_FAILURE); - break; - } - } - - DWORD_PTR ret = (st == 0) ? prevMask : 0; -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's ignore the request - DWORD_PTR ret = 0; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - LOGEXIT("SetThreadAffinityMask returns %lu\n", ret); - PERF_EXIT(SetThreadAffinityMask); - - return ret; -} - -/*++ -Function: - GetCurrentProcessorNumberEx - -See MSDN doc. ---*/ -VOID -PALAPI -GetCurrentProcessorNumberEx( - OUT PPROCESSOR_NUMBER ProcNumber -) -{ - PERF_ENTRY(GetCurrentProcessorNumberEx); - ENTRY("GetCurrentProcessorNumberEx(ProcNumber=%p\n", ProcNumber); - - DWORD cpu = GetCurrentProcessorNumber(); - _ASSERTE((int)cpu < g_possibleCpuCount); - ProcNumber->Group = g_cpuToAffinity[cpu].Group; - ProcNumber->Number = g_cpuToAffinity[cpu].Number; - - LOGEXIT("GetCurrentProcessorNumberEx\n"); - PERF_EXIT(GetCurrentProcessorNumberEx); -} - -/*++ -Function: - GetProcessAffinityMask - -See MSDN doc. ---*/ -BOOL -PALAPI -GetProcessAffinityMask( - IN HANDLE hProcess, - OUT PDWORD_PTR lpProcessAffinityMask, - OUT PDWORD_PTR lpSystemAffinityMask -) -{ - PERF_ENTRY(GetProcessAffinityMask); - ENTRY("GetProcessAffinityMask(hProcess=%p, lpProcessAffinityMask=%p, lpSystemAffinityMask=%p\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask); - - BOOL success = FALSE; - - if (hProcess == GetCurrentProcess()) +#if HAVE_NUMA_H + if (g_numaAvailable) { - int cpuCountInMask = (g_cpuCount > 64) ? 64 : g_cpuCount; - - DWORD_PTR systemMask = GetFullAffinityMask(cpuCountInMask); - -#if HAVE_SCHED_GETAFFINITY - int pid = getpid(); - cpu_set_t cpuSet; - int st = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuSet); - if (st == 0) - { - DWORD_PTR processMask = 0; - - for (int i = 0; i < cpuCountInMask; i++) - { - if (CPU_ISSET(i, &cpuSet)) - { - processMask |= ((DWORD_PTR)1) << i; - } - } - - success = TRUE; - - *lpProcessAffinityMask = processMask; - *lpSystemAffinityMask = systemMask; - } - else if (errno == EINVAL) + int result = numa_node_of_cpu(procNo); + if (result >= 0) { - // There are more processors than can fit in a cpu_set_t - // return all bits set for all processors (upto 64) for both masks. - *lpProcessAffinityMask = systemMask; - *lpSystemAffinityMask = systemMask; - success = TRUE; + *node = (WORD)result; + return TRUE; } - else - { - // We should not get any of the errors that the sched_getaffinity can return since none - // of them applies for the current thread, so this is an unexpected kind of failure. - SetLastError(ERROR_GEN_FAILURE); - } -#else // HAVE_SCHED_GETAFFINITY - // There is no API to manage thread affinity, so let's return both affinity masks - // with all the CPUs on the system set. - *lpSystemAffinityMask = systemMask; - *lpProcessAffinityMask = systemMask; - - success = TRUE; -#endif // HAVE_SCHED_GETAFFINITY } - else - { - // PAL supports getting affinity mask for the current process only - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("GetProcessAffinityMask returns BOOL %d\n", success); - PERF_EXIT(GetProcessAffinityMask); +#endif // HAVE_NUMA_H - return success; + return FALSE; } /*++ @@ -866,15 +204,15 @@ VirtualAllocExNuma( #if HAVE_NUMA_H if (result != NULL && g_numaAvailable) { - int nodeMaskLength = (g_highestNumaNode + 1 + sizeof(unsigned long) - 1) / sizeof(unsigned long); - unsigned long *nodeMask = (unsigned long*)alloca(nodeMaskLength * sizeof(unsigned long)); - memset(nodeMask, 0, nodeMaskLength); + int usedNodeMaskBits = g_highestNumaNode + 1; + int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); + unsigned long nodeMask[nodeMaskLength]; + memset(nodeMask, 0, sizeof(nodeMask)); int index = nndPreferred / sizeof(unsigned long); - int mask = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1)); - nodeMask[index] = mask; + nodeMask[index] = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1)); - int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, g_highestNumaNode, 0); + int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, usedNodeMaskBits, 0); _ASSERTE(st == 0); // If the mbind fails, we still return the allocated memory since the nndPreferred is just a hint @@ -898,115 +236,3 @@ VirtualAllocExNuma( return result; } - -/*++ -Function: - SetThreadIdealProcessorEx - -See MSDN doc. ---*/ -BOOL -PALAPI -SetThreadIdealProcessorEx( - IN HANDLE hThread, - IN PPROCESSOR_NUMBER lpIdealProcessor, - OUT PPROCESSOR_NUMBER lpPreviousIdealProcessor) -{ - PERF_ENTRY(SetThreadIdealProcessorEx); - ENTRY("SetThreadIdealProcessorEx(hThread=%p, lpIdealProcessor=%p)\n", hThread, lpIdealProcessor); - - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return 0; - } - - pthread_t thread = pTargetThread->GetPThreadSelf(); - -#if HAVE_PTHREAD_GETAFFINITY_NP - int cpu = -1; - if ((lpIdealProcessor->Group < g_groupCount) && - (lpIdealProcessor->Number < MaxCpusPerGroup) && - (lpIdealProcessor->Reserved == 0)) - { - cpu = g_groupAndIndexToCpu[lpIdealProcessor->Group * MaxCpusPerGroup + lpIdealProcessor->Number]; - } - - if (cpu == -1) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (lpPreviousIdealProcessor != NULL) - { - cpu_set_t prevCpuSet; - CPU_ZERO(&prevCpuSet); - DWORD prevCpu = GetCurrentProcessorNumber(); - - int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &prevCpuSet); - - if (st == 0) - { - for (int i = 0; i < g_possibleCpuCount; i++) - { - if (CPU_ISSET(i, &prevCpuSet)) - { - prevCpu = i; - break; - } - } - } - - _ASSERTE((int)prevCpu < g_possibleCpuCount); - lpPreviousIdealProcessor->Group = g_cpuToAffinity[prevCpu].Group; - lpPreviousIdealProcessor->Number = g_cpuToAffinity[prevCpu].Number; - lpPreviousIdealProcessor->Reserved = 0; - } - - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - CPU_SET(cpu, &cpuSet); - - int st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st != 0) - { - switch (st) - { - case EINVAL: - // There is no processor in the mask that is allowed to execute the - // process - SetLastError(ERROR_INVALID_PARAMETER); - break; - case ESRCH: - SetLastError(ERROR_INVALID_HANDLE); - break; - default: - SetLastError(ERROR_GEN_FAILURE); - break; - } - } - - BOOL success = (st == 0); - -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's ignore the request - BOOL success = FALSE; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - - LOGEXIT("SetThreadIdealProcessorEx returns BOOL %d\n", success); - PERF_EXIT(SetThreadIdealProcessorEx); - - return success; -} diff --git a/src/pal/src/numa/numashim.h b/src/pal/src/numa/numashim.h index dd7f58d6de24..e56cfab9d123 100644 --- a/src/pal/src/numa/numashim.h +++ b/src/pal/src/numa/numashim.h @@ -13,19 +13,12 @@ #include #include -#define numa_free_cpumask numa_bitmask_free - // List of all functions from the numa library that are used #define FOR_ALL_NUMA_FUNCTIONS \ PER_FUNCTION_BLOCK(numa_available) \ PER_FUNCTION_BLOCK(mbind) \ - PER_FUNCTION_BLOCK(numa_num_possible_cpus) \ PER_FUNCTION_BLOCK(numa_max_node) \ - PER_FUNCTION_BLOCK(numa_allocate_cpumask) \ - PER_FUNCTION_BLOCK(numa_node_to_cpus) \ - PER_FUNCTION_BLOCK(numa_bitmask_weight) \ - PER_FUNCTION_BLOCK(numa_bitmask_isbitset) \ - PER_FUNCTION_BLOCK(numa_bitmask_free) + PER_FUNCTION_BLOCK(numa_node_of_cpu) // Declare pointers to all the used numa functions #define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; @@ -36,13 +29,8 @@ FOR_ALL_NUMA_FUNCTIONS // to the functions of libnuma in the initialization. #define numa_available() numa_available_ptr() #define mbind(...) mbind_ptr(__VA_ARGS__) -#define numa_num_possible_cpus() numa_num_possible_cpus_ptr() #define numa_max_node() numa_max_node_ptr() -#define numa_allocate_cpumask() numa_allocate_cpumask_ptr() -#define numa_node_to_cpus(...) numa_node_to_cpus_ptr(__VA_ARGS__) -#define numa_bitmask_weight(...) numa_bitmask_weight_ptr(__VA_ARGS__) -#define numa_bitmask_isbitset(...) numa_bitmask_isbitset_ptr(__VA_ARGS__) -#define numa_bitmask_free(...) numa_bitmask_free_ptr(__VA_ARGS__) +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) #endif // HAVE_NUMA_H diff --git a/src/pal/src/thread/thread.cpp b/src/pal/src/thread/thread.cpp index 86a08639c7fc..21775f1541fb 100644 --- a/src/pal/src/thread/thread.cpp +++ b/src/pal/src/thread/thread.cpp @@ -64,6 +64,7 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do #include "pal/fakepoll.h" #endif // HAVE_POLL #include +#include #if HAVE_SYS_LWP_H #include @@ -76,6 +77,10 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do extern "C" int _lwp_self (); #endif +#if HAVE_CPUSET_T +typedef cpuset_t cpu_set_t; +#endif + using namespace CorUnix; @@ -2921,3 +2926,90 @@ int CorUnix::CThreadMachExceptionHandlers::GetIndexOfHandler(exception_mask_t bm } #endif // HAVE_MACH_EXCEPTIONS + +/*++ +Function: + PAL_SetCurrentThreadAffinity + +Abstract + Set affinity of the current thread to the specified processor. + +Parameters: + procNo - number of the processor to affinitize the current thread to + +Return value: + TRUE if the function was able to set the affinity, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_SetCurrentThreadAffinity(WORD procNo) +{ +#if HAVE_PTHREAD_GETAFFINITY_NP + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + CPU_SET(procNo, &cpuSet); + int st = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + + return st == 0; +#else // HAVE_PTHREAD_GETAFFINITY_NP + // There is no API to manage thread affinity, so let's ignore the request + return FALSE; +#endif // HAVE_PTHREAD_GETAFFINITY_NP +} + +/*++ +Function: + PAL_SetCurrentThreadAffinity + +Abstract + Get affinity set of the current thread. The set is represented by an array of "size" entries of UINT_PTR type. + +Parameters: + size - number of entries in the "data" array + data - pointer to the data of the resulting set, the LSB of the first entry in the array represents processor 0 + +Return value: + TRUE if the function was able to get the affinity set, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data) +{ +#if HAVE_PTHREAD_GETAFFINITY_NP + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + int st = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + + if (st == 0) + { + const SIZE_T BitsPerBitsetEntry = 8 * sizeof(UINT_PTR); + int nrcpus = PAL_GetTotalCpuCount(); + + // Get info for as much processors as it is possible to fit into the resulting set + SIZE_T remainingCount = std::min(size * BitsPerBitsetEntry, (SIZE_T)nrcpus); + SIZE_T i = 0; + while (remainingCount != 0) + { + UINT_PTR entry = 0; + SIZE_T bitsToCopy = std::min(remainingCount, BitsPerBitsetEntry); + SIZE_T cpuSetOffset = i * BitsPerBitsetEntry; + for (SIZE_T j = 0; j < bitsToCopy; j++) + { + if (CPU_ISSET(cpuSetOffset + j, &cpuSet)) + { + entry |= (UINT_PTR)1 << j; + } + } + remainingCount -= bitsToCopy; + data[i++] = entry; + } + } + + return st == 0; +#else // HAVE_PTHREAD_GETAFFINITY_NP + // There is no API to manage thread affinity, so let's ignore the request + return FALSE; +#endif // HAVE_PTHREAD_GETAFFINITY_NP +} diff --git a/src/strongname/api/common.h b/src/strongname/api/common.h index 626d9bb720d6..4347ebae516c 100644 --- a/src/strongname/api/common.h +++ b/src/strongname/api/common.h @@ -94,11 +94,11 @@ typedef VPTR(class LoaderAllocator) PTR_LoaderAllocator; typedef VPTR(class AppDomain) PTR_AppDomain; -typedef VPTR(class AppDomainBaseObject) PTR_AppDomainBaseObject; typedef DPTR(class ArrayBase) PTR_ArrayBase; typedef DPTR(class ArrayTypeDesc) PTR_ArrayTypeDesc; typedef DPTR(class Assembly) PTR_Assembly; typedef DPTR(class AssemblyBaseObject) PTR_AssemblyBaseObject; +typedef DPTR(class AssemblyLoadContextBaseObject) PTR_AssemblyLoadContextBaseObject; typedef DPTR(class AssemblyNameBaseObject) PTR_AssemblyNameBaseObject; typedef VPTR(class BaseDomain) PTR_BaseDomain; typedef DPTR(class MscorlibBinder) PTR_MscorlibBinder; diff --git a/src/utilcode/pedecoder.cpp b/src/utilcode/pedecoder.cpp index 13d1d27b32b7..24cde95441cc 100644 --- a/src/utilcode/pedecoder.cpp +++ b/src/utilcode/pedecoder.cpp @@ -2559,7 +2559,7 @@ CORCOMPILE_METHOD_PROFILE_LIST *PEDecoder::GetNativeProfileDataList(COUNT_T * pS RETURN PTR_CORCOMPILE_METHOD_PROFILE_LIST(GetDirectoryData(pDir)); } - +#endif // FEATURE_PREJIT PTR_CVOID PEDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const { @@ -2574,7 +2574,13 @@ PTR_CVOID PEDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const CONTRACT_END; IMAGE_DATA_DIRECTORY *pDir; - if (HasReadyToRunHeader()) +#ifdef FEATURE_PREJIT + if (!HasReadyToRunHeader()) + { + pDir = GetMetaDataHelper(METADATA_SECTION_MANIFEST); + } + else +#endif { READYTORUN_HEADER * pHeader = GetReadyToRunHeader(); @@ -2590,10 +2596,6 @@ PTR_CVOID PEDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const pDir = &pSection->Section; } } - else - { - pDir = GetMetaDataHelper(METADATA_SECTION_MANIFEST); - } if (pSize != NULL) *pSize = VAL32(pDir->Size); @@ -2601,6 +2603,8 @@ PTR_CVOID PEDecoder::GetNativeManifestMetadata(COUNT_T *pSize) const RETURN dac_cast(GetDirectoryData(pDir)); } +#ifdef FEATURE_PREJIT + PTR_CORCOMPILE_IMPORT_SECTION PEDecoder::GetNativeImportSections(COUNT_T *pCount) const { CONTRACT(PTR_CORCOMPILE_IMPORT_SECTION) diff --git a/src/utilcode/posterror.cpp b/src/utilcode/posterror.cpp index 3c97db7ea295..a15128add9cc 100644 --- a/src/utilcode/posterror.cpp +++ b/src/utilcode/posterror.cpp @@ -28,16 +28,6 @@ // Local prototypes. HRESULT FillErrorInfo(LPCWSTR szMsg, DWORD dwHelpContext); -//***************************************************************************** -// Function that we'll expose to the outside world to fire off the shutdown method -//***************************************************************************** -#ifdef SHOULD_WE_CLEANUP -void ShutdownCompRC() -{ - CCompRC::ShutdownDefaultResourceDll(); -} -#endif /* SHOULD_WE_CLEANUP */ - void GetResourceCultureCallbacks( FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, FPGETTHREADUICULTUREID* fpGetThreadUICultureId) diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp index 61f41d7a22eb..e7091604af7c 100644 --- a/src/utilcode/util.cpp +++ b/src/utilcode/util.cpp @@ -733,10 +733,17 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, return ::VirtualAllocExNuma(hProc, lpAddr, dwSize, allocType, prot, node); } +#ifndef FEATURE_PAL /*static*/ BOOL NumaNodeInfo::GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no) { return ::GetNumaProcessorNodeEx(proc_no, node_no); } +#else // !FEATURE_PAL +/*static*/ BOOL NumaNodeInfo::GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no) +{ + return PAL_GetNumaProcessorNode(proc_no, node_no); +} +#endif // !FEATURE_PAL #endif /*static*/ BOOL NumaNodeInfo::m_enableGCNumaAware = FALSE; @@ -749,15 +756,6 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_GCNumaAware) == 0) return FALSE; -#ifndef FEATURE_PAL - // check if required APIs are supported - HMODULE hMod = GetModuleHandleW(WINDOWS_KERNEL32_DLLNAME_W); -#else - HMODULE hMod = GetCLRModule(); -#endif - if (hMod == NULL) - return FALSE; - // fail to get the highest numa node number if (!::GetNumaHighestNodeNumber(&highest) || (highest == 0)) return FALSE; @@ -778,8 +776,10 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, m_enableGCNumaAware = InitNumaNodeInfoAPI(); } +#ifndef FEATURE_PAL + //****************************************************************************** -// NumaNodeInfo +// CPUGroupInfo //****************************************************************************** #if !defined(FEATURE_REDHAWK) /*static*/ //CPUGroupInfo::PNTQSIEx CPUGroupInfo::m_pNtQuerySystemInformationEx = NULL; @@ -1187,6 +1187,7 @@ BOOL CPUGroupInfo::GetCPUGroupRange(WORD group_number, WORD* group_begin, WORD* LIMITED_METHOD_CONTRACT; return m_threadUseAllCpuGroups; } +#endif // !FEATURE_PAL //****************************************************************************** // Returns the number of processors that a process has been configured to run on @@ -1206,6 +1207,8 @@ int GetCurrentProcessCpuCount() return cCPUs; unsigned int count = 0; + +#ifndef FEATURE_PAL DWORD_PTR pmask, smask; if (!GetProcessAffinityMask(GetCurrentProcess(), &pmask, &smask)) @@ -1233,18 +1236,20 @@ int GetCurrentProcessCpuCount() count = 64; } -#ifdef FEATURE_PAL - uint32_t cpuLimit; +#else // !FEATURE_PAL + count = PAL_GetLogicalCpuCountFromOS(); + uint32_t cpuLimit; if (PAL_GetCpuLimit(&cpuLimit) && cpuLimit < count) count = cpuLimit; -#endif +#endif // !FEATURE_PAL cCPUs = count; return count; } +#ifndef FEATURE_PAL DWORD_PTR GetCurrentProcessCpuMask() { CONTRACTL @@ -1266,6 +1271,7 @@ DWORD_PTR GetCurrentProcessCpuMask() return 0; #endif } +#endif // !FEATURE_PAL uint32_t GetOsPageSizeUncached() { diff --git a/src/vm/amd64/VirtualCallStubAMD64.asm b/src/vm/amd64/VirtualCallStubAMD64.asm index fc032dd20462..c6ae0aaf2365 100644 --- a/src/vm/amd64/VirtualCallStubAMD64.asm +++ b/src/vm/amd64/VirtualCallStubAMD64.asm @@ -10,8 +10,10 @@ CHAIN_SUCCESS_COUNTER equ ?g_dispatch_cache_chain_success_counter@@3_KA extern VSD_ResolveWorker:proc extern CHAIN_SUCCESS_COUNTER:dword +ifdef FEATURE_PREJIT extern StubDispatchFixupWorker:proc extern ProcessCLRException:proc +endif BACKPATCH_FLAG equ 1 ;; Also known as SDF_ResolveBackPatch in the EE PROMOTE_CHAIN_FLAG equ 2 ;; Also known as SDF_ResolvePromoteChain in the EE @@ -88,6 +90,7 @@ Fail: LEAF_END ResolveWorkerChainLookupAsmStub, _TEXT +ifdef FEATURE_PREJIT NESTED_ENTRY StubDispatchFixupStub, _TEXT, ProcessCLRException PROLOG_WITH_TRANSITION_BLOCK @@ -105,5 +108,6 @@ PATCH_LABEL StubDispatchFixupPatchLabel TAILJMP_RAX NESTED_END StubDispatchFixupStub, _TEXT +endif end diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index abb9ac15d6b6..c106d9dca306 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -3207,11 +3207,7 @@ void AppDomain::Stop() #ifdef DEBUGGING_SUPPORTED if (IsDebuggerAttached()) NotifyDebuggerUnload(); -#endif // DEBUGGING_SUPPORTED - - m_pRootAssembly = NULL; // This assembly is in the assembly list; -#ifdef DEBUGGING_SUPPORTED if (NULL != g_pDebugInterface) { // Call the publisher API to delete this appdomain entry from the list @@ -5240,6 +5236,7 @@ AppDomain::BindHostedPrivAssembly( // Get the NI PEFile if available. PEImageHolder pPEImageNI; +#ifdef FEATURE_PREJIT if (dwAvailableImages & ASSEMBLY_IMAGE_TYPE_NATIVE) { DWORD dwImageType; @@ -5250,6 +5247,7 @@ AppDomain::BindHostedPrivAssembly( pPEImageNI = PEImage::OpenImage(pIResourceNI, MDInternalImport_TrustedNativeImage); } +#endif // FEATURE_PREJIT _ASSERTE(pPEImageIL != nullptr); // Create a PEAssembly using the IL and NI images. diff --git a/src/vm/argdestination.h b/src/vm/argdestination.h index 386ba57c821f..8ddd7b210412 100644 --- a/src/vm/argdestination.h +++ b/src/vm/argdestination.h @@ -60,22 +60,24 @@ class ArgDestination // fieldBytes - size of the structure void CopyHFAStructToRegister(void *src, int fieldBytes) { - // We are either copying either a float or double HFA and need to + // We are copying a float, double or vector HFA/HVA and need to // enregister each field. int floatRegCount = m_argLocDescForStructInRegs->m_cFloatReg; - bool typeFloat = m_argLocDescForStructInRegs->m_isSinglePrecision; + int hfaFieldSize = m_argLocDescForStructInRegs->m_hfaFieldSize; UINT64* dest = (UINT64*) this->GetDestinationAddress(); for (int i = 0; i < floatRegCount; ++i) { // Copy 4 or 8 bytes from src. - UINT64 val = typeFloat ? *((UINT32*)src + i) : *((UINT64*)src + i); + UINT64 val = (hfaFieldSize == 4) ? *((UINT32*)src) : *((UINT64*)src); // Always store 8 bytes *(dest++) = val; - // For now, always zero the next 8 bytes. - // (When HVAs are supported we will get the next 8 bytes from src.) - *(dest++) = 0; + // Either zero the next 8 bytes or get the next 8 bytes from src for 16-byte vector. + *(dest++) = (hfaFieldSize == 16) ? *((UINT64*)src + 1) : 0; + + // Increment src by the appropriate amount. + src = (void*)((char*)src + hfaFieldSize); } } diff --git a/src/vm/arm64/CallDescrWorkerARM64.asm b/src/vm/arm64/CallDescrWorkerARM64.asm index fe277ceb6282..9f2ec2461159 100644 --- a/src/vm/arm64/CallDescrWorkerARM64.asm +++ b/src/vm/arm64/CallDescrWorkerARM64.asm @@ -93,7 +93,7 @@ LNoFloatingPoint bne LNoDoubleReturn LFloatReturn - str d0, [x19, #(CallDescrData__returnValue + 0)] + str q0, [x19, #(CallDescrData__returnValue + 0)] b LReturnDone LNoDoubleReturn @@ -117,6 +117,16 @@ LNoFloatHFAReturn LNoDoubleHFAReturn + ;;VectorHFAReturn return case + cmp w3, #64 + bne LNoVectorHFAReturn + + stp q0, q1, [x19, #(CallDescrData__returnValue + 0)] + stp q2, q3, [x19, #(CallDescrData__returnValue + 0x20)] + b LReturnDone + +LNoVectorHFAReturn + EMIT_BREAKPOINT ; Unreachable LIntReturn diff --git a/src/vm/arm64/asmconstants.h b/src/vm/arm64/asmconstants.h index caffa809eb50..8c99ed841967 100644 --- a/src/vm/arm64/asmconstants.h +++ b/src/vm/arm64/asmconstants.h @@ -61,7 +61,7 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__FloatArgumentRegisters == sizeof(FloatArgumentRegi #define CallDescrData__fpReturnSize 0x20 #define CallDescrData__pTarget 0x28 #define CallDescrData__pRetBuffArg 0x30 -#define CallDescrData__returnValue 0x38 +#define CallDescrData__returnValue 0x40 ASMCONSTANTS_C_ASSERT(CallDescrData__pSrc == offsetof(CallDescrData, pSrc)) ASMCONSTANTS_C_ASSERT(CallDescrData__numStackSlots == offsetof(CallDescrData, numStackSlots)) diff --git a/src/vm/arm64/asmhelpers.asm b/src/vm/arm64/asmhelpers.asm index dfdca9ce4ee1..71e53d3d09e8 100644 --- a/src/vm/arm64/asmhelpers.asm +++ b/src/vm/arm64/asmhelpers.asm @@ -35,10 +35,14 @@ #endif IMPORT ObjIsInstanceOfNoGC - IMPORT ArrayStoreCheck + IMPORT ArrayStoreCheck SETALIAS g_pObjectClass, ?g_pObjectClass@@3PEAVMethodTable@@EA IMPORT $g_pObjectClass +#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP + IMPORT g_sw_ww_table +#endif + IMPORT g_ephemeral_low IMPORT g_ephemeral_high IMPORT g_lowest_address @@ -387,6 +391,7 @@ wbs_highest_address ; x13 : incremented by 8 ; x14 : incremented by 8 ; x15 : trashed +; x17 : trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP ; WRITE_BARRIER_ENTRY JIT_ByRefWriteBarrier @@ -406,6 +411,7 @@ wbs_highest_address ; x12 : trashed ; x14 : incremented by 8 ; x15 : trashed +; x17 : trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP ; WRITE_BARRIER_ENTRY JIT_CheckedWriteBarrier ldr x12, wbs_lowest_address @@ -429,6 +435,7 @@ NotInHeap ; x12 : trashed ; x14 : incremented by 8 ; x15 : trashed +; x17 : trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP ; WRITE_BARRIER_ENTRY JIT_WriteBarrier stlr x15, [x14] @@ -478,7 +485,14 @@ ShadowUpdateDisabled #endif #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP -#error Need to implement for ARM64 + ; Update the write watch table if necessary + ldr x12, wbs_sw_ww_table + cbz x12, CheckCardTable + add x12, x12, x14, LSR #0xC // SoftwareWriteWatch::AddressToTableByteIndexShift + ldrb w17, [x12] + cbnz x17, CheckCardTable + mov w17, 0xFF + strb w17, [x12] #endif CheckCardTable @@ -691,8 +705,9 @@ NoFloatingPointRetVal ; x0 = fpRetSize - ; return value is stored before float argument registers - add x1, sp, #(__PWTB_FloatArgumentRegisters - 0x20) + ; The return value is stored before float argument registers + ; The maximum size of a return value is 0x40 (HVA of 4x16) + add x1, sp, #(__PWTB_FloatArgumentRegisters - 0x40) bl setStubReturnValue EPILOG_WITH_TRANSITION_BLOCK_RETURN diff --git a/src/vm/arm64/calldescrworkerarm64.S b/src/vm/arm64/calldescrworkerarm64.S index f987d402ddee..8e8084ba3496 100644 --- a/src/vm/arm64/calldescrworkerarm64.S +++ b/src/vm/arm64/calldescrworkerarm64.S @@ -85,7 +85,7 @@ LOCAL_LABEL(NoFloatingPoint): bne LOCAL_LABEL(NoDoubleReturn) LOCAL_LABEL(FloatReturn): - str d0, [x19, #(CallDescrData__returnValue + 0)] + str q0, [x19, #(CallDescrData__returnValue + 0)] b LOCAL_LABEL(ReturnDone) LOCAL_LABEL(NoDoubleReturn): @@ -97,6 +97,7 @@ LOCAL_LABEL(NoDoubleReturn): stp s0, s1, [x19, #(CallDescrData__returnValue + 0)] stp s2, s3, [x19, #(CallDescrData__returnValue + 0x08)] b LOCAL_LABEL(ReturnDone) + LOCAL_LABEL(NoFloatHFAReturn): //DoubleHFAReturn return case @@ -109,6 +110,16 @@ LOCAL_LABEL(NoFloatHFAReturn): LOCAL_LABEL(NoDoubleHFAReturn): + //VectorHFAReturn return case + cmp w3, #64 + bne LOCAL_LABEL(LNoVectorHFAReturn) + + stp q0, q1, [x19, #(CallDescrData__returnValue + 0)] + stp q2, q3, [x19, #(CallDescrData__returnValue + 0x20)] + b LOCAL_LABEL(ReturnDone) + +LOCAL_LABEL(LNoVectorHFAReturn): + EMIT_BREAKPOINT // Unreachable LOCAL_LABEL(IntReturn): diff --git a/src/vm/arm64/cgencpu.h b/src/vm/arm64/cgencpu.h index fd1fbafe96da..a2cac4eb7c20 100644 --- a/src/vm/arm64/cgencpu.h +++ b/src/vm/arm64/cgencpu.h @@ -51,7 +51,7 @@ extern PCODE GetPreStubEntryPoint(); #define CACHE_LINE_SIZE 64 #define LOG2SLOT LOG2_PTRSIZE -#define ENREGISTERED_RETURNTYPE_MAXSIZE 32 // bytes (four FP registers: d0,d1,d2 and d3) +#define ENREGISTERED_RETURNTYPE_MAXSIZE 64 // bytes (four vector registers: q0,q1,q2 and q3) #define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE 16 // bytes (two int registers: x0 and x1) #define ENREGISTERED_PARAMTYPE_MAXSIZE 16 // bytes (max value type size that can be passed by value) diff --git a/src/vm/assembly.cpp b/src/vm/assembly.cpp index 1326dfb9b8e1..2d89cc467534 100644 --- a/src/vm/assembly.cpp +++ b/src/vm/assembly.cpp @@ -126,7 +126,7 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyContr #ifdef FEATURE_COMINTEROP , m_InteropAttributeStatus(INTEROP_ATTRIBUTE_UNSET) #endif -#ifdef FEATURE_PREJIT +#if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN) , m_isInstrumentedStatus(IS_INSTRUMENTED_UNSET) #endif { @@ -1866,7 +1866,7 @@ BOOL Assembly::GetResource(LPCSTR szName, DWORD *cbResource, return result; } -#ifdef FEATURE_PREJIT +#if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN) BOOL Assembly::IsInstrumented() { STATIC_CONTRACT_THROWS; diff --git a/src/vm/assembly.hpp b/src/vm/assembly.hpp index d8d974b19840..43d91725de18 100644 --- a/src/vm/assembly.hpp +++ b/src/vm/assembly.hpp @@ -449,7 +449,7 @@ class Assembly BOOL IsSIMDVectorAssembly() { LIMITED_METHOD_DAC_CONTRACT; return m_fIsSIMDVectorAssembly; } -#ifdef FEATURE_PREJIT +#if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN) BOOL IsInstrumented(); BOOL IsInstrumentedHelper(); #endif // FEATURE_PREJIT @@ -627,7 +627,7 @@ class Assembly BOOL m_fIsSIMDVectorAssembly; -#ifdef FEATURE_PREJIT +#if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN) enum IsInstrumentedStatus { IS_INSTRUMENTED_UNSET = 0, IS_INSTRUMENTED_FALSE = 1, diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp index 9c1e467f2f9c..aa830932ed5c 100644 --- a/src/vm/assemblynative.cpp +++ b/src/vm/assemblynative.cpp @@ -38,22 +38,24 @@ FCIMPL6(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAF AssemblyBaseObject* requestingAssemblyUNSAFE, StackCrawlMark* stackMark, CLR_BOOL fThrowOnFileNotFound, - INT_PTR ptrLoadContextBinder) + AssemblyLoadContextBaseObject *assemblyLoadContextUNSAFE) { FCALL_CONTRACT; struct _gc { - ASSEMBLYNAMEREF assemblyName; - STRINGREF codeBase; - ASSEMBLYREF requestingAssembly; - ASSEMBLYREF rv; + ASSEMBLYNAMEREF assemblyName; + STRINGREF codeBase; + ASSEMBLYREF requestingAssembly; + ASSEMBLYREF rv; + ASSEMBLYLOADCONTEXTREF assemblyLoadContext; } gc; - gc.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; - gc.codeBase = (STRINGREF) codeBaseUNSAFE; - gc.requestingAssembly = (ASSEMBLYREF) requestingAssemblyUNSAFE; - gc.rv = NULL; + gc.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; + gc.codeBase = (STRINGREF) codeBaseUNSAFE; + gc.requestingAssembly = (ASSEMBLYREF) requestingAssemblyUNSAFE; + gc.rv = NULL; + gc.assemblyLoadContext = (ASSEMBLYLOADCONTEXTREF) assemblyLoadContextUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); @@ -66,6 +68,8 @@ FCIMPL6(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAF DomainAssembly * pParentAssembly = NULL; Assembly * pRefAssembly = NULL; + INT_PTR ptrLoadContextBinder = (gc.assemblyLoadContext != NULL) ? gc.assemblyLoadContext->GetNativeAssemblyLoadContext() : NULL; + if(gc.assemblyName->GetSimpleName() == NULL) { if (gc.codeBase == NULL) @@ -257,6 +261,7 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext } } +#ifdef FEATURE_PREJIT // Form the PEImage for the NI assembly, if specified if (pwzNIPath != NULL) { @@ -277,6 +282,7 @@ void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext ThrowHR(COR_E_BADIMAGEFORMAT); } } +#endif // FEATURE_PREJIT Assembly *pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinderContext, pILImage, pNIImage); @@ -446,7 +452,13 @@ void QCALLTYPE AssemblyNative::LoadTypeForWinRTTypeNameInContext(INT_PTR ptrAsse } #endif -void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive) +void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, + LPCWSTR wszName, + BOOL bThrowOnError, + BOOL bIgnoreCase, + QCall::ObjectHandleOnStack retType, + QCall::ObjectHandleOnStack keepAlive, + QCall::ObjectHandleOnStack pAssemblyLoadContext) { CONTRACTL { @@ -464,8 +476,20 @@ void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR BOOL prohibitAsmQualifiedName = TRUE; + ICLRPrivBinder * pPrivHostBinder = NULL; + + if (*pAssemblyLoadContext.m_ppObject != NULL) + { + GCX_COOP(); + ASSEMBLYLOADCONTEXTREF * pAssemblyLoadContextRef = reinterpret_cast(pAssemblyLoadContext.m_ppObject); + + INT_PTR nativeAssemblyLoadContext = (*pAssemblyLoadContextRef)->GetNativeAssemblyLoadContext(); + + pPrivHostBinder = reinterpret_cast(nativeAssemblyLoadContext); + } + // Load the class from this assembly (fail if it is in a different one). - retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, NULL, FALSE, (OBJECTREF*)keepAlive.m_ppObject); + retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, pAssembly->GetAssembly(), FALSE, (OBJECTREF*)keepAlive.m_ppObject, pPrivHostBinder); if (!retTypeHandle.IsNull()) { diff --git a/src/vm/assemblynative.hpp b/src/vm/assemblynative.hpp index 0ce2fb232776..12d4ff865877 100644 --- a/src/vm/assemblynative.hpp +++ b/src/vm/assemblynative.hpp @@ -37,7 +37,7 @@ class AssemblyNative AssemblyBaseObject* requestingAssemblyUNSAFE, StackCrawlMark* stackMark, CLR_BOOL fThrowOnFileNotFound, - INT_PTR ptrLoadContextBinder); + AssemblyLoadContextBaseObject *assemblyLoadContextUNSAFE); // // instance FCALLs @@ -78,7 +78,7 @@ class AssemblyNative void QCALLTYPE GetVersion(QCall::AssemblyHandle pAssembly, INT32* pMajorVersion, INT32* pMinorVersion, INT32*pBuildNumber, INT32* pRevisionNumber); static - void QCALLTYPE GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive); + void QCALLTYPE GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive, QCall::ObjectHandleOnStack pAssemblyLoadContext); static void QCALLTYPE GetForwardedType(QCall::AssemblyHandle pAssembly, mdToken mdtExternalType, QCall::ObjectHandleOnStack retType); diff --git a/src/vm/assemblyspec.cpp b/src/vm/assemblyspec.cpp index a044456ff994..ad2ebfdda7e0 100644 --- a/src/vm/assemblyspec.cpp +++ b/src/vm/assemblyspec.cpp @@ -434,13 +434,6 @@ HRESULT AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* CloneFieldsToStackingAllocator(alloc); - // Hash for control - // @TODO cts, can we use unsafe in this case!!! - if ((*pName)->GetHashForControl() != NULL) - SetHashForControl((*pName)->GetHashForControl()->GetDataPtr(), - (*pName)->GetHashForControl()->GetNumComponents(), - (*pName)->GetHashAlgorithmForControl()); - // Extract embedded WinRT name, if present. ParseEncodedName(); @@ -587,7 +580,7 @@ void AssemblySpec::AssemblyNameInit(ASSEMBLYNAMEREF* pAsmName, PEImage* pImageIn IfFailThrow(pImageInfo->GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, &hashAlgId, NULL, NULL, NULL)); } - MethodDescCallSite init(METHOD__ASSEMBLY_NAME__INIT); + MethodDescCallSite init(METHOD__ASSEMBLY_NAME__CTOR); ARG_SLOT MethodArgs[] = { diff --git a/src/vm/assemblyspec.hpp b/src/vm/assemblyspec.hpp index 798f73c2508a..a52c2fcdfe00 100644 --- a/src/vm/assemblyspec.hpp +++ b/src/vm/assemblyspec.hpp @@ -34,7 +34,6 @@ class AssemblySpec : public BaseAssemblySpec friend class AssemblyNameNative; AppDomain *m_pAppDomain; - SBuffer m_HashForControl; DWORD m_dwHashAlg; DomainAssembly *m_pParentAssembly; @@ -187,7 +186,6 @@ class AssemblySpec : public BaseAssemblySpec SetFallbackLoadContextBinderForRequestingAssembly(pSource->GetFallbackLoadContextBinderForRequestingAssembly()); m_fPreferFallbackLoadContextBinder = pSource->GetPreferFallbackLoadContextBinder(); - m_HashForControl = pSource->m_HashForControl; m_dwHashAlg = pSource->m_dwHashAlg; } @@ -248,21 +246,6 @@ class AssemblySpec : public BaseAssemblySpec return m_pAppDomain; } - HRESULT SetHashForControl(PBYTE pHashForControl, DWORD dwHashForControl, DWORD dwHashAlg) - { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - PRECONDITION(CheckPointer(pHashForControl)); - } - CONTRACTL_END; - - m_HashForControl.Set(pHashForControl, dwHashForControl); - m_dwHashAlg=dwHashAlg; - return S_OK; - } - void ParseEncodedName(); void SetWindowsRuntimeType(LPCUTF8 szNamespace, LPCUTF8 szClassName); diff --git a/src/vm/callhelpers.h b/src/vm/callhelpers.h index db9cfad6cb1e..f0d718c6ff5d 100644 --- a/src/vm/callhelpers.h +++ b/src/vm/callhelpers.h @@ -39,8 +39,13 @@ struct CallDescrData // Return value // #ifdef ENREGISTERED_RETURNTYPE_MAXSIZE +#ifdef _TARGET_ARM64_ + // Use NEON128 to ensure proper alignment for vectors. + DECLSPEC_ALIGN(16) NEON128 returnValue[ENREGISTERED_RETURNTYPE_MAXSIZE / sizeof(NEON128)]; +#else // Use UINT64 to ensure proper alignment UINT64 returnValue[ENREGISTERED_RETURNTYPE_MAXSIZE / sizeof(UINT64)]; +#endif #else UINT64 returnValue; #endif diff --git a/src/vm/callingconvention.h b/src/vm/callingconvention.h index 7368fecac816..cbc6aad5c4f6 100644 --- a/src/vm/callingconvention.h +++ b/src/vm/callingconvention.h @@ -49,9 +49,25 @@ struct ArgLocDesc #endif // UNIX_AMD64_ABI +#ifdef FEATURE_HFA + static unsigned getHFAFieldSize(CorElementType hfaType) + { + switch (hfaType) + { + case ELEMENT_TYPE_R4: return 4; + case ELEMENT_TYPE_R8: return 8; + // We overload VALUETYPE for 16-byte vectors. + case ELEMENT_TYPE_VALUETYPE: return 16; + default: _ASSERTE(!"Invalid HFA Type"); return 0; + } + } +#endif #if defined(_TARGET_ARM64_) - bool m_isSinglePrecision; // For determining if HFA is single or double - // precision + unsigned m_hfaFieldSize; // Size of HFA field in bytes. + void setHFAFieldSize(CorElementType hfaType) + { + m_hfaFieldSize = getHFAFieldSize(hfaType); + } #endif // defined(_TARGET_ARM64_) #if defined(_TARGET_ARM_) @@ -76,7 +92,7 @@ struct ArgLocDesc m_fRequires64BitAlignment = FALSE; #endif #if defined(_TARGET_ARM64_) - m_isSinglePrecision = FALSE; + m_hfaFieldSize = 0; #endif // defined(_TARGET_ARM64_) #if defined(UNIX_AMD64_ABI) m_eeClass = NULL; @@ -589,10 +605,9 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE if (!m_argTypeHandle.IsNull() && m_argTypeHandle.IsHFA()) { CorElementType type = m_argTypeHandle.GetHFAType(); - bool isFloatType = (type == ELEMENT_TYPE_R4); + pLoc->setHFAFieldSize(type); + pLoc->m_cFloatReg = GetArgSize()/pLoc->m_hfaFieldSize; - pLoc->m_cFloatReg = isFloatType ? GetArgSize()/sizeof(float): GetArgSize()/sizeof(double); - pLoc->m_isSinglePrecision = isFloatType; } else { @@ -1297,16 +1312,14 @@ int ArgIteratorTemplate::GetNextOffset() if (thValueType.IsHFA()) { CorElementType type = thValueType.GetHFAType(); - bool isFloatType = (type == ELEMENT_TYPE_R4); - - cFPRegs = (type == ELEMENT_TYPE_R4)? (argSize/sizeof(float)): (argSize/sizeof(double)); m_argLocDescForStructInRegs.Init(); - m_argLocDescForStructInRegs.m_cFloatReg = cFPRegs; m_argLocDescForStructInRegs.m_idxFloatReg = m_idxFPReg; - m_argLocDescForStructInRegs.m_isSinglePrecision = isFloatType; - + m_argLocDescForStructInRegs.setHFAFieldSize(type); + cFPRegs = argSize/m_argLocDescForStructInRegs.m_hfaFieldSize; + m_argLocDescForStructInRegs.m_cFloatReg = cFPRegs; + m_hasArgLocDescForStructInRegs = true; } else @@ -1474,10 +1487,8 @@ void ArgIteratorTemplate::ComputeReturnFlags() { CorElementType hfaType = thValueType.GetHFAType(); - flags |= (hfaType == ELEMENT_TYPE_R4) ? - ((4 * sizeof(float)) << RETURN_FP_SIZE_SHIFT) : - ((4 * sizeof(double)) << RETURN_FP_SIZE_SHIFT); - + int hfaFieldSize = ArgLocDesc::getHFAFieldSize(hfaType); + flags |= ((4 * hfaFieldSize) << RETURN_FP_SIZE_SHIFT); break; } #endif diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index 9011cb8d90e2..d98f180eb2d1 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -387,6 +387,7 @@ void Module::InitializeForProfiling() m_nativeImageProfiling = FALSE; +#ifdef FEATURE_PREJIT if (HasNativeImage()) { PEImageLayout * pNativeImage = GetNativeImage(); @@ -400,6 +401,7 @@ void Module::InitializeForProfiling() m_methodProfileList = pNativeImage->GetNativeProfileDataList(&cbProfileList); } else // ReadyToRun image +#endif { #ifdef FEATURE_READYTORUN // We already setup the m_methodProfileList in the ReadyToRunInfo constructor @@ -458,6 +460,13 @@ void Module::InitializeNativeImage(AllocMemTracker* pamTracker) } #endif // defined(HAVE_GCCOVER) } +#else // FEATURE_PREJIT +BOOL Module::IsPersistedObject(void *address) +{ + LIMITED_METHOD_CONTRACT; + return FALSE; +} +#endif // FEATURE_PREJIT void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssembly) { @@ -478,27 +487,19 @@ void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssemb S_SIZE_T dwAllocSize = S_SIZE_T(sizeof(PTR_Assembly)) * S_SIZE_T(dwMaxRid); AllocMemTracker amTracker; - PTR_Assembly * NativeMetadataAssemblyRefMap = (PTR_Assembly *) amTracker.Track( GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(dwAllocSize) ); + PTR_Assembly* NativeMetadataAssemblyRefMap = (PTR_Assembly*)amTracker.Track(GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(dwAllocSize)); // Note: Memory allocated on loader heap is zero filled - if (InterlockedCompareExchangeT(&m_NativeMetadataAssemblyRefMap, NativeMetadataAssemblyRefMap, NULL) == NULL) + if (InterlockedCompareExchangeT(&m_NativeMetadataAssemblyRefMap, NativeMetadataAssemblyRefMap, NULL) == NULL) amTracker.SuppressRelease(); } _ASSERTE(m_NativeMetadataAssemblyRefMap != NULL); _ASSERTE(rid <= GetNativeAssemblyImport()->GetCountWithTokenKind(mdtAssemblyRef)); - m_NativeMetadataAssemblyRefMap[rid-1] = pAssembly; -} -#else // FEATURE_PREJIT -BOOL Module::IsPersistedObject(void *address) -{ - LIMITED_METHOD_CONTRACT; - return FALSE; + m_NativeMetadataAssemblyRefMap[rid - 1] = pAssembly; } -#endif // FEATURE_PREJIT - // Module initialization occurs in two phases: the constructor phase and the Initialize phase. // // The Initialize() phase completes the initialization after the constructor has run. @@ -588,7 +589,7 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) } } -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) && defined(FEATURE_PREJIT) if (IsCompilationProcess() && m_pGuidToTypeHash == NULL) { // only allocate this during NGEN-ing @@ -4146,12 +4147,12 @@ PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSections(COUNT_T *pCount) } CONTRACTL_END; -#ifdef FEATURE_READYTORUN - if (IsReadyToRun()) - return GetReadyToRunInfo()->GetImportSections(pCount); +#ifdef FEATURE_PREJIT + if (!IsReadyToRun()) + return GetNativeImage()->GetNativeImportSections(pCount); #endif - return GetNativeImage()->GetNativeImportSections(pCount); + return GetReadyToRunInfo()->GetImportSections(pCount); } PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionFromIndex(COUNT_T index) @@ -4163,12 +4164,12 @@ PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionFromIndex(COUNT_T index) } CONTRACTL_END; -#ifdef FEATURE_READYTORUN - if (IsReadyToRun()) - return GetReadyToRunInfo()->GetImportSectionFromIndex(index); +#ifdef FEATURE_PREJIT + if (!IsReadyToRun()) + return GetNativeImage()->GetNativeImportSectionFromIndex(index); #endif - return GetNativeImage()->GetNativeImportSectionFromIndex(index); + return GetReadyToRunInfo()->GetImportSectionFromIndex(index); } PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionForRVA(RVA rva) @@ -4180,12 +4181,12 @@ PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionForRVA(RVA rva) } CONTRACTL_END; -#ifdef FEATURE_READYTORUN - if (IsReadyToRun()) - return GetReadyToRunInfo()->GetImportSectionForRVA(rva); +#ifdef FEATURE_PREJIT + if (!IsReadyToRun()) + return GetNativeImage()->GetNativeImportSectionForRVA(rva); #endif - return GetNativeImage()->GetNativeImportSectionForRVA(rva); + return GetReadyToRunInfo()->GetImportSectionForRVA(rva); } TADDR Module::GetIL(DWORD target) @@ -6353,6 +6354,11 @@ static HMODULE GetIJWHostForModule(Module* module) IMAGE_IMPORT_DESCRIPTOR* importDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)pe->GetDirectoryData(pe->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_IMPORT)); + if (importDescriptor == nullptr) + { + return nullptr; + } + for(; importDescriptor->Characteristics != 0; importDescriptor++) { IMAGE_THUNK_DATA* importNameTable = (IMAGE_THUNK_DATA*)pe->GetRvaData(importDescriptor->OriginalFirstThunk); @@ -9804,6 +9810,7 @@ BOOL Module::IsPersistedObject(void *address) return (address >= pLayout->GetBase() && address < (BYTE*)pLayout->GetBase() + pLayout->GetVirtualSize()); } +#endif // FEATURE_PREJIT Module *Module::GetModuleFromIndex(DWORD ix) { @@ -9836,12 +9843,9 @@ Module *Module::GetModuleFromIndex(DWORD ix) } } } -#endif // FEATURE_PREJIT #endif // !DACCESS_COMPILE -#ifdef FEATURE_PREJIT - Module *Module::GetModuleFromIndexIfLoaded(DWORD ix) { CONTRACT(Module*) @@ -9864,25 +9868,9 @@ Module *Module::GetModuleFromIndexIfLoaded(DWORD ix) } #ifndef DACCESS_COMPILE - -BYTE *Module::GetNativeFixupBlobData(RVA rva) -{ - CONTRACT(BYTE *) - { - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - RETURN (BYTE *) GetNativeOrReadyToRunImage()->GetRvaData(rva); -} - -IMDInternalImport *Module::GetNativeAssemblyImport(BOOL loadAllowed) +IMDInternalImport* Module::GetNativeAssemblyImport(BOOL loadAllowed) { - CONTRACT(IMDInternalImport *) + CONTRACT(IMDInternalImport*) { INSTANCE_CHECK; if (loadAllowed) GC_TRIGGERS; else GC_NOTRIGGER; @@ -9891,21 +9879,41 @@ IMDInternalImport *Module::GetNativeAssemblyImport(BOOL loadAllowed) MODE_ANY; PRECONDITION(HasNativeOrReadyToRunImage()); POSTCONDITION(loadAllowed ? - CheckPointer(RETVAL): - CheckPointer(RETVAL, NULL_OK)); + CheckPointer(RETVAL) : + CheckPointer(RETVAL, NULL_OK)); } CONTRACT_END; +#ifdef FEATURE_PREJIT // Check if image is R2R - if (GetFile()->IsILImageReadyToRun()) + if (!GetFile()->IsILImageReadyToRun()) { - RETURN GetFile()->GetOpenedILimage()->GetNativeMDImport(loadAllowed); + RETURN GetFile()->GetPersistentNativeImage()->GetNativeMDImport(loadAllowed); } - else +#endif + + RETURN GetFile()->GetOpenedILimage()->GetNativeMDImport(loadAllowed); +} + +BYTE* Module::GetNativeFixupBlobData(RVA rva) +{ + CONTRACT(BYTE*) { - RETURN GetFile()->GetPersistentNativeImage()->GetNativeMDImport(loadAllowed); + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + POSTCONDITION(CheckPointer(RETVAL)); } + CONTRACT_END; + + RETURN(BYTE*) GetNativeOrReadyToRunImage()->GetRvaData(rva); } +#endif // DACCESS_COMPILE + +#ifdef FEATURE_PREJIT + +#ifndef DACCESS_COMPILE /*static*/ void Module::RestoreMethodTablePointerRaw(MethodTable ** ppMT, @@ -10543,63 +10551,6 @@ ZapHeader.ImportTable | | | non-NULL //----------------------------------------------------------------------------- -BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixupCell) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(fixupCell)); - } - CONTRACTL_END; - - // Ensure that the compiler won't fetch the value twice - SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell); - - if (pSection->Signatures != NULL) - { - if (fixup == NULL) - { - PTR_DWORD pSignatures = dac_cast(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures)); - - if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell)) - return FALSE; - - _ASSERTE(*fixupCell != NULL); - } - } - else - { - if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection)) - { - // Fixup has not been fixed up yet - if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell)) - return FALSE; - - _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection)); - } - else - { - // - // Handle tables are special. We may need to restore static handle or previous - // attempts to load handle could have been partial. - // - if (pSection->Type == CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE) - { - TypeHandle::FromPtr((void *)fixup).CheckRestore(); - } - else - if (pSection->Type == CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE) - { - ((MethodDesc *)(fixup))->CheckRestore(); - } - } - } - - return TRUE; -} - -//----------------------------------------------------------------------------- - void Module::RunEagerFixups() { STANDARD_VM_CONTRACT; @@ -10816,9 +10767,64 @@ PTR_BYTE Module::GetNativeDebugInfo(MethodDesc * pMD) } #endif //FEATURE_PREJIT +#ifndef DACCESS_COMPILE +//----------------------------------------------------------------------------- -#ifndef DACCESS_COMPILE +BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell) +{ + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(CheckPointer(fixupCell)); + } + CONTRACTL_END; + + // Ensure that the compiler won't fetch the value twice + SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell); + + if (pSection->Signatures != NULL) + { + if (fixup == NULL) + { + PTR_DWORD pSignatures = dac_cast(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures)); + + if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell)) + return FALSE; + + _ASSERTE(*fixupCell != NULL); + } + } + else + { + if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection)) + { + // Fixup has not been fixed up yet + if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell)) + return FALSE; + + _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection)); + } + else + { + // + // Handle tables are special. We may need to restore static handle or previous + // attempts to load handle could have been partial. + // + if (pSection->Type == CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE) + { + TypeHandle::FromPtr((void*)fixup).CheckRestore(); + } + else + if (pSection->Type == CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE) + { + ((MethodDesc*)(fixup))->CheckRestore(); + } + } + } + + return TRUE; +} #ifdef FEATURE_PREJIT // @@ -13850,7 +13856,9 @@ void Module::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, { m_pBinder->EnumMemoryRegions(flags); } +#ifdef FEATURE_PREJIT m_ModuleCtorInfo.EnumMemoryRegions(flags); +#endif // Save the LookupMap structures. m_MethodDefToDescMap.ListEnumMemoryRegions(flags); diff --git a/src/vm/ceeload.h b/src/vm/ceeload.h index 01d5ba880ab1..99c1c7840f2c 100644 --- a/src/vm/ceeload.h +++ b/src/vm/ceeload.h @@ -33,10 +33,11 @@ #include "ilstubcache.h" #include "classhash.h" -#ifdef FEATURE_PREJIT #include "corcompile.h" -#include "dataimage.h" #include + +#ifdef FEATURE_PREJIT +#include "dataimage.h" #endif // FEATURE_PREJIT #ifdef FEATURE_COMINTEROP @@ -75,15 +76,16 @@ class AppDomain; class DynamicMethodTable; class CodeVersionManager; class TieredCompilationManager; +class ProfileEmitter; #ifdef FEATURE_PREJIT -class CerNgenRootTable; -struct MethodContextElement; class TypeHandleList; -class ProfileEmitter; class TrackingMap; struct MethodInModule; class PersistentInlineTrackingMapNGen; +extern VerboseLevel g_CorCompileVerboseLevel; +#endif + // Hash table parameter of available classes (name -> module/class) hash #define AVAILABLE_CLASSES_HASH_BUCKETS 1024 #define AVAILABLE_CLASSES_HASH_BUCKETS_COLLECTIBLE 128 @@ -107,9 +109,6 @@ class PersistentInlineTrackingMapNGen; typedef DPTR(PersistentInlineTrackingMapNGen) PTR_PersistentInlineTrackingMapNGen; -extern VerboseLevel g_CorCompileVerboseLevel; -#endif // FEATURE_PREJIT - // // LookupMaps are used to implement RID maps // It is a linked list of nodes, each handling a successive (and consecutive) @@ -1342,7 +1341,7 @@ class Module // Note that none of these flags survive a prejit save/restore. MODULE_IS_TENURED = 0x00000001, // Set once we know for sure the Module will not be freed until the appdomain itself exits - M_CER_ROOT_TABLE_ON_HEAP = 0x00000002, // Set when m_pCerNgenRootTable is allocated from heap (at ngen time) + // unused = 0x00000002, CLASSES_FREED = 0x00000004, IS_EDIT_AND_CONTINUE = 0x00000008, // is EnC Enabled for this module @@ -1615,11 +1614,7 @@ class Module PTR_ReadyToRunInfo m_pReadyToRunInfo; #endif -#ifdef FEATURE_PREJIT - private: - PTR_NGenLayoutInfo m_pNGenLayoutInfo; - PTR_ProfilingBlobTable m_pProfilingBlobTable; // While performing IBC instrumenting this hashtable is populated with the External defs CorProfileData * m_pProfileData; // While ngen-ing with IBC optimizations this contains a link to the IBC data for the assembly @@ -1632,6 +1627,9 @@ class Module DWORD m_dwExportedTypeCount; #endif // PROFILING_SUPPORTED_DATA +#ifdef FEATURE_PREJIT + PTR_NGenLayoutInfo m_pNGenLayoutInfo; + #if defined(FEATURE_COMINTEROP) public: @@ -1648,12 +1646,11 @@ class Module #endif // defined(FEATURE_COMINTEROP) -#endif // FEATURE_PREJIT - // Module wide static fields information ModuleCtorInfo m_ModuleCtorInfo; -#ifdef FEATURE_PREJIT +#endif // FEATURE_PREJIT + struct TokenProfileData { static TokenProfileData *CreateNoThrow(void); @@ -1681,6 +1678,7 @@ class Module } *m_tokenProfileData; +#ifdef FEATURE_PREJIT // Stats for prejit log NgenStats *m_pNgenStats; #endif // FEATURE_PREJIT @@ -2559,13 +2557,15 @@ class Module m_pDllMain = pMD; } +#ifdef FEATURE_PREJIT // This data is only valid for NGEN'd modules, and for modules we're creating at NGEN time. ModuleCtorInfo* GetZapModuleCtorInfo() { LIMITED_METHOD_DAC_CONTRACT; - + return &m_ModuleCtorInfo; } +#endif private: @@ -2734,8 +2734,9 @@ class Module PCCOR_SIGNATURE GetEncodedSig(RVA fixupRva, Module **ppDefiningModule); PCCOR_SIGNATURE GetEncodedSigIfLoaded(RVA fixupRva, Module **ppDefiningModule); +#endif - BYTE *GetNativeFixupBlobData(RVA fixup); + BYTE* GetNativeFixupBlobData(RVA fixup); IMDInternalImport *GetNativeAssemblyImport(BOOL loadAllowed = TRUE); IMDInternalImport *GetNativeAssemblyImportIfLoaded(); @@ -2753,10 +2754,10 @@ class Module PEDecoder * pNativeImage); void RunEagerFixups(); - IMDInternalImport *GetNativeFixupImport(); Module *GetModuleFromIndex(DWORD ix); Module *GetModuleFromIndexIfLoaded(DWORD ix); +#ifdef FEATURE_PREJIT // This is to rebuild stub dispatch maps to module-local values. void UpdateStubDispatchTypeTable(DataImage *image); @@ -2863,6 +2864,7 @@ class Module return m_pNGenLayoutInfo->m_VirtualMethodThunks.IsInRange(code); } +#endif // FEATURE_PREJIT ICorJitInfo::ProfileBuffer * AllocateProfileBuffer(mdToken _token, DWORD _size, DWORD _ILSize); HANDLE OpenMethodProfileDataLogFile(GUID mvid); @@ -2882,6 +2884,7 @@ class Module void LogTokenAccess(mdToken token, SectionFormat format, ULONG flagNum); void LogTokenAccess(mdToken token, ULONG flagNum); +#ifdef FEATURE_PREJIT BOOL AreTypeSpecsTriaged() { return m_dwTransientFlags & TYPESPECS_TRIAGED; @@ -3228,7 +3231,6 @@ class Module LPCSTR *m_AssemblyRefByNameTable; // array that maps mdAssemblyRef tokens into their simple name DWORD m_AssemblyRefByNameCount; // array size -#if defined(FEATURE_PREJIT) // a.dll calls a method in b.dll and that method call a method in c.dll. When ngening // a.dll it is possible then method in b.dll can be inlined. When that happens a.ni.dll stores // an added native metadata which has information about assemblyRef to c.dll @@ -3238,10 +3240,9 @@ class Module // is not called for each fixup PTR_Assembly *m_NativeMetadataAssemblyRefMap; -#endif // defined(FEATURE_PREJIT) public: -#if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT) +#if !defined(DACCESS_COMPILE) PTR_Assembly GetNativeMetadataAssemblyRefFromCache(DWORD rid) { PTR_Assembly * NativeMetadataAssemblyRefMap = VolatileLoadWithoutBarrier(&m_NativeMetadataAssemblyRefMap); @@ -3254,7 +3255,7 @@ class Module } void SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssembly); -#endif // !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT) +#endif // !defined(DACCESS_COMPILE) }; // diff --git a/src/vm/ceeload.inl b/src/vm/ceeload.inl index 4997f574d39d..e0ce07f54c91 100644 --- a/src/vm/ceeload.inl +++ b/src/vm/ceeload.inl @@ -497,8 +497,6 @@ FORCEINLINE PTR_DomainLocalModule Module::GetDomainLocalModule(AppDomain *pDomai return pDomain->GetDomainLocalBlock()->GetModuleSlot(GetModuleIndex()); } -#ifdef FEATURE_PREJIT - #include "nibblestream.h" FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList) @@ -629,8 +627,6 @@ BOOL Module::FixupDelayListAux(TADDR pFixupList, return TRUE; } -#endif //FEATURE_PREJIT - inline PTR_LoaderAllocator Module::GetLoaderAllocator() { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index 1b85649d679f..3ca335671757 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -257,12 +257,6 @@ HRESULT g_EEStartupStatus = S_OK; // checking this flag. Volatile g_fEEStarted = FALSE; -// Flag indicating if the EE should be suspended on shutdown. -BOOL g_fSuspendOnShutdown = FALSE; - -// Flag indicating if the finalizer thread should be suspended on shutdown. -BOOL g_fSuspendFinalizerOnShutdown = FALSE; - // Flag indicating if the EE was started up by COM. extern BOOL g_fEEComActivatedStartup; @@ -654,8 +648,9 @@ void EEStartupHelper(COINITIEE fFlags) // Need to do this as early as possible. Used by creating object handle // table inside Ref_Initialization() before GC is initialized. NumaNodeInfo::InitNumaNodeInfo(); +#ifndef FEATURE_PAL CPUGroupInfo::EnsureInitialized(); - +#endif // !FEATURE_PAL // Initialize global configuration settings based on startup flags // This needs to be done before the EE has started @@ -1456,7 +1451,7 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) // Used later for a callback. CEEInfo ceeInf; - if(fIsDllUnloading) + if (fIsDllUnloading) { ETW::EnumerationLog::ProcessShutdown(); } @@ -1512,8 +1507,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) g_pDebugInterface->EarlyHelperThreadDeath(); #endif // DEBUGGING_SUPPORTED - BOOL fFinalizeOK = FALSE; - EX_TRY { ClrFlsSetThreadType(ThreadType_Shutdown); @@ -1527,20 +1520,17 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) // Indicate the EE is the shut down phase. g_fEEShutDown |= ShutDown_Start; - fFinalizeOK = TRUE; - // Terminate the BBSweep thread g_BBSweep.ShutdownBBSweepThread(); - // We perform the final GC only if the user has requested it through the GC class. - // We should never do the final GC for a process detach if (!g_fProcessDetach && !g_fFastExitProcess) { g_fEEShutDown |= ShutDown_Finalize1; - FinalizerThread::EnableFinalization(); - fFinalizeOK = FinalizerThread::FinalizerThreadWatchDog(); - } + // Wait for the finalizer thread to deliver process exit event + GCX_PREEMP(); + FinalizerThread::RaiseShutdownEvents(); + } // Ok. Let's stop the EE. if (!g_fProcessDetach) @@ -1565,21 +1555,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) // This call will convert the ThreadStoreLock into "shutdown" mode, just like the debugger lock above. g_fEEShutDown |= ShutDown_Finalize2; - if (fFinalizeOK) - { - fFinalizeOK = FinalizerThread::FinalizerThreadWatchDog(); - } - - if (!fFinalizeOK) - { - // One of the calls to FinalizerThreadWatchDog failed due to timeout, so we need to prevent - // any thread from running managed code, including the finalizer. - ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_SHUTDOWN); - g_fSuspendOnShutdown = TRUE; - g_fSuspendFinalizerOnShutdown = TRUE; - ThreadStore::TrapReturningThreads(TRUE); - ThreadSuspend::RestartEE(FALSE, TRUE); - } } #ifdef FEATURE_EVENT_TRACE @@ -1630,18 +1605,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) Interpreter::PrintPostMortemData(); #endif // FEATURE_INTERPRETER - FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE); - - if (g_fProcessDetach) - { - ThreadStore::TrapReturningThreads(TRUE); - } - - if (!g_fProcessDetach && !fFinalizeOK) - { - goto lDone; - } - #ifdef PROFILING_SUPPORTED // If profiling is enabled, then notify of shutdown first so that the // profiler can make any last calls it needs to. Do this only if we @@ -1760,13 +1723,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) Interpreter::Terminate(); #endif // FEATURE_INTERPRETER -#ifdef SHOULD_WE_CLEANUP - if (!g_fFastExitProcess) - { - GCHandleUtilities::GetGCHandleManager()->Shutdown(); - } -#endif /* SHOULD_WE_CLEANUP */ - //@TODO: find the right place for this VirtualCallStubManager::UninitStatic(); @@ -1774,13 +1730,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) PerfLog::PerfLogDone(); #endif //ENABLE_PERF_LOG - Frame::Term(); - - if (!g_fFastExitProcess) - { - SystemDomain::DetachEnd(); - } - // Unregister our vectored exception and continue handlers from the OS. // This will ensure that if any other DLL unload (after ours) has an exception, // we wont attempt to process that exception (which could lead to various @@ -1821,9 +1770,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) StressLog::Terminate(TRUE); #endif - if (g_pConfig != NULL) - g_pConfig->Cleanup(); - #ifdef LOGGING ShutdownLogging(); #endif @@ -1909,46 +1855,6 @@ BOOL IsThreadInSTA() } #endif -static LONG s_ActiveShutdownThreadCount = 0; - -// --------------------------------------------------------------------------- -// Function: EEShutDownProcForSTAThread(LPVOID lpParameter) -// -// Parameters: -// LPVOID lpParameter: unused -// -// Description: -// When EEShutDown decides that the shut down logic must occur on another thread, -// EEShutDown creates a new thread, and this function acts as the thread proc. See -// code:#STAShutDown for details. -// -DWORD WINAPI EEShutDownProcForSTAThread(LPVOID lpParameter) -{ - ClrFlsSetThreadType(ThreadType_ShutdownHelper); - - EEShutDownHelper(FALSE); - for (int i = 0; i < 10; i ++) - { - if (s_ActiveShutdownThreadCount) - { - return 0; - } - __SwitchToThread(20, CALLER_LIMITS_SPINNING); - } - - EPolicyAction action = GetEEPolicy()->GetDefaultAction(OPR_ProcessExit, NULL); - if (action < eRudeExitProcess) - { - action = eRudeExitProcess; - } - - UINT exitCode = GetLatchedExitCode(); - EEPolicy::HandleExitProcessFromEscalation(action, exitCode); - - return 0; -} - -// --------------------------------------------------------------------------- // #EEShutDown // // Function: EEShutDown(BOOL fIsDllUnloading) @@ -2026,60 +1932,14 @@ void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading) #endif } -#ifdef FEATURE_COMINTEROP - if (!fIsDllUnloading && CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_FinalizeOnShutdown) && IsThreadInSTA()) - { - // #STAShutDown - // - // During shutdown, we may need to release STA interface on the shutdown thread. - // It is possible that the shutdown thread may deadlock. During shutdown, all - // threads are blocked, except the shutdown thread and finalizer thread. If a - // lock is held by one of these suspended threads, it can deadlock the process if - // the shutdown thread tries to enter the lock. To mitigate this risk, create - // another thread (B) to do shutdown activities (i.e., EEShutDownHelper), while - // this thread (A) waits. If B deadlocks, A will time out and immediately return - // from EEShutDown. A will then eventually call the OS's ExitProcess, which will - // kill the deadlocked thread (and all other threads). - // - // Many Windows Forms-based apps will also execute the code below to shift shut - // down logic to a separate thread, even if they don't use COM objects. Reason - // being that they will typically use a main UI thread to pump all Windows - // messages (including messages that facilitate cross-thread COM calls to STA COM - // objects), and will set that thread up as an STA thread just in case there are - // such cross-thread COM calls to contend with. In fact, when you use VS's - // File.New.Project to make a new Windows Forms project, VS will mark Main() with - // [STAThread] - DWORD thread_id = 0; - if (CreateThread(NULL,0,EEShutDownProcForSTAThread,NULL,0,&thread_id)) - { - GCX_PREEMP_NO_DTOR(); - - ClrFlsSetThreadType(ThreadType_Shutdown); - WaitForEndOfShutdown(); - FastInterlockIncrement(&s_ActiveShutdownThreadCount); - ClrFlsClearThreadType(ThreadType_Shutdown); - } - } - else - // Otherwise, this thread calls EEShutDownHelper directly. First switch to - // cooperative mode if this is a managed thread -#endif if (GetThread()) { GCX_COOP(); EEShutDownHelper(fIsDllUnloading); - if (!fIsDllUnloading) - { - FastInterlockIncrement(&s_ActiveShutdownThreadCount); - } } else { EEShutDownHelper(fIsDllUnloading); - if (!fIsDllUnloading) - { - FastInterlockIncrement(&s_ActiveShutdownThreadCount); - } } } @@ -2405,11 +2265,7 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. if (g_fEEStarted) { - // GetThread() may be set to NULL for Win9x during shutdown. - Thread *pThread = GetThread(); - if (GCHeapUtilities::IsGCInProgress() && - ( (pThread && (pThread != ThreadSuspend::GetSuspensionThread() )) - || !g_fSuspendOnShutdown)) + if (GCHeapUtilities::IsGCInProgress()) { g_fEEShutDown |= ShutDown_Phase2; break; diff --git a/src/vm/class.cpp b/src/vm/class.cpp index af1073fb5109..14eb0595b450 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -1172,6 +1172,58 @@ bool MethodTable::IsHFA() } #endif // !FEATURE_HFA +//******************************************************************************* +int MethodTable::GetVectorSize() +{ + // This is supported for finding HVA types for Arm64. In order to support the altjit, + // we support this on 64-bit platforms (i.e. Arm64 and X64). +#ifdef _TARGET_64BIT_ + if (IsIntrinsicType()) + { + LPCUTF8 namespaceName; + LPCUTF8 className = GetFullyQualifiedNameInfo(&namespaceName); + int vectorSize = 0; + + if (strcmp(className, "Vector`1") == 0) + { + vectorSize = GetNumInstanceFieldBytes(); + _ASSERTE(strcmp(namespaceName, "System.Numerics") == 0); + return vectorSize; + } + if (strcmp(className, "Vector128`1") == 0) + { + vectorSize = 16; + } + else if (strcmp(className, "Vector256`1") == 0) + { + vectorSize = 32; + } + else if (strcmp(className, "Vector64`1") == 0) + { + vectorSize = 8; + } + if (vectorSize != 0) + { + // We need to verify that T (the element or "base" type) is a primitive type. + TypeHandle typeArg = GetInstantiation()[0]; + CorElementType corType = typeArg.GetSignatureCorElementType(); + bool isSupportedElementType = (corType >= ELEMENT_TYPE_I1 && corType <= ELEMENT_TYPE_R8); + // These element types are not supported for Vector64. + if ((vectorSize == 8) && (corType == ELEMENT_TYPE_I8 || corType == ELEMENT_TYPE_U8 || corType == ELEMENT_TYPE_R8)) + { + isSupportedElementType = false; + } + if (isSupportedElementType) + { + _ASSERTE(strcmp(namespaceName, "System.Runtime.Intrinsics") == 0); + return vectorSize; + } + } + } +#endif // _TARGET_64BIT_ + return 0; +} + //******************************************************************************* CorElementType MethodTable::GetHFAType() { @@ -1191,17 +1243,28 @@ CorElementType MethodTable::GetHFAType() _ASSERTE(pMT->IsValueType()); _ASSERTE(pMT->GetNumInstanceFields() > 0); + int vectorSize = pMT->GetVectorSize(); + if (vectorSize != 0) + { + return (vectorSize == 8) ? ELEMENT_TYPE_R8 : ELEMENT_TYPE_VALUETYPE; + } + PTR_FieldDesc pFirstField = pMT->GetApproxFieldDescListRaw(); CorElementType fieldType = pFirstField->GetFieldType(); - + // All HFA fields have to be of the same type, so we can just return the type of the first field switch (fieldType) { case ELEMENT_TYPE_VALUETYPE: pMT = pFirstField->LookupApproxFieldTypeHandle().GetMethodTable(); + vectorSize = pMT->GetVectorSize(); + if (vectorSize != 0) + { + return (vectorSize == 8) ? ELEMENT_TYPE_R8 : ELEMENT_TYPE_VALUETYPE; + } break; - + case ELEMENT_TYPE_R4: case ELEMENT_TYPE_R8: return fieldType; @@ -1212,7 +1275,7 @@ CorElementType MethodTable::GetHFAType() _ASSERTE(false); return ELEMENT_TYPE_END; } - } + } } bool MethodTable::IsNativeHFA() @@ -1231,6 +1294,7 @@ CorElementType MethodTable::GetNativeHFAType() // // When FEATURE_HFA is defined, we cache the value; otherwise we recompute it with each // call. The latter is only for the armaltjit and the arm64altjit. +// bool #if defined(FEATURE_HFA) EEClass::CheckForHFA(MethodTable ** pByValueClassCache) @@ -1243,25 +1307,18 @@ EEClass::CheckForHFA() // This method should be called for valuetypes only _ASSERTE(GetMethodTable()->IsValueType()); - // The SIMD Intrinsic types are meant to be handled specially and should not be treated as HFA - if (GetMethodTable()->IsIntrinsicType()) - { - LPCUTF8 namespaceName; - LPCUTF8 className = GetMethodTable()->GetFullyQualifiedNameInfo(&namespaceName); - if ((strcmp(className, "Vector256`1") == 0) || (strcmp(className, "Vector128`1") == 0) || - (strcmp(className, "Vector64`1") == 0)) - { - assert(strcmp(namespaceName, "System.Runtime.Intrinsics") == 0); - return false; - } - - if ((strcmp(className, "Vector`1") == 0) && (strcmp(namespaceName, "System.Numerics") == 0)) - { - return false; - } + // The opaque Vector types appear to have multiple fields, but need to be treated + // as an opaque type of a single vector. + if (GetMethodTable()->GetVectorSize() != 0) + { +#if defined(FEATURE_HFA) + GetMethodTable()->SetIsHFA(); +#endif + return true; } + int elemSize = 0; CorElementType hfaType = ELEMENT_TYPE_END; FieldDesc *pFieldDescList = GetFieldDescList(); @@ -1278,11 +1335,41 @@ EEClass::CheckForHFA() switch (fieldType) { case ELEMENT_TYPE_VALUETYPE: + { +#ifdef _TARGET_ARM64_ + // hfa/hva types are unique by size, except for Vector64 which we can conveniently + // treat as if it were a double for ABI purposes. However, it only qualifies as + // an HVA if all fields are the same type. This will ensure that we only + // consider it an HVA if all the fields are ELEMENT_TYPE_VALUETYPE (which have been + // determined above to be vectors) of the same size. + MethodTable* pMT; +#if defined(FEATURE_HFA) + pMT = pByValueClassCache[i]; +#else + pMT = pFD->LookupApproxFieldTypeHandle().AsMethodTable(); +#endif + int thisElemSize = pMT->GetVectorSize(); + if (thisElemSize != 0) + { + if (elemSize == 0) + { + elemSize = thisElemSize; + } + else if ((thisElemSize != elemSize) || (hfaType != ELEMENT_TYPE_VALUETYPE)) + { + return false; + } + } + else +#endif // _TARGET_ARM64_ + { #if defined(FEATURE_HFA) - fieldType = pByValueClassCache[i]->GetHFAType(); + fieldType = pByValueClassCache[i]->GetHFAType(); #else - fieldType = pFD->LookupApproxFieldTypeHandle().AsMethodTable()->GetHFAType(); + fieldType = pFD->LookupApproxFieldTypeHandle().AsMethodTable()->GetHFAType(); #endif + } + } break; case ELEMENT_TYPE_R4: @@ -1326,14 +1413,31 @@ EEClass::CheckForHFA() } } - if (hfaType == ELEMENT_TYPE_END) + switch (hfaType) + { + case ELEMENT_TYPE_R4: + elemSize = 4; + break; + case ELEMENT_TYPE_R8: + elemSize = 8; + break; +#ifdef _TARGET_ARM64_ + case ELEMENT_TYPE_VALUETYPE: + // Should already have set elemSize, but be conservative + if (elemSize == 0) + { + return false; + } + break; +#endif + default: + // ELEMENT_TYPE_END return false; + } if (!hasZeroOffsetField) // If the struct doesn't have a zero-offset field, it's not an HFA. return false; - int elemSize = (hfaType == ELEMENT_TYPE_R8) ? sizeof(double) : sizeof(float); - // Note that we check the total size, but do not perform any checks on number of fields: // - Type of fields can be HFA valuetype itself // - Managed C++ HFA valuetypes have just one of type float to signal that @@ -1348,7 +1452,7 @@ EEClass::CheckForHFA() if (totalSize / elemSize > 4) return false; - // All the above tests passed. It's HFA! + // All the above tests passed. It's HFA(/HVA)! #if defined(FEATURE_HFA) GetMethodTable()->SetIsHFA(); #endif @@ -1421,7 +1525,16 @@ CorElementType EEClassLayoutInfo::GetNativeHFATypeRaw() if (hfaType == ELEMENT_TYPE_END) return ELEMENT_TYPE_END; - int elemSize = (hfaType == ELEMENT_TYPE_R8) ? sizeof(double) : sizeof(float); + int elemSize = 1; + switch (hfaType) + { + case ELEMENT_TYPE_R4: elemSize = sizeof(float); break; + case ELEMENT_TYPE_R8: elemSize = sizeof(double); break; +#ifdef _TARGET_ARM64_ + case ELEMENT_TYPE_VALUETYPE: elemSize = 16; break; +#endif + default: _ASSERTE(!"Invalid HFA Type"); + } // Note that we check the total size, but do not perform any checks on number of fields: // - Type of fields can be HFA valuetype itself diff --git a/src/vm/class.h b/src/vm/class.h index 2853aee330e2..7faf7a090252 100644 --- a/src/vm/class.h +++ b/src/vm/class.h @@ -414,8 +414,11 @@ class EEClassLayoutInfo #endif // UNIX_AMD64_ABI #ifdef FEATURE_HFA // HFA type of the unmanaged layout + // Note that these are not flags, they are discrete values. e_R4_HFA = 0x10, e_R8_HFA = 0x20, + e_16_HFA = 0x30, + e_HFATypeFlags = 0x30, #endif }; @@ -526,15 +529,19 @@ class EEClassLayoutInfo bool IsNativeHFA() { LIMITED_METHOD_CONTRACT; - return (m_bFlags & (e_R4_HFA | e_R8_HFA)) != 0; + return (m_bFlags & e_HFATypeFlags) != 0; } CorElementType GetNativeHFAType() { LIMITED_METHOD_CONTRACT; - if (IsNativeHFA()) - return (m_bFlags & e_R4_HFA) ? ELEMENT_TYPE_R4 : ELEMENT_TYPE_R8; - return ELEMENT_TYPE_END; + switch (m_bFlags & e_HFATypeFlags) + { + case e_R4_HFA: return ELEMENT_TYPE_R4; + case e_R8_HFA: return ELEMENT_TYPE_R8; + case e_16_HFA: return ELEMENT_TYPE_VALUETYPE; + default: return ELEMENT_TYPE_END; + } } #else // !FEATURE_HFA bool IsNativeHFA() @@ -580,7 +587,15 @@ class EEClassLayoutInfo void SetNativeHFAType(CorElementType hfaType) { LIMITED_METHOD_CONTRACT; - m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA; + // We should call this at most once. + _ASSERTE((m_bFlags & e_HFATypeFlags) == 0); + switch (hfaType) + { + case ELEMENT_TYPE_R4: m_bFlags |= e_R4_HFA; break; + case ELEMENT_TYPE_R8: m_bFlags |= e_R8_HFA; break; + case ELEMENT_TYPE_VALUETYPE: m_bFlags |= e_16_HFA; break; + default: _ASSERTE(!"Invalid HFA Type"); + } } #endif #ifdef UNIX_AMD64_ABI @@ -1349,6 +1364,11 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! LIMITED_METHOD_CONTRACT; m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS; } + void SetHasOnlyAbstractMethods() + { + LIMITED_METHOD_CONTRACT; + m_VMFlags |= (DWORD) VMFLAG_ONLY_ABSTRACT_METHODS; + } #ifdef FEATURE_COMINTEROP void SetSparseForCOMInterop() { @@ -1430,6 +1450,13 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! LIMITED_METHOD_CONTRACT; return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS; } + + BOOL HasOnlyAbstractMethods() + { + LIMITED_METHOD_CONTRACT; + return m_VMFlags & VMFLAG_ONLY_ABSTRACT_METHODS; + } + #ifdef FEATURE_COMINTEROP BOOL IsSparseForCOMInterop() { @@ -1859,7 +1886,7 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! // unused = 0x00080000, VMFLAG_CONTAINS_STACK_PTR = 0x00100000, VMFLAG_PREFER_ALIGN8 = 0x00200000, // Would like to have 8-byte alignment - // unused = 0x00400000, + VMFLAG_ONLY_ABSTRACT_METHODS = 0x00400000, // Type only contains abstract methods #ifdef FEATURE_COMINTEROP VMFLAG_SPARSE_FOR_COMINTEROP = 0x00800000, diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index 4188658cca4f..00ed67a92ca4 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -1721,9 +1721,6 @@ EXTERN_C void __stdcall jitStartup(ICorJitHost* host); EXTERN_C ICorJitCompiler* __stdcall getJit(); #endif // FEATURE_MERGE_JIT_AND_ENGINE -// Set this to the result of LoadJIT as a courtesy to code:CorCompileGetRuntimeDll -extern HMODULE s_ngenCompilerDll; - BOOL EEJitManager::LoadJIT() { STANDARD_VM_CONTRACT; @@ -1767,9 +1764,6 @@ BOOL EEJitManager::LoadJIT() g_JitLoadData.jld_id = JIT_LOAD_MAIN; LoadAndInitializeJIT(ExecutionManager::GetJitName(), &m_JITCompiler, &newJitCompiler, &g_JitLoadData); - - // Set as a courtesy to code:CorCompileGetRuntimeDll - s_ngenCompilerDll = m_JITCompiler; #endif // !FEATURE_MERGE_JIT_AND_ENGINE #ifdef ALLOW_SXS_JIT @@ -5236,6 +5230,116 @@ PCODE ExecutionManager::getNextJumpStub(MethodDesc* pMD, PCODE target, } #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE +static void GetFuncletStartOffsetsHelper(PCODE pCodeStart, SIZE_T size, SIZE_T ofsAdj, + PTR_RUNTIME_FUNCTION pFunctionEntry, TADDR moduleBase, + DWORD * pnFunclets, DWORD* pStartFuncletOffsets, DWORD dwLength) +{ + _ASSERTE(FitsInU4((pCodeStart + size) - moduleBase)); + DWORD endAddress = (DWORD)((pCodeStart + size) - moduleBase); + + // Entries are sorted and terminated by sentinel value (DWORD)-1 + for (; RUNTIME_FUNCTION__BeginAddress(pFunctionEntry) < endAddress; pFunctionEntry++) + { +#ifdef _TARGET_AMD64_ + _ASSERTE((pFunctionEntry->UnwindData & RUNTIME_FUNCTION_INDIRECT) == 0); +#endif + +#if defined(EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS) + if (IsFunctionFragment(moduleBase, pFunctionEntry)) + { + // This is a fragment (not the funclet beginning); skip it + continue; + } +#endif // EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS + + if (*pnFunclets < dwLength) + { + TADDR funcletStartAddress = (moduleBase + RUNTIME_FUNCTION__BeginAddress(pFunctionEntry)) + ofsAdj; + _ASSERTE(FitsInU4(funcletStartAddress - pCodeStart)); + pStartFuncletOffsets[*pnFunclets] = (DWORD)(funcletStartAddress - pCodeStart); + } + (*pnFunclets)++; + } +} + +#if defined(WIN64EXCEPTIONS) && defined(DACCESS_COMPILE) + +// +// To locate an entry in the function entry table (the program exceptions data directory), the debugger +// performs a binary search over the table. This function reports the entries that are encountered in the +// binary search. +// +// Parameters: +// pRtf: The target function table entry to be located +// pNativeLayout: A pointer to the loaded native layout for the module containing pRtf +// +static void EnumRuntimeFunctionEntriesToFindEntry(PTR_RUNTIME_FUNCTION pRtf, PTR_PEImageLayout pNativeLayout) +{ + pRtf.EnumMem(); + + if (pNativeLayout == NULL) + { + return; + } + + IMAGE_DATA_DIRECTORY * pProgramExceptionsDirectory = pNativeLayout->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXCEPTION); + if (!pProgramExceptionsDirectory || + (pProgramExceptionsDirectory->Size == 0) || + (pProgramExceptionsDirectory->Size % sizeof(T_RUNTIME_FUNCTION) != 0)) + { + // Program exceptions directory malformatted + return; + } + + PTR_BYTE moduleBase(pNativeLayout->GetBase()); + PTR_RUNTIME_FUNCTION firstFunctionEntry(moduleBase + pProgramExceptionsDirectory->VirtualAddress); + + if (pRtf < firstFunctionEntry || + ((dac_cast(pRtf) - dac_cast(firstFunctionEntry)) % sizeof(T_RUNTIME_FUNCTION) != 0)) + { + // Program exceptions directory malformatted + return; + } + + // Review conversion of size_t to ULONG. +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4267) +#endif // defined(_MSC_VER) + + ULONG indexToLocate = pRtf - firstFunctionEntry; + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // defined(_MSC_VER) + + ULONG low = 0; // index in the function entry table of low end of search range + ULONG high = (pProgramExceptionsDirectory->Size) / sizeof(T_RUNTIME_FUNCTION) - 1; // index of high end of search range + ULONG mid = (low + high) / 2; // index of entry to be compared + + if (indexToLocate > high) + { + return; + } + + while (indexToLocate != mid) + { + PTR_RUNTIME_FUNCTION functionEntry = firstFunctionEntry + mid; + functionEntry.EnumMem(); + if (indexToLocate > mid) + { + low = mid + 1; + } + else + { + high = mid - 1; + } + mid = (low + high) / 2; + _ASSERTE(low <= mid && mid <= high); + } +} +#endif // WIN64EXCEPTIONS + #ifdef FEATURE_PREJIT //*************************************************************************************** //*************************************************************************************** @@ -5702,38 +5806,6 @@ TADDR NativeImageJitManager::GetFuncletStartAddress(EECodeInfo * pCodeInfo) return IJitManager::GetFuncletStartAddress(pCodeInfo); } -static void GetFuncletStartOffsetsHelper(PCODE pCodeStart, SIZE_T size, SIZE_T ofsAdj, - PTR_RUNTIME_FUNCTION pFunctionEntry, TADDR moduleBase, - DWORD * pnFunclets, DWORD* pStartFuncletOffsets, DWORD dwLength) -{ - _ASSERTE(FitsInU4((pCodeStart + size) - moduleBase)); - DWORD endAddress = (DWORD)((pCodeStart + size) - moduleBase); - - // Entries are sorted and terminated by sentinel value (DWORD)-1 - for ( ; RUNTIME_FUNCTION__BeginAddress(pFunctionEntry) < endAddress; pFunctionEntry++) - { -#ifdef _TARGET_AMD64_ - _ASSERTE((pFunctionEntry->UnwindData & RUNTIME_FUNCTION_INDIRECT) == 0); -#endif - -#if defined(EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS) - if (IsFunctionFragment(moduleBase, pFunctionEntry)) - { - // This is a fragment (not the funclet beginning); skip it - continue; - } -#endif // EXCEPTION_DATA_SUPPORTS_FUNCTION_FRAGMENTS - - if (*pnFunclets < dwLength) - { - TADDR funcletStartAddress = (moduleBase + RUNTIME_FUNCTION__BeginAddress(pFunctionEntry)) + ofsAdj; - _ASSERTE(FitsInU4(funcletStartAddress - pCodeStart)); - pStartFuncletOffsets[*pnFunclets] = (DWORD)(funcletStartAddress - pCodeStart); - } - (*pnFunclets)++; - } -} - DWORD NativeImageJitManager::GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength) { CONTRACTL @@ -5988,81 +6060,6 @@ void NativeImageJitManager::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) #if defined(WIN64EXCEPTIONS) -// -// To locate an entry in the function entry table (the program exceptions data directory), the debugger -// performs a binary search over the table. This function reports the entries that are encountered in the -// binary search. -// -// Parameters: -// pRtf: The target function table entry to be located -// pNativeLayout: A pointer to the loaded native layout for the module containing pRtf -// -static void EnumRuntimeFunctionEntriesToFindEntry(PTR_RUNTIME_FUNCTION pRtf, PTR_PEImageLayout pNativeLayout) -{ - pRtf.EnumMem(); - - if (pNativeLayout == NULL) - { - return; - } - - IMAGE_DATA_DIRECTORY * pProgramExceptionsDirectory = pNativeLayout->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXCEPTION); - if (!pProgramExceptionsDirectory || - (pProgramExceptionsDirectory->Size == 0) || - (pProgramExceptionsDirectory->Size % sizeof(T_RUNTIME_FUNCTION) != 0)) - { - // Program exceptions directory malformatted - return; - } - - PTR_BYTE moduleBase(pNativeLayout->GetBase()); - PTR_RUNTIME_FUNCTION firstFunctionEntry(moduleBase + pProgramExceptionsDirectory->VirtualAddress); - - if (pRtf < firstFunctionEntry || - ((dac_cast(pRtf) - dac_cast(firstFunctionEntry)) % sizeof(T_RUNTIME_FUNCTION) != 0)) - { - // Program exceptions directory malformatted - return; - } - -// Review conversion of size_t to ULONG. -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable:4267) -#endif // defined(_MSC_VER) - - ULONG indexToLocate = pRtf - firstFunctionEntry; - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif // defined(_MSC_VER) - - ULONG low = 0; // index in the function entry table of low end of search range - ULONG high = (pProgramExceptionsDirectory->Size)/sizeof(T_RUNTIME_FUNCTION) - 1; // index of high end of search range - ULONG mid = (low + high) /2; // index of entry to be compared - - if (indexToLocate > high) - { - return; - } - - while (indexToLocate != mid) - { - PTR_RUNTIME_FUNCTION functionEntry = firstFunctionEntry + mid; - functionEntry.EnumMem(); - if (indexToLocate > mid) - { - low = mid + 1; - } - else - { - high = mid - 1; - } - mid = (low + high) /2; - _ASSERTE( low <= mid && mid <= high ); - } -} - // // EnumMemoryRegionsForMethodUnwindInfo - enumerate the memory necessary to read the unwind info for the // specified method. @@ -6101,6 +6098,10 @@ void NativeImageJitManager::EnumMemoryRegionsForMethodUnwindInfo(CLRDataEnumMemo #endif //WIN64EXCEPTIONS #endif // #ifdef DACCESS_COMPILE +#endif // FEATURE_PREJIT + +#if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN) + // Return start of exception info for a method, or 0 if the method has no EH info DWORD NativeExceptionInfoLookupTable::LookupExceptionInfoRVAForMethod(PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE pExceptionLookupTable, COUNT_T numLookupEntries, @@ -6216,6 +6217,7 @@ int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(DWORD RelativePc, return -1; } +#ifdef FEATURE_PREJIT BOOL NativeUnwindInfoLookupTable::HasExceptionInfo(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction) { LIMITED_METHOD_DAC_CONTRACT; @@ -6250,9 +6252,10 @@ DWORD NativeUnwindInfoLookupTable::GetMethodDescRVA(NGenLayoutInfo * pNgenLayout return rva; } - #endif // FEATURE_PREJIT +#endif // FEATURE_PREJIT || FEATURE_READYTORUN + #ifndef DACCESS_COMPILE //----------------------------------------------------------------------------- diff --git a/src/vm/codeman.h b/src/vm/codeman.h index e08721c16f91..04e7dd162e74 100644 --- a/src/vm/codeman.h +++ b/src/vm/codeman.h @@ -1615,6 +1615,23 @@ class NativeImageJitManager : public IJitManager #endif //DACCESS_COMPILE }; +inline TADDR NativeImageJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken) +{ + CONTRACTL{ + NOTHROW; + GC_NOTRIGGER; + HOST_NOCALLS; + SUPPORTS_DAC; + } CONTRACTL_END; + + return JitTokenToModuleBase(MethodToken) + + RUNTIME_FUNCTION__BeginAddress(dac_cast(MethodToken.m_pCodeHeader)); +} + +#endif // FEATURE_PREJIT + +#if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN) + class NativeExceptionInfoLookupTable { public: @@ -1632,27 +1649,16 @@ class NativeUnwindInfoLookupTable int StartIndex, int EndIndex); +#ifdef FEATURE_PREJIT static BOOL HasExceptionInfo(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction); static PTR_MethodDesc GetMethodDesc(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction, TADDR moduleBase); private: static DWORD GetMethodDescRVA(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction); +#endif }; -inline TADDR NativeImageJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - HOST_NOCALLS; - SUPPORTS_DAC; - } CONTRACTL_END; - - return JitTokenToModuleBase(MethodToken) + - RUNTIME_FUNCTION__BeginAddress(dac_cast(MethodToken.m_pCodeHeader)); -} - -#endif // FEATURE_PREJIT +#endif // FEATURE_PREJIT || FEATURE_READYTORUN #ifdef FEATURE_READYTORUN diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp index 713d7c17b517..39cd0a14cfe3 100644 --- a/src/vm/comcallablewrapper.cpp +++ b/src/vm/comcallablewrapper.cpp @@ -159,6 +159,9 @@ void DestructComCallMethodDescs(ArrayList *pDescArray) typedef Wrapper, DestructComCallMethodDescs> ComCallMethodDescArrayHolder; +// Forward declarations +static bool GetComIPFromCCW_HandleCustomQI(ComCallWrapper *pWrap, REFIID riid, MethodTable * pIntfMT, IUnknown **ppUnkOut); + //-------------------------------------------------------------------------- // IsDuplicateClassItfMD(MethodDesc *pMD, unsigned int ix) // Determines if the specified method desc is a duplicate. @@ -918,7 +921,7 @@ void SimpleComCallWrapper::BuildRefCountLogMessage(LPCWSTR wszOperation, StackSS LPCUTF8 pszNamespace; if (SUCCEEDED(m_pMT->GetMDImport()->GetNameOfTypeDef(m_pMT->GetCl(), &pszClassName, &pszNamespace))) { - OBJECTHANDLE handle = GetMainWrapper()->GetRawObjectHandle(); + OBJECTHANDLE handle = GetMainWrapper()->GetObjectHandle(); _UNCHECKED_OBJECTREF obj = NULL; // Force retriving the handle without using OBJECTREF and under cooperative mode @@ -1277,7 +1280,7 @@ BOOL SimpleComCallWrapper::CustomQIRespondsToIMarshal() DWORD newFlags = enum_CustomQIRespondsToIMarshal_Inited; SafeComHolder pUnk; - if (ComCallWrapper::GetComIPFromCCW_HandleCustomQI(GetMainWrapper(), IID_IMarshal, NULL, &pUnk)) + if (GetComIPFromCCW_HandleCustomQI(GetMainWrapper(), IID_IMarshal, NULL, &pUnk)) { newFlags |= enum_CustomQIRespondsToIMarshal; } @@ -2016,12 +2019,27 @@ void SimpleComCallWrapper::EnumConnectionPoints(IEnumConnectionPoints **ppEnumCP // //-------------------------------------------------------------------------- - //-------------------------------------------------------------------------- -// void ComCallWrapper::MarkHandleWeak() -// mark the wrapper as holding a weak handle to the object +// Check if the wrapper has been deactivated //-------------------------------------------------------------------------- +BOOL ComCallWrapper::IsHandleWeak() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + return simpleWrap->IsHandleWeak(); +} +//-------------------------------------------------------------------------- +// Mark the wrapper as holding a weak handle to the object +//-------------------------------------------------------------------------- void ComCallWrapper::MarkHandleWeak() { CONTRACTL @@ -2032,18 +2050,51 @@ void ComCallWrapper::MarkHandleWeak() } CONTRACTL_END; - SyncBlock* pSyncBlock = GetSyncBlock(); - _ASSERTE(pSyncBlock); + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + simpleWrap->MarkHandleWeak(); +} + +//-------------------------------------------------------------------------- +// Mark the wrapper as not having a weak handle +//-------------------------------------------------------------------------- +void ComCallWrapper::ResetHandleStrength() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; - GetSimpleWrapper()->MarkHandleWeak(); + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + simpleWrap->ResetHandleStrength(); } //-------------------------------------------------------------------------- -// void ComCallWrapper::ResetHandleStrength() -// mark the wrapper as not having a weak handle +// Check if the wrapper was activated via COM //-------------------------------------------------------------------------- +BOOL ComCallWrapper::IsComActivated() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; -void ComCallWrapper::ResetHandleStrength() + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + return simpleWrap->IsComActivated(); +} + +//-------------------------------------------------------------------------- +// Mark the wrapper as being created via COM activation +//-------------------------------------------------------------------------- +VOID ComCallWrapper::MarkComActivated() { CONTRACTL { @@ -2052,11 +2103,10 @@ void ComCallWrapper::ResetHandleStrength() MODE_ANY; } CONTRACTL_END; - - SyncBlock* pSyncBlock = GetSyncBlock(); - _ASSERTE(pSyncBlock); - GetSimpleWrapper()->ResetHandleStrength(); + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + simpleWrap->MarkComActivated(); } //-------------------------------------------------------------------------- @@ -2267,6 +2317,37 @@ ComCallWrapper* ComCallWrapper::CopyFromTemplate(ComCallWrapperTemplate* pTempla RETURN pStartWrapper; } +//-------------------------------------------------------------------------- +// identify the location within the wrapper where the vtable for this index will +// be stored +//-------------------------------------------------------------------------- +SLOT** ComCallWrapper::GetComIPLocInWrapper(ComCallWrapper* pWrap, unsigned int iIndex) +{ + CONTRACT (SLOT**) + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + PRECONDITION(CheckPointer(pWrap)); + PRECONDITION(iIndex > 1); // We should never attempt to get the basic or IClassX interface here. + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + SLOT** pTearOff = NULL; + while (iIndex >= NumVtablePtrs) + { + //@todo delayed creation support + _ASSERTE(pWrap->IsLinked() != 0); + pWrap = GetNext(pWrap); + iIndex-= NumVtablePtrs; + } + _ASSERTE(pWrap != NULL); + pTearOff = (SLOT **)&pWrap->m_rgpIPtr[iIndex]; + + RETURN pTearOff; +} + //-------------------------------------------------------------------------- // void ComCallWrapper::Cleanup(ComCallWrapper* pWrap) // clean up , release gc registered reference and free wrapper @@ -2424,7 +2505,6 @@ void ComCallWrapper::Neuter() } } - //-------------------------------------------------------------------------- // void ComCallWrapper::ClearHandle() // clear the ref-counted handle @@ -2440,6 +2520,20 @@ void ComCallWrapper::ClearHandle() } } +SLOT** ComCallWrapper::GetFirstInterfaceSlot() +{ + CONTRACT(SLOT**) + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + SLOT** firstInterface = GetComIPLocInWrapper(this, Slot_FirstInterface); + RETURN firstInterface; +} //-------------------------------------------------------------------------- // void ComCallWrapper::FreeWrapper(ComCallWrapper* pWrap) @@ -2611,67 +2705,6 @@ ComCallWrapper* ComCallWrapper::CreateWrapper(OBJECTREF* ppObj, ComCallWrapperTe RETURN pStartWrapper; } - -//-------------------------------------------------------------------------- -// signed ComCallWrapper::GetIndexForIntfMT(ComCallWrapperTemplate *pTemplate, MethodTable *pIntfMT) -// check if the interface is supported, return a index into the IMap -// returns -1, if pIntfMT is not supported -//-------------------------------------------------------------------------- -signed ComCallWrapper::GetIndexForIntfMT(ComCallWrapperTemplate *pTemplate, MethodTable *pIntfMT) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pTemplate)); - PRECONDITION(CheckPointer(pIntfMT)); - } - CONTRACTL_END; - - for (unsigned j = 0; j < pTemplate->GetNumInterfaces(); j++) - { - ComMethodTable *pItfComMT = (ComMethodTable *)pTemplate->GetVTableSlot(j) - 1; - if (pItfComMT->GetMethodTable()->IsEquivalentTo(pIntfMT)) - return j; - } - - // oops, iface not found - return -1; -} - -//-------------------------------------------------------------------------- -// SLOT** ComCallWrapper::GetComIPLocInWrapper(ComCallWrapper* pWrap, unsigned iIndex) -// identify the location within the wrapper where the vtable for this index will -// be stored -//-------------------------------------------------------------------------- -SLOT** ComCallWrapper::GetComIPLocInWrapper(ComCallWrapper* pWrap, unsigned iIndex) -{ - CONTRACT (SLOT**) - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(CheckPointer(pWrap)); - PRECONDITION(iIndex > 1); // We should never attempt to get the basic or IClassX interface here. - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - SLOT** pTearOff = NULL; - while (iIndex >= NumVtablePtrs) - { - //@todo delayed creation support - _ASSERTE(pWrap->IsLinked() != 0); - pWrap = GetNext(pWrap); - iIndex-= NumVtablePtrs; - } - _ASSERTE(pWrap != NULL); - pTearOff = (SLOT **)&pWrap->m_rgpIPtr[iIndex]; - - RETURN pTearOff; -} - //-------------------------------------------------------------------------- // Get IClassX interface pointer from the wrapper. This method will also // lay out the IClassX COM method table if it has not yet been laid out. @@ -2839,8 +2872,7 @@ VOID __stdcall InvokeICustomQueryInterfaceGetInterface_CallBack(LPVOID ptr) } // Returns a covariant supertype of pMT with the given IID or NULL if not found. -// static -MethodTable *ComCallWrapper::FindCovariantSubtype(MethodTable *pMT, REFIID riid) +static MethodTable *FindCovariantSubtype(MethodTable *pMT, REFIID riid) { CONTRACTL { @@ -2911,21 +2943,121 @@ MethodTable *ComCallWrapper::FindCovariantSubtype(MethodTable *pMT, REFIID riid) return NULL; } -// Like GetComIPFromCCW, but will try to find riid/pIntfMT among interfaces implemented by this object that have variance. -IUnknown* ComCallWrapper::GetComIPFromCCWUsingVariance(REFIID riid, MethodTable* pIntfMT, GetComIPFromCCW::flags flags) +//-------------------------------------------------------------------------- +// check if the interface is supported, return a index into the IMap +// returns -1, if pIntfMT is not supported +//-------------------------------------------------------------------------- +static int GetIndexForIntfMT(ComCallWrapperTemplate *pTemplate, MethodTable *pIntfMT) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(CheckPointer(pTemplate)); + PRECONDITION(CheckPointer(pIntfMT)); + } + CONTRACTL_END; + + for (ULONG j = 0; j < pTemplate->GetNumInterfaces(); j++) + { + ComMethodTable *pItfComMT = (ComMethodTable *)pTemplate->GetVTableSlot(j) - 1; + if (pItfComMT->GetMethodTable()->IsEquivalentTo(pIntfMT)) + return j; + } + + return -1; +} + +static IUnknown *GetComIPFromCCW_VisibilityCheck( + IUnknown *pIntf, + MethodTable *pIntfMT, + ComMethodTable *pIntfComMT, + GetComIPFromCCW::flags flags) +{ + CONTRACT(IUnknown*) + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(CheckPointer(pIntf)); + PRECONDITION(CheckPointer(pIntfComMT)); + } + CONTRACT_END; + + if (// Do a visibility check if needed. + ((flags & GetComIPFromCCW::CheckVisibility) && (!pIntfComMT->IsComVisible()))) + { + // If not, fail to return the interface. + SafeRelease(pIntf); + RETURN NULL; + } + RETURN pIntf; +} + +static IUnknown *GetComIPFromCCW_VariantInterface( + ComCallWrapper *pWrap, + REFIID riid, + MethodTable *pIntfMT, + GetComIPFromCCW::flags flags, + ComCallWrapperTemplate *pTemplate) +{ + CONTRACT(IUnknown*) + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(CheckPointer(pWrap)); + } + CONTRACT_END; + + IUnknown* pIntf = NULL; + ComMethodTable *pIntfComMT = NULL; + + // we are only going to respond to the one interface that this CCW represents + pIntfComMT = pTemplate->GetComMTForIndex(0); + if (pIntfComMT->GetIID() == riid || (pIntfMT != NULL && GetIndexForIntfMT(pTemplate, pIntfMT) == 0)) + { + SLOT **ppVtable = pWrap->GetFirstInterfaceSlot(); + _ASSERTE(*ppVtable != NULL); // this should point to COM Vtable or interface vtable + + if (!pIntfComMT->IsLayoutComplete() && !pIntfComMT->LayOutInterfaceMethodTable(NULL)) + { + RETURN NULL; + } + + // The interface pointer is the pointer to the vtable. + pIntf = (IUnknown*)ppVtable; + + // AddRef the wrapper. + // Note that we don't do SafeAddRef(pIntf) because it's overkill to + // go via IUnknown when we already have the wrapper in-hand. + pWrap->AddRefWithAggregationCheck(); + + RETURN GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags); + } + + // for anything else, fall back to the CCW representing the "parent" class + RETURN ComCallWrapper::GetComIPFromCCW(pWrap->GetSimpleWrapper()->GetClassWrapper(), riid, pIntfMT, flags); +} + +// Like GetComIPFromCCW, but will try to find riid/pIntfMT among interfaces implemented by this +// object that have variance. Assumes that call GetComIPFromCCW with same arguments has failed. +static IUnknown* GetComIPFromCCW_UsingVariance(ComCallWrapper *pWrap, REFIID riid, MethodTable* pIntfMT, GetComIPFromCCW::flags flags) { CONTRACTL { THROWS; GC_TRIGGERS; MODE_ANY; - PRECONDITION(GetComCallWrapperTemplate()->SupportsVariantInterface()); - PRECONDITION(!GetComCallWrapperTemplate()->RepresentsVariantInterface()); + PRECONDITION(CheckPointer(pWrap)); + PRECONDITION(pWrap->GetComCallWrapperTemplate()->SupportsVariantInterface()); + PRECONDITION(!pWrap->GetComCallWrapperTemplate()->RepresentsVariantInterface()); } CONTRACTL_END; // try the fast per-ComCallWrapperTemplate cache first - ComCallWrapperTemplate::IIDToInterfaceTemplateCache *pCache = GetComCallWrapperTemplate()->GetOrCreateIIDToInterfaceTemplateCache(); + ComCallWrapperTemplate::IIDToInterfaceTemplateCache *pCache = pWrap->GetComCallWrapperTemplate()->GetOrCreateIIDToInterfaceTemplateCache(); GUID local_iid; const IID *piid = &riid; @@ -2980,7 +3112,7 @@ IUnknown* ComCallWrapper::GetComIPFromCCWUsingVariance(REFIID riid, MethodTable* // We'll perform a simplified check which is limited only to covariance with one generic parameter (luckily // all WinRT variant types currently fall into this bucket). // - TypeHandle thClass = GetComCallWrapperTemplate()->GetClassType(); + TypeHandle thClass = pWrap->GetComCallWrapperTemplate()->GetClassType(); ComCallWrapperTemplate::CCWInterfaceMapIterator it(thClass, NULL, false); while (it.Next()) @@ -3018,7 +3150,7 @@ IUnknown* ComCallWrapper::GetComIPFromCCWUsingVariance(REFIID riid, MethodTable* pVariantIntfMT = pIntfMT; } - TypeHandle thClass = GetComCallWrapperTemplate()->GetClassType(); + TypeHandle thClass = pWrap->GetComCallWrapperTemplate()->GetClassType(); if (pVariantIntfMT != NULL && thClass.CanCastTo(pVariantIntfMT)) { _ASSERTE_MSG(!thClass.GetMethodTable()->ImplementsInterface(pVariantIntfMT), "This should have been taken care of by GetComIPFromCCW"); @@ -3048,8 +3180,8 @@ IUnknown* ComCallWrapper::GetComIPFromCCWUsingVariance(REFIID riid, MethodTable* GCPROTECT_BEGIN(oref); { - oref = GetObjectRef(); - pCCW = InlineGetWrapper(&oref, pIntfTemplate, this); + oref = pWrap->GetObjectRef(); + pCCW = ComCallWrapper::InlineGetWrapper(&oref, pIntfTemplate, pWrap); } GCPROTECT_END(); } @@ -3062,77 +3194,178 @@ IUnknown* ComCallWrapper::GetComIPFromCCWUsingVariance(REFIID riid, MethodTable* return NULL; } -// static -inline IUnknown * ComCallWrapper::GetComIPFromCCW_VisibilityCheck( - IUnknown * pIntf, MethodTable * pIntfMT, ComMethodTable * pIntfComMT, - GetComIPFromCCW::flags flags) +static IUnknown * GetComIPFromCCW_HandleExtendsCOMObject( + ComCallWrapper * pWrap, + REFIID riid, + MethodTable * pIntfMT, + ComCallWrapperTemplate * pTemplate, + int imapIndex, + unsigned int intfIndex) { - CONTRACT(IUnknown*) + CONTRACTL { THROWS; GC_TRIGGERS; MODE_ANY; - PRECONDITION(CheckPointer(pIntf)); - PRECONDITION(CheckPointer(pIntfComMT)); } - CONTRACT_END; + CONTRACTL_END; - if (// Do a visibility check if needed. - ((flags & GetComIPFromCCW::CheckVisibility) && (!pIntfComMT->IsComVisible()))) + // If we don't implement the interface, we delegate to base + BOOL bDelegateToBase = TRUE; + if (imapIndex != -1) { - // If not, fail to return the interface. - SafeRelease(pIntf); - RETURN NULL; - } - RETURN pIntf; -} + MethodTable * pMT = pWrap->GetMethodTableOfObjectRef(); -// static -IUnknown * ComCallWrapper::GetComIPFromCCW_VariantInterface( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, - GetComIPFromCCW::flags flags, ComCallWrapperTemplate * pTemplate) -{ - CONTRACT(IUnknown*) - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pWrap)); - } - CONTRACT_END; + // Check if this index is actually an interface implemented by us + // if it belongs to the base COM guy then we can hand over the call + // to him + if (pMT->IsWinRTObjectType()) + { + bDelegateToBase = pTemplate->GetComMTForIndex(intfIndex)->IsWinRTTrivialAggregate(); + } + else + { + MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMapFrom(intfIndex); - IUnknown* pIntf = NULL; - ComMethodTable *pIntfComMT = NULL; + // If the number of slots is 0, then no need to proceed + if (intIt.GetInterface()->GetNumVirtuals() != 0) + { + MethodDesc *pClsMD = NULL; - // we are only going to respond to the one interface that this CCW represents - pIntfComMT = pTemplate->GetComMTForIndex(0); - if (pIntfComMT->GetIID() == riid || (pIntfMT != NULL && GetIndexForIntfMT(pTemplate, pIntfMT) == 0)) + // Find the implementation for the first slot of the interface + DispatchSlot impl(pMT->FindDispatchSlot(intIt.GetInterface()->GetTypeID(), 0, FALSE /* throwOnConflict */)); + CONSISTENCY_CHECK(!impl.IsNull()); + + // Get the MethodDesc for this slot in the class + pClsMD = impl.GetMethodDesc(); + + MethodTable * pClsMT = pClsMD->GetMethodTable(); + bDelegateToBase = (pClsMT->IsInterface() || pClsMT->IsComImport()) ? TRUE : FALSE; + } + else + { + // The interface has no methods so we cannot override it. Because of this + // it makes sense to delegate to the base COM component. + bDelegateToBase = TRUE; + } + } + } + + if (bDelegateToBase) { - SLOT **ppVtable = GetComIPLocInWrapper(pWrap, Slot_FirstInterface); - _ASSERTE(*ppVtable != NULL); // this should point to COM Vtable or interface vtable + // This is an interface of the base COM guy so delegate the call to him + SyncBlock* pBlock = pWrap->GetSyncBlock(); + _ASSERTE(pBlock); - if (!pIntfComMT->IsLayoutComplete() && !pIntfComMT->LayOutInterfaceMethodTable(NULL)) + SafeComHolder pUnk; + + RCWHolder pRCW(GetThread()); + RCWPROTECT_BEGIN(pRCW, pBlock); + + pUnk = (pIntfMT != NULL) ? pRCW->GetComIPFromRCW(pIntfMT) + : pRCW->GetComIPFromRCW(riid); + + RCWPROTECT_END(pRCW); + return pUnk.Extract(); + } + + return NULL; +} + +static IUnknown * GetComIPFromCCW_ForIID_Worker( + ComCallWrapper *pWrap, + REFIID riid, + MethodTable *pIntfMT, + GetComIPFromCCW::flags flags, + ComCallWrapperTemplate * pTemplate) +{ + CONTRACT(IUnknown*) + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(CheckPointer(pWrap)); + POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); + } + CONTRACT_END; + + ComMethodTable * pIntfComMT = NULL; + MethodTable * pMT = pWrap->GetMethodTableOfObjectRef(); + + // At this point, it must be that the IID is one of IClassX IIDs or + // it isn't implemented on this class. We'll have to search through and set + // up the entire hierarchy to determine which it is. + if (IsIClassX(pMT, riid, &pIntfComMT)) + { + // If the class that this IClassX's was generated for is marked + // as ClassInterfaceType.AutoDual or AutoDisp, or it is a WinRT + // delegate, then give out the IClassX IP. + if (pIntfComMT->GetClassInterfaceType() == clsIfAutoDual || pIntfComMT->GetClassInterfaceType() == clsIfAutoDisp || + pIntfComMT->IsWinRTDelegate()) { - RETURN NULL; - } + // Make sure the all the base classes of the class this IClassX corresponds to + // are visible to COM. + pIntfComMT->CheckParentComVisibility(FALSE); - // The interface pointer is the pointer to the vtable. - pIntf = (IUnknown*)ppVtable; + // Giveout IClassX of this class because the IID matches one of the IClassX in the hierarchy + // This assumes any IClassX implementation must be derived from base class IClassX's implementation + IUnknown * pIntf = pWrap->GetIClassXIP(); + RETURN GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags); + } + } - // AddRef the wrapper. - // Note that we don't do SafeAddRef(pIntf) because it's overkill to - // go via IUnknown when we already have the wrapper in-hand. - pWrap->AddRefWithAggregationCheck(); + RETURN NULL; +} - RETURN GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags); +static IUnknown *GetComIPFromCCW_ForIntfMT_Worker(ComCallWrapper *pWrap, MethodTable *pIntfMT, GetComIPFromCCW::flags flags) +{ + CONTRACT(IUnknown*) + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(CheckPointer(pWrap)); + POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); } + CONTRACT_END; - // for anything else, fall back to the CCW representing the "parent" class - RETURN GetComIPFromCCW(pWrap->GetSimpleWrapper()->GetClassWrapper(), riid, pIntfMT, flags); + MethodTable * pMT = pWrap->GetMethodTableOfObjectRef(); + + // class method table + if (pMT->CanCastToClass(pIntfMT)) + { + // Make sure we're not trying to pass out a generic-based class interface (except for WinRT delegates) + if (pMT->HasInstantiation() && !pMT->SupportsGenericInterop(TypeHandle::Interop_NativeToManaged)) + { + COMPlusThrow(kInvalidOperationException, IDS_EE_ATTEMPT_TO_CREATE_GENERIC_CCW); + } + + // Retrieve the COM method table for the requested interface. + ComCallWrapperTemplate *pIntfCCWTemplate = ComCallWrapperTemplate::GetTemplate(TypeHandle(pIntfMT)); + if (pIntfCCWTemplate->SupportsIClassX()) + { + ComMethodTable * pIntfComMT = pIntfCCWTemplate->GetClassComMT(); + + // If the class that this IClassX's was generated for is marked + // as ClassInterfaceType.AutoDual or AutoDisp, or it is a WinRT + // delegate, then give out the IClassX IP. + if (pIntfComMT->GetClassInterfaceType() == clsIfAutoDual || pIntfComMT->GetClassInterfaceType() == clsIfAutoDisp || + pIntfComMT->IsWinRTDelegate()) + { + // Make sure the all the base classes of the class this IClassX corresponds to + // are visible to COM. + pIntfComMT->CheckParentComVisibility(FALSE); + + // Giveout IClassX + IUnknown * pIntf = pWrap->GetIClassXIP(); + RETURN GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags); + } + } + } + RETURN NULL; } -// static -bool ComCallWrapper::GetComIPFromCCW_HandleCustomQI( +static bool GetComIPFromCCW_HandleCustomQI( ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, IUnknown ** ppUnkOut) { CONTRACTL @@ -3196,86 +3429,6 @@ MethodTable * ComCallWrapper::GetMethodTableOfObjectRef() return GetObjectRef()->GetMethodTable(); } -// static -IUnknown * ComCallWrapper::GetComIPFromCCW_HandleExtendsCOMObject( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, - ComCallWrapperTemplate * pTemplate, signed imapIndex, unsigned intfIndex) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - BOOL bDelegateToBase = FALSE; - if (imapIndex != -1) - { - MethodTable * pMT = pWrap->GetMethodTableOfObjectRef(); - - // Check if this index is actually an interface implemented by us - // if it belongs to the base COM guy then we can hand over the call - // to him - if (pMT->IsWinRTObjectType()) - { - bDelegateToBase = pTemplate->GetComMTForIndex(intfIndex)->IsWinRTTrivialAggregate(); - } - else - { - MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMapFrom(intfIndex); - - // If the number of slots is 0, then no need to proceed - if (intIt.GetInterface()->GetNumVirtuals() != 0) - { - MethodDesc *pClsMD = NULL; - - // Find the implementation for the first slot of the interface - DispatchSlot impl(pMT->FindDispatchSlot(intIt.GetInterface()->GetTypeID(), 0, FALSE /* throwOnConflict */)); - CONSISTENCY_CHECK(!impl.IsNull()); - - // Get the MethodDesc for this slot in the class - pClsMD = impl.GetMethodDesc(); - - MethodTable * pClsMT = pClsMD->GetMethodTable(); - if (pClsMT->IsInterface() || pClsMT->IsComImport()) - bDelegateToBase = TRUE; - } - else - { - // The interface has no methods so we cannot override it. Because of this - // it makes sense to delegate to the base COM component. - bDelegateToBase = TRUE; - } - } - } - else - { - // If we don't implement the interface, we delegate to base - bDelegateToBase = TRUE; - } - - if (bDelegateToBase) - { - // This is an interface of the base COM guy so delegate the call to him - SyncBlock* pBlock = pWrap->GetSyncBlock(); - _ASSERTE(pBlock); - - SafeComHolder pUnk; - - RCWHolder pRCW(GetThread()); - RCWPROTECT_BEGIN(pRCW, pBlock); - - pUnk = (pIntfMT != NULL) ? pRCW->GetComIPFromRCW(pIntfMT) - : pRCW->GetComIPFromRCW(riid); - - RCWPROTECT_END(pRCW); - return pUnk.Extract(); - } - - return NULL; -} - //-------------------------------------------------------------------------- // IUnknown* ComCallWrapper::GetComIPfromCCW(ComCallWrapper *pWrap, REFIID riid, MethodTable* pIntfMT, BOOL bCheckVisibility) // Get an interface from wrapper, based on riid or pIntfMT. The returned interface is AddRef'd. @@ -3405,7 +3558,12 @@ IUnknown* ComCallWrapper::GetComIPFromCCW(ComCallWrapper *pWrap, REFIID riid, Me { COMPlusThrow(kInvalidOperationException, IDS_EE_ATTEMPT_TO_CREATE_GENERIC_CCW); } - + + if (pIntfMT->IsInterface() && !pIntfMT->HasOnlyAbstractMethods()) + { + COMPlusThrow(kInvalidOperationException, IDS_EE_ATTEMPT_TO_CREATE_NON_ABSTRACT_CCW); + } + // The first block has one slot for the IClassX vtable pointer // and one slot for the basic vtable pointer. imapIndex += Slot_FirstInterface; @@ -3414,7 +3572,7 @@ IUnknown* ComCallWrapper::GetComIPFromCCW(ComCallWrapper *pWrap, REFIID riid, Me { // We haven't found an interface corresponding to the incoming pIntfMT/IID because we don't implement it. // However, we could still implement an interface that is castable to pIntfMT/IID via co-/contra-variance. - IUnknown * pIntf = pWrap->GetComIPFromCCWUsingVariance(riid, pIntfMT, flags); + IUnknown * pIntf = GetComIPFromCCW_UsingVariance(pWrap, riid, pIntfMT, flags); if (pIntf != NULL) { RETURN pIntf; @@ -3487,99 +3645,6 @@ IUnknown* ComCallWrapper::GetComIPFromCCW(ComCallWrapper *pWrap, REFIID riid, Me RETURN pIntf; } -// static -IUnknown * ComCallWrapper::GetComIPFromCCW_ForIID_Worker( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, GetComIPFromCCW::flags flags, - ComCallWrapperTemplate * pTemplate) -{ - CONTRACT(IUnknown*) - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pWrap)); - POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); - } - CONTRACT_END; - - ComMethodTable * pIntfComMT = NULL; - MethodTable * pMT = pWrap->GetMethodTableOfObjectRef(); - - // At this point, it must be that the IID is one of IClassX IIDs or - // it isn't implemented on this class. We'll have to search through and set - // up the entire hierarchy to determine which it is. - if (IsIClassX(pMT, riid, &pIntfComMT)) - { - // If the class that this IClassX's was generated for is marked - // as ClassInterfaceType.AutoDual or AutoDisp, or it is a WinRT - // delegate, then give out the IClassX IP. - if (pIntfComMT->GetClassInterfaceType() == clsIfAutoDual || pIntfComMT->GetClassInterfaceType() == clsIfAutoDisp || - pIntfComMT->IsWinRTDelegate()) - { - // Make sure the all the base classes of the class this IClassX corresponds to - // are visible to COM. - pIntfComMT->CheckParentComVisibility(FALSE); - - // Giveout IClassX of this class because the IID matches one of the IClassX in the hierarchy - // This assumes any IClassX implementation must be derived from base class IClassX's implementation - IUnknown * pIntf = pWrap->GetIClassXIP(); - RETURN GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags); - } - } - - RETURN NULL; -} - -// static -IUnknown * ComCallWrapper::GetComIPFromCCW_ForIntfMT_Worker( - ComCallWrapper * pWrap, MethodTable * pIntfMT, GetComIPFromCCW::flags flags) -{ - CONTRACT(IUnknown*) - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(pWrap)); - POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); - } - CONTRACT_END; - - MethodTable * pMT = pWrap->GetMethodTableOfObjectRef(); - - // class method table - if (pMT->CanCastToClass(pIntfMT)) - { - // Make sure we're not trying to pass out a generic-based class interface (except for WinRT delegates) - if (pMT->HasInstantiation() && !pMT->SupportsGenericInterop(TypeHandle::Interop_NativeToManaged)) - { - COMPlusThrow(kInvalidOperationException, IDS_EE_ATTEMPT_TO_CREATE_GENERIC_CCW); - } - - // Retrieve the COM method table for the requested interface. - ComCallWrapperTemplate *pIntfCCWTemplate = ComCallWrapperTemplate::GetTemplate(TypeHandle(pIntfMT)); - if (pIntfCCWTemplate->SupportsIClassX()) - { - ComMethodTable * pIntfComMT = pIntfCCWTemplate->GetClassComMT(); - - // If the class that this IClassX's was generated for is marked - // as ClassInterfaceType.AutoDual or AutoDisp, or it is a WinRT - // delegate, then give out the IClassX IP. - if (pIntfComMT->GetClassInterfaceType() == clsIfAutoDual || pIntfComMT->GetClassInterfaceType() == clsIfAutoDisp || - pIntfComMT->IsWinRTDelegate()) - { - // Make sure the all the base classes of the class this IClassX corresponds to - // are visible to COM. - pIntfComMT->CheckParentComVisibility(FALSE); - - // Giveout IClassX - IUnknown * pIntf = pWrap->GetIClassXIP(); - RETURN GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags); - } - } - } - RETURN NULL; -} - //-------------------------------------------------------------------------- // Get the IDispatch interface pointer for the wrapper. // The returned interface is AddRef'd. diff --git a/src/vm/comcallablewrapper.h b/src/vm/comcallablewrapper.h index 8ec126fbfc2a..104d7ec6fa2d 100644 --- a/src/vm/comcallablewrapper.h +++ b/src/vm/comcallablewrapper.h @@ -978,48 +978,38 @@ class ComCallWrapper { friend class MarshalNative; friend class ClrDataAccess; - + private: enum { -#ifdef _WIN64 NumVtablePtrs = 5, - enum_ThisMask = ~0x3f, // mask on IUnknown ** to get at the OBJECT-REF handle +#ifdef _WIN64 + enum_ThisMask = ~0x3f, // mask on IUnknown ** to get at the OBJECT-REF handle #else - - NumVtablePtrs = 5, enum_ThisMask = ~0x1f, // mask on IUnknown ** to get at the OBJECT-REF handle #endif - Slot_IClassX = 1, - Slot_Basic = 0, - + Slot_Basic = 0, + Slot_IClassX = 1, Slot_FirstInterface = 2, }; - + public: - VOID ResetHandleStrength(); + BOOL IsHandleWeak(); VOID MarkHandleWeak(); + VOID ResetHandleStrength(); - BOOL IsHandleWeak(); + BOOL IsComActivated(); + VOID MarkComActivated(); - OBJECTHANDLE GetObjectHandle(); - OBJECTHANDLE GetRawObjectHandle() { LIMITED_METHOD_CONTRACT; return m_ppThis; } // no NULL check + OBJECTHANDLE GetObjectHandle() { LIMITED_METHOD_CONTRACT; return m_ppThis; } -protected: // don't instantiate this class directly - ComCallWrapper() - { - LIMITED_METHOD_CONTRACT; - } - ~ComCallWrapper() - { - LIMITED_METHOD_CONTRACT; - } - - void Init(); + ComCallWrapper() = delete; + ~ComCallWrapper() = delete; +protected: #ifndef DACCESS_COMPILE - inline static void SetNext(ComCallWrapper* pWrap, ComCallWrapper* pNextWrapper) + static void SetNext(ComCallWrapper* pWrap, ComCallWrapper* pNextWrapper) { CONTRACTL { @@ -1035,7 +1025,7 @@ class ComCallWrapper } #endif // !DACCESS_COMPILE - inline static PTR_ComCallWrapper GetNext(PTR_ComCallWrapper pWrap) + static PTR_ComCallWrapper GetNext(PTR_ComCallWrapper pWrap) { CONTRACT (PTR_ComCallWrapper) { @@ -1047,20 +1037,13 @@ class ComCallWrapper POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); } CONTRACT_END; - + RETURN (LinkedWrapperTerminator == pWrap->m_pNext ? NULL : pWrap->m_pNext); } // Helper to create a wrapper, pClassCCW must be specified if pTemplate->RepresentsVariantInterface() static ComCallWrapper* CreateWrapper(OBJECTREF* pObj, ComCallWrapperTemplate *pTemplate, ComCallWrapper *pClassCCW); - // helper to get the IUnknown* within a wrapper - static SLOT** GetComIPLocInWrapper(ComCallWrapper* pWrap, unsigned iIndex); - - // helper to get index within the interface map for an interface that matches - // the interface MT - static signed GetIndexForIntfMT(ComCallWrapperTemplate *pTemplate, MethodTable *pIntfMT); - // helper to get wrapper from sync block static PTR_ComCallWrapper GetStartWrapper(PTR_ComCallWrapper pWrap); @@ -1069,36 +1052,10 @@ class ComCallWrapper ComCallWrapperCache *pWrapperCache, OBJECTHANDLE oh); - // helper to find a covariant supertype of pMT with the given IID - static MethodTable *FindCovariantSubtype(MethodTable *pMT, REFIID riid); - - // Like GetComIPFromCCW, but will try to find riid/pIntfMT among interfaces implemented by this - // object that have variance. Assumes that call GetComIPFromCCW with same arguments has failed. - IUnknown *GetComIPFromCCWUsingVariance(REFIID riid, MethodTable *pIntfMT, GetComIPFromCCW::flags flags); - - static IUnknown * GetComIPFromCCW_VariantInterface( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, GetComIPFromCCW::flags flags, - ComCallWrapperTemplate * pTemplate); - - inline static IUnknown * GetComIPFromCCW_VisibilityCheck( - IUnknown * pIntf, MethodTable * pIntfMT, ComMethodTable * pIntfComMT, - GetComIPFromCCW::flags flags); - - static IUnknown * GetComIPFromCCW_HandleExtendsCOMObject( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, - ComCallWrapperTemplate * pTemplate, signed imapIndex, unsigned intfIndex); - - static IUnknown * GetComIPFromCCW_ForIID_Worker( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, GetComIPFromCCW::flags flags, - ComCallWrapperTemplate * pTemplate); - - static IUnknown * GetComIPFromCCW_ForIntfMT_Worker( - ComCallWrapper * pWrap, MethodTable * pIntfMT, GetComIPFromCCW::flags flags); - + static SLOT** GetComIPLocInWrapper(ComCallWrapper* pWrap, unsigned int iIndex); public: - static bool GetComIPFromCCW_HandleCustomQI( - ComCallWrapper * pWrap, REFIID riid, MethodTable * pIntfMT, IUnknown ** ppUnkOut); + SLOT** GetFirstInterfaceSlot(); // walk the list and free all blocks void FreeWrapper(ComCallWrapperCache *pWrapperCache); @@ -1120,7 +1077,6 @@ class ComCallWrapper return m_pNext != NULL; } - // wrapper is not guaranteed to be present // accessor to wrapper object in the sync block inline static PTR_ComCallWrapper GetWrapperForObject(OBJECTREF pObj, ComCallWrapperTemplate *pTemplate = NULL) @@ -1438,7 +1394,7 @@ struct SimpleComCallWrapper enum_IsAggregated = 0x1, enum_IsExtendsCom = 0x2, enum_IsHandleWeak = 0x4, - // unused = 0x8, + enum_IsComActivated = 0x8, // unused = 0x10, enum_IsPegged = 0x80, // unused = 0x100, @@ -1622,6 +1578,18 @@ public : return m_flags & enum_IsExtendsCom; } + BOOL IsComActivated() + { + LIMITED_METHOD_CONTRACT; + return m_flags & enum_IsComActivated; + } + + void MarkComActivated() + { + LIMITED_METHOD_CONTRACT; + FastInterlockOr((ULONG*)&m_flags, enum_IsComActivated); + } + inline BOOL IsPegged() { LIMITED_METHOD_DAC_CONTRACT; @@ -2060,20 +2028,6 @@ public : LONGLONG m_llRefCount; }; -inline OBJECTHANDLE ComCallWrapper::GetObjectHandle() -{ - CONTRACT (OBJECTHANDLE) - { - WRAPPER(THROWS); - WRAPPER(GC_TRIGGERS); - MODE_COOPERATIVE; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - RETURN m_ppThis; -} - //-------------------------------------------------------------------------------- // ComCallWrapper* ComCallWrapper::InlineGetWrapper(OBJECTREF* ppObj, ComCallWrapperTemplate *pTemplate) // returns the wrapper for the object, if not yet created, creates one @@ -2275,8 +2229,6 @@ inline ULONG ComCallWrapper::GetJupiterRefCount() return m_pSimpleWrapper->GetJupiterRefCount(); } - - inline PTR_ComCallWrapper ComCallWrapper::GetWrapperFromIP(PTR_IUnknown pUnk) { CONTRACT (PTR_ComCallWrapper) @@ -2340,27 +2292,6 @@ inline PTR_ComCallWrapperTemplate ComCallWrapper::GetComCallWrapperTemplate() return GetSimpleWrapper()->GetComCallWrapperTemplate(); } -//-------------------------------------------------------------------------- -// BOOL ComCallWrapper::BOOL IsHandleWeak() -// check if the wrapper has been deactivated -// Moved here to make DAC build happy and hopefully get it inlined -//-------------------------------------------------------------------------- -inline BOOL ComCallWrapper::IsHandleWeak() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - SimpleComCallWrapper* pSimpleWrap = GetSimpleWrapper(); - _ASSERTE(pSimpleWrap); - - return pSimpleWrap->IsHandleWeak(); -} - inline BOOL ComCallWrapper::IsWrapperActive() { CONTRACTL @@ -2384,12 +2315,12 @@ inline BOOL ComCallWrapper::IsWrapperActive() BOOL bHasStrongCOMRefCount = ((cbRef > 0) || bHasJupiterStrongRefCount); - BOOL bIsWrapperActive = (bHasStrongCOMRefCount && !IsHandleWeak()); + BOOL bIsWrapperActive = (bHasStrongCOMRefCount && !m_pSimpleWrapper->IsHandleWeak()); LOG((LF_INTEROP, LL_INFO1000, "CCW 0x%p: cbRef = 0x%x, cbJupiterRef = 0x%x, IsPegged = %d, GlobalPegging = %d, IsHandleWeak = %d\n", this, - cbRef, cbJupiterRef, IsPegged(), RCWWalker::IsGlobalPeggingOn(), IsHandleWeak())); + cbRef, cbJupiterRef, m_pSimpleWrapper->IsPegged(), RCWWalker::IsGlobalPeggingOn(), m_pSimpleWrapper->IsHandleWeak())); LOG((LF_INTEROP, LL_INFO1000, "CCW 0x%p: IsWrapperActive returned %d\n", this, bIsWrapperActive)); return bIsWrapperActive; diff --git a/src/vm/common.h b/src/vm/common.h index 61ba2a7514f3..6fd5a37ad584 100644 --- a/src/vm/common.h +++ b/src/vm/common.h @@ -114,11 +114,11 @@ typedef VPTR(class LoaderAllocator) PTR_LoaderAllocator; typedef VPTR(class AppDomain) PTR_AppDomain; -typedef VPTR(class AppDomainBaseObject) PTR_AppDomainBaseObject; typedef DPTR(class ArrayBase) PTR_ArrayBase; typedef DPTR(class ArrayTypeDesc) PTR_ArrayTypeDesc; typedef DPTR(class Assembly) PTR_Assembly; typedef DPTR(class AssemblyBaseObject) PTR_AssemblyBaseObject; +typedef DPTR(class AssemblyLoadContextBaseObject) PTR_AssemblyLoadContextBaseObject; typedef DPTR(class AssemblyNameBaseObject) PTR_AssemblyNameBaseObject; typedef VPTR(class BaseDomain) PTR_BaseDomain; typedef DPTR(class ClassLoader) PTR_ClassLoader; diff --git a/src/vm/coreassemblyspec.cpp b/src/vm/coreassemblyspec.cpp index 44da97220ee2..387c25b1e202 100644 --- a/src/vm/coreassemblyspec.cpp +++ b/src/vm/coreassemblyspec.cpp @@ -301,11 +301,13 @@ STDAPI BinderAcquireImport(PEImage *pPEImage, if (!pLayout->CheckFormat()) IfFailGo(COR_E_BADIMAGEFORMAT); +#ifdef FEATURE_PREJIT if (bNativeImage && pPEImage->IsNativeILILOnly()) { pPEImage->GetNativeILPEKindAndMachine(&pdwPAFlags[0], &pdwPAFlags[1]); } else +#endif { pPEImage->GetPEKindAndMachine(&pdwPAFlags[0], &pdwPAFlags[1]); } diff --git a/src/vm/coreclr/corebindresult.h b/src/vm/coreclr/corebindresult.h index 12e6d459a8af..cd63d5070165 100644 --- a/src/vm/coreclr/corebindresult.h +++ b/src/vm/coreclr/corebindresult.h @@ -48,6 +48,9 @@ struct CoreBindResult : public IUnknown PEImage* GetNativeImage(); void SetNativeImage(PEImage * pNativeImage); PEImage* GetILImage(); +#else + BOOL HasNativeImage() { return FALSE; } + PEImage* GetNativeImage() { return NULL; } #endif void SetHRBindResult(HRESULT hrBindResult); HRESULT GetHRBindResult(); diff --git a/src/vm/diagnosticserver.cpp b/src/vm/diagnosticserver.cpp index 81cdc25d5b98..4ce013139772 100644 --- a/src/vm/diagnosticserver.cpp +++ b/src/vm/diagnosticserver.cpp @@ -57,20 +57,17 @@ static DWORD WINAPI DiagnosticsServerThread(LPVOID lpThreadParameter) switch (header.RequestType) { - case DiagnosticMessageType::EnableEventPipe: - EventPipeProtocolHelper::EnableFileTracingEventHandler(pStream); + case DiagnosticMessageType::StopEventPipeTracing: + EventPipeProtocolHelper::StopTracing(pStream); break; - case DiagnosticMessageType::DisableEventPipe: - EventPipeProtocolHelper::DisableFileTracingEventHandler(pStream); - break; - - case DiagnosticMessageType::StreamEventPipe: - EventPipeProtocolHelper::AttachTracingEventHandler(pStream); + case DiagnosticMessageType::CollectEventPipeTracing: + EventPipeProtocolHelper::CollectTracing(pStream); break; default: - LOG((LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknow request type (%d)\n", header.RequestType)); + STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknown request type (%d)\n", header.RequestType); + delete pStream; break; } } diff --git a/src/vm/diagnosticserver.h b/src/vm/diagnosticserver.h index 76ad3eff2304..c3c2ca477dcf 100644 --- a/src/vm/diagnosticserver.h +++ b/src/vm/diagnosticserver.h @@ -18,11 +18,9 @@ enum class DiagnosticMessageType : uint32_t /////////////////////////////////////////////////////////////////////////// // EventPipe - EnableEventPipe = 1024, - DisableEventPipe, - StreamEventPipe, - AttachEventPipe, - DetachEventPipe, + StartEventPipeTracing = 1024, // To file + StopEventPipeTracing, + CollectEventPipeTracing, // To IPC /////////////////////////////////////////////////////////////////////////// // Profiler = 2048 diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp index 93d0f79ca098..c9a11f3a7d39 100644 --- a/src/vm/dllimport.cpp +++ b/src/vm/dllimport.cpp @@ -5508,12 +5508,16 @@ MethodDesc* GetStubMethodDescFromInteropMethodDesc(MethodDesc* pMD, DWORD dwStub #ifdef FEATURE_COMINTEROP if (SF_IsReverseCOMStub(dwStubFlags)) { +#ifdef FEATURE_PREJIT if (fGcMdaEnabled) return NULL; // reverse COM stubs live in a hash table StubMethodHashTable *pHash = pMD->GetLoaderModule()->GetStubMethodHashTable(); return (pHash == NULL ? NULL : pHash->FindMethodDesc(pMD)); +#else + return NULL; +#endif } else #endif // FEATURE_COMINTEROP @@ -6108,7 +6112,7 @@ class LoadLibErrorTracker // Load the library directly. On Unix systems, don't register it yet with PAL. // * External callers like AssemblyNative::InternalLoadUnmanagedDllFromPath() and the upcoming -// System.Runtime.Interop.Marshall.LoadLibrary() need the raw system handle +// System.Runtime.InteropServices.NativeLibrary.Load() need the raw system handle // * Internal callers like LoadLibraryModule() can convert this handle to a HMODULE via PAL APIs on Unix static NATIVE_LIBRARY_HANDLE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTracker *pErrorTracker ) { diff --git a/src/vm/domainfile.cpp b/src/vm/domainfile.cpp index 5c89767d1a9f..0864ff1acd97 100644 --- a/src/vm/domainfile.cpp +++ b/src/vm/domainfile.cpp @@ -851,8 +851,7 @@ void DomainFile::CheckZapRequired() GetFile()->FlushExternalLog(); StackSString ss; - ss.Printf("ZapRequire: Could not get native image for %s.\n" - "Use FusLogVw.exe to check the reason.", + ss.Printf("ZapRequire: Could not get native image for %s.\n", GetSimpleName()); #if defined(_DEBUG) diff --git a/src/vm/dwbucketmanager.hpp b/src/vm/dwbucketmanager.hpp index 0095eb6a1c6c..9b0d7b12e16c 100644 --- a/src/vm/dwbucketmanager.hpp +++ b/src/vm/dwbucketmanager.hpp @@ -982,6 +982,7 @@ bool BaseBucketParamsManager::GetFileVersionInfoForModule(Module* pModule, USHOR PEFile* pFile = pModule->GetFile(); if (pFile) { +#ifdef FEATURE_PREJIT // if we have a native imaged loaded for this module then get the version information from that. if (pFile->IsNativeLoaded()) { @@ -996,6 +997,7 @@ bool BaseBucketParamsManager::GetFileVersionInfoForModule(Module* pModule, USHOR } } } +#endif // if we failed to get the version info from the native image then fall back to the IL image. if (!succeeded) diff --git a/src/vm/dynamicmethod.cpp b/src/vm/dynamicmethod.cpp index 5b9a6fac0368..611a9852d6f4 100644 --- a/src/vm/dynamicmethod.cpp +++ b/src/vm/dynamicmethod.cpp @@ -1109,7 +1109,7 @@ BYTE* LCGMethodResolver::GetCodeInfo(unsigned *pCodeSize, unsigned *pStackSize, }; U1ARRAYREF dataArray = (U1ARRAYREF) getCodeInfo.Call_RetOBJECTREF(args); DWORD codeSize = dataArray->GetNumComponents(); - NewHolder code(new BYTE[codeSize]); + NewArrayHolder code(new BYTE[codeSize]); memcpy(code, dataArray->GetDataPtr(), codeSize); m_CodeSize = codeSize; _ASSERTE(FitsIn(stackSize)); @@ -1157,7 +1157,7 @@ LCGMethodResolver::GetLocalSig() }; U1ARRAYREF dataArray = (U1ARRAYREF) getLocalsSignature.Call_RetOBJECTREF(args); DWORD localSigSize = dataArray->GetNumComponents(); - NewHolder localSig(new COR_SIGNATURE[localSigSize]); + NewArrayHolder localSig(new COR_SIGNATURE[localSigSize]); memcpy((void *)localSig, dataArray->GetDataPtr(), localSigSize); m_LocalSig = SigPointer((PCCOR_SIGNATURE)localSig, localSigSize); @@ -1504,7 +1504,7 @@ void* ChunkAllocator::New(size_t size) if (size + (sizeof(void*) * 2) < CHUNK_SIZE) { // make the allocation - NewHolder newBlock(new BYTE[CHUNK_SIZE]); + NewArrayHolder newBlock(new BYTE[CHUNK_SIZE]); pNewBlock = (BYTE*)newBlock; ((size_t*)pNewBlock)[1] = CHUNK_SIZE - size - (sizeof(void*) * 2); LOG((LF_BCL, LL_INFO10, "Level1 - DM - Allocator [0x%p] - new block {0x%p}\n", this, pNewBlock)); @@ -1513,7 +1513,7 @@ void* ChunkAllocator::New(size_t size) else { // request bigger than default size this is going to be a single block - NewHolder newBlock(new BYTE[size + (sizeof(void*) * 2)]); + NewArrayHolder newBlock(new BYTE[size + (sizeof(void*) * 2)]); pNewBlock = (BYTE*)newBlock; ((size_t*)pNewBlock)[1] = 0; // no available bytes left LOG((LF_BCL, LL_INFO10, "Level1 - DM - Allocator [0x%p] - new BIG block {0x%p}\n", this, pNewBlock)); diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 7f617caca512..50071ed410b1 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -164,7 +164,6 @@ FCFuncStart(gEnvironmentFuncs) QCFuncElement("_Exit", SystemNative::Exit) FCFuncElement("set_ExitCode", SystemNative::SetExitCode) FCFuncElement("get_ExitCode", SystemNative::GetExitCode) - FCFuncElement("get_HasShutdownStarted", SystemNative::HasShutdownStarted) QCFuncElement("GetProcessorCount", SystemNative::GetProcessorCount) FCFuncElement("GetCommandLineArgsNative", SystemNative::GetCommandLineArgs) @@ -536,7 +535,7 @@ FCFuncEnd() FCFuncStart(gAssemblyNameFuncs) FCFuncElement("nInit", AssemblyNameNative::Init) - FCFuncElement("nGetPublicKeyToken", AssemblyNameNative::GetPublicKeyToken) + FCFuncElement("ComputePublicKeyToken", AssemblyNameNative::GetPublicKeyToken) FCFuncElement("nGetFileInformation", AssemblyNameNative::GetFileInformation) FCFuncEnd() diff --git a/src/vm/eeconfig.cpp b/src/vm/eeconfig.cpp index e59a85e1e5ce..9cb07fc2e860 100644 --- a/src/vm/eeconfig.cpp +++ b/src/vm/eeconfig.cpp @@ -1226,7 +1226,14 @@ HRESULT EEConfig::sync() tieredCompilation_StartupTier_CallCountingDelayMs = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_CallCountingDelayMs); - if (CPUGroupInfo::HadSingleProcessorAtStartup()) + +#ifndef FEATURE_PAL + bool hadSingleProcessorAtStartup = CPUGroupInfo::HadSingleProcessorAtStartup(); +#else // !FEATURE_PAL + bool hadSingleProcessorAtStartup = g_SystemInfo.dwNumberOfProcessors == 1; +#endif // !FEATURE_PAL + + if (hadSingleProcessorAtStartup) { DWORD delayMultiplier = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_DelaySingleProcMultiplier); diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp index a6ecda05201f..2da1c70f7091 100644 --- a/src/vm/eepolicy.cpp +++ b/src/vm/eepolicy.cpp @@ -538,61 +538,6 @@ void EEPolicy::ExitProcessViaShim(UINT exitCode) ExitProcess(exitCode); } - -//--------------------------------------------------------------------------------------- -// DisableRuntime disables this runtime, suspending all managed execution and preventing -// threads from entering the runtime. This will cause the caller to block forever as well -// unless sca is SCA_ReturnWhenShutdownComplete. -//--------------------------------------------------------------------------------------- -void DisableRuntime(ShutdownCompleteAction sca) -{ - CONTRACTL - { - DISABLED(GC_TRIGGERS); - NOTHROW; - } - CONTRACTL_END; - - FastInterlockExchange((LONG*)&g_fForbidEnterEE, TRUE); - - if (!g_fSuspendOnShutdown) - { - if (!IsGCThread()) - { - if (ThreadStore::HoldingThreadStore(GetThread())) - { - ThreadSuspend::UnlockThreadStore(); - } - ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_SHUTDOWN); - } - - if (!g_fSuspendOnShutdown) - { - ThreadStore::TrapReturningThreads(TRUE); - g_fSuspendOnShutdown = TRUE; - ClrFlsSetThreadType(ThreadType_Shutdown); - } - - // Don't restart runtime. CLR is disabled. - } - - GCX_PREEMP_NO_DTOR(); - - ClrFlsClearThreadType(ThreadType_Shutdown); - - if (g_pDebugInterface != NULL) - { - g_pDebugInterface->DisableDebugger(); - } - - if (sca == SCA_ExitProcessWhenShutdownComplete) - { - __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING); - _ASSERTE (!"Should not reach here"); - SafeExitProcess(0); - } -} - //--------------------------------------------------------------------------------------- // HandleExitProcessHelper is used to shutdown the runtime as specified by the given // action, then to exit the process. Note, however, that the process will not exit if @@ -629,9 +574,6 @@ static void HandleExitProcessHelper(EPolicyAction action, UINT exitCode, Shutdow g_fFastExitProcess = 2; SafeExitProcess(exitCode, TRUE, sca); break; - case eDisableRuntime: - DisableRuntime(sca); - break; default: _ASSERTE (!"Invalid policy"); break; @@ -686,7 +628,6 @@ void EEPolicy::PerformResourceConstraintAction(Thread *pThread, EPolicyAction ac case eExitProcess: case eFastExitProcess: case eRudeExitProcess: - case eDisableRuntime: HandleExitProcessFromEscalation(action, exitCode); break; default: @@ -1040,13 +981,6 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage } #endif // _DEBUG - // We're here logging a fatal error. If the policy is to then do anything other than - // disable the runtime (ie, if the policy is to terminate the runtime), we should give - // Watson an opportunity to capture an error report. - // Presumably, hosts that are sophisticated enough to disable the runtime are also cognizant - // of how they want to handle fatal errors in the runtime, including whether they want - // to capture Watson information (for which they are responsible). - if (GetEEPolicy()->GetActionOnFailureNoHostNotification(FAIL_FatalRuntime) != eDisableRuntime) { #ifdef DEBUGGING_SUPPORTED //Give a managed debugger a chance if this fatal error is on a managed thread. @@ -1279,10 +1213,6 @@ int NOINLINE EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR LogFatalError(exitCode, address, pszMessage, pExceptionInfo, errorSource, argExceptionString); SafeExitProcess(exitCode, TRUE); break; - case eDisableRuntime: - LogFatalError(exitCode, address, pszMessage, pExceptionInfo, errorSource, argExceptionString); - DisableRuntime(SCA_ExitProcessWhenShutdownComplete); - break; default: _ASSERTE(!"Invalid action for FAIL_FatalRuntime"); break; diff --git a/src/vm/eventpipe.cpp b/src/vm/eventpipe.cpp index 92b4793f2e74..b6ec53011074 100644 --- a/src/vm/eventpipe.cpp +++ b/src/vm/eventpipe.cpp @@ -31,14 +31,11 @@ bool EventPipe::s_tracingInitialized = false; EventPipeConfiguration *EventPipe::s_pConfig = NULL; EventPipeSession *EventPipe::s_pSession = NULL; EventPipeBufferManager *EventPipe::s_pBufferManager = NULL; -LPCWSTR EventPipe::s_pOutputPath = NULL; EventPipeFile *EventPipe::s_pFile = NULL; EventPipeEventSource *EventPipe::s_pEventSource = NULL; LPCWSTR EventPipe::s_pCommandLine = NULL; -unsigned long EventPipe::s_nextFileIndex; HANDLE EventPipe::s_fileSwitchTimerHandle = NULL; ULONGLONG EventPipe::s_lastFlushSwitchTime = 0; -uint64_t EventPipe::s_multiFileTraceLengthInSeconds = 0; #ifdef FEATURE_PAL // This function is auto-generated from /src/scripts/genEventPipe.py @@ -225,8 +222,6 @@ void EventPipe::Shutdown() delete pBufferManager; delete s_pEventSource; s_pEventSource = NULL; - delete[] s_pOutputPath; - s_pOutputPath = NULL; // On Windows, this is just a pointer to the return value from // GetCommandLineW(), so don't attempt to free it. @@ -242,116 +237,40 @@ EventPipeSessionID EventPipe::Enable( uint64_t profilerSamplingRateInNanoseconds, const EventPipeProviderConfiguration *pProviders, uint32_t numProviders, - uint64_t multiFileTraceLengthInSeconds) + EventPipeSessionType sessionType, + IpcStream *const pStream) { CONTRACTL { THROWS; GC_TRIGGERS; MODE_ANY; - PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr)); + PRECONDITION(circularBufferSizeInMB > 0); + PRECONDITION(profilerSamplingRateInNanoseconds > 0); + PRECONDITION(numProviders > 0 && pProviders != nullptr); } CONTRACTL_END; // Take the lock before enabling tracing. CrstHolder _crst(GetLock()); - s_multiFileTraceLengthInSeconds = multiFileTraceLengthInSeconds; - // Create a new session. - SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds); + SampleProfiler::SetSamplingRate(static_cast(profilerSamplingRateInNanoseconds)); EventPipeSession *pSession = s_pConfig->CreateSession( - (strOutputPath != nullptr) ? EventPipeSessionType::File : EventPipeSessionType::Streaming, + sessionType, circularBufferSizeInMB, pProviders, numProviders); - // Initialize the next file index. - s_nextFileIndex = 1; - - // Initialize the last file switch time. - s_lastFlushSwitchTime = CLRGetTickCount64(); - - // Create the event pipe file. - // A NULL output path means that we should not write the results to a file. - // This is used in the EventListener streaming case. - if (strOutputPath != NULL) - { - - // Save the output file path. - SString outputPath(strOutputPath); - SIZE_T outputPathLen = outputPath.GetCount(); - WCHAR *pOutputPath = new WCHAR[outputPathLen + 1]; - wcsncpy(pOutputPath, outputPath.GetUnicode(), outputPathLen); - pOutputPath[outputPathLen] = '\0'; - s_pOutputPath = pOutputPath; - - SString nextTraceFilePath; - GetNextFilePath(nextTraceFilePath); - - s_pFile = new EventPipeFile(new FileStreamWriter(nextTraceFilePath)); - } - - const DWORD FileSwitchTimerPeriodMS = 1000; - return Enable(pSession, SwitchToNextFileTimerCallback, FileSwitchTimerPeriodMS, FileSwitchTimerPeriodMS); -} - -EventPipeSessionID EventPipe::Enable( - IpcStream *pStream, - uint32_t circularBufferSizeInMB, - uint64_t profilerSamplingRateInNanoseconds, - const EventPipeProviderConfiguration *pProviders, - uint32_t numProviders) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(pStream != nullptr); - PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr)); - } - CONTRACTL_END; - - if (numProviders == 0 || pProviders == nullptr) - return (EventPipeSessionID) nullptr; - - // Take the lock before enabling tracing. - CrstHolder _crst(GetLock()); - - // Create a new session. - SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds); - EventPipeSession *pSession = s_pConfig->CreateSession( - EventPipeSessionType::IpcStream, - circularBufferSizeInMB, - pProviders, - numProviders); - - // Reply back to client with the SessionId - uint32_t nBytesWritten = 0; - EventPipeSessionID sessionId = (EventPipeSessionID) pSession; - bool fSuccess = pStream->Write(&sessionId, sizeof(sessionId), nBytesWritten); - if (!fSuccess) - { - // TODO: Add error handling. - s_pConfig->DeleteSession(pSession); - - delete pStream; - return (EventPipeSessionID) nullptr; - } - - s_pFile = new EventPipeFile(new IpcStreamWriter(pStream)); - - // Enable the session. - const DWORD FlushTimerPeriodMS = 100; // TODO: Define a good number here for streaming. - return Enable(pSession, FlushTimer, FlushTimerPeriodMS, FlushTimerPeriodMS); + EventPipeSessionID sessionId = Enable(strOutputPath, pSession, sessionType, pStream); + return sessionId; } EventPipeSessionID EventPipe::Enable( + LPCWSTR strOutputPath, EventPipeSession *const pSession, - WAITORTIMERCALLBACK callback, - DWORD dueTime, - DWORD period) + EventPipeSessionType sessionType, + IpcStream *const pStream) { CONTRACTL { @@ -359,19 +278,20 @@ EventPipeSessionID EventPipe::Enable( GC_TRIGGERS; MODE_ANY; PRECONDITION(pSession != nullptr); - PRECONDITION(callback != nullptr); - PRECONDITION(dueTime > 0); - PRECONDITION(period > 0); PRECONDITION(GetLock()->OwnedByCurrentThread()); } CONTRACTL_END; - // If tracing is not initialized or is already enabled, bail here. - if (!s_tracingInitialized || s_pConfig == nullptr || s_pConfig->Enabled()) + // If the state or arguments are invalid, bail here. + if (pSession == nullptr || !pSession->IsValid()) + return 0; + if (sessionType == EventPipeSessionType::File && strOutputPath == nullptr) + return 0; + if (sessionType == EventPipeSessionType::IpcStream && pStream == nullptr) return 0; - // If the state or arguments are invalid, bail here. - if (pSession == NULL || !pSession->IsValid()) + // If tracing is not initialized or is already enabled, bail here. + if (!s_tracingInitialized || s_pConfig == nullptr || s_pConfig->Enabled()) return 0; // Enable the EventPipe EventSource. @@ -379,6 +299,27 @@ EventPipeSessionID EventPipe::Enable( // Save the session. s_pSession = pSession; + EventPipeSessionID sessionId = reinterpret_cast(s_pSession); + + // Create the event pipe file. + // A NULL output path means that we should not write the results to a file. + // This is used in the EventListener streaming case. + switch (sessionType) + { + case EventPipeSessionType::File: + if (strOutputPath != nullptr) + s_pFile = new EventPipeFile(new FileStreamWriter(SString(strOutputPath))); + break; + + case EventPipeSessionType::IpcStream: + s_pFile = new EventPipeFile(new IpcStreamWriter(sessionId, pStream)); + CreateFlushTimerCallback(); + break; + + default: + s_pFile = nullptr; + break; + } // Enable tracing. s_pConfig->Enable(s_pSession); @@ -386,10 +327,8 @@ EventPipeSessionID EventPipe::Enable( // Enable the sample profiler SampleProfiler::Enable(); - CreateFlushTimerCallback(callback, dueTime, period); - // Return the session ID. - return (EventPipeSessionID)s_pSession; + return sessionId; } void EventPipe::Disable(EventPipeSessionID id) @@ -412,6 +351,19 @@ void EventPipe::Disable(EventPipeSessionID id) // Take the lock before disabling tracing. CrstHolder _crst(GetLock()); + DisableInternal(reinterpret_cast(s_pSession)); +} + +void EventPipe::DisableInternal(EventPipeSessionID id) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(GetLock()->OwnedByCurrentThread()); + } + CONTRACTL_END; if (s_pConfig != NULL && s_pConfig->Enabled()) { @@ -427,8 +379,6 @@ void EventPipe::Disable(EventPipeSessionID id) // Disable tracing. s_pConfig->Disable(s_pSession); - s_multiFileTraceLengthInSeconds = 0; - // Delete the session. s_pConfig->DeleteSession(s_pSession); s_pSession = NULL; @@ -487,16 +437,13 @@ void EventPipe::Disable(EventPipeSessionID id) } } -void EventPipe::CreateFlushTimerCallback(WAITORTIMERCALLBACK callback, DWORD dueTime, DWORD period) +void EventPipe::CreateFlushTimerCallback() { CONTRACTL { THROWS; GC_TRIGGERS; MODE_ANY; - PRECONDITION(callback != nullptr); - PRECONDITION(dueTime > 0); - PRECONDITION(period > 0); PRECONDITION(GetLock()->OwnedByCurrentThread()); } CONTRACTL_END @@ -510,16 +457,19 @@ void EventPipe::CreateFlushTimerCallback(WAITORTIMERCALLBACK callback, DWORD due timerContextHolder->TimerId = 0; + // Initialize the last file switch time. + s_lastFlushSwitchTime = CLRGetTickCount64(); + bool success = false; _ASSERTE(s_fileSwitchTimerHandle == NULL); EX_TRY { if (ThreadpoolMgr::CreateTimerQueueTimer( &s_fileSwitchTimerHandle, - callback, + FlushTimer, timerContextHolder, - dueTime, - period, + 100, // DueTime (msec) + 100, // Period (msec) 0 /* flags */)) { _ASSERTE(s_fileSwitchTimerHandle != NULL); @@ -555,7 +505,7 @@ void EventPipe::DeleteFlushTimerCallback() s_fileSwitchTimerHandle = NULL; } -void WINAPI EventPipe::SwitchToNextFileTimerCallback(PVOID parameter, BOOLEAN timerFired) +void WINAPI EventPipe::FlushTimer(PVOID parameter, BOOLEAN timerFired) { CONTRACTL { @@ -566,36 +516,8 @@ void WINAPI EventPipe::SwitchToNextFileTimerCallback(PVOID parameter, BOOLEAN ti } CONTRACTL_END; - // Take the lock control lock to make sure that tracing isn't disabled during this operation. - CrstHolder _crst(GetLock()); - - if (s_pSession == nullptr || s_pFile == nullptr) - return; - - // Make sure that we should actually switch files. - if (!Enabled() || s_pSession->GetSessionType() != EventPipeSessionType::File || s_multiFileTraceLengthInSeconds == 0) - return; - GCX_PREEMP(); - if (CLRGetTickCount64() > (s_lastFlushSwitchTime + (s_multiFileTraceLengthInSeconds * 1000))) - { - SwitchToNextFile(); - s_lastFlushSwitchTime = CLRGetTickCount64(); - } -} - -void WINAPI EventPipe::FlushTimer(PVOID parameter, BOOLEAN timerFired) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(timerFired); - } - CONTRACTL_END; - // Take the lock control lock to make sure that tracing isn't disabled during this operation. CrstHolder _crst(GetLock()); @@ -606,8 +528,6 @@ void WINAPI EventPipe::FlushTimer(PVOID parameter, BOOLEAN timerFired) if (!Enabled() || s_pSession->GetSessionType() != EventPipeSessionType::IpcStream) return; - GCX_PREEMP(); - if (CLRGetTickCount64() > (s_lastFlushSwitchTime + 100)) { // Get the current time stamp. @@ -619,79 +539,15 @@ void WINAPI EventPipe::FlushTimer(PVOID parameter, BOOLEAN timerFired) s_lastFlushSwitchTime = CLRGetTickCount64(); } -} -void EventPipe::SwitchToNextFile() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - PRECONDITION(s_pFile != nullptr); - PRECONDITION(GetLock()->OwnedByCurrentThread()); - } - CONTRACTL_END - - // Get the current time stamp. - // WriteAllBuffersToFile will use this to ensure that no events after the current timestamp are written into the file. - LARGE_INTEGER stopTimeStamp; - QueryPerformanceCounter(&stopTimeStamp); - s_pBufferManager->WriteAllBuffersToFile(s_pFile, stopTimeStamp); - - // Open the new file. - SString nextTraceFilePath; - GetNextFilePath(nextTraceFilePath); - - StreamWriter *pStreamWriter = new (nothrow) FileStreamWriter(nextTraceFilePath); - if (pStreamWriter == nullptr) + if (s_pFile->HasErrors()) { - // TODO: Add error handling. - return; - } - - EventPipeFile *pFile = new (nothrow) EventPipeFile(pStreamWriter); - if (pFile == NULL) - { - // TODO: Add error handling. - return; - } - - // Close the previous file. - delete s_pFile; - - // Swap in the new file. - s_pFile = pFile; -} - -void EventPipe::GetNextFilePath(SString &nextTraceFilePath) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(GetLock()->OwnedByCurrentThread()); - } - CONTRACTL_END; - - // Set the full path to the requested trace file as the next file path. - nextTraceFilePath.Set(s_pOutputPath); - - // If multiple files have been requested, then add a sequence number to the trace file name. - if (s_multiFileTraceLengthInSeconds > 0) - { - // Remove the ".netperf" file extension if it exists. - SString::Iterator netPerfExtension = nextTraceFilePath.End(); - if (nextTraceFilePath.FindBack(netPerfExtension, W(".netperf"))) + EX_TRY { - nextTraceFilePath.Truncate(netPerfExtension); + DisableInternal(reinterpret_cast(s_pSession)); } - - // Add the sequence number and the ".netperf" file extension. - WCHAR strNextIndex[21]; - swprintf_s(strNextIndex, 21, W(".%u.netperf"), s_nextFileIndex++); - nextTraceFilePath.Append(strNextIndex); + EX_CATCH {} + EX_END_CATCH(SwallowAllExceptions); } } diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h index 5129baf9a93b..b40a0b7735ab 100644 --- a/src/vm/eventpipe.h +++ b/src/vm/eventpipe.h @@ -21,6 +21,7 @@ class MethodDesc; struct EventPipeProviderConfiguration; class EventPipeSession; class IpcStream; +enum class EventPipeSessionType; // EVENT_FILTER_DESCRIPTOR (This type does not exist on non-Windows platforms.) // https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor @@ -28,6 +29,7 @@ class IpcStream; // determines which events are reported and traced. The structure gives the // event provider greater control over the selection of events for reporting // and tracing. +// TODO: EventFilterDescriptor and EventData (defined below) are the same. struct EventFilterDescriptor { // A pointer to the filter data. @@ -231,7 +233,6 @@ class StackContents }; typedef UINT64 EventPipeSessionID; -typedef void (*FlushTimerCallback)(); class EventPipe { @@ -256,14 +257,8 @@ class EventPipe uint64_t profilerSamplingRateInNanoseconds, const EventPipeProviderConfiguration *pProviders, uint32_t numProviders, - uint64_t multiFileTraceLengthInSeconds); - - static EventPipeSessionID Enable( - IpcStream *pStream, - uint32_t circularBufferSizeInMB, - uint64_t profilerSamplingRateInNanoseconds, - const EventPipeProviderConfiguration *pProviders, - uint32_t numProviders); + EventPipeSessionType sessionType, + IpcStream *const pStream); // Disable tracing via the event pipe. static void Disable(EventPipeSessionID id); @@ -310,31 +305,21 @@ class EventPipe // The counterpart to WriteEvent which after the payload is constructed static void WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL); + static void DisableInternal(EventPipeSessionID id); + // Enable the specified EventPipe session. static EventPipeSessionID Enable( + LPCWSTR strOutputPath, EventPipeSession *const pSession, - WAITORTIMERCALLBACK callback, - DWORD dueTime, - DWORD period); + EventPipeSessionType sessionType, + IpcStream *const pStream); - static void CreateFlushTimerCallback(WAITORTIMERCALLBACK Callback, DWORD DueTime, DWORD Period); + static void CreateFlushTimerCallback(); static void DeleteFlushTimerCallback(); - // Performs one polling operation to determine if it is necessary to switch to a new file. - // If the polling operation decides it is time, it will perform the switch. - // Called directly from the timer when the timer is triggered. - static void WINAPI SwitchToNextFileTimerCallback(PVOID parameter, BOOLEAN timerFired); - static void WINAPI FlushTimer(PVOID parameter, BOOLEAN timerFired); - // If event pipe has been configured to write multiple files, switch to the next file. - static void SwitchToNextFile(); - - // Generate the file path for the next trace file. - // This is used when event pipe has been configured to create multiple trace files with a specified maximum length of time. - static void GetNextFilePath(SString &nextTraceFilePath); - // Callback function for the stack walker. For each frame walked, this callback is invoked. static StackWalkAction StackWalkCallback(CrawlFrame *pCf, StackContents *pData); @@ -358,14 +343,11 @@ class EventPipe static EventPipeConfiguration *s_pConfig; static EventPipeSession *s_pSession; static EventPipeBufferManager *s_pBufferManager; - static LPCWSTR s_pOutputPath; - static unsigned long s_nextFileIndex; static EventPipeFile *s_pFile; static EventPipeEventSource *s_pEventSource; static LPCWSTR s_pCommandLine; static HANDLE s_fileSwitchTimerHandle; static ULONGLONG s_lastFlushSwitchTime; - static uint64_t s_multiFileTraceLengthInSeconds; }; struct EventPipeProviderConfiguration diff --git a/src/vm/eventpipebuffermanager.cpp b/src/vm/eventpipebuffermanager.cpp index e15676e15e3d..f08a2b3640f7 100644 --- a/src/vm/eventpipebuffermanager.cpp +++ b/src/vm/eventpipebuffermanager.cpp @@ -434,6 +434,7 @@ void EventPipeBufferManager::WriteAllBuffersToFile(EventPipeFile *pFile, LARGE_I SpinLockHolder _slh(&m_lock); // Naively walk the circular buffer, writing the event stream in timestamp order. + m_numEventsWritten = 0; while(true) { EventPipeEventInstance *pOldestInstance = NULL; @@ -470,13 +471,14 @@ void EventPipeBufferManager::WriteAllBuffersToFile(EventPipeFile *pFile, LARGE_I // Write the oldest event. pFile->WriteEvent(*pOldestInstance); -#ifdef _DEBUG - m_numEventsWritten++; -#endif // _DEBUG + m_numEventsWritten++; // Pop the event from the buffer. pOldestContainingList->PopNextEvent(stopTimeStamp); } + + if (m_numEventsWritten > 0) + pFile->Flush(); } EventPipeEventInstance* EventPipeBufferManager::GetNextEvent() diff --git a/src/vm/eventpipebuffermanager.h b/src/vm/eventpipebuffermanager.h index a7584cce1dda..a6e47f30bca8 100644 --- a/src/vm/eventpipebuffermanager.h +++ b/src/vm/eventpipebuffermanager.h @@ -71,9 +71,9 @@ class EventPipeBufferManager unsigned int m_numBuffersLeaked; Volatile m_numEventsStored; Volatile m_numEventsDropped; - LONG m_numEventsWritten; #endif // _DEBUG + unsigned long m_numEventsWritten; // Allocate a new buffer for the specified thread. // This function will store the buffer in the thread's buffer list for future use and also return it here. // A NULL return value means that a buffer could not be allocated. diff --git a/src/vm/eventpipeconfiguration.cpp b/src/vm/eventpipeconfiguration.cpp index 48899df16c9b..9c7d396af129 100644 --- a/src/vm/eventpipeconfiguration.cpp +++ b/src/vm/eventpipeconfiguration.cpp @@ -319,7 +319,8 @@ EventPipeSession *EventPipeConfiguration::CreateSession( THROWS; GC_NOTRIGGER; MODE_ANY; - PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr)); + PRECONDITION(circularBufferSizeInMB > 0); + PRECONDITION(numProviders > 0 && pProviders != nullptr); } CONTRACTL_END; diff --git a/src/vm/eventpipeeventinstance.h b/src/vm/eventpipeeventinstance.h index cf995f2534c5..54ad807d83ee 100644 --- a/src/vm/eventpipeeventinstance.h +++ b/src/vm/eventpipeeventinstance.h @@ -41,7 +41,7 @@ class EventPipeEventInstance return m_pEvent; } - const LARGE_INTEGER* const GetTimeStamp() const + const LARGE_INTEGER* GetTimeStamp() const { LIMITED_METHOD_CONTRACT; @@ -69,21 +69,21 @@ class EventPipeEventInstance return m_threadID; } - const GUID* const GetActivityId() const + const GUID* GetActivityId() const { LIMITED_METHOD_CONTRACT; return &m_activityId; } - const GUID* const GetRelatedActivityId() const + const GUID* GetRelatedActivityId() const { LIMITED_METHOD_CONTRACT; return &m_relatedActivityId; } - const BYTE* const GetData() const + const BYTE* GetData() const { LIMITED_METHOD_CONTRACT; diff --git a/src/vm/eventpipeeventsource.cpp b/src/vm/eventpipeeventsource.cpp index ca62677cde17..a993bf17a346 100644 --- a/src/vm/eventpipeeventsource.cpp +++ b/src/vm/eventpipeeventsource.cpp @@ -57,7 +57,7 @@ EventPipeEventSource::EventPipeEventSource() // Delete the metadata after the event is created. // The metadata blob will be copied into EventPipe-owned memory. - delete(pMetadata); + delete [] pMetadata; } EventPipeEventSource::~EventPipeEventSource() diff --git a/src/vm/eventpipefile.cpp b/src/vm/eventpipefile.cpp index 73fb48e2e39f..ee16767a5be3 100644 --- a/src/vm/eventpipefile.cpp +++ b/src/vm/eventpipefile.cpp @@ -66,6 +66,12 @@ EventPipeFile::~EventPipeFile() delete m_pSerializer; } +bool EventPipeFile::HasErrors() const +{ + LIMITED_METHOD_CONTRACT; + return (m_pSerializer == nullptr) || m_pSerializer->HasWriteErrors(); +} + void EventPipeFile::WriteEvent(EventPipeEventInstance &instance) { CONTRACTL @@ -96,6 +102,20 @@ void EventPipeFile::WriteEvent(EventPipeEventInstance &instance) WriteToBlock(instance, metadataId); } +void EventPipeFile::Flush() +{ + // Write existing buffer to the stream/file regardless of whether it is full or not. + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + m_pSerializer->WriteObject(m_pBlock); // we write current block to the disk, whether it's full or not + m_pBlock->Clear(); +} + void EventPipeFile::WriteEnd() { CONTRACTL diff --git a/src/vm/eventpipefile.h b/src/vm/eventpipefile.h index d99bcd1883d7..00e32aeeaf87 100644 --- a/src/vm/eventpipefile.h +++ b/src/vm/eventpipefile.h @@ -21,6 +21,8 @@ class EventPipeFile final : public FastSerializableObject ~EventPipeFile(); void WriteEvent(EventPipeEventInstance &instance); + void Flush(); + bool HasErrors() const; const char *GetTypeName() override { diff --git a/src/vm/eventpipeinternal.cpp b/src/vm/eventpipeinternal.cpp index 30a14642c0fe..9291d6b22852 100644 --- a/src/vm/eventpipeinternal.cpp +++ b/src/vm/eventpipeinternal.cpp @@ -20,15 +20,23 @@ UINT64 QCALLTYPE EventPipeInternal::Enable( __in_z LPCWSTR outputFile, UINT32 circularBufferSizeInMB, - INT64 profilerSamplingRateInNanoseconds, + UINT64 profilerSamplingRateInNanoseconds, EventPipeProviderConfiguration *pProviders, - UINT32 numProviders, - UINT64 multiFileTraceLengthInSeconds) + UINT32 numProviders) { QCALL_CONTRACT; UINT64 sessionID = 0; + // Invalid input! + if (circularBufferSizeInMB == 0 || + profilerSamplingRateInNanoseconds == 0 || + numProviders == 0 || + pProviders == nullptr) + { + return 0; + } + BEGIN_QCALL; { sessionID = EventPipe::Enable( @@ -37,7 +45,8 @@ UINT64 QCALLTYPE EventPipeInternal::Enable( profilerSamplingRateInNanoseconds, pProviders, numProviders, - multiFileTraceLengthInSeconds); + outputFile != NULL ? EventPipeSessionType::File : EventPipeSessionType::Streaming, + nullptr); } END_QCALL; diff --git a/src/vm/eventpipeinternal.h b/src/vm/eventpipeinternal.h index bbd4ad633b27..97178c067d76 100644 --- a/src/vm/eventpipeinternal.h +++ b/src/vm/eventpipeinternal.h @@ -47,12 +47,9 @@ class EventPipeInternal static UINT64 QCALLTYPE Enable( __in_z LPCWSTR outputFile, UINT32 circularBufferSizeInMB, - INT64 profilerSamplingRateInNanoseconds, + UINT64 profilerSamplingRateInNanoseconds, EventPipeProviderConfiguration *pProviders, - UINT32 numProviders, - UINT64 multiFileTraceLengthInSeconds); - - //! TODO: Add a ListActiveSessions to get the live SessionID in order to Disable? + UINT32 numProviders); //! //! Disables the specified session Id. diff --git a/src/vm/eventpipeprotocolhelper.cpp b/src/vm/eventpipeprotocolhelper.cpp index c1fe613c054c..8217dae22c8b 100644 --- a/src/vm/eventpipeprotocolhelper.cpp +++ b/src/vm/eventpipeprotocolhelper.cpp @@ -3,12 +3,29 @@ // See the LICENSE file in the project root for more information. #include "common.h" +#include "fastserializer.h" +#include "eventpipefile.h" #include "eventpipeprotocolhelper.h" +#include "eventpipesession.h" #include "diagnosticsipc.h" #include "diagnosticsprotocol.h" #ifdef FEATURE_PERFTRACING +static bool IsNullOrWhiteSpace(LPCWSTR value) +{ + if (value == nullptr) + return true; + + while (*value) + { + if (!iswspace(*value)) + return false; + ++value; + } + return true; +} + bool EventPipeProtocolHelper::TryParseProviderConfiguration(uint8_t *&bufferCursor, uint32_t &bufferLen, CQuickArray &result) { // Picking an arbitrary upper bound, @@ -39,96 +56,18 @@ bool EventPipeProtocolHelper::TryParseProviderConfiguration(uint8_t *&bufferCurs LPCWSTR pProviderName = nullptr; if (!TryParseString(bufferCursor, bufferLen, pProviderName)) return false; - if (wcslen(pProviderName) == 0) - return false; // TODO: Should we ignore these input? + if (IsNullOrWhiteSpace(pProviderName)) + return false; LPCWSTR pFilterData = nullptr; // This parameter is optional. TryParseString(bufferCursor, bufferLen, pFilterData); pConfigs[i] = EventPipeProviderConfiguration(pProviderName, keywords, logLevel, pFilterData); } - return true; -} - -void EventPipeProtocolHelper::EnableFileTracingEventHandler(IpcStream *pStream) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(pStream != nullptr); - } - CONTRACTL_END; - - // TODO: Read within a loop. - uint8_t buffer[IpcStreamReadBufferSize]{}; - uint32_t nNumberOfBytesRead = 0; - bool fSuccess = pStream->Read(buffer, sizeof(buffer), nNumberOfBytesRead); - if (!fSuccess) - { - // TODO: Add error handling. - delete pStream; - return; - } - - // The protocol buffer is defined as: - // X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z - // message = uint circularBufferMB, ulong multiFileTraceLength, string outputPath, array providers - // uint = 4 little endian bytes - // ulong = 8 little endian bytes - // wchar = 2 little endian bytes, UTF16 encoding - // array = uint length, length # of Ts - // string = (array where the last char must = 0) or (length = 0) - // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data - - LPCWSTR strOutputPath; - uint32_t circularBufferSizeInMB = EventPipeProtocolHelper::DefaultCircularBufferMB; - uint64_t multiFileTraceLengthInSeconds = EventPipeProtocolHelper::DefaultMultiFileTraceLengthInSeconds; - CQuickArray providerConfigs; - - uint8_t *pBufferCursor = buffer; - uint32_t bufferLen = nNumberOfBytesRead; - if (!TryParse(pBufferCursor, bufferLen, circularBufferSizeInMB) || - !TryParse(pBufferCursor, bufferLen, multiFileTraceLengthInSeconds) || - !TryParseString(pBufferCursor, bufferLen, strOutputPath) || - !TryParseProviderConfiguration(pBufferCursor, bufferLen, providerConfigs)) - { - // TODO: error handling - delete pStream; - return; - } - - EventPipeSessionID sessionId = (EventPipeSessionID) nullptr; - if (providerConfigs.Size() > 0) - { - sessionId = EventPipe::Enable( - strOutputPath, // outputFile - circularBufferSizeInMB, // circularBufferSizeInMB - DefaultProfilerSamplingRateInNanoseconds, // ProfilerSamplingRateInNanoseconds - providerConfigs.Ptr(), // pConfigs - static_cast(providerConfigs.Size()), // numConfigs - multiFileTraceLengthInSeconds); // multiFileTraceLengthInSeconds - } - - uint32_t nBytesWritten = 0; - fSuccess = pStream->Write(&sessionId, sizeof(sessionId), nBytesWritten); - if (!fSuccess) - { - // TODO: Add error handling. - delete pStream; - return; - } - - fSuccess = pStream->Flush(); - if (!fSuccess) - { - // TODO: Add error handling. - } - delete pStream; + return (countConfigs > 0); } -void EventPipeProtocolHelper::DisableFileTracingEventHandler(IpcStream *pStream) +void EventPipeProtocolHelper::StopTracing(IpcStream *pStream) { CONTRACTL { @@ -167,7 +106,13 @@ void EventPipeProtocolHelper::DisableFileTracingEventHandler(IpcStream *pStream) delete pStream; } -void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream) +static bool TryParseCircularBufferSize(uint8_t *&bufferCursor, uint32_t &bufferLen, uint32_t &circularBufferSizeInMB) +{ + const bool CanParse = TryParse(bufferCursor, bufferLen, circularBufferSizeInMB); + return CanParse && (circularBufferSizeInMB > 0); +} + +void EventPipeProtocolHelper::CollectTracing(IpcStream *pStream) { CONTRACTL { @@ -178,6 +123,9 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream) } CONTRACTL_END; + if (pStream == nullptr) + return; + // TODO: Read within a loop. uint8_t buffer[IpcStreamReadBufferSize]{}; uint32_t nNumberOfBytesRead = 0; @@ -191,7 +139,7 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream) // The protocol buffer is defined as: // X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z - // message = uint circularBufferMB, ulong multiFileTraceLength, string outputPath, array providers + // message = uint circularBufferMB, string outputPath, array providers // uint = 4 little endian bytes // wchar = 2 little endian bytes, UTF16 encoding // array = uint length, length # of Ts @@ -200,14 +148,12 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream) LPCWSTR strOutputPath; uint32_t circularBufferSizeInMB = EventPipeProtocolHelper::DefaultCircularBufferMB; - uint64_t multiFileTraceLengthInSeconds = EventPipeProtocolHelper::DefaultMultiFileTraceLengthInSeconds; CQuickArray providerConfigs; uint8_t *pBufferCursor = buffer; uint32_t bufferLen = nNumberOfBytesRead; - if (!TryParse(pBufferCursor, bufferLen, circularBufferSizeInMB) || - !TryParse(pBufferCursor, bufferLen, multiFileTraceLengthInSeconds) || - !TryParseString(pBufferCursor, bufferLen, strOutputPath) || + if (!TryParseCircularBufferSize(pBufferCursor, bufferLen, circularBufferSizeInMB) || + !TryParseString(pBufferCursor, bufferLen, strOutputPath) || // TODO: Remove. Currently ignored in this scenario. !TryParseProviderConfiguration(pBufferCursor, bufferLen, providerConfigs)) { // TODO: error handling @@ -215,15 +161,17 @@ void EventPipeProtocolHelper::AttachTracingEventHandler(IpcStream *pStream) return; } - if (providerConfigs.Size() > 0) - { - EventPipe::Enable( - pStream, // IPC stream - circularBufferSizeInMB, // circularBufferSizeInMB - DefaultProfilerSamplingRateInNanoseconds, // ProfilerSamplingRateInNanoseconds - providerConfigs.Ptr(), // pConfigs - static_cast(providerConfigs.Size())); // numConfigs - } + auto sessionId = EventPipe::Enable( + nullptr, // strOutputPath (ignored in this scenario) + circularBufferSizeInMB, // circularBufferSizeInMB + DefaultProfilerSamplingRateInNanoseconds, // ProfilerSamplingRateInNanoseconds + providerConfigs.Ptr(), // pConfigs + static_cast(providerConfigs.Size()), // numConfigs + EventPipeSessionType::IpcStream, // EventPipeSessionType + pStream); // IpcStream + + if (sessionId == 0) + delete pStream; } #endif // FEATURE_PERFTRACING diff --git a/src/vm/eventpipeprotocolhelper.h b/src/vm/eventpipeprotocolhelper.h index 44192d724af9..883252116515 100644 --- a/src/vm/eventpipeprotocolhelper.h +++ b/src/vm/eventpipeprotocolhelper.h @@ -16,14 +16,11 @@ class EventPipeProtocolHelper { public: // IPC event handlers. - static void EnableFileTracingEventHandler(IpcStream *pStream); - static void DisableFileTracingEventHandler(IpcStream *pStream); - - static void AttachTracingEventHandler(IpcStream *pStream); + static void StopTracing(IpcStream *pStream); + static void CollectTracing(IpcStream *pStream); // `dotnet-trace collect` private: const static uint32_t DefaultCircularBufferMB = 1024; // 1 GB - const static uint64_t DefaultMultiFileTraceLengthInSeconds = 0; const static uint32_t DefaultProfilerSamplingRateInNanoseconds = 1000000; // 1 msec. const static uint32_t IpcStreamReadBufferSize = 8192; diff --git a/src/vm/eventpipeprovider.h b/src/vm/eventpipeprovider.h index 8ae57d9d6282..6da1ec7dafe8 100644 --- a/src/vm/eventpipeprovider.h +++ b/src/vm/eventpipeprovider.h @@ -18,7 +18,6 @@ class EventPipeProvider // Declare friends. friend class EventPipe; friend class EventPipeConfiguration; - friend class SampleProfiler; private: // The name of the provider. diff --git a/src/vm/eventpipesession.cpp b/src/vm/eventpipesession.cpp index 30c88fb8079e..ef7181861f6c 100644 --- a/src/vm/eventpipesession.cpp +++ b/src/vm/eventpipesession.cpp @@ -21,7 +21,8 @@ EventPipeSession::EventPipeSession( THROWS; GC_NOTRIGGER; MODE_ANY; - PRECONDITION((numProviders == 0) || (numProviders > 0 && pProviders != nullptr)); + PRECONDITION(circularBufferSizeInMB > 0); + PRECONDITION(numProviders > 0 && pProviders != nullptr); } CONTRACTL_END; diff --git a/src/vm/eventpipesession.h b/src/vm/eventpipesession.h index 128ba77012f8..829e18b8a7c5 100644 --- a/src/vm/eventpipesession.h +++ b/src/vm/eventpipesession.h @@ -12,9 +12,9 @@ class EventPipeSessionProvider; enum class EventPipeSessionType { - File, - Streaming, - IpcStream + File, // EventToFile + Streaming, // EventToEventListener + IpcStream // EventToIpc }; class EventPipeSession diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index 7ad93db5db2b..7c30cde1613e 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -5790,7 +5790,7 @@ ETW_INLINE { ULONG Result = ERROR_SUCCESS; - +#ifdef FEATURE_PREJIT // do not fire the ETW event when: // 1. We did not load the native image // 2. We do not have IBC data for the native image @@ -5842,6 +5842,8 @@ ETW_INLINE Result &= FireEtwModuleRangeLoadPrivate(ClrInstanceId, ModuleID, rangeBegin, rangeSize, rangeType, ibcType, virtualSectionType); } } +#endif + return Result; } diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 4d24b21d9030..52cab1113863 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -4738,17 +4738,6 @@ LONG InternalUnhandledExceptionFilter_Worker( return EXCEPTION_CONTINUE_SEARCH; } - - if (GetEEPolicy()->GetActionOnFailure(FAIL_FatalRuntime) == eDisableRuntime) - { - ETaskType type = ::GetCurrentTaskType(); - if (type != TT_UNKNOWN && type != TT_USER) - { - LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker: calling EEPolicy::HandleFatalError\n")); - EEPolicy::HandleFatalError(COR_E_EXECUTIONENGINE, (UINT_PTR)GetIP(pExceptionInfo->ContextRecord), NULL, pExceptionInfo); - } - } - // We don't do anything when this is called from an unmanaged thread. Thread *pThread = GetThread(); diff --git a/src/vm/fastserializer.cpp b/src/vm/fastserializer.cpp index 2941f6ac6a20..5457ee9d37ce 100644 --- a/src/vm/fastserializer.cpp +++ b/src/vm/fastserializer.cpp @@ -12,7 +12,7 @@ // As a result of work on V3 of Event Pipe (https://github.com/Microsoft/perfview/pull/532) it got removed // if you need it, please use git to restore it -IpcStreamWriter::IpcStreamWriter(IpcStream *pStream) : _pStream(pStream) +IpcStreamWriter::IpcStreamWriter(uint64_t id, IpcStream *pStream) : _pStream(pStream) { CONTRACTL { @@ -22,6 +22,17 @@ IpcStreamWriter::IpcStreamWriter(IpcStream *pStream) : _pStream(pStream) PRECONDITION(_pStream != nullptr); } CONTRACTL_END; + + if (_pStream == nullptr) + return; + + uint32_t nBytesWritten = 0; + bool fSuccess = _pStream->Write(&id, sizeof(id), nBytesWritten); + if (!fSuccess) + { + delete _pStream; + _pStream = nullptr; + } } IpcStreamWriter::~IpcStreamWriter() @@ -51,6 +62,8 @@ bool IpcStreamWriter::Write(const void *lpBuffer, const uint32_t nBytesToWrite, if (_pStream == nullptr) return false; + if (lpBuffer == nullptr || nBytesToWrite == 0) + return false; return _pStream->Write(lpBuffer, nBytesToWrite, nBytesWritten); } @@ -63,7 +76,6 @@ FileStreamWriter::FileStreamWriter(const SString &outputFilePath) MODE_ANY; } CONTRACTL_END; - m_pFileStream = new CFileStream(); if (FAILED(m_pFileStream->OpenForWrite(outputFilePath))) { @@ -176,7 +188,7 @@ void FastSerializer::WriteBuffer(BYTE *pBuffer, unsigned int length) EX_TRY { uint32_t outCount; - m_pStreamWriter->Write(pBuffer, length, outCount); + bool fSuccess = m_pStreamWriter->Write(pBuffer, length, outCount); #ifdef _DEBUG size_t prevPos = m_currentPos; @@ -186,7 +198,7 @@ void FastSerializer::WriteBuffer(BYTE *pBuffer, unsigned int length) // This will cause us to stop writing to the file. // The file will still remain open until shutdown so that we don't // have to take a lock at this level when we touch the file stream. - m_writeErrorEncountered = (length != outCount); + m_writeErrorEncountered = (length != outCount) || !fSuccess; #ifdef _DEBUG _ASSERTE(m_writeErrorEncountered || (prevPos < m_currentPos)); diff --git a/src/vm/fastserializer.h b/src/vm/fastserializer.h index 4d61adceeb17..f62bb62b5289 100644 --- a/src/vm/fastserializer.h +++ b/src/vm/fastserializer.h @@ -16,7 +16,7 @@ class IpcStream; // the enumeration has a specific set of values to keep it compatible with consumer library // it's sibling is defined in https://github.com/Microsoft/perfview/blob/10d1f92b242c98073b3817ac5ee6d98cd595d39b/src/FastSerialization/FastSerialization.cs#L2295 -enum class FastSerializerTags : BYTE +enum class FastSerializerTags : uint8_t { Error = 0, // To improve debugabilty, 0 is an illegal tag. NullReference = 1, // Tag for a null object forwardReference. @@ -53,16 +53,16 @@ class StreamWriter class IpcStreamWriter final : public StreamWriter { public: - IpcStreamWriter(IpcStream *pStream); + IpcStreamWriter(uint64_t id, IpcStream *pStream); ~IpcStreamWriter(); bool Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const; private: - IpcStream *const _pStream; + IpcStream *_pStream; }; //! -//! Implements a StreamWriter for writing bytes to an File. +//! Implements a StreamWriter for writing bytes to a File. //! class FileStreamWriter final : public StreamWriter { diff --git a/src/vm/finalizerthread.cpp b/src/vm/finalizerthread.cpp index 15e97878c0be..ad3386e5a59a 100644 --- a/src/vm/finalizerthread.cpp +++ b/src/vm/finalizerthread.cpp @@ -17,7 +17,6 @@ #include "profattach.h" #endif // FEATURE_PROFAPI_ATTACH_DETACH -BOOL FinalizerThread::fRunFinalizersOnUnload = FALSE; BOOL FinalizerThread::fQuitFinalizer = FALSE; #if defined(__linux__) && defined(FEATURE_EVENT_TRACE) @@ -31,7 +30,6 @@ Volatile g_TriggerHeapDump = FALSE; CLREvent * FinalizerThread::hEventFinalizer = NULL; CLREvent * FinalizerThread::hEventFinalizerDone = NULL; -CLREvent * FinalizerThread::hEventShutDownToFinalizer = NULL; CLREvent * FinalizerThread::hEventFinalizerToShutDown = NULL; HANDLE FinalizerThread::MHandles[kHandleCount]; @@ -408,8 +406,6 @@ static BOOL s_FinalizerThreadOK = FALSE; VOID FinalizerThread::FinalizerThreadWorker(void *args) { - // TODO: The following line should be removed after contract violation is fixed. - // See bug 27409 SCAN_IGNORE_THROW; SCAN_IGNORE_TRIGGER; @@ -523,16 +519,6 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) } } - -// During shutdown, finalize all objects that haven't been run yet... whether reachable or not. -void FinalizerThread::FinalizeObjectsOnShutdown(LPVOID args) -{ - WRAPPER_NO_CONTRACT; - - FinalizeAllObjects(BIT_SBLK_FINALIZER_RUN); -} - - DWORD WINAPI FinalizerThread::FinalizerThreadStart(void *args) { ClrFlsSetThreadType (ThreadType_Finalizer); @@ -591,7 +577,7 @@ DWORD WINAPI FinalizerThread::FinalizerThreadStart(void *args) MHandles[kProfilingAPIAttach] = ::ProfilingAPIAttachDetach::GetAttachEvent(); GetFinalizerThread()->DisablePreemptiveGC(); #endif // FEATURE_PROFAPI_ATTACH_DETACH - + while (!fQuitFinalizer) { // This will apply any policy for swallowing exceptions during normal @@ -605,67 +591,12 @@ DWORD WINAPI FinalizerThread::FinalizerThreadStart(void *args) EnableFinalization(); } - // Tell shutdown thread we are done with finalizing dead objects. - hEventFinalizerToShutDown->Set(); - - // Wait for shutdown thread to signal us. - GetFinalizerThread()->EnablePreemptiveGC(); - hEventShutDownToFinalizer->Wait(INFINITE,FALSE); - GetFinalizerThread()->DisablePreemptiveGC(); - AppDomain::RaiseExitProcessEvent(); - hEventFinalizerToShutDown->Set(); - - // Phase 1 ends. - // Now wait for Phase 2 signal. - - // Wait for shutdown thread to signal us. - GetFinalizerThread()->EnablePreemptiveGC(); - hEventShutDownToFinalizer->Wait(INFINITE,FALSE); - GetFinalizerThread()->DisablePreemptiveGC(); - // We have been asked to quit, so must be shutting down _ASSERTE(g_fEEShutDown); _ASSERTE(GetFinalizerThread()->PreemptiveGCDisabled()); - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_FinalizeOnShutdown) != 0) - { - // Finalize all registered objects during shutdown, even they are still reachable. - GCHeapUtilities::GetGCHeap()->SetFinalizeQueueForShutdown(FALSE); - - // This will apply any policy for swallowing exceptions during normal - // processing, without allowing the finalizer thread to disappear on us. - ManagedThreadBase::FinalizerBase(FinalizeObjectsOnShutdown); - } - - _ASSERTE(GetFinalizerThread()->GetDomain()->IsDefaultDomain()); - - // we might want to do some extra work on the finalizer thread - // check and do it - if (GetFinalizerThread()->HaveExtraWorkForFinalizer()) - { - GetFinalizerThread()->DoExtraWorkForFinalizer(); - } - - hEventFinalizerToShutDown->Set(); - - // Wait for shutdown thread to signal us. - GetFinalizerThread()->EnablePreemptiveGC(); - hEventShutDownToFinalizer->Wait(INFINITE,FALSE); - GetFinalizerThread()->DisablePreemptiveGC(); - -#ifdef FEATURE_COMINTEROP - // Do extra cleanup for part 1 of shutdown. - // If we hang here (bug 87809) shutdown thread will - // timeout on us and will proceed normally - // - // We cannot call CoEEShutDownCOM, since the BEGIN_EXTERNAL_ENTRYPOINT - // will turn our call into a NOP. We can no longer execute managed - // code for an external caller. - InnerCoEEShutDownCOM(); -#endif // FEATURE_COMINTEROP - hEventFinalizerToShutDown->Set(); #ifdef _DEBUG // The only purpose of this try/finally is to trigger an assertion @@ -729,8 +660,6 @@ void FinalizerThread::FinalizerThreadCreate() hEventFinalizer->CreateAutoEvent(FALSE); hEventFinalizerToShutDown = new CLREvent(); hEventFinalizerToShutDown->CreateAutoEvent(FALSE); - hEventShutDownToFinalizer = new CLREvent(); - hEventShutDownToFinalizer->CreateAutoEvent(FALSE); _ASSERTE(g_pFinalizerThread == 0); g_pFinalizerThread = SetupUnstartedThread(); @@ -833,335 +762,3 @@ void FinalizerThread::FinalizerThreadWait(DWORD timeout) } } } - - -#ifdef _DEBUG -#define FINALIZER_WAIT_TIMEOUT 250 -#else -#define FINALIZER_WAIT_TIMEOUT 200 -#endif -#define FINALIZER_TOTAL_WAIT 2000 - -static BOOL s_fRaiseExitProcessEvent = FALSE; -static DWORD dwBreakOnFinalizeTimeOut = (DWORD) -1; - -static ULONGLONG ShutdownEnd; - - -BOOL FinalizerThread::FinalizerThreadWatchDog() -{ - Thread *pThread = GetThread(); - - if (dwBreakOnFinalizeTimeOut == (DWORD) -1) { - dwBreakOnFinalizeTimeOut = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_BreakOnFinalizeTimeOut); - } - - // Do not wait for FinalizerThread if the current one is FinalizerThread. - if (pThread == GetFinalizerThread()) - return TRUE; - - // If finalizer thread is gone, just return. - if (GetFinalizerThread()->Join (0, FALSE) != WAIT_TIMEOUT) - return TRUE; - - // *** This is the first call ShutDown -> Finalizer to Finilize dead objects *** - if ((g_fEEShutDown & ShutDown_Finalize1) && - !(g_fEEShutDown & ShutDown_Finalize2)) { - ShutdownEnd = CLRGetTickCount64() + GetEEPolicy()->GetTimeout(OPR_ProcessExit); - // Wait for the finalizer... - LOG((LF_GC, LL_INFO10, "Signalling finalizer to quit...")); - - fQuitFinalizer = TRUE; - hEventFinalizerDone->Reset(); - EnableFinalization(); - - LOG((LF_GC, LL_INFO10, "Waiting for finalizer to quit...")); - - if (pThread) - { - pThread->EnablePreemptiveGC(); - } - - BOOL fTimeOut = FinalizerThreadWatchDogHelper(); - - if (!fTimeOut) { - hEventShutDownToFinalizer->Set(); - - // Wait for finalizer thread to finish raising ExitProcess Event. - s_fRaiseExitProcessEvent = TRUE; - fTimeOut = FinalizerThreadWatchDogHelper(); - s_fRaiseExitProcessEvent = FALSE; - } - - if (pThread) - { - pThread->DisablePreemptiveGC(); - } - - // Can not call ExitProcess here if we are in a hosting environment. - // The host does not expect that we terminate the process. - //if (fTimeOut) - //{ - //::ExitProcess (GetLatchedExitCode()); - //} - - return !fTimeOut; - } - - // *** This is the second call ShutDown -> Finalizer to *** - // suspend the Runtime and Finilize live objects - if ( g_fEEShutDown & ShutDown_Finalize2 && - !(g_fEEShutDown & ShutDown_COM) ) { - -#ifdef BACKGROUND_GC - gc_heap::gc_can_use_concurrent = FALSE; - - if (pGenGCHeap->settings.concurrent) - pGenGCHeap->background_gc_wait(); -#endif //BACKGROUND_GC - - _ASSERTE((g_fEEShutDown & ShutDown_Finalize1) || g_fFastExitProcess); - - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_FinalizeOnShutdown) != 0) - { - // When running finalizers on shutdown (including for reachable objects), suspend threads for shutdown before - // running finalizers, so that the reachable objects will not be used after they are finalized. - - ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_SHUTDOWN); - - g_fSuspendOnShutdown = TRUE; - - // Do not balance the trap returning threads. - // We are shutting down CLR. Only Finalizer/Shutdown threads can - // return from DisablePreemptiveGC. - ThreadStore::TrapReturningThreads(TRUE); - - ThreadSuspend::RestartEE(FALSE, TRUE); - } - - if (g_fFastExitProcess) - { - return TRUE; - } - - // !!! Before we wake up Finalizer thread, we need to enable preemptive gc on the - // !!! shutdown thread. Otherwise we may see a deadlock during debug test. - if (pThread) - { - pThread->EnablePreemptiveGC(); - } - - GCHeapUtilities::GetGCHeap()->SetFinalizeRunOnShutdown(true); - - // Wait for finalizer thread to finish finalizing all objects. - hEventShutDownToFinalizer->Set(); - BOOL fTimeOut = FinalizerThreadWatchDogHelper(); - - if (!fTimeOut) { - GCHeapUtilities::GetGCHeap()->SetFinalizeRunOnShutdown(false); - } - - // Can not call ExitProcess here if we are in a hosting environment. - // The host does not expect that we terminate the process. - //if (fTimeOut) { - // ::ExitProcess (GetLatchedExitCode()); - //} - - if (pThread) - { - pThread->DisablePreemptiveGC(); - } - return !fTimeOut; - } - - // *** This is the third call ShutDown -> Finalizer *** - // to do additional cleanup - if (g_fEEShutDown & ShutDown_COM) { - _ASSERTE (g_fEEShutDown & (ShutDown_Finalize2 | ShutDown_Finalize1)); - - if (pThread) - { - pThread->EnablePreemptiveGC(); - } - - GCHeapUtilities::GetGCHeap()->SetFinalizeRunOnShutdown(true); - - hEventShutDownToFinalizer->Set(); - DWORD status = WAIT_OBJECT_0; - while (CLREventWaitWithTry(hEventFinalizerToShutDown, FINALIZER_WAIT_TIMEOUT, TRUE, &status)) - { - } - - BOOL fTimeOut = (status == WAIT_TIMEOUT) ? TRUE : FALSE; - - if (fTimeOut) - { - if (dwBreakOnFinalizeTimeOut) { - LOG((LF_GC, LL_INFO10, "Finalizer took too long to clean up COM IP's.\n")); - DebugBreak(); - } - } - - if (pThread) - { - pThread->DisablePreemptiveGC(); - } - - return !fTimeOut; - } - - _ASSERTE(!"Should never reach this point"); - return FALSE; -} - -BOOL FinalizerThread::FinalizerThreadWatchDogHelper() -{ - // Since our thread is blocking waiting for the finalizer thread, we must be in preemptive GC - // so that we don't in turn block the finalizer on us in a GC. - Thread *pCurrentThread; - pCurrentThread = GetThread(); - _ASSERTE (pCurrentThread == NULL || !pCurrentThread->PreemptiveGCDisabled()); - - // We're monitoring the finalizer thread. - Thread *pThread = GetFinalizerThread(); - _ASSERTE(pThread != pCurrentThread); - - ULONGLONG dwBeginTickCount = CLRGetTickCount64(); - - size_t prevCount; - size_t curCount; - BOOL fTimeOut = FALSE; - DWORD nTry = 0; - DWORD maxTotalWait = (DWORD)(ShutdownEnd - dwBeginTickCount); - DWORD totalWaitTimeout; - totalWaitTimeout = GetEEPolicy()->GetTimeout(OPR_FinalizerRun); - if (totalWaitTimeout == (DWORD)-1) - { - totalWaitTimeout = FINALIZER_TOTAL_WAIT; - } - - if (s_fRaiseExitProcessEvent) - { - DWORD tmp = maxTotalWait/20; // Normally we assume 2 seconds timeout if total timeout is 40 seconds. - if (tmp > totalWaitTimeout) - { - totalWaitTimeout = tmp; - } - prevCount = MAXLONG; - } - else - { - prevCount = GCHeapUtilities::GetGCHeap()->GetNumberOfFinalizable(); - } - - DWORD maxTry = (DWORD)(totalWaitTimeout*1.0/FINALIZER_WAIT_TIMEOUT + 0.5); - BOOL bAlertable = TRUE; //(g_fEEShutDown & ShutDown_Finalize2) ? FALSE:TRUE; - - if (dwBreakOnFinalizeTimeOut == (DWORD) -1) { - dwBreakOnFinalizeTimeOut = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_BreakOnFinalizeTimeOut); - } - - DWORD dwTimeout = FINALIZER_WAIT_TIMEOUT; - - // This used to set the dwTimeout to infinite, but this can cause a hang when shutting down - // if a finalizer tries to take a lock that another suspended managed thread already has. - // This results in the hang because the other managed thread is never going to be resumed - // because we're in shutdown. So we make a compromise here - make the timeout for every - // iteration 10 times longer and make the total wait infinite - so if things hang we will - // eventually shutdown but we also give things a chance to finish if they're running slower - // because of the profiler. -#ifdef PROFILING_SUPPORTED - if (CORProfilerPresent()) - { - dwTimeout *= 10; - maxTotalWait = INFINITE; - } -#endif // PROFILING_SUPPORTED - - // This change was added late in Windows Phone 8, so we want to keep it minimal. - // We should consider refactoring this later, as we've got a lot of dead code here now on CoreCLR. - dwTimeout = INFINITE; - maxTotalWait = INFINITE; - - while (1) { - struct Param - { - DWORD status; - DWORD dwTimeout; - BOOL bAlertable; - } param; - param.status = 0; - param.dwTimeout = dwTimeout; - param.bAlertable = bAlertable; - - PAL_TRY(Param *, pParam, ¶m) - { - pParam->status = hEventFinalizerToShutDown->Wait(pParam->dwTimeout, pParam->bAlertable); - } - PAL_EXCEPT (EXCEPTION_EXECUTE_HANDLER) - { - param.status = WAIT_TIMEOUT; - } - PAL_ENDTRY - - if (param.status != WAIT_TIMEOUT) { - break; - } - nTry ++; - // ExitProcessEventCount is incremental - // FinalizableObjects is decremental - if (s_fRaiseExitProcessEvent) - { - curCount = MAXLONG - GetProcessedExitProcessEventCount(); - } - else - { - curCount = GCHeapUtilities::GetGCHeap()->GetNumberOfFinalizable(); - } - - if ((prevCount <= curCount) - && !GCHeapUtilities::GetGCHeap()->ShouldRestartFinalizerWatchDog() - && (pThread == NULL || !(pThread->m_State & (Thread::TS_UserSuspendPending | Thread::TS_DebugSuspendPending)))){ - if (nTry == maxTry) { - if (!s_fRaiseExitProcessEvent) { - LOG((LF_GC, LL_INFO10, "Finalizer took too long on one object.\n")); - } - else - LOG((LF_GC, LL_INFO10, "Finalizer took too long to process ExitProcess event.\n")); - - fTimeOut = TRUE; - if (dwBreakOnFinalizeTimeOut != 2) { - break; - } - } - } - else - { - nTry = 0; - prevCount = curCount; - } - ULONGLONG dwCurTickCount = CLRGetTickCount64(); - if (pThread && pThread->m_State & (Thread::TS_UserSuspendPending | Thread::TS_DebugSuspendPending)) { - // CoreCLR does not support user-requested thread suspension - _ASSERTE(!(pThread->m_State & Thread::TS_UserSuspendPending)); - dwBeginTickCount = dwCurTickCount; - } - if (dwCurTickCount - dwBeginTickCount >= maxTotalWait) - { - LOG((LF_GC, LL_INFO10, "Finalizer took too long on shutdown.\n")); - fTimeOut = TRUE; - if (dwBreakOnFinalizeTimeOut != 2) { - break; - } - } - } - - if (fTimeOut) - { - if (dwBreakOnFinalizeTimeOut){ - DebugBreak(); - } - } - - return fTimeOut; -} diff --git a/src/vm/finalizerthread.h b/src/vm/finalizerthread.h index f11dd1520965..d5063b21668e 100644 --- a/src/vm/finalizerthread.h +++ b/src/vm/finalizerthread.h @@ -8,16 +8,14 @@ class FinalizerThread { - static BOOL fRunFinalizersOnUnload; static BOOL fQuitFinalizer; - + #if defined(__linux__) && defined(FEATURE_EVENT_TRACE) static ULONGLONG LastHeapDumpTime; #endif static CLREvent *hEventFinalizer; static CLREvent *hEventFinalizerDone; - static CLREvent *hEventShutDownToFinalizer; static CLREvent *hEventFinalizerToShutDown; // Note: This enum makes it easier to read much of the code that deals with the @@ -40,8 +38,6 @@ class FinalizerThread static void WaitForFinalizerEvent (CLREvent *event); - static BOOL FinalizerThreadWatchDogHelper(); - #ifdef FEATURE_PROFAPI_ATTACH_DETACH static void ProcessProfilerAttachIfNecessary(ULONGLONG * pui64TimestampLastCheckedEventMs); #endif // FEATURE_PROFAPI_ATTACH_DETACH @@ -64,6 +60,17 @@ class FinalizerThread static BOOL HaveExtraWorkForFinalizer(); + static void RaiseShutdownEvents() + { + WRAPPER_NO_CONTRACT; + fQuitFinalizer = TRUE; + EnableFinalization(); + + // Do not wait for FinalizerThread if the current one is FinalizerThread. + if (GetThread() != GetFinalizerThread()) + hEventFinalizerToShutDown->Wait(INFINITE,FALSE); + } + static void FinalizerThreadWait(DWORD timeout = INFINITE); // We wake up a wait for finaliation for two reasons: @@ -72,11 +79,9 @@ class FinalizerThread static void SignalFinalizationDone(BOOL fFinalizer); static VOID FinalizerThreadWorker(void *args); - static void FinalizeObjectsOnShutdown(LPVOID args); static DWORD WINAPI FinalizerThreadStart(void *args); static void FinalizerThreadCreate(); - static BOOL FinalizerThreadWatchDog(); }; #endif // _FINALIZER_THREAD_H_ diff --git a/src/vm/frames.cpp b/src/vm/frames.cpp index af41def0c190..f44f32a4c2ca 100644 --- a/src/vm/frames.cpp +++ b/src/vm/frames.cpp @@ -311,14 +311,6 @@ void Frame::Init() } // void Frame::Init() -// static -void Frame::Term() -{ - LIMITED_METHOD_CONTRACT; - delete s_pFrameVTables; - s_pFrameVTables = NULL; -} - #endif // DACCESS_COMPILE // Returns true if the Frame's VTablePtr is valid diff --git a/src/vm/frames.h b/src/vm/frames.h index 5cc5e37d5e71..d219ac30a552 100644 --- a/src/vm/frames.h +++ b/src/vm/frames.h @@ -543,7 +543,6 @@ class Frame : public FrameBase static bool HasValidVTablePtr(Frame * pFrame); static PTR_GSCookie SafeGetGSCookiePtr(Frame * pFrame); static void Init(); - static void Term(); // Callers, note that the REGDISPLAY parameter is actually in/out. While // UpdateRegDisplay is generally used to fill out the REGDISPLAY parameter, some diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp index 909319889e5c..6e3f7756606a 100644 --- a/src/vm/gcenv.os.cpp +++ b/src/vm/gcenv.os.cpp @@ -55,6 +55,48 @@ class GroupProcNo uint16_t GetCombinedValue() { return m_groupProc; } }; +#if !defined(FEATURE_PAL) + +static bool g_SeLockMemoryPrivilegeAcquired = false; + +bool InitLargePagesPrivilege() +{ + TOKEN_PRIVILEGES tp; + LUID luid; + if (!LookupPrivilegeValueW(nullptr, SE_LOCK_MEMORY_NAME, &luid)) + { + return false; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + HANDLE token; + if (!OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) + { + return false; + } + + BOOL retVal = AdjustTokenPrivileges(token, FALSE, &tp, 0, nullptr, 0); + DWORD gls = GetLastError(); + CloseHandle(token); + + if (!retVal) + { + return false; + } + + if (gls != 0) + { + return false; + } + + return true; +} + +#endif // FEATURE_PAL + // Initialize the interface implementation // Return: // true if it has succeeded, false if it has failed @@ -64,8 +106,21 @@ bool GCToOSInterface::Initialize() #ifdef FEATURE_PAL g_pageSizeUnixInl = GetOsPageSize(); -#endif + uint32_t currentProcessCpuCount = PAL_GetLogicalCpuCountFromOS(); + if (PAL_GetCurrentThreadAffinitySet(AffinitySet::BitsetDataSize, g_processAffinitySet.GetBitsetData())) + { + assert(currentProcessCpuCount == g_processAffinitySet.Count()); + } + else + { + // There is no way to get affinity on the current OS, set the affinity set to reflect all processors + for (size_t i = 0; i < currentProcessCpuCount; i++) + { + g_processAffinitySet.Add(i); + } + } +#else // FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups()) { // When CPU groups are enabled, then the process is not bound by the process affinity set at process launch. @@ -93,6 +148,7 @@ bool GCToOSInterface::Initialize() } } } +#endif // FEATURE_PAL return true; } @@ -133,7 +189,7 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t LIMITED_METHOD_CONTRACT; bool success = true; - +#ifndef FEATURE_PAL GroupProcNo srcGroupProcNo(srcProcNo); GroupProcNo dstGroupProcNo(dstProcNo); @@ -160,7 +216,6 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); } -#if !defined(FEATURE_PAL) else { if (GetThreadIdealProcessorEx(GetCurrentThread(), &proc)) @@ -169,10 +224,13 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, &proc); } } -#endif // !defined(FEATURE_PAL) -#endif - +#endif // !FEATURE_CORESYSTEM return success; + +#else // !FEATURE_PAL + return GCToOSInterface::SetThreadAffinity(dstProcNo); + +#endif // !FEATURE_PAL } // Get the number of the current processor @@ -271,6 +329,33 @@ bool GCToOSInterface::VirtualRelease(void* address, size_t size) return !!::ClrVirtualFree(address, 0, MEM_RELEASE); } +// Commit virtual memory range. +// Parameters: +// size - size of the virtual memory range +// Return: +// Starting virtual address of the committed range +void* GCToOSInterface::VirtualReserveAndCommitLargePages(size_t size) +{ + LIMITED_METHOD_CONTRACT; + +#if !defined(FEATURE_PAL) + if (!g_SeLockMemoryPrivilegeAcquired) + { + if (!InitLargePagesPrivilege()) + { + return nullptr; + } + + g_SeLockMemoryPrivilegeAcquired = true; + } + + SIZE_T largePageMinimum = GetLargePageMinimum(); + size = (size + (largePageMinimum - 1)) & ~(largePageMinimum - 1); +#endif + + return ::ClrVirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); +} + // Commit virtual memory range. It must be part of a range reserved using VirtualReserve. // Parameters: // address - starting virtual address @@ -403,7 +488,7 @@ size_t GCToOSInterface::GetCacheSizePerLogicalCpu(bool trueSize) bool GCToOSInterface::SetThreadAffinity(uint16_t procNo) { LIMITED_METHOD_CONTRACT; - +#ifndef FEATURE_PAL GroupProcNo groupProcNo(procNo); if (groupProcNo.GetGroup() != GroupProcNo::NoGroup) @@ -420,6 +505,9 @@ bool GCToOSInterface::SetThreadAffinity(uint16_t procNo) { return !!SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)1 << groupProcNo.GetProcIndex()); } +#else // FEATURE_PAL + return PAL_SetCurrentThreadAffinity(procNo); +#endif // FEATURE_PAL } // Boosts the calling thread's thread priority to a level higher than the default @@ -441,7 +529,9 @@ bool GCToOSInterface::BoostThreadPriority() // set of enabled processors const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffinityMask, const AffinitySet* configAffinitySet) { +#ifndef FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups()) +#endif // !FEATURE_PAL { if (!configAffinitySet->IsEmpty()) { @@ -455,6 +545,7 @@ const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffi } } } +#ifndef FEATURE_PAL else { if (configAffinityMask != 0) @@ -469,6 +560,7 @@ const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffi } } } +#endif // !FEATURE_PAL return &g_processAffinitySet; } @@ -480,10 +572,14 @@ uint32_t GCToOSInterface::GetCurrentProcessCpuCount() { LIMITED_METHOD_CONTRACT; +#ifndef FEATURE_PAL // GetCurrentProcessCpuCount only returns up to 64 procs. return CPUGroupInfo::CanEnableGCCPUGroups() ? GCToOSInterface::GetTotalProcessorCount(): ::GetCurrentProcessCpuCount(); +#else // !FEATURE_PAL + return ::GetCurrentProcessCpuCount(); +#endif // !FEATURE_PAL } // Return the size of the user-mode portion of the virtual address space of this process. @@ -818,6 +914,7 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() { LIMITED_METHOD_CONTRACT; +#ifndef FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups()) { return CPUGroupInfo::GetNumActiveProcessors(); @@ -826,6 +923,9 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() { return g_SystemInfo.dwNumberOfProcessors; } +#else // !FEATURE_PAL + return PAL_GetTotalCpuCount(); +#endif // !FEATURE_PAL } bool GCToOSInterface::CanEnableGCNumaAware() @@ -835,20 +935,6 @@ bool GCToOSInterface::CanEnableGCNumaAware() return NumaNodeInfo::CanEnableGCNumaAware() != FALSE; } -bool GCToOSInterface::GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no) -{ - LIMITED_METHOD_CONTRACT; - - GroupProcNo groupProcNo(proc_no); - - PROCESSOR_NUMBER procNumber; - procNumber.Group = groupProcNo.GetGroup(); - procNumber.Number = (BYTE)groupProcNo.GetProcIndex(); - procNumber.Reserved = 0; - - return NumaNodeInfo::GetNumaProcessorNodeEx(&procNumber, node_no) != FALSE; -} - // Get processor number and optionally its NUMA node number for the specified heap number // Parameters: // heap_number - heap number to get the result for @@ -860,53 +946,75 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n { bool success = false; - if (CPUGroupInfo::CanEnableGCCPUGroups()) + // Locate heap_number-th available processor + uint16_t procIndex; + size_t cnt = heap_number; + for (uint16_t i = 0; i < GCToOSInterface::GetTotalProcessorCount(); i++) + { + if (g_processAffinitySet.Contains(i)) + { + if (cnt == 0) + { + procIndex = i; + success = true; + break; + } + + cnt--; + } + } + + if (success) { - uint16_t gn, gpn; - CPUGroupInfo::GetGroupForProcessor((uint16_t)heap_number, &gn, &gpn); +#ifndef FEATURE_PAL + WORD gn, gpn; + + if (CPUGroupInfo::CanEnableGCCPUGroups()) + { + CPUGroupInfo::GetGroupForProcessor(procIndex, &gn, &gpn); + } + else + { + gn = GroupProcNo::NoGroup; + gpn = procIndex; + } + + GroupProcNo groupProcNo(gn, gpn); + *proc_no = groupProcNo.GetCombinedValue(); - *proc_no = GroupProcNo(gn, gpn).GetCombinedValue(); if (GCToOSInterface::CanEnableGCNumaAware()) { - if (!GCToOSInterface::GetNumaProcessorNode(*proc_no, node_no)) + PROCESSOR_NUMBER procNumber; + + if (CPUGroupInfo::CanEnableGCCPUGroups()) + { + procNumber.Group = gn; + } + else + { + // Get the current processor group + GetCurrentProcessorNumberEx(&procNumber); + } + + procNumber.Number = (BYTE)gpn; + procNumber.Reserved = 0; + + if (!NumaNodeInfo::GetNumaProcessorNodeEx(&procNumber, node_no)) { *node_no = NUMA_NODE_UNDEFINED; } } else { // no numa setting, each cpu group is treated as a node - *node_no = gn; + *node_no = groupProcNo.GetGroup(); } - - success = true; - } - else - { - int bit_number = 0; - uint8_t proc_number = 0; - for (uintptr_t mask = 1; mask != 0; mask <<= 1) +#else // !FEATURE_PAL + *proc_no = procIndex; + if (!GCToOSInterface::CanEnableGCNumaAware() || !NumaNodeInfo::GetNumaProcessorNodeEx(procIndex, (WORD*)node_no)) { - if (g_processAffinitySet.Contains(proc_number)) - { - if (bit_number == heap_number) - { - *proc_no = GroupProcNo(GroupProcNo::NoGroup, proc_number).GetCombinedValue(); - - if (GCToOSInterface::CanEnableGCNumaAware()) - { - if (!GCToOSInterface::GetNumaProcessorNode(proc_number, node_no)) - { - *node_no = NUMA_NODE_UNDEFINED; - } - } - - success = true; - break; - } - bit_number++; - } - proc_number++; + *node_no = NUMA_NODE_UNDEFINED; } +#endif // !FEATURE_PAL } return success; @@ -924,6 +1032,7 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin size_t index_offset = 0; char* number_end; +#ifndef FEATURE_PAL size_t group_number = strtoul(*config_string, &number_end, 10); if ((number_end == *config_string) || (*number_end != ':')) @@ -942,6 +1051,7 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin index_offset = group_begin; *config_string = number_end + 1; +#endif // !FEATURE_PAL size_t start, end; if (!ParseIndexOrRange(config_string, &start, &end)) @@ -949,11 +1059,13 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin return false; } +#ifndef FEATURE_PAL if ((start >= group_size) || (end >= group_size)) { // Invalid CPU index values or range return false; } +#endif // !FEATURE_PAL *start_index = index_offset + start; *end_index = index_offset + end; diff --git a/src/vm/i386/asmhelpers.asm b/src/vm/i386/asmhelpers.asm index 18b5c6eb98ef..85a19b898222 100644 --- a/src/vm/i386/asmhelpers.asm +++ b/src/vm/i386/asmhelpers.asm @@ -1528,6 +1528,8 @@ public _StubDispatchFixupPatchLabel@0 _StubDispatchFixupStub@0 endp +endif ; FEATURE_PREJIT + ;========================================================================== _ExternalMethodFixupStub@0 proc public @@ -1605,6 +1607,8 @@ _DelayLoad_MethodCall@0 proc public _DelayLoad_MethodCall@0 endp endif +ifdef FEATURE_PREJIT + ;======================================================================================= ; The call in softbound vtable slots initially points to this function. ; The pupose of this function is to transfer the control to right target and diff --git a/src/vm/ilstubresolver.cpp b/src/vm/ilstubresolver.cpp index 5b2f8a462e71..4d429626ebc0 100644 --- a/src/vm/ilstubresolver.cpp +++ b/src/vm/ilstubresolver.cpp @@ -266,7 +266,7 @@ ILStubResolver::SetStubTargetMethodSig( } CONTRACTL_END; - NewHolder pNewSig = new BYTE[cbStubTargetSigLength]; + NewArrayHolder pNewSig = new BYTE[cbStubTargetSigLength]; memcpyNoGCRefs((void *)pNewSig, pStubTargetMethodSig, cbStubTargetSigLength); @@ -313,9 +313,9 @@ ILStubResolver::AllocGeneratedIL( #if !defined(DACCESS_COMPILE) _ASSERTE(0 != cbCode); - NewHolder pNewILCodeBuffer = NULL; - NewHolder pNewLocalSig = NULL; - NewHolder pNewCompileTimeState = NULL; + NewArrayHolder pNewILCodeBuffer = NULL; + NewArrayHolder pNewLocalSig = NULL; + NewArrayHolder pNewCompileTimeState = NULL; pNewCompileTimeState = (CompileTimeState *)new BYTE[sizeof(CompileTimeState)]; memset(pNewCompileTimeState, 0, sizeof(CompileTimeState)); diff --git a/src/vm/instmethhash.cpp b/src/vm/instmethhash.cpp index 560e9554be35..05378b4450cb 100644 --- a/src/vm/instmethhash.cpp +++ b/src/vm/instmethhash.cpp @@ -183,12 +183,16 @@ MethodDesc* InstMethodHashTable::FindMethodDesc(TypeHandle declaringType, if ( ((dwKeyFlags & InstMethodHashEntry::UnboxingStub) == 0) != (unboxingStub == 0) ) continue; +#ifdef FEATURE_PREJIT // Note pMD->GetMethodTable() might not be restored at this point. RelativeFixupPointer * ppMT = pMD->GetMethodTablePtr(); TADDR pMT = ppMT->GetValueMaybeTagged((TADDR)ppMT); if (!ZapSig::CompareTaggedPointerToTypeHandle(GetModule(), pMT, declaringType)) +#else + if (TypeHandle(pMD->GetMethodTable()) != declaringType) +#endif { continue; // Next iteration of the for loop } @@ -204,11 +208,15 @@ MethodDesc* InstMethodHashTable::FindMethodDesc(TypeHandle declaringType, for (DWORD i = 0; i < inst.GetNumArgs(); i++) { +#ifdef FEATURE_PREJIT // Fetch the type handle as TADDR. It may be may be encoded fixup - TypeHandle debug-only validation // asserts on encoded fixups. TADDR candidateArg = ((FixupPointer *)candidateInst.GetRawArgs())[i].GetValue(); if (!ZapSig::CompareTaggedPointerToTypeHandle(GetModule(), candidateArg, inst[i])) +#else + if (candidateInst[i] != inst[i]) +#endif { match = false; break; diff --git a/src/vm/interopconverter.cpp b/src/vm/interopconverter.cpp index 70b1113cd312..d8bb08d53db3 100644 --- a/src/vm/interopconverter.cpp +++ b/src/vm/interopconverter.cpp @@ -414,7 +414,7 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, REFIID iid, bool throwIfNoComI // GetObjectRefFromComIP // pUnk : input IUnknown // pMTClass : specifies the type of instance to be returned -// NOTE:** As per COM Rules, the IUnknown passed is shouldn't be AddRef'ed +// NOTE:** As per COM Rules, the IUnknown passed in shouldn't be AddRef'ed //+---------------------------------------------------------------------------- void GetObjectRefFromComIP(OBJECTREF* pObjOut, IUnknown **ppUnk, MethodTable *pMTClass, MethodTable *pItfMT, DWORD dwFlags) { @@ -456,24 +456,27 @@ void GetObjectRefFromComIP(OBJECTREF* pObjOut, IUnknown **ppUnk, MethodTable *pM if (pUnk != NULL) { // get CCW for IUnknown - ComCallWrapper* pWrap = GetCCWFromIUnknown(pUnk); - if (pWrap == NULL) + ComCallWrapper *ccw = GetCCWFromIUnknown(pUnk); + if (ccw == NULL) { // could be aggregated scenario HRESULT hr = SafeQueryInterface(pUnk, IID_IUnknown, &pOuter); LogInteropQI(pUnk, IID_IUnknown, hr, "GetObjectRefFromComIP: QI for Outer"); IfFailThrow(hr); - + // store the outer in the auto pointer pAutoOuterUnk = pOuter; - pWrap = GetCCWFromIUnknown(pOuter); + ccw = GetCCWFromIUnknown(pOuter); } - if (pWrap != NULL) - { // our tear-off - _ASSERTE(pWrap != NULL); - AppDomain* pCurrDomain = pThread->GetDomain(); - *pObjOut = pWrap->GetObjectRef(); + // If the CCW was activated via COM, do not unwrap it. + // Unwrapping a CCW would deliver the underlying OBJECTREF, + // but when a managed class is activated via COM it should + // remain a COM object and adhere to COM rules. + if (ccw != NULL + && !ccw->IsComActivated()) + { + *pObjOut = ccw->GetObjectRef(); } if (*pObjOut != NULL) diff --git a/src/vm/interoputil.cpp b/src/vm/interoputil.cpp index 7cca714a1463..11859f50cffd 100644 --- a/src/vm/interoputil.cpp +++ b/src/vm/interoputil.cpp @@ -3700,6 +3700,7 @@ BOOL IsTypeVisibleFromCom(TypeHandle hndType) return SpecialIsGenericTypeVisibleFromCom(hndType); } +#ifdef FEATURE_PREJIT //--------------------------------------------------------------------------- // Determines if a method is likely to be used for forward COM/WinRT interop. BOOL MethodNeedsForwardComStub(MethodDesc *pMD, DataImage *pImage) @@ -3762,7 +3763,6 @@ BOOL MethodNeedsForwardComStub(MethodDesc *pMD, DataImage *pImage) return FALSE; } -#ifdef FEATURE_PREJIT //--------------------------------------------------------------------------- // Determines if a method is visible from COM in a way that requires a marshaling // stub, i.e. it allows early binding. diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index e00ebd096222..11d5039210be 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -13177,6 +13177,7 @@ void Module::LoadHelperTable() ClrFlushInstructionCache(table, tableSize); #endif // CROSSGEN_COMPILE } +#endif // FEATURE_PREJIT #ifdef FEATURE_READYTORUN CorInfoHelpFunc MapReadyToRunHelper(ReadyToRunHelper helperNum) @@ -13809,7 +13810,6 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, return TRUE; } -#endif // FEATURE_PREJIT void* CEEInfo::getTailCallCopyArgsThunk(CORINFO_SIG_INFO *pSig, CorInfoHelperTailCallSpecialHandling flags) diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index af42bd29ab8b..4b2fd004aceb 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -83,11 +83,9 @@ void getMethodInfoILMethodHeaderHelper( ); -#ifdef FEATURE_PREJIT BOOL LoadDynamicInfoEntry(Module *currentModule, RVA fixupRva, SIZE_T *entry); -#endif // FEATURE_PREJIT // // The legacy x86 monitor helpers do not need a state argument diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index 34381fa2aad2..27083b0c4078 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -449,6 +449,7 @@ PTR_Module MethodTable::GetModuleIfLoaded() } CONTRACTL_END; +#ifdef FEATURE_PREJIT g_IBCLogger.LogMethodTableAccess(this); MethodTable * pMTForModule = IsArray() ? this : GetCanonicalMethodTable(); @@ -456,6 +457,9 @@ PTR_Module MethodTable::GetModuleIfLoaded() return pMTForModule->GetLoaderModule(); return Module::RestoreModulePointerIfLoaded(pMTForModule->GetModuleOverridePtr(), pMTForModule->GetLoaderModule()); +#else + return GetModule(); +#endif } #ifndef DACCESS_COMPILE @@ -3224,6 +3228,7 @@ void MethodTable::AllocateRegularStaticBoxes() GCPROTECT_BEGININTERIOR(pStaticBase); +#ifdef FEATURE_PREJIT // In ngened case, we have cached array with boxed statics MTs. In JITed case, we have just the FieldDescs ClassCtorInfoEntry *pClassCtorInfoEntry = GetClassCtorInfoIfExists(); if (pClassCtorInfoEntry != NULL) @@ -3237,9 +3242,8 @@ void MethodTable::AllocateRegularStaticBoxes() DWORD numBoxedStatics = pClassCtorInfoEntry->numBoxedStatics; for (DWORD i = 0; i < numBoxedStatics; i++) { -#ifdef FEATURE_PREJIT Module::RestoreMethodTablePointer(&(ppMTs[i]), GetLoaderModule()); -#endif + MethodTable *pFieldMT = ppMTs[i].GetValue(); _ASSERTE(pFieldMT); @@ -3252,6 +3256,7 @@ void MethodTable::AllocateRegularStaticBoxes() GCPROTECT_END(); } else +#endif { // We should never take this codepath in zapped images. _ASSERTE(!IsZapped()); @@ -5661,7 +5666,7 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited, const Module * pModule = GetModule(); // No sanity checks for ready-to-run compiled images if possible - if (pModule->IsReadyToRun() && pModule->GetReadyToRunInfo()->SkipTypeValidation()) + if (pModule->IsSystem() || (pModule->IsReadyToRun() && pModule->GetReadyToRunInfo()->SkipTypeValidation())) fNeedsSanityChecks = false; } #endif @@ -8221,6 +8226,14 @@ DWORD MethodTable::HasFixedAddressVTStatics() return GetClass()->HasFixedAddressVTStatics(); } +//========================================================================================== +BOOL MethodTable::HasOnlyAbstractMethods() +{ + LIMITED_METHOD_CONTRACT; + + return GetClass()->HasOnlyAbstractMethods(); +} + //========================================================================================== WORD MethodTable::GetNumHandleRegularStatics() { @@ -8250,6 +8263,7 @@ ClassCtorInfoEntry* MethodTable::GetClassCtorInfoIfExists() { LIMITED_METHOD_CONTRACT; +#ifdef FEATURE_PREJIT if (!IsZapped()) return NULL; @@ -8292,6 +8306,7 @@ ClassCtorInfoEntry* MethodTable::GetClassCtorInfoIfExists() } } } +#endif // FEATURE_PREJIT return NULL; } @@ -8976,7 +8991,7 @@ void MethodTable::CheckInitMethodDataCache() if (s_pMethodDataCache == NULL) { UINT32 cb = MethodDataCache::GetObjectSize(8); - NewHolder hb(new BYTE[cb]); + NewArrayHolder hb(new BYTE[cb]); MethodDataCache *pCache = new (hb.GetValue()) MethodDataCache(8); if (InterlockedCompareExchangeT( &s_pMethodDataCache, pCache, NULL) == NULL) @@ -9085,7 +9100,7 @@ MethodTable::GetMethodDataHelper( MethodDataWrapper hImpl(GetMethodData(pMTImpl, FALSE)); UINT32 cb = MethodDataInterfaceImpl::GetObjectSize(pMTDecl); - NewHolder pb(new BYTE[cb]); + NewArrayHolder pb(new BYTE[cb]); MethodDataInterfaceImpl * pData = new (pb.GetValue()) MethodDataInterfaceImpl(rgDeclTypeIDs, cDeclTypeIDs, hDecl, hImpl); pb.SuppressRelease(); @@ -9128,7 +9143,7 @@ MethodTable::MethodData *MethodTable::GetMethodDataHelper(MethodTable *pMTDecl, } else { UINT32 cb = MethodDataObject::GetObjectSize(pMTDecl); - NewHolder pb(new BYTE[cb]); + NewArrayHolder pb(new BYTE[cb]); MethodDataHolder h(FindParentMethodDataHelper(pMTDecl)); pData = new (pb.GetValue()) MethodDataObject(pMTDecl, h.GetValue()); pb.SuppressRelease(); diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h index 74febebc39bc..18cca3f6a12e 100644 --- a/src/vm/methodtable.h +++ b/src/vm/methodtable.h @@ -1929,6 +1929,9 @@ class MethodTable bool IsHFA(); #endif // FEATURE_HFA + // Returns the size in bytes of this type if it is a HW vector type; 0 otherwise. + int GetVectorSize(); + // Get the HFA type. This is supported both with FEATURE_HFA, in which case it // depends on the cached bit on the class, or without, in which case it is recomputed // for each invocation. @@ -2572,6 +2575,9 @@ class MethodTable DWORD HasFixedAddressVTStatics(); + // Indicates if the MethodTable only contains abstract methods + BOOL HasOnlyAbstractMethods(); + //------------------------------------------------------------------- // PER-INSTANTIATION STATICS INFO // diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index 286cd74c0a27..53ba9ce3777d 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -1390,7 +1390,7 @@ MethodTableBuilder::BuildMethodTableThrowing( #endif // _DEBUG // If this is mscorlib, then don't perform some sanity checks on the layout - bmtProp->fNoSanityChecks = ((g_pObjectClass == NULL) || pModule == g_pObjectClass->GetModule()) || + bmtProp->fNoSanityChecks = pModule->IsSystem() || #ifdef FEATURE_READYTORUN // No sanity checks for ready-to-run compiled images if possible (pModule->IsReadyToRun() && pModule->GetReadyToRunInfo()->SkipTypeValidation()) || @@ -3230,6 +3230,11 @@ MethodTableBuilder::EnumerateClassMethods() } } + if (bmtMethod->dwNumDeclaredNonAbstractMethods == 0) + { + GetHalfBakedClass()->SetHasOnlyAbstractMethods(); + } + // Check to see that we have all of the required delegate methods (ECMA 13.6 Delegates) if (IsDelegate()) { diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp index 2e675fde2a97..5a013407043c 100644 --- a/src/vm/mlinfo.cpp +++ b/src/vm/mlinfo.cpp @@ -1652,7 +1652,19 @@ MarshalInfo::MarshalInfo(Module* pModule, } else { - mtype = sig.PeekElemTypeClosed(pModule, pTypeContext); + SigPointer sigtmp = sig; + CorElementType closedElemType = sigtmp.PeekElemTypeClosed(pModule, pTypeContext); + if (closedElemType == ELEMENT_TYPE_VALUETYPE) + { + TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext); + // If the return type of an instance method is a value-type we need the actual return type. + // However, if the return type is an enum, we can normalize it. + if (!th.IsEnum()) + { + mtype = closedElemType; + } + } + } #endif // _TARGET_X86_ @@ -2311,7 +2323,7 @@ MarshalInfo::MarshalInfo(Module* pModule, case NATIVE_TYPE_DEFAULT: #ifdef FEATURE_COMINTEROP - if (m_ms == MARSHAL_SCENARIO_WINRT) + if (m_ms == MARSHAL_SCENARIO_WINRT || m_pMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(m_pMT)) { m_type = MARSHAL_TYPE_INTERFACE; } diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index d2a0ad61fdc9..ec96d5e79115 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -114,13 +114,11 @@ DEFINE_FIELD_U(_publicKeyToken, AssemblyNameBaseObject, _publicKeyTok DEFINE_FIELD_U(_cultureInfo, AssemblyNameBaseObject, _cultureInfo) DEFINE_FIELD_U(_codeBase, AssemblyNameBaseObject, _codeBase) DEFINE_FIELD_U(_version, AssemblyNameBaseObject, _version) -DEFINE_FIELD_U(_hashForControl, AssemblyNameBaseObject, _hashForControl) DEFINE_FIELD_U(_hashAlgorithm, AssemblyNameBaseObject, _hashAlgorithm) -DEFINE_FIELD_U(_hashAlgorithmForControl, AssemblyNameBaseObject, _hashAlgorithmForControl) DEFINE_FIELD_U(_versionCompatibility, AssemblyNameBaseObject, _versionCompatibility) DEFINE_FIELD_U(_flags, AssemblyNameBaseObject, _flags) DEFINE_CLASS(ASSEMBLY_NAME, Reflection, AssemblyName) -DEFINE_METHOD(ASSEMBLY_NAME, INIT, Init, IM_Str_ArrB_ArrB_Ver_CI_AHA_AVC_Str_ANF_SNKP_RetV) +DEFINE_METHOD(ASSEMBLY_NAME, CTOR, .ctor, IM_Str_ArrB_ArrB_Ver_CI_AHA_AVC_Str_ANF_SNKP_RetV) DEFINE_METHOD(ASSEMBLY_NAME, SET_PROC_ARCH_INDEX, SetProcArchIndex, IM_PEK_IFM_RetV) DEFINE_CLASS_U(System, Version, VersionBaseObject) @@ -889,6 +887,16 @@ DEFINE_METHOD(UNHANDLED_EVENTARGS, CTOR, .ctor, DEFINE_CLASS(FIRSTCHANCE_EVENTARGS, ExceptionServices, FirstChanceExceptionEventArgs) DEFINE_METHOD(FIRSTCHANCE_EVENTARGS, CTOR, .ctor, IM_Exception_RetVoid) +DEFINE_CLASS_U(Loader, AssemblyLoadContext, AssemblyLoadContextBaseObject) +DEFINE_FIELD_U(_unloadLock, AssemblyLoadContextBaseObject, _unloadLock) +DEFINE_FIELD_U(_resolvingUnmanagedDll, AssemblyLoadContextBaseObject, _resovlingUnmanagedDll) +DEFINE_FIELD_U(_resolving, AssemblyLoadContextBaseObject, _resolving) +DEFINE_FIELD_U(_unloading, AssemblyLoadContextBaseObject, _unloading) +DEFINE_FIELD_U(_name, AssemblyLoadContextBaseObject, _name) +DEFINE_FIELD_U(_nativeAssemblyLoadContext, AssemblyLoadContextBaseObject, _nativeAssemblyLoadContext) +DEFINE_FIELD_U(_id, AssemblyLoadContextBaseObject, _id) +DEFINE_FIELD_U(_state, AssemblyLoadContextBaseObject, _state) +DEFINE_FIELD_U(_isCollectible, AssemblyLoadContextBaseObject, _isCollectible) DEFINE_CLASS(ASSEMBLYLOADCONTEXT, Loader, AssemblyLoadContext) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVE, Resolve, SM_IntPtr_AssemblyName_RetAssemblyBase) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVEUNMANAGEDDLL, ResolveUnmanagedDll, SM_Str_IntPtr_RetIntPtr) diff --git a/src/vm/object.h b/src/vm/object.h index 590f1e0618fe..173036d24987 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -1610,6 +1610,53 @@ class AssemblyBaseObject : public Object NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive); #define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive)) +// AssemblyLoadContextBaseObject +// This class is the base class for AssemblyLoadContext +// +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) +#include "pshpack4.h" +#endif // defined(_TARGET_X86_) && !defined(FEATURE_PAL) +class AssemblyLoadContextBaseObject : public Object +{ + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. +#ifdef _TARGET_64BIT_ + OBJECTREF _unloadLock; + OBJECTREF _resovlingUnmanagedDll; + OBJECTREF _resolving; + OBJECTREF _unloading; + OBJECTREF _name; + INT_PTR _nativeAssemblyLoadContext; + int64_t _id; // On 64-bit platforms this is a value type so it is placed after references and pointers + DWORD _state; + CLR_BOOL _isCollectible; +#else // _TARGET_64BIT_ + int64_t _id; // On 32-bit platforms this 64-bit value type is larger than a pointer so JIT places it first + OBJECTREF _unloadLock; + OBJECTREF _resovlingUnmanagedDll; + OBJECTREF _resolving; + OBJECTREF _unloading; + OBJECTREF _name; + INT_PTR _nativeAssemblyLoadContext; + DWORD _state; + CLR_BOOL _isCollectible; +#endif // _TARGET_64BIT_ + + protected: + AssemblyLoadContextBaseObject() { LIMITED_METHOD_CONTRACT; } + ~AssemblyLoadContextBaseObject() { LIMITED_METHOD_CONTRACT; } + + public: + INT_PTR GetNativeAssemblyLoadContext() { LIMITED_METHOD_CONTRACT; return _nativeAssemblyLoadContext; } +}; +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) +#include "poppack.h" +#endif // defined(_TARGET_X86_) && !defined(FEATURE_PAL) + // AssemblyNameBaseObject // This class is the base class for assembly names // @@ -1631,9 +1678,7 @@ class AssemblyNameBaseObject : public Object OBJECTREF _codeBase; OBJECTREF _version; OBJECTREF _strongNameKeyPair; - U1ARRAYREF _hashForControl; DWORD _hashAlgorithm; - DWORD _hashAlgorithmForControl; DWORD _versionCompatibility; DWORD _flags; @@ -1651,8 +1696,6 @@ class AssemblyNameBaseObject : public Object OBJECTREF GetVersion() { LIMITED_METHOD_CONTRACT; return _version; } DWORD GetAssemblyHashAlgorithm() { LIMITED_METHOD_CONTRACT; return _hashAlgorithm; } DWORD GetFlags() { LIMITED_METHOD_CONTRACT; return _flags; } - U1ARRAYREF GetHashForControl() { LIMITED_METHOD_CONTRACT; return _hashForControl;} - DWORD GetHashAlgorithmForControl() { LIMITED_METHOD_CONTRACT; return _hashAlgorithmForControl; } }; // VersionBaseObject @@ -1700,12 +1743,12 @@ typedef REF REFLECTFIELDREF; typedef REF THREADBASEREF; -typedef REF APPDOMAINREF; - typedef REF MARSHALBYREFOBJECTBASEREF; typedef REF ASSEMBLYREF; +typedef REF ASSEMBLYLOADCONTEXTREF; + typedef REF ASSEMBLYNAMEREF; typedef REF VERSIONREF; @@ -1753,6 +1796,7 @@ typedef PTR_ReflectMethodObject REFLECTMETHODREF; typedef PTR_ReflectFieldObject REFLECTFIELDREF; typedef PTR_ThreadBaseObject THREADBASEREF; typedef PTR_AssemblyBaseObject ASSEMBLYREF; +typedef PTR_AssemblyLoadContextBaseObject ASSEMBLYLOADCONTEXTREF; typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; #ifndef DACCESS_COMPILE diff --git a/src/vm/pefile.cpp b/src/vm/pefile.cpp index 9f3c358e1671..f0a44d862db3 100644 --- a/src/vm/pefile.cpp +++ b/src/vm/pefile.cpp @@ -1111,9 +1111,6 @@ LPCWSTR CorCompileGetRuntimeDllName(CorCompileRuntimeDlls id) // Will always return a valid HMODULE for CLR_INFO, but will return NULL for NGEN_COMPILER_INFO // if the DLL has not yet been loaded (it does not try to cause a load). -// Gets set by IJitManager::LoadJit (yes, this breaks the abstraction boundary). -HMODULE s_ngenCompilerDll = NULL; - extern HMODULE CorCompileGetRuntimeDll(CorCompileRuntimeDlls id) { CONTRACTL @@ -1905,6 +1902,7 @@ PEAssembly::PEAssembly( if (system) m_flags |= PEFILE_SYSTEM; +#ifdef FEATURE_PREJIT // We check the precondition above that either pBindResultInfo is null or both pPEImageIL and pPEImageNI are, // so we'll only get a max of one native image passed in. if (pPEImageNI != NULL) @@ -1912,7 +1910,6 @@ PEAssembly::PEAssembly( SetNativeImage(pPEImageNI); } -#ifdef FEATURE_PREJIT if (pBindResultInfo && pBindResultInfo->HasNativeImage()) SetNativeImage(pBindResultInfo->GetNativeImage()); #endif diff --git a/src/vm/peimage.cpp b/src/vm/peimage.cpp index ac894b2a5dc7..a79a33b62014 100644 --- a/src/vm/peimage.cpp +++ b/src/vm/peimage.cpp @@ -123,6 +123,7 @@ CHECK PEImage::CheckILFormat() pLayoutToCheck = pLayoutHolder; } +#ifdef FEATURE_PREJIT if (PEFile::ShouldTreatNIAsMSIL()) { // This PEImage may intentionally be an NI image, being used as if it were an @@ -132,6 +133,7 @@ CHECK PEImage::CheckILFormat() CHECK(pLayoutToCheck->CheckCORFormat()); } else +#endif { CHECK(pLayoutToCheck->CheckILFormat()); } @@ -450,7 +452,6 @@ IMDInternalImport* PEImage::GetMDImport() return m_pMDImport; } -#ifdef FEATURE_PREJIT IMDInternalImport* PEImage::GetNativeMDImport(BOOL loadAllowed) { CONTRACTL @@ -508,7 +509,6 @@ void PEImage::OpenNativeMDImport() } _ASSERTE(m_pNativeMDImport); } -#endif void PEImage::OpenMDImport() { @@ -673,6 +673,7 @@ void PEImage::VerifyIsILOrNIAssembly(BOOL fIL) ThrowFormat(COR_E_ASSEMBLYEXPECTED); CHECK checkGoodFormat; +#ifdef FEATURE_PREJIT if (fIL) { checkGoodFormat = CheckILFormat(); @@ -681,6 +682,9 @@ void PEImage::VerifyIsILOrNIAssembly(BOOL fIL) { checkGoodFormat = CheckNativeFormat(); } +#else + checkGoodFormat = CheckILFormat(); +#endif if (!checkGoodFormat) ThrowFormat(COR_E_BADIMAGEFORMAT); @@ -948,7 +952,6 @@ void PEImage::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) PEImage::PEImage(): m_refCount(1), m_bIsTrustedNativeImage(FALSE), - m_bIsNativeImageInstall(FALSE), m_bPassiveDomainOnly(FALSE), m_bInHashMap(FALSE), #ifdef METADATATRACKER_DATA @@ -1211,7 +1214,7 @@ PTR_PEImage PEImage::LoadImage(HMODULE hMod) StackSString path; GetPathFromDll(hMod, path); - PEImageHolder pImage(PEImage::OpenImage(path,(MDInternalImportFlags)(MDInternalImport_CheckLongPath|MDInternalImport_CheckShortPath))); + PEImageHolder pImage(PEImage::OpenImage(path,(MDInternalImportFlags)(0))); if (pImage->HasLoadedLayout()) RETURN dac_cast(pImage.Extract()); diff --git a/src/vm/peimage.h b/src/vm/peimage.h index 5cfd160e1b41..45452160bf37 100644 --- a/src/vm/peimage.h +++ b/src/vm/peimage.h @@ -189,8 +189,6 @@ class PEImage static BOOL PathEquals(const SString &p1, const SString &p2); BOOL IsTrustedNativeImage(){LIMITED_METHOD_CONTRACT; return m_bIsTrustedNativeImage;}; void SetIsTrustedNativeImage(){LIMITED_METHOD_CONTRACT; m_bIsTrustedNativeImage=TRUE;}; - BOOL IsNativeImageInstall(){LIMITED_METHOD_CONTRACT; return m_bIsNativeImageInstall;} - void SetIsNativeImageInstall(){LIMITED_METHOD_CONTRACT; m_bIsNativeImageInstall=TRUE;}; void SetModuleFileNameHintForDAC(); #ifdef DACCESS_COMPILE @@ -208,8 +206,8 @@ class PEImage BOOL IsNativeILILOnly(); BOOL IsNativeILDll(); void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine); - PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL); #endif + PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL); BOOL HasDirectoryEntry(int entry); mdToken GetEntryPointToken(); DWORD GetCorHeaderFlags(); @@ -293,7 +291,6 @@ class PEImage SString m_sModuleFileNameHintUsedByDac; // This is only used by DAC private: BOOL m_bIsTrustedNativeImage; - BOOL m_bIsNativeImageInstall; BOOL m_bPassiveDomainOnly; #ifdef FEATURE_LAZY_COW_PAGES BOOL m_bAllocatedLazyCOWPages; diff --git a/src/vm/peimage.inl b/src/vm/peimage.inl index 156dae67d6d7..142012ea54d2 100644 --- a/src/vm/peimage.inl +++ b/src/vm/peimage.inl @@ -388,7 +388,6 @@ inline BOOL PEImage::IsIbcOptimized() #endif } -#ifdef FEATURE_PREJIT inline PTR_CVOID PEImage::GetNativeManifestMetadata(COUNT_T *pSize) { WRAPPER_NO_CONTRACT; @@ -400,7 +399,6 @@ inline PTR_CVOID PEImage::GetNativeManifestMetadata(COUNT_T *pSize) return pLayout->GetNativeManifestMetadata(pSize); } } -#endif inline PTR_CVOID PEImage::GetMetadata(COUNT_T *pSize) { @@ -532,8 +530,6 @@ inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags #ifdef FEATURE_PREJIT if (flags & MDInternalImport_TrustedNativeImage) pImage->SetIsTrustedNativeImage(); - if (flags & MDInternalImport_NativeImageInstall) - pImage->SetIsNativeImageInstall(); #endif pImage->Init(pPath); diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index c63e39933256..4adf32ede19e 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -2447,7 +2447,7 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl } -#if !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) +#if !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) && defined(FEATURE_PREJIT) //========================================================================================== // In NGen image, virtual slots inherited from cross-module dependencies point to jump thunks. @@ -2504,7 +2504,7 @@ EXTERN_C PCODE VirtualMethodFixupWorker(Object * pThisPtr, CORCOMPILE_VIRTUAL_I #endif return pCode; } -#endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) +#endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) && defined(FEATURE_PREJIT) #ifdef FEATURE_READYTORUN diff --git a/src/vm/qcall.cpp b/src/vm/qcall.cpp index 3b35f9089f24..1b7bbda3b74e 100644 --- a/src/vm/qcall.cpp +++ b/src/vm/qcall.cpp @@ -76,25 +76,3 @@ void QCall::ObjectHandleOnStack::SetGuidArray(const GUID * p, COUNT_T length) memcpyNoGCRefs(arr->GetDataPtr(), p, length * sizeof(GUID)); Set(arr); } - -// -// Helpers for passing an AppDomain to a QCall -// - -#ifdef _DEBUG - -//--------------------------------------------------------------------------------------- -// -// Verify that the AppDomain being passed from the BCL is valid for use in a QCall. Note: some additional -// checks are in System.AppDomain.GetNativeHandle() -// - -void QCall::AppDomainHandle::VerifyDomainHandle() const -{ - LIMITED_METHOD_CONTRACT; - - // System.AppDomain.GetNativeHandle() should ensure that we're not calling through with a null AppDomain pointer. - _ASSERTE(m_pAppDomain); -} - -#endif // _DEBUG diff --git a/src/vm/qcall.h b/src/vm/qcall.h index 3ad328a2e1ae..dd60bbb158c2 100644 --- a/src/vm/qcall.h +++ b/src/vm/qcall.h @@ -237,35 +237,6 @@ class QCall } }; - // AppDomainHandle is used for passing AppDomains into QCalls via System.AppDomainHandle - struct AppDomainHandle - { - AppDomain *m_pAppDomain; - - operator AppDomain *() - { - LIMITED_METHOD_CONTRACT; -#ifdef _DEBUG - VerifyDomainHandle(); -#endif // _DEBUG - return m_pAppDomain; - } - - AppDomain *operator->() const - { - LIMITED_METHOD_CONTRACT; -#ifdef _DEBUG - VerifyDomainHandle(); -#endif // _DEBUG - return m_pAppDomain; - } - - private: -#ifdef _DEBUG - void VerifyDomainHandle() const; -#endif // _DEBUG - }; - struct AssemblyHandle { DomainAssembly * m_pAssembly; diff --git a/src/vm/readytoruninfo.h b/src/vm/readytoruninfo.h index 56331377a28b..1ccd239ca50e 100644 --- a/src/vm/readytoruninfo.h +++ b/src/vm/readytoruninfo.h @@ -17,10 +17,6 @@ typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; -#ifndef FEATURE_PREJIT -typedef DPTR(struct READYTORUN_IMPORT_SECTION) PTR_CORCOMPILE_IMPORT_SECTION; -#endif - class PrepareCodeConfig; typedef DPTR(class ReadyToRunInfo) PTR_ReadyToRunInfo; diff --git a/src/vm/runtimecallablewrapper.cpp b/src/vm/runtimecallablewrapper.cpp index 540536ef5f5b..26c2a5cd5dbc 100644 --- a/src/vm/runtimecallablewrapper.cpp +++ b/src/vm/runtimecallablewrapper.cpp @@ -242,6 +242,12 @@ IUnknown *ComClassFactory::CreateInstanceFromClassFactory(IClassFactory *pClassF ThrowHRMsg(hr, IDS_EE_CREATEINSTANCE_LIC_FAILED); } + // If the activated COM class has a CCW, mark the + // CCW as being activated via COM. + ComCallWrapper *ccw = GetCCWFromIUnknown(pUnk); + if (ccw != NULL) + ccw->MarkComActivated(); + pUnk.SuppressRelease(); RETURN pUnk; } diff --git a/src/vm/runtimehandles.cpp b/src/vm/runtimehandles.cpp index c25bcbf3fe19..620886e8142b 100644 --- a/src/vm/runtimehandles.cpp +++ b/src/vm/runtimehandles.cpp @@ -1415,7 +1415,7 @@ void QCALLTYPE RuntimeTypeHandle::GetTypeByNameUsingCARules(LPCWSTR pwzClassName void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::StackCrawlMarkHandle pStackMark, - ICLRPrivBinder * pPrivHostBinder, + QCall::ObjectHandleOnStack pAssemblyLoadContext, BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive) { @@ -1429,6 +1429,19 @@ void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThro COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String")); { + ICLRPrivBinder * pPrivHostBinder = NULL; + + if (*pAssemblyLoadContext.m_ppObject != NULL) + { + GCX_COOP(); + ASSEMBLYLOADCONTEXTREF * pAssemblyLoadContextRef = reinterpret_cast(pAssemblyLoadContext.m_ppObject); + + INT_PTR nativeAssemblyLoadContext = (*pAssemblyLoadContextRef)->GetNativeAssemblyLoadContext(); + + pPrivHostBinder = reinterpret_cast(nativeAssemblyLoadContext); + } + + typeHandle = TypeName::GetTypeManaged(pwzClassName, NULL, bThrowOnError, bIgnoreCase, /*bProhibitAsmQualifiedName =*/ FALSE, SystemDomain::GetCallersAssembly(pStackMark), bLoadTypeFromPartialNameHack, (OBJECTREF*)keepAlive.m_ppObject, @@ -3020,7 +3033,7 @@ FCIMPL5(ReflectMethodObject*, ModuleHandle::GetDynamicMethod, ReflectMethodObjec U1ARRAYREF dataArray = (U1ARRAYREF)sig; DWORD sigSize = dataArray->GetNumComponents(); - NewHolder pSig(new BYTE[sigSize]); + NewArrayHolder pSig(new BYTE[sigSize]); memcpy(pSig, dataArray->GetDataPtr(), sigSize); DWORD length = gc.nameRef->GetStringLength(); diff --git a/src/vm/runtimehandles.h b/src/vm/runtimehandles.h index 4c2ebdf52ddc..c83461a8a52e 100644 --- a/src/vm/runtimehandles.h +++ b/src/vm/runtimehandles.h @@ -177,7 +177,7 @@ class RuntimeTypeHandle { static void QCALLTYPE GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::StackCrawlMarkHandle pStackMark, - ICLRPrivBinder * pPrivHostBinder, + QCall::ObjectHandleOnStack pAssemblyLoadContext, BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive); diff --git a/src/vm/stdinterfaces.cpp b/src/vm/stdinterfaces.cpp index 15da1c8c2210..e050f2f66b70 100644 --- a/src/vm/stdinterfaces.cpp +++ b/src/vm/stdinterfaces.cpp @@ -198,7 +198,18 @@ Unknown_QueryInterface_Internal(ComCallWrapper* pWrap, IUnknown* pUnk, REFIID ri // If we haven't found the IP or if we haven't looked yet (because we aren't // being aggregated), now look on the managed object to see if it supports the interface. if (pDestItf == NULL) - pDestItf = ComCallWrapper::GetComIPFromCCW(pWrap, riid, NULL, GetComIPFromCCW::CheckVisibility); + { + EX_TRY + { + pDestItf = ComCallWrapper::GetComIPFromCCW(pWrap, riid, NULL, GetComIPFromCCW::CheckVisibility); + } + EX_CATCH + { + Exception *e = GET_EXCEPTION(); + hr = e->GetHR(); + } + EX_END_CATCH(RethrowTerminalExceptions) + } ErrExit: // If we succeeded in obtaining the requested IP then return S_OK. diff --git a/src/vm/stubmgr.cpp b/src/vm/stubmgr.cpp index 17d262c0589e..a18792d76efb 100644 --- a/src/vm/stubmgr.cpp +++ b/src/vm/stubmgr.cpp @@ -1467,7 +1467,6 @@ BOOL RangeSectionStubManager::DoTraceStub(PCODE stubStartAddress, TraceDestinati } return TRUE; } -#endif case STUB_CODE_BLOCK_EXTERNAL_METHOD_THUNK: { @@ -1481,6 +1480,7 @@ BOOL RangeSectionStubManager::DoTraceStub(PCODE stubStartAddress, TraceDestinati } __fallthrough; +#endif case STUB_CODE_BLOCK_METHOD_CALL_THUNK: #ifdef DACCESS_COMPILE @@ -2528,7 +2528,6 @@ JumpStubStubManager::DoEnumMemoryRegions(CLRDataEnumMemoryFlags flags) EMEM_OUT(("MEM: %p JumpStubStubManager\n", dac_cast(this))); } -#ifdef FEATURE_PREJIT void RangeSectionStubManager::DoEnumMemoryRegions(CLRDataEnumMemoryFlags flags) { @@ -2537,7 +2536,6 @@ RangeSectionStubManager::DoEnumMemoryRegions(CLRDataEnumMemoryFlags flags) DAC_ENUM_VTHIS(); EMEM_OUT(("MEM: %p RangeSectionStubManager\n", dac_cast(this))); } -#endif void ILStubManager::DoEnumMemoryRegions(CLRDataEnumMemoryFlags flags) diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 6890290caaf8..70c26118ea15 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -451,7 +451,7 @@ void Thread::ChooseThreadCPUGroupAffinity() GC_TRIGGERS; } CONTRACTL_END; - +#ifndef FEATURE_PAL if (!CPUGroupInfo::CanEnableGCCPUGroups() || !CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) return; @@ -471,6 +471,7 @@ void Thread::ChooseThreadCPUGroupAffinity() CPUGroupInfo::SetThreadGroupAffinity(GetThreadHandle(), &groupAffinity, NULL); m_wCPUGroup = groupAffinity.Group; m_pAffinityMask = groupAffinity.Mask; +#endif // !FEATURE_PAL } void Thread::ClearThreadCPUGroupAffinity() @@ -481,7 +482,7 @@ void Thread::ClearThreadCPUGroupAffinity() GC_NOTRIGGER; } CONTRACTL_END; - +#ifndef FEATURE_PAL if (!CPUGroupInfo::CanEnableGCCPUGroups() || !CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) return; @@ -499,6 +500,7 @@ void Thread::ClearThreadCPUGroupAffinity() m_wCPUGroup = 0; m_pAffinityMask = 0; +#endif // !FEATURE_PAL } DWORD Thread::StartThread() @@ -1561,8 +1563,10 @@ Thread::Thread() m_fGCSpecial = FALSE; +#ifndef FEATURE_PAL m_wCPUGroup = 0; m_pAffinityMask = 0; +#endif // !FEATURE_PAL m_pAllLoggedTypes = NULL; @@ -5209,12 +5213,6 @@ DEBUG_NOINLINE void ThreadStore::Enter() ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT; CHECK_ONE_STORE(); m_Crst.Enter(); - - // Threadstore needs special shutdown handling. - if (g_fSuspendOnShutdown) - { - m_Crst.ReleaseAndBlockForShutdownIfNotSpecialThread(); - } } DEBUG_NOINLINE void ThreadStore::Leave() diff --git a/src/vm/threads.h b/src/vm/threads.h index 94ce27560405..e5307d9a5dd5 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -4824,9 +4824,10 @@ class Thread: public IUnknown void SetGCSpecial(bool fGCSpecial); private: +#ifndef FEATURE_PAL WORD m_wCPUGroup; DWORD_PTR m_pAffinityMask; - +#endif // !FEATURE_PAL public: void ChooseThreadCPUGroupAffinity(); void ClearThreadCPUGroupAffinity(); diff --git a/src/vm/threadstatics.cpp b/src/vm/threadstatics.cpp index 562ac8bf5365..999c1210f19d 100644 --- a/src/vm/threadstatics.cpp +++ b/src/vm/threadstatics.cpp @@ -647,7 +647,7 @@ PTR_ThreadLocalModule ThreadStatics::AllocateAndInitTLM(ModuleIndex index, PTR_T _ASSERTE(pThreadLocalBlock != NULL); _ASSERTE(pModule != NULL); - NewHolder pThreadLocalModule = AllocateTLM(pModule); + NewArrayHolder pThreadLocalModule = AllocateTLM(pModule); pThreadLocalBlock->AllocateThreadStaticHandles(pModule, pThreadLocalModule); diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index 1fee3b760c70..9760fe4293e7 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -1356,7 +1356,6 @@ Thread::UserAbort(ThreadAbortRequester requester, case eExitProcess: case eFastExitProcess: case eRudeExitProcess: - case eDisableRuntime: GetEEPolicy()->NotifyHostOnDefaultAction(operation,action); EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_THREADABORT); _ASSERTE (!"Should not reach here"); @@ -1986,7 +1985,6 @@ Thread::UserAbort(ThreadAbortRequester requester, case eExitProcess: case eFastExitProcess: case eRudeExitProcess: - case eDisableRuntime: GetEEPolicy()->NotifyHostOnTimeout(operation1, action1); EEPolicy::HandleExitProcessFromEscalation(action1, HOST_E_EXITPROCESS_TIMEOUT); _ASSERTE (!"Should not reach here"); @@ -2543,9 +2541,8 @@ void Thread::RareDisablePreemptiveGC() // Note IsGCInProgress is also true for say Pause (anywhere SuspendEE happens) and GCThread is the // thread that did the Pause. While in Pause if another thread attempts Rev/Pinvoke it should get inside the following and // block until resume - if (((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || - (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))) && - (!g_fSuspendOnShutdown || IsFinalizerThread() || IsShutdownSpecialThread())) + if ((GCHeapUtilities::IsGCInProgress() && (this != ThreadSuspend::GetSuspensionThread())) || + (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))) { if (!ThreadStore::HoldingThreadStore(this)) { @@ -2653,47 +2650,6 @@ void Thread::RareDisablePreemptiveGC() STRESS_LOG0(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: leaving\n"); } - // Block all threads except finalizer and shutdown thread during shutdown. - // If g_fSuspendFinalizerOnShutdown is set, block the finalizer too. - if ((g_fSuspendOnShutdown && !IsFinalizerThread() && !IsShutdownSpecialThread()) || - (g_fSuspendFinalizerOnShutdown && IsFinalizerThread())) - { - STRESS_LOG1(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: entering. Thread state = %x\n", m_State.Load()); - - EnablePreemptiveGC(); - - // Cannot use GCX_PREEMP_NO_DTOR here because we're inside of the thread - // PREEMP->COOP switch mechanism and GCX_PREEMP's assert's will fire. - // Instead we use BEGIN_GCX_ASSERT_PREEMP to inform Scan of the mode - // change here. - BEGIN_GCX_ASSERT_PREEMP; - -#ifdef PROFILING_SUPPORTED - // If profiler desires GC events, notify it that this thread is waiting until the GC is over - // Do not send suspend notifications for debugger suspensions - { - BEGIN_PIN_PROFILER(CORProfilerTrackSuspends()); - if (!(m_State & TS_DebugSuspendPending)) - { - g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)this); - } - END_PIN_PROFILER(); - } -#endif // PROFILING_SUPPORTED - - - - // The thread is blocked for shutdown. We do not concern for GC violation. - CONTRACT_VIOLATION(GCViolation); - - WaitForEndOfShutdown(); - - END_GCX_ASSERT_PREEMP; - - __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING); - _ASSERTE(!"Cannot reach here"); - } - Exit: ; END_PRESERVE_LAST_ERROR; } @@ -2740,7 +2696,6 @@ void Thread::HandleThreadAbortTimeout() case eExitProcess: case eFastExitProcess: case eRudeExitProcess: - case eDisableRuntime: GetEEPolicy()->NotifyHostOnTimeout(operation,action); EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_THREADABORT); _ASSERTE (!"Should not reach here"); @@ -2844,7 +2799,6 @@ void Thread::PreWorkForThreadAbort() case eExitProcess: case eFastExitProcess: case eRudeExitProcess: - case eDisableRuntime: { GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ThreadRudeAbortInCriticalRegion,action); GetEEPolicy()->HandleExitProcessFromEscalation(action,HOST_E_EXITPROCESS_ADUNLOAD); diff --git a/src/vm/typehash.cpp b/src/vm/typehash.cpp index 552960b916b0..524dd291389d 100644 --- a/src/vm/typehash.cpp +++ b/src/vm/typehash.cpp @@ -523,12 +523,16 @@ BOOL EETypeHashTable::CompareInstantiatedType(TypeHandle t, Module *pModule, mdT // Now check the instantiations. Some type arguments might be encoded. for (DWORD i = 0; i < inst.GetNumArgs(); i++) { +#ifdef FEATURE_PREJIT // Fetch the type handle as TADDR. It may be may be encoded fixup - TypeHandle debug-only validation // asserts on encoded fixups. DACCOP_IGNORE(CastOfMarshalledType, "Dual mode DAC problem, but since the size is the same, the cast is safe"); TADDR candidateArg = ((FixupPointer *)candidateInst.GetRawArgs())[i].GetValue(); if (!ZapSig::CompareTaggedPointerToTypeHandle(GetModule(), candidateArg, inst[i])) +#else + if (candidateInst[i] != inst[i]) +#endif { return FALSE; } @@ -569,8 +573,12 @@ BOOL EETypeHashTable::CompareFnPtrType(TypeHandle t, BYTE callConv, DWORD numArg TypeHandle *retAndArgTypes2 = pTD->GetRetAndArgTypesPointer(); for (DWORD i = 0; i <= numArgs; i++) { +#ifdef FEATURE_PREJIT TADDR candidateArg = retAndArgTypes2[i].AsTAddr(); if (!ZapSig::CompareTaggedPointerToTypeHandle(GetModule(), candidateArg, retAndArgTypes[i])) +#else + if (retAndArgTypes2[i] != retAndArgTypes[i]) +#endif { return FALSE; } diff --git a/src/vm/typeparse.cpp b/src/vm/typeparse.cpp index 858d9a32d3a3..0794454be283 100644 --- a/src/vm/typeparse.cpp +++ b/src/vm/typeparse.cpp @@ -1507,20 +1507,23 @@ DomainAssembly * LoadDomainAssembly( spec.SetWindowsRuntimeType(*pssOuterTypeName); } - if (pPrivHostBinder) - { - spec.SetHostBinder(pPrivHostBinder); - } - else if (pRequestingAssembly && (!pRequestingAssembly->IsCollectible())) + if (pRequestingAssembly) { GCX_PREEMP(); spec.SetParentAssembly(pRequestingAssembly->GetDomainAssembly()); } - // If the requesting assembly has Fallback LoadContext binder available, - // then set it up in the AssemblySpec. - if (pRequestingAssembly != NULL) + // Have we been passed the reference to the binder against which this load should be triggered? + // If so, then use it to set the fallback load context binder. + if (pPrivHostBinder != NULL) + { + spec.SetFallbackLoadContextBinderForRequestingAssembly(pPrivHostBinder); + spec.SetPreferFallbackLoadContextBinder(); + } + else if (pRequestingAssembly != NULL) { + // If the requesting assembly has Fallback LoadContext binder available, + // then set it up in the AssemblySpec. PEFile *pRequestingAssemblyManifestFile = pRequestingAssembly->GetManifestFile(); spec.SetFallbackLoadContextBinderForRequestingAssembly(pRequestingAssemblyManifestFile->GetFallbackLoadContextBinder()); } diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index 2c3d978d022e..e4b790836e1b 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -162,8 +162,7 @@ class OBJECTREF { class ReflectClassBaseObject* m_asReflectClass; class ExecutionContextObject* m_asExecutionContext; - class AppDomainBaseObject* m_asAppDomainBase; - class PermissionSetObject* m_asPermissionSetObject; + class AssemblyLoadContextBaseObject* m_asAssemblyLoadContextBase; }; public: @@ -530,10 +529,6 @@ EXTERN BOOL g_fComStarted; GVAL_DECL(DWORD, g_fEEShutDown); EXTERN DWORD g_fFastExitProcess; EXTERN BOOL g_fFatalErrorOccurredOnGCThread; -#ifndef DACCESS_COMPILE -EXTERN BOOL g_fSuspendOnShutdown; -EXTERN BOOL g_fSuspendFinalizerOnShutdown; -#endif // DACCESS_COMPILE EXTERN Volatile g_fForbidEnterEE; GVAL_DECL(bool, g_fProcessDetach); EXTERN bool g_fManagedAttach; diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 29c1d21c99c0..f340542b0c93 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -345,12 +345,16 @@ BOOL ThreadpoolMgr::Initialize() UnManagedPerAppDomainTPCount* pADTPCount; pADTPCount = PerAppDomainTPCountList::GetUnmanagedTPCount(); +#ifndef FEATURE_PAL //ThreadPool_CPUGroup CPUGroupInfo::EnsureInitialized(); if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) NumberOfProcessors = CPUGroupInfo::GetNumActiveProcessors(); else NumberOfProcessors = GetCurrentProcessCpuCount(); +#else // !FEATURE_PAL + NumberOfProcessors = GetCurrentProcessCpuCount(); +#endif // !FEATURE_PAL InitPlatformVariables(); EX_TRY @@ -380,20 +384,15 @@ BOOL ThreadpoolMgr::Initialize() RetiredWorkerSemaphore = new CLRLifoSemaphore(); RetiredWorkerSemaphore->Create(0, ThreadCounter::MaxPossibleCount); +#ifndef FEATURE_PAL //ThreadPool_CPUGroup if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) RecycledLists.Initialize( CPUGroupInfo::GetNumActiveProcessors() ); else RecycledLists.Initialize( g_SystemInfo.dwNumberOfProcessors ); - /* - { - SYSTEM_INFO sysInfo; - - ::GetSystemInfo( &sysInfo ); - - RecycledLists.Initialize( sysInfo.dwNumberOfProcessors ); - } - */ +#else // !FEATURE_PAL + RecycledLists.Initialize( PAL_GetTotalCpuCount() ); +#endif // !FEATURE_PAL } EX_CATCH { @@ -405,7 +404,7 @@ BOOL ThreadpoolMgr::Initialize() RetiredCPWakeupEvent = NULL; } - // Note: It is fine to call Destroy on unitialized critical sections + // Note: It is fine to call Destroy on uninitialized critical sections WorkerCriticalSection.Destroy(); WaitThreadsCriticalSection.Destroy(); TimerQueueCriticalSection.Destroy(); @@ -3095,12 +3094,7 @@ void ThreadpoolMgr::DeregisterWait(WaitInfo* pArgs) if (InterlockedDecrement(&waitInfo->refCount) == 0) { - // After we suspend EE during shutdown, a thread may be blocked in WaitForEndOfShutdown in alertable state. - // We don't allow a thread reenter runtime while processing APC or pumping message. - if (!g_fSuspendOnShutdown ) - { - DeleteWait(waitInfo); - } + DeleteWait(waitInfo); } return; } @@ -4095,9 +4089,10 @@ DWORD WINAPI ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) return 0; } +#ifndef FEATURE_PAL //GateThread can start before EESetup, so ensure CPU group information is initialized; CPUGroupInfo::EnsureInitialized(); - +#endif // !FEATURE_PAL // initialize CPU usage information structure; prevCPUInfo.idleTime.QuadPart = 0; prevCPUInfo.kernelTime.QuadPart = 0; diff --git a/src/vm/win32threadpool.h b/src/vm/win32threadpool.h index bb6ebc06130a..55f321c37f50 100644 --- a/src/vm/win32threadpool.h +++ b/src/vm/win32threadpool.h @@ -735,12 +735,22 @@ class ThreadpoolMgr { LIMITED_METHOD_CONTRACT; + DWORD processorNumber = 0; + +#ifndef FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) - return pRecycledListPerProcessor[CPUGroupInfo::CalculateCurrentProcessorNumber()][memType]; + processorNumber = CPUGroupInfo::CalculateCurrentProcessorNumber(); else // Turns out GetCurrentProcessorNumber can return a value greater than the number of processors reported by // GetSystemInfo, if we're running in WOW64 on a machine with >32 processors. - return pRecycledListPerProcessor[GetCurrentProcessorNumber()%NumberOfProcessors][memType]; + processorNumber = GetCurrentProcessorNumber()%NumberOfProcessors; +#else // !FEATURE_PAL + if (PAL_HasGetCurrentProcessorNumber()) + { + processorNumber = GetCurrentProcessorNumber(); + } +#endif // !FEATURE_PAL + return pRecycledListPerProcessor[processorNumber][memType]; } }; diff --git a/src/vm/winrthelpers.cpp b/src/vm/winrthelpers.cpp index a034fb542d05..531673eb2823 100644 --- a/src/vm/winrthelpers.cpp +++ b/src/vm/winrthelpers.cpp @@ -146,10 +146,9 @@ GetBindableWinRTName( // Therefore we do not have to use file name to create fake type name IfFailRet(GetFirstWinRTTypeDef(pMDInternalImport, &szNameSpace, &szTypeName, NULL, NULL)); - DWORD dwSize = MAX_PATH_FNAME; WCHAR wzAsmName[MAX_PATH_FNAME]; + DWORD dwSize = sizeof(wzAsmName); - dwSize = MAX_PATH_FNAME * sizeof(WCHAR); IfFailRet(pIAssemblyName->GetProperty(ASM_NAME_NAME, wzAsmName, &dwSize)); StackSString sNamespaceAndType(wzAsmName); diff --git a/src/vm/zapsig.cpp b/src/vm/zapsig.cpp index 4db83ec4b073..73cc604a8f92 100644 --- a/src/vm/zapsig.cpp +++ b/src/vm/zapsig.cpp @@ -11,7 +11,6 @@ #include "common.h" -#ifdef FEATURE_PREJIT #include "zapsig.h" #include "typedesc.h" #include "compile.h" @@ -566,6 +565,7 @@ BOOL ZapSig::GetSignatureForTypeHandle(TypeHandle handle, RETURN(TRUE); } +#ifdef FEATURE_PREJIT /*static*/ BOOL ZapSig::CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle) { @@ -588,6 +588,7 @@ BOOL ZapSig::CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle ZapSig::Context zapSigContext(pDefiningModule, pModule); return ZapSig::CompareSignatureToTypeHandle(pSig, pDefiningModule, handle, &zapSigContext); } +#endif // FEATURE_PREJIT /*static*/ BOOL ZapSig::CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2) @@ -607,6 +608,7 @@ BOOL ZapSig::CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle // Ensure that the compiler won't fetch the value twice SIZE_T fixup = VolatileLoadWithoutBarrier((SIZE_T *)pTypeHnd); +#ifdef FEATURE_PREJIT if (CORCOMPILE_IS_POINTER_TAGGED(fixup)) { Module *pContainingModule = ExecutionManager::FindZapModule(dac_cast(pTypeHnd)); @@ -624,6 +626,7 @@ BOOL ZapSig::CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle } } else +#endif // FEATURE_PREJIT return TypeHandle::FromTAddr(fixup) == typeHnd2; } @@ -1532,5 +1535,3 @@ void ZapSig::EncodeField( } #endif // DACCESS_COMPILE - -#endif // FEATURE_PREJIT diff --git a/src/vm/zapsig.h b/src/vm/zapsig.h index d09290c27d3d..3b537cf8c10a 100644 --- a/src/vm/zapsig.h +++ b/src/vm/zapsig.h @@ -78,7 +78,14 @@ class ZapSig pfnTokenDefinition(_pfnTokenDefinition) {} -#ifdef FEATURE_PREJIT + // Static methods + + // Compare a type handle with a signature whose tokens are resolved with respect to pModule + // pZapSigContext is used to resolve ELEMENT_TYPE_MODULE_ZAPSIG encodings + static BOOL CompareSignatureToTypeHandle(PCCOR_SIGNATURE pSig, + Module* pModule, + TypeHandle handle, + const ZapSig::Context * pZapSigContext); // Instance methods @@ -94,15 +101,7 @@ class ZapSig BOOL GetSignatureForTypeHandle(TypeHandle typeHandle, SigBuilder * pSigBuilder); - // Static methods - - // Compare a type handle with a signature whose tokens are resolved with respect to pModule - // pZapSigContext is used to resolve ELEMENT_TYPE_MODULE_ZAPSIG encodings - static BOOL CompareSignatureToTypeHandle(PCCOR_SIGNATURE pSig, - Module* pModule, - TypeHandle handle, - const ZapSig::Context * pZapSigContext); - +#ifdef FEATURE_PREJIT // Compare a type handle with a tagged pointer. Ensure that the common path is inlined into the caller. static FORCEINLINE BOOL CompareTaggedPointerToTypeHandle(Module * pModule, TADDR addr, TypeHandle handle) { @@ -115,6 +114,7 @@ class ZapSig } static BOOL CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle); +#endif static BOOL CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2); @@ -127,7 +127,6 @@ class ZapSig // static CorElementType TryEncodeUsingShortcut(/* in */ MethodTable * pMT); -#endif // FEATURE_PREJIT private: diff --git a/src/zap/zapcode.cpp b/src/zap/zapcode.cpp index 91cf7163e623..0e35eb3314e5 100644 --- a/src/zap/zapcode.cpp +++ b/src/zap/zapcode.cpp @@ -281,11 +281,6 @@ void ZapImage::OutputCode(CodeType codeType) if (!pTarget->IsPlaced()) m_pImportTable->PlaceIndirectHelperThunk(pTarget); break; - - case ZapNodeType_RVAFieldData: - if (!pTarget->IsPlaced()) - m_pReadOnlyDataSection->Place(pTarget); - break; #endif case ZapNodeType_GenericSignature: diff --git a/src/zap/zapheaders.cpp b/src/zap/zapheaders.cpp index 8ca00d748662..c931d3bfcb63 100644 --- a/src/zap/zapheaders.cpp +++ b/src/zap/zapheaders.cpp @@ -223,7 +223,6 @@ void ZapVersionResource::Save(ZapWriter * pZapWriter) void ZapImage::CopyWin32VersionResource() { -#ifndef FEATURE_PAL // Copy the version resource over so it is easy to see in the dumps where the ngened module came from COUNT_T cbResourceData; PVOID pResourceData = m_ModuleDecoder.GetWin32Resource(MAKEINTRESOURCE(1), RT_VERSION, &cbResourceData); @@ -239,7 +238,6 @@ void ZapImage::CopyWin32VersionResource() m_pWin32ResourceSection->Place(pVersionData); SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE, m_pWin32ResourceSection); -#endif } #undef MAKEINTRESOURCE diff --git a/src/zap/zapimage.cpp b/src/zap/zapimage.cpp index da7ea508e49e..aa661f53ebec 100644 --- a/src/zap/zapimage.cpp +++ b/src/zap/zapimage.cpp @@ -2448,7 +2448,6 @@ HRESULT ZapImage::LocateProfileData() return S_FALSE; } -#if !defined(FEATURE_PAL) // // See if there's profile data in the resource section of the PE // @@ -2463,7 +2462,6 @@ HRESULT ZapImage::LocateProfileData() static ConfigDWORD g_UseIBCFile; if (g_UseIBCFile.val(CLRConfig::EXTERNAL_UseIBCFile) != 1) return S_OK; -#endif // // Couldn't find profile resource--let's see if there's an ibc file to use instead diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index 1e498463c6a0..21ce5f558db4 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -3864,6 +3864,14 @@ BOOL ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, return TRUE; #endif + if (IsReadyToRunCompilation() && method != NULL && !m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getMethodModule(method))) + { + // FUTURE: ZapSig::EncodeMethod does not yet handle cross module references for ReadyToRun + // See zapsig.cpp around line 1217. + // Once this is implemented, we'll be able to inline pinvokes of extern methods declared in other modules (Ex: PresentationCore.dll) + return TRUE; + } + return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig); } diff --git a/src/zap/zapmetadata.cpp b/src/zap/zapmetadata.cpp index a3a9e2d9d62c..4b785f14b479 100644 --- a/src/zap/zapmetadata.cpp +++ b/src/zap/zapmetadata.cpp @@ -162,6 +162,15 @@ void ZapILMetaData::CopyRVAFields() // Managed C++ binaries depend on the order of RVA fields qsort(&fields[0], fields.GetCount(), sizeof(RVAField), RVAFieldCmp); +#ifdef _DEBUG + for (COUNT_T i = 0; i < fields.GetCount(); i++) + { + // Make sure no RVA field node has been placed during compilation. This would mess up the ordering + // and can potentially break the Managed C++ scenarios. + _ASSERTE(!GetRVAField(fields[i].pData)->IsPlaced()); + } +#endif + for (COUNT_T i = 0; i < fields.GetCount(); i++) { RVAField field = fields[i]; @@ -172,7 +181,7 @@ void ZapILMetaData::CopyRVAFields() pRVADataNode->UpdateSizeAndAlignment(field.cbSize, field.cbAlignment); if (!pRVADataNode->IsPlaced()) - m_pImage->m_pReadOnlyDataSection->Place(pRVADataNode); + m_pImage->m_pReadOnlyDataSection->Place(pRVADataNode); } } diff --git a/tests/CoreFX/CoreFX.issues.json b/tests/CoreFX/CoreFX.issues.json index cfd18acfd05a..78960e96ffc3 100644 --- a/tests/CoreFX/CoreFX.issues.json +++ b/tests/CoreFX/CoreFX.issues.json @@ -260,6 +260,20 @@ "methods": null } }, + { + "name": "System.Diagnostics.StackTrace.Tests", + "enabled": true, + "exclusions": { + "namespaces": null, + "classes": null, + "methods": [ + { + "name": "System.Diagnostics.Tests.StackTraceTests.ToString_NullFrame_ThrowsNullReferenceException", + "reason": "outdated" + } + ] + } + }, { "name": "System.Diagnostics.Tracing.Tests", "enabled": true, @@ -896,15 +910,23 @@ "methods": [ { "name": "System.Text.Tests.EncoderConvert2.EncoderASCIIConvertMixedASCIIUnicodeCharArrayPartial", - "reason": "https://github.com/dotnet/coreclr/issues/23020" + "reason": "https://github.com/dotnet/coreclr/issues/23864" }, { "name": "System.Text.Tests.EncoderConvert2.EncoderUTF8ConvertMixedASCIIUnicodeCharArrayPartial", - "reason": "https://github.com/dotnet/coreclr/issues/23020" + "reason": "https://github.com/dotnet/coreclr/issues/23864" }, { "name": "System.Text.Tests.EncoderConvert2.EncoderUTF8ConvertUnicodeCharArrayPartial", - "reason": "https://github.com/dotnet/coreclr/issues/23020" + "reason": "https://github.com/dotnet/coreclr/issues/23864" + }, + { + "name": "System.Text.Tests.NegativeEncodingTests.GetByteCount_Invalid", + "reason": "https://github.com/dotnet/coreclr/issues/23864" + }, + { + "name": "System.Text.Tests.UTF8EncodingDecode.Decode_InvalidBytes", + "reason": "https://github.com/dotnet/coreclr/issues/23864" } ] } @@ -1357,7 +1379,11 @@ }, { "name": "System.Tests.BufferTests.BlockCopy_Invalid", - "reason" : "https://github.com/dotnet/coreclr/pull/23636" + "reason": "https://github.com/dotnet/coreclr/pull/23636" + }, + { + "name": "System.Tests.VersionTests.Comparisons_NullArgument_ThrowsArgumentNullException", + "reason": "Version was improved to no longer throw from comparison operators" }, ] } diff --git a/tests/arm64/corefx_linux_test_exclusions.txt b/tests/arm64/corefx_linux_test_exclusions.txt index 60050cc1d85d..67483871c61a 100644 --- a/tests/arm64/corefx_linux_test_exclusions.txt +++ b/tests/arm64/corefx_linux_test_exclusions.txt @@ -9,5 +9,4 @@ System.Net.Sockets.Tests # https://github.com/dotnet/corecl System.Runtime.Numerics.Tests # https://github.com/dotnet/coreclr/issues/23242 -- timeout System.Runtime.Serialization.Formatters.Tests # https://github.com/dotnet/coreclr/issues/20246 -- timeout System.Text.RegularExpressions.Tests # https://github.com/dotnet/coreclr/issues/17754 -- timeout -- JitMinOpts + Tiered only -System.Threading.Tasks.Tests # https://github.com/dotnet/coreclr/issues/20706 System.Threading.Tests # https://github.com/dotnet/coreclr/issues/20215 diff --git a/tests/arm64/corefx_test_exclusions.txt b/tests/arm64/corefx_test_exclusions.txt index 2c1b800072a5..6078887b919e 100644 --- a/tests/arm64/corefx_test_exclusions.txt +++ b/tests/arm64/corefx_test_exclusions.txt @@ -1,7 +1,7 @@ Microsoft.Win32.SystemEvents.Tests # https://github.com/dotnet/coreclr/issues/22442 -- timeout -System.ComponentModel.Composition.Tests # https://github.com/dotnet/coreclr/issues/18913 System.Drawing.Common.Tests # https://github.com/dotnet/corefx/issues/35424 System.IO.FileSystem.Tests # https://github.com/dotnet/coreclr/issues/23447 +System.IO.Tests.dll # https://github.com/dotnet/coreclr/pull/23388 - reenable with the new CoreFX test runner System.Management.Tests # https://github.com/dotnet/corefx/issues/34030 System.Net.HttpListener.Tests # https://github.com/dotnet/coreclr/issues/17584 System.Net.Sockets.Tests # https://github.com/dotnet/coreclr/issues/23378 diff --git a/tests/helixpublishwitharcade.proj b/tests/helixpublishwitharcade.proj index d928269412ad..1016f94b1d90 100644 --- a/tests/helixpublishwitharcade.proj +++ b/tests/helixpublishwitharcade.proj @@ -10,10 +10,6 @@ that will run in parallel. --> - - <_Scenarios Include="$(_Scenarios.Split(','))" /> - - @@ -34,9 +30,13 @@ + + + - + <_Scenarios Include="$(_Scenarios.Split(','))" /> + <_ProjectsToBuild Include="$(MSBuildProjectFile)"> $(_PropertiesToPass);Scenario=%(_Scenarios.Identity) @@ -44,41 +44,116 @@ <_BuildInParallel>false - <_BuildInParallel Condition=" '@(_ProjectsToBuild->Count())' > '1' ">true + <_BuildInParallel Condition=" '@(_ProjectsToBuild->Count())' > '1' ">true - - + - $(TestWorkingDir)Tests\Core_Root + $([MSBuild]::NormalizeDirectory($(BinDir))) + $(BinDir)Tests\Core_Root\ + $(BinDir)Payloads\ SetStressModes_$(Scenario).cmd SetStressModes_$(Scenario).sh - - - %(RootDir)%(Directory) - %(FileName)%(Extension) - - + - + + + <_XUnitWrapperDll Include="%(TestGrouping.XUnitWrapperDll)" Condition="Exists('%(XUnitWrapperDll)')"> + %(TestGroup) + + <_XUnitWrapperDll Include="@(XUnitWrapperGrouping)" /> + + + <_XUnitWrapperDll Include="$(BinDir)**\*.XUnitWrapper.dll" Exclude="$(PayloadsRootDirectory)**\*.XUnitWrapper.dll;@(XUnitWrapperGrouping->Metadata('FullPath'))"> + + + + + + <_XUnitWrapperDll Update="@(_XUnitWrapperDll)"> + $([MSBuild]::ValueOrDefault(%(FileName),'').Replace('.XUnitWrapper','')) + + + + + + + <_FileDirectory>%(_XUnitWrapperDll.RootDir)%(Directory) + <_PayloadGroup>%(_XUnitWrapperDll.PayloadGroup) + <_XUnitWrapperDll>%(_XUnitWrapperDll.FullPath) + + + + <_TestGroupingRelevant Include="@(TestGrouping->WithMetadataValue('XUnitWrapperDll',$(_XUnitWrapperDll))->Metadata('FullPath'))" /> + + + + <_TestGroupingExists>@(_TestGroupingRelevant->AnyHaveMetadataValue('TestGroup','$(_PayloadGroup)')) + - + + + <_PayloadFiles Include="$(_FileDirectory)**" Exclude="@(_TestGroupingRelevant)" Condition="'$(_TestGroupingExists)' != 'true'" /> + + <_PayloadFiles Include="@(_TestGroupingRelevant->WithMetadataValue('TestGroup','$(_PayloadGroup)')->DistinctWithCase())" Condition="'$(_TestGroupingExists)' == 'true'" /> + <_PayloadFiles Include="$(_FileDirectory)*" Condition="'$(_TestGroupingExists)' == 'true'" /> + + <_PayloadFiles Update="@(_PayloadFiles)"> + + $(_PayloadGroup)\$([System.IO.Path]::GetRelativePath($(BinDir), %(FullPath))) + + + + + + + + + + + <_XUnitConsoleRunnerFiles Include="$(PackagesDir)$(MicrosoftDotNetXUnitConsoleRunnerPackage.ToLower())\$(MicrosoftDotNetXUnitConsoleRunnerVersion)\**\xunit.console.*" /> + + + + + + + - <_ProjectsToBuild Include=".\testenvironment.proj"> - Scenario=$(Scenario);TestEnvFileName=%(XUnitWrapperDll.FileDirectory)$(TestEnvFileName);TargetsWindows=$(TargetsWindows) + <_PayloadGroups Include="$(PayloadGroups)" /> + <_ProjectsToBuild Include="testenvironment.proj"> + Scenario=$(Scenario);TestEnvFileName=$(PayloadsRootDirectory)%(_PayloadGroups.Identity)\$(TestEnvFileName);TargetsWindows=$(TargetsWindows) + + + <_PayloadGroups>@(_XUnitWrapperDll->Metadata('PayloadGroup')->DistinctWithCase()) + + + + <_Scenario Include="$(_Scenarios.Split(','))" /> + <_ProjectsToBuild Include="$(MSBuildProjectFile)"> + Scenario=%(_Scenario.Identity);PayloadGroups=$(_PayloadGroups) + + + + + + $(PublishTestResults) false @@ -89,11 +164,12 @@ $(BuildType) $(BuildType)-$(Scenario) false - $(BuildOS) $(BuildArch) $(BuildType) @ - $(BuildOS) $(BuildArch) $(BuildType) $(Scenario) @ + R2R + $(TestRunNamePrefix)$(BuildOS) $(BuildArch) $(BuildType) @ + $(TestRunNamePrefix)$(BuildOS) $(BuildArch) $(BuildType) $(Scenario) @ $([System.TimeSpan]::FromMinutes($(TimeoutPerTestInMinutes)).TotalMilliseconds) true - -parallel collections -nocolor -noshadow -xml testResults.xml -notrait category=outerloop -notrait category=failing + -parallel collections -nocolor -noshadow -xml testResults.xml @@ -128,11 +204,26 @@ $CORE_ROOT/xunit.console.dll - - - - %(FileDirectory) - $(CoreRun) $(XUnitRunnerDll) %(File) $(XUnitRunnerArgs) + + + + + + $([MSBuild]::MakeRelative($(PayloadsRootDirectory), %(FullPath))) + %(FullPath) + $([System.String]::Join(' ', $([System.IO.Directory]::GetFiles(%(FullPath), '*.XUnitWrapper.dll', SearchOption.AllDirectories))).Replace($([MSBuild]::EnsureTrailingSlash(%(FullPath))),'')) + + + + %(PayloadGroup) + + + + + + %(PayloadDirectory) + $(CoreRun) $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) + $(CoreRun) $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) -trait TestGroup=%(TestGroup) $([System.TimeSpan]::FromMinutes($(TimeoutPerTestCollectionInMinutes))) diff --git a/tests/issues.targets b/tests/issues.targets index 79e559838d98..0a1103ddfc2b 100644 --- a/tests/issues.targets +++ b/tests/issues.targets @@ -298,6 +298,12 @@ Varargs supported on this platform + + 23941 + + + 23941 + @@ -329,6 +335,9 @@ 22784 + + 20682 + @@ -405,9 +414,6 @@ Varargs supported on this platform - - Needs triage - Needs Triage diff --git a/tests/runtest.proj b/tests/runtest.proj index 1adcfc4f126e..3f1faa8fd810 100644 --- a/tests/runtest.proj +++ b/tests/runtest.proj @@ -147,6 +147,8 @@ $(_XunitEpilog) + + @@ -164,6 +166,7 @@ $(_XunitEpilog) <_XunitProlog Condition=" '$(_XunitProlog)'=='' "> - - - - testExecutable = testExecutable.Replace("\\", "/")%3B @@ -226,22 +225,38 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). - - - - - <_FactName Condition="'$(RunningOnUnix)' != 'true'" >$([System.String]::Copy('%(AllCMDs.FullPath)').Replace("$(_CMDDIR)",'').Replace(".","_").Replace("\","_").Replace("-","_")) - <_ClassName Condition="'$(RunningOnUnix)' != 'true'" >$([System.String]::Copy('%(AllCMDs.FullPath)').Replace("$(_CMDDIR)",'').Replace("cmd","").Replace(".","_").Replace("\","_").Replace("-","_")) - <_FactName Condition="'$(RunningOnUnix)' == 'true'" >$([System.String]::Copy('%(AllCMDs.FullPath)').Replace("$(_CMDDIR)",'').Replace(".","_").Replace("/","_").Replace("-","_")) - <_ClassName Condition="'$(RunningOnUnix)' == 'true'" >$([System.String]::Copy('%(AllCMDs.FullPath)').Replace("$(_CMDDIR)",'').Replace("sh","").Replace(".","_").Replace("/","_").Replace("-","_")) - - <_XunitFact > + + + + + $(Category) + + + + $([MSBuild]::MakeRelative($(_CMDDIR), %(FullPath))) + + + $([MSBuild]::MakeRelative($(XunitTestBinBase), %(AllCMDs.FullPath))) + _$([MSBuild]::ValueOrDefault(%(AllCMDs.RelativeToCMDDIR),"").Replace(".","_").Replace("\","_").Replace("-","_")) + _$([MSBuild]::ValueOrDefault(%(AllCMDs.RelativeToCMDDIR),"").Replace("cmd","").Replace(".","_").Replace("\","_").Replace("-","_")) + _$([MSBuild]::ValueOrDefault(%(AllCMDs.RelativeToCMDDIR),"").Replace(".","_").Replace("/","_").Replace("-","_")) + _$([MSBuild]::ValueOrDefault(%(AllCMDs.RelativeToCMDDIR), '').Replace('sh','').Replace('.','_').Replace('/','_').Replace('-','_')) + %(AllCMDs.TestGroup) + allOutput = new List()%3B + try { - sErrorText = System.IO.File.ReadAllText(errorFile)%3B + allOutput.AddRange(System.IO.File.ReadAllLines(errorFile))%3B } - catch(Exception ex) + catch (Exception ex) { - sErrorText = $"Unable to read error file: {errorFile}\n{ex}"%3B + allOutput.Add("Unable to read error file: " + errorFile)%3B + allOutput.Add(ex.Message)%3B } - string outputText = null%3B + allOutput.Add(string.Empty)%3B + allOutput.Add("Return code: " + ret)%3B + allOutput.Add("Raw output file: " + outputFile)%3B + allOutput.Add("Raw output:")%3B + try { - System.IO.StreamReader outputReader = new System.IO.StreamReader(outputFile)%3B - outputText = outputReader.ReadToEnd()%3B - outputReader.Close()%3B + allOutput.AddRange(System.IO.File.ReadAllLines(outputFile))%3B } catch(Exception ex) { - outputText = $"Unable to read error file: {outputFile}\n{ex}"%3B + allOutput.Add("Unable to read output file: " + outputFile)%3B + allOutput.Add(ex.Message)%3B } - string msg = infraEx != null ? "Test Infrastructure Failure: " + infraEx.ToString() - : sErrorText + "\n\n" + - "Return code: " + ret + "\n" + - "Raw output file: " + outputFile + "\n" + - "Raw output:\n" + outputText + "\n" + - "To run the test:\n" + - "> set CORE_ROOT=" + _Global.coreRoot + "\n" + - "> " + testExecutable + "\n"%3B + allOutput.Add("To run the test:")%3B + allOutput.Add("> set CORE_ROOT=" + _Global.coreRoot)%3B + allOutput.Add("> " + testExecutable)%3B + + foreach (string line in allOutput) + { + output.WriteLine(line)%3B + } - Assert.True(ret == CoreclrTestWrapperLib.EXIT_SUCCESS_CODE, msg)%3B + Assert.True(false, string.Join(Environment.NewLine, allOutput))%3B } } - } + } ]]> - + - + @@ -350,7 +374,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). - @@ -394,7 +418,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). hostpolicy dll - + libhostfxr so @@ -403,9 +427,9 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). $(HostFxrFileExtension) dotnet - + - @@ -427,17 +451,17 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). - @@ -461,7 +485,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). + Condition=" '$(GenerateTestHost)'=='true' "/> diff --git a/tests/scripts/run-corefx-tests.bat b/tests/scripts/run-corefx-tests.bat index b77644f44ed1..34f86d2949b6 100644 --- a/tests/scripts/run-corefx-tests.bat +++ b/tests/scripts/run-corefx-tests.bat @@ -81,7 +81,7 @@ if %errorlevel% EQU 0 ( echo COREFX TEST %_t3% EXCLUDED set /A _skipped=_skipped + 1 ) else ( - call :run %1\RunTests.cmd %_runtime_path% + call :run %1\RunTests.cmd --runtime-path %_runtime_path% ) goto :eof diff --git a/tests/scripts/run-corefx-tests.sh b/tests/scripts/run-corefx-tests.sh index 2d1dcb86048c..4a04f0a7b33d 100755 --- a/tests/scripts/run-corefx-tests.sh +++ b/tests/scripts/run-corefx-tests.sh @@ -327,9 +327,9 @@ run_test() echo echo "Running tests in $dirName" - echo "${TimeoutTool}./RunTests.sh $Runtime" + echo "${TimeoutTool}./RunTests.sh --runtime-path $Runtime" echo - ${TimeoutTool}./RunTests.sh "$Runtime" + ${TimeoutTool}./RunTests.sh --runtime-path "$Runtime" exitCode=$? if [ $exitCode -ne 0 ] ; then diff --git a/tests/src/GC/Scenarios/Samples/gc.cs b/tests/src/GC/Scenarios/Samples/gc.cs index 7ed11bc4094a..7b3e38f68c24 100644 --- a/tests/src/GC/Scenarios/Samples/gc.cs +++ b/tests/src/GC/Scenarios/Samples/gc.cs @@ -518,11 +518,6 @@ public static int Main(String[] args) { // Demos Finalize on Shutdown symantics (this demo is inline) Display(0, "\n\nDemo start: Finalize on shutdown.", +1); - // Normally, when an application terminates, the GC does NOT collect and run finalizers. - // The line below forces the GC to do complete object cleanup - // GC.RequestFinalizeOnShutdown(); // For default behavior, comment out this line - // NOTE: Once you request FinalizeOnShutdown, you cannot change your mind. - // When Main returns, obj will have its Finalize method called. BaseObj obj = new BaseObj("Shutdown"); diff --git a/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj b/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj index 182ba923c93e..63df65745192 100644 --- a/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj +++ b/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj @@ -30,7 +30,7 @@ - + diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest b/tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest new file mode 100644 index 000000000000..58fc0a2781f0 --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj b/tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj new file mode 100644 index 000000000000..9202a9757a9a --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj @@ -0,0 +1,54 @@ + + + + + Debug + AnyCPU + ConsumeNETServer + 2.0 + {4BDB75BD-30D8-4603-98DB-C6CFDC5F6F0E} + Exe + {209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766} + App.manifest + true + true + + + BuildOnly + + + false + + + true + true + + true + + + $(NoWarn),0436 + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest b/tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest new file mode 100644 index 000000000000..abb39fbb21c7 --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs b/tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs new file mode 100644 index 000000000000..1a2aa68d9931 --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs @@ -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. +// See the LICENSE file in the project root for more information. + +namespace NetClient +{ + using System; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using TestLibrary; + using Server.Contract; + + using CoClass = Server.Contract.Servers; + + class Program + { + static void Validate_Activation() + { + Console.WriteLine($"{nameof(Validate_Activation)}..."); + + var test = new CoClass.ConsumeNETServerTesting(); + test.ReleaseResources(); + + // The CoClass should be the activated type, _not_ the activation interface. + Assert.AreEqual(test.GetType(), typeof(CoClass.ConsumeNETServerTestingClass)); + } + + static void Validate_CCW_Wasnt_Unwrapped() + { + Console.WriteLine($"{nameof(Validate_CCW_Wasnt_Unwrapped)}..."); + + var test = new CoClass.ConsumeNETServerTesting(); + test.ReleaseResources(); + + // The CoClass should be the activated type, _not_ the implementation class. + // This indicates the real implementation class is wrapped in its CCW and exposed + // to the runtime as an RCW. + Assert.AreNotEqual(test.GetType(), typeof(ConsumeNETServerTesting)); + } + + static void Validate_Client_CCW_RCW() + { + Console.WriteLine($"{nameof(Validate_Client_CCW_RCW)}..."); + + IntPtr ccw = IntPtr.Zero; + + // Validate the client side view is consistent + var test = new CoClass.ConsumeNETServerTesting(); + try + { + ccw = test.GetCCW(); + object rcw = Marshal.GetObjectForIUnknown(ccw); + object inst = test.GetRCW(); + Assert.AreEqual(rcw, inst); + } + finally + { + test.ReleaseResources(); + } + } + + static void Validate_Server_CCW_RCW() + { + Console.WriteLine($"{nameof(Validate_Server_CCW_RCW)}..."); + + // Validate the server side view is consistent + var test = new CoClass.ConsumeNETServerTesting(); + try + { + Assert.IsTrue(test.EqualByCCW(test)); + Assert.IsTrue(test.NotEqualByRCW(test)); + } + finally + { + test.ReleaseResources(); + } + } + + static int Main(string[] doNotUse) + { + // RegFree COM is not supported on Windows Nano + if (Utilities.IsWindowsNanoServer) + { + return 100; + } + + // Initialize CoreShim and hostpolicymock + HostPolicyMock.Initialize(Environment.CurrentDirectory, null); + Environment.SetEnvironmentVariable("CORESHIM_COMACT_ASSEMBLYNAME", "NETServer"); + Environment.SetEnvironmentVariable("CORESHIM_COMACT_TYPENAME", "ConsumeNETServerTesting"); + + try + { + using (HostPolicyMock.Mock_corehost_resolve_component_dependencies( + 0, + string.Empty, + string.Empty, + string.Empty)) + { + Validate_Activation(); + Validate_CCW_Wasnt_Unwrapped(); + Validate_Client_CCW_RCW(); + Validate_Server_CCW_RCW(); + } + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } + } +} diff --git a/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj b/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj index fccbee9258c6..f346a0227e81 100644 --- a/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj +++ b/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj @@ -30,7 +30,7 @@ - + diff --git a/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj b/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj index 4fd95f66941d..a99416ba28fa 100644 --- a/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj +++ b/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj @@ -30,7 +30,7 @@ - + diff --git a/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj b/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj index 52154225c4c7..a46a2a2619f7 100644 --- a/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj +++ b/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj @@ -30,7 +30,7 @@ - + diff --git a/tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs b/tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs index 93eba8ef72e5..ed2fa713c307 100644 --- a/tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs +++ b/tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs @@ -54,6 +54,7 @@ private void VerifyReturnHResult() foreach (var hr in hrs) { Assert.AreEqual(hr, this.server.Return_As_HResult(hr)); + Assert.AreEqual(hr, this.server.Return_As_HResult_Struct(hr).hr); } } } diff --git a/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj b/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj index 81c06a3f3cf7..c1f38576e3ad 100644 --- a/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj +++ b/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj @@ -35,7 +35,7 @@ - + diff --git a/tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs b/tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs index c134ea25acb9..19d0574063a0 100644 --- a/tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs +++ b/tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs @@ -200,39 +200,5 @@ private void Marshal_ManyInts() Console.WriteLine($"{expected.GetType().Name} 12 test invariant: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 = {expected}"); Assert.IsTrue(expected == this.server.Add_ManyInts12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)); } - - private void Marshal_Struct_Return() - { - Console.WriteLine("Struct return from member function marshalling with struct > 4 bytes"); - { - var width = 1.0f; - var height = 2.0f; - Server.Contract.SizeF result = this.server.MakeSize(width, height); - - Assert.AreEqual(width, result.width); - Assert.AreEqual(height, result.height); - } - Console.WriteLine("Struct return from member function marshalling with struct <= 4 bytes"); - { - byte width = 1; - byte height = 2; - Server.Contract.Size result = this.server.MakeSizeSmall(width, height); - - Assert.AreEqual(width, result.width); - Assert.AreEqual(height, result.height); - } - Console.WriteLine("Struct return from member function marshalling with struct > 8 bytes"); - { - var x = 1.0f; - var y = 2.0f; - var z = 3.0f; - var w = 4.0f; - Server.Contract.HFA_4 result = this.server.MakeHFA(x, y ,z, w); - Assert.AreEqual(x, result.x); - Assert.AreEqual(y, result.y); - Assert.AreEqual(z, result.z); - Assert.AreEqual(w, result.w); - } - } } } diff --git a/tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs b/tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs new file mode 100644 index 000000000000..d8dba73982d9 --- /dev/null +++ b/tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +[ComVisible(true)] +[Guid(Server.Contract.Guids.ConsumeNETServerTesting)] +public class ConsumeNETServerTesting : Server.Contract.IConsumeNETServer +{ + private IntPtr _ccw; + private object _rcwUnwrapped; + + public ConsumeNETServerTesting() + { + _ccw = Marshal.GetIUnknownForObject(this); + _rcwUnwrapped = Marshal.GetObjectForIUnknown(_ccw); + } + + public IntPtr GetCCW() + { + return _ccw; + } + + public object GetRCW() + { + return _rcwUnwrapped; + } + + public void ReleaseResources() + { + Marshal.Release(_ccw); + _ccw = IntPtr.Zero; + _rcwUnwrapped = null; + } + + public bool EqualByCCW(object obj) + { + IntPtr ccwMaybe = Marshal.GetIUnknownForObject(obj); + bool areEqual = ccwMaybe == _ccw; + Marshal.Release(ccwMaybe); + + return areEqual; + } + + public bool NotEqualByRCW(object obj) + { + return _rcwUnwrapped != obj; + } +} diff --git a/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs b/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs index 6bd104f5d494..e0fe38e2149b 100644 --- a/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs +++ b/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs @@ -25,4 +25,10 @@ public int Return_As_HResult(int hresultToReturn) { return hresultToReturn; } -} \ No newline at end of file + + [PreserveSig] + public Server.Contract.HResult Return_As_HResult_Struct(int hresultToReturn) + { + return new Server.Contract.HResult { hr = hresultToReturn }; + } +} diff --git a/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il b/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il index 3e4180c7b7cb..a45fc521069d 100644 --- a/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il +++ b/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il @@ -62,16 +62,17 @@ ret } - .method public abstract virtual - instance int32 DefOnInterface2Ret5() cil managed + .method public virtual + instance int32 DefOnInterfaceRet5() cil managed { - // Simple interface method + // Default interface implementation + ldc.i4 5 + ret } } // Interface defintion for overriding another interface's implementation -.class interface private abstract auto ansi Server.Contract.IDefaultInterfaceTesting2 - implements Server.Contract.IDefaultInterfaceTesting +.class interface public abstract auto ansi Server.Contract.IDefaultInterfaceTesting2 { .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 01 00 00 ) @@ -82,20 +83,13 @@ 39 34 42 46 37 41 30 00 00 ) .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.InterfaceTypeAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ComInterfaceType) = ( 01 00 01 00 00 00 00 00 ) - - .method public virtual final - instance int32 DefOnInterface2Ret5() cil managed - { - .override Server.Contract.IDefaultInterfaceTesting::DefOnInterface2Ret5 - ldc.i4 5 - ret - } } // COM server consuming interfaces with default methods .class public auto ansi beforefieldinit DefaultInterfaceTesting extends [System.Runtime]System.Object - implements Server.Contract.IDefaultInterfaceTesting2 + implements Server.Contract.IDefaultInterfaceTesting, + Server.Contract.IDefaultInterfaceTesting2 { .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 01 00 00 ) // GUID: FAEF42AE-C1A4-419F-A912-B768AC2679EA diff --git a/tests/src/Interop/COM/NETServer/NETServer.csproj b/tests/src/Interop/COM/NETServer/NETServer.csproj index aa4e791a6cef..e820c0c63f3a 100644 --- a/tests/src/Interop/COM/NETServer/NETServer.csproj +++ b/tests/src/Interop/COM/NETServer/NETServer.csproj @@ -17,13 +17,7 @@ - - - - - - - + diff --git a/tests/src/Interop/COM/NETServer/NumericTesting.cs b/tests/src/Interop/COM/NETServer/NumericTesting.cs index 64ca47d31891..36edab46f44f 100644 --- a/tests/src/Interop/COM/NETServer/NumericTesting.cs +++ b/tests/src/Interop/COM/NETServer/NumericTesting.cs @@ -200,19 +200,4 @@ public int Add_ManyInts12(int i1, int i2, int i3, int i4, int i5, int i6, int i7 { return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12; } - - public Server.Contract.SizeF MakeSize(float width, float height) - { - return new Server.Contract.SizeF { width = width, height = height }; - } - - public Server.Contract.Size MakeSizeSmall(byte width, byte height) - { - return new Server.Contract.Size { width = width, height = height }; - } - - public Server.Contract.HFA_4 MakeHFA(float x, float y, float z, float w) - { - return new Server.Contract.HFA_4 {x = x, y = y, z = z, w = w}; - } } diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj b/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj index f8a5dd6d22af..7d86d1013627 100644 --- a/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj @@ -5,6 +5,7 @@ true true true + BuildOnly true true diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp index 9d87215049e5..1751abbbc5a8 100644 --- a/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp @@ -34,7 +34,9 @@ struct ComInit using ComMTA = ComInit; -void CallDefaultInterface(); +void ActivateClassWithDefaultInterfaces(); +void FailToActivateDefaultInterfaceInstance(); +void FailToQueryInterfaceForDefaultInterface(); int __cdecl main() { @@ -46,7 +48,9 @@ int __cdecl main() { CoreShimComActivation csact{ W("NetServer.DefaultInterfaces"), W("DefaultInterfaceTesting") }; - CallDefaultInterface(); + ActivateClassWithDefaultInterfaces(); + FailToActivateDefaultInterfaceInstance(); + FailToQueryInterfaceForDefaultInterface(); } catch (HRESULT hr) { @@ -57,27 +61,52 @@ int __cdecl main() return 100; } -void CallDefaultInterface() +void ActivateClassWithDefaultInterfaces() { - ::printf("Call functions on Default Interface...\n"); + ::printf("Activate class using default interfaces via IUnknown...\n"); + + HRESULT hr; + + // Validate a class that has an interface with function definitions can be activated + { + ComSmartPtr unknown; + THROW_IF_FAILED(::CoCreateInstance(CLSID_DefaultInterfaceTesting, nullptr, CLSCTX_INPROC, IID_IUnknown, (void**)&unknown)); + THROW_FAIL_IF_FALSE(unknown != nullptr); + } + + { + ComSmartPtr classFactory; + THROW_IF_FAILED(::CoGetClassObject(CLSID_DefaultInterfaceTesting, CLSCTX_INPROC, nullptr, IID_IClassFactory, (void**)&classFactory)); + + ComSmartPtr unknown; + THROW_IF_FAILED(classFactory->CreateInstance(nullptr, IID_IUnknown, (void**)&unknown)); + THROW_FAIL_IF_FALSE(unknown != nullptr); + } +} + +const int COR_E_INVALIDOPERATION = 0x80131509; + +void FailToActivateDefaultInterfaceInstance() +{ + ::printf("Fail to activate class via a default interface...\n"); HRESULT hr; ComSmartPtr defInterface; - THROW_IF_FAILED(::CoCreateInstance(CLSID_DefaultInterfaceTesting, nullptr, CLSCTX_INPROC, IID_IDefaultInterfaceTesting, (void**)&defInterface)); + hr = ::CoCreateInstance(CLSID_DefaultInterfaceTesting, nullptr, CLSCTX_INPROC, IID_IDefaultInterfaceTesting, (void**)&defInterface); + THROW_FAIL_IF_FALSE(hr == COR_E_INVALIDOPERATION); +} - int i; +void FailToQueryInterfaceForDefaultInterface() +{ + ::printf("Fail to QueryInterface() for default interface...\n"); - THROW_IF_FAILED(defInterface->DefOnInterfaceRet2(&i)); - THROW_FAIL_IF_FALSE(i == 2); + HRESULT hr; - THROW_IF_FAILED(defInterface->DefOnClassRet3(&i)); - THROW_FAIL_IF_FALSE(i == 3); + ComSmartPtr defInterface2; + THROW_IF_FAILED(::CoCreateInstance(CLSID_DefaultInterfaceTesting, nullptr, CLSCTX_INPROC, IID_IDefaultInterfaceTesting2, (void**)&defInterface2)); - // - // Overridden default interface defintions do not work - // https://github.com/dotnet/coreclr/issues/15683 - // - //THROW_IF_FAILED(defInterface->DefOnInterface2Ret5(&i)); - //THROW_FAIL_IF_FALSE(i == 5); + ComSmartPtr defInterface; + hr = defInterface2->QueryInterface(&defInterface); + THROW_FAIL_IF_FALSE(hr == COR_E_INVALIDOPERATION); } diff --git a/tests/src/Interop/COM/NativeClients/Licensing.csproj b/tests/src/Interop/COM/NativeClients/Licensing.csproj index 3bebdce2823a..9c70513e3c7a 100644 --- a/tests/src/Interop/COM/NativeClients/Licensing.csproj +++ b/tests/src/Interop/COM/NativeClients/Licensing.csproj @@ -5,6 +5,7 @@ true true true + BuildOnly true true diff --git a/tests/src/Interop/COM/NativeClients/Primitives.csproj b/tests/src/Interop/COM/NativeClients/Primitives.csproj index 932fdb734210..8315a5fd49a4 100644 --- a/tests/src/Interop/COM/NativeClients/Primitives.csproj +++ b/tests/src/Interop/COM/NativeClients/Primitives.csproj @@ -5,6 +5,7 @@ true true true + BuildOnly true true diff --git a/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp b/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp index 1708aca2e1ed..18606a628085 100644 --- a/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp +++ b/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp @@ -52,6 +52,30 @@ namespace THROW_FAIL_IF_FALSE(hr == hrMaybe); } } + + void VerifyReturnHResultStruct(_In_ IErrorMarshalTesting *et) + { + ::printf("Verify preserved function signature\n"); + + HRESULT hrs[] = + { + E_NOTIMPL, + E_POINTER, + E_ACCESSDENIED, + E_INVALIDARG, + E_UNEXPECTED, + HRESULT{-1}, + S_FALSE, + HRESULT{2} + }; + + for (int i = 0; i < ARRAYSIZE(hrs); ++i) + { + HRESULT hr = hrs[i]; + HRESULT hrMaybe = et->Return_As_HResult_Struct(hr); + THROW_FAIL_IF_FALSE(hr == hrMaybe); + } + } } void Run_ErrorTests() @@ -65,4 +89,5 @@ void Run_ErrorTests() VerifyExpectedException(errorMarshal); VerifyReturnHResult(errorMarshal); + VerifyReturnHResultStruct(errorMarshal); } diff --git a/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp b/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp index c02e704bdea5..c951c8c52765 100644 --- a/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp +++ b/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp @@ -216,26 +216,6 @@ namespace THROW_IF_FAILED(numericTesting->Add_ManyInts12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &result)); THROW_FAIL_IF_FALSE(result == expected); } - - void MarshalStructReturn(_In_ INumericTesting* numericTesting) - { - { - ::printf("Marshal struct return type with size > 4 bytes\n"); - float width = 1.0f; - float height = 2.0f; - SizeF size = numericTesting->MakeSize(width, height); - THROW_FAIL_IF_FALSE(width == size.width); - THROW_FAIL_IF_FALSE(height == size.height); - } - { - ::printf("Marshal struct return type with size < 4 bytes\n"); - BYTE width = 1; - BYTE height = 2; - Size size = numericTesting->MakeSizeSmall(width, height); - THROW_FAIL_IF_FALSE(width == size.width); - THROW_FAIL_IF_FALSE(height == size.height); - } - } } void Run_NumericTests() diff --git a/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h b/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h index c28fa0f64582..6675044101e9 100644 --- a/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h +++ b/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h @@ -21,6 +21,12 @@ class ErrorMarshalTesting : public UnknownImpl, public IErrorMarshalTesting return hresultToReturn; } + int STDMETHODCALLTYPE Return_As_HResult_Struct( + /*[in]*/ int hresultToReturn) + { + return hresultToReturn; + } + public: // IUnknown STDMETHOD(QueryInterface)( /* [in] */ REFIID riid, diff --git a/tests/src/Interop/COM/NativeServer/NumericTesting.h b/tests/src/Interop/COM/NativeServer/NumericTesting.h index 95ec2dbc185a..d30427aa3d9a 100644 --- a/tests/src/Interop/COM/NativeServer/NumericTesting.h +++ b/tests/src/Interop/COM/NativeServer/NumericTesting.h @@ -283,30 +283,6 @@ class NumericTesting : public UnknownImpl, public INumericTesting return S_OK; } - virtual COM_DECLSPEC_NOTHROW SizeF STDMETHODCALLTYPE MakeSize( - /*[in]*/ float width, - /*[in]*/ float height) - { - return { width, height }; - } - - virtual COM_DECLSPEC_NOTHROW Size STDMETHODCALLTYPE MakeSizeSmall( - /*[in]*/ BYTE width, - /*[in]*/ BYTE height) - { - return { width, height }; - } - - virtual COM_DECLSPEC_NOTHROW HFA_4 STDMETHODCALLTYPE MakeHFA( - /*[in]*/ float x, - /*[in]*/ float y, - /*[in]*/ float z, - /*[in]*/ float w - ) - { - return { x, y, z, w }; - } - public: // IUnknown STDMETHOD(QueryInterface)( /* [in] */ REFIID riid, diff --git a/tests/src/Interop/COM/ServerContracts/NativeServers.cs b/tests/src/Interop/COM/ServerContracts/Server.CoClasses.cs similarity index 86% rename from tests/src/Interop/COM/ServerContracts/NativeServers.cs rename to tests/src/Interop/COM/ServerContracts/Server.CoClasses.cs index 724f7e2bccad..25432a27db0d 100644 --- a/tests/src/Interop/COM/ServerContracts/NativeServers.cs +++ b/tests/src/Interop/COM/ServerContracts/Server.CoClasses.cs @@ -183,6 +183,31 @@ internal class DefaultInterfaceTestingClass { } */ + + /// + /// Managed definition of CoClass + /// + /// + /// This interface is used to test consumption of the NET server from a NET client only. + /// + [ComImport] + [CoClass(typeof(ConsumeNETServerTestingClass))] + [Guid("CCBC1915-3252-4F6B-98AA-411CE6213D94")] + internal interface ConsumeNETServerTesting : Server.Contract.IConsumeNETServer + { + } + + /// + /// Managed activation for CoClass + /// + /// + /// This interface is used to test consumption of the NET server from a NET client only. + /// + [ComImport] + [Guid(Server.Contract.Guids.ConsumeNETServerTesting)] + internal class ConsumeNETServerTestingClass + { + } } #pragma warning restore 618 // Must test deprecated features diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs b/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs index 7c198c71380c..f16007f38e04 100644 --- a/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs @@ -11,18 +11,6 @@ namespace Server.Contract using System.Runtime.InteropServices; using System.Text; - public struct SizeF - { - public float width; - public float height; - } - - public struct Size - { - public byte width; - public byte height; - } - [ComVisible(true)] [Guid("05655A94-A915-4926-815D-A9EA648BAAD9")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] @@ -60,14 +48,6 @@ public interface INumericTesting int Add_ManyInts11(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11); int Add_ManyInts12(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12); - - [PreserveSig] - SizeF MakeSize(float width, float height); - [PreserveSig] - Size MakeSizeSmall(byte width, byte height); - - [PreserveSig] - HFA_4 MakeHFA(float x, float y, float z, float w); } [ComVisible(true)] @@ -198,6 +178,11 @@ string Add_BStr( void Reverse_BStr_OutAttr([MarshalAs(UnmanagedType.BStr)] string a, [Out][MarshalAs(UnmanagedType.BStr)] string b); } + public struct HResult + { + public int hr; + } + [ComVisible(true)] [Guid("592386A5-6837-444D-9DE3-250815D18556")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] @@ -207,6 +192,9 @@ public interface IErrorMarshalTesting [PreserveSig] int Return_As_HResult(int hresultToReturn); + + [PreserveSig] + HResult Return_As_HResult_Struct(int hresultToReturn); } public enum IDispatchTesting_Exception @@ -306,6 +294,22 @@ public interface ILicenseTesting void SetNextLicense([MarshalAs(UnmanagedType.LPWStr)] string lic); } + + /// + /// This interface is used to test consumption of the NET server from a NET client only. + /// + [ComVisible(true)] + [Guid("CCBC1915-3252-4F6B-98AA-411CE6213D94")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IConsumeNETServer + { + IntPtr GetCCW(); + object GetRCW(); + void ReleaseResources(); + + bool EqualByCCW(object obj); + bool NotEqualByRCW(object obj); + } } #pragma warning restore 618 // Must test deprecated features diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.h b/tests/src/Interop/COM/ServerContracts/Server.Contracts.h index a3629c140cdc..b2c258d7be31 100644 --- a/tests/src/Interop/COM/ServerContracts/Server.Contracts.h +++ b/tests/src/Interop/COM/ServerContracts/Server.Contracts.h @@ -5,18 +5,6 @@ #include -struct SizeF -{ - float width; - float height; -}; - -struct Size -{ - BYTE width; - BYTE height; -}; - struct HFA_4 { float x; @@ -163,17 +151,6 @@ INumericTesting : IUnknown /*[in]*/ int i11, /*[in]*/ int i12, /*[out]*/ int * result ) = 0; - virtual COM_DECLSPEC_NOTHROW SizeF STDMETHODCALLTYPE MakeSize( - /*[in]*/ float width, - /*[in]*/ float height) = 0; - virtual COM_DECLSPEC_NOTHROW Size STDMETHODCALLTYPE MakeSizeSmall( - /*[in]*/ BYTE width, - /*[in]*/ BYTE height) = 0; - virtual COM_DECLSPEC_NOTHROW HFA_4 STDMETHODCALLTYPE MakeHFA( - /*[in]*/ float x, - /*[in]*/ float y, - /*[in]*/ float z, - /*[in]*/ float w) = 0; }; struct __declspec(uuid("7731cb31-e063-4cc8-bcd2-d151d6bc8f43")) @@ -388,6 +365,8 @@ IErrorMarshalTesting : IUnknown /*[in]*/ int hresultToReturn ) = 0; virtual int STDMETHODCALLTYPE Return_As_HResult ( /*[in]*/ int hresultToReturn ) = 0; + virtual int STDMETHODCALLTYPE Return_As_HResult_Struct ( + /*[in]*/ int hresultToReturn ) = 0; }; enum IDispatchTesting_Exception @@ -488,13 +467,13 @@ IDefaultInterfaceTesting : IUnknown virtual HRESULT STDMETHODCALLTYPE DefOnClassRet3(_Out_ int *p) = 0; - virtual HRESULT STDMETHODCALLTYPE DefOnInterface2Ret5(_Out_ int *p) = 0; + virtual HRESULT STDMETHODCALLTYPE DefOnInterfaceRet5(_Out_ int *p) = 0; }; struct __declspec(uuid("9B3CE792-F063-427D-B48E-4354094BF7A0")) -IDefaultInterfaceTesting2 : IDefaultInterfaceTesting +IDefaultInterfaceTesting2 : IUnknown { - + // Empty }; #pragma pack(pop) diff --git a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs index 98ed0aed85f6..d03eacf70859 100644 --- a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs +++ b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs @@ -19,5 +19,6 @@ internal sealed class Guids public const string ColorTesting = "C222F472-DA5A-4FC6-9321-92F4F7053A65"; public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535"; public const string DefaultInterfaceTesting = "FAEF42AE-C1A4-419F-A912-B768AC2679EA"; + public const string ConsumeNETServerTesting = "DE4ACF53-5957-4D31-8BE2-EA6C80683246"; } } diff --git a/tests/src/JIT/Directed/arglist/vararg.cs b/tests/src/JIT/Directed/arglist/vararg.cs index cf05aeb123d4..cc2ccc472751 100644 --- a/tests/src/JIT/Directed/arglist/vararg.cs +++ b/tests/src/JIT/Directed/arglist/vararg.cs @@ -4044,8 +4044,6 @@ static bool TestEchoTwoDoubleStructManagedNoVararg() [MethodImpl(MethodImplOptions.NoInlining)] static bool TestEchoThreeDoubleStructManagedNoVararg() { -#if false - // Disabled - see issue #20046 ThreeDoubleStruct arg = new ThreeDoubleStruct(); arg.a = 1.0; arg.b = 2.0; @@ -4055,9 +4053,6 @@ static bool TestEchoThreeDoubleStructManagedNoVararg() bool equal = arg.a == returnValue.a && arg.b == returnValue.b && arg.c == returnValue.c; return equal; -#else - return true; -#endif } [MethodImpl(MethodImplOptions.NoInlining)] @@ -4081,8 +4076,6 @@ static bool TestEchoFourFloatStructManagedNoVararg() [MethodImpl(MethodImplOptions.NoInlining)] static bool TestEchoFourDoubleStructManagedNoVararg() { -#if false - // Disabled - see issue #20046 FourDoubleStruct arg = new FourDoubleStruct(); arg.a = 1.0; arg.b = 2.0; @@ -4096,9 +4089,6 @@ static bool TestEchoFourDoubleStructManagedNoVararg() arg.d == returnValue.d; return equal; -#else - return true; -#endif } [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/tests/src/JIT/Directed/rvastatics/RVAOrderingTest.il b/tests/src/JIT/Directed/rvastatics/RVAOrderingTest.il new file mode 100644 index 000000000000..3f8faf78de10 --- /dev/null +++ b/tests/src/JIT/Directed/rvastatics/RVAOrderingTest.il @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.assembly extern System.Runtime { } +.assembly extern System.Runtime.Extensions { } +.assembly extern System.Console { } +.assembly RVAOrderingTest { } +.module RVAOrderingTest.exe + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class private auto ansi beforefieldinit RVAOrderingTest + extends [System.Runtime]System.Object +{ + .method private hidebysig static int32 + Main(string[] args) cil managed + { + .entrypoint + // Code size 106 (0x6a) + .maxstack 2 + .locals init ([0] int32 result, + [1] int32* pBegin, + [2] int32& pinned V_2, + [3] int32* pEnd, + [4] int32& pinned V_4, + [5] bool V_5, + [6] int32 V_6) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: ldsflda int32 RVAOrderingTest::s_First + IL_0008: stloc.2 + IL_0009: ldloc.2 + IL_000a: conv.u + IL_000b: stloc.1 + IL_000c: ldsflda int32 RVAOrderingTest::s_Last + IL_0011: stloc.s V_4 + IL_0013: ldloc.s V_4 + IL_0015: conv.u + IL_0016: stloc.3 + IL_0017: ldloc.1 + IL_0018: ldloc.3 + IL_0019: call int32 RVAOrderingTest::AddFields(int32*, + int32*) + ldsflda int32 RVAOrderingTest::s_Another1 + ldind.i4 + add + + IL_001e: stloc.0 + IL_001f: ldc.i4.0 + IL_0020: conv.u + IL_0021: stloc.s V_4 + IL_0023: ldc.i4.0 + IL_0024: conv.u + IL_0025: stloc.2 + IL_0026: ldstr "{0:x}" + IL_002b: ldloc.0 + IL_002c: box [System.Runtime]System.Int32 + IL_0031: call void [System.Console]System.Console::WriteLine(string, + object) + IL_0036: nop + IL_0037: ldloc.0 + IL_0038: ldc.i4 0x600000f2 + IL_003d: ceq + IL_003f: stloc.s V_5 + IL_0041: ldloc.s V_5 + IL_0043: brfalse.s IL_0057 + + IL_0045: nop + IL_0046: ldstr "PASS" + IL_004b: call void [System.Console]System.Console::WriteLine(string) + IL_0050: nop + IL_0051: ldc.i4.s 100 + IL_0053: stloc.s V_6 + IL_0055: br.s IL_0067 + + IL_0057: ldstr "FAIL" + IL_005c: call void [System.Console]System.Console::WriteLine(string) + IL_0061: nop + IL_0062: ldc.i4.m1 + IL_0063: stloc.s V_6 + IL_0065: br.s IL_0067 + + IL_0067: ldloc.s V_6 + IL_0069: ret + } // end of method RVAOrderingTest::Main + + .method private hidebysig static int32 + AddFields(int32* pBegin, + int32* pEnd) cil managed + { + // Code size 34 (0x22) + .maxstack 2 + .locals init ([0] int32 result, + [1] bool V_1, + [2] int32 V_2) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0011 + + IL_0005: nop + IL_0006: ldloc.0 + IL_0007: ldarg.0 + IL_0008: ldind.i4 + IL_0009: add + IL_000a: stloc.0 + IL_000b: ldarg.0 + IL_000c: ldc.i4.4 + IL_000d: add + IL_000e: starg.s pBegin + IL_0010: nop + IL_0011: ldarg.0 + IL_0012: ldarg.1 + IL_0013: cgt.un + IL_0015: ldc.i4.0 + IL_0016: ceq + IL_0018: stloc.1 + IL_0019: ldloc.1 + IL_001a: brtrue.s IL_0005 + IL_001c: ldloc.0 + IL_001d: stloc.2 + IL_001e: br.s IL_0020 + IL_0020: ldloc.2 + IL_0021: ret + } // end of method RVAOrderingTest::AddFields + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method RVAOrderingTest::.ctor + + .field public static int32 s_First at D_00014000 + .field public static int32 s_1 at D_00014008 + .field public static int32 s_Another1 at D_00014008 + .field public static int32 s_2 at D_00014010 + .field public static int32 s_3 at D_00014018 + .field public static int32 s_4 at D_00014020 + .field public static int32 s_5 at D_00014028 + .field public static int32 s_Last at D_00014030 + +} // end of class RVAOrderingTest + + +.data D_00014000 = bytearray (00 00 00 00 00 00 00 00) + +.data D_00014008 = bytearray (01 00 00 10 00 00 00 00) +.data D_00014010 = bytearray (10 00 00 10 00 00 00 00) +.data D_00014018 = bytearray (20 00 00 10 00 00 00 00) +.data D_00014020 = bytearray (40 00 00 10 00 00 00 00) +.data D_00014028 = bytearray (80 00 00 10 00 00 00 00) + +.data D_00014030 = bytearray (00 00 00 00 00 00 00 00) diff --git a/tests/src/JIT/Directed/rvastatics/RVAOrderingTest.ilproj b/tests/src/JIT/Directed/rvastatics/RVAOrderingTest.ilproj new file mode 100644 index 000000000000..a961e563f862 --- /dev/null +++ b/tests/src/JIT/Directed/rvastatics/RVAOrderingTest.ilproj @@ -0,0 +1,18 @@ + + + + + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + 1 + + + + + + + \ No newline at end of file diff --git a/tests/src/JIT/HardwareIntrinsics/Arm64/Simd.cs b/tests/src/JIT/HardwareIntrinsics/Arm64/Simd.cs index 97c0a42bd199..ad7602246b9d 100644 --- a/tests/src/JIT/HardwareIntrinsics/Arm64/Simd.cs +++ b/tests/src/JIT/HardwareIntrinsics/Arm64/Simd.cs @@ -1355,7 +1355,6 @@ static void TestExtract() testExtractOp>(name, (x) => Simd.Extract(x, 1), (x) => x[ 1]); testExtractOp>(name, (x) => Simd.Extract(x, 0), (x) => x[ 0]); testExtractOp>(name, (x) => Simd.Extract(x, 1), (x) => x[ 1]); -#if Broken // Test non-constant call testExtractOp>(name, (x) => simdExtract(x, 0), (x) => x[ 0]); @@ -1472,7 +1471,6 @@ static void TestExtract() testThrowsArgumentOutOfRangeException>(name, (x, y) => Simd.Extract(x, 4)); testThrowsArgumentOutOfRangeException>(name, (x, y) => Simd.Extract(x, 2)); testThrowsArgumentOutOfRangeException>(name, (x, y) => Simd.Extract(x, 2)); -#endif testThrowsTypeNotSupported>(name, (x, y) => { return Simd.Extract(x, 1) > 1 ? x : y; }); testThrowsTypeNotSupported>(name, (x, y) => { return Simd.Extract(x, 1) > 1 ? x : y; }); @@ -1528,7 +1526,6 @@ static void TestInsert() testPermuteOp>(name, (x, y) => Simd.Insert(x, 1, (ushort)2), (i, x, y) => (ushort)(i != 1 ? x[i] : 2)); testPermuteOp>(name, (x, y) => Simd.Insert(x, 1, (int )2), (i, x, y) => (int )(i != 1 ? x[i] : 2)); testPermuteOp>(name, (x, y) => Simd.Insert(x, 1, (uint )2), (i, x, y) => (uint )(i != 1 ? x[i] : 2)); -#if Broken testPermuteOp>(name, (x, y) => Simd.Insert(x, 3, Simd.Extract(y, 1)), (i, x, y) => (float )(i != 3 ? x[i] : y[1])); testPermuteOp>(name, (x, y) => Simd.Insert(x, 0, Simd.Extract(y, 1)), (i, x, y) => (double)(i != 0 ? x[i] : y[1])); @@ -1565,7 +1562,6 @@ static void TestInsert() testThrowsArgumentOutOfRangeException, Vector64< ushort>>(name, (x, y) => Simd.Insert(x, 4, (ushort)1)); testThrowsArgumentOutOfRangeException, Vector64< int >>(name, (x, y) => Simd.Insert(x, 2, (int )1)); testThrowsArgumentOutOfRangeException, Vector64< uint >>(name, (x, y) => Simd.Insert(x, 2, (uint )1)); -#endif testThrowsTypeNotSupported>(name, (x, y) => Simd.Insert(x, 1, true)); testThrowsTypeNotSupported>(name, (x, y) => Simd.Insert(x, 1, ( long )5)); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Compare.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Compare.cs index bae45ccc0c0d..ad9ae5f1cfed 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx/Compare.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/Compare.cs @@ -28,12 +28,12 @@ static unsafe int Main(string[] args) var vf1 = Unsafe.Read>(floatTable.inArray1Ptr); var vf2 = Unsafe.Read>(floatTable.inArray2Ptr); - var vf3 = Avx.Compare(vf1, vf2, FloatComparisonMode.EqualOrderedNonSignaling); + var vf3 = Avx.Compare(vf1, vf2, FloatComparisonMode.OrderedEqualNonSignaling); Unsafe.Write(floatTable.outArrayPtr, vf3); var vd1 = Unsafe.Read>(doubleTable.inArray1Ptr); var vd2 = Unsafe.Read>(doubleTable.inArray2Ptr); - var vd3 = Avx.Compare(vd1, vd2, FloatComparisonMode.EqualOrderedNonSignaling); + var vd3 = Avx.Compare(vd1, vd2, FloatComparisonMode.OrderedEqualNonSignaling); Unsafe.Write(doubleTable.outArrayPtr, vd3); for (int i = 0; i < floatTable.outArray.Length; i++) @@ -66,12 +66,12 @@ static unsafe int Main(string[] args) var svf1 = Unsafe.Read>(floatTable.inArray1Ptr); var svf2 = Unsafe.Read>(floatTable.inArray2Ptr); - var svf3 = Avx.Compare(svf1, svf2, FloatComparisonMode.EqualOrderedNonSignaling); + var svf3 = Avx.Compare(svf1, svf2, FloatComparisonMode.OrderedEqualNonSignaling); Unsafe.Write(floatTable.outArrayPtr, svf3); var svd1 = Unsafe.Read>(doubleTable.inArray1Ptr); var svd2 = Unsafe.Read>(doubleTable.inArray2Ptr); - var svd3 = Avx.Compare(svd1, svd2, FloatComparisonMode.EqualOrderedNonSignaling); + var svd3 = Avx.Compare(svd1, svd2, FloatComparisonMode.OrderedEqualNonSignaling); Unsafe.Write(doubleTable.outArrayPtr, svd3); for (int i = 0; i < floatTable.outArray.Length/2; i++) diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx/CompareScalar.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx/CompareScalar.cs index 255b3e61c93a..c9b64abdcb4e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx/CompareScalar.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx/CompareScalar.cs @@ -28,12 +28,12 @@ static unsafe int Main(string[] args) var vf1 = Unsafe.Read>(floatTable.inArray1Ptr); var vf2 = Unsafe.Read>(floatTable.inArray2Ptr); - var vf3 = Avx.CompareScalar(vf1, vf2, FloatComparisonMode.EqualOrderedNonSignaling); + var vf3 = Avx.CompareScalar(vf1, vf2, FloatComparisonMode.OrderedEqualNonSignaling); Unsafe.Write(floatTable.outArrayPtr, vf3); var vd1 = Unsafe.Read>(doubleTable.inArray1Ptr); var vd2 = Unsafe.Read>(doubleTable.inArray2Ptr); - var vd3 = Avx.CompareScalar(vd1, vd2, FloatComparisonMode.EqualOrderedNonSignaling); + var vd3 = Avx.CompareScalar(vd1, vd2, FloatComparisonMode.OrderedEqualNonSignaling); Unsafe.Write(doubleTable.outArrayPtr, vd3); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt16.Byte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int16.Byte.cs similarity index 88% rename from tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt16.Byte.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int16.Byte.cs index 682b76a89402..ebaea926c647 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt16.Byte.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int16.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void ConvertToVector256UInt16Byte() + private static void ConvertToVector256Int16Byte() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt16Byte(); + var test = new SimpleUnaryOpTest__ConvertToVector256Int16Byte(); if (test.IsSupported) { @@ -83,7 +83,7 @@ private static void ConvertToVector256UInt16Byte() } } - public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt16Byte + public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256Int16Byte { private const int VectorSize = 32; @@ -98,7 +98,7 @@ public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt16Byte private SimpleUnaryOpTest__DataTable _dataTable; - static SimpleUnaryOpTest__ConvertToVector256UInt16Byte() + static SimpleUnaryOpTest__ConvertToVector256Int16Byte() { var random = new Random(); @@ -106,7 +106,7 @@ static SimpleUnaryOpTest__ConvertToVector256UInt16Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), 16); } - public SimpleUnaryOpTest__ConvertToVector256UInt16Byte() + public SimpleUnaryOpTest__ConvertToVector256Int16Byte() { Succeeded = true; @@ -125,7 +125,7 @@ public SimpleUnaryOpTest__ConvertToVector256UInt16Byte() public void RunBasicScenario_UnsafeRead() { - var result = Avx2.ConvertToVector256UInt16( + var result = Avx2.ConvertToVector256Int16( Unsafe.Read>(_dataTable.inArrayPtr) ); @@ -135,7 +135,7 @@ public void RunBasicScenario_UnsafeRead() public void RunBasicScenario_Load() { - var result = Avx2.ConvertToVector256UInt16( + var result = Avx2.ConvertToVector256Int16( Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)) ); @@ -145,7 +145,7 @@ public void RunBasicScenario_Load() public void RunBasicScenario_LoadAligned() { - var result = Avx2.ConvertToVector256UInt16( + var result = Avx2.ConvertToVector256Int16( Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)) ); @@ -155,40 +155,40 @@ public void RunBasicScenario_LoadAligned() public void RunReflectionScenario_UnsafeRead() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt16), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int16), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArrayPtr) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_Load() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt16), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int16), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_LoadAligned() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt16), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int16), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunClsVarScenario() { - var result = Avx2.ConvertToVector256UInt16( + var result = Avx2.ConvertToVector256Int16( _clsVar ); @@ -199,7 +199,7 @@ public void RunClsVarScenario() public void RunLclVarScenario_UnsafeRead() { var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); - var result = Avx2.ConvertToVector256UInt16(firstOp); + var result = Avx2.ConvertToVector256Int16(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -208,7 +208,7 @@ public void RunLclVarScenario_UnsafeRead() public void RunLclVarScenario_Load() { var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt16(firstOp); + var result = Avx2.ConvertToVector256Int16(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -217,7 +217,7 @@ public void RunLclVarScenario_Load() public void RunLclVarScenario_LoadAligned() { var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt16(firstOp); + var result = Avx2.ConvertToVector256Int16(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -225,8 +225,8 @@ public void RunLclVarScenario_LoadAligned() public void RunLclFldScenario() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt16Byte(); - var result = Avx2.ConvertToVector256UInt16(test._fld); + var test = new SimpleUnaryOpTest__ConvertToVector256Int16Byte(); + var result = Avx2.ConvertToVector256Int16(test._fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld, _dataTable.outArrayPtr); @@ -234,7 +234,7 @@ public void RunLclFldScenario() public void RunFldScenario() { - var result = Avx2.ConvertToVector256UInt16(_fld); + var result = Avx2.ConvertToVector256Int16(_fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld, _dataTable.outArrayPtr); @@ -296,7 +296,7 @@ private void ValidateResult(Byte[] firstOp, UInt16[] result, [CallerMemberName] if (!Succeeded) { - Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256UInt16)}(Vector128): {method} failed:"); + Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256Int16)}(Vector128): {method} failed:"); Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); Console.WriteLine($" result: ({string.Join(", ", result)})"); Console.WriteLine(); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt32.Byte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int32.Byte.cs similarity index 88% rename from tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt32.Byte.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int32.Byte.cs index 89202c2f1eb7..172ce8539d16 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt32.Byte.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int32.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void ConvertToVector256UInt32Byte() + private static void ConvertToVector256Int32Byte() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt32Byte(); + var test = new SimpleUnaryOpTest__ConvertToVector256Int32Byte(); if (test.IsSupported) { @@ -83,7 +83,7 @@ private static void ConvertToVector256UInt32Byte() } } - public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt32Byte + public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256Int32Byte { private const int VectorSize = 32; @@ -98,7 +98,7 @@ public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt32Byte private SimpleUnaryOpTest__DataTable _dataTable; - static SimpleUnaryOpTest__ConvertToVector256UInt32Byte() + static SimpleUnaryOpTest__ConvertToVector256Int32Byte() { var random = new Random(); @@ -106,7 +106,7 @@ static SimpleUnaryOpTest__ConvertToVector256UInt32Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), 16); } - public SimpleUnaryOpTest__ConvertToVector256UInt32Byte() + public SimpleUnaryOpTest__ConvertToVector256Int32Byte() { Succeeded = true; @@ -125,7 +125,7 @@ public SimpleUnaryOpTest__ConvertToVector256UInt32Byte() public void RunBasicScenario_UnsafeRead() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( Unsafe.Read>(_dataTable.inArrayPtr) ); @@ -135,7 +135,7 @@ public void RunBasicScenario_UnsafeRead() public void RunBasicScenario_Load() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)) ); @@ -145,7 +145,7 @@ public void RunBasicScenario_Load() public void RunBasicScenario_LoadAligned() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)) ); @@ -155,40 +155,40 @@ public void RunBasicScenario_LoadAligned() public void RunReflectionScenario_UnsafeRead() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt32), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int32), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArrayPtr) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_Load() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt32), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int32), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_LoadAligned() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt32), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int32), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunClsVarScenario() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( _clsVar ); @@ -199,7 +199,7 @@ public void RunClsVarScenario() public void RunLclVarScenario_UnsafeRead() { var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); - var result = Avx2.ConvertToVector256UInt32(firstOp); + var result = Avx2.ConvertToVector256Int32(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -208,7 +208,7 @@ public void RunLclVarScenario_UnsafeRead() public void RunLclVarScenario_Load() { var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt32(firstOp); + var result = Avx2.ConvertToVector256Int32(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -217,7 +217,7 @@ public void RunLclVarScenario_Load() public void RunLclVarScenario_LoadAligned() { var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt32(firstOp); + var result = Avx2.ConvertToVector256Int32(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -225,8 +225,8 @@ public void RunLclVarScenario_LoadAligned() public void RunLclFldScenario() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt32Byte(); - var result = Avx2.ConvertToVector256UInt32(test._fld); + var test = new SimpleUnaryOpTest__ConvertToVector256Int32Byte(); + var result = Avx2.ConvertToVector256Int32(test._fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld, _dataTable.outArrayPtr); @@ -234,7 +234,7 @@ public void RunLclFldScenario() public void RunFldScenario() { - var result = Avx2.ConvertToVector256UInt32(_fld); + var result = Avx2.ConvertToVector256Int32(_fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld, _dataTable.outArrayPtr); @@ -296,7 +296,7 @@ private void ValidateResult(Byte[] firstOp, UInt32[] result, [CallerMemberName] if (!Succeeded) { - Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256UInt32)}(Vector128): {method} failed:"); + Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256Int32)}(Vector128): {method} failed:"); Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); Console.WriteLine($" result: ({string.Join(", ", result)})"); Console.WriteLine(); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt32.UInt16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int32.UInt16.cs similarity index 88% rename from tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt32.UInt16.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int32.UInt16.cs index afb35c6404f0..8020d84a9110 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt32.UInt16.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int32.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void ConvertToVector256UInt32UInt16() + private static void ConvertToVector256Int32UInt16() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt32UInt16(); + var test = new SimpleUnaryOpTest__ConvertToVector256Int32UInt16(); if (test.IsSupported) { @@ -83,7 +83,7 @@ private static void ConvertToVector256UInt32UInt16() } } - public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt32UInt16 + public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256Int32UInt16 { private const int VectorSize = 32; @@ -98,7 +98,7 @@ public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt32UInt16 private SimpleUnaryOpTest__DataTable _dataTable; - static SimpleUnaryOpTest__ConvertToVector256UInt32UInt16() + static SimpleUnaryOpTest__ConvertToVector256Int32UInt16() { var random = new Random(); @@ -106,7 +106,7 @@ static SimpleUnaryOpTest__ConvertToVector256UInt32UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), 16); } - public SimpleUnaryOpTest__ConvertToVector256UInt32UInt16() + public SimpleUnaryOpTest__ConvertToVector256Int32UInt16() { Succeeded = true; @@ -125,7 +125,7 @@ public SimpleUnaryOpTest__ConvertToVector256UInt32UInt16() public void RunBasicScenario_UnsafeRead() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( Unsafe.Read>(_dataTable.inArrayPtr) ); @@ -135,7 +135,7 @@ public void RunBasicScenario_UnsafeRead() public void RunBasicScenario_Load() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)) ); @@ -145,7 +145,7 @@ public void RunBasicScenario_Load() public void RunBasicScenario_LoadAligned() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)) ); @@ -155,40 +155,40 @@ public void RunBasicScenario_LoadAligned() public void RunReflectionScenario_UnsafeRead() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt32), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int32), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArrayPtr) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_Load() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt32), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int32), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_LoadAligned() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt32), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int32), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunClsVarScenario() { - var result = Avx2.ConvertToVector256UInt32( + var result = Avx2.ConvertToVector256Int32( _clsVar ); @@ -199,7 +199,7 @@ public void RunClsVarScenario() public void RunLclVarScenario_UnsafeRead() { var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); - var result = Avx2.ConvertToVector256UInt32(firstOp); + var result = Avx2.ConvertToVector256Int32(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -208,7 +208,7 @@ public void RunLclVarScenario_UnsafeRead() public void RunLclVarScenario_Load() { var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt32(firstOp); + var result = Avx2.ConvertToVector256Int32(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -217,7 +217,7 @@ public void RunLclVarScenario_Load() public void RunLclVarScenario_LoadAligned() { var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt32(firstOp); + var result = Avx2.ConvertToVector256Int32(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -225,8 +225,8 @@ public void RunLclVarScenario_LoadAligned() public void RunLclFldScenario() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt32UInt16(); - var result = Avx2.ConvertToVector256UInt32(test._fld); + var test = new SimpleUnaryOpTest__ConvertToVector256Int32UInt16(); + var result = Avx2.ConvertToVector256Int32(test._fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld, _dataTable.outArrayPtr); @@ -234,7 +234,7 @@ public void RunLclFldScenario() public void RunFldScenario() { - var result = Avx2.ConvertToVector256UInt32(_fld); + var result = Avx2.ConvertToVector256Int32(_fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld, _dataTable.outArrayPtr); @@ -296,7 +296,7 @@ private void ValidateResult(UInt16[] firstOp, UInt32[] result, [CallerMemberName if (!Succeeded) { - Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256UInt32)}(Vector128): {method} failed:"); + Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256Int32)}(Vector128): {method} failed:"); Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); Console.WriteLine($" result: ({string.Join(", ", result)})"); Console.WriteLine(); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.Byte.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.Byte.cs similarity index 88% rename from tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.Byte.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.Byte.cs index 4d95740aaa81..80c10fed288e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.Byte.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.Byte.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void ConvertToVector256UInt64Byte() + private static void ConvertToVector256Int64Byte() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt64Byte(); + var test = new SimpleUnaryOpTest__ConvertToVector256Int64Byte(); if (test.IsSupported) { @@ -83,7 +83,7 @@ private static void ConvertToVector256UInt64Byte() } } - public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt64Byte + public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256Int64Byte { private const int VectorSize = 32; @@ -98,7 +98,7 @@ public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt64Byte private SimpleUnaryOpTest__DataTable _dataTable; - static SimpleUnaryOpTest__ConvertToVector256UInt64Byte() + static SimpleUnaryOpTest__ConvertToVector256Int64Byte() { var random = new Random(); @@ -106,7 +106,7 @@ static SimpleUnaryOpTest__ConvertToVector256UInt64Byte() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), 16); } - public SimpleUnaryOpTest__ConvertToVector256UInt64Byte() + public SimpleUnaryOpTest__ConvertToVector256Int64Byte() { Succeeded = true; @@ -125,7 +125,7 @@ public SimpleUnaryOpTest__ConvertToVector256UInt64Byte() public void RunBasicScenario_UnsafeRead() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Unsafe.Read>(_dataTable.inArrayPtr) ); @@ -135,7 +135,7 @@ public void RunBasicScenario_UnsafeRead() public void RunBasicScenario_Load() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)) ); @@ -145,7 +145,7 @@ public void RunBasicScenario_Load() public void RunBasicScenario_LoadAligned() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)) ); @@ -155,40 +155,40 @@ public void RunBasicScenario_LoadAligned() public void RunReflectionScenario_UnsafeRead() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArrayPtr) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_Load() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_LoadAligned() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunClsVarScenario() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( _clsVar ); @@ -199,7 +199,7 @@ public void RunClsVarScenario() public void RunLclVarScenario_UnsafeRead() { var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -208,7 +208,7 @@ public void RunLclVarScenario_UnsafeRead() public void RunLclVarScenario_Load() { var firstOp = Sse2.LoadVector128((Byte*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -217,7 +217,7 @@ public void RunLclVarScenario_Load() public void RunLclVarScenario_LoadAligned() { var firstOp = Sse2.LoadAlignedVector128((Byte*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -225,8 +225,8 @@ public void RunLclVarScenario_LoadAligned() public void RunLclFldScenario() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt64Byte(); - var result = Avx2.ConvertToVector256UInt64(test._fld); + var test = new SimpleUnaryOpTest__ConvertToVector256Int64Byte(); + var result = Avx2.ConvertToVector256Int64(test._fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld, _dataTable.outArrayPtr); @@ -234,7 +234,7 @@ public void RunLclFldScenario() public void RunFldScenario() { - var result = Avx2.ConvertToVector256UInt64(_fld); + var result = Avx2.ConvertToVector256Int64(_fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld, _dataTable.outArrayPtr); @@ -296,7 +296,7 @@ private void ValidateResult(Byte[] firstOp, UInt64[] result, [CallerMemberName] if (!Succeeded) { - Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256UInt64)}(Vector128): {method} failed:"); + Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256Int64)}(Vector128): {method} failed:"); Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); Console.WriteLine($" result: ({string.Join(", ", result)})"); Console.WriteLine(); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.UInt16.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.UInt16.cs similarity index 88% rename from tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.UInt16.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.UInt16.cs index 48d5d7f95439..63a9e208231f 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.UInt16.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.UInt16.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void ConvertToVector256UInt64UInt16() + private static void ConvertToVector256Int64UInt16() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt64UInt16(); + var test = new SimpleUnaryOpTest__ConvertToVector256Int64UInt16(); if (test.IsSupported) { @@ -83,7 +83,7 @@ private static void ConvertToVector256UInt64UInt16() } } - public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt64UInt16 + public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256Int64UInt16 { private const int VectorSize = 32; @@ -98,7 +98,7 @@ public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt64UInt16 private SimpleUnaryOpTest__DataTable _dataTable; - static SimpleUnaryOpTest__ConvertToVector256UInt64UInt16() + static SimpleUnaryOpTest__ConvertToVector256Int64UInt16() { var random = new Random(); @@ -106,7 +106,7 @@ static SimpleUnaryOpTest__ConvertToVector256UInt64UInt16() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), 16); } - public SimpleUnaryOpTest__ConvertToVector256UInt64UInt16() + public SimpleUnaryOpTest__ConvertToVector256Int64UInt16() { Succeeded = true; @@ -125,7 +125,7 @@ public SimpleUnaryOpTest__ConvertToVector256UInt64UInt16() public void RunBasicScenario_UnsafeRead() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Unsafe.Read>(_dataTable.inArrayPtr) ); @@ -135,7 +135,7 @@ public void RunBasicScenario_UnsafeRead() public void RunBasicScenario_Load() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)) ); @@ -145,7 +145,7 @@ public void RunBasicScenario_Load() public void RunBasicScenario_LoadAligned() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)) ); @@ -155,40 +155,40 @@ public void RunBasicScenario_LoadAligned() public void RunReflectionScenario_UnsafeRead() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArrayPtr) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_Load() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_LoadAligned() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunClsVarScenario() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( _clsVar ); @@ -199,7 +199,7 @@ public void RunClsVarScenario() public void RunLclVarScenario_UnsafeRead() { var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -208,7 +208,7 @@ public void RunLclVarScenario_UnsafeRead() public void RunLclVarScenario_Load() { var firstOp = Sse2.LoadVector128((UInt16*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -217,7 +217,7 @@ public void RunLclVarScenario_Load() public void RunLclVarScenario_LoadAligned() { var firstOp = Sse2.LoadAlignedVector128((UInt16*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -225,8 +225,8 @@ public void RunLclVarScenario_LoadAligned() public void RunLclFldScenario() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt64UInt16(); - var result = Avx2.ConvertToVector256UInt64(test._fld); + var test = new SimpleUnaryOpTest__ConvertToVector256Int64UInt16(); + var result = Avx2.ConvertToVector256Int64(test._fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld, _dataTable.outArrayPtr); @@ -234,7 +234,7 @@ public void RunLclFldScenario() public void RunFldScenario() { - var result = Avx2.ConvertToVector256UInt64(_fld); + var result = Avx2.ConvertToVector256Int64(_fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld, _dataTable.outArrayPtr); @@ -296,7 +296,7 @@ private void ValidateResult(UInt16[] firstOp, UInt64[] result, [CallerMemberName if (!Succeeded) { - Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256UInt64)}(Vector128): {method} failed:"); + Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256Int64)}(Vector128): {method} failed:"); Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); Console.WriteLine($" result: ({string.Join(", ", result)})"); Console.WriteLine(); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.UInt32.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.UInt32.cs similarity index 88% rename from tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.UInt32.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.UInt32.cs index 67f361b4f170..2fd078610bcb 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256UInt64.UInt32.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256Int64.UInt32.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void ConvertToVector256UInt64UInt32() + private static void ConvertToVector256Int64UInt32() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt64UInt32(); + var test = new SimpleUnaryOpTest__ConvertToVector256Int64UInt32(); if (test.IsSupported) { @@ -83,7 +83,7 @@ private static void ConvertToVector256UInt64UInt32() } } - public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt64UInt32 + public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256Int64UInt32 { private const int VectorSize = 32; @@ -98,7 +98,7 @@ public sealed unsafe class SimpleUnaryOpTest__ConvertToVector256UInt64UInt32 private SimpleUnaryOpTest__DataTable _dataTable; - static SimpleUnaryOpTest__ConvertToVector256UInt64UInt32() + static SimpleUnaryOpTest__ConvertToVector256Int64UInt32() { var random = new Random(); @@ -106,7 +106,7 @@ static SimpleUnaryOpTest__ConvertToVector256UInt64UInt32() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar), ref Unsafe.As(ref _data[0]), 16); } - public SimpleUnaryOpTest__ConvertToVector256UInt64UInt32() + public SimpleUnaryOpTest__ConvertToVector256Int64UInt32() { Succeeded = true; @@ -125,7 +125,7 @@ public SimpleUnaryOpTest__ConvertToVector256UInt64UInt32() public void RunBasicScenario_UnsafeRead() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Unsafe.Read>(_dataTable.inArrayPtr) ); @@ -135,7 +135,7 @@ public void RunBasicScenario_UnsafeRead() public void RunBasicScenario_Load() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)) ); @@ -145,7 +145,7 @@ public void RunBasicScenario_Load() public void RunBasicScenario_LoadAligned() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)) ); @@ -155,40 +155,40 @@ public void RunBasicScenario_LoadAligned() public void RunReflectionScenario_UnsafeRead() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArrayPtr) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_Load() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunReflectionScenario_LoadAligned() { - var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256UInt64), new Type[] { typeof(Vector128) }) + var result = typeof(Avx2).GetMethod(nameof(Avx2.ConvertToVector256Int64), new Type[] { typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)) }); - Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); + Unsafe.Write(_dataTable.outArrayPtr, (Vector256)(result)); ValidateResult(_dataTable.inArrayPtr, _dataTable.outArrayPtr); } public void RunClsVarScenario() { - var result = Avx2.ConvertToVector256UInt64( + var result = Avx2.ConvertToVector256Int64( _clsVar ); @@ -199,7 +199,7 @@ public void RunClsVarScenario() public void RunLclVarScenario_UnsafeRead() { var firstOp = Unsafe.Read>(_dataTable.inArrayPtr); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -208,7 +208,7 @@ public void RunLclVarScenario_UnsafeRead() public void RunLclVarScenario_Load() { var firstOp = Sse2.LoadVector128((UInt32*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -217,7 +217,7 @@ public void RunLclVarScenario_Load() public void RunLclVarScenario_LoadAligned() { var firstOp = Sse2.LoadAlignedVector128((UInt32*)(_dataTable.inArrayPtr)); - var result = Avx2.ConvertToVector256UInt64(firstOp); + var result = Avx2.ConvertToVector256Int64(firstOp); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(firstOp, _dataTable.outArrayPtr); @@ -225,8 +225,8 @@ public void RunLclVarScenario_LoadAligned() public void RunLclFldScenario() { - var test = new SimpleUnaryOpTest__ConvertToVector256UInt64UInt32(); - var result = Avx2.ConvertToVector256UInt64(test._fld); + var test = new SimpleUnaryOpTest__ConvertToVector256Int64UInt32(); + var result = Avx2.ConvertToVector256Int64(test._fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld, _dataTable.outArrayPtr); @@ -234,7 +234,7 @@ public void RunLclFldScenario() public void RunFldScenario() { - var result = Avx2.ConvertToVector256UInt64(_fld); + var result = Avx2.ConvertToVector256Int64(_fld); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld, _dataTable.outArrayPtr); @@ -296,7 +296,7 @@ private void ValidateResult(UInt32[] firstOp, UInt64[] result, [CallerMemberName if (!Succeeded) { - Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256UInt64)}(Vector128): {method} failed:"); + Console.WriteLine($"{nameof(Avx2)}.{nameof(Avx2.ConvertToVector256Int64)}(Vector128): {method} failed:"); Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})"); Console.WriteLine($" result: ({string.Join(", ", result)})"); Console.WriteLine(); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_r.csproj index a866a5ed3dab..b5063d619bda 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_r.csproj @@ -27,18 +27,18 @@ - + - + - - + + - - + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_ro.csproj index 7d07e72af171..104f22db3b19 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/ConvertToVector256_ro.csproj @@ -27,18 +27,18 @@ - + - + - - + + - - + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/Program.ConvertToVector256.cs b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/Program.ConvertToVector256.cs index 0848ebb1be4c..c41b6cd616c9 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Avx2/Program.ConvertToVector256.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Avx2/Program.ConvertToVector256.cs @@ -12,18 +12,18 @@ public static partial class Program static Program() { TestList = new Dictionary() { - ["ConvertToVector256UInt16.Byte"] = ConvertToVector256UInt16Byte, + ["ConvertToVector256Int16.Byte"] = ConvertToVector256Int16Byte, ["ConvertToVector256Int16.SByte"] = ConvertToVector256Int16SByte, - ["ConvertToVector256UInt32.Byte"] = ConvertToVector256UInt32Byte, + ["ConvertToVector256Int32.Byte"] = ConvertToVector256Int32Byte, ["ConvertToVector256Int32.Int16"] = ConvertToVector256Int32Int16, ["ConvertToVector256Int32.SByte"] = ConvertToVector256Int32SByte, - ["ConvertToVector256UInt32.UInt16"] = ConvertToVector256UInt32UInt16, - ["ConvertToVector256UInt64.Byte"] = ConvertToVector256UInt64Byte, + ["ConvertToVector256Int32.UInt16"] = ConvertToVector256Int32UInt16, + ["ConvertToVector256Int64.Byte"] = ConvertToVector256Int64Byte, ["ConvertToVector256Int64.Int16"] = ConvertToVector256Int64Int16, ["ConvertToVector256Int64.Int32"] = ConvertToVector256Int64Int32, ["ConvertToVector256Int64.SByte"] = ConvertToVector256Int64SByte, - ["ConvertToVector256UInt64.UInt16"] = ConvertToVector256UInt64UInt16, - ["ConvertToVector256UInt64.UInt32"] = ConvertToVector256UInt64UInt32, + ["ConvertToVector256Int64.UInt16"] = ConvertToVector256Int64UInt16, + ["ConvertToVector256Int64.UInt32"] = ConvertToVector256Int64UInt32, }; } } diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx index db492c0daa9e..ee4460283a89 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx +++ b/tests/src/JIT/HardwareIntrinsics/X86/Shared/GenerateTests.csx @@ -26,41 +26,41 @@ private static readonly (string templateFileName, Dictionary tem ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "And", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(BitConverter.SingleToInt32Bits(left[0]) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(BitConverter.SingleToInt32Bits(left[0]) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "AndNot", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(~BitConverter.SingleToInt32Bits(left[0]) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "(~BitConverter.SingleToInt32Bits(left[0]) & BitConverter.SingleToInt32Bits(right[0])) != BitConverter.SingleToInt32Bits(result[0])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] == right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrderedEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnorderedEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] > right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrderedGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnorderedGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] >= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanOrEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareGreaterThanOrEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrderedGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnorderedGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] < right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrderedLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnorderedLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] <= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanOrEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareLessThanOrEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrderedLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnorderedLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((left[i] != right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrderedNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnorderedNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] > right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotGreaterThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarNotGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] >= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarNotGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] < right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotLessThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarNotLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != (!(left[i] <= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareNotLessThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarNotLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareOrdered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((!float.IsNaN(left[0]) && !float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((!float.IsNaN(left[i]) && !float.IsNaN(right[i])) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((!float.IsNaN(left[0]) && !float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarOrdered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((!float.IsNaN(left[0]) && !float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareUnordered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((float.IsNaN(left[0]) || float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(result[i]) != ((float.IsNaN(left[i]) || float.IsNaN(right[i])) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((float.IsNaN(left[0]) || float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "CompareScalarUnordered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(result[0]) != ((float.IsNaN(left[0]) || float.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpConvTest.template",new Dictionary{["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "ConvertScalarToVector128Single", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "(float)right != result[0]"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "Divide", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] / right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i] / right[i]) != BitConverter.SingleToInt32Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse", ["LoadIsa"] = "Sse", ["Method"] = "DivideScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Single", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Single", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Single", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSingle()", ["NextValueOp2"] = "TestLibrary.Generator.GetSingle()", ["ValidateFirstResult"] = "BitConverter.SingleToInt32Bits(left[0] / right[0]) != BitConverter.SingleToInt32Bits(result[0])", ["ValidateRemainingResults"] = "BitConverter.SingleToInt32Bits(left[i]) != BitConverter.SingleToInt32Bits(result[i])"}), @@ -128,47 +128,47 @@ private static readonly (string templateFileName, Dictionary tem ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((sbyte)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((sbyte)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt16()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((ushort)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((ushort)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "UInt32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "UInt32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "UInt32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetUInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetUInt32()", ["ValidateFirstResult"] = "result[0] != ((left[0] == right[0]) ? unchecked((uint)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] == right[i]) ? unchecked((uint)(-1)) : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] == right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrderedEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnorderedEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] == right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] > right[i]) ? -1 : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != ((left[0] > right[0]) ? unchecked((short)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] > right[i]) ? unchecked((short)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != ((left[0] > right[0]) ? unchecked((int)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] > right[i]) ? unchecked((int)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != ((left[0] > right[0]) ? unchecked((sbyte)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] > right[i]) ? unchecked((sbyte)(-1)) : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrderedGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnorderedGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] > right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] >= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanOrEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareGreaterThanOrEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrderedGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnorderedGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] >= right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] < right[i]) ? -1 : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int16", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int16", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int16", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt16()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt16()", ["ValidateFirstResult"] = "result[0] != ((left[0] < right[0]) ? unchecked((short)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] < right[i]) ? unchecked((short)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["NextValueOp2"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "result[0] != ((left[0] < right[0]) ? unchecked((int)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] < right[i]) ? unchecked((int)(-1)) : 0)"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "SByte", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "SByte", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "SByte", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetSByte()", ["NextValueOp2"] = "TestLibrary.Generator.GetSByte()", ["ValidateFirstResult"] = "result[0] != ((left[0] < right[0]) ? unchecked((sbyte)(-1)) : 0)", ["ValidateRemainingResults"] = "result[i] != ((left[i] < right[i]) ? unchecked((sbyte)(-1)) : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrderedLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnorderedLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] < right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] <= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanOrEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareLessThanOrEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrderedLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnorderedLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] <= right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((left[i] != right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotEqualOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), - ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotEqualUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((left[0] != right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrderedNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), + ("BooleanCmpOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnorderedNotEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Boolean",["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(left[0] != right[0]) != result"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] > right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotGreaterThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarNotGreaterThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] > right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] >= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotGreaterThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarNotGreaterThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] >= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] < right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotLessThanScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarNotLessThan", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] < right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != (!(left[i] <= right[i]) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareNotLessThanOrEqualScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarNotLessThanOrEqual", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != (!(left[0] <= right[0]) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareOrdered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((!double.IsNaN(left[0]) && !double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((!double.IsNaN(left[i]) && !double.IsNaN(right[i])) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareOrderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((!double.IsNaN(left[0]) && !double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarOrdered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((!double.IsNaN(left[0]) && !double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareUnordered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((double.IsNaN(left[0]) || double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(result[i]) != ((double.IsNaN(left[i]) || double.IsNaN(right[i])) ? -1 : 0)"}), - ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareUnorderedScalar", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((double.IsNaN(left[0]) || double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), + ("SimpleBinOpTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "CompareScalarUnordered", ["RetVectorType"] = "Vector128", ["RetBaseType"] = "Double", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["Op2VectorType"] = "Vector128", ["Op2BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["NextValueOp2"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "BitConverter.DoubleToInt64Bits(result[0]) != ((double.IsNaN(left[0]) || double.IsNaN(right[0])) ? -1 : 0)", ["ValidateRemainingResults"] = "BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i])"}), ("SimdScalarUnOpConvTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "ConvertToInt32", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(int)Math.Round(firstOp[0]) != result"}), ("SimdScalarUnOpConvTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "ConvertToInt32", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Int32", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetInt32()", ["ValidateFirstResult"] = "firstOp[0] != result"}), ("SimdScalarUnOpConvTest.template", new Dictionary { ["Isa"] = "Sse2", ["LoadIsa"] = "Sse2", ["Method"] = "ConvertToInt32WithTruncation", ["RetBaseType"] = "Int32", ["Op1VectorType"] = "Vector128", ["Op1BaseType"] = "Double", ["LargestVectorSize"] = "16", ["NextValueOp1"] = "TestLibrary.Generator.GetDouble()", ["ValidateFirstResult"] = "(int) firstOp[0] != result"}), diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarEqual.Single.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarEqual.Single.cs index 7dda69629876..a6da8fbba20d 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarEqual.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareEqualScalarSingle() + private static void CompareScalarEqualSingle() { - var test = new SimpleBinaryOpTest__CompareEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarEqualSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareEqualScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareEqualScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarEqualSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareEqualScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarEqualSingle testClass) { - var result = Sse.CompareEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareEqualScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarEqualSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareEqualScalarSing private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareEqualScalarSingle() + static SimpleBinaryOpTest__CompareScalarEqualSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareEqualScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareEqualScalarSingle() + public SimpleBinaryOpTest__CompareScalarEqualSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareEqualScalar(left, right); + var result = Sse.CompareScalarEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareEqualScalar(left, right); + var result = Sse.CompareScalarEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareEqualScalar(left, right); + var result = Sse.CompareScalarEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareEqualScalarSingle(); - var result = Sse.CompareEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarEqualSingle(); + var result = Sse.CompareScalarEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarEqualSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareEqualScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareEqualScalar( + var result = Sse.CompareScalarEqual( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarGreaterThan.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarGreaterThan.Single.cs index 8828ab2965a1..d44cb8a30aad 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarGreaterThan.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanScalarSingle() + private static void CompareScalarGreaterThanSingle() { - var test = new SimpleBinaryOpTest__CompareGreaterThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareGreaterThanScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareGreaterThanScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarGreaterThanSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarGreaterThanSingle testClass) { - var result = Sse.CompareGreaterThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarGreaterThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarGreaterThanSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanScal private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareGreaterThanScalarSingle() + static SimpleBinaryOpTest__CompareScalarGreaterThanSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareGreaterThanScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareGreaterThanScalarSingle() + public SimpleBinaryOpTest__CompareScalarGreaterThanSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareGreaterThanScalar(left, right); + var result = Sse.CompareScalarGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanScalar(left, right); + var result = Sse.CompareScalarGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanScalar(left, right); + var result = Sse.CompareScalarGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareGreaterThanScalarSingle(); - var result = Sse.CompareGreaterThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanSingle(); + var result = Sse.CompareScalarGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareGreaterThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareGreaterThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarGreaterThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanScalar( + var result = Sse.CompareScalarGreaterThan( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareGreaterThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarGreaterThanOrEqual.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarGreaterThanOrEqual.Single.cs index 756e7c0f1cab..8bda7cb6629b 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarGreaterThanOrEqual.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrEqualScalarSingle() + private static void CompareScalarGreaterThanOrEqualSingle() { - var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareGreaterThanOrEqualScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle testClass) { - var result = Sse.CompareGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanOrEq private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle() + static SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle() + public SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareGreaterThanOrEqualScalar(left, right); + var result = Sse.CompareScalarGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrEqualScalar(left, right); + var result = Sse.CompareScalarGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrEqualScalar(left, right); + var result = Sse.CompareScalarGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle(); - var result = Sse.CompareGreaterThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle(); + var result = Sse.CompareScalarGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanOrEqualScalar( + var result = Sse.CompareScalarGreaterThanOrEqual( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareGreaterThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarLessThan.Single.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarLessThan.Single.cs index 5045993efa85..f85644d765a9 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarLessThan.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanScalarSingle() + private static void CompareScalarLessThanSingle() { - var test = new SimpleBinaryOpTest__CompareLessThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareLessThanScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareLessThanScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarLessThanSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarLessThanSingle testClass) { - var result = Sse.CompareLessThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarLessThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarLessThanSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanScalarS private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareLessThanScalarSingle() + static SimpleBinaryOpTest__CompareScalarLessThanSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareLessThanScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareLessThanScalarSingle() + public SimpleBinaryOpTest__CompareScalarLessThanSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareLessThanScalar(left, right); + var result = Sse.CompareScalarLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanScalar(left, right); + var result = Sse.CompareScalarLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanScalar(left, right); + var result = Sse.CompareScalarLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareLessThanScalarSingle(); - var result = Sse.CompareLessThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarLessThanSingle(); + var result = Sse.CompareScalarLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareLessThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareLessThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarLessThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanScalar( + var result = Sse.CompareScalarLessThan( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareLessThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarLessThanOrEqual.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarLessThanOrEqual.Single.cs index 9d2adcfcf17a..a730fd3a7d63 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarLessThanOrEqual.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrEqualScalarSingle() + private static void CompareScalarLessThanOrEqualSingle() { - var test = new SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareLessThanOrEqualScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle testClass) { - var result = Sse.CompareLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarLessThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanOrEqual private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle() + static SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle() + public SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareLessThanOrEqualScalar(left, right); + var result = Sse.CompareScalarLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrEqualScalar(left, right); + var result = Sse.CompareScalarLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrEqualScalar(left, right); + var result = Sse.CompareScalarLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle(); - var result = Sse.CompareLessThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle(); + var result = Sse.CompareScalarLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareLessThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanOrEqualSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarLessThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanOrEqualScalar( + var result = Sse.CompareScalarLessThanOrEqual( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareLessThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotEqual.Single.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotEqual.Single.cs index d026a9181013..8c69b8072eba 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotEqual.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotEqualScalarSingle() + private static void CompareScalarNotEqualSingle() { - var test = new SimpleBinaryOpTest__CompareNotEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotEqualSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotEqualScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotEqualScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotEqualSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotEqualScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotEqualSingle testClass) { - var result = Sse.CompareNotEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotEqualScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotEqualSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotEqualScalarS private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotEqualScalarSingle() + static SimpleBinaryOpTest__CompareScalarNotEqualSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotEqualScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotEqualScalarSingle() + public SimpleBinaryOpTest__CompareScalarNotEqualSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotEqualScalar(left, right); + var result = Sse.CompareScalarNotEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotEqualScalar(left, right); + var result = Sse.CompareScalarNotEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotEqualScalar(left, right); + var result = Sse.CompareScalarNotEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotEqualScalarSingle(); - var result = Sse.CompareNotEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotEqualSingle(); + var result = Sse.CompareScalarNotEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotEqualSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotEqualScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarNotEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareNotEqualScalar( + var result = Sse.CompareScalarNotEqual( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarNotEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotGreaterThanScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotGreaterThan.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotGreaterThanScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotGreaterThan.Single.cs index 7c6bc50a9af6..4e6de137714c 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotGreaterThanScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotGreaterThan.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotGreaterThanScalarSingle() + private static void CompareScalarNotGreaterThanSingle() { - var test = new SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotGreaterThanScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle testClass) { - var result = Sse.CompareNotGreaterThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotGreaterThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanS private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle() + static SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle() + public SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotGreaterThanScalar(left, right); + var result = Sse.CompareScalarNotGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotGreaterThanScalar(left, right); + var result = Sse.CompareScalarNotGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotGreaterThanScalar(left, right); + var result = Sse.CompareScalarNotGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle(); - var result = Sse.CompareNotGreaterThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle(); + var result = Sse.CompareScalarNotGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotGreaterThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotGreaterThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotGreaterThanScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarNotGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareNotGreaterThanScalar( + var result = Sse.CompareScalarNotGreaterThan( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotGreaterThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarNotGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotGreaterThanOrEqualScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotGreaterThanOrEqual.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotGreaterThanOrEqualScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotGreaterThanOrEqual.Single.cs index 68122a46852e..475c64232560 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotGreaterThanOrEqualScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotGreaterThanOrEqual.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotGreaterThanOrEqualScalarSingle() + private static void CompareScalarNotGreaterThanOrEqualSingle() { - var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotGreaterThanOrEqualScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle testClass) { - var result = Sse.CompareNotGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanO private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle() + static SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle() + public SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotGreaterThanOrEqualScalar(left, right); + var result = Sse.CompareScalarNotGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotGreaterThanOrEqualScalar(left, right); + var result = Sse.CompareScalarNotGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotGreaterThanOrEqualScalar(left, right); + var result = Sse.CompareScalarNotGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle(); - var result = Sse.CompareNotGreaterThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle(); + var result = Sse.CompareScalarNotGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotGreaterThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarNotGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareNotGreaterThanOrEqualScalar( + var result = Sse.CompareScalarNotGreaterThanOrEqual( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotGreaterThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarNotGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotLessThanScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotLessThan.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotLessThanScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotLessThan.Single.cs index ebda3d2d6eb0..4b92ff189ca8 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotLessThanScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotLessThan.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotLessThanScalarSingle() + private static void CompareScalarNotLessThanSingle() { - var test = new SimpleBinaryOpTest__CompareNotLessThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotLessThanScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotLessThanScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotLessThanSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotLessThanSingle testClass) { - var result = Sse.CompareNotLessThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotLessThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotLessThanSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanScal private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotLessThanScalarSingle() + static SimpleBinaryOpTest__CompareScalarNotLessThanSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotLessThanScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotLessThanScalarSingle() + public SimpleBinaryOpTest__CompareScalarNotLessThanSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotLessThanScalar(left, right); + var result = Sse.CompareScalarNotLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotLessThanScalar(left, right); + var result = Sse.CompareScalarNotLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotLessThanScalar(left, right); + var result = Sse.CompareScalarNotLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotLessThanScalarSingle(); - var result = Sse.CompareNotLessThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanSingle(); + var result = Sse.CompareScalarNotLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotLessThanScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotLessThanScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotLessThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotLessThanScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarNotLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareNotLessThanScalar( + var result = Sse.CompareScalarNotLessThan( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotLessThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarNotLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotLessThanOrEqualScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotLessThanOrEqual.Single.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotLessThanOrEqualScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotLessThanOrEqual.Single.cs index 29b731ae6485..71839f16f66e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotLessThanOrEqualScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarNotLessThanOrEqual.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotLessThanOrEqualScalarSingle() + private static void CompareScalarNotLessThanOrEqualSingle() { - var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotLessThanOrEqualScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle testClass) { - var result = Sse.CompareNotLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotLessThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanOrEq private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle() + static SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle() + public SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarNotLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotLessThanOrEqualScalar(left, right); + var result = Sse.CompareScalarNotLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotLessThanOrEqualScalar(left, right); + var result = Sse.CompareScalarNotLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotLessThanOrEqualScalar(left, right); + var result = Sse.CompareScalarNotLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle(); - var result = Sse.CompareNotLessThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle(); + var result = Sse.CompareScalarNotLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse.CompareScalarNotLessThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotLessThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarNotLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareNotLessThanOrEqualScalar( + var result = Sse.CompareScalarNotLessThanOrEqual( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotLessThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarNotLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareOrderedScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrdered.Single.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareOrderedScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrdered.Single.cs index d15259b6798c..6db1ad8495e3 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareOrderedScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrdered.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareOrderedScalarSingle() + private static void CompareScalarOrderedSingle() { - var test = new SimpleBinaryOpTest__CompareOrderedScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarOrderedSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareOrderedScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareOrderedScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarOrderedSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareOrderedScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarOrderedSingle testClass) { - var result = Sse.CompareOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrdered(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareOrderedScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarOrderedSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareOrderedScalarSi private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareOrderedScalarSingle() + static SimpleBinaryOpTest__CompareScalarOrderedSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareOrderedScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareOrderedScalarSingle() + public SimpleBinaryOpTest__CompareScalarOrderedSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrdered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrdered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrdered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareOrderedScalar(left, right); + var result = Sse.CompareScalarOrdered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareOrderedScalar(left, right); + var result = Sse.CompareScalarOrdered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareOrderedScalar(left, right); + var result = Sse.CompareScalarOrdered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareOrderedScalarSingle(); - var result = Sse.CompareOrderedScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarOrderedSingle(); + var result = Sse.CompareScalarOrdered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareOrderedScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarOrderedSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrdered(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrdered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareOrderedScalar( + var result = Sse.CompareScalarOrdered( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrdered)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedEqual.Boolean.cs index 71d650b7b6b0..01ef9f2dae43 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareEqualOrderedScalarBoolean() + private static void CompareScalarOrderedEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean testClass) { - var result = Sse.CompareEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualOrderedSca private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareEqualOrderedScalar( + var result = Sse.CompareScalarOrderedEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareEqualOrderedScalar( + var result = Sse.CompareScalarOrderedEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareEqualOrderedScalar( + var result = Sse.CompareScalarOrderedEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareEqualOrderedScalar( + var result = Sse.CompareScalarOrderedEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean(); - var result = Sse.CompareEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean(); + var result = Sse.CompareScalarOrderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] == right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrderedEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedGreaterThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedGreaterThan.Boolean.cs index 0ed6f13439ed..4b2b1a3b05b0 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedGreaterThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrderedScalarBoolean() + private static void CompareScalarOrderedGreaterThanBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean testClass) { - var result = Sse.CompareGreaterThanOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedGreaterThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrde private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareGreaterThanOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareGreaterThanOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareGreaterThanOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareGreaterThanOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareGreaterThanOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean(); - var result = Sse.CompareGreaterThanOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean(); + var result = Sse.CompareScalarOrderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareGreaterThanOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedGreaterThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] > right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareGreaterThanOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrderedGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedGreaterThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedGreaterThanOrEqual.Boolean.cs index 353e8f7290a7..92b6e015df0b 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedGreaterThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrEqualOrderedScalarBoolean() + private static void CompareScalarOrderedGreaterThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanOrEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean testClass) { - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEq private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean(); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean(); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanOrEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] >= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareGreaterThanOrEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrderedGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedLessThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedLessThan.Boolean.cs index d0bb4fa3842f..2724f73a73aa 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedLessThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrderedScalarBoolean() + private static void CompareScalarOrderedLessThanBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean testClass) { - var result = Sse.CompareLessThanOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedLessThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrdered private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareLessThanOrderedScalar( + var result = Sse.CompareScalarOrderedLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareLessThanOrderedScalar( + var result = Sse.CompareScalarOrderedLessThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareLessThanOrderedScalar( + var result = Sse.CompareScalarOrderedLessThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareLessThanOrderedScalar( + var result = Sse.CompareScalarOrderedLessThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareLessThanOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedLessThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedLessThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedLessThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean(); - var result = Sse.CompareLessThanOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean(); + var result = Sse.CompareScalarOrderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareLessThanOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedLessThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] < right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareLessThanOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrderedLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedLessThanOrEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedLessThanOrEqual.Boolean.cs index 80c55e6fa55f..00baaff03855 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedLessThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrEqualOrderedScalarBoolean() + private static void CompareScalarOrderedLessThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanOrEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean testClass) { - var result = Sse.CompareLessThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedLessThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqual private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareLessThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareLessThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedLessThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareLessThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedLessThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareLessThanOrEqualOrderedScalar( + var result = Sse.CompareScalarOrderedLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareLessThanOrEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean(); - var result = Sse.CompareLessThanOrEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean(); + var result = Sse.CompareScalarOrderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareLessThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedLessThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanOrEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] <= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareLessThanOrEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrderedLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedNotEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedNotEqual.Boolean.cs index fe4b03425354..e9c7bd84214b 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarOrderedNotEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotEqualOrderedScalarBoolean() + private static void CompareScalarOrderedNotEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareNotEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean testClass) { - var result = Sse.CompareNotEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedNotEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualOrdered private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotEqualOrderedScalar( + var result = Sse.CompareScalarOrderedNotEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotEqualOrderedScalar( + var result = Sse.CompareScalarOrderedNotEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotEqualOrderedScalar( + var result = Sse.CompareScalarOrderedNotEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarOrderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotEqualOrderedScalar( + var result = Sse.CompareScalarOrderedNotEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotEqualOrderedScalar(left, right); + var result = Sse.CompareScalarOrderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean(); - var result = Sse.CompareNotEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean(); + var result = Sse.CompareScalarOrderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotEqualOrderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarOrderedNotEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarOrderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] != right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarOrderedNotEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareUnorderedScalar.Single.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnordered.Single.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareUnorderedScalar.Single.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnordered.Single.cs index 14cc9d137c70..4f51678d4275 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareUnorderedScalar.Single.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnordered.Single.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareUnorderedScalarSingle() + private static void CompareScalarUnorderedSingle() { - var test = new SimpleBinaryOpTest__CompareUnorderedScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarUnorderedSingle(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareUnorderedScalarSingle() } } - public sealed unsafe class SimpleBinaryOpTest__CompareUnorderedScalarSingle + public sealed unsafe class SimpleBinaryOpTest__CompareScalarUnorderedSingle { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareUnorderedScalarSingle testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarUnorderedSingle testClass) { - var result = Sse.CompareUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnordered(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareUnorderedScalarSingle testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarUnorderedSingle testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareUnorderedScalar private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareUnorderedScalarSingle() + static SimpleBinaryOpTest__CompareScalarUnorderedSingle() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareUnorderedScalarSingle() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareUnorderedScalarSingle() + public SimpleBinaryOpTest__CompareScalarUnorderedSingle() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnordered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnordered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnordered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadVector128((Single*)(pClsVar1)), Sse.LoadVector128((Single*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareUnorderedScalar(left, right); + var result = Sse.CompareScalarUnordered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareUnorderedScalar(left, right); + var result = Sse.CompareScalarUnordered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareUnorderedScalar(left, right); + var result = Sse.CompareScalarUnordered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareUnorderedScalarSingle(); - var result = Sse.CompareUnorderedScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarUnorderedSingle(); + var result = Sse.CompareScalarUnordered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareUnorderedScalarSingle(); + var test = new SimpleBinaryOpTest__CompareScalarUnorderedSingle(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnordered(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadVector128((Single*)(pFld1)), Sse.LoadVector128((Single*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnordered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse.CompareUnorderedScalar( + var result = Sse.CompareScalarUnordered( Sse.LoadVector128((Single*)(&test._fld1)), Sse.LoadVector128((Single*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Single[] left, Single[] right, Single[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnordered)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedEqual.Boolean.cs index 535755efc8e9..d33a057fda91 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean testClass) { - var result = Sse.CompareEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualUnorderedS private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean(); - var result = Sse.CompareEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean(); + var result = Sse.CompareScalarUnorderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnorderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] == right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnorderedEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedGreaterThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedGreaterThan.Boolean.cs index da2ffd63c172..8ee255685cbb 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedGreaterThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanUnorderedScalarBoolean() + private static void CompareScalarUnorderedGreaterThanBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean testClass) { - var result = Sse.CompareGreaterThanUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedGreaterThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanUnor private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareGreaterThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareGreaterThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareGreaterThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareGreaterThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareGreaterThanUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean(); - var result = Sse.CompareGreaterThanUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean(); + var result = Sse.CompareScalarUnorderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareGreaterThanUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedGreaterThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnorderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] > right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareGreaterThanUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnorderedGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedGreaterThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedGreaterThanOrEqual.Boolean.cs index 8d179b975c00..3ffcc3c24b7e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareGreaterThanOrEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedGreaterThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedGreaterThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanOrEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean testClass) { - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEq private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean( Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean(); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean(); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareGreaterThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnorderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] >= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareGreaterThanOrEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnorderedGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedLessThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedLessThan.Boolean.cs index d6afcb9f3f5e..e6436ba69e64 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedLessThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanUnorderedScalarBoolean() + private static void CompareScalarUnorderedLessThanBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean testClass) { - var result = Sse.CompareLessThanUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedLessThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanUnorder private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareLessThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareLessThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThan( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareLessThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThan( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareLessThanUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareLessThanUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedLessThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedLessThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedLessThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean(); - var result = Sse.CompareLessThanUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean(); + var result = Sse.CompareScalarUnorderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareLessThanUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedLessThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnorderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] < right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareLessThanUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnorderedLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedLessThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedLessThanOrEqual.Boolean.cs index 57e760167e3e..d1c04c86800a 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareLessThanOrEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedLessThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedLessThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanOrEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean testClass) { - var result = Sse.CompareLessThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqual private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThanOrEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThanOrEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareLessThanOrEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean(); - var result = Sse.CompareLessThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean(); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareLessThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareLessThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnorderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] <= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareLessThanOrEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnorderedLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedNotEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedNotEqual.Boolean.cs index 06995a1f510b..528ca5cb1a41 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareNotEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/CompareScalarUnorderedNotEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedNotEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareNotEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean testClass) { - var result = Sse.CompareNotEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedNotEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualUnorder private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse.CompareNotEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedNotEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse.CompareNotEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedNotEqual( Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse.CompareNotEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedNotEqual( Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse).GetMethod(nameof(Sse.CompareNotEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse).GetMethod(nameof(Sse.CompareScalarUnorderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)), Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse.CompareNotEqualUnorderedScalar( + var result = Sse.CompareScalarUnorderedNotEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse.CompareNotEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse.LoadVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray1Ptr)); var right = Sse.LoadAlignedVector128((Single*)(_dataTable.inArray2Ptr)); - var result = Sse.CompareNotEqualUnorderedScalar(left, right); + var result = Sse.CompareScalarUnorderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean(); - var result = Sse.CompareNotEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean(); + var result = Sse.CompareScalarUnorderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse.CompareNotEqualUnorderedScalar(_fld1, _fld2); + var result = Sse.CompareScalarUnorderedNotEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse.CompareNotEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse.CompareScalarUnorderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Single[] left, Single[] right, bool result, [CallerM { if ((left[0] != right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareNotEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse)}.{nameof(Sse.CompareScalarUnorderedNotEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/Program.Sse.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse/Program.Sse.cs index 533f0e3adbfa..b53770f55b71 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/Program.Sse.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/Program.Sse.cs @@ -17,41 +17,41 @@ static Program() ["And.Single"] = AndSingle, ["AndNot.Single"] = AndNotSingle, ["CompareEqual.Single"] = CompareEqualSingle, - ["CompareEqualScalar.Single"] = CompareEqualScalarSingle, - ["CompareEqualOrderedScalar.Boolean"] = CompareEqualOrderedScalarBoolean, - ["CompareEqualUnorderedScalar.Boolean"] = CompareEqualUnorderedScalarBoolean, + ["CompareScalarEqual.Single"] = CompareScalarEqualSingle, + ["CompareScalarOrderedEqual.Boolean"] = CompareScalarOrderedEqualBoolean, + ["CompareScalarUnorderedEqual.Boolean"] = CompareScalarUnorderedEqualBoolean, ["CompareGreaterThan.Single"] = CompareGreaterThanSingle, - ["CompareGreaterThanScalar.Single"] = CompareGreaterThanScalarSingle, - ["CompareGreaterThanOrderedScalar.Boolean"] = CompareGreaterThanOrderedScalarBoolean, - ["CompareGreaterThanUnorderedScalar.Boolean"] = CompareGreaterThanUnorderedScalarBoolean, + ["CompareScalarGreaterThan.Single"] = CompareScalarGreaterThanSingle, + ["CompareScalarOrderedGreaterThan.Boolean"] = CompareScalarOrderedGreaterThanBoolean, + ["CompareScalarUnorderedGreaterThan.Boolean"] = CompareScalarUnorderedGreaterThanBoolean, ["CompareGreaterThanOrEqual.Single"] = CompareGreaterThanOrEqualSingle, - ["CompareGreaterThanOrEqualScalar.Single"] = CompareGreaterThanOrEqualScalarSingle, - ["CompareGreaterThanOrEqualOrderedScalar.Boolean"] = CompareGreaterThanOrEqualOrderedScalarBoolean, - ["CompareGreaterThanOrEqualUnorderedScalar.Boolean"] = CompareGreaterThanOrEqualUnorderedScalarBoolean, + ["CompareScalarGreaterThanOrEqual.Single"] = CompareScalarGreaterThanOrEqualSingle, + ["CompareScalarOrderedGreaterThanOrEqual.Boolean"] = CompareScalarOrderedGreaterThanOrEqualBoolean, + ["CompareScalarUnorderedGreaterThanOrEqual.Boolean"] = CompareScalarUnorderedGreaterThanOrEqualBoolean, ["CompareLessThan.Single"] = CompareLessThanSingle, - ["CompareLessThanScalar.Single"] = CompareLessThanScalarSingle, - ["CompareLessThanOrderedScalar.Boolean"] = CompareLessThanOrderedScalarBoolean, - ["CompareLessThanUnorderedScalar.Boolean"] = CompareLessThanUnorderedScalarBoolean, + ["CompareScalarLessThan.Single"] = CompareScalarLessThanSingle, + ["CompareScalarOrderedLessThan.Boolean"] = CompareScalarOrderedLessThanBoolean, + ["CompareScalarUnorderedLessThan.Boolean"] = CompareScalarUnorderedLessThanBoolean, ["CompareLessThanOrEqual.Single"] = CompareLessThanOrEqualSingle, - ["CompareLessThanOrEqualScalar.Single"] = CompareLessThanOrEqualScalarSingle, - ["CompareLessThanOrEqualOrderedScalar.Boolean"] = CompareLessThanOrEqualOrderedScalarBoolean, - ["CompareLessThanOrEqualUnorderedScalar.Boolean"] = CompareLessThanOrEqualUnorderedScalarBoolean, + ["CompareScalarLessThanOrEqual.Single"] = CompareScalarLessThanOrEqualSingle, + ["CompareScalarOrderedLessThanOrEqual.Boolean"] = CompareScalarOrderedLessThanOrEqualBoolean, + ["CompareScalarUnorderedLessThanOrEqual.Boolean"] = CompareScalarUnorderedLessThanOrEqualBoolean, ["CompareNotEqual.Single"] = CompareNotEqualSingle, - ["CompareNotEqualScalar.Single"] = CompareNotEqualScalarSingle, - ["CompareNotEqualOrderedScalar.Boolean"] = CompareNotEqualOrderedScalarBoolean, - ["CompareNotEqualUnorderedScalar.Boolean"] = CompareNotEqualUnorderedScalarBoolean, + ["CompareScalarNotEqual.Single"] = CompareScalarNotEqualSingle, + ["CompareScalarOrderedNotEqual.Boolean"] = CompareScalarOrderedNotEqualBoolean, + ["CompareScalarUnorderedNotEqual.Boolean"] = CompareScalarUnorderedNotEqualBoolean, ["CompareNotGreaterThan.Single"] = CompareNotGreaterThanSingle, - ["CompareNotGreaterThanScalar.Single"] = CompareNotGreaterThanScalarSingle, + ["CompareScalarNotGreaterThan.Single"] = CompareScalarNotGreaterThanSingle, ["CompareNotGreaterThanOrEqual.Single"] = CompareNotGreaterThanOrEqualSingle, - ["CompareNotGreaterThanOrEqualScalar.Single"] = CompareNotGreaterThanOrEqualScalarSingle, + ["CompareScalarNotGreaterThanOrEqual.Single"] = CompareScalarNotGreaterThanOrEqualSingle, ["CompareNotLessThan.Single"] = CompareNotLessThanSingle, - ["CompareNotLessThanScalar.Single"] = CompareNotLessThanScalarSingle, + ["CompareScalarNotLessThan.Single"] = CompareScalarNotLessThanSingle, ["CompareNotLessThanOrEqual.Single"] = CompareNotLessThanOrEqualSingle, - ["CompareNotLessThanOrEqualScalar.Single"] = CompareNotLessThanOrEqualScalarSingle, + ["CompareScalarNotLessThanOrEqual.Single"] = CompareScalarNotLessThanOrEqualSingle, ["CompareOrdered.Single"] = CompareOrderedSingle, - ["CompareOrderedScalar.Single"] = CompareOrderedScalarSingle, + ["CompareScalarOrdered.Single"] = CompareScalarOrderedSingle, ["CompareUnordered.Single"] = CompareUnorderedSingle, - ["CompareUnorderedScalar.Single"] = CompareUnorderedScalarSingle, + ["CompareScalarUnordered.Single"] = CompareScalarUnorderedSingle, ["ConvertScalarToVector128Single.Single"] = ConvertScalarToVector128SingleSingle, ["Divide.Single"] = DivideSingle, ["DivideScalar.Single"] = DivideScalarSingle, diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_r.csproj index 8205d1198526..9d6211cff262 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_r.csproj @@ -32,41 +32,41 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_ro.csproj index 5abfc839d160..ac4265796076 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse/Sse_ro.csproj @@ -32,41 +32,41 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarEqual.Double.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarEqual.Double.cs index 8273eeeee495..e829a7a645f0 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarEqual.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareEqualScalarDouble() + private static void CompareScalarEqualDouble() { - var test = new SimpleBinaryOpTest__CompareEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarEqualDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareEqualScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareEqualScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarEqualDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareEqualScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarEqualDouble testClass) { - var result = Sse2.CompareEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareEqualScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarEqualDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareEqualScalarDoub private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareEqualScalarDouble() + static SimpleBinaryOpTest__CompareScalarEqualDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareEqualScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareEqualScalarDouble() + public SimpleBinaryOpTest__CompareScalarEqualDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareEqualScalar(left, right); + var result = Sse2.CompareScalarEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareEqualScalar(left, right); + var result = Sse2.CompareScalarEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareEqualScalar(left, right); + var result = Sse2.CompareScalarEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareEqualScalarDouble(); - var result = Sse2.CompareEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarEqualDouble(); + var result = Sse2.CompareScalarEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarEqualDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareEqualScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareEqualScalar( + var result = Sse2.CompareScalarEqual( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarGreaterThan.Double.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarGreaterThan.Double.cs index d62488400249..b4af1fb8f86a 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarGreaterThan.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanScalarDouble() + private static void CompareScalarGreaterThanDouble() { - var test = new SimpleBinaryOpTest__CompareGreaterThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareGreaterThanScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareGreaterThanScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarGreaterThanDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarGreaterThanDouble testClass) { - var result = Sse2.CompareGreaterThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarGreaterThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarGreaterThanDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanScal private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareGreaterThanScalarDouble() + static SimpleBinaryOpTest__CompareScalarGreaterThanDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareGreaterThanScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareGreaterThanScalarDouble() + public SimpleBinaryOpTest__CompareScalarGreaterThanDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareGreaterThanScalar(left, right); + var result = Sse2.CompareScalarGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanScalar(left, right); + var result = Sse2.CompareScalarGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanScalar(left, right); + var result = Sse2.CompareScalarGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareGreaterThanScalarDouble(); - var result = Sse2.CompareGreaterThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanDouble(); + var result = Sse2.CompareScalarGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareGreaterThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareGreaterThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarGreaterThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanScalar( + var result = Sse2.CompareScalarGreaterThan( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareGreaterThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarGreaterThanOrEqual.Double.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarGreaterThanOrEqual.Double.cs index 06539ae8d438..018dd2712445 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarGreaterThanOrEqual.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrEqualScalarDouble() + private static void CompareScalarGreaterThanOrEqualDouble() { - var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareGreaterThanOrEqualScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble testClass) { - var result = Sse2.CompareGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareGreaterThanOrEq private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble() + static SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble() + public SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareGreaterThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble(); - var result = Sse2.CompareGreaterThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble(); + var result = Sse2.CompareScalarGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareGreaterThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarGreaterThanOrEqualDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarGreaterThanOrEqual( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareGreaterThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarLessThan.Double.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarLessThan.Double.cs index ef25bde41b75..55105bac1c56 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarLessThan.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanScalarDouble() + private static void CompareScalarLessThanDouble() { - var test = new SimpleBinaryOpTest__CompareLessThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareLessThanScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareLessThanScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarLessThanDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarLessThanDouble testClass) { - var result = Sse2.CompareLessThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarLessThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarLessThanDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanScalarD private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareLessThanScalarDouble() + static SimpleBinaryOpTest__CompareScalarLessThanDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareLessThanScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareLessThanScalarDouble() + public SimpleBinaryOpTest__CompareScalarLessThanDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareLessThanScalar(left, right); + var result = Sse2.CompareScalarLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanScalar(left, right); + var result = Sse2.CompareScalarLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanScalar(left, right); + var result = Sse2.CompareScalarLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareLessThanScalarDouble(); - var result = Sse2.CompareLessThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarLessThanDouble(); + var result = Sse2.CompareScalarLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareLessThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareLessThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarLessThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanScalar( + var result = Sse2.CompareScalarLessThan( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareLessThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarLessThanOrEqual.Double.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarLessThanOrEqual.Double.cs index 4316dd97d91b..379c9157d7f7 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarLessThanOrEqual.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrEqualScalarDouble() + private static void CompareScalarLessThanOrEqualDouble() { - var test = new SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareLessThanOrEqualScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble testClass) { - var result = Sse2.CompareLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarLessThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareLessThanOrEqual private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble() + static SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble() + public SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareLessThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble(); - var result = Sse2.CompareLessThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble(); + var result = Sse2.CompareScalarLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareLessThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarLessThanOrEqualDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarLessThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanOrEqualScalar( + var result = Sse2.CompareScalarLessThanOrEqual( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareLessThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotEqual.Double.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotEqual.Double.cs index 4d34c3281f55..e64966b12ee1 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotEqual.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotEqualScalarDouble() + private static void CompareScalarNotEqualDouble() { - var test = new SimpleBinaryOpTest__CompareNotEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotEqualDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotEqualScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotEqualScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotEqualDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotEqualScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotEqualDouble testClass) { - var result = Sse2.CompareNotEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotEqualScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotEqualDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotEqualScalarD private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotEqualScalarDouble() + static SimpleBinaryOpTest__CompareScalarNotEqualDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotEqualScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotEqualScalarDouble() + public SimpleBinaryOpTest__CompareScalarNotEqualDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotEqualScalar(left, right); + var result = Sse2.CompareScalarNotEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotEqualScalar(left, right); + var result = Sse2.CompareScalarNotEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotEqualScalar(left, right); + var result = Sse2.CompareScalarNotEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotEqualScalarDouble(); - var result = Sse2.CompareNotEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotEqualDouble(); + var result = Sse2.CompareScalarNotEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotEqualDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotEqualScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarNotEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareNotEqualScalar( + var result = Sse2.CompareScalarNotEqual( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarNotEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotGreaterThanScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotGreaterThan.Double.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotGreaterThanScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotGreaterThan.Double.cs index 8dd5638eb645..6b2e0c0fa331 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotGreaterThanScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotGreaterThan.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotGreaterThanScalarDouble() + private static void CompareScalarNotGreaterThanDouble() { - var test = new SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotGreaterThanScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble testClass) { - var result = Sse2.CompareNotGreaterThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotGreaterThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanS private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble() + static SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble() + public SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotGreaterThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotGreaterThanScalar(left, right); + var result = Sse2.CompareScalarNotGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotGreaterThanScalar(left, right); + var result = Sse2.CompareScalarNotGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotGreaterThanScalar(left, right); + var result = Sse2.CompareScalarNotGreaterThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble(); - var result = Sse2.CompareNotGreaterThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble(); + var result = Sse2.CompareScalarNotGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotGreaterThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotGreaterThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotGreaterThanScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarNotGreaterThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareNotGreaterThanScalar( + var result = Sse2.CompareScalarNotGreaterThan( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotGreaterThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarNotGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotGreaterThanOrEqualScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotGreaterThanOrEqual.Double.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotGreaterThanOrEqualScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotGreaterThanOrEqual.Double.cs index 6c24f073c329..6440a9e32148 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotGreaterThanOrEqualScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotGreaterThanOrEqual.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotGreaterThanOrEqualScalarDouble() + private static void CompareScalarNotGreaterThanOrEqualDouble() { - var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotGreaterThanOrEqualScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble testClass) { - var result = Sse2.CompareNotGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotGreaterThanO private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble() + static SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble() + public SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotGreaterThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotGreaterThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble(); - var result = Sse2.CompareNotGreaterThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble(); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotGreaterThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotGreaterThanOrEqualDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotGreaterThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotGreaterThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarNotGreaterThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareNotGreaterThanOrEqualScalar( + var result = Sse2.CompareScalarNotGreaterThanOrEqual( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotGreaterThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarNotGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotLessThanScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotLessThan.Double.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotLessThanScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotLessThan.Double.cs index c6c7c61fe366..58196238b94e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotLessThanScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotLessThan.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotLessThanScalarDouble() + private static void CompareScalarNotLessThanDouble() { - var test = new SimpleBinaryOpTest__CompareNotLessThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotLessThanScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotLessThanScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotLessThanDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotLessThanDouble testClass) { - var result = Sse2.CompareNotLessThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotLessThan(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotLessThanDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanScal private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotLessThanScalarDouble() + static SimpleBinaryOpTest__CompareScalarNotLessThanDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotLessThanScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotLessThanScalarDouble() + public SimpleBinaryOpTest__CompareScalarNotLessThanDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotLessThanScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotLessThanScalar(left, right); + var result = Sse2.CompareScalarNotLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotLessThanScalar(left, right); + var result = Sse2.CompareScalarNotLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotLessThanScalar(left, right); + var result = Sse2.CompareScalarNotLessThan(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotLessThanScalarDouble(); - var result = Sse2.CompareNotLessThanScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanDouble(); + var result = Sse2.CompareScalarNotLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotLessThanScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotLessThanScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotLessThan(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotLessThanScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarNotLessThan(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareNotLessThanScalar( + var result = Sse2.CompareScalarNotLessThan( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotLessThanScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarNotLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotLessThanOrEqualScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotLessThanOrEqual.Double.cs similarity index 91% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotLessThanOrEqualScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotLessThanOrEqual.Double.cs index 2d15a02f12e6..90e0cc54a199 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotLessThanOrEqualScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarNotLessThanOrEqual.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotLessThanOrEqualScalarDouble() + private static void CompareScalarNotLessThanOrEqualDouble() { - var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareNotLessThanOrEqualScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble testClass) { - var result = Sse2.CompareNotLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotLessThanOrEqual(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareNotLessThanOrEq private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble() + static SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble() + public SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotLessThanOrEqualScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarNotLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotLessThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarNotLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotLessThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarNotLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotLessThanOrEqualScalar(left, right); + var result = Sse2.CompareScalarNotLessThanOrEqual(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble(); - var result = Sse2.CompareNotLessThanOrEqualScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble(); + var result = Sse2.CompareScalarNotLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareNotLessThanOrEqualScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarNotLessThanOrEqualDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotLessThanOrEqualScalar(_fld1, _fld2); + var result = Sse2.CompareScalarNotLessThanOrEqual(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotLessThanOrEqualScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarNotLessThanOrEqual(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareNotLessThanOrEqualScalar( + var result = Sse2.CompareScalarNotLessThanOrEqual( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotLessThanOrEqualScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarNotLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareOrderedScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrdered.Double.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareOrderedScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrdered.Double.cs index c27f98dc4636..116c94bd28dc 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareOrderedScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrdered.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareOrderedScalarDouble() + private static void CompareScalarOrderedDouble() { - var test = new SimpleBinaryOpTest__CompareOrderedScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarOrderedDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareOrderedScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareOrderedScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarOrderedDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareOrderedScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarOrderedDouble testClass) { - var result = Sse2.CompareOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrdered(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareOrderedScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarOrderedDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareOrderedScalarDo private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareOrderedScalarDouble() + static SimpleBinaryOpTest__CompareScalarOrderedDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareOrderedScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareOrderedScalarDouble() + public SimpleBinaryOpTest__CompareScalarOrderedDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrdered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrdered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrdered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareOrderedScalar(left, right); + var result = Sse2.CompareScalarOrdered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareOrderedScalar(left, right); + var result = Sse2.CompareScalarOrdered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareOrderedScalar(left, right); + var result = Sse2.CompareScalarOrdered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareOrderedScalarDouble(); - var result = Sse2.CompareOrderedScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarOrderedDouble(); + var result = Sse2.CompareScalarOrdered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareOrderedScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarOrderedDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrdered(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrdered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareOrderedScalar( + var result = Sse2.CompareScalarOrdered( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrdered)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedEqual.Boolean.cs index 979a2ec99550..6281a9cfc5eb 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareEqualOrderedScalarBoolean() + private static void CompareScalarOrderedEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean testClass) { - var result = Sse2.CompareEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualOrderedSca private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareEqualOrderedScalarBoolean(); - var result = Sse2.CompareEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedEqualBoolean(); + var result = Sse2.CompareScalarOrderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] == right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrderedEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedGreaterThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedGreaterThan.Boolean.cs index 1e1072c9198b..182800c87f68 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedGreaterThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrderedScalarBoolean() + private static void CompareScalarOrderedGreaterThanBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean testClass) { - var result = Sse2.CompareGreaterThanOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedGreaterThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrde private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareGreaterThanOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareGreaterThanOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareGreaterThanOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareGreaterThanOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareGreaterThanOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanOrderedScalarBoolean(); - var result = Sse2.CompareGreaterThanOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanBoolean(); + var result = Sse2.CompareScalarOrderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareGreaterThanOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedGreaterThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] > right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareGreaterThanOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrderedGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedGreaterThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedGreaterThanOrEqual.Boolean.cs index c7a82b8e87d1..0e5ce983f34c 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedGreaterThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrEqualOrderedScalarBoolean() + private static void CompareScalarOrderedGreaterThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanOrEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean testClass) { - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEq private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualOrderedScalarBoolean(); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedGreaterThanOrEqualBoolean(); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanOrEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] >= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrderedGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedLessThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedLessThan.Boolean.cs index 0cd4106abcd0..fcd5dd00900d 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedLessThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrderedScalarBoolean() + private static void CompareScalarOrderedLessThanBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean testClass) { - var result = Sse2.CompareLessThanOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedLessThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrdered private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareLessThanOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareLessThanOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareLessThanOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareLessThanOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareLessThanOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedLessThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedLessThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedLessThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanOrderedScalarBoolean(); - var result = Sse2.CompareLessThanOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanBoolean(); + var result = Sse2.CompareScalarOrderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareLessThanOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedLessThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] < right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareLessThanOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrderedLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedLessThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedLessThanOrEqual.Boolean.cs index 05e2e2fefc90..01b41e293f4b 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedLessThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrEqualOrderedScalarBoolean() + private static void CompareScalarOrderedLessThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanOrEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean testClass) { - var result = Sse2.CompareLessThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqual private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareLessThanOrEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualOrderedScalarBoolean(); - var result = Sse2.CompareLessThanOrEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedLessThanOrEqualBoolean(); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareLessThanOrEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanOrEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] <= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareLessThanOrEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrderedLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualOrderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedNotEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualOrderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedNotEqual.Boolean.cs index c8367f7751a5..59aa6f2d0eda 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualOrderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarOrderedNotEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotEqualOrderedScalarBoolean() + private static void CompareScalarOrderedNotEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareNotEqualOrderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean testClass) { - var result = Sse2.CompareNotEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedNotEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualOrdered private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedNotEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedNotEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedNotEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualOrderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarOrderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotEqualOrderedScalar( + var result = Sse2.CompareScalarOrderedNotEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotEqualOrderedScalar(left, right); + var result = Sse2.CompareScalarOrderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareNotEqualOrderedScalarBoolean(); - var result = Sse2.CompareNotEqualOrderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarOrderedNotEqualBoolean(); + var result = Sse2.CompareScalarOrderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotEqualOrderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarOrderedNotEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotEqualOrderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarOrderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] != right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotEqualOrderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarOrderedNotEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareUnorderedScalar.Double.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnordered.Double.cs similarity index 92% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareUnorderedScalar.Double.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnordered.Double.cs index f2188750873b..83d57c49ef40 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareUnorderedScalar.Double.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnordered.Double.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareUnorderedScalarDouble() + private static void CompareScalarUnorderedDouble() { - var test = new SimpleBinaryOpTest__CompareUnorderedScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarUnorderedDouble(); if (test.IsSupported) { @@ -119,7 +119,7 @@ private static void CompareUnorderedScalarDouble() } } - public sealed unsafe class SimpleBinaryOpTest__CompareUnorderedScalarDouble + public sealed unsafe class SimpleBinaryOpTest__CompareScalarUnorderedDouble { private struct TestStruct { @@ -138,20 +138,20 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(SimpleBinaryOpTest__CompareUnorderedScalarDouble testClass) + public void RunStructFldScenario(SimpleBinaryOpTest__CompareScalarUnorderedDouble testClass) { - var result = Sse2.CompareUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnordered(_fld1, _fld2); Unsafe.Write(testClass._dataTable.outArrayPtr, result); testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr); } - public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareUnorderedScalarDouble testClass) + public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareScalarUnorderedDouble testClass) { fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -179,7 +179,7 @@ public void RunStructFldScenario_Load(SimpleBinaryOpTest__CompareUnorderedScalar private SimpleBinaryOpTest__DataTable _dataTable; - static SimpleBinaryOpTest__CompareUnorderedScalarDouble() + static SimpleBinaryOpTest__CompareScalarUnorderedDouble() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -187,7 +187,7 @@ static SimpleBinaryOpTest__CompareUnorderedScalarDouble() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public SimpleBinaryOpTest__CompareUnorderedScalarDouble() + public SimpleBinaryOpTest__CompareScalarUnorderedDouble() { Succeeded = true; @@ -209,7 +209,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -222,7 +222,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -235,7 +235,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -248,7 +248,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnordered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -262,7 +262,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnordered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -276,7 +276,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnordered), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -290,7 +290,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( _clsVar1, _clsVar2 ); @@ -306,7 +306,7 @@ public void RunClsVarScenario_Load() fixed (Vector128* pClsVar1 = &_clsVar1) fixed (Vector128* pClsVar2 = &_clsVar2) { - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadVector128((Double*)(pClsVar1)), Sse2.LoadVector128((Double*)(pClsVar2)) ); @@ -322,7 +322,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnordered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -334,7 +334,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnordered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -346,7 +346,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnordered(left, right); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(left, right, _dataTable.outArrayPtr); @@ -356,8 +356,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new SimpleBinaryOpTest__CompareUnorderedScalarDouble(); - var result = Sse2.CompareUnorderedScalar(test._fld1, test._fld2); + var test = new SimpleBinaryOpTest__CompareScalarUnorderedDouble(); + var result = Sse2.CompareScalarUnordered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -367,12 +367,12 @@ public void RunClassLclFldScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario_Load)); - var test = new SimpleBinaryOpTest__CompareUnorderedScalarDouble(); + var test = new SimpleBinaryOpTest__CompareScalarUnorderedDouble(); fixed (Vector128* pFld1 = &test._fld1) fixed (Vector128* pFld2 = &test._fld2) { - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -386,7 +386,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnordered(_fld1, _fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr); @@ -399,7 +399,7 @@ public void RunClassFldScenario_Load() fixed (Vector128* pFld1 = &_fld1) fixed (Vector128* pFld2 = &_fld2) { - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadVector128((Double*)(pFld1)), Sse2.LoadVector128((Double*)(pFld2)) ); @@ -414,7 +414,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnordered(test._fld1, test._fld2); Unsafe.Write(_dataTable.outArrayPtr, result); ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr); @@ -425,7 +425,7 @@ public void RunStructLclFldScenario_Load() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario_Load)); var test = TestStruct.Create(); - var result = Sse2.CompareUnorderedScalar( + var result = Sse2.CompareScalarUnordered( Sse2.LoadVector128((Double*)(&test._fld1)), Sse2.LoadVector128((Double*)(&test._fld2)) ); @@ -519,7 +519,7 @@ private void ValidateResult(Double[] left, Double[] right, Double[] result, [Cal if (!succeeded) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnordered)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedEqual.Boolean.cs index b5c416b6df5a..5ad4073edfab 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean testClass) { - var result = Sse2.CompareEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareEqualUnorderedS private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareEqualUnorderedScalarBoolean(); - var result = Sse2.CompareEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedEqualBoolean(); + var result = Sse2.CompareScalarUnorderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnorderedEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] == right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnorderedEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedGreaterThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedGreaterThan.Boolean.cs index 2e208d4e18a4..0ea2751f22a0 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedGreaterThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanUnorderedScalarBoolean() + private static void CompareScalarUnorderedGreaterThanBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean testClass) { - var result = Sse2.CompareGreaterThanUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedGreaterThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanUnor private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareGreaterThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareGreaterThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareGreaterThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedGreaterThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareGreaterThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareGreaterThanUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedGreaterThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanUnorderedScalarBoolean(); - var result = Sse2.CompareGreaterThanUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanBoolean(); + var result = Sse2.CompareScalarUnorderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareGreaterThanUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedGreaterThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnorderedGreaterThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] > right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareGreaterThanUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnorderedGreaterThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedGreaterThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedGreaterThanOrEqual.Boolean.cs index 41f1acf2083e..5f9483973bd5 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareGreaterThanOrEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedGreaterThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareGreaterThanOrEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedGreaterThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareGreaterThanOrEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean testClass) { - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareGreaterThanOrEq private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean( Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedGreaterThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareGreaterThanOrEqualUnorderedScalarBoolean(); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedGreaterThanOrEqualBoolean(); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareGreaterThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnorderedGreaterThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] >= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareGreaterThanOrEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnorderedGreaterThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedLessThan.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedLessThan.Boolean.cs index 36d688f5f2e8..9544c8bcdf8e 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedLessThan.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanUnorderedScalarBoolean() + private static void CompareScalarUnorderedLessThanBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean testClass) { - var result = Sse2.CompareLessThanUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedLessThan(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanUnorder private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareLessThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThan( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareLessThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThan( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareLessThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThan( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedLessThan), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareLessThanUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThan( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareLessThanUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedLessThan(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedLessThan(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedLessThan(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanUnorderedScalarBoolean(); - var result = Sse2.CompareLessThanUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanBoolean(); + var result = Sse2.CompareScalarUnorderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareLessThanUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedLessThan(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnorderedLessThan(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] < right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareLessThanUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnorderedLessThan)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedLessThanOrEqual.Boolean.cs similarity index 89% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedLessThanOrEqual.Boolean.cs index b9ec317045fa..e2f81dd69334 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareLessThanOrEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedLessThanOrEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareLessThanOrEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedLessThanOrEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareLessThanOrEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean testClass) { - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareLessThanOrEqual private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThanOrEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThanOrEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThanOrEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedLessThanOrEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedLessThanOrEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareLessThanOrEqualUnorderedScalarBoolean(); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedLessThanOrEqualBoolean(); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareLessThanOrEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnorderedLessThanOrEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] <= right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareLessThanOrEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnorderedLessThanOrEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualUnorderedScalar.Boolean.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedNotEqual.Boolean.cs similarity index 90% rename from tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualUnorderedScalar.Boolean.cs rename to tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedNotEqual.Boolean.cs index 4199cd8ec3b6..f13dc85baadf 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareNotEqualUnorderedScalar.Boolean.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/CompareScalarUnorderedNotEqual.Boolean.cs @@ -19,9 +19,9 @@ namespace JIT.HardwareIntrinsics.X86 { public static partial class Program { - private static void CompareNotEqualUnorderedScalarBoolean() + private static void CompareScalarUnorderedNotEqualBoolean() { - var test = new BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean(); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean(); if (test.IsSupported) { @@ -89,7 +89,7 @@ private static void CompareNotEqualUnorderedScalarBoolean() } } - public sealed unsafe class BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean + public sealed unsafe class BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean { private struct TestStruct { @@ -108,9 +108,9 @@ public static TestStruct Create() return testStruct; } - public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean testClass) + public void RunStructFldScenario(BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean testClass) { - var result = Sse2.CompareNotEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedNotEqual(_fld1, _fld2); testClass.ValidateResult(_fld1, _fld2, result); } } @@ -131,7 +131,7 @@ public void RunStructFldScenario(BooleanComparisonOpTest__CompareNotEqualUnorder private BooleanComparisonOpTest__DataTable _dataTable; - static BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean() + static BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean() { for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); } Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar1), ref Unsafe.As(ref _data1[0]), (uint)Unsafe.SizeOf>()); @@ -139,7 +139,7 @@ static BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean() Unsafe.CopyBlockUnaligned(ref Unsafe.As, byte>(ref _clsVar2), ref Unsafe.As(ref _data2[0]), (uint)Unsafe.SizeOf>()); } - public BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean() + public BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean() { Succeeded = true; @@ -161,7 +161,7 @@ public void RunBasicScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_UnsafeRead)); - var result = Sse2.CompareNotEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedNotEqual( Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) ); @@ -173,7 +173,7 @@ public void RunBasicScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_Load)); - var result = Sse2.CompareNotEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedNotEqual( Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -185,7 +185,7 @@ public void RunBasicScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunBasicScenario_LoadAligned)); - var result = Sse2.CompareNotEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedNotEqual( Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) ); @@ -197,7 +197,7 @@ public void RunReflectionScenario_UnsafeRead() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_UnsafeRead)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Unsafe.Read>(_dataTable.inArray1Ptr), Unsafe.Read>(_dataTable.inArray2Ptr) @@ -210,7 +210,7 @@ public void RunReflectionScenario_Load() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_Load)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)) @@ -223,7 +223,7 @@ public void RunReflectionScenario_LoadAligned() { TestLibrary.TestFramework.BeginScenario(nameof(RunReflectionScenario_LoadAligned)); - var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareNotEqualUnorderedScalar), new Type[] { typeof(Vector128), typeof(Vector128) }) + var result = typeof(Sse2).GetMethod(nameof(Sse2.CompareScalarUnorderedNotEqual), new Type[] { typeof(Vector128), typeof(Vector128) }) .Invoke(null, new object[] { Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)), Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)) @@ -236,7 +236,7 @@ public void RunClsVarScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClsVarScenario)); - var result = Sse2.CompareNotEqualUnorderedScalar( + var result = Sse2.CompareScalarUnorderedNotEqual( _clsVar1, _clsVar2 ); @@ -250,7 +250,7 @@ public void RunLclVarScenario_UnsafeRead() var left = Unsafe.Read>(_dataTable.inArray1Ptr); var right = Unsafe.Read>(_dataTable.inArray2Ptr); - var result = Sse2.CompareNotEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -261,7 +261,7 @@ public void RunLclVarScenario_Load() var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -272,7 +272,7 @@ public void RunLclVarScenario_LoadAligned() var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)); var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)); - var result = Sse2.CompareNotEqualUnorderedScalar(left, right); + var result = Sse2.CompareScalarUnorderedNotEqual(left, right); ValidateResult(left, right, result); } @@ -281,8 +281,8 @@ public void RunClassLclFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassLclFldScenario)); - var test = new BooleanComparisonOpTest__CompareNotEqualUnorderedScalarBoolean(); - var result = Sse2.CompareNotEqualUnorderedScalar(test._fld1, test._fld2); + var test = new BooleanComparisonOpTest__CompareScalarUnorderedNotEqualBoolean(); + var result = Sse2.CompareScalarUnorderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -291,7 +291,7 @@ public void RunClassFldScenario() { TestLibrary.TestFramework.BeginScenario(nameof(RunClassFldScenario)); - var result = Sse2.CompareNotEqualUnorderedScalar(_fld1, _fld2); + var result = Sse2.CompareScalarUnorderedNotEqual(_fld1, _fld2); ValidateResult(_fld1, _fld2, result); } @@ -301,7 +301,7 @@ public void RunStructLclFldScenario() TestLibrary.TestFramework.BeginScenario(nameof(RunStructLclFldScenario)); var test = TestStruct.Create(); - var result = Sse2.CompareNotEqualUnorderedScalar(test._fld1, test._fld2); + var result = Sse2.CompareScalarUnorderedNotEqual(test._fld1, test._fld2); ValidateResult(test._fld1, test._fld2, result); } @@ -360,7 +360,7 @@ private void ValidateResult(Double[] left, Double[] right, bool result, [CallerM { if ((left[0] != right[0]) != result) { - TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareNotEqualUnorderedScalar)}(Vector128, Vector128): {method} failed:"); + TestLibrary.TestFramework.LogInformation($"{nameof(Sse2)}.{nameof(Sse2.CompareScalarUnorderedNotEqual)}(Vector128, Vector128): {method} failed:"); TestLibrary.TestFramework.LogInformation($" left: ({string.Join(", ", left)})"); TestLibrary.TestFramework.LogInformation($" right: ({string.Join(", ", right)})"); TestLibrary.TestFramework.LogInformation($" result: ({string.Join(", ", result)})"); diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs index a61a8cd992c5..324c4495f531 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Program.Sse2.cs @@ -53,47 +53,47 @@ static Program() ["CompareEqual.SByte"] = CompareEqualSByte, ["CompareEqual.UInt16"] = CompareEqualUInt16, ["CompareEqual.UInt32"] = CompareEqualUInt32, - ["CompareEqualScalar.Double"] = CompareEqualScalarDouble, - ["CompareEqualOrderedScalar.Boolean"] = CompareEqualOrderedScalarBoolean, - ["CompareEqualUnorderedScalar.Boolean"] = CompareEqualUnorderedScalarBoolean, + ["CompareScalarEqual.Double"] = CompareScalarEqualDouble, + ["CompareScalarOrderedEqual.Boolean"] = CompareScalarOrderedEqualBoolean, + ["CompareScalarUnorderedEqual.Boolean"] = CompareScalarUnorderedEqualBoolean, ["CompareGreaterThan.Double"] = CompareGreaterThanDouble, ["CompareGreaterThan.Int16"] = CompareGreaterThanInt16, ["CompareGreaterThan.Int32"] = CompareGreaterThanInt32, ["CompareGreaterThan.SByte"] = CompareGreaterThanSByte, - ["CompareGreaterThanScalar.Double"] = CompareGreaterThanScalarDouble, - ["CompareGreaterThanOrderedScalar.Boolean"] = CompareGreaterThanOrderedScalarBoolean, - ["CompareGreaterThanUnorderedScalar.Boolean"] = CompareGreaterThanUnorderedScalarBoolean, + ["CompareScalarGreaterThan.Double"] = CompareScalarGreaterThanDouble, + ["CompareScalarOrderedGreaterThan.Boolean"] = CompareScalarOrderedGreaterThanBoolean, + ["CompareScalarUnorderedGreaterThan.Boolean"] = CompareScalarUnorderedGreaterThanBoolean, ["CompareGreaterThanOrEqual.Double"] = CompareGreaterThanOrEqualDouble, - ["CompareGreaterThanOrEqualScalar.Double"] = CompareGreaterThanOrEqualScalarDouble, - ["CompareGreaterThanOrEqualOrderedScalar.Boolean"] = CompareGreaterThanOrEqualOrderedScalarBoolean, - ["CompareGreaterThanOrEqualUnorderedScalar.Boolean"] = CompareGreaterThanOrEqualUnorderedScalarBoolean, + ["CompareScalarGreaterThanOrEqual.Double"] = CompareScalarGreaterThanOrEqualDouble, + ["CompareScalarOrderedGreaterThanOrEqual.Boolean"] = CompareScalarOrderedGreaterThanOrEqualBoolean, + ["CompareScalarUnorderedGreaterThanOrEqual.Boolean"] = CompareScalarUnorderedGreaterThanOrEqualBoolean, ["CompareLessThan.Double"] = CompareLessThanDouble, ["CompareLessThan.Int16"] = CompareLessThanInt16, ["CompareLessThan.Int32"] = CompareLessThanInt32, ["CompareLessThan.SByte"] = CompareLessThanSByte, - ["CompareLessThanScalar.Double"] = CompareLessThanScalarDouble, - ["CompareLessThanOrderedScalar.Boolean"] = CompareLessThanOrderedScalarBoolean, - ["CompareLessThanUnorderedScalar.Boolean"] = CompareLessThanUnorderedScalarBoolean, + ["CompareScalarLessThan.Double"] = CompareScalarLessThanDouble, + ["CompareScalarOrderedLessThan.Boolean"] = CompareScalarOrderedLessThanBoolean, + ["CompareScalarUnorderedLessThan.Boolean"] = CompareScalarUnorderedLessThanBoolean, ["CompareLessThanOrEqual.Double"] = CompareLessThanOrEqualDouble, - ["CompareLessThanOrEqualScalar.Double"] = CompareLessThanOrEqualScalarDouble, - ["CompareLessThanOrEqualOrderedScalar.Boolean"] = CompareLessThanOrEqualOrderedScalarBoolean, - ["CompareLessThanOrEqualUnorderedScalar.Boolean"] = CompareLessThanOrEqualUnorderedScalarBoolean, + ["CompareScalarLessThanOrEqual.Double"] = CompareScalarLessThanOrEqualDouble, + ["CompareScalarOrderedLessThanOrEqual.Boolean"] = CompareScalarOrderedLessThanOrEqualBoolean, + ["CompareScalarUnorderedLessThanOrEqual.Boolean"] = CompareScalarUnorderedLessThanOrEqualBoolean, ["CompareNotEqual.Double"] = CompareNotEqualDouble, - ["CompareNotEqualScalar.Double"] = CompareNotEqualScalarDouble, - ["CompareNotEqualOrderedScalar.Boolean"] = CompareNotEqualOrderedScalarBoolean, - ["CompareNotEqualUnorderedScalar.Boolean"] = CompareNotEqualUnorderedScalarBoolean, + ["CompareScalarNotEqual.Double"] = CompareScalarNotEqualDouble, + ["CompareScalarOrderedNotEqual.Boolean"] = CompareScalarOrderedNotEqualBoolean, + ["CompareScalarUnorderedNotEqual.Boolean"] = CompareScalarUnorderedNotEqualBoolean, ["CompareNotGreaterThan.Double"] = CompareNotGreaterThanDouble, - ["CompareNotGreaterThanScalar.Double"] = CompareNotGreaterThanScalarDouble, + ["CompareScalarNotGreaterThan.Double"] = CompareScalarNotGreaterThanDouble, ["CompareNotGreaterThanOrEqual.Double"] = CompareNotGreaterThanOrEqualDouble, - ["CompareNotGreaterThanOrEqualScalar.Double"] = CompareNotGreaterThanOrEqualScalarDouble, + ["CompareScalarNotGreaterThanOrEqual.Double"] = CompareScalarNotGreaterThanOrEqualDouble, ["CompareNotLessThan.Double"] = CompareNotLessThanDouble, - ["CompareNotLessThanScalar.Double"] = CompareNotLessThanScalarDouble, + ["CompareScalarNotLessThan.Double"] = CompareScalarNotLessThanDouble, ["CompareNotLessThanOrEqual.Double"] = CompareNotLessThanOrEqualDouble, - ["CompareNotLessThanOrEqualScalar.Double"] = CompareNotLessThanOrEqualScalarDouble, + ["CompareScalarNotLessThanOrEqual.Double"] = CompareScalarNotLessThanOrEqualDouble, ["CompareOrdered.Double"] = CompareOrderedDouble, - ["CompareOrderedScalar.Double"] = CompareOrderedScalarDouble, + ["CompareScalarOrdered.Double"] = CompareScalarOrderedDouble, ["CompareUnordered.Double"] = CompareUnorderedDouble, - ["CompareUnorderedScalar.Double"] = CompareUnorderedScalarDouble, + ["CompareScalarUnordered.Double"] = CompareScalarUnorderedDouble, ["ConvertToInt32.Vector128Double"] = ConvertToInt32Vector128Double, ["ConvertToInt32.Vector128Int32"] = ConvertToInt32Vector128Int32, ["ConvertToInt32WithTruncation.Vector128Double"] = ConvertToInt32WithTruncationVector128Double, diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj index 900e2a11e2ad..fb09352256e3 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_r.csproj @@ -36,11 +36,11 @@ - - - - - + + + + + @@ -59,56 +59,56 @@ - - - + + + - - - + + + - + + + - - - - - + + + - + + + - - - - - + + + - - - + + + + - - + + - - + - + - + @@ -132,6 +132,7 @@ + @@ -140,7 +141,6 @@ - @@ -186,6 +186,18 @@ + + + + + + + + + + + + @@ -198,18 +210,6 @@ - - - - - - - - - - - - @@ -226,10 +226,10 @@ - - + + @@ -241,10 +241,10 @@ - - - - + + + + diff --git a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj index 9ad362660b47..b9efd1b53643 100644 --- a/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj +++ b/tests/src/JIT/HardwareIntrinsics/X86/Sse2/Sse2_ro.csproj @@ -27,8 +27,8 @@ - + @@ -36,13 +36,13 @@ - - - - - - + + + + + + @@ -50,8 +50,8 @@ - + @@ -59,56 +59,56 @@ - - - + + + - - - + + + - + + + - - - - - + + + - + + + - - - - - + + + - - - + + + + - - + + - - + - + - + @@ -129,9 +129,10 @@ - + + @@ -140,18 +141,17 @@ - - + - + @@ -162,8 +162,8 @@ - + @@ -174,50 +174,49 @@ - - + - + - - + + - + - + + - - - + + - + - + - + - - + + - + - + + - - - + + @@ -227,14 +226,14 @@ - - + + - + @@ -242,10 +241,10 @@ - - - - + + + + @@ -266,8 +265,8 @@ - + @@ -275,6 +274,7 @@ + diff --git a/tests/src/JIT/Methodical/largeframes/skip3/skippage3.cs b/tests/src/JIT/Methodical/largeframes/skip3/skippage3.cs new file mode 100644 index 000000000000..f4ec9ff6931e --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip3/skippage3.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Passing a very large struct by value on the stack, on arm32 and x86, +// can cause it to be copied from a temp to the outgoing space without +// probing the stack. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace BigFrames +{ + + [StructLayout(LayoutKind.Explicit)] + public struct LargeStruct + { + [FieldOffset(0)] + public int i1; + [FieldOffset(65512)] + public int i2; + } + + public class Test + { + public static int iret = 1; + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void TestWrite(int i1, int i2, int i3, int i4, LargeStruct s) + { + Console.Write("Enter TestWrite: "); + Console.WriteLine(i1 + i2 + i3 + i4 + s.i2); + iret = 100; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Test1() + { + Console.WriteLine("Enter Test1"); + LargeStruct s = new LargeStruct(); + s.i2 = 5; + TestWrite(1, 2, 3, 4, s); // 4 int reg args, then struct stack arg + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Escape(ref LargeStruct s) + { + } + + // A lot of time the stack when we are called has a bunch of committed pages + // before the guard page. So eat up a bunch of stack before doing our test, + // where we want to be near the guard page. + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void EatStackThenTest1(int level = 0) + { + LargeStruct s = new LargeStruct(); + s.i2 = level; + Escape(ref s); + + if (level < 10) + { + EatStackThenTest1(level + 1); + } + else + { + Test1(); + } + } + + public static int Main() + { + Test1(); // force JIT of this + + EatStackThenTest1(); // If that didn't fail, eat stack then try again. + + if (iret == 100) + { + Console.WriteLine("TEST PASSED"); + } + else + { + Console.WriteLine("TEST FAILED"); + } + return iret; + } + } +} diff --git a/tests/src/JIT/Methodical/largeframes/skip3/skippage3.csproj b/tests/src/JIT/Methodical/largeframes/skip3/skippage3.csproj new file mode 100644 index 000000000000..1b7f680295da --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip3/skippage3.csproj @@ -0,0 +1,35 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {43F24741-6FD9-4593-92FA-D3252B540A92} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + 1 + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + diff --git a/tests/src/JIT/Methodical/largeframes/skip4/skippage4.cs b/tests/src/JIT/Methodical/largeframes/skip4/skippage4.cs new file mode 100644 index 000000000000..7e0fed56bf38 --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip4/skippage4.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Passing a very large struct by value on the stack, on arm32 and x86, +// can cause it to be copied from a temp to the outgoing space without +// probing the stack. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace BigFrames +{ + + [StructLayout(LayoutKind.Explicit)] + public struct LargeStructWithRef + { + [FieldOffset(0)] + public int i1; + [FieldOffset(65496)] // Must be 8-byte aligned for test to work on 64-bit platforms. + public Object o1; + } + + public class Test + { + public static int iret = 1; + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void TestWrite(LargeStructWithRef s) + { + Console.Write("Enter TestWrite: "); + Console.WriteLine(s.o1.GetHashCode()); + iret = 100; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Test1() + { + Console.WriteLine("Enter Test1"); + LargeStructWithRef s = new LargeStructWithRef(); + s.o1 = new Object(); + TestWrite(s); + } + + public static int Main() + { + Test1(); + + if (iret == 100) + { + Console.WriteLine("TEST PASSED"); + } + else + { + Console.WriteLine("TEST FAILED"); + } + return iret; + } + } +} diff --git a/tests/src/JIT/Methodical/largeframes/skip4/skippage4.csproj b/tests/src/JIT/Methodical/largeframes/skip4/skippage4.csproj new file mode 100644 index 000000000000..1482b3e1fa54 --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip4/skippage4.csproj @@ -0,0 +1,35 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {43F24741-6FD9-4593-92FA-D3252B540A92} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + 1 + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + diff --git a/tests/src/JIT/Methodical/largeframes/skip4/skippage4_save.cs b/tests/src/JIT/Methodical/largeframes/skip4/skippage4_save.cs new file mode 100644 index 000000000000..95fe0edfc696 --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip4/skippage4_save.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Passing a very large struct by value on the stack, on arm32 and x86, +// can cause it to be copied from a temp to the outgoing space without +// probing the stack. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace BigFrames +{ + + [StructLayout(LayoutKind.Explicit)] + public struct Struct65500ref + { + [FieldOffset(0)] + public int i1; + [FieldOffset(65496)] + public Object o1; + } + + public class Test + { + public static int iret = 1; + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void TestWrite(int i1, int i2, int i3, int i4, Struct65500ref s) + { + Console.Write("Enter TestWrite: "); + Console.WriteLine(i1 + i2 + i3 + i4 + s.o1.GetHashCode()); + iret = 100; + // Test1(); // recurse + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static void Test1() + { + Console.WriteLine("Enter Test1"); + Struct65500ref s = new Struct65500ref(); + s.o1 = new Object(); + TestWrite(1, 2, 3, 4, s); // 4 int reg args, then struct stack arg + } + + public static int Main() + { + Test1(); + + if (iret == 100) + { + Console.WriteLine("TEST PASSED"); + } + else + { + Console.WriteLine("TEST FAILED"); + } + return iret; + } + } +} diff --git a/tests/src/JIT/Methodical/largeframes/skip5/skippage5.cs b/tests/src/JIT/Methodical/largeframes/skip5/skippage5.cs new file mode 100644 index 000000000000..4d10adb77b51 --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip5/skippage5.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +class Program +{ + [StructLayout(LayoutKind.Sequential)] + unsafe struct S + { + fixed byte x[65500]; + } + + class C + { + public S s; + } + + static int Main() => Test(new C()); + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Call(int r0, int r1, int r2, int r3, int r4, int r5, int r6, S s) + { + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int Test(C c) + { + Call(0, 1, 2, 3, 4, 5, 42, c.s); + Console.WriteLine("TEST PASSED"); + return 100; // If we don't crash, we pass + } +} diff --git a/tests/src/JIT/Methodical/largeframes/skip5/skippage5.csproj b/tests/src/JIT/Methodical/largeframes/skip5/skippage5.csproj new file mode 100644 index 000000000000..3e4678528e19 --- /dev/null +++ b/tests/src/JIT/Methodical/largeframes/skip5/skippage5.csproj @@ -0,0 +1,36 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {43F24741-6FD9-4593-92FA-D3252B540A92} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + 1 + true + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + diff --git a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/ColorPacket.cs b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/ColorPacket.cs index 59756243d655..bf48fcf9e9cd 100644 --- a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/ColorPacket.cs +++ b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/ColorPacket.cs @@ -18,9 +18,9 @@ internal static class ColorPacket256Helper public static Int32RGBPacket256 ConvertToIntRGB(this VectorPacket256 colors) { - var rsMask = Compare(colors.Xs, One, FloatComparisonMode.GreaterThanOrderedNonSignaling); - var gsMask = Compare(colors.Ys, One, FloatComparisonMode.GreaterThanOrderedNonSignaling); - var bsMask = Compare(colors.Zs, One, FloatComparisonMode.GreaterThanOrderedNonSignaling); + var rsMask = Compare(colors.Xs, One, FloatComparisonMode.OrderedGreaterThanNonSignaling); + var gsMask = Compare(colors.Ys, One, FloatComparisonMode.OrderedGreaterThanNonSignaling); + var bsMask = Compare(colors.Zs, One, FloatComparisonMode.OrderedGreaterThanNonSignaling); var rs = BlendVariable(colors.Xs, One, rsMask); var gs = BlendVariable(colors.Ys, One, gsMask); diff --git a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/Intersections.cs b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/Intersections.cs index 917b3dbb3bbe..6c1441cba530 100644 --- a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/Intersections.cs +++ b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/Intersections.cs @@ -33,7 +33,7 @@ public bool AllNullIntersections() [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AllNullIntersections(Vector256 dis) { - var cmp = Compare(dis, NullDistance, FloatComparisonMode.EqualOrderedNonSignaling); + var cmp = Compare(dis, NullDistance, FloatComparisonMode.OrderedEqualNonSignaling); var zero = Vector256.Zero; // efficiently generate an all-one mask vector by lower latency AVX2 ComapreEqual var mask = Avx2.CompareEqual(zero, zero); diff --git a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PacketTracer.cs b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PacketTracer.cs index b0d2fe7201f7..34a2dd5d38b4 100644 --- a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PacketTracer.cs +++ b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PacketTracer.cs @@ -68,7 +68,7 @@ private ColorPacket256 TraceRay(RayPacket256 rayPacket256, Scene scene, int dept return ColorPacket256Helper.BackgroundColor; } var color = Shade(isect, rayPacket256, scene, depth); - var isNull = Compare(isect.Distances, Intersections.NullDistance, FloatComparisonMode.EqualOrderedNonSignaling); + var isNull = Compare(isect.Distances, Intersections.NullDistance, FloatComparisonMode.OrderedEqualNonSignaling); var backgroundColor = ColorPacket256Helper.BackgroundColor.Xs; return new ColorPacket256(BlendVariable(color.Xs, backgroundColor, isNull), BlendVariable(color.Ys, backgroundColor, isNull), @@ -82,7 +82,7 @@ private Vector256 TestRay(RayPacket256 rayPacket256, Scene scene) { return Vector256.Zero; } - var isNull = Compare(isect.Distances, Intersections.NullDistance, FloatComparisonMode.EqualOrderedNonSignaling); + var isNull = Compare(isect.Distances, Intersections.NullDistance, FloatComparisonMode.OrderedEqualNonSignaling); return BlendVariable(isect.Distances, Vector256.Zero, isNull); } @@ -95,10 +95,10 @@ private Intersections MinIntersections(RayPacket256 rayPacket256, Scene scene) if (!Intersections.AllNullIntersections(distance)) { - var notNullMask = Compare(distance, Intersections.NullDistance, FloatComparisonMode.NotEqualOrderedNonSignaling); - var nullMinMask = Compare(mins.Distances, Intersections.NullDistance, FloatComparisonMode.EqualOrderedNonSignaling); + var notNullMask = Compare(distance, Intersections.NullDistance, FloatComparisonMode.OrderedNotEqualNonSignaling); + var nullMinMask = Compare(mins.Distances, Intersections.NullDistance, FloatComparisonMode.OrderedEqualNonSignaling); - var lessMinMask = Compare(mins.Distances, distance, FloatComparisonMode.GreaterThanOrderedNonSignaling); + var lessMinMask = Compare(mins.Distances, distance, FloatComparisonMode.OrderedGreaterThanNonSignaling); var minMask = And(notNullMask, Or(nullMinMask, lessMinMask)); var minDis = BlendVariable(mins.Distances, distance, minMask); var minIndices = BlendVariable(mins.ThingIndices.AsSingle(), @@ -141,12 +141,12 @@ private ColorPacket256 GetNaturalColor(Vector256 things, VectorPacket256 po var neatIsectDis = TestRay(new RayPacket256(pos, livec), scene); // is in shadow? - var mask1 = Compare(neatIsectDis, ldis.Lengths, FloatComparisonMode.LessThanOrEqualOrderedNonSignaling); - var mask2 = Compare(neatIsectDis, zero, FloatComparisonMode.NotEqualOrderedNonSignaling); + var mask1 = Compare(neatIsectDis, ldis.Lengths, FloatComparisonMode.OrderedLessThanOrEqualNonSignaling); + var mask2 = Compare(neatIsectDis, zero, FloatComparisonMode.OrderedNotEqualNonSignaling); var isInShadow = And(mask1, mask2); Vector256 illum = VectorPacket256.DotProduct(livec, norms); - Vector256 illumGraterThanZero = Compare(illum, zero, FloatComparisonMode.GreaterThanOrderedNonSignaling); + Vector256 illumGraterThanZero = Compare(illum, zero, FloatComparisonMode.OrderedGreaterThanNonSignaling); var tmpColor1 = illum * colorPacket; var defaultRGB = zero; Vector256 lcolorR = BlendVariable(defaultRGB, tmpColor1.Xs, illumGraterThanZero); @@ -155,7 +155,7 @@ private ColorPacket256 GetNaturalColor(Vector256 things, VectorPacket256 po ColorPacket256 lcolor = new ColorPacket256(lcolorR, lcolorG, lcolorB); Vector256 specular = VectorPacket256.DotProduct(livec, rds.Normalize()); - Vector256 specularGraterThanZero = Compare(specular, zero, FloatComparisonMode.GreaterThanOrderedNonSignaling); + Vector256 specularGraterThanZero = Compare(specular, zero, FloatComparisonMode.OrderedGreaterThanNonSignaling); var difColor = new ColorPacket256(1, 1, 1); var splColor = new ColorPacket256(1, 1, 1); diff --git a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PlanePacket.cs b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PlanePacket.cs index b3607b9581b4..c2947944140a 100644 --- a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PlanePacket.cs +++ b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/PlanePacket.cs @@ -29,7 +29,7 @@ public override Vector256 Intersect(RayPacket256 rayPacket256) { var denom = VectorPacket256.DotProduct(Norms, rayPacket256.Dirs); var dist = Divide(Add(VectorPacket256.DotProduct(Norms, rayPacket256.Starts), Offsets), Subtract(Vector256.Zero, denom)); - var gtMask = Compare(denom, Vector256.Zero, FloatComparisonMode.GreaterThanOrderedNonSignaling); + var gtMask = Compare(denom, Vector256.Zero, FloatComparisonMode.OrderedGreaterThanNonSignaling); return BlendVariable(dist, Intersections.NullDistance, gtMask); } } diff --git a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/SpherePacket.cs b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/SpherePacket.cs index 09e461201ec2..0f87171b263a 100644 --- a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/SpherePacket.cs +++ b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/SpherePacket.cs @@ -30,11 +30,11 @@ public override Vector256 Intersect(RayPacket256 rayPacket256) var eo = Centers - rayPacket256.Starts; var v = VectorPacket256.DotProduct(eo, rayPacket256.Dirs); var zero = Vector256.Zero; - var vLessZeroMask = Compare(v, zero, FloatComparisonMode.LessThanOrderedNonSignaling); + var vLessZeroMask = Compare(v, zero, FloatComparisonMode.OrderedLessThanNonSignaling); var discs = Subtract(Multiply(Radiuses, Radiuses), Subtract(VectorPacket256.DotProduct(eo, eo), Multiply(v, v))); - var discLessZeroMask = Compare(discs, zero, FloatComparisonMode.LessThanOrderedNonSignaling); + var discLessZeroMask = Compare(discs, zero, FloatComparisonMode.OrderedLessThanNonSignaling); var dists = BlendVariable(Subtract(v, Sqrt(discs)), zero, Or(vLessZeroMask, discLessZeroMask)); - var isZero = Compare(dists, zero, FloatComparisonMode.EqualOrderedNonSignaling); + var isZero = Compare(dists, zero, FloatComparisonMode.OrderedEqualNonSignaling); return BlendVariable(dists, Intersections.NullDistance, isZero); } } diff --git a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/VectorMath.cs b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/VectorMath.cs index c0e3437af2c0..074b90005036 100644 --- a/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/VectorMath.cs +++ b/tests/src/JIT/Performance/CodeQuality/HWIntrinsic/X86/PacketTracer/VectorMath.cs @@ -76,13 +76,13 @@ public static Vector256 Exp(Vector256 value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Log(Vector256 value) { - Vector256 invalidMask = Compare(value, Vector256.Zero, FloatComparisonMode.LessThanOrEqualOrderedNonSignaling); + Vector256 invalidMask = Compare(value, Vector256.Zero, FloatComparisonMode.OrderedLessThanOrEqualNonSignaling); Vector256 x = Max(value, MinNormPos.AsSingle()); Vector256 ei = Avx2.ShiftRightLogical(x.AsInt32(), 23); x = Or(And(x, MantMask.AsSingle()), Point5); ei = Avx2.Subtract(ei, Ox7); Vector256 e = Add(ConvertToVector256Single(ei), One); - Vector256 mask = Compare(x, Sqrthf, FloatComparisonMode.LessThanOrderedNonSignaling); + Vector256 mask = Compare(x, Sqrthf, FloatComparisonMode.OrderedLessThanNonSignaling); Vector256 tmp = And(x, mask); x = Subtract(x, One); e = Subtract(e, And(One, mask)); diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_20958/GitHub_20958.cs b/tests/src/JIT/Regression/JitBlue/GitHub_20958/GitHub_20958.cs deleted file mode 100644 index 45730f5ee4da..000000000000 --- a/tests/src/JIT/Regression/JitBlue/GitHub_20958/GitHub_20958.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -// This test was extracted from the Indexer tests in the corefx System.Memory.Tests. -// The JIT was trying to expand the form of indexer that takes a range, but was not -// correctly expanding it, as it was expecting only the scalar index form. - -public class GitHub_20958 -{ - - public static int IndexerWithRangeTest() - { - int returnVal = 100; - - ReadOnlySpan span = "Hello".AsSpan(); - ReadOnlySpan sliced = span[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))]; - if (span.Slice(1, 3) != sliced) - { - returnVal = -1; - } - try - { - ReadOnlySpan s = "Hello".AsSpan()[new Range(new Index(1, fromEnd: true), new Index(1, fromEnd: false))]; - returnVal = -1; - } - catch (ArgumentOutOfRangeException) - { - } - catch (Exception e) - { - returnVal = -1; - } - Span span1 = new Span(new char[] { 'H', 'e', 'l', 'l', 'o' }); - Span sliced1 = span1[new Range(new Index(2, fromEnd: false), new Index(1, fromEnd: true))]; - if (span1.Slice(2, 2) != sliced1) - { - returnVal = -1; - } - try - { - Span s = new Span(new char[] { 'H', 'i' })[new Range(new Index(0, fromEnd: true), new Index(1, fromEnd: false))]; - returnVal = -1; - } - catch (ArgumentOutOfRangeException) - { - } - catch (Exception e) - { - returnVal = -1; - } - return returnVal; - } - - public static int Main() - { - return IndexerWithRangeTest(); - } -} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23411/GitHub_23411.il b/tests/src/JIT/Regression/JitBlue/GitHub_23411/GitHub_23411.il index e6e508f0e3d1..e56102620623 100644 --- a/tests/src/JIT/Regression/JitBlue/GitHub_23411/GitHub_23411.il +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23411/GitHub_23411.il @@ -1,3 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + .assembly extern System.Runtime { } .assembly extern System.Console { } .assembly extern System.Globalization { } diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs new file mode 100644 index 000000000000..b75bc5156850 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs @@ -0,0 +1,212 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +using System; +using System.Runtime.CompilerServices; + +class GitHub_23739 +{ + struct Struct1f + { + float a; + } + + class Cls1f + { + public Struct1f sf; + } + + struct Struct2f + { + float a, b; + } + + class Cls2f + { + public Struct2f sf; + } + + struct Struct3f + { + float a, b, c; + } + + class Cls3f + { + public Struct3f sf; + } + + struct Struct4f + { + float a, b, c, d; + } + + class Cls4f + { + public Struct4f sf; + } + + struct Struct5f + { + float a, b, c, d, e; + } + + class Cls5f + { + public Struct5f sf; + } + + struct Struct6f + { + float a, b, c, d, e, f; + } + + class Cls6f + { + public Struct6f sf; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Sink(ref T t) + { + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test1f(Cls1f c) + { + Struct1f l1 = default; + Struct1f l2 = default; + Struct1f l3 = default; + + for (int i = 0; i < 10; i++) + { + l1 = c.sf; + l2 = c.sf; + l3 = c.sf; + } + + Sink(ref l1); + Sink(ref l2); + Sink(ref l3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test2f(Cls2f c) + { + Struct2f l1 = default; + Struct2f l2 = default; + Struct2f l3 = default; + + for (int i = 0; i < 10; i++) + { + l1 = c.sf; + l2 = c.sf; + l3 = c.sf; + } + + Sink(ref l1); + Sink(ref l2); + Sink(ref l3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test3f(Cls3f c) + { + Struct3f l1 = default; + Struct3f l2 = default; + Struct3f l3 = default; + + for (int i = 0; i < 10; i++) + { + l1 = c.sf; + l2 = c.sf; + l3 = c.sf; + } + + Sink(ref l1); + Sink(ref l2); + Sink(ref l3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test4f(Cls4f c) + { + Struct4f l1 = default; + Struct4f l2 = default; + Struct4f l3 = default; + + for (int i = 0; i < 10; i++) + { + l1 = c.sf; + l2 = c.sf; + l3 = c.sf; + } + + Sink(ref l1); + Sink(ref l2); + Sink(ref l3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test5f(Cls5f c) + { + Struct5f l1 = default; + Struct5f l2 = default; + Struct5f l3 = default; + + for (int i = 0; i < 10; i++) + { + l1 = c.sf; + l2 = c.sf; + l3 = c.sf; + } + + Sink(ref l1); + Sink(ref l2); + Sink(ref l3); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Test6f(Cls6f c) + { + Struct6f l1 = default; + Struct6f l2 = default; + Struct6f l3 = default; + + for (int i = 0; i < 10; i++) + { + l1 = c.sf; + l2 = c.sf; + l3 = c.sf; + } + + Sink(ref l1); + Sink(ref l2); + Sink(ref l3); + } + + static int Main() + { + Cls1f cls1f = new Cls1f(); + Test1f(cls1f); + + Cls2f cls2f = new Cls2f(); + Test2f(cls2f); + + Cls3f cls3f = new Cls3f(); + Test3f(cls3f); + + Cls4f cls4f = new Cls4f(); + Test4f(cls4f); + + Cls5f cls5f = new Cls5f(); + Test5f(cls5f); + + Cls6f cls6f = new Cls6f(); + Test6f(cls6f); + + return 100; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_20958/GitHub_20958.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj similarity index 93% rename from tests/src/JIT/Regression/JitBlue/GitHub_20958/GitHub_20958.csproj rename to tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj index d86ed9f3d765..fb6ae363ebee 100644 --- a/tests/src/JIT/Regression/JitBlue/GitHub_20958/GitHub_20958.csproj +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj @@ -8,10 +8,11 @@ Exe True + True - \ No newline at end of file + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23791/GitHub_23791.cs b/tests/src/JIT/Regression/JitBlue/GitHub_23791/GitHub_23791.cs new file mode 100644 index 000000000000..e724823c34f0 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23791/GitHub_23791.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +using System; +using System.Runtime.CompilerServices; + +// The jit should null check 'this' in NextElement + +unsafe struct GitHub_23791 +{ + fixed byte A[10]; + + [MethodImpl(MethodImplOptions.NoInlining)] + byte NextElement(int i) => A[1+i]; + + static int Main() + { + int result = -1; + GitHub_23791* x = null; + bool threw = true; + + try + { + byte t = x->NextElement(100000); + threw = false; + } + catch (NullReferenceException) + { + result = 100; + } + + if (!threw) + { + Console.WriteLine($"FAIL: did not throw an exception"); + } + + return result; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23791/GitHub_23791.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_23791/GitHub_23791.csproj new file mode 100644 index 000000000000..7198ed8b5bc1 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23791/GitHub_23791.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + 2.0 + {2649FAFE-07BF-4F93-8120-BA9A69285ABB} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + None + True + True + + + + False + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23792/GitHub_23792.il b/tests/src/JIT/Regression/JitBlue/GitHub_23792/GitHub_23792.il new file mode 100644 index 000000000000..9c63524e6fb5 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23792/GitHub_23792.il @@ -0,0 +1,163 @@ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This tests that +// ((x+icon)+y) => ((x+y)+icon) +// and +// ((x+icon1)+(y+icon2)) => ((x+y)+(icon1+icon2)) +// transformations in morph don't create byrefs pointing outside of the ref object. +// Method Run1 calculates (theRef - 8 + a -8 + b). +// Before the fix morph transformed this to ((theRef + a) + b -16). +// theRef + a may point outside of the object. +// Method Run2 calculates ((theRef - 8) + (a - 8) + b). +// Before the fix morph transformed this to ((theRef + a) + b -16). +// theRef + a may point outside of the object. + +.assembly extern mscorlib{} +.assembly extern System.Console{} +.assembly a {} + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + + //public static int Main() + //{ + // byte size = 9; + // byte[] arr = new byte[9]; + // for (byte i = 0; i < size; ++i) + // { + // arr[i] = i; + // } + // ref byte newRef1 = ref Run1(ref arr[8], (IntPtr)8, (IntPtr)8); + // ref byte newRef2 = ref Run2(ref arr[8], (IntPtr)8, (IntPtr)8); + // int result = 84 + newRef1 + newRef2; + // if (result == 100) + // { + // Console.WriteLine("PASS"); + // } + // else + // { + // Console.WriteLine("FAIL"); + // } + // return result; + //} + + .method public hidebysig static int32 Main() cil managed + { + .entrypoint + // Code size 119 (0x77) + .maxstack 3 + .locals init (uint8 V_0, + uint8[] V_1, + uint8& V_2, + uint8& V_3, + uint8 V_4) + IL_0000: ldc.i4.s 9 + IL_0002: stloc.0 + IL_0003: ldc.i4.s 9 + IL_0005: newarr [mscorlib]System.Byte + IL_000a: stloc.1 + IL_000b: ldc.i4.0 + IL_000c: stloc.s V_4 + IL_000e: br.s IL_001d + IL_0010: ldloc.1 + IL_0011: ldloc.s V_4 + IL_0013: ldloc.s V_4 + IL_0015: stelem.i1 + IL_0016: ldloc.s V_4 + IL_0018: ldc.i4.1 + IL_0019: add + IL_001a: conv.u1 + IL_001b: stloc.s V_4 + IL_001d: ldloc.s V_4 + IL_001f: ldloc.0 + IL_0020: blt.s IL_0010 + IL_0022: ldloc.1 + IL_0023: ldc.i4.8 + IL_0024: ldelema [mscorlib]System.Byte + IL_0029: ldc.i4.8 + IL_002a: call native int [mscorlib]System.IntPtr::op_Explicit(int32) + IL_002f: ldc.i4.8 + IL_0030: call native int [mscorlib]System.IntPtr::op_Explicit(int32) + IL_0035: call uint8& Test::Run1(uint8&, + native int, + native int) + IL_003a: stloc.2 + IL_003b: ldloc.1 + IL_003c: ldc.i4.8 + IL_003d: ldelema [mscorlib]System.Byte + IL_0042: ldc.i4.8 + IL_0043: call native int [mscorlib]System.IntPtr::op_Explicit(int32) + IL_0048: ldc.i4.8 + IL_0049: call native int [mscorlib]System.IntPtr::op_Explicit(int32) + IL_004e: call uint8& Test::Run2(uint8&, + native int, + native int) + IL_0053: stloc.3 + IL_0054: ldc.i4.s 84 + IL_0056: ldloc.2 + IL_0057: ldind.u1 + IL_0058: add + IL_0059: ldloc.3 + IL_005a: ldind.u1 + IL_005b: add + IL_005c: dup + IL_005d: ldc.i4.s 100 + IL_005f: bne.un.s IL_006c + IL_0061: ldstr "PASS" + IL_0066: call void [System.Console]System.Console::WriteLine(string) + IL_006b: ret + IL_006c: ldstr "FAIL" + IL_0071: call void [System.Console]System.Console::WriteLine(string) + IL_0076: ret +} // end of method Test::Main + + + .method private hidebysig static uint8& + Run1(uint8& theRef, + native int a, + native int b) cil managed noinlining + { + ldarg.0 + ldc.i4 8 + sub + ldarg.1 + ldc.i4 8 + sub + add + ldc.i4 8 + add + ret + } // end of method Test::Run1 + + .method private hidebysig static uint8& + Run2(uint8& theRef, + native int a, + native int b) cil managed noinlining + { + ldarg.0 + ldc.i4 -8 + add + ldarg.1 + ldc.i4 -8 + add + add + ldarg.2 + add + ret + } // end of method Test::Run2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method Test::.ctor + +} // end of class Test diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23792/GitHub_23792.ilproj b/tests/src/JIT/Regression/JitBlue/GitHub_23792/GitHub_23792.ilproj new file mode 100644 index 000000000000..1e33a02324f9 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23792/GitHub_23792.ilproj @@ -0,0 +1,37 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + + + False + + + + None + True + + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.cs b/tests/src/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.cs new file mode 100644 index 000000000000..bfa6fcc49251 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +class Program +{ + [StructLayout(LayoutKind.Sequential)] + struct S + { + public uint i0; + public uint i1; + public uint i2; + public uint i3; + + public int i4; + public int i5; + } + + [StructLayout(LayoutKind.Sequential)] + struct S16 + { + public uint i0; + public uint i1; + public uint i2; + public uint i3; + } + + static int Main() + { + S s = new S(); + s.i0 = 0x12345678; + s.i1 = 0x87654321; + return Test(s); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int Call(int r0, int r1, int r2, int r3, int r4, int r5, int r6, S16 s) + { + return (s.i0 == 0x12345678 && s.i1 == 0x87654321) ? 100 : 1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Escape(ref T t) + { + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int Test(S p) + { + S s = p; + Escape(ref s); + return Call(0, 1, 2, 3, 4, 5, 6, Unsafe.As(ref s)); + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj new file mode 100644 index 000000000000..83594da8faf8 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23794/GitHub_23794.csproj @@ -0,0 +1,17 @@ + + + + + Release + AnyCPU + $(MSBuildProjectName) + Exe + + True + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23861/GitHub_23861.cs b/tests/src/JIT/Regression/JitBlue/GitHub_23861/GitHub_23861.cs new file mode 100644 index 000000000000..2bd0d0982d9d --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23861/GitHub_23861.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; +using System.Numerics; + +namespace GitHub_23861 +{ + class Program + { + static int returnVal = 100; + static int Main(string[] args) + { + LessThanAllDouble(); + + if (returnVal == 100) + { + Console.WriteLine("Pass"); + } + else + { + Console.WriteLine("FAIL"); + } + return returnVal; + } + + public static void LessThanAllDouble() { TestVectorLessThanAll(); } + + private static void TestVectorLessThanAll() where T : struct + { + T[] values1 = new T[Vector.Count]; + for (int g = 0; g < Vector.Count; g++) + { + values1[g] = (T)(dynamic)g; + } + Vector vec1 = new Vector(values1); + + T[] values2 = new T[Vector.Count]; + for (int g = 0; g < Vector.Count; g++) + { + values2[g] = (T)(dynamic)(g + 25); + } + Vector vec2 = new Vector(values2); + + if (!Vector.LessThanAll(vec1, vec2)) + { + returnVal = -1; + } + if (!Vector.LessThanAll(Vector.Zero, Vector.One)) + { + returnVal = -1; + } + + T[] values3 = new T[Vector.Count]; + for (int g = 0; g < Vector.Count; g++) + { + values3[g] = (g < Vector.Count / 2) ? Vector.Zero[0] : Vector.One[0]; + } + Vector vec3 = new Vector(values3); + if (Vector.LessThanAll(vec3, Vector.One)) + { + returnVal = -1; + } + } + } +} + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23861/GitHub_23861.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_23861/GitHub_23861.csproj new file mode 100644 index 000000000000..e191e01217e9 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23861/GitHub_23861.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + False + + + + None + True + + + + + + + + + + diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23950/GitHub_23950.il b/tests/src/JIT/Regression/JitBlue/GitHub_23950/GitHub_23950.il new file mode 100644 index 000000000000..f96e2cd3d798 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23950/GitHub_23950.il @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.assembly extern mscorlib {} + +.assembly GitHub_23970 {} + +// Test that jit can inline method with a pinned pointer + +.class public sequential ansi sealed beforefieldinit Program + extends [mscorlib]System.Object +{ + .method private hidebysig static + int32 Main ( + string[] args + ) cil managed + { + + .maxstack 1 + .entrypoint + .locals init ( + [0] int32 + ) + nop + ldc.i4.s 100 + stloc.0 + ldloca.s 0 + call int32 Program::GetValueUnsafe(int32&) + ret + } + + .method private hidebysig + static int32 GetValueUnsafe ( + int32& buffer + ) cil managed + { + .maxstack 3 + .locals init ( + [0] int32* pinned + ) + + ldarg.0 + stloc.0 + ldloc.0 + ldind.i4 + ret + } +} \ No newline at end of file diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23950/GitHub_23950.ilproj b/tests/src/JIT/Regression/JitBlue/GitHub_23950/GitHub_23950.ilproj new file mode 100644 index 000000000000..43c02b93f769 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23950/GitHub_23950.ilproj @@ -0,0 +1,25 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + ..\..\ + 0 + + + + + None + True + + + + + + + + diff --git a/tests/src/JIT/opt/Enum/hasflag.cs b/tests/src/JIT/opt/Enum/hasflag.cs index 08b418b69497..0c415ee7285c 100644 --- a/tests/src/JIT/opt/Enum/hasflag.cs +++ b/tests/src/JIT/opt/Enum/hasflag.cs @@ -8,6 +8,7 @@ // except for the case in the try/catch. using System; +using System.Runtime.CompilerServices; enum E { @@ -40,6 +41,12 @@ class EClass public E e; } +class ShortHolder +{ + public ShortHolder(short s) { v = s; } + public short v; +} + class P { static E[] ArrayOfE = { E.RED, E.BLUE }; @@ -81,6 +88,20 @@ public static bool ByrefG(ref G e1, G e2) return e1.HasFlag(e2); } + // Example from GitHub 23847 + [MethodImpl(MethodImplOptions.NoInlining)] + public static bool GitHub23847(E e1, short s) + { + return GitHub23847Aux(s).HasFlag(e1); + } + + // Once this is inlined we end up with a short pre-boxed value + public static E GitHub23847Aux(short s) + { + ShortHolder h = new ShortHolder(s); + return (E)h.v; + } + public static int Main() { E e1 = E.RED; @@ -120,8 +141,10 @@ public static int Main() G g1 = G.RED; bool true9 = ByrefG(ref g1, G.RED); + bool false10 = GitHub23847(E.RED, 0x100); + bool[] trueResults = {true0, true1, true2, true3, true4, true5, true6, true7, true8, true9}; - bool[] falseResults = {false0, false1, false2, false3, false4, false5, false6, false7, false8, false9}; + bool[] falseResults = {false0, false1, false2, false3, false4, false5, false6, false7, false8, false9, false10}; bool resultOk = true; diff --git a/tests/src/JIT/opt/Enum/hasflag.csproj b/tests/src/JIT/opt/Enum/hasflag.csproj index 42e9f46eba09..a86bec7f0d8e 100644 --- a/tests/src/JIT/opt/Enum/hasflag.csproj +++ b/tests/src/JIT/opt/Enum/hasflag.csproj @@ -14,7 +14,6 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages ..\..\ 7a9bfb7d - 1 diff --git a/tests/src/Loader/ContextualReflection/ContextualReflection.cs b/tests/src/Loader/ContextualReflection/ContextualReflection.cs new file mode 100644 index 000000000000..1612c141b2d4 --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflection.cs @@ -0,0 +1,759 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Loader; +using System.Runtime.Remoting; +using System.Threading.Tasks; +using TestLibrary; + +namespace ContextualReflectionTest +{ + class AGenericClass + { + } + + class MockAssembly : Assembly + { + public MockAssembly() {} + } + + class Program : IProgram + { + public AssemblyLoadContext alc { get; set; } + public Assembly alcAssembly { get; set; } + public Type alcProgramType { get; set; } + public IProgram alcProgramInstance { get; set; } + public Assembly defaultAssembly { get; set; } + + public static int Main() + { + Program program = new Program(isolated:false); + + program.RunTests(); + + Console.WriteLine("Success"); + + return 100; + } + + public Program() + { + InitializeIsolation(true); + } + + public Program(bool isolated) + { + InitializeIsolation(isolated); + } + + public void InitializeIsolation(bool isolated) + { + if (isolated == false) + { + alc = new AssemblyLoadContext("Isolated", isCollectible: true); + defaultAssembly = Assembly.GetExecutingAssembly(); + alcAssembly = alc.LoadFromAssemblyPath(defaultAssembly.Location); + + Assert.AreEqual(alcAssembly, alc.LoadFromAssemblyName(alcAssembly.GetName())); + + alcProgramType = alcAssembly.GetType("ContextualReflectionTest.Program"); + + AssemblyLoadContext.Default.Resolving += TestResolve.ResolvingTestDefault; + alc.Resolving += TestResolve.ResolvingTestIsolated; + + alcProgramInstance = (IProgram) Activator.CreateInstance(alcProgramType); + } + else + { + alcAssembly = Assembly.GetExecutingAssembly(); + alc = AssemblyLoadContext.GetLoadContext(alcAssembly); + alcProgramType = typeof(Program); + alcProgramInstance = this; + defaultAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(alcAssembly.GetName()); + } + } + + void VerifyIsolationDefault() + { + VerifyIsolation(); + Assert.AreEqual(defaultAssembly, Assembly.GetExecutingAssembly()); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())); + Assert.AreNotEqual(alcProgramType, typeof(Program)); + Assert.AreNotEqual((object)alcProgramInstance, (object)this); + } + + void VerifyIsolationAlc() + { + VerifyIsolation(); + Assert.AreEqual(alcAssembly, Assembly.GetExecutingAssembly()); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())); + Assert.AreEqual(alcProgramType, typeof(Program)); + Assert.AreEqual((object)alcProgramInstance, (object)this); + } + + void VerifyIsolation() + { + Assert.AreEqual("Default", AssemblyLoadContext.Default.Name); + + Assert.IsNotNull(alc); + Assert.IsNotNull(alcAssembly); + Assert.IsNotNull(alcProgramType); + Assert.IsNotNull(alcProgramInstance); + + Assert.AreEqual("Isolated", alc.Name); + + Assert.AreNotEqual(defaultAssembly, alcAssembly); + Assert.AreNotEqual(alc, AssemblyLoadContext.Default); + + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(alcProgramInstance.alcAssembly)); + Assert.AreEqual(alcAssembly, alcProgramInstance.alcAssembly); + Assert.AreEqual(alcProgramType, alcProgramInstance.alcProgramType); + Assert.AreEqual(alcProgramInstance, alcProgramInstance.alcProgramInstance); + } + + void VerifyTestResolve() + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + TestResolve.Assert(ResolveEvents.NoEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + + // Make sure failure is not cached + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + TestResolve.Assert(ResolveEvents.NoEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + } + + void VerifyContextualReflectionProxy() + { + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + using (alc.EnterContextualReflection()) + { + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + using (AssemblyLoadContext.Default.EnterContextualReflection()) + { + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + using (AssemblyLoadContext.EnterContextualReflection(null)) + { + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + using (AssemblyLoadContext.EnterContextualReflection(alcAssembly)) + { + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + } + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + } + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + } + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + } + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + } + + void VerifyUsingStatementContextualReflectionUsage() + { + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + { + using IDisposable defaultScope = AssemblyLoadContext.Default.EnterContextualReflection(); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + + } + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + try + { + using IDisposable defaultScope = AssemblyLoadContext.Default.EnterContextualReflection(); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + + throw new InvalidOperationException(); + } + catch + { + } + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + using IDisposable defaultScope = AssemblyLoadContext.Default.EnterContextualReflection(); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + defaultScope.Dispose(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + } + + void VerifyBadContextualReflectionUsage() + { + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + alcScope.Dispose(); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + IDisposable defaultScope = AssemblyLoadContext.Default.EnterContextualReflection(); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + defaultScope.Dispose(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + IDisposable defaultScope = AssemblyLoadContext.Default.EnterContextualReflection(); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.CurrentContextualReflectionContext); + + alcScope.Dispose(); + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + defaultScope.Dispose(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + + { + IDisposable alcScope = alc.EnterContextualReflection(); + Assert.AreEqual(alc, AssemblyLoadContext.CurrentContextualReflectionContext); + try + { + IDisposable defaultScope = AssemblyLoadContext.EnterContextualReflection(null); + Assert.AreEqual(null, AssemblyLoadContext.CurrentContextualReflectionContext); + + throw new InvalidOperationException(); + } + catch + { + } + } + + Assert.IsNull(AssemblyLoadContext.CurrentContextualReflectionContext); + } + + void TestResolveMissingAssembly(bool isolated, Action action, bool skipNullIsolated = false) + { + using (AssemblyLoadContext.EnterContextualReflection(null)) + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestDefaultLoad")); + if (!skipNullIsolated) + TestResolve.Assert(isolated ? ResolveEvents.ExpectedEvent : ResolveEvents.NoEvent, () => action("TestIsolatedLoad")); + } + using (AssemblyLoadContext.Default.EnterContextualReflection()) + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestDefaultLoad")); + TestResolve.Assert(ResolveEvents.NoEvent, () => action("TestIsolatedLoad")); + } + using (alc.EnterContextualReflection()) + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestDefaultLoad")); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestIsolatedLoad")); + } + } + + void TestAssemblyLoad(bool isolated) + { + TestAssemblyLoad(isolated, (string assemblyName) => Assembly.Load(assemblyName)); + TestAssemblyLoad(isolated, (string assemblyName) => Assembly.Load(new AssemblyName(assemblyName))); + } + + void TestAssemblyLoad(bool isolated, Func assemblyLoad) + { + TestResolveMissingAssembly(isolated, (string assemblyName) => assemblyLoad(assemblyName)); + + using (AssemblyLoadContext.EnterContextualReflection(null)) + { + Assembly assembly = assemblyLoad("ContextualReflection"); + + Assert.AreEqual(isolated ? alc : AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(assembly)); + + Assembly depends = assemblyLoad("ContextualReflectionDependency"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(depends)); + } + using (AssemblyLoadContext.Default.EnterContextualReflection()) + { + Assembly assembly = assemblyLoad("ContextualReflection"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(assembly)); + + Assembly depends = assemblyLoad("ContextualReflectionDependency"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(depends)); + } + using (alc.EnterContextualReflection()) + { + Assembly assembly = assemblyLoad("ContextualReflection"); + + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(assembly)); + + Assembly depends = assemblyLoad("ContextualReflectionDependency"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(depends)); + } + } + + void TestTypeGetType(bool isolated) + { + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, throwOnError : false)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, throwOnError : false, ignoreCase : false)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, assemblyResolver : null, typeResolver : null)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, assemblyResolver : null, typeResolver : null, throwOnError : false)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, assemblyResolver : null, typeResolver : null, throwOnError : false, ignoreCase : false)); + } + + void TestTypeGetType(bool isolated, Func typeGetType) + { + TestResolveMissingAssembly(isolated, (string assemblyName) => typeGetType(string.Format("MyType, {0}", assemblyName))); + + using (AssemblyLoadContext.EnterContextualReflection(null)) + { + { + Type p = typeGetType("ContextualReflectionTest.Program"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type p = typeGetType("ContextualReflectionTest.Program, ContextualReflection"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type g = typeGetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]], ContextualReflection"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + Assert.AreEqual(isolated ? alc : AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(g.GenericTypeArguments[0].Assembly)); + } + } + using (AssemblyLoadContext.Default.EnterContextualReflection()) + { + { + Type p = typeGetType("ContextualReflectionTest.Program"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type p = typeGetType("ContextualReflectionTest.Program, ContextualReflection"); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(p.Assembly)); + } + { + Type g = typeGetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]], ContextualReflection"); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(g.Assembly)); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(g.GenericTypeArguments[0].Assembly)); + } + } + using (alc.EnterContextualReflection()) + { + { + Type p = typeGetType("ContextualReflectionTest.Program"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type p = typeGetType("ContextualReflectionTest.Program, ContextualReflection"); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(p.Assembly)); + } + { + Type g = typeGetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]], ContextualReflection"); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(g.Assembly)); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(g.GenericTypeArguments[0].Assembly)); + } + } + } + + void TestAssemblyGetType(bool isolated) + { + Assembly assembly = Assembly.GetExecutingAssembly(); + TestResolveMissingAssembly(isolated, + (string assemblyName) => assembly.GetType(string.Format("ContextualReflectionTest.AGenericClass`1[[MyType, {0}]]", assemblyName))); + + using (AssemblyLoadContext.EnterContextualReflection(null)) + { + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List).Assembly; + + Type m = mscorlib.GetType("System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (AssemblyLoadContext.Default.EnterContextualReflection()) + { + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List).Assembly; + + Type m = mscorlib.GetType("System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (alc.EnterContextualReflection()) + { + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List).Assembly; + + Type m = mscorlib.GetType("System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + } + + void TestActivatorCreateInstance(bool isolated) + { + TestResolveMissingAssembly(isolated, (string assemblyName) => Activator.CreateInstance(assemblyName, "MyType")); + TestResolveMissingAssembly(isolated, + (string assemblyName) => Activator.CreateInstance("System.Private.CoreLib", string.Format("System.Collections.Generic.List`1[[MyType, {0}]]", assemblyName)), + skipNullIsolated : true); + + TestResolveMissingAssembly(isolated, + (string assemblyName) => Activator.CreateInstance("ContextualReflection", string.Format("ContextualReflectionTest.AGenericClass`1[[MyType, {0}]]", assemblyName))); + + Assembly assembly = Assembly.GetExecutingAssembly(); + + using (AssemblyLoadContext.EnterContextualReflection(null)) + { + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance("ContextualReflection" , "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = assembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly expectedAssembly = alcAssembly; + + Assembly mscorlib = typeof (System.Collections.Generic.List).Assembly; + + ObjectHandle objectHandle = Activator.CreateInstance(mscorlib.GetName().Name, "System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type m = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(m); + Assert.AreEqual(mscorlib, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (AssemblyLoadContext.Default.EnterContextualReflection()) + { + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + ObjectHandle objectHandle = Activator.CreateInstance("ContextualReflection" , "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List).Assembly; + + ObjectHandle objectHandle = Activator.CreateInstance(mscorlib.GetName().Name, "System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type m = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (alc.EnterContextualReflection()) + { + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + ObjectHandle objectHandle = Activator.CreateInstance("ContextualReflection" , "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List).Assembly; + + ObjectHandle objectHandle = Activator.CreateInstance(mscorlib.GetName().Name, "System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type m = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(m); + Assert.AreEqual(mscorlib, m.Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + } + + void TestMockAssemblyThrows() + { + Exception e = Assert.ThrowsArgumentException("activating", () => AssemblyLoadContext.EnterContextualReflection(new MockAssembly())); + } + + public void RunTests() + { + VerifyIsolationDefault(); + VerifyTestResolve(); + VerifyContextualReflectionProxy(); + VerifyUsingStatementContextualReflectionUsage(); + VerifyBadContextualReflectionUsage(); + + RunTests(isolated : false); + alcProgramInstance.RunTestsIsolated(); + } + + public void RunTests(bool isolated) + { + TestAssemblyLoad(isolated); + TestTypeGetType(isolated); + TestAssemblyGetType(isolated); + TestActivatorCreateInstance(isolated); + TestMockAssemblyThrows(); + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public void RunTestsIsolated() + { + VerifyIsolationAlc(); + RunTests(isolated : true); + } + } +} + diff --git a/tests/src/Loader/ContextualReflection/ContextualReflection.csproj b/tests/src/Loader/ContextualReflection/ContextualReflection.csproj new file mode 100644 index 000000000000..6f88de38779c --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflection.csproj @@ -0,0 +1,18 @@ + + + + + Debug + AnyCPU + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + BuildAndRun + {78030DC5-F1A6-4B98-A130-A66F5047FF29} + + + + + + + + diff --git a/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs new file mode 100644 index 000000000000..f498db49a758 --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; +using System.Runtime.Loader; + +namespace ContextualReflectionTest +{ + public interface IProgram + { + AssemblyLoadContext alc { get; } + Assembly alcAssembly { get; } + Type alcProgramType { get; } + IProgram alcProgramInstance { get; } + [MethodImplAttribute(MethodImplOptions.NoInlining)] + void RunTestsIsolated(); + } + + public enum ResolveEvents + { + NoEvent, + ExpectedEvent, + }; + + public class TestResolve + { + static public ResolveEvents ResolveEvent { get; set;} + + static public Assembly ResolvingTestDefault(AssemblyLoadContext alc, AssemblyName assemblyName) + { + if (assemblyName.Name.Contains("TestDefaultLoad") && (ResolveEvent == ResolveEvents.NoEvent)) + { + ResolveEvent = ResolveEvents.ExpectedEvent; + } + return null; + } + + static public Assembly ResolvingTestIsolated(AssemblyLoadContext alc, AssemblyName assemblyName) + { + if (assemblyName.Name.Contains("TestIsolatedLoad") && (ResolveEvent == ResolveEvents.NoEvent)) + { + ResolveEvent = ResolveEvents.ExpectedEvent; + } + return null; + } + + static public void Assert(ResolveEvents expected, Action action) + { + ResolveEvent = ResolveEvents.NoEvent; + try + { + action(); + } + catch + { + } + finally + { + TestLibrary.Assert.AreEqual(expected, ResolveEvent); + } + } + } +} diff --git a/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj new file mode 100644 index 000000000000..1d8fb64087d8 --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj @@ -0,0 +1,17 @@ + + + + + Debug + AnyCPU + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + BuildOnly + {95DBE3B0-AA86-4366-BB8A-E04B534365F3} + + + + + + + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2.il index ad63b215c90a..5a928ff385a6 100644 --- a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2.il +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2.il @@ -62,18 +62,18 @@ ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() add ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() add add diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2_gm.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2_gm.il index 119b893b8a1b..a6ee94401eb4 100644 --- a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2_gm.il +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrained2_gm.il @@ -62,18 +62,18 @@ ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() add ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() ldarga.s 0 constrained. !!T - callvirt instance int32 class IAdder`1::PlusPlus() + callvirt instance int32 class IAdder`1::PlusPlus() add add diff --git a/tests/src/readytorun/tests/mainv1.csproj b/tests/src/readytorun/tests/mainv1.csproj index cca0b4106bd0..5a58658cb12c 100644 --- a/tests/src/readytorun/tests/mainv1.csproj +++ b/tests/src/readytorun/tests/mainv1.csproj @@ -11,6 +11,7 @@ ..\..\ BuildAndRun $(DefineConstants);STATIC;CORECLR + false diff --git a/tests/src/readytorun/tests/mainv2.csproj b/tests/src/readytorun/tests/mainv2.csproj index acf898e7f9ba..f7752947dbbc 100644 --- a/tests/src/readytorun/tests/mainv2.csproj +++ b/tests/src/readytorun/tests/mainv2.csproj @@ -11,6 +11,7 @@ ..\..\ $(DefineConstants);STATIC;CORECLR BuildAndRun + false diff --git a/tests/src/tracing/eventcounter/incrementingpollingcounter.cs b/tests/src/tracing/eventcounter/incrementingpollingcounter.cs index f2154607418c..d838087ec524 100644 --- a/tests/src/tracing/eventcounter/incrementingpollingcounter.cs +++ b/tests/src/tracing/eventcounter/incrementingpollingcounter.cs @@ -19,11 +19,11 @@ public partial class TestEventCounter [EventSource(Name = "SimpleEventSource")] private sealed class SimpleEventSource : EventSource { - private object _failureCounter; + private object _mockedCounter; - public SimpleEventSource(Func getFailureCount, Type IncrementingPollingCounterType) + public SimpleEventSource(Func getMockedCount, Type IncrementingPollingCounterType) { - _failureCounter = Activator.CreateInstance(IncrementingPollingCounterType, "failureCount", this, getFailureCount); + _mockedCounter = Activator.CreateInstance(IncrementingPollingCounterType, "failureCount", this, getMockedCount); } } @@ -91,12 +91,12 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } - public static int failureCountCalled = 0; + public static int mockedCountCalled = 0; - public static float getFailureCount() + public static double getMockedCount() { - failureCountCalled++; - return failureCountCalled; + mockedCountCalled++; + return mockedCountCalled; } public static int Main(string[] args) { @@ -117,12 +117,12 @@ public static int Main(string[] args) return 1; } - SimpleEventSource eventSource = new SimpleEventSource(getFailureCount, IncrementingPollingCounterType); + SimpleEventSource eventSource = new SimpleEventSource(getMockedCount, IncrementingPollingCounterType); // Want to sleep for 5000 ms to get some counters piling up. Thread.Sleep(5000); - if (!myListener.Failed && failureCountCalled > 0) + if (!myListener.Failed && mockedCountCalled > 0) { Console.WriteLine("Test Passed"); return 100; diff --git a/tests/src/tracing/eventcounter/pollingcounter.cs b/tests/src/tracing/eventcounter/pollingcounter.cs index ba2369d63998..de50ff49a1a0 100644 --- a/tests/src/tracing/eventcounter/pollingcounter.cs +++ b/tests/src/tracing/eventcounter/pollingcounter.cs @@ -22,10 +22,10 @@ private sealed class SimpleEventSource : EventSource private object _failureCounter; private object _successCounter; - public SimpleEventSource(Func getFailureCount, Func getSuccessCount, Type PollingCounterType) + public SimpleEventSource(Func getMockedCount, Func getSuccessCount, Type PollingCounterType) { _failureCounter = Activator.CreateInstance(PollingCounterType, "failureCount", this, getSuccessCount); - _successCounter = Activator.CreateInstance(PollingCounterType, "successCount", this, getFailureCount); + _successCounter = Activator.CreateInstance(PollingCounterType, "successCount", this, getMockedCount); } } @@ -112,9 +112,9 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } else if (name.Equals("successCount")) { - if (Int32.Parse(mean) != failureCountCalled) + if (Int32.Parse(mean) != mockedCountCalled) { - Console.WriteLine($"Mean is not what we expected: {mean} vs {failureCountCalled}"); + Console.WriteLine($"Mean is not what we expected: {mean} vs {mockedCountCalled}"); } } @@ -137,16 +137,16 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } - public static int failureCountCalled = 0; + public static int mockedCountCalled = 0; public static int successCountCalled = 0; - public static float getFailureCount() + public static double getMockedCount() { - failureCountCalled++; - return failureCountCalled; + mockedCountCalled++; + return mockedCountCalled; } - public static float getSuccessCount() + public static double getSuccessCount() { successCountCalled++; return successCountCalled; @@ -171,12 +171,12 @@ public static int Main(string[] args) return 1; } - SimpleEventSource eventSource = new SimpleEventSource(getFailureCount, getSuccessCount, PollingCounterType); + SimpleEventSource eventSource = new SimpleEventSource(getMockedCount, getSuccessCount, PollingCounterType); // Want to sleep for 5000 ms to get some counters piling up. Thread.Sleep(5000); - if (myListener.FailureEventCount > 0 && myListener.SuccessEventCount > 0 && !myListener.Failed && (failureCountCalled > 0 && successCountCalled > 0)) + if (myListener.FailureEventCount > 0 && myListener.SuccessEventCount > 0 && !myListener.Failed && (mockedCountCalled > 0 && successCountCalled > 0)) { Console.WriteLine("Test Passed"); return 100; diff --git a/tests/testgrouping.proj b/tests/testgrouping.proj new file mode 100644 index 000000000000..1ff04a97d59c --- /dev/null +++ b/tests/testgrouping.proj @@ -0,0 +1,155 @@ + + + + baseservices.threading.generics + $(BinDir)baseservices\threading\baseservices.threading.XUnitWrapper.dll + + + + JIT.jit64.hfa + $(BinDir)JIT\jit64\JIT.jit64.XUnitWrapper.dll + + + + JIT.jit64.mcc + $(BinDir)JIT\jit64\JIT.jit64.XUnitWrapper.dll + + + + JIT.jit64.opt + $(BinDir)JIT\jit64\JIT.jit64.XUnitWrapper.dll + + + + JIT.jit64.valuetypes + $(BinDir)JIT\jit64\JIT.jit64.XUnitWrapper.dll + + + + JIT.Methodical.a-dA-D + $(BinDir)JIT\Methodical\JIT.Methodical.XUnitWrapper.dll + + + + JIT.Methodical.eh + $(BinDir)JIT\Methodical\JIT.Methodical.XUnitWrapper.dll + + + + JIT.Methodical.e-iE-I + $(BinDir)JIT\Methodical\JIT.Methodical.XUnitWrapper.dll + + + + JIT.Methodical.e-iE-I + $(BinDir)JIT\Methodical\JIT.Methodical.XUnitWrapper.dll + + + + JIT.Regression.CLR-x86-JIT.V1-M09-M11 + $(BinDir)JIT\Regression\JIT.Regression.XUnitWrapper.dll + + + + JIT.Regression.CLR-x86-JIT.V1-M12-M13 + $(BinDir)JIT\Regression\JIT.Regression.XUnitWrapper.dll + + + + Loader.classloader.generics + $(BinDir)Loader\classloader\Loader.classloader.XUnitWrapper.dll + + + + Loader.classloader.TypeGeneratorTests.TypeGeneratorTest0-299 + $(BinDir)Loader\classloader\Loader.classloader.XUnitWrapper.dll + + + + Loader.classloader.TypeGeneratorTests.TypeGeneratorTest300-599 + $(BinDir)Loader\classloader\Loader.classloader.XUnitWrapper.dll + + + + Loader.classloader.TypeGeneratorTests.TypeGeneratorTest600-899 + $(BinDir)Loader\classloader\Loader.classloader.XUnitWrapper.dll + + + + Loader.classloader.TypeGeneratorTests.TypeGeneratorTest900-1199 + $(BinDir)Loader\classloader\Loader.classloader.XUnitWrapper.dll + + + + Loader.classloader.TypeGeneratorTests.TypeGeneratorTest1200-1500 + $(BinDir)Loader\classloader\Loader.classloader.XUnitWrapper.dll + + + + PayloadGroup0 + + + + Interop + + + + JIT + + + diff --git a/tests/xunitconsolerunner.depproj b/tests/xunitconsolerunner.depproj new file mode 100644 index 000000000000..4d6e724684d3 --- /dev/null +++ b/tests/xunitconsolerunner.depproj @@ -0,0 +1,13 @@ + + + + + + netcoreapp2.0 + + + + + + +