From cf801ca091d69295399561ff1472cf24f55c13b8 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 8 Mar 2021 19:11:45 -0600 Subject: [PATCH 001/115] Generalize the test runner a bit --- src/mono/sample/wasm/wasm.mk | 2 +- src/mono/wasm/runtime-test.js | 154 ++++++++++++----------- src/mono/wasm/runtime/binding_support.js | 3 +- src/mono/wasm/runtime/library_mono.js | 17 ++- 4 files changed, 95 insertions(+), 81 deletions(-) diff --git a/src/mono/sample/wasm/wasm.mk b/src/mono/sample/wasm/wasm.mk index 1858ca37911824..c62b67a1777119 100644 --- a/src/mono/sample/wasm/wasm.mk +++ b/src/mono/sample/wasm/wasm.mk @@ -23,7 +23,7 @@ run-browser: echo "The tool dotnet-serve could not be found. Install with: $(DOTNET) tool install --global dotnet-serve"; \ exit 1; \ else \ - $(DOTNET) serve -d bin/$(CONFIG)/AppBundle -p 8000; \ + $(DOTNET) serve -d=bin/$(CONFIG)/AppBundle -p 8000; \ fi run-console: diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 74aa1083c033d1..4a10be1e9220d1 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -4,29 +4,31 @@ // //glue code to deal with the differences between chrome, ch, d8, jsc and sm. -var is_browser = typeof window != "undefined"; +const is_browser = typeof window != "undefined"; +const is_node = !is_browser && typeof process != 'undefined'; // if the engine doesn't provide a console if (typeof (console) === "undefined") { - var console = { + console = { log: globalThis.print, clear: function () { } }; } + globalThis.testConsole = console; -function proxyMethod (prefix, func, asJson) { +function proxyMethod (prefix, proxyFunc, asJson) { return function() { var args = [...arguments]; if (asJson) { - func (JSON.stringify({ + proxyFunc (JSON.stringify({ method: prefix, payload: args[0], arguments: args })); } else { - func([prefix + args[0], ...args.slice(1)]); + proxyFunc([prefix + args[0], ...args.slice(1)]); } }; }; @@ -38,9 +40,9 @@ for (var m of methods) { } } -function proxyJson (func) { +function proxyJson (consoleFunc) { for (var m of ["log", ...methods]) - console[m] = proxyMethod(`console.${m}`,func, true); + console[m] = proxyMethod(`console.${m}`, consolefunc, true); } if (is_browser) { @@ -49,7 +51,7 @@ if (is_browser) { let consoleWebSocket = new WebSocket(consoleUrl); consoleWebSocket.onopen = function(event) { proxyJson(function (msg) { consoleWebSocket.send (msg); }); - globalThis.testConsole.log("browser: Console websocket connected."); + testConsole.log("browser: Console websocket connected."); }; consoleWebSocket.onerror = function(event) { console.log(`websocket error: ${event}`); @@ -64,6 +66,18 @@ if (is_browser) { } } } + +if (is_node) { + arguments = process.argv.slice (2); + var fs = require ('fs'); + function load (file) { + eval (fs.readFileSync(file).toString()); + }; + function read (path) { + return fs.readFileSync(path); + }; + const { performance, PerformanceObserver } = require("perf_hooks") +} //proxyJson(console.log); @@ -91,22 +105,20 @@ if (typeof performance == 'undefined') { } } -try { - if (typeof arguments == "undefined") - arguments = WScript.Arguments; - load = WScript.LoadScriptFile; - read = WScript.LoadBinaryFile; -} catch (e) { -} - try { if (typeof arguments == "undefined") { - if (typeof scriptArgs !== "undefined") + if (typeof (WScript) != "undefined") { + arguments = WScript.Arguments; + load = WScript.LoadScriptFile; + read = WScript.LoadBinaryFile; + } else if (typeof (scriptArgs) != "undefined") { arguments = scriptArgs; + } } } catch (e) { } + if (arguments === undefined) arguments = []; @@ -119,7 +131,7 @@ function test_exit (exit_code) { if (is_browser) { // Notify the selenium script Module.exit_code = exit_code; - Module.print ("WASM EXIT " + exit_code); + console.log ("WASM EXIT " + exit_code); var tests_done_elem = document.createElement ("label"); tests_done_elem.id = "tests_done"; tests_done_elem.innerHTML = exit_code.toString (); @@ -130,7 +142,7 @@ function test_exit (exit_code) { } function fail_exec (reason) { - Module.print (reason); + console.log (reason); test_exit (1); } @@ -144,8 +156,8 @@ function inspect_object (o) { } // Preprocess arguments -var args = testArguments; -console.info("Arguments: " + testArguments); +var args = [...testArguments]; +//console.info("Arguments: " + testArguments); profilers = []; setenv = {}; runtime_args = []; @@ -153,28 +165,29 @@ enable_gc = true; enable_zoneinfo = false; working_dir='/'; while (args !== undefined && args.length > 0) { - if (args [0].startsWith ("--profile=")) { - var arg = args [0].substring ("--profile=".length); + let currentArg = args [0].toString(); + if (currentArg.startsWith ("--profile=")) { + var arg = currentArg.substring ("--profile=".length); profilers.push (arg); args = args.slice (1); - } else if (args [0].startsWith ("--setenv=")) { - var arg = args [0].substring ("--setenv=".length); + } else if (currentArg.startsWith ("--setenv=")) { + var arg = currentArg.substring ("--setenv=".length); var parts = arg.split ('='); if (parts.length != 2) - fail_exec ("Error: malformed argument: '" + args [0]); + fail_exec ("Error: malformed argument: '" + currentArg); setenv [parts [0]] = parts [1]; args = args.slice (1); - } else if (args [0].startsWith ("--runtime-arg=")) { - var arg = args [0].substring ("--runtime-arg=".length); + } else if (currentArg.startsWith ("--runtime-arg=")) { + var arg = currentArg.substring ("--runtime-arg=".length); runtime_args.push (arg); args = args.slice (1); - } else if (args [0] == "--disable-on-demand-gc") { + } else if (currentArg == "--disable-on-demand-gc") { enable_gc = false; args = args.slice (1); - } else if (args [0].startsWith ("--working-dir=")) { - var arg = args [0].substring ("--working-dir=".length); + } else if (currentArg.startsWith ("--working-dir=")) { + var arg = currentArg.substring ("--working-dir=".length); working_dir = arg; args = args.slice (1); } else { @@ -186,44 +199,46 @@ testArguments = args; // cheap way to let the testing infrastructure know we're running in a browser context (or not) setenv["IsBrowserDomSupported"] = is_browser.toString().toLowerCase(); -function writeContentToFile(content, path) -{ +function writeContentToFile(content, path) { var stream = FS.open(path, 'w+'); FS.write(stream, content, 0, content.length, 0); FS.close(stream); } -function loadScript (url) -{ +function loadScript (url){ if (is_browser) { var script = document.createElement ("script"); script.src = url; document.head.appendChild (script); + } else if (is_node) { + return read (url).toString(); } else { load (url); } + return ""; } -loadScript ("mono-config.js"); - +eval (loadScript ("mono-config.js")); var Module = { mainScriptUrlOrBlob: "dotnet.js", - - print, - printErr, - + config, + setenv, + read, + arguments, onAbort: function(x) { - print ("ABORT: " + x); + console.log ("ABORT: " + x); var err = new Error(); - print ("Stacktrace: \n"); - print (err.stack); + console.log ("Stacktrace: \n"); + console.log (err.stack); test_exit (1); }, onRuntimeInitialized: function () { + try { + // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. for (var variable in setenv) { - MONO.mono_wasm_setenv (variable, setenv [variable]); + Module._mono_wasm_setenv (variable, setenv [variable]); } if (!enable_gc) { @@ -241,7 +256,7 @@ var Module = { App.init (); }; config.fetch_file_cb = function (asset) { - // console.log("fetch_file_cb('" + asset + "')"); + //console.log("fetch_file_cb('" + asset + "')"); // for testing purposes add BCL assets to VFS until we special case File.Open // to identify when an assembly from the BCL is being open and resolve it correctly. /* @@ -261,30 +276,29 @@ var Module = { return new Promise ((resolve, reject) => { var bytes = null, error = null; try { - bytes = read (asset, 'binary'); + bytes = Module.read (asset, 'binary'); } catch (exc) { - error = exc; + reject (exc); } - var response = { ok: (bytes && !error), url: asset, - arrayBuffer: function () { - return new Promise ((resolve2, reject2) => { - if (error) - reject2 (error); - else - resolve2 (new Uint8Array (bytes)); - } - )} - } - resolve (response); - }) + resolve ({ + ok: (bytes && !error), + url: asset, + arrayBuffer: () => Promise.resolve (new Uint8Array (bytes)) + }); + }); } }; - MONO.mono_load_runtime_and_bcl_args (config); + Module.mono_load_runtime_and_bcl_args (config); + } catch (e) { + console.log (e); + } }, }; -loadScript ("dotnet.js"); +eval (loadScript ("dotnet.js")); +//var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); +//globalThis.Module = Module; const IGNORE_PARAM_COUNT = -1; @@ -314,10 +328,10 @@ var App = { var res = 0; try { res = exec_regression (10, args[1]); - Module.print ("REGRESSION RESULT: " + res); + console.log ("REGRESSION RESULT: " + res); } catch (e) { - Module.print ("ABORT: " + e); - print (e.stack); + console.log ("ABORT: " + e); + console.log (e.stack); res = 1; } @@ -352,9 +366,7 @@ var App = { wasm_set_main_args (main_argc, main_argv); // Automatic signature isn't working correctly - let result = Module.mono_call_assembly_entry_point (main_assembly_name, [app_args], "m"); - let onError = function (error) - { + let onError = function (error) { console.error (error); if (error.stack) console.error (error.stack); @@ -362,13 +374,15 @@ var App = { test_exit (1); } try { - result.then (test_exit).catch (onError); + Module.mono_call_assembly_entry_point (main_assembly_name, [app_args], "m") + .then (test_exit) + .catch (onError); } catch (error) { onError(error); } } else { - fail_exec ("Unhandled argument: " + args [0]); + fail_exec ("Unhandled argument: " + args[0]); } }, call_test_method: function (method_name, args, signature) { diff --git a/src/mono/wasm/runtime/binding_support.js b/src/mono/wasm/runtime/binding_support.js index 3938dc83041b64..a9fe4fbc8d6ca2 100644 --- a/src/mono/wasm/runtime/binding_support.js +++ b/src/mono/wasm/runtime/binding_support.js @@ -1016,7 +1016,7 @@ var BindingSupportLib = { // ensure the indirect values are 8-byte aligned so that aligned loads and stores will work var indirectBaseOffset = ((((args_marshal.length * 4) + 7) / 8) | 0) * 8; - var closure = {}; + var closure = { Module }; var indirectLocalOffset = 0; body.push ( @@ -1349,6 +1349,7 @@ var BindingSupportLib = { library_mono: MONO, binding_support: this, method: method, + Module: Module, this_arg: this_arg }; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 685aaaf375d85e..5a8bf50e988753 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -1759,9 +1759,9 @@ var MonoSupportLib = { try { load_runtime ("unused", args.debug_level); } catch (ex) { - print ("MONO_WASM: load_runtime () failed: " + ex); - print ("MONO_WASM: Stacktrace: \n"); - print (ex.stack); + Module.print ("MONO_WASM: load_runtime () failed: " + ex); + Module.print ("MONO_WASM: Stacktrace: \n"); + Module.print (ex.stack); var wasm_exit = Module.cwrap ('mono_wasm_exit', null, ['number']); wasm_exit (1); @@ -2454,6 +2454,8 @@ var MonoSupportLib = { ++MONO.pump_count; if (typeof globalThis.setTimeout === 'function') { globalThis.setTimeout (MONO.pump_message, 0); + } else { + Promise.resolve().then (MONO.pump_message); } }, @@ -2461,15 +2463,12 @@ var MonoSupportLib = { if (!this.mono_set_timeout_exec) this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", null, [ 'number' ]); + var timer = function () { this.mono_set_timeout_exec (id) }.bind (this); if (typeof globalThis.setTimeout === 'function') { - globalThis.setTimeout (function () { - this.mono_set_timeout_exec (id); - }, timeout); + globalThis.setTimeout (timer, timeout); } else { ++MONO.pump_count; - MONO.timeout_queue.push(function() { - this.mono_set_timeout_exec (id); - }) + MONO.timeout_queue.push(timer); } }, From ed4f9be7b9bba5e3e8e5d877ed32ccd0e38d3820 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Wed, 14 Apr 2021 19:23:53 -0500 Subject: [PATCH 002/115] checkpoint --- src/mono/wasm/runtime-test.js | 16 +++++++++++----- src/mono/wasm/runtime/library_mono.js | 8 ++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 4a10be1e9220d1..f91b8fe59ab6d9 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -210,15 +210,17 @@ function loadScript (url){ var script = document.createElement ("script"); script.src = url; document.head.appendChild (script); - } else if (is_node) { - return read (url).toString(); } else { load (url); } - return ""; } -eval (loadScript ("mono-config.js")); +if (is_node) { + eval (read ("mono-config.js").toString()); +} else { + loadScript("mono-config.js"); +} + var Module = { mainScriptUrlOrBlob: "dotnet.js", config, @@ -296,7 +298,11 @@ var Module = { }, }; -eval (loadScript ("dotnet.js")); +if (is_node) { + eval (read ("dotnet.js").toString()); +} else { + loadScript ("dotnet.js"); +} //var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); //globalThis.Module = Module; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 5a8bf50e988753..60de7ff8aa54f9 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -64,7 +64,7 @@ var MonoSupportLib = { this.mono_background_exec = Module.cwrap ("mono_background_exec", null); while (MONO.timeout_queue.length > 0) { --MONO.pump_count; - MONO.timeout_queue.shift()(); + Promise.resolve().then(MONO.timeout_queue.shift()()); } while (MONO.pump_count > 0) { --MONO.pump_count; @@ -2452,11 +2452,7 @@ var MonoSupportLib = { schedule_background_exec: function () { ++MONO.pump_count; - if (typeof globalThis.setTimeout === 'function') { - globalThis.setTimeout (MONO.pump_message, 0); - } else { - Promise.resolve().then (MONO.pump_message); - } + Promise.resolve().then (MONO.pump_message); }, mono_set_timeout: function (timeout, id) { From 5177380e13371730b60dc6a91249edd166009633 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 10:00:16 -0400 Subject: [PATCH 003/115] converted mono-config.js to mono-config.json --- .../Directory.Build.props | 1 + src/mono/sample/mbr/browser/index.html | 1 - src/mono/sample/mbr/browser/runtime.js | 4 +++ src/mono/sample/wasm/browser-bench/index.html | 1 - src/mono/sample/wasm/browser-bench/runtime.js | 15 +++++++-- .../sample/wasm/browser-profile/index.html | 1 - .../sample/wasm/browser-profile/runtime.js | 8 +++-- src/mono/sample/wasm/browser/index.html | 1 - src/mono/sample/wasm/browser/runtime.js | 6 +++- src/mono/wasm/Makefile | 6 ++-- src/mono/wasm/build/WasmApp.targets | 2 +- .../tests/debugger-test/debugger-driver.html | 1 - .../tests/debugger-test/runtime-debugger.js | 12 ++++--- src/mono/wasm/runtime-test.js | 6 +--- src/mono/wasm/runtime/js_support.js | 32 +++++++++++++++++++ src/mono/wasm/wasm.proj | 2 +- src/tasks/WasmAppBuilder/WasmAppBuilder.cs | 6 ++-- .../Wasm.Build.Tests/BuildTestBase.cs | 2 +- .../WebAssembly/Browser/AOT/index.html | 1 - .../WebAssembly/Browser/AOT/runtime.js | 6 +++- .../Browser/NormalInterp/index.html | 1 - .../Browser/NormalInterp/runtime.js | 4 +++ 22 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 src/mono/wasm/runtime/js_support.js diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index ac2d3cc1a02246..a360fc5d5e5021 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -219,6 +219,7 @@ + diff --git a/src/mono/sample/mbr/browser/index.html b/src/mono/sample/mbr/browser/index.html index 472cf5f29ea053..eb19b7bb2f5954 100644 --- a/src/mono/sample/mbr/browser/index.html +++ b/src/mono/sample/mbr/browser/index.html @@ -29,7 +29,6 @@ }, }; - diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index 0856b8d0e03033..a0179a97ae5a78 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/sample/wasm/browser-bench/index.html b/src/mono/sample/wasm/browser-bench/index.html index eebbae65eb1052..658bfb573ddbfc 100644 --- a/src/mono/sample/wasm/browser-bench/index.html +++ b/src/mono/sample/wasm/browser-bench/index.html @@ -51,7 +51,6 @@ } }; - diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index a39b0b97b14901..39ebf6c0c276b6 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -1,8 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -15,6 +18,14 @@ var Module = { return fetch (asset, { credentials: 'same-origin' }); } + if (config.enable_profiler) + { + config.aot_profiler_options = { + write_at:"Sample.Test::StopProfile", + send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" + } + } + try { MONO.mono_load_runtime_and_bcl_args (config); @@ -23,4 +34,4 @@ var Module = { throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/mono/sample/wasm/browser-profile/index.html b/src/mono/sample/wasm/browser-profile/index.html index 50eb0ff28c2efe..286aa812e869d7 100644 --- a/src/mono/sample/wasm/browser-profile/index.html +++ b/src/mono/sample/wasm/browser-profile/index.html @@ -68,7 +68,6 @@ } - diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 1ce1c0b736034c..39ebf6c0c276b6 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -1,7 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -var Module = { +var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -29,5 +33,5 @@ var Module = { test_exit(1); throw(error); } - } + }, }; \ No newline at end of file diff --git a/src/mono/sample/wasm/browser/index.html b/src/mono/sample/wasm/browser/index.html index bd8e5015a0ee5f..5f170bb38e7bcb 100644 --- a/src/mono/sample/wasm/browser/index.html +++ b/src/mono/sample/wasm/browser/index.html @@ -48,7 +48,6 @@ }, }; - diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index a39b0b97b14901..5588740f8efe99 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -23,4 +27,4 @@ var Module = { throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index abb93b97f40685..b3442e44b63e18 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -101,8 +101,8 @@ $(NATIVE_BIN_DIR)/include/wasm: $(BUILDS_OBJ_DIR): mkdir -p $$@ -$(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) +$(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js runtime/js_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) + $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --post-js runtime/js_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi @@ -141,7 +141,7 @@ clean: icu-files: $(wildcard $(ICU_LIBDIR)/*.dat) $(ICU_LIBDIR)/libicuuc.a $(ICU_LIBDIR)/libicui18n.a | $(NATIVE_BIN_DIR) cp $^ $(NATIVE_BIN_DIR) -source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js | $(NATIVE_BIN_DIR)/src +source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js runtime/js_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js | $(NATIVE_BIN_DIR)/src cp $^ $(NATIVE_BIN_DIR)/src header-files: runtime/pinvoke.h | $(NATIVE_BIN_DIR)/include/wasm diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 0467636bd6c729..a2adbf6076526f 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -67,7 +67,7 @@ - @(WasmFilesToIncludeInFileSystem) - Files to include in the vfs - @(WasmNativeAsset) - Native files to be added to `NativeAssets` in the bundle. - - @(WasmExtraConfig) - json elements to add to `mono-config.js` + - @(WasmExtraConfig) - json elements to add to `mono-config.json` Eg. - Value attribute can have a number, bool, quoted string, or json string diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html index 87ba804792ef39..b1bfcd859d0644 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html @@ -83,7 +83,6 @@ return App.int_add (a, b); } - diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index 4c641eb2c6a0d7..6d3a83dfaaa24a 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -2,8 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - config.loaded_cb = function () { + onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { + config.loaded_cb = function () { App.init (); }; // For custom logging patch the functions below @@ -16,5 +20,5 @@ var Module = { MONO.mono_wasm_setenv ("MONO_LOG_MASK", "all"); */ MONO.mono_load_runtime_and_bcl_args (config) - }, -}; + }, +}; \ No newline at end of file diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index f91b8fe59ab6d9..f6169347b449fd 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -215,11 +215,7 @@ function loadScript (url){ } } -if (is_node) { - eval (read ("mono-config.js").toString()); -} else { - loadScript("mono-config.js"); -} +JSSupportLib.load_config(); var Module = { mainScriptUrlOrBlob: "dotnet.js", diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js new file mode 100644 index 00000000000000..ffde2df6c5d017 --- /dev/null +++ b/src/mono/wasm/runtime/js_support.js @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var JSSupportLib = { + // $JS__postset: 'JS.export_functions (Module);', + // $JS: { + load_config: function (callback) { + if (ENVIRONMENT_IS_NODE){ + const config = require('./mono-config.json'); + callback(config); + } + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function () { + if (xobj.readyState == 4 && xobj.status == "200") { + const config = JSON.parse(xobj.responseText); + callback(config); + } + }; + xobj.send(); + }, + + // export_functions: function (module) { + // module ["load_config"] = JS.load_config.bind(JS); + + // } + // }, +} + +// autoAddDeps(JSSupportLib, '$JS') +// mergeInto(LibraryManager.library, JSSupportLib) // TODO FOR SOME REASON THE LOAD_CONFIG FUNCTION IS NOT BEING ADDED TO DOTNET.JS. THIS IS NEEDED SO THAT I CAN CALL LOAD_CONFIG() IN THE SAMPLES diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 86da385e608e5e..d397b3808e5602 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -153,7 +153,7 @@ EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" /> - diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index 9ef7679c292b66..aedcb5dd36bb5d 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -51,7 +51,7 @@ public class WasmAppBuilder : Task public ITaskItem[]? ExtraFilesToDeploy { get; set; } // - // Extra json elements to add to mono-config.js + // Extra json elements to add to mono-config.json // // Metadata: // - Value: can be a number, bool, quoted string, or json string @@ -246,11 +246,11 @@ public override bool Execute () config.Extra[name] = valueObject; } - string monoConfigPath = Path.Combine(AppDir, "mono-config.js"); + string monoConfigPath = Path.Combine(AppDir, "mono-config.json"); using (var sw = File.CreateText(monoConfigPath)) { var json = JsonSerializer.Serialize (config, new JsonSerializerOptions { WriteIndented = true }); - sw.Write($"config = {json};"); + sw.Write($"{json}"); } _fileWrites.Add(monoConfigPath); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index b5f1f7e0b95f73..99e721dfa65f78 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -347,7 +347,7 @@ protected static void AssertBasicAppBundle(string bundleDir, string projectName, "runtime.js", "dotnet.timezones.blat", "dotnet.wasm", - "mono-config.js", + "mono-config.json", "dotnet.js", "run-v8.sh" }); diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html index efab9ac4324a21..642987d23c5e2b 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html @@ -47,7 +47,6 @@ }, }; - diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js index a39b0b97b14901..5588740f8efe99 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -23,4 +27,4 @@ var Module = { throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html index 03f68679a5b85c..9de05f5031b325 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html @@ -47,7 +47,6 @@ }, }; - diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js index a39b0b97b14901..f15dfa7274d999 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); From 5b24b9711a0733a49c7a991ce1a50ce947cfd097 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 12:43:15 -0400 Subject: [PATCH 004/115] Fixed tests as config is loaded async now --- .../sample/wasm/browser-profile/index.html | 58 ----------------- .../sample/wasm/browser-profile/runtime.js | 63 +++++++++++++++++-- src/mono/wasm/runtime/js_support.js | 43 ++++++------- 3 files changed, 77 insertions(+), 87 deletions(-) diff --git a/src/mono/sample/wasm/browser-profile/index.html b/src/mono/sample/wasm/browser-profile/index.html index 286aa812e869d7..de4a5599e94ad0 100644 --- a/src/mono/sample/wasm/browser-profile/index.html +++ b/src/mono/sample/wasm/browser-profile/index.html @@ -10,66 +10,8 @@ Result from Sample.Test.TestMeaning: - - diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 39ebf6c0c276b6..96572c69592d9e 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -1,16 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. var Module = { + is_testing: false, + onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(Module.setupConfig); }, setupConfig: function (config) { config.loaded_cb = function () { try { - App.init (); + Module.init(); } catch (error) { - test_exit(1); + Module.test_exit(1); throw (error); } }; @@ -30,8 +32,61 @@ var Module = { { MONO.mono_load_runtime_and_bcl_args (config); } catch (error) { - test_exit(1); + Module.test_exit(1); throw(error); } }, + + init: function () { + console.log("not ready yet") + var ret = BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:TestMeaning", []); + document.getElementById("out").innerHTML = ret; + console.log ("ready"); + + if (Module.is_testing) + { + console.debug(`ret: ${ret}`); + let exit_code = ret == 42 ? 0 : 1; + Module.test_exit(exit_code); + } + + if (config.enable_profiler) { + BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []); + Module.saveProfile(); + } + }, + + onLoad: function() { + var url = new URL(decodeURI(window.location)); + let args = url.searchParams.getAll('arg'); + is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); + }, + + test_exit: function(exit_code) { + if (!Module.is_testing) { + console.log(`test_exit: ${exit_code}`); + return; + } + + /* Set result in a tests_done element, to be read by xharness */ + var tests_done_elem = document.createElement("label"); + tests_done_elem.id = "tests_done"; + tests_done_elem.innerHTML = exit_code.toString(); + document.body.appendChild(tests_done_elem); + + console.log(`WASM EXIT ${exit_code}`); + }, + + saveProfile: function () { + var a = document.createElement('a'); + var blob = new Blob([Module.aot_profile_data]); + a.href = URL.createObjectURL(blob); + a.download = "data.aotprofile"; + // Append anchor to body. + document.body.appendChild(a); + a.click(); + + // Remove anchor from body + document.body.removeChild(a); + } }; \ No newline at end of file diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index ffde2df6c5d017..e4ef25c30ad125 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -1,32 +1,25 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +// THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMZIED +// IT I MEANT AS A SET OF JS TOOLS TO SUPPORT THE SDK + var JSSupportLib = { - // $JS__postset: 'JS.export_functions (Module);', - // $JS: { - load_config: function (callback) { - if (ENVIRONMENT_IS_NODE){ - const config = require('./mono-config.json'); + // Loads the config file located in the root of the project + load_config: function (callback) { + if (ENVIRONMENT_IS_NODE){ + const config = require('./mono-config.json'); + callback(config); + } + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function () { + if (xobj.readyState == 4 && xobj.status == "200") { + const config = JSON.parse(xobj.responseText); callback(config); } - var xobj = new XMLHttpRequest(); - xobj.overrideMimeType("application/json"); - xobj.open('GET', './mono-config.json', true); - xobj.onreadystatechange = function () { - if (xobj.readyState == 4 && xobj.status == "200") { - const config = JSON.parse(xobj.responseText); - callback(config); - } - }; - xobj.send(); - }, - - // export_functions: function (module) { - // module ["load_config"] = JS.load_config.bind(JS); - - // } - // }, + }; + xobj.send(); + }, } - -// autoAddDeps(JSSupportLib, '$JS') -// mergeInto(LibraryManager.library, JSSupportLib) // TODO FOR SOME REASON THE LOAD_CONFIG FUNCTION IS NOT BEING ADDED TO DOTNET.JS. THIS IS NEEDED SO THAT I CAN CALL LOAD_CONFIG() IN THE SAMPLES From 03856e1c5a6ec592908b1a07b339095678b1be9f Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 15:55:08 -0400 Subject: [PATCH 005/115] added line to end of file + more comments --- src/mono/sample/wasm/browser/runtime.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 5588740f8efe99..0c996cac3de58a 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -2,10 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { + // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { JSSupportLib.load_config(this.setupConfig); }, + // Called once the config file is loaded. THe contents of the config file + // are passed as a JS object within the config parameter setupConfig: function (config) { config.loaded_cb = function () { try { @@ -27,4 +30,4 @@ var Module = { throw(error); } }, -}; \ No newline at end of file +}; From b2b93b8801e3a83ac43929624050e797cb24c27b Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 16:01:46 -0400 Subject: [PATCH 006/115] added space that was accidentally removed --- src/mono/wasm/wasm.proj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index ba045d435948c6..3e0df2db216cc3 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -152,6 +152,7 @@ + From 77d39dbfd08986c5d7d2ff542520a828e180a047 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 17:08:10 -0400 Subject: [PATCH 007/115] Addressed some PR comments --- src/mono/sample/mbr/browser/runtime.js | 4 ++-- src/mono/sample/wasm/browser-bench/runtime.js | 4 ++-- src/mono/sample/wasm/browser-profile/runtime.js | 4 ++-- src/mono/sample/wasm/browser/runtime.js | 4 ++-- .../tests/debugger-test/runtime-debugger.js | 14 +++++++------- src/mono/wasm/runtime/js_support.js | 10 +++++++--- src/mono/wasm/wasm.proj | 2 +- .../WebAssembly/Browser/AOT/runtime.js | 6 +++--- .../WebAssembly/Browser/NormalInterp/runtime.js | 4 ++-- 9 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index a0179a97ae5a78..1f311ca4811aff 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -3,10 +3,10 @@ var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index 39ebf6c0c276b6..5ecacd345993f4 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 96572c69592d9e..df506c9f651a98 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -4,10 +4,10 @@ var Module = { is_testing: false, onRuntimeInitialized: function () { - JSSupportLib.load_config(Module.setupConfig); + JSSupportLib.load_config(Module.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { Module.init(); diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 0c996cac3de58a..9d74612aef2238 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -4,12 +4,12 @@ var Module = { // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, // Called once the config file is loaded. THe contents of the config file // are passed as a JS object within the config parameter - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index 6d3a83dfaaa24a..a8baa920f78bfd 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -2,12 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); - }, + onRuntimeInitialized: function () { + JSSupportLib.load_config(this.onConfigLoaded); + }, - setupConfig: function (config) { - config.loaded_cb = function () { + onConfigLoaded: function (config) { + config.loaded_cb = function () { App.init (); }; // For custom logging patch the functions below @@ -20,5 +20,5 @@ var Module = { MONO.mono_wasm_setenv ("MONO_LOG_MASK", "all"); */ MONO.mono_load_runtime_and_bcl_args (config) - }, -}; \ No newline at end of file + }, +}; diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index e4ef25c30ad125..032c0eaef193c4 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMZIED +// THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMIZED // IT I MEANT AS A SET OF JS TOOLS TO SUPPORT THE SDK var JSSupportLib = { @@ -9,7 +9,9 @@ var JSSupportLib = { load_config: function (callback) { if (ENVIRONMENT_IS_NODE){ const config = require('./mono-config.json'); - callback(config); + if (callback){ + callback(config); + } } var xobj = new XMLHttpRequest(); xobj.overrideMimeType("application/json"); @@ -17,7 +19,9 @@ var JSSupportLib = { xobj.onreadystatechange = function () { if (xobj.readyState == 4 && xobj.status == "200") { const config = JSON.parse(xobj.responseText); - callback(config); + if (callback){ + callback(config); + } } }; xobj.send(); diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 3e0df2db216cc3..3bb7a55cfa8e2e 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -152,7 +152,7 @@ - + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js index 5588740f8efe99..6488f420c27c3d 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js @@ -3,10 +3,10 @@ var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); @@ -27,4 +27,4 @@ var Module = { throw(error); } }, -}; \ No newline at end of file +}; diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js index f15dfa7274d999..6488f420c27c3d 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js @@ -3,10 +3,10 @@ var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); From a2f48fb79eb4eed4f4bd49871998a30b39e319c2 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 19:26:38 -0400 Subject: [PATCH 008/115] Addressed a few more PR comments --- src/mono/sample/mbr/browser/runtime.js | 5 +++ src/mono/sample/wasm/browser-bench/runtime.js | 5 +++ .../sample/wasm/browser-profile/runtime.js | 5 +++ src/mono/sample/wasm/browser/runtime.js | 5 +++ .../tests/debugger-test/runtime-debugger.js | 5 +++ src/mono/wasm/runtime/js_support.js | 40 ++++++++++++++----- .../WebAssembly/Browser/AOT/runtime.js | 5 +++ .../Browser/NormalInterp/runtime.js | 5 +++ 8 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index 1f311ca4811aff..b26dcce86e1c2e 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index 5ecacd345993f4..ea10bc2b822cd3 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -6,6 +6,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index df506c9f651a98..553d7ce2800ef8 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -8,6 +8,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { Module.init(); diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 9d74612aef2238..5e13da47258a27 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -10,6 +10,11 @@ var Module = { // Called once the config file is loaded. THe contents of the config file // are passed as a JS object within the config parameter onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index a8baa920f78bfd..a74836490c6379 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index 032c0eaef193c4..099c57ec3e6162 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -12,18 +12,36 @@ var JSSupportLib = { if (callback){ callback(config); } - } - var xobj = new XMLHttpRequest(); - xobj.overrideMimeType("application/json"); - xobj.open('GET', './mono-config.json', true); - xobj.onreadystatechange = function () { - if (xobj.readyState == 4 && xobj.status == "200") { - const config = JSON.parse(xobj.responseText); - if (callback){ - callback(config); + } else { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function() { + if (callback && xobj.readyState == XMLHttpRequest.DONE) { + if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { + const config = JSON.parse(xobj.responseText); + callback(config); + } else { + // error if the request to load the file was successful but loading failed + callback({error: "Error loading mono-config.json file from current directory"}); + } + } + }; + xobj.onerror = function() { + // error if the request failed + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); + } + } + + try { + xobj.send() + } catch(e) { + // other kinds of errors + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); } } - }; - xobj.send(); + } }, } diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js index 6488f420c27c3d..d60354b01d042a 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js index 6488f420c27c3d..d60354b01d042a 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); From 7fe322f614d49c6a0149dc5e7b79f1de78f06f80 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Wed, 26 May 2021 18:20:13 -0400 Subject: [PATCH 009/115] changed post-js to pre-js --- src/mono/sample/wasm/browser/runtime.js | 28 ++++++---- src/mono/wasm/Makefile | 2 +- src/mono/wasm/runtime/js_support.js | 70 +++++++++++++------------ src/mono/wasm/wasm.proj | 2 +- 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 5e13da47258a27..9bfacdfbd6d460 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -2,20 +2,28 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - // Called when the runtime is initialized and wasm is ready - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, - // Called once the config file is loaded. THe contents of the config file + config: null, + + // Called once the config file is loaded. The contents of the config file // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ - alert("An error occured while loading the config file"); + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ + alert("No config found"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { try { App.init (); } catch (error) { @@ -23,16 +31,16 @@ var Module = { throw (error); } }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } try { - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); } catch (error) { test_exit(1); throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index b3442e44b63e18..699630e0850e55 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -102,7 +102,7 @@ $(BUILDS_OBJ_DIR): mkdir -p $$@ $(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js runtime/js_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --post-js runtime/js_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) + $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --pre-js runtime/js_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index 099c57ec3e6162..9fecab85a2ca1e 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -4,44 +4,46 @@ // THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMIZED // IT I MEANT AS A SET OF JS TOOLS TO SUPPORT THE SDK -var JSSupportLib = { - // Loads the config file located in the root of the project - load_config: function (callback) { - if (ENVIRONMENT_IS_NODE){ - const config = require('./mono-config.json'); - if (callback){ - callback(config); - } - } else { - var xobj = new XMLHttpRequest(); - xobj.overrideMimeType("application/json"); - xobj.open('GET', './mono-config.json', true); - xobj.onreadystatechange = function() { - if (callback && xobj.readyState == XMLHttpRequest.DONE) { - if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { - const config = JSON.parse(xobj.responseText); - callback(config); - } else { - // error if the request to load the file was successful but loading failed - callback({error: "Error loading mono-config.json file from current directory"}); - } - } - }; - xobj.onerror = function() { - // error if the request failed - if (callback){ +// Loads the config file located in the root of the project +// Not meant to be used outside of this class (TODO make private to this file when project converted to TS) +function load_config() { + callback = Module['onConfigLoaded'] + + if (ENVIRONMENT_IS_NODE){ + const config = require('./mono-config.json'); + if (callback){ + callback(config); + } + } else { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function() { + if (callback && xobj.readyState == XMLHttpRequest.DONE) { + if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { + const config = JSON.parse(xobj.responseText); + callback(config); + } else { + // error if the request to load the file was successful but loading failed callback({error: "Error loading mono-config.json file from current directory"}); } } + }; + xobj.onerror = function() { + // error if the request failed + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); + } + } - try { - xobj.send() - } catch(e) { - // other kinds of errors - if (callback){ - callback({error: "Error loading mono-config.json file from current directory"}); - } + try { + xobj.send() + } catch(e) { + // other kinds of errors + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); } } - }, + } } +load_config() \ No newline at end of file diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 3bb7a55cfa8e2e..2d0006bfe14eb1 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -153,7 +153,7 @@ EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" /> - From 8438e67fdd1125e0f7f1627f78a8b4765aa7ff9f Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Wed, 26 May 2021 18:37:46 -0400 Subject: [PATCH 010/115] Fixed samples --- src/mono/sample/mbr/browser/runtime.js | 24 ++++++++++---- src/mono/sample/wasm/browser-bench/runtime.js | 28 +++++++++++----- .../sample/wasm/browser-profile/runtime.js | 33 ++++++++++++------- .../tests/debugger-test/runtime-debugger.js | 24 ++++++++++---- 4 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index b26dcce86e1c2e..3a63c214f2ff65 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -2,26 +2,36 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, + config: null, + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ alert("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { App.init (); }; - config.environment_variables = { + Module.config.environment_variables = { "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); }, }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index ea10bc2b822cd3..cbebc617ba82d7 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -1,17 +1,27 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, + config: null, + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ alert("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { try { App.init (); } catch (error) { @@ -19,13 +29,13 @@ var Module = { throw (error); } }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } - if (config.enable_profiler) + if (Module.config.enable_profiler) { - config.aot_profiler_options = { + Module.config.aot_profiler_options = { write_at:"Sample.Test::StopProfile", send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" } @@ -33,10 +43,10 @@ var Module = { try { - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); } catch (error) { test_exit(1); throw(error); } }, -}; \ No newline at end of file +}; diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 553d7ce2800ef8..e385167eaec223 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -2,18 +2,27 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { is_testing: false, + config: null, - onRuntimeInitialized: function () { - JSSupportLib.load_config(Module.onConfigLoaded); - }, - + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ alert("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { try { Module.init(); } catch (error) { @@ -21,13 +30,13 @@ var Module = { throw (error); } }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } - if (config.enable_profiler) + if (Module.config.enable_profiler) { - config.aot_profiler_options = { + Module.config.aot_profiler_options = { write_at:"Sample.Test::StopProfile", send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" } @@ -35,7 +44,7 @@ var Module = { try { - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); } catch (error) { Module.test_exit(1); throw(error); @@ -55,7 +64,7 @@ var Module = { Module.test_exit(exit_code); } - if (config.enable_profiler) { + if (Module.config.enable_profiler) { BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []); Module.saveProfile(); } @@ -64,7 +73,7 @@ var Module = { onLoad: function() { var url = new URL(decodeURI(window.location)); let args = url.searchParams.getAll('arg'); - is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); + Module.is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); }, test_exit: function(exit_code) { @@ -94,4 +103,4 @@ var Module = { // Remove anchor from body document.body.removeChild(a); } -}; \ No newline at end of file +}; diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index a74836490c6379..da8da61bd92fd3 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -2,17 +2,27 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, + config: null, + + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter + onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, - onConfigLoaded: function (config) { - if (!config || config.error){ + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ console.log("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { App.init (); }; // For custom logging patch the functions below @@ -24,6 +34,6 @@ var Module = { MONO.mono_wasm_setenv ("MONO_LOG_LEVEL", "debug"); MONO.mono_wasm_setenv ("MONO_LOG_MASK", "all"); */ - MONO.mono_load_runtime_and_bcl_args (config) + MONO.mono_load_runtime_and_bcl_args (Module.config) }, }; From 261c1336f35f0387d42f7782e3827bda4743b4b2 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Thu, 27 May 2021 11:39:34 -0400 Subject: [PATCH 011/115] Fixed console sample --- src/mono/sample/wasm/browser/runtime.js | 2 +- src/mono/wasm/runtime-test.js | 36 ++++++++++++++--------- src/mono/wasm/runtime/js_support.js | 39 ++++++++++++++++--------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 9bfacdfbd6d460..0a99c174a01f62 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -43,4 +43,4 @@ var Module = { throw(error); } }, -}; \ No newline at end of file +}; diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index f6169347b449fd..03676e969241e8 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -215,11 +215,12 @@ function loadScript (url){ } } -JSSupportLib.load_config(); +//var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); +//globalThis.Module = Module; var Module = { mainScriptUrlOrBlob: "dotnet.js", - config, + config: null, setenv, read, arguments, @@ -231,6 +232,21 @@ var Module = { test_exit (1); }, + onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + + if (is_node) { + eval (read ("dotnet.js").toString()); + } else { + loadScript ("dotnet.js"); + } + }, + onRuntimeInitialized: function () { try { @@ -243,7 +259,7 @@ var Module = { Module.ccall ('mono_wasm_enable_on_demand_gc', 'void', ['number'], [0]); } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { let wds = FS.stat (working_dir); if (wds === undefined || !FS.isDir (wds.mode)) { fail_exec (`Could not find working directory ${working_dir}`); @@ -253,13 +269,13 @@ var Module = { FS.chdir (working_dir); App.init (); }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { //console.log("fetch_file_cb('" + asset + "')"); // for testing purposes add BCL assets to VFS until we special case File.Open // to identify when an assembly from the BCL is being open and resolve it correctly. /* var content = new Uint8Array (read (asset, 'binary')); - var path = asset.substr(config.deploy_prefix.length); + var path = asset.substr(Module.config.deploy_prefix.length); writeContentToFile(content, path); */ @@ -287,21 +303,13 @@ var Module = { } }; - Module.mono_load_runtime_and_bcl_args (config); + Module.mono_load_runtime_and_bcl_args (Module.config); } catch (e) { console.log (e); } }, }; -if (is_node) { - eval (read ("dotnet.js").toString()); -} else { - loadScript ("dotnet.js"); -} -//var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); -//globalThis.Module = Module; - const IGNORE_PARAM_COUNT = -1; var App = { diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index 9fecab85a2ca1e..80353e35fa0b25 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -7,21 +7,29 @@ // Loads the config file located in the root of the project // Not meant to be used outside of this class (TODO make private to this file when project converted to TS) function load_config() { - callback = Module['onConfigLoaded'] + // since this file loads before emsdk we don't have environment vars yet, so we define them locally + var ENVIRONMENT_IS_NODE = typeof process === 'object'; + var ENVIRONMENT_IS_WEB = typeof window === 'object'; + // var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; + // var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + + callback = Module['onConfigLoaded']; if (ENVIRONMENT_IS_NODE){ - const config = require('./mono-config.json'); - if (callback){ + try { + var config = JSON.parse(require('./mono-config.json')); callback(config); + } catch(e) { + callback({error: "Error loading mono-config.json file from current directory"}); } - } else { + } else if (ENVIRONMENT_IS_WEB){ var xobj = new XMLHttpRequest(); xobj.overrideMimeType("application/json"); xobj.open('GET', './mono-config.json', true); xobj.onreadystatechange = function() { - if (callback && xobj.readyState == XMLHttpRequest.DONE) { + if (xobj.readyState == XMLHttpRequest.DONE) { if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { - const config = JSON.parse(xobj.responseText); + var config = JSON.parse(xobj.responseText); callback(config); } else { // error if the request to load the file was successful but loading failed @@ -31,19 +39,22 @@ function load_config() { }; xobj.onerror = function() { // error if the request failed - if (callback){ - callback({error: "Error loading mono-config.json file from current directory"}); - } + callback({error: "Error loading mono-config.json file from current directory"}); } try { - xobj.send() + xobj.send(); } catch(e) { // other kinds of errors - if (callback){ - callback({error: "Error loading mono-config.json file from current directory"}); - } + callback({error: "Error loading mono-config.json file from current directory"}); + } + } else { + try { + var config = JSON.parse(load("./mono-config.json")); + callback(config); + } catch(e) { + callback({error: "Error loading mono-config.json file from current directory"}); } } } -load_config() \ No newline at end of file +load_config(); From dca4bbc3c4c87b390c47db2ad1c3fe344f9539cd Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 10:00:16 -0400 Subject: [PATCH 012/115] converted mono-config.js to mono-config.json --- .../Directory.Build.props | 1 + src/mono/sample/mbr/browser/index.html | 1 - src/mono/sample/mbr/browser/runtime.js | 4 +++ src/mono/sample/wasm/browser-bench/index.html | 1 - src/mono/sample/wasm/browser-bench/runtime.js | 15 +++++++-- .../sample/wasm/browser-profile/index.html | 1 - .../sample/wasm/browser-profile/runtime.js | 8 +++-- src/mono/sample/wasm/browser/index.html | 1 - src/mono/sample/wasm/browser/runtime.js | 6 +++- src/mono/wasm/Makefile | 6 ++-- src/mono/wasm/build/WasmApp.targets | 2 +- .../tests/debugger-test/debugger-driver.html | 1 - .../tests/debugger-test/runtime-debugger.js | 12 ++++--- src/mono/wasm/runtime-test.js | 2 +- src/mono/wasm/runtime/js_support.js | 32 +++++++++++++++++++ src/mono/wasm/wasm.proj | 2 +- src/tasks/WasmAppBuilder/WasmAppBuilder.cs | 6 ++-- .../Wasm.Build.Tests/BuildTestBase.cs | 2 +- .../WebAssembly/Browser/AOT/index.html | 1 - .../WebAssembly/Browser/AOT/runtime.js | 6 +++- .../Browser/NormalInterp/index.html | 1 - .../Browser/NormalInterp/runtime.js | 4 +++ 22 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 src/mono/wasm/runtime/js_support.js diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index ac2d3cc1a02246..a360fc5d5e5021 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -219,6 +219,7 @@ + diff --git a/src/mono/sample/mbr/browser/index.html b/src/mono/sample/mbr/browser/index.html index 472cf5f29ea053..eb19b7bb2f5954 100644 --- a/src/mono/sample/mbr/browser/index.html +++ b/src/mono/sample/mbr/browser/index.html @@ -29,7 +29,6 @@ }, }; - diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index 0856b8d0e03033..a0179a97ae5a78 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/sample/wasm/browser-bench/index.html b/src/mono/sample/wasm/browser-bench/index.html index eebbae65eb1052..658bfb573ddbfc 100644 --- a/src/mono/sample/wasm/browser-bench/index.html +++ b/src/mono/sample/wasm/browser-bench/index.html @@ -51,7 +51,6 @@ } }; - diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index a39b0b97b14901..39ebf6c0c276b6 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -1,8 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -15,6 +18,14 @@ var Module = { return fetch (asset, { credentials: 'same-origin' }); } + if (config.enable_profiler) + { + config.aot_profiler_options = { + write_at:"Sample.Test::StopProfile", + send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" + } + } + try { MONO.mono_load_runtime_and_bcl_args (config); @@ -23,4 +34,4 @@ var Module = { throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/mono/sample/wasm/browser-profile/index.html b/src/mono/sample/wasm/browser-profile/index.html index 50eb0ff28c2efe..286aa812e869d7 100644 --- a/src/mono/sample/wasm/browser-profile/index.html +++ b/src/mono/sample/wasm/browser-profile/index.html @@ -68,7 +68,6 @@ } - diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 1ce1c0b736034c..39ebf6c0c276b6 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -1,7 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -var Module = { +var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -29,5 +33,5 @@ var Module = { test_exit(1); throw(error); } - } + }, }; \ No newline at end of file diff --git a/src/mono/sample/wasm/browser/index.html b/src/mono/sample/wasm/browser/index.html index bd8e5015a0ee5f..5f170bb38e7bcb 100644 --- a/src/mono/sample/wasm/browser/index.html +++ b/src/mono/sample/wasm/browser/index.html @@ -48,7 +48,6 @@ }, }; - diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index a39b0b97b14901..5588740f8efe99 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -23,4 +27,4 @@ var Module = { throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index abb93b97f40685..b3442e44b63e18 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -101,8 +101,8 @@ $(NATIVE_BIN_DIR)/include/wasm: $(BUILDS_OBJ_DIR): mkdir -p $$@ -$(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) +$(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js runtime/js_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) + $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --post-js runtime/js_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi @@ -141,7 +141,7 @@ clean: icu-files: $(wildcard $(ICU_LIBDIR)/*.dat) $(ICU_LIBDIR)/libicuuc.a $(ICU_LIBDIR)/libicui18n.a | $(NATIVE_BIN_DIR) cp $^ $(NATIVE_BIN_DIR) -source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js | $(NATIVE_BIN_DIR)/src +source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js runtime/js_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js | $(NATIVE_BIN_DIR)/src cp $^ $(NATIVE_BIN_DIR)/src header-files: runtime/pinvoke.h | $(NATIVE_BIN_DIR)/include/wasm diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 0467636bd6c729..a2adbf6076526f 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -67,7 +67,7 @@ - @(WasmFilesToIncludeInFileSystem) - Files to include in the vfs - @(WasmNativeAsset) - Native files to be added to `NativeAssets` in the bundle. - - @(WasmExtraConfig) - json elements to add to `mono-config.js` + - @(WasmExtraConfig) - json elements to add to `mono-config.json` Eg. - Value attribute can have a number, bool, quoted string, or json string diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html index 87ba804792ef39..b1bfcd859d0644 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html @@ -83,7 +83,6 @@ return App.int_add (a, b); } - diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index 4c641eb2c6a0d7..6d3a83dfaaa24a 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -2,8 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - config.loaded_cb = function () { + onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { + config.loaded_cb = function () { App.init (); }; // For custom logging patch the functions below @@ -16,5 +20,5 @@ var Module = { MONO.mono_wasm_setenv ("MONO_LOG_MASK", "all"); */ MONO.mono_load_runtime_and_bcl_args (config) - }, -}; + }, +}; \ No newline at end of file diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 74aa1083c033d1..cfc25430c13db5 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -204,7 +204,7 @@ function loadScript (url) } } -loadScript ("mono-config.js"); +JSSupportLib.load_config(); var Module = { mainScriptUrlOrBlob: "dotnet.js", diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js new file mode 100644 index 00000000000000..ffde2df6c5d017 --- /dev/null +++ b/src/mono/wasm/runtime/js_support.js @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var JSSupportLib = { + // $JS__postset: 'JS.export_functions (Module);', + // $JS: { + load_config: function (callback) { + if (ENVIRONMENT_IS_NODE){ + const config = require('./mono-config.json'); + callback(config); + } + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function () { + if (xobj.readyState == 4 && xobj.status == "200") { + const config = JSON.parse(xobj.responseText); + callback(config); + } + }; + xobj.send(); + }, + + // export_functions: function (module) { + // module ["load_config"] = JS.load_config.bind(JS); + + // } + // }, +} + +// autoAddDeps(JSSupportLib, '$JS') +// mergeInto(LibraryManager.library, JSSupportLib) // TODO FOR SOME REASON THE LOAD_CONFIG FUNCTION IS NOT BEING ADDED TO DOTNET.JS. THIS IS NEEDED SO THAT I CAN CALL LOAD_CONFIG() IN THE SAMPLES diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 86da385e608e5e..d397b3808e5602 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -153,7 +153,7 @@ EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" /> - diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index 9ef7679c292b66..aedcb5dd36bb5d 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -51,7 +51,7 @@ public class WasmAppBuilder : Task public ITaskItem[]? ExtraFilesToDeploy { get; set; } // - // Extra json elements to add to mono-config.js + // Extra json elements to add to mono-config.json // // Metadata: // - Value: can be a number, bool, quoted string, or json string @@ -246,11 +246,11 @@ public override bool Execute () config.Extra[name] = valueObject; } - string monoConfigPath = Path.Combine(AppDir, "mono-config.js"); + string monoConfigPath = Path.Combine(AppDir, "mono-config.json"); using (var sw = File.CreateText(monoConfigPath)) { var json = JsonSerializer.Serialize (config, new JsonSerializerOptions { WriteIndented = true }); - sw.Write($"config = {json};"); + sw.Write($"{json}"); } _fileWrites.Add(monoConfigPath); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index b5f1f7e0b95f73..99e721dfa65f78 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -347,7 +347,7 @@ protected static void AssertBasicAppBundle(string bundleDir, string projectName, "runtime.js", "dotnet.timezones.blat", "dotnet.wasm", - "mono-config.js", + "mono-config.json", "dotnet.js", "run-v8.sh" }); diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html index efab9ac4324a21..642987d23c5e2b 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/index.html @@ -47,7 +47,6 @@ }, }; - diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js index a39b0b97b14901..5588740f8efe99 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); @@ -23,4 +27,4 @@ var Module = { throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html index 03f68679a5b85c..9de05f5031b325 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/index.html @@ -47,7 +47,6 @@ }, }; - diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js index a39b0b97b14901..f15dfa7274d999 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js @@ -3,6 +3,10 @@ var Module = { onRuntimeInitialized: function () { + JSSupportLib.load_config(this.setupConfig); + }, + + setupConfig: function (config) { config.loaded_cb = function () { try { App.init (); From c3d996dbe233934a293ca291ac5a26e49a409650 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 12:43:15 -0400 Subject: [PATCH 013/115] Fixed tests as config is loaded async now --- .../sample/wasm/browser-profile/index.html | 58 ----------------- .../sample/wasm/browser-profile/runtime.js | 63 +++++++++++++++++-- src/mono/wasm/runtime/js_support.js | 43 ++++++------- 3 files changed, 77 insertions(+), 87 deletions(-) diff --git a/src/mono/sample/wasm/browser-profile/index.html b/src/mono/sample/wasm/browser-profile/index.html index 286aa812e869d7..de4a5599e94ad0 100644 --- a/src/mono/sample/wasm/browser-profile/index.html +++ b/src/mono/sample/wasm/browser-profile/index.html @@ -10,66 +10,8 @@ Result from Sample.Test.TestMeaning: - - diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 39ebf6c0c276b6..96572c69592d9e 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -1,16 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. var Module = { + is_testing: false, + onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(Module.setupConfig); }, setupConfig: function (config) { config.loaded_cb = function () { try { - App.init (); + Module.init(); } catch (error) { - test_exit(1); + Module.test_exit(1); throw (error); } }; @@ -30,8 +32,61 @@ var Module = { { MONO.mono_load_runtime_and_bcl_args (config); } catch (error) { - test_exit(1); + Module.test_exit(1); throw(error); } }, + + init: function () { + console.log("not ready yet") + var ret = BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:TestMeaning", []); + document.getElementById("out").innerHTML = ret; + console.log ("ready"); + + if (Module.is_testing) + { + console.debug(`ret: ${ret}`); + let exit_code = ret == 42 ? 0 : 1; + Module.test_exit(exit_code); + } + + if (config.enable_profiler) { + BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []); + Module.saveProfile(); + } + }, + + onLoad: function() { + var url = new URL(decodeURI(window.location)); + let args = url.searchParams.getAll('arg'); + is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); + }, + + test_exit: function(exit_code) { + if (!Module.is_testing) { + console.log(`test_exit: ${exit_code}`); + return; + } + + /* Set result in a tests_done element, to be read by xharness */ + var tests_done_elem = document.createElement("label"); + tests_done_elem.id = "tests_done"; + tests_done_elem.innerHTML = exit_code.toString(); + document.body.appendChild(tests_done_elem); + + console.log(`WASM EXIT ${exit_code}`); + }, + + saveProfile: function () { + var a = document.createElement('a'); + var blob = new Blob([Module.aot_profile_data]); + a.href = URL.createObjectURL(blob); + a.download = "data.aotprofile"; + // Append anchor to body. + document.body.appendChild(a); + a.click(); + + // Remove anchor from body + document.body.removeChild(a); + } }; \ No newline at end of file diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index ffde2df6c5d017..e4ef25c30ad125 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -1,32 +1,25 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +// THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMZIED +// IT I MEANT AS A SET OF JS TOOLS TO SUPPORT THE SDK + var JSSupportLib = { - // $JS__postset: 'JS.export_functions (Module);', - // $JS: { - load_config: function (callback) { - if (ENVIRONMENT_IS_NODE){ - const config = require('./mono-config.json'); + // Loads the config file located in the root of the project + load_config: function (callback) { + if (ENVIRONMENT_IS_NODE){ + const config = require('./mono-config.json'); + callback(config); + } + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function () { + if (xobj.readyState == 4 && xobj.status == "200") { + const config = JSON.parse(xobj.responseText); callback(config); } - var xobj = new XMLHttpRequest(); - xobj.overrideMimeType("application/json"); - xobj.open('GET', './mono-config.json', true); - xobj.onreadystatechange = function () { - if (xobj.readyState == 4 && xobj.status == "200") { - const config = JSON.parse(xobj.responseText); - callback(config); - } - }; - xobj.send(); - }, - - // export_functions: function (module) { - // module ["load_config"] = JS.load_config.bind(JS); - - // } - // }, + }; + xobj.send(); + }, } - -// autoAddDeps(JSSupportLib, '$JS') -// mergeInto(LibraryManager.library, JSSupportLib) // TODO FOR SOME REASON THE LOAD_CONFIG FUNCTION IS NOT BEING ADDED TO DOTNET.JS. THIS IS NEEDED SO THAT I CAN CALL LOAD_CONFIG() IN THE SAMPLES From f14f41241ab97aa2ced5cb50b10a49c713ed49e0 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 15:55:08 -0400 Subject: [PATCH 014/115] added line to end of file + more comments --- src/mono/sample/wasm/browser/runtime.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 5588740f8efe99..0c996cac3de58a 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -2,10 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { + // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { JSSupportLib.load_config(this.setupConfig); }, + // Called once the config file is loaded. THe contents of the config file + // are passed as a JS object within the config parameter setupConfig: function (config) { config.loaded_cb = function () { try { @@ -27,4 +30,4 @@ var Module = { throw(error); } }, -}; \ No newline at end of file +}; From 492eb2ad9182a2d17a1d1f6968166c02fa53c171 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Sanchez Date: Thu, 20 May 2021 19:46:20 +0000 Subject: [PATCH 015/115] Print R2RDump Statistics in the Output File Instead of Console (#52278) * Moved R2RDump statistics from console to --out file * Automated the fixup statistics report into a self-maintaining component. * Optimized the minimum values by setting them at the beginning, and removing the Math.Max() calls. --- src/coreclr/tools/r2rdump/TextDumper.cs | 46 ++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/coreclr/tools/r2rdump/TextDumper.cs b/src/coreclr/tools/r2rdump/TextDumper.cs index 613c0bb96eadbb..0e062b88508f93 100644 --- a/src/coreclr/tools/r2rdump/TextDumper.cs +++ b/src/coreclr/tools/r2rdump/TextDumper.cs @@ -561,13 +561,51 @@ internal override void DumpFixupStats() Count = group.Count() }).OrderByDescending(x => x.Count); - Console.WriteLine($" Fixup | Count"); + /* Runtime Repo GH Issue #49249: + * + * In order to format the fixup counts results table, we need to + * know beforehand the size of each column. The padding is calculated + * as follows: + * + * Fixup: Length of the longest Fixup Kind name. + * Count: Since a total is always bigger than its operands, we set + * the padding to the total's number of digits. + * + * The reason we want them to be at least 5, is because in the case of only + * getting values shorter than 5 digits (Length of "Fixup" and "Count"), + * the formatting could be messed up. The likelyhood of this happening + * is apparently 0%, but better safe than sorry. */ + + int fixupPadding = 5; + int sortedFixupCountsTotal = sortedFixupCounts.Sum(x => x.Count); + int countPadding = Math.Max(sortedFixupCountsTotal.ToString().Length, 5); + + /* We look at all the Fixup Kinds that will be printed. We + * then store the length of the longest one's name. */ + foreach (var fixupAndCount in sortedFixupCounts) { - Console.WriteLine($"{fixupAndCount.FixupKind, 27} | {fixupAndCount.Count, 5}"); + int kindLength = fixupAndCount.FixupKind.ToString().Length; + + if (kindLength > fixupPadding) + fixupPadding = kindLength; } - Console.WriteLine("-----------------------------------"); - Console.WriteLine($" Total | {sortedFixupCounts.Sum(x => x.Count), 5}"); + + _writer.WriteLine( + $"{"Fixup".PadLeft(fixupPadding)} | {"Count".PadLeft(countPadding)}" + ); + foreach (var fixupAndCount in sortedFixupCounts) + { + _writer.WriteLine( + $"{fixupAndCount.FixupKind.ToString().PadLeft(fixupPadding)} | {fixupAndCount.Count.ToString().PadLeft(countPadding)}" + ); + } + + // The +3 in this divider is to account for the " | " table division. + _writer.WriteLine(new string('-', fixupPadding + countPadding + 3)); + _writer.WriteLine( + $"{"Total".PadLeft(fixupPadding)} | {sortedFixupCountsTotal.ToString().PadLeft(countPadding)}" + ); SkipLine(); } } From e7bfefbd405654ce0bad7448fe617377644d9042 Mon Sep 17 00:00:00 2001 From: Steve Molloy Date: Thu, 20 May 2021 13:56:55 -0700 Subject: [PATCH 016/115] Use Assembly.Load as first option to load TempAssembly. (#52429) * Use Assembly.Load as first option to load TempAssembly. --- .../System/Xml/Serialization/Compilation.cs | 75 ++++++++++++------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs index 6fd1d1c83e81ac..8fdeed7b60b770 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs @@ -139,7 +139,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) /// // SxS: This method does not take any resource name and does not expose any resources to the caller. // It's OK to suppress the SxS warning. - [RequiresUnreferencedCode("calls LoadFile")] + [RequiresUnreferencedCode("calls LoadFrom")] [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead " + "this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820")] @@ -161,39 +161,20 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) name.CodeBase = null; name.CultureInfo = CultureInfo.InvariantCulture; - string? serializerPath = null; - try { - if (!string.IsNullOrEmpty(type.Assembly.Location)) - { - serializerPath = Path.Combine(Path.GetDirectoryName(type.Assembly.Location)!, serializerName + ".dll"); - } - - if ((string.IsNullOrEmpty(serializerPath) || !File.Exists(serializerPath)) && !string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location)) - { - serializerPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)!, serializerName + ".dll"); - } - - if (!string.IsNullOrEmpty(serializerPath)) - { - serializer = Assembly.LoadFile(serializerPath); - } + serializer = Assembly.Load(name); } catch (Exception e) { - if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) + if (e is OutOfMemoryException) { throw; } - byte[]? token = name.GetPublicKeyToken(); - if (token != null && token.Length > 0) - { - // the parent assembly was signed, so do not try to LoadWithPartialName - return null; - } } + serializer ??= LoadAssemblyByPath(type, serializerName); + if (serializer == null) { if (XmlSerializer.Mode == SerializationMode.PreGenOnly) @@ -220,9 +201,7 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) if (assemblyAttribute.AssemblyName != null) { serializerName = assemblyAttribute.AssemblyName; -#pragma warning disable 618 - serializer = Assembly.LoadWithPartialName(serializerName); -#pragma warning restore 618 + serializer = Assembly.Load(serializerName); // LoadWithPartialName just does this in .Net Core; changing the obsolete call. } else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0) { @@ -247,6 +226,48 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) return null; } + [RequiresUnreferencedCode("calls LoadFile")] + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + Justification = "Annotating this as dangerous will make the core of the serializer to be marked as not safe, instead " + + "this pattern is only dangerous if using sgen only. See https://github.com/dotnet/runtime/issues/50820")] + private static Assembly? LoadAssemblyByPath(Type type, string assemblyName) + { + Assembly? assembly = null; + string? path = null; + + try + { + if (!string.IsNullOrEmpty(type.Assembly.Location)) + { + path = Path.Combine(Path.GetDirectoryName(type.Assembly.Location)!, assemblyName + ".dll"); + } + + if ((string.IsNullOrEmpty(path) || !File.Exists(path)) && !string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location)) + { + path = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)!, assemblyName + ".dll"); + } + + if ((string.IsNullOrEmpty(path) || !File.Exists(path)) && !string.IsNullOrEmpty(AppContext.BaseDirectory)) + { + path = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory)!, assemblyName + ".dll"); + } + + if (!string.IsNullOrEmpty(path)) + { + assembly = Assembly.LoadFile(path); + } + } + catch (Exception e) + { + if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) + { + throw; + } + } + + return assembly; + } + private static bool IsSerializerVersionMatch(Assembly serializer, Type type, string? defaultNamespace) { if (serializer == null) From 11b2f1aa2a895f783a3e172c4b8b2b1d6c920f6f Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Thu, 20 May 2021 14:07:45 -0700 Subject: [PATCH 017/115] Support string interning for InvokeJS, address string interning performance hazard (#51576) * In WASM builds, inflated lock words have an 'is interned' flag for strings to enable O(1) 'is interned' checks vs the previous hash lookup * When the expression being passed to InvokeJS is interned, the binding_support string intern table is used to avoid marshaling the expression again --- src/mono/mono/metadata/monitor.c | 25 ++++++++++++++++++++++ src/mono/mono/metadata/monitor.h | 11 ++++++++++ src/mono/mono/metadata/object-internals.h | 5 +++++ src/mono/mono/metadata/object.c | 26 ++++++++++++++++++++--- src/mono/wasm/runtime/binding_support.js | 6 +++++- src/mono/wasm/runtime/driver.c | 23 +++++++++++++++----- 6 files changed, 87 insertions(+), 9 deletions(-) diff --git a/src/mono/mono/metadata/monitor.c b/src/mono/mono/metadata/monitor.c index 66ed83156f0ffc..da5662677b8664 100644 --- a/src/mono/mono/metadata/monitor.c +++ b/src/mono/mono/metadata/monitor.c @@ -1430,6 +1430,31 @@ mono_monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_in return success; } +#ifdef HOST_WASM +void +mono_set_string_interned_internal (MonoObject* obj) +{ + LockWord tmp; + tmp.sync = obj->synchronisation; + if (!lock_word_is_inflated (tmp)) { + mono_monitor_inflate (obj); + tmp.sync = obj->synchronisation; + } + lock_word_get_inflated_lock (tmp)->is_interned = 1; +} + +gboolean +mono_is_string_interned_internal (MonoObject* obj) +{ + LockWord tmp; + tmp.sync = obj->synchronisation; + if (!lock_word_is_inflated (tmp)) + return 0; + + return lock_word_get_inflated_lock (tmp)->is_interned; +} +#endif + MonoBoolean ves_icall_System_Threading_Monitor_Monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_interruption, MonoError* error) { diff --git a/src/mono/mono/metadata/monitor.h b/src/mono/mono/metadata/monitor.h index fecec04d55ea15..9e79c4050bb29a 100644 --- a/src/mono/mono/metadata/monitor.h +++ b/src/mono/mono/metadata/monitor.h @@ -43,6 +43,9 @@ struct _MonoThreadsSync void *data; MonoCoopMutex *entry_mutex; MonoCoopCond *entry_cond; +#ifdef HOST_WASM + gboolean is_interned; +#endif }; /* @@ -131,4 +134,12 @@ ICALL_EXPORT gint64 ves_icall_System_Threading_Monitor_Monitor_LockContentionCount (void); +#ifdef HOST_WASM +void +mono_set_string_interned_internal (MonoObject* obj); + +gboolean +mono_is_string_interned_internal (MonoObject* obj); +#endif + #endif /* _MONO_METADATA_MONITOR_H_ */ diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index 78502016cc2fa5..e985bdbe0498aa 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -2084,4 +2084,9 @@ mono_runtime_get_managed_cmd_line (void); char * mono_runtime_get_cmd_line (int argc, char **argv); +#ifdef HOST_WASM +int +mono_string_instance_is_interned (MonoString *str); +#endif + #endif /* __MONO_OBJECT_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 1e59f65a70e0f8..a8d2c1c70a154a 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -6736,16 +6736,36 @@ mono_string_is_interned_lookup (MonoStringHandle str, gboolean insert, MonoError res = (MonoString *)mono_g_hash_table_lookup (ldstr_table, MONO_HANDLE_RAW (str)); if (res) MONO_HANDLE_ASSIGN_RAW (s, res); - else + else { mono_g_hash_table_insert_internal (ldstr_table, MONO_HANDLE_RAW (s), MONO_HANDLE_RAW (s)); + +#ifdef HOST_WASM + mono_set_string_interned_internal ((MonoObject *)MONO_HANDLE_RAW (s)); +#endif + } ldstr_unlock (); return s; } +#ifdef HOST_WASM +/** + * mono_string_instance_is_interned: + * Searches the interned string table for the provided string instance. + * \param str String to probe + * \returns TRUE if the string is interned, FALSE otherwise. + */ +int +mono_string_instance_is_interned (MonoString *str) +{ + return mono_is_string_interned_internal ((MonoObject *)str); +} +#endif + /** * mono_string_is_interned: - * \param o String to probe - * \returns Whether the string has been interned. + * Searches the interned string table for a string with value equal to the provided string. + * \param str String to probe + * \returns The string located within the intern table, or null. */ MonoString* mono_string_is_interned (MonoString *str_raw) diff --git a/src/mono/wasm/runtime/binding_support.js b/src/mono/wasm/runtime/binding_support.js index 3938dc83041b64..3951da52101b43 100644 --- a/src/mono/wasm/runtime/binding_support.js +++ b/src/mono/wasm/runtime/binding_support.js @@ -278,8 +278,12 @@ var BindingSupportLib = { return null; }, + _get_string_from_intern_table: function (mono_obj) { + return this._managed_pointer_to_interned_string_table.get (mono_obj); + }, + conv_string: function (mono_obj, interned) { - var interned_instance = this._managed_pointer_to_interned_string_table.get (mono_obj); + var interned_instance = this._get_string_from_intern_table(mono_obj); if (interned_instance !== undefined) return interned_instance; diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index 515391815c4bbc..7a2e0fc4fb7159 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -78,6 +78,9 @@ typedef struct { const char* (*lookup_icall_symbol) (void* func); } MonoIcallTableCallbacks; +int +mono_string_instance_is_interned (MonoString *str_raw); + void mono_install_icall_table_callbacks (const MonoIcallTableCallbacks *cb); @@ -95,13 +98,23 @@ mono_wasm_invoke_js (MonoString *str, int *is_exception) if (str == NULL) return NULL; - mono_unichar2 *native_val = mono_string_chars (str); + int is_interned = mono_string_instance_is_interned (str); + mono_unichar2 *native_chars = mono_string_chars (str); int native_len = mono_string_length (str) * 2; int native_res_len; int *p_native_res_len = &native_res_len; mono_unichar2 *native_res = (mono_unichar2*)EM_ASM_INT ({ - var str = MONO.string_decoder.decode ($0, $0 + $1); + var str; + // If the expression is interned, use binding_support's intern table implementation to + // avoid decoding it again unless necessary + // We could technically use conv_string for both cases here, but it's more expensive + // than using decode directly in the case where the expression isn't interned + if ($4) + str = BINDING.conv_string($5, true); + else + str = MONO.string_decoder.decode ($0, $0 + $1); + try { var res = eval (str); if (res === null || res == undefined) @@ -128,7 +141,7 @@ mono_wasm_invoke_js (MonoString *str, int *is_exception) stringToUTF16 (res, buff, (res.length + 1) * 2); setValue ($3, res.length, "i32"); return buff; - }, (int)native_val, native_len, is_exception, p_native_res_len); + }, (int)native_chars, native_len, is_exception, p_native_res_len, is_interned, (int)str); if (native_res == NULL) return NULL; @@ -920,7 +933,7 @@ mono_wasm_get_obj_type (MonoObject *obj) /* Process obj before calling into the runtime, class_from_name () can invoke managed code */ MonoClass *klass = mono_object_get_class (obj); if ((klass == mono_get_string_class ()) && - (mono_string_is_interned ((MonoString *)obj) == (MonoString *)obj)) + mono_string_instance_is_interned ((MonoString *)obj)) return MARSHAL_TYPE_STRING_INTERNED; MonoType *type = mono_class_get_type (klass); @@ -947,7 +960,7 @@ mono_wasm_try_unbox_primitive_and_get_type (MonoObject *obj, void *result) /* Process obj before calling into the runtime, class_from_name () can invoke managed code */ MonoClass *klass = mono_object_get_class (obj); if ((klass == mono_get_string_class ()) && - (mono_string_is_interned ((MonoString *)obj) == (MonoString *)obj)) { + mono_string_instance_is_interned ((MonoString *)obj)) { *resultL = 0; return MARSHAL_TYPE_STRING_INTERNED; } From 0f887cebc93b7f15d406879fbb6b3cf9ce212200 Mon Sep 17 00:00:00 2001 From: imhameed Date: Thu, 20 May 2021 14:44:36 -0700 Subject: [PATCH 018/115] [mono] LLVM 11 compatibility fixes (#53019) Fixes for minor source-level incompatibilities caught by https://github.com/dotnet/runtime/pull/52984. `AArch64Intrinsics` really should be `AARCH64Intrinsics`. And `llvm.floor`, `llvm.ceil`, and `llvm.trunc` are architecture-independent intrinsics. Also adds LLVM 11 linking flags to CMakeLists.txt. --- src/mono/CMakeLists.txt | 43 +++++++++++++++++++++------- src/mono/mono/mini/llvm-intrinsics.h | 6 ++-- src/mono/mono/mini/mini-llvm-cpp.cpp | 2 +- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 22cf849b4460f2..1e7fa7a08c4bd9 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -469,6 +469,35 @@ if(GCC) endif() endif() +###################################### +# LLVM FLAGS AND LIBRARIES +###################################### + +# llvm-config --libs analysis core bitwriter mcjit orcjit +set(MONO_llvm_core_libs_1100 "-lLLVMOrcJIT" "-lLLVMPasses" "-lLLVMCoroutines" "-lLLVMipo" "-lLLVMInstrumentation" "-lLLVMVectorize" "-lLLVMScalarOpts" "-lLLVMLinker" "-lLLVMIRReader" "-lLLVMAsmParser" "-lLLVMInstCombine" "-lLLVMFrontendOpenMP" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMOrcError" "-lLLVMJITLink" "-lLLVMMCJIT" "-lLLVMExecutionEngine" "-lLLVMTarget" "-lLLVMRuntimeDyld" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMTextAPI" "-lLLVMMCParser" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBitReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBitstreamReader" "-lLLVMBinaryFormat" "-lLLVMSupport" "-lLLVMDemangle") + +# llvm-config --libs x86codegen +set(MONO_llvm_extra_libs_x86codegen_1100 "-lLLVMX86CodeGen" "-lLLVMCFGuard" "-lLLVMGlobalISel" "-lLLVMX86Desc" "-lLLVMX86Info" "-lLLVMMCDisassembler" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMTextAPI" "-lLLVMMCParser" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBitReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBitstreamReader" "-lLLVMBinaryFormat" "-lLLVMSupport" "-lLLVMDemangle") + +# llvm-config --libs armcodegen +set(MONO_llvm_extra_libs_armcodegen_1100 "-lLLVMARMCodeGen" "-lLLVMCFGuard" "-lLLVMGlobalISel" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMTextAPI" "-lLLVMMCParser" "-lLLVMBitReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBitstreamReader" "-lLLVMARMDesc" "-lLLVMMCDisassembler" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBinaryFormat" "-lLLVMARMUtils" "-lLLVMARMInfo" "-lLLVMSupport" "-lLLVMDemangle") + +# llvm-config --libs aarch64codegen +set(MONO_llvm_extra_libs_aarch64codegen_1100 "-lLLVMAArch64CodeGen" "-lLLVMCFGuard" "-lLLVMGlobalISel" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMTextAPI" "-lLLVMMCParser" "-lLLVMBitReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBitstreamReader" "-lLLVMAArch64Desc" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBinaryFormat" "-lLLVMAArch64Utils" "-lLLVMAArch64Info" "-lLLVMSupport" "-lLLVMDemangle") + + +# llvm-config --libs analysis core bitwriter mcjit orcjit +set(MONO_llvm_core_libs_900 "-lLLVMOrcJIT" "-lLLVMJITLink" "-lLLVMMCJIT" "-lLLVMExecutionEngine" "-lLLVMRuntimeDyld" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBinaryFormat" "-lLLVMSupport" "-lLLVMDemangle") + +# llvm-config --libs x86codegen +set(MONO_llvm_extra_libs_x86codegen_900 "-lLLVMX86CodeGen" "-lLLVMGlobalISel" "-lLLVMX86Desc" "-lLLVMX86Utils" "-lLLVMX86Info" "-lLLVMMCDisassembler" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBinaryFormat" "-lLLVMSupport" "-lLLVMDemangle") + +# llvm-config --libs armcodegen +set(MONO_llvm_extra_libs_armcodegen_900 "-lLLVMARMCodeGen" "-lLLVMGlobalISel" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMARMDesc" "-lLLVMMCDisassembler" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBinaryFormat" "-lLLVMARMUtils" "-lLLVMARMInfo" "-lLLVMSupport" "-lLLVMDemangle") + +# llvm-config --libs aarch64codegen +set(MONO_llvm_extra_libs_aarch64codegen_900 "-lLLVMAArch64CodeGen" "-lLLVMGlobalISel" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMAArch64Desc" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBinaryFormat" "-lLLVMAArch64Utils" "-lLLVMAArch64Info" "-lLLVMSupport" "-lLLVMDemangle") + ###################################### # LLVM CHECKS ###################################### @@ -504,19 +533,11 @@ if(LLVM_PREFIX) set(llvm_system_libs "-lz" "-lrt" "-ldl" "-lpthread" "-lm") # llvm-config --libs analysis core bitwriter mcjit orcjit - set(llvm_core_libs "-lLLVMOrcJIT" "-lLLVMJITLink" "-lLLVMMCJIT" "-lLLVMExecutionEngine" "-lLLVMRuntimeDyld" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBinaryFormat" "-lLLVMSupport" "-lLLVMDemangle") + set(llvm_core_libs ${MONO_llvm_core_libs_${llvm_api_version}}) # Check codegen libs and add needed libraries. - if("${llvm_codegen_libs}" STREQUAL "x86codegen") - # llvm-config --libs x86codegen - set(llvm_extra "-lLLVMX86CodeGen" "-lLLVMGlobalISel" "-lLLVMX86Desc" "-lLLVMX86Utils" "-lLLVMX86Info" "-lLLVMMCDisassembler" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMBinaryFormat" "-lLLVMSupport" "-lLLVMDemangle") - elseif("${llvm_codegen_libs}" STREQUAL "armcodegen") - # llvm-config --libs armcodegen - set(llvm_extra "-lLLVMARMCodeGen" "-lLLVMGlobalISel" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMARMDesc" "-lLLVMMCDisassembler" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBinaryFormat" "-lLLVMARMUtils" "-lLLVMARMInfo" "-lLLVMSupport" "-lLLVMDemangle") - elseif("${llvm_codegen_libs}" STREQUAL "aarch64codegen") - # llvm-config --libs aarch64codegen - set(llvm_extra "-lLLVMAArch64CodeGen" "-lLLVMGlobalISel" "-lLLVMSelectionDAG" "-lLLVMAsmPrinter" "-lLLVMDebugInfoDWARF" "-lLLVMCodeGen" "-lLLVMTarget" "-lLLVMScalarOpts" "-lLLVMInstCombine" "-lLLVMAggressiveInstCombine" "-lLLVMTransformUtils" "-lLLVMBitWriter" "-lLLVMAnalysis" "-lLLVMProfileData" "-lLLVMObject" "-lLLVMMCParser" "-lLLVMBitReader" "-lLLVMBitstreamReader" "-lLLVMCore" "-lLLVMRemarks" "-lLLVMAArch64Desc" "-lLLVMMC" "-lLLVMDebugInfoCodeView" "-lLLVMDebugInfoMSF" "-lLLVMBinaryFormat" "-lLLVMAArch64Utils" "-lLLVMAArch64Info" "-lLLVMSupport" "-lLLVMDemangle") - else() + set(llvm_extra ${MONO_llvm_extra_libs_${llvm_codegen_libs}_${llvm_api_version}}) + if("${llvm_extra}" STREQUAL "") message(FATAL_ERROR "FIXME: ${TARGET_ARCH}") endif() diff --git a/src/mono/mono/mini/llvm-intrinsics.h b/src/mono/mono/mini/llvm-intrinsics.h index e1712e1ec49fed..b72ec3cd09c7a4 100644 --- a/src/mono/mono/mini/llvm-intrinsics.h +++ b/src/mono/mono/mini/llvm-intrinsics.h @@ -425,9 +425,9 @@ INTRINS_OVR_TAG(AARCH64_ADV_SIMD_RBIT, aarch64_neon_rbit, Arm64, V64 | V128 | I1 INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTA, round, Generic, Scalar | V64 | V128 | R4 | R8) INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTN, aarch64_neon_frintn, Arm64, Scalar | V64 | V128 | R4 | R8) -INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTM, floor, Arm64, Scalar | V64 | V128 | R4 | R8) -INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTP, ceil, Arm64, Scalar | V64 | V128 | R4 | R8) -INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTZ, trunc, Arm64, Scalar | V64 | V128 | R4 | R8) +INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTM, floor, Generic, Scalar | V64 | V128 | R4 | R8) +INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTP, ceil, Generic, Scalar | V64 | V128 | R4 | R8) +INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTZ, trunc, Generic, Scalar | V64 | V128 | R4 | R8) INTRINS_OVR_TAG(AARCH64_ADV_SIMD_SUQADD, aarch64_neon_suqadd, Arm64, Scalar | V64 | V128 | I1 | I2 | I4 | I8) INTRINS_OVR_TAG(AARCH64_ADV_SIMD_USQADD, aarch64_neon_usqadd, Arm64, Scalar | V64 | V128 | I1 | I2 | I4 | I8) diff --git a/src/mono/mono/mini/mini-llvm-cpp.cpp b/src/mono/mono/mini/mini-llvm-cpp.cpp index 1cbcec5e41399a..9e7113122f9478 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.cpp +++ b/src/mono/mono/mini/mini-llvm-cpp.cpp @@ -692,7 +692,7 @@ get_intrins_id (IntrinsicId id) #if LLVM_API_VERSION >= 1100 #define Generic IndependentIntrinsics #define X86 X86Intrinsics -#define Arm64 AArch64Intrinsics +#define Arm64 AARCH64Intrinsics #define Wasm WASMIntrinsics #define INTRINS(id, llvm_id, arch) case INTRINS_ ## id: intrins_id = Intrinsic::arch::llvm_id; break; #else From 881f491b4fc1e21f8ea4d410a64bd48269257d3c Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Thu, 20 May 2021 23:26:21 +0100 Subject: [PATCH 019/115] StringValues.Count test null first (#52508) --- .../Microsoft.Extensions.Primitives/src/StringValues.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs b/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs index 25c586d9a9e979..7a7ec59457a930 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/src/StringValues.cs @@ -93,14 +93,14 @@ public int Count { // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in memory object value = _values; - if (value is string) - { - return 1; - } if (value is null) { return 0; } + if (value is string) + { + return 1; + } else { // Not string, not null, can only be string[] From 993f8fa801de3bcb396e1b33cb5709790b1957c9 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Fri, 21 May 2021 04:34:02 +0600 Subject: [PATCH 020/115] Return null when Variant contains BSTR (#53030) * Return null when Variant contains BSTR I found this one when implement VARIANT marshalling for NativeAOT. Without that I have to resort to duplicate implementation in that class. PR where I discover this - https://github.com/dotnet/runtimelab/pull/1142 Problem is `Marshal.PtrToStringBSTR` throw exception when passed `IntPtr.Zero`, but `Marshal.StringToBSTR` produce `IntPtr.Zero` when given null. * Update nullable annotations --- .../Common/src/System/Runtime/InteropServices/Variant.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs b/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs index c0eb0c6b819b6b..ab2210cdda15c8 100644 --- a/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs +++ b/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs @@ -628,11 +628,15 @@ public DateTime AsDate // VT_BSTR - public string AsBstr + public string? AsBstr { get { Debug.Assert(VariantType == VarEnum.VT_BSTR); + if (_typeUnion._unionTypes._bstr == IntPtr.Zero) + { + return null; + } return (string)Marshal.PtrToStringBSTR(this._typeUnion._unionTypes._bstr); } set From 118f54c6278e06344e1ecb3006319b832c2a50f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Fri, 21 May 2021 01:15:59 +0200 Subject: [PATCH 021/115] Fix OperatingSystem.IsAndroidVersionAtLeast() (#53034) The implementation called into uname() which returns the Linux kernel version, but the API as specified in https://github.com/dotnet/designs/blob/main/accepted/2020/platform-checks/platform-checks.md expects the Android API level to be passed in and checked. Also fix `OperatingSystem.IsLinux()` to return false on Android. --- .../System.Native/pal_runtimeinformation.c | 16 ++++++++++++++++ .../src/System/OperatingSystem.cs | 4 ++-- .../tests/System/OperatingSystemTests.cs | 4 +++- .../tests/ChaCha20Poly1305Tests.cs | 19 +------------------ 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_runtimeinformation.c b/src/libraries/Native/Unix/System.Native/pal_runtimeinformation.c index 504cb32e0d1921..c7b7073adfafd1 100644 --- a/src/libraries/Native/Unix/System.Native/pal_runtimeinformation.c +++ b/src/libraries/Native/Unix/System.Native/pal_runtimeinformation.c @@ -7,6 +7,9 @@ #include #include #include +#if defined(TARGET_ANDROID) +#include +#endif const char* SystemNative_GetUnixName() { @@ -15,10 +18,23 @@ const char* SystemNative_GetUnixName() char* SystemNative_GetUnixRelease() { +#if defined(TARGET_ANDROID) + // get the Android API level + char sdk_ver_str[PROP_VALUE_MAX]; + if (__system_property_get("ro.build.version.sdk", sdk_ver_str)) + { + return strdup(sdk_ver_str); + } + else + { + return NULL; + } +#else struct utsname _utsname; return uname(&_utsname) != -1 ? strdup(_utsname.release) : NULL; +#endif } int32_t SystemNative_GetUnixVersion(char* version, int* capacity) diff --git a/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs b/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs index 892b31f8b9e819..ff577894c606df 100644 --- a/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs +++ b/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs @@ -133,7 +133,7 @@ public static bool IsBrowser() => /// Indicates whether the current application is running on Linux. /// public static bool IsLinux() => -#if TARGET_LINUX +#if TARGET_LINUX && !TARGET_ANDROID true; #else false; @@ -166,7 +166,7 @@ public static bool IsAndroid() => #endif /// - /// Check for the Android version (returned by 'uname') with a >= version comparison. Used to guard APIs that were added in the given Android release. + /// Check for the Android API level (returned by 'ro.build.version.sdk') with a >= version comparison. Used to guard APIs that were added in the given Android release. /// public static bool IsAndroidVersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) => IsAndroid() && IsOSVersionAtLeast(major, minor, build, revision); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs index ab60be543e1e28..6a6b1cdd6b6a2f 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs @@ -93,12 +93,14 @@ public static void IsOSPlatformVersionAtLeast_InvalidArgs_Throws() public static void TestIsOSVersionAtLeast_FreeBSD() => TestIsOSVersionAtLeast("FreeBSD"); [Fact, PlatformSpecific(TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void TestIsOSPlatform_Android() => TestIsOSPlatform("Android", OperatingSystem.IsAndroid); [Fact, PlatformSpecific(TestPlatforms.Android)] public static void TestIsOSVersionAtLeast_Android() => TestIsOSVersionAtLeast("Android"); + [Fact, PlatformSpecific(TestPlatforms.Android)] + public static void TestIsOSVersionAtLeast_Android_21() => Assert.True(OperatingSystem.IsAndroidVersionAtLeast(21)); // 21 is our min supported version + [Fact, PlatformSpecific(TestPlatforms.iOS)] public static void TestIsOSPlatform_IOS() => TestIsOSPlatform("iOS", OperatingSystem.IsIOS); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/ChaCha20Poly1305Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/ChaCha20Poly1305Tests.cs index 64d40f03705894..1d7ee47d6a7091 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/ChaCha20Poly1305Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/ChaCha20Poly1305Tests.cs @@ -451,7 +451,7 @@ public static void CheckIsSupported() else if (PlatformDetection.IsAndroid) { // Android with API Level 28 is the minimum API Level support for ChaChaPoly1305. - expectedIsSupported = GetAndroidSdkVersion() >= 28; + expectedIsSupported = OperatingSystem.IsAndroidVersionAtLeast(28); } else if (PlatformDetection.OpenSslPresentOnSystem && (PlatformDetection.IsOSX || PlatformDetection.IsOpenSslSupported)) @@ -462,22 +462,5 @@ public static void CheckIsSupported() Assert.Equal(expectedIsSupported, ChaCha20Poly1305.IsSupported); } - - private static int GetAndroidSdkVersion() - { - using Process proc = new Process(); - proc.StartInfo.FileName = "getprop"; - proc.StartInfo.Arguments = " ro.build.version.sdk"; - proc.StartInfo.UseShellExecute = false; - proc.StartInfo.RedirectStandardOutput = true; - proc.Start(); - string stdout = proc.StandardOutput.ReadToEnd(); - - // This should never take more than a second. - int sdkVersion = -1; - bool success = proc.WaitForExit(5_000) && int.TryParse(stdout, out sdkVersion); - Assert.True(success, "Could not determine Android SDK version for current device."); - return sdkVersion; - } } } From 3eb2f9fbae03405b776189de2cb7785df46072ba Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Thu, 20 May 2021 19:16:57 -0400 Subject: [PATCH 022/115] Make the lookup for getApplicationProtocol optional (#53001) * Make the lookup for getApplicationProtocol optional The method getApplicationProtocol in javax.net.ssl.SSLEngine is only supported on API level 29 and above, so running on older devices would result in a crash. This change makes the initial method lookup optional and AndroidCryptoNative_SSLStreamGetApplicationProtocol in pal_sslstream.c will error if it is not supported. Fixes https://github.com/dotnet/runtime/issues/52965 * Feedback Co-authored-by: Steve Pfister --- .../System.Security.Cryptography.Native.Android/pal_jni.c | 2 +- .../pal_sslstream.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c index b53703be6a0db3..d847680d421141 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c @@ -967,7 +967,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_SSLEngine = GetClassGRef(env, "javax/net/ssl/SSLEngine"); g_SSLEngineBeginHandshake = GetMethod(env, false, g_SSLEngine, "beginHandshake", "()V"); g_SSLEngineCloseOutbound = GetMethod(env, false, g_SSLEngine, "closeOutbound", "()V"); - g_SSLEngineGetApplicationProtocol = GetMethod(env, false, g_SSLEngine, "getApplicationProtocol", "()Ljava/lang/String;"); + g_SSLEngineGetApplicationProtocol = GetOptionalMethod(env, false, g_SSLEngine, "getApplicationProtocol", "()Ljava/lang/String;"); g_SSLEngineGetHandshakeStatus = GetMethod(env, false, g_SSLEngine, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;"); g_SSLEngineGetSession = GetMethod(env, false, g_SSLEngine, "getSession", "()Ljavax/net/ssl/SSLSession;"); g_SSLEngineGetSSLParameters = GetMethod(env, false, g_SSLEngine, "getSSLParameters", "()Ljavax/net/ssl/SSLParameters;"); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c index da90e8eeb2e716..0a458eab355483 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c @@ -652,6 +652,12 @@ void AndroidCryptoNative_SSLStreamRelease(SSLStream* sslStream) int32_t AndroidCryptoNative_SSLStreamGetApplicationProtocol(SSLStream* sslStream, uint8_t* out, int32_t* outLen) { + if (g_SSLEngineGetApplicationProtocol == NULL) + { + // SSLEngine.getApplicationProtocol() is only supported from API level 29 and above + return FAIL; + } + abort_if_invalid_pointer_argument (sslStream); abort_if_invalid_pointer_argument (outLen); From f15a7fccce708e19e47eec90582a4eb5a44b7aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Rylek?= Date: Fri, 21 May 2021 01:22:54 +0200 Subject: [PATCH 023/115] Disable crossgen2determinism test on OSX arm64 (#53045) --- src/tests/issues.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 008255e24e39e0..26836c55e86c0d 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -749,6 +749,9 @@ https://github.com/dotnet/runtime/issues/49365 + + https://github.com/dotnet/runtime/issues/52529 + From a5b1eac16392b62597676091f1da3c51f2714801 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Thu, 20 May 2021 16:54:08 -0700 Subject: [PATCH 024/115] Resolving ILLink warnings for Microsoft.Extensions.Configuration.Binder (#52795) * Resolving ILLink warnings for Microsoft.Extensions.Configuration.Binder * Addressing PR Feedback --- ...crosoft.Extensions.Configuration.Binder.cs | 25 +++-- ...oft.Extensions.Configuration.Binder.csproj | 3 + .../src/ConfigurationBinder.cs | 95 +++++++++++++++---- .../src/ILLink/ILLink.Suppressions.xml | 53 ----------- ...oft.Extensions.Configuration.Binder.csproj | 3 + .../src/ILLink/ILLink.Suppressions.xml | 6 ++ .../src/LoggerFilterConfigureOptions.cs | 7 +- ...ft.Extensions.Logging.Configuration.csproj | 1 + .../src/ILLink/ILLink.Suppressions.xml | 23 +++++ 9 files changed, 139 insertions(+), 77 deletions(-) delete mode 100644 src/libraries/Microsoft.Extensions.Configuration.Binder/src/ILLink/ILLink.Suppressions.xml create mode 100644 src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs index 4d3c63896503b7..3022b1f9c2ff70 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.cs @@ -13,16 +13,27 @@ public BinderOptions() { } } public static partial class ConfigurationBinder { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Cannot statically analyze the type of instance so its members may be trimmed")] public static void Bind(this Microsoft.Extensions.Configuration.IConfiguration configuration, object instance) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Cannot statically analyze the type of instance so its members may be trimmed")] public static void Bind(this Microsoft.Extensions.Configuration.IConfiguration configuration, object instance, System.Action configureOptions) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Cannot statically analyze the type of instance so its members may be trimmed")] public static void Bind(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key, object instance) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static object Get(this Microsoft.Extensions.Configuration.IConfiguration configuration, System.Type type) { throw null; } - public static object Get(this Microsoft.Extensions.Configuration.IConfiguration configuration, System.Type type, System.Action configureOptions) { throw null; } - public static object GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, System.Type type, string key) { throw null; } - public static object GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, System.Type type, string key, object defaultValue) { throw null; } - public static T GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; } - public static T GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) { throw null; } - public static T Get(this Microsoft.Extensions.Configuration.IConfiguration configuration) { throw null; } - public static T Get(this Microsoft.Extensions.Configuration.IConfiguration configuration, System.Action configureOptions) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static object Get(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, System.Action configureOptions) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static object GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string key) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static object GetValue(this Microsoft.Extensions.Configuration.IConfiguration configuration, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string key, object defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static T GetValue<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static T GetValue<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static T Get<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] + public static T Get<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T>(this Microsoft.Extensions.Configuration.IConfiguration configuration, System.Action configureOptions) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.csproj index 3e14fd0db31e7a..93e90d2109a8de 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/ref/Microsoft.Extensions.Configuration.Binder.csproj @@ -4,6 +4,9 @@ + + + diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index 33aa11eaed985d..b475fb7554fa13 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -15,6 +16,9 @@ namespace Microsoft.Extensions.Configuration public static class ConfigurationBinder { private const BindingFlags DeclaredOnlyLookup = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; + private const string TrimmingWarningMessage = "In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed."; + private const string InstanceGetTypeTrimmingWarningMessage = "Cannot statically analyze the type of instance so its members may be trimmed"; + private const string PropertyTrimmingWarningMessage = "Cannot statically analyze property.PropertyType so its members may be trimmed."; /// /// Attempts to bind the configuration instance to a new instance of type T. @@ -24,7 +28,8 @@ public static class ConfigurationBinder /// The type of the new instance to bind. /// The configuration instance to bind. /// The new instance of T if successful, default(T) otherwise. - public static T Get(this IConfiguration configuration) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static T Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration) => configuration.Get(_ => { }); /// @@ -36,7 +41,8 @@ public static T Get(this IConfiguration configuration) /// The configuration instance to bind. /// Configures the binder options. /// The new instance of T if successful, default(T) otherwise. - public static T Get(this IConfiguration configuration, Action configureOptions) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static T Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, Action configureOptions) { if (configuration == null) { @@ -59,6 +65,7 @@ public static T Get(this IConfiguration configuration, Action /// The configuration instance to bind. /// The type of the new instance to bind. /// The new instance if successful, null otherwise. + [RequiresUnreferencedCode(TrimmingWarningMessage)] public static object Get(this IConfiguration configuration, Type type) => configuration.Get(type, _ => { }); @@ -71,7 +78,12 @@ public static object Get(this IConfiguration configuration, Type type) /// The type of the new instance to bind. /// Configures the binder options. /// The new instance if successful, null otherwise. - public static object Get(this IConfiguration configuration, Type type, Action configureOptions) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static object Get( + this IConfiguration configuration, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, + Action configureOptions) { if (configuration == null) { @@ -89,6 +101,7 @@ public static object Get(this IConfiguration configuration, Type type, ActionThe configuration instance to bind. /// The key of the configuration section to bind. /// The object to bind. + [RequiresUnreferencedCode(InstanceGetTypeTrimmingWarningMessage)] public static void Bind(this IConfiguration configuration, string key, object instance) => configuration.GetSection(key).Bind(instance); @@ -97,6 +110,7 @@ public static void Bind(this IConfiguration configuration, string key, object in /// /// The configuration instance to bind. /// The object to bind. + [RequiresUnreferencedCode(InstanceGetTypeTrimmingWarningMessage)] public static void Bind(this IConfiguration configuration, object instance) => configuration.Bind(instance, o => { }); @@ -106,6 +120,7 @@ public static void Bind(this IConfiguration configuration, object instance) /// The configuration instance to bind. /// The object to bind. /// Configures the binder options. + [RequiresUnreferencedCode(InstanceGetTypeTrimmingWarningMessage)] public static void Bind(this IConfiguration configuration, object instance, Action configureOptions) { if (configuration == null) @@ -128,7 +143,8 @@ public static void Bind(this IConfiguration configuration, object instance, Acti /// The configuration. /// The key of the configuration section's value to convert. /// The converted value. - public static T GetValue(this IConfiguration configuration, string key) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static T GetValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, string key) { return GetValue(configuration, key, default(T)); } @@ -141,7 +157,8 @@ public static T GetValue(this IConfiguration configuration, string key) /// The key of the configuration section's value to convert. /// The default value to use if no value is found. /// The converted value. - public static T GetValue(this IConfiguration configuration, string key, T defaultValue) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static T GetValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, string key, T defaultValue) { return (T)GetValue(configuration, typeof(T), key, defaultValue); } @@ -153,7 +170,12 @@ public static T GetValue(this IConfiguration configuration, string key, T def /// The type to convert the value to. /// The key of the configuration section's value to convert. /// The converted value. - public static object GetValue(this IConfiguration configuration, Type type, string key) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static object GetValue( + this IConfiguration configuration, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, + string key) { return GetValue(configuration, type, key, defaultValue: null); } @@ -166,7 +188,12 @@ public static object GetValue(this IConfiguration configuration, Type type, stri /// The key of the configuration section's value to convert. /// The default value to use if no value is found. /// The converted value. - public static object GetValue(this IConfiguration configuration, Type type, string key, object defaultValue) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + public static object GetValue( + this IConfiguration configuration, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, string key, + object defaultValue) { IConfigurationSection section = configuration.GetSection(key); string value = section.Value; @@ -177,6 +204,7 @@ public static object GetValue(this IConfiguration configuration, Type type, stri return defaultValue; } + [RequiresUnreferencedCode(PropertyTrimmingWarningMessage)] private static void BindNonScalar(this IConfiguration configuration, object instance, BinderOptions options) { if (instance != null) @@ -188,6 +216,7 @@ private static void BindNonScalar(this IConfiguration configuration, object inst } } + [RequiresUnreferencedCode(PropertyTrimmingWarningMessage)] private static void BindProperty(PropertyInfo property, object instance, IConfiguration config, BinderOptions options) { // We don't support set only, non public, or indexer properties @@ -216,6 +245,7 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig } } + [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the object collection in type so its members may be trimmed.")] private static object BindToCollection(Type type, IConfiguration config, BinderOptions options) { Type genericType = typeof(List<>).MakeGenericType(type.GenericTypeArguments[0]); @@ -225,7 +255,11 @@ private static object BindToCollection(Type type, IConfiguration config, BinderO } // Try to create an array/dictionary instance to back various collection interfaces - private static object AttemptBindToCollectionInterfaces(Type type, IConfiguration config, BinderOptions options) + [RequiresUnreferencedCode("In case type is a Dictionary, cannot statically analyze what the element type is of the value objects in the dictionary so its members may be trimmed.")] + private static object AttemptBindToCollectionInterfaces( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, + IConfiguration config, BinderOptions options) { if (!type.IsInterface) { @@ -280,7 +314,11 @@ private static object AttemptBindToCollectionInterfaces(Type type, IConfiguratio return null; } - private static object BindInstance(Type type, object instance, IConfiguration config, BinderOptions options) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + private static object BindInstance( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, + object instance, IConfiguration config, BinderOptions options) { // if binding IConfigurationSection, break early if (type == typeof(IConfigurationSection)) @@ -347,7 +385,7 @@ private static object BindInstance(Type type, object instance, IConfiguration co return instance; } - private static object CreateInstance(Type type) + private static object CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type) { if (type.IsInterface || type.IsAbstract) { @@ -383,7 +421,12 @@ private static object CreateInstance(Type type) } } - private static void BindDictionary(object dictionary, Type dictionaryType, IConfiguration config, BinderOptions options) + [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the value objects in the dictionary so its members may be trimmed.")] + private static void BindDictionary( + object dictionary, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + Type dictionaryType, + IConfiguration config, BinderOptions options) { // IDictionary is guaranteed to have exactly two parameters Type keyType = dictionaryType.GenericTypeArguments[0]; @@ -420,7 +463,12 @@ private static void BindDictionary(object dictionary, Type dictionaryType, IConf } } - private static void BindCollection(object collection, Type collectionType, IConfiguration config, BinderOptions options) + [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the object collection so its members may be trimmed.")] + private static void BindCollection( + object collection, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] + Type collectionType, + IConfiguration config, BinderOptions options) { // ICollection is guaranteed to have exactly one parameter Type itemType = collectionType.GenericTypeArguments[0]; @@ -446,6 +494,7 @@ private static void BindCollection(object collection, Type collectionType, IConf } } + [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the Array so its members may be trimmed.")] private static Array BindArray(Array source, IConfiguration config, BinderOptions options) { IConfigurationSection[] children = config.GetChildren().ToArray(); @@ -481,7 +530,11 @@ private static Array BindArray(Array source, IConfiguration config, BinderOption return newArray; } - private static bool TryConvertValue(Type type, string value, string path, out object result, out Exception error) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + private static bool TryConvertValue( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, + string value, string path, out object result, out Exception error) { error = null; result = null; @@ -530,7 +583,11 @@ private static bool TryConvertValue(Type type, string value, string path, out ob return false; } - private static object ConvertValue(Type type, string value, string path) + [RequiresUnreferencedCode(TrimmingWarningMessage)] + private static object ConvertValue( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type, + string value, string path) { object result; Exception error; @@ -542,7 +599,10 @@ private static object ConvertValue(Type type, string value, string path) return result; } - private static Type FindOpenGenericInterface(Type expected, Type actual) + private static Type FindOpenGenericInterface( + Type expected, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] + Type actual) { if (actual.IsGenericType && actual.GetGenericTypeDefinition() == expected) @@ -562,7 +622,9 @@ private static Type FindOpenGenericInterface(Type expected, Type actual) return null; } - private static IEnumerable GetAllProperties(Type type) + private static IEnumerable GetAllProperties( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + Type type) { var allProperties = new List(); @@ -576,6 +638,7 @@ private static IEnumerable GetAllProperties(Type type) return allProperties; } + [RequiresUnreferencedCode(PropertyTrimmingWarningMessage)] private static object GetPropertyValue(PropertyInfo property, object instance, IConfiguration config, BinderOptions options) { string propertyName = GetPropertyName(property); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index 6009aeac36e38b..00000000000000 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - ILLink - IL2026 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.TryConvertValue(System.Type,System.String,System.String,System.Object@,System.Exception@) - - - ILLink - IL2067 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(System.Type) - - - ILLink - IL2067 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.TryConvertValue(System.Type,System.String,System.String,System.Object@,System.Exception@) - - - ILLink - IL2070 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.BindCollection(System.Object,System.Type,Microsoft.Extensions.Configuration.IConfiguration,Microsoft.Extensions.Configuration.BinderOptions) - - - ILLink - IL2070 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.BindDictionary(System.Object,System.Type,Microsoft.Extensions.Configuration.IConfiguration,Microsoft.Extensions.Configuration.BinderOptions) - - - ILLink - IL2070 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(System.Type) - - - ILLink - IL2070 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.GetAllProperties(System.Type) - - - ILLink - IL2070 - member - M:Microsoft.Extensions.Configuration.ConfigurationBinder.FindOpenGenericInterface(System.Type,System.Type) - - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj index 680611d2971a6b..ec4d33e23eeeef 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/Microsoft.Extensions.Configuration.Binder.csproj @@ -8,6 +8,9 @@ + + + diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.Extensions.Hosting/src/ILLink/ILLink.Suppressions.xml index f98c29e8c56375..47cf8403bb6511 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/Microsoft.Extensions.Hosting/src/ILLink/ILLink.Suppressions.xml @@ -25,5 +25,11 @@ member M:Microsoft.Extensions.DependencyInjection.OptionsBuilderExtensions.ValidateOnStart``1(Microsoft.Extensions.Options.OptionsBuilder{``0}) + + ILLink + IL2026 + member + M:Microsoft.Extensions.Hosting.HostingHostBuilderExtensions.<>c__DisplayClass11_0.<ConfigureDefaults>b__1(Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.Extensions.Configuration.IConfigurationBuilder) + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerFilterConfigureOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerFilterConfigureOptions.cs index bc7c220080d9d9..87948d69e521c9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerFilterConfigureOptions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerFilterConfigureOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; @@ -30,7 +31,7 @@ private void LoadDefaultConfigValues(LoggerFilterOptions options) return; } - options.CaptureScopes = _configuration.GetValue(nameof(options.CaptureScopes), options.CaptureScopes); + options.CaptureScopes = GetCaptureScopesValue(options); foreach (IConfigurationSection configurationSection in _configuration.GetChildren()) { @@ -50,6 +51,10 @@ private void LoadDefaultConfigValues(LoggerFilterOptions options) } } } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "IConfiguration.GetValue is safe when T is a bool.")] + bool GetCaptureScopesValue(LoggerFilterOptions options) => _configuration.GetValue(nameof(options.CaptureScopes), options.CaptureScopes); } private void LoadRules(LoggerFilterOptions options, IConfigurationSection configurationSection, string logger) diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj index e936b26ac1e4ae..387ecfe46af42c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj @@ -9,6 +9,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml new file mode 100644 index 00000000000000..f9ff691945bc56 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Options.ConfigurationExtensions/src/ILLink/ILLink.Suppressions.xml @@ -0,0 +1,23 @@ + + + + + ILLink + IL2026 + member + M:Microsoft.Extensions.DependencyInjection.OptionsBuilderConfigurationExtensions.<>c__DisplayClass2_0`1.<BindConfiguration>b__0(`0,Microsoft.Extensions.Configuration.IConfiguration) + + + ILLink + IL2026 + member + M:Microsoft.Extensions.Options.ConfigureFromConfigurationOptions`1.<>c__DisplayClass0_0.<#ctor>b__0(`0) + + + ILLink + IL2026 + member + M:Microsoft.Extensions.Options.NamedConfigureFromConfigurationOptions`1.<>c__DisplayClass1_0.<#ctor>b__0(`0) + + + \ No newline at end of file From 9487aad8983f835fd1f4867b6909af7bb82ca171 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Fri, 21 May 2021 04:45:15 +0200 Subject: [PATCH 025/115] Fix DataCommonEventSource EnterScope (#53043) --- .../src/System/Data/Common/DataCommonEventSource.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs b/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs index 8150768023a940..0144c53cf75220 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/DataCommonEventSource.cs @@ -66,18 +66,21 @@ internal void Trace(string format, T0 arg0, T1 arg1, Trace(string.Format(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6)); } - [Event(EnterScopeId, Level = EventLevel.Verbose)] + [NonEvent] internal long EnterScope(string message) { long scopeId = 0; if (Log.IsEnabled()) { scopeId = Interlocked.Increment(ref s_nextScopeId); - WriteEvent(EnterScopeId, scopeId, message); + EnterScope(scopeId, message); } return scopeId; } + [Event(EnterScopeId, Level = EventLevel.Verbose)] + private void EnterScope(long scopeId, string message) => WriteEvent(EnterScopeId, scopeId, message); + [NonEvent] internal long EnterScope(string format, T1 arg1) => Log.IsEnabled() ? EnterScope(string.Format(format, arg1)) : 0; From f48e281bf4d3df76ea761b5f478329b8e3f60e4f Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Thu, 20 May 2021 20:27:02 -0700 Subject: [PATCH 026/115] Delete an unnecessary pessimization for x86. (#52803) --- src/coreclr/jit/compiler.hpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index b0f8d0d0353a99..ff0f0dee54ba06 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3953,17 +3953,13 @@ inline Compiler::lvaPromotionType Compiler::lvaGetPromotionType(const LclVarDsc* return PROMOTION_TYPE_DEPENDENT; } - // We have a parameter that could be enregistered - CLANG_FORMAT_COMMENT_ANCHOR; - -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) - - // The struct parameter is a register candidate - return PROMOTION_TYPE_INDEPENDENT; -#else - // The struct parameter is not enregistered +// We have a parameter that could be enregistered +#if defined(TARGET_ARM) + // TODO-Cleanup: return INDEPENDENT for arm32. return PROMOTION_TYPE_DEPENDENT; -#endif +#else // !TARGET_ARM + return PROMOTION_TYPE_INDEPENDENT; +#endif // !TARGET_ARM } /***************************************************************************** From 00dcb2ce08a8a69c4fe897066dd621350b1bbb3f Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Fri, 21 May 2021 06:48:30 +0300 Subject: [PATCH 027/115] Add a missing end of line to JITDUMP in lclmorph.cpp (#53028) --- src/coreclr/jit/lclmorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 9e49f30bd70bda..bfa47db004ab6a 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -641,7 +641,7 @@ class LocalAddressVisitor final : public GenTreeVisitor if (Compiler::gtHasCallOnStack(&m_ancestors)) { varDsc->lvQuirkToLong = true; - JITDUMP("Adding a quirk for the storage size of V%02u of type %s", val.LclNum(), + JITDUMP("Adding a quirk for the storage size of V%02u of type %s\n", val.LclNum(), varTypeName(varDsc->TypeGet())); } } From a808b6a9b703d84e49b48fb40d2e5e545a086085 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Thu, 20 May 2021 23:07:39 -0700 Subject: [PATCH 028/115] Add UnmanagedCallConvAttribute (#52869) --- src/coreclr/inc/corcompile.h | 3 + .../Common/JitInterface/CallConvHelper.cs | 42 ++ .../tools/Common/JitInterface/CorInfoImpl.cs | 53 +-- .../Compiler/MethodExtensions.cs | 40 +- .../ILCompiler.ReadyToRun.csproj | 3 + src/coreclr/vm/callconvbuilder.cpp | 68 ++- src/coreclr/vm/callconvbuilder.hpp | 14 + src/coreclr/vm/compile.cpp | 8 + src/coreclr/vm/compile.h | 2 + src/coreclr/vm/dllimport.cpp | 203 +++++++-- src/coreclr/vm/dllimport.h | 42 +- src/coreclr/vm/jitinterface.cpp | 15 +- src/coreclr/vm/method.cpp | 46 +- src/coreclr/vm/method.hpp | 1 + src/coreclr/vm/wellknownattributes.h | 3 + src/coreclr/zap/zapinfo.cpp | 7 + .../System.Private.CoreLib.Shared.projitems | 1 + .../UnmanagedCallConvAttribute.cs | 25 ++ .../ref/System.Runtime.InteropServices.cs | 6 + src/mono/mono/metadata/marshal.c | 108 ++++- src/tests/Interop/CMakeLists.txt | 1 + .../SuppressGCTransitionTest.cs | 55 +-- .../SuppressGCTransitionTest.csproj | 1 + .../Interop/UnmanagedCallConv/CMakeLists.txt | 10 + .../Interop/UnmanagedCallConv/PInvokesCS.cs | 232 ++++++++++ .../Interop/UnmanagedCallConv/PInvokesIL.il | 151 +++++++ .../UnmanagedCallConv/PInvokesIL.ilproj | 8 + .../UnmanagedCallConvNative.cpp | 42 ++ .../UnmanagedCallConvTest.cs | 414 ++++++++++++++++++ .../UnmanagedCallConvTest.csproj | 16 + src/tests/Interop/common/CheckGCMode.cs | 37 ++ src/tests/issues.targets | 3 + 32 files changed, 1523 insertions(+), 137 deletions(-) create mode 100644 src/coreclr/tools/Common/JitInterface/CallConvHelper.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallConvAttribute.cs create mode 100644 src/tests/Interop/UnmanagedCallConv/CMakeLists.txt create mode 100644 src/tests/Interop/UnmanagedCallConv/PInvokesCS.cs create mode 100644 src/tests/Interop/UnmanagedCallConv/PInvokesIL.il create mode 100644 src/tests/Interop/UnmanagedCallConv/PInvokesIL.ilproj create mode 100644 src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvNative.cpp create mode 100644 src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.cs create mode 100644 src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.csproj create mode 100644 src/tests/Interop/common/CheckGCMode.cs diff --git a/src/coreclr/inc/corcompile.h b/src/coreclr/inc/corcompile.h index 8226fba3d8f0a0..2fb5d6fabc7f96 100644 --- a/src/coreclr/inc/corcompile.h +++ b/src/coreclr/inc/corcompile.h @@ -1713,6 +1713,9 @@ class ICorCompileInfo // to 1 on the clone. The buffer has to be large enough to hold the stub object and the code virtual HRESULT GetStubClone(void *pStub, BYTE *pBuffer, DWORD dwBufferSize) = 0; + // true if the method has [UnmanagedCallConvAttribute] + virtual BOOL IsUnmanagedCallConvMethod(CORINFO_METHOD_HANDLE handle) = 0; + // true if the method has [UnmanagedCallersOnlyAttribute] virtual BOOL IsUnmanagedCallersOnlyMethod(CORINFO_METHOD_HANDLE handle) = 0; diff --git a/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs b/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs new file mode 100644 index 00000000000000..ad92b5b36e34c1 --- /dev/null +++ b/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Reflection.Metadata; + +using Internal.TypeSystem; + +namespace Internal.JitInterface +{ + internal static unsafe class CallConvHelper + { + internal static IEnumerable EnumerateCallConvsFromAttribute(CustomAttributeValue attributeWithCallConvsArray) + { + ImmutableArray> callConvArray = default; + foreach (var arg in attributeWithCallConvsArray.NamedArguments) + { + if (arg.Name == "CallConvs") + { + callConvArray = (ImmutableArray>)arg.Value; + } + } + + // No calling convention was specified in the attribute + if (callConvArray.IsDefault) + yield break; + + foreach (CustomAttributeTypedArgument type in callConvArray) + { + if (!(type.Value is DefType defType)) + continue; + + if (defType.Namespace != "System.Runtime.CompilerServices") + continue; + + yield return defType; + } + } + } +} diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 65137fad8c029d..be2c200f2d63a6 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -637,41 +637,27 @@ private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, bool } } - private CorInfoCallConvExtension GetUnmanagedCallingConventionFromAttribute(CustomAttributeValue unmanagedCallersOnlyAttribute) + private CorInfoCallConvExtension GetUnmanagedCallingConventionFromAttribute(CustomAttributeValue attributeWithCallConvsArray, out bool suppressGCTransition) { + suppressGCTransition = false; CorInfoCallConvExtension callConv = (CorInfoCallConvExtension)PlatformDefaultUnmanagedCallingConvention(); - ImmutableArray> callConvArray = default; - foreach (var arg in unmanagedCallersOnlyAttribute.NamedArguments) - { - if (arg.Name == "CallConvs") - { - callConvArray = (ImmutableArray>)arg.Value; - } - } - - // No calling convention was specified in the attribute, so return the default. - if (callConvArray.IsDefault) - { - return callConv; - } - bool found = false; bool memberFunctionVariant = false; - foreach (CustomAttributeTypedArgument type in callConvArray) + foreach (DefType defType in CallConvHelper.EnumerateCallConvsFromAttribute(attributeWithCallConvsArray)) { - if (!(type.Value is DefType defType)) - continue; - - if (defType.Namespace != "System.Runtime.CompilerServices") - continue; - if (defType.Name == "CallConvMemberFunction") { memberFunctionVariant = true; continue; } + if (defType.Name == "CallConvSuppressGCTransition") + { + suppressGCTransition = true; + continue; + } + CorInfoCallConvExtension? callConvLocal = GetCallingConventionForCallConvType(defType); if (callConvLocal.HasValue) @@ -1258,11 +1244,28 @@ private CorInfoCallConvExtension GetUnmanagedCallConv(MethodDesc methodDesc, out { if (methodDesc.IsPInvoke) { - suppressGCTransition = methodDesc.IsSuppressGCTransition(); + suppressGCTransition = methodDesc.HasSuppressGCTransitionAttribute(); MethodSignatureFlags unmanagedCallConv = methodDesc.GetPInvokeMethodMetadata().Flags.UnmanagedCallingConvention; if (unmanagedCallConv == MethodSignatureFlags.None) + { + MethodDesc methodDescLocal = methodDesc; + if (methodDesc is IL.Stubs.PInvokeTargetNativeMethod rawPInvoke) + { + methodDescLocal = rawPInvoke.Target; + } + + CustomAttributeValue? unmanagedCallConvAttribute = ((EcmaMethod)methodDescLocal).GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute"); + if (unmanagedCallConvAttribute != null) + { + bool suppressGCTransitionLocal; + CorInfoCallConvExtension callConvFromAttribute = GetUnmanagedCallingConventionFromAttribute(unmanagedCallConvAttribute.Value, out suppressGCTransitionLocal); + suppressGCTransition |= suppressGCTransitionLocal; + return callConvFromAttribute; + } + unmanagedCallConv = PlatformDefaultUnmanagedCallingConvention(); + } // Verify that it is safe to convert MethodSignatureFlags.UnmanagedCallingConvention to CorInfoCallConvExtension via a simple cast Debug.Assert((int)CorInfoCallConvExtension.C == (int)MethodSignatureFlags.UnmanagedCallingConventionCdecl); @@ -1275,7 +1278,7 @@ private CorInfoCallConvExtension GetUnmanagedCallConv(MethodDesc methodDesc, out { Debug.Assert(methodDesc.IsUnmanagedCallersOnly); CustomAttributeValue unmanagedCallersOnlyAttribute = ((EcmaMethod)methodDesc).GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute").Value; - return GetUnmanagedCallingConventionFromAttribute(unmanagedCallersOnlyAttribute); + return GetUnmanagedCallingConventionFromAttribute(unmanagedCallersOnlyAttribute, out _); } } return GetUnmanagedCallConv(methodDesc.Signature, out suppressGCTransition); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs index eabc035af09268..f9b363778a6b04 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; using Debug = System.Diagnostics.Debug; @@ -21,18 +22,53 @@ public static bool IsRawPInvoke(this MethodDesc method) } /// - /// Gets a value indicating whether GC transition should be suppressed on the given p/invoke. + /// Gets a value indicating whether the method has the SuppressGCTransition attribute /// - public static bool IsSuppressGCTransition(this MethodDesc method) + public static bool HasSuppressGCTransitionAttribute(this MethodDesc method) { Debug.Assert(method.IsPInvoke); if (method is Internal.IL.Stubs.PInvokeTargetNativeMethod rawPinvoke) method = rawPinvoke.Target; + // Check SuppressGCTransition attribute return method.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute"); } + /// + /// Gets a value indicating whether GC transition should be suppressed on the given p/invoke. + /// + public static bool IsSuppressGCTransition(this MethodDesc method) + { + Debug.Assert(method.IsPInvoke); + + // Check SuppressGCTransition attribute + if (method.HasSuppressGCTransitionAttribute()) + return true; + + MethodSignatureFlags unmanagedCallConv = method.GetPInvokeMethodMetadata().Flags.UnmanagedCallingConvention; + if (unmanagedCallConv != MethodSignatureFlags.None) + return false; + + if (!(method is Internal.TypeSystem.Ecma.EcmaMethod ecmaMethod)) + return false; + + // Check UnmanagedCallConv attribute + System.Reflection.Metadata.CustomAttributeValue? unmanagedCallConvAttribute = ecmaMethod.GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute"); + if (unmanagedCallConvAttribute == null) + return false; + + foreach (DefType defType in Internal.JitInterface.CallConvHelper.EnumerateCallConvsFromAttribute(unmanagedCallConvAttribute.Value)) + { + if (defType.Name == "CallConvSuppressGCTransition") + { + return true; + } + } + + return false; + } + /// /// Return true when the method is marked as non-versionable. Non-versionable methods /// may be freely inlined into ReadyToRun images even when they don't reside in the diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 8c387fa3c980a1..6299418227bde3 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -248,6 +248,9 @@ JitInterface\TypeString.cs + + JitInterface\CallConvHelper.cs + JitInterface\CorInfoBase.cs diff --git a/src/coreclr/vm/callconvbuilder.cpp b/src/coreclr/vm/callconvbuilder.cpp index 8146289c7a667e..b56cd1695e4cb7 100644 --- a/src/coreclr/vm/callconvbuilder.cpp +++ b/src/coreclr/vm/callconvbuilder.cpp @@ -387,32 +387,86 @@ HRESULT CallConv::TryGetUnmanagedCallingConventionFromModOpt( #ifndef CROSSGEN_COMPILE namespace { - bool TryGetCallingConventionFromTypeArray(_In_ CaValue* arrayOfTypes, _Out_ CorInfoCallConvExtension* callConv) + bool TryGetCallingConventionFromTypeArray(_In_ CaValue* arrayOfTypes, _Inout_ CallConvBuilder* builder) { CONTRACTL { STANDARD_VM_CHECK; PRECONDITION(arrayOfTypes != NULL); - PRECONDITION(callConv != NULL); + PRECONDITION(builder != NULL); } CONTRACTL_END - CallConvBuilder builder; for (ULONG i = 0; i < arrayOfTypes->arr.length; i++) { CaValue& typeNameValue = arrayOfTypes->arr[i]; - if (!builder.AddFullyQualifiedTypeName(typeNameValue.str.cbStr, typeNameValue.str.pStr)) + if (!builder->AddFullyQualifiedTypeName(typeNameValue.str.cbStr, typeNameValue.str.pStr)) { // We found a second base calling convention. return false; } } - *callConv = builder.GetCurrentCallConv(); return true; } } +HRESULT CallConv::TryGetCallingConventionFromUnmanagedCallConv( + _In_ MethodDesc* pMD, + _Inout_ CallConvBuilder* builder, + _Out_opt_ UINT* errorResID) +{ + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(pMD != NULL); + PRECONDITION(builder != NULL); + } + CONTRACTL_END; + + BYTE *pData = NULL; + LONG cData = 0; + + // System.Runtime.InteropServices.UnmanagedCallConvAttribute + HRESULT hr = pMD->GetCustomAttribute(WellKnownAttribute::UnmanagedCallConv, (const VOID **)(&pData), (ULONG *)&cData); + if (hr != S_OK) // GetCustomAttribute returns S_FALSE if the method does not have the attribute + return hr; + + _ASSERTE(cData > 0); + CustomAttributeParser ca(pData, cData); + + // CallConvs named argument + CaTypeCtor callConvsType(SERIALIZATION_TYPE_SZARRAY, SERIALIZATION_TYPE_TYPE, SERIALIZATION_TYPE_UNDEFINED, NULL, 0); + CaNamedArg callConvsArg; + callConvsArg.Init("CallConvs", SERIALIZATION_TYPE_SZARRAY, callConvsType); + + InlineFactory, 4> caValueArrayFactory; + DomainAssembly* domainAssembly = pMD->GetLoaderModule()->GetDomainAssembly(); + IfFailThrow(Attribute::ParseAttributeArgumentValues( + pData, + cData, + &caValueArrayFactory, + NULL, + 0, + &callConvsArg, + 1, + domainAssembly)); + + // Value isn't defined + if (callConvsArg.val.type.tag == SERIALIZATION_TYPE_UNDEFINED) + return S_FALSE; + + if (!TryGetCallingConventionFromTypeArray(&callConvsArg.val, builder)) + { + if (errorResID != NULL) + *errorResID = IDS_EE_MULTIPLE_CALLCONV_UNSUPPORTED; + + return COR_E_INVALIDPROGRAM; + } + + return S_OK; +} + bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc* pMD, _Out_ CorInfoCallConvExtension* pCallConv) { STANDARD_VM_CONTRACT; @@ -484,12 +538,14 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc* } else { - if (!TryGetCallingConventionFromTypeArray(&namedArgs[0].val, &callConvLocal)) + CallConvBuilder builder; + if (!TryGetCallingConventionFromTypeArray(&namedArgs[0].val, &builder)) { // We found a second base calling convention. return false; } + callConvLocal = builder.GetCurrentCallConv(); if (callConvLocal == CallConvBuilder::UnsetValue) { callConvLocal = CallConv::GetDefaultUnmanagedCallingConvention(); diff --git a/src/coreclr/vm/callconvbuilder.hpp b/src/coreclr/vm/callconvbuilder.hpp index 6f479012ac7cc9..6f197d92029dd4 100644 --- a/src/coreclr/vm/callconvbuilder.hpp +++ b/src/coreclr/vm/callconvbuilder.hpp @@ -80,6 +80,20 @@ namespace CallConv _Inout_ CallConvBuilder *builder, _Out_ UINT *errorResID); + //------------------------------------------------------------------------- + // Gets the calling convention from the UnmanagedCallConv attribute + // + // Returns: + // S_OK - No errors + // S_FALSE - UnmanagedCallConv or UnmanagedCallConv.CallConvs not specified + // COR_E_INVALIDPROGRAM - Program is considered invalid (more + // than one calling convention specified) + //------------------------------------------------------------------------- + HRESULT TryGetCallingConventionFromUnmanagedCallConv( + _In_ MethodDesc* pMD, + _Inout_ CallConvBuilder* builder, + _Out_opt_ UINT* errorResID); + //------------------------------------------------------------------------- // Gets the unmanaged calling convention from the UnmanagedCallersOnly attribute. // diff --git a/src/coreclr/vm/compile.cpp b/src/coreclr/vm/compile.cpp index 4edd220728a0ef..486844c7f79a48 100644 --- a/src/coreclr/vm/compile.cpp +++ b/src/coreclr/vm/compile.cpp @@ -968,6 +968,14 @@ BOOL CEEPreloader::DoesMethodNeedRestoringBeforePrestubIsRun( return FALSE; } +BOOL CEECompileInfo::IsUnmanagedCallConvMethod(CORINFO_METHOD_HANDLE handle) +{ + WRAPPER_NO_CONTRACT; + + MethodDesc * pMethod = GetMethod(handle); + return pMethod->HasUnmanagedCallConvAttribute(); +} + BOOL CEECompileInfo::IsUnmanagedCallersOnlyMethod(CORINFO_METHOD_HANDLE handle) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/compile.h b/src/coreclr/vm/compile.h index a04e19307f3e9b..6280497d13cba7 100644 --- a/src/coreclr/vm/compile.h +++ b/src/coreclr/vm/compile.h @@ -280,6 +280,8 @@ class CEECompileInfo : public ICorCompileInfo BOOL IsEmptyString(mdString token, CORINFO_MODULE_HANDLE module); + BOOL IsUnmanagedCallConvMethod(CORINFO_METHOD_HANDLE handle); + BOOL IsUnmanagedCallersOnlyMethod(CORINFO_METHOD_HANDLE handle); BOOL IsCachingOfInliningHintsEnabled() diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 1f7163fc914ce6..925e1f7de522f0 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -1371,7 +1371,8 @@ class PInvoke_ILStubState : public ILStubState { dwStubFlags |= NDIRECTSTUB_FL_STUB_HAS_THIS; } - if (TargetSuppressGCTransition(dwStubFlags, pTargetMD)) + if ((dwStubFlags & NDIRECTSTUB_FL_SUPPRESSGCTRANSITION) == 0 + && TargetSuppressGCTransition(dwStubFlags, pTargetMD)) { dwStubFlags |= NDIRECTSTUB_FL_SUPPRESSGCTRANSITION; } @@ -2785,7 +2786,7 @@ void PInvokeStaticSigInfo::DllImportInit( mdModuleRef modref = mdModuleRefNil; if (FAILED(pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, ppEntryPointName, &modref))) { - InitCallConv(CallConvWinApiSentinel, pMD->IsVarArg()); + InitCallConv(CallConvWinApiSentinel, pMD); return; } @@ -2802,7 +2803,7 @@ void PInvokeStaticSigInfo::DllImportInit( } // m_callConv - InitCallConv(GetCallConvValueForPInvokeCallConv((CorPinvokeMap)(mappingFlags & pmCallConvMask)), pMD->IsVarArg()); + InitCallConv(GetCallConvValueForPInvokeCallConv((CorPinvokeMap)(mappingFlags & pmCallConvMask)), pMD); // m_bestFit CorPinvokeMap bestFitMask = (CorPinvokeMap)(mappingFlags & pmBestFitMask); @@ -2958,6 +2959,46 @@ CorInfoCallConvExtension GetDefaultCallConv(BOOL bIsVarArg) return bIsVarArg ? CorInfoCallConvExtension::C : CallConv::GetDefaultUnmanagedCallingConvention(); } +void PInvokeStaticSigInfo::InitCallConv(_In_ CorInfoCallConvExtension callConv, _In_ MethodDesc *pMD) +{ + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(pMD != NULL); + } + CONTRACTL_END; + +#ifdef CROSSGEN_COMPILE + _ASSERTE_MSG(!pMD->HasUnmanagedCallConvAttribute(), "UnmanagedCallConv methods are not supported in crossgen and should be rejected before getting here."); +#else + // If the calling convention has not been determined yet, check the UnmanagedCallConv attribute + if (callConv == CallConvWinApiSentinel) + { + CallConvBuilder builder; + UINT errorResID = 0; + + // System.Runtime.InteropServices.UnmanagedCallConvAttribute + HRESULT hr = CallConv::TryGetCallingConventionFromUnmanagedCallConv(pMD, &builder, &errorResID); + if (FAILED(hr)) + { + // Use a generic error message for P/Invokes or UnmanagedFunction if no specific one was provided + ThrowError(errorResID == 0 ? IDS_EE_NDIRECT_BADNATL : errorResID); + } + + if (hr == S_OK) + { + callConv = builder.GetCurrentCallConv(); + if (builder.IsCurrentCallConvModSet(CallConvBuilder::CALL_CONV_MOD_SUPPRESSGCTRANSITION)) + { + SetShouldSuppressGCTransition(TRUE); + } + } + } +#endif // CROSSGEN_COMPILE + + InitCallConv(callConv, pMD->IsVarArg()); +} + void PInvokeStaticSigInfo::InitCallConv(CorInfoCallConvExtension callConv, BOOL bIsVarArg) { STANDARD_VM_CONTRACT; @@ -3007,62 +3048,172 @@ void PInvokeStaticSigInfo::ThrowError(WORD errorResourceID) COMPlusThrow(kTypeLoadException, errorResourceID); } -CorInfoCallConvExtension NDirect::GetCallingConvention_IgnoreErrors(_In_ MethodDesc* pMD) +namespace +{ + bool HasSuppressGCTransitionAttribute(_In_ MethodDesc* pMD) + { + LIMITED_METHOD_CONTRACT; + + HRESULT hr = pMD->GetCustomAttribute( + WellKnownAttribute::SuppressGCTransition, + nullptr, + nullptr); + return hr == S_OK; + } + + bool TryGetCallingConventionFromPInvokeMetadata(_In_ MethodDesc* pMD, _Out_ CorInfoCallConvExtension* callConv) + { + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(pMD != NULL); + PRECONDITION(pMD->IsNDirect()); + PRECONDITION(callConv != NULL); + } + CONTRACTL_END; + + CorInfoCallConvExtension callConvLocal; + IMDInternalImport* pInternalImport = pMD->GetMDImport(); + CorPinvokeMap mappingFlags = pmMaxValue; + HRESULT hr = pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, NULL /*pszImportName*/, NULL /*pmrImportDLL*/); + if (FAILED(hr)) + return false; + + callConvLocal = GetCallConvValueForPInvokeCallConv((CorPinvokeMap)(mappingFlags & pmCallConvMask)); + if (callConvLocal != CallConvWinApiSentinel) + { + *callConv = callConvLocal; + return true; + } + + return false; + } + + bool TryGetCallingConventionFromUnmanagedFunctionPointer(_In_ MethodTable* pMT, _Out_ CorInfoCallConvExtension* callConv) + { + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(pMT != NULL); + PRECONDITION(pMT->IsDelegate()); + PRECONDITION(callConv != NULL); + } + CONTRACTL_END; + + BYTE* pData = NULL; + LONG cData = 0; + HRESULT hr = pMT->GetCustomAttribute(WellKnownAttribute::UnmanagedFunctionPointer, (const VOID **)(&pData), (ULONG *)&cData); + if (hr != S_OK) + return false; + + _ASSERTE(cData > 0); + CustomAttributeParser ca(pData, cData); + CorInfoCallConvExtension callConvLocal; + hr = ParseCallingConventionFromAttributeConstructor(ca, &callConvLocal); + if (SUCCEEDED(hr) && callConvLocal != CallConvWinApiSentinel) + { + *callConv = callConvLocal; + return true; + } + + return false; + } +} + +void NDirect::GetCallingConvention_IgnoreErrors(_In_ MethodDesc* pMD, _Out_opt_ CorInfoCallConvExtension* callConv, _Out_opt_ bool* suppressGCTransition) { CONTRACTL { STANDARD_VM_CHECK; PRECONDITION(pMD != NULL); PRECONDITION(pMD->IsNDirect()); + PRECONDITION(callConv != NULL || suppressGCTransition != NULL); } CONTRACTL_END; + if (suppressGCTransition != NULL) + { + *suppressGCTransition = HasSuppressGCTransitionAttribute(pMD); + + // Caller only cares about SuppressGCTransition and we have already determined it is true. + if (callConv == NULL && *suppressGCTransition) + return; + } + // This method intentionally does not check that any calling convention specified through // attributes match that in the signature. We just return once a non-sentinel calling // convention is found. - CorInfoCallConvExtension callConv; + CorInfoCallConvExtension callConvLocal; MethodTable* pMT = pMD->GetMethodTable(); if (pMT->IsDelegate()) { + if (callConv == NULL) + return; + // System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute - BYTE* pData = NULL; - LONG cData = 0; - HRESULT hr = pMT->GetCustomAttribute(WellKnownAttribute::UnmanagedFunctionPointer, (const VOID **)(&pData), (ULONG *)&cData); - if (hr == S_OK) + if (TryGetCallingConventionFromUnmanagedFunctionPointer(pMT, &callConvLocal)) { - _ASSERTE(cData > 0); - CustomAttributeParser ca(pData, cData); - hr = ParseCallingConventionFromAttributeConstructor(ca, &callConv); - if (SUCCEEDED(hr) && callConv != CallConvWinApiSentinel) - return callConv; + *callConv = callConvLocal; + return; } } else { // P/Invoke metadata - IMDInternalImport* pInternalImport = pMD->GetMDImport(); - CorPinvokeMap mappingFlags = pmMaxValue; - HRESULT hr = pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, NULL /*pszImportName*/, NULL /*pmrImportDLL*/); - if (SUCCEEDED(hr)) + if (TryGetCallingConventionFromPInvokeMetadata(pMD, &callConvLocal)) { - callConv = GetCallConvValueForPInvokeCallConv((CorPinvokeMap)(mappingFlags & pmCallConvMask)); - if (callConv != CallConvWinApiSentinel) - return callConv; + if (callConv != NULL) + *callConv = callConvLocal; + + return; } + +#ifdef CROSSGEN_COMPILE + _ASSERTE_MSG(!pMD->HasUnmanagedCallConvAttribute(), "UnmanagedCallConv methods are not supported in crossgen and should be rejected before getting here."); +#else + // System.Runtime.InteropServices.UnmanagedCallConvAttribute + CallConvBuilder unmanagedCallConvBuilder; + if (CallConv::TryGetCallingConventionFromUnmanagedCallConv(pMD, &unmanagedCallConvBuilder, NULL /*errorResID*/) == S_OK) + { + if (suppressGCTransition != NULL) + { + (*suppressGCTransition) |= unmanagedCallConvBuilder.IsCurrentCallConvModSet(CallConvBuilder::CALL_CONV_MOD_SUPPRESSGCTRANSITION); + } + + callConvLocal = unmanagedCallConvBuilder.GetCurrentCallConv(); + if (callConvLocal != CallConvWinApiSentinel) + { + if (callConv != NULL) + *callConv = callConvLocal; + + return; + } + } +#endif // CROSSGEN_COMPILE + + // Caller only cares about SuppressGCTransition - we have checked SuppressGCTransition and UnmanagedCallConv + if (callConv == NULL) + return; } + _ASSERTE(callConv != NULL); + const Signature& sig = pMD->GetSignature(); Module* module = pMD->GetModule(); - // modopts CallConvBuilder builder; UINT errorResID; + + // modopts (void)CallConv::TryGetUnmanagedCallingConventionFromModOpt(GetScopeHandle(module), sig.GetRawSig(), sig.GetRawSigLen(), &builder, &errorResID); - callConv = builder.GetCurrentCallConv(); - if (callConv != CallConvWinApiSentinel) - return callConv; + callConvLocal = builder.GetCurrentCallConv(); + if (callConvLocal != CallConvWinApiSentinel) + { + *callConv = callConvLocal; + return; + } - return GetDefaultCallConv(pMD->IsVarArg()); + *callConv = GetDefaultCallConv(pMD->IsVarArg()); } //--------------------------------------------------------- diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h index c55ce9f7f4030c..4e1d050091c33d 100644 --- a/src/coreclr/vm/dllimport.h +++ b/src/coreclr/vm/dllimport.h @@ -56,14 +56,15 @@ struct StubSigDesc class NDirect { public: - // Get the calling convention for a method by checking: + // Get the calling convention and whether to suppress GC transition for a method by checking: + // - SuppressGCTransition attribute // - For delegates: UnmanagedFunctionPointer attribute // - For non-delegates: P/Invoke metadata // - Any modopts encoded in the method signature // If no calling convention is specified, the default calling convention is returned // This function ignores any errors when reading attributes/metadata, treating them as // if no calling convention was specified through that mechanism. - static CorInfoCallConvExtension GetCallingConvention_IgnoreErrors(_In_ MethodDesc* pMD); + static void GetCallingConvention_IgnoreErrors(_In_ MethodDesc* pMD, _Out_opt_ CorInfoCallConvExtension* callConv, _Out_opt_ bool* suppressGCTransition); //--------------------------------------------------------- // Does a class or method have a NAT_L CustomAttribute? @@ -319,16 +320,17 @@ struct PInvokeStaticSigInfo PInvokeStaticSigInfo(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8* pLibName, _Outptr_opt_ LPCUTF8* pEntryPointName); private: - void ThrowError(WORD errorResourceID); - void InitCallConv(CorInfoCallConvExtension callConv, BOOL bIsVarArg); + void ThrowError(_In_ WORD errorResourceID); + void InitCallConv(_In_ CorInfoCallConvExtension callConv, _In_ MethodDesc* pMD); + void InitCallConv(_In_ CorInfoCallConvExtension callConv, _In_ BOOL bIsVarArg); void DllImportInit(_In_ MethodDesc* pMD, _Outptr_opt_ LPCUTF8* pLibName, _Outptr_opt_ LPCUTF8* pEntryPointName); - void PreInit(Module* pModule, MethodTable *pClass); - void PreInit(MethodDesc* pMD); + void PreInit(_In_ Module* pModule, _In_ MethodTable* pClass); + void PreInit(_In_ MethodDesc* pMD); private: enum { - PINVOKE_STATIC_SIGINFO_IS_STATIC = 0x0001, + PINVOKE_STATIC_SIGINFO_SUPPRESS_GC_TRANSITION = 0x0001, PINVOKE_STATIC_SIGINFO_THROW_ON_UNMAPPABLE_CHAR = 0x0002, PINVOKE_STATIC_SIGINFO_BEST_FIT = 0x0004, @@ -346,9 +348,20 @@ struct PInvokeStaticSigInfo DWORD GetStubFlags() const { WRAPPER_NO_CONTRACT; - return (GetThrowOnUnmappableChar() ? NDIRECTSTUB_FL_THROWONUNMAPPABLECHAR : 0) | - (GetBestFitMapping() ? NDIRECTSTUB_FL_BESTFIT : 0) | - (IsDelegateInterop() ? NDIRECTSTUB_FL_DELEGATE : 0); + DWORD flags = 0; + if (GetThrowOnUnmappableChar()) + flags |= NDIRECTSTUB_FL_THROWONUNMAPPABLECHAR; + + if (GetBestFitMapping()) + flags |= NDIRECTSTUB_FL_BESTFIT; + + if (IsDelegateInterop()) + flags |= NDIRECTSTUB_FL_DELEGATE; + + if (ShouldSuppressGCTransition()) + flags |= NDIRECTSTUB_FL_SUPPRESSGCTRANSITION; + + return flags; } Module* GetModule() const { LIMITED_METHOD_CONTRACT; return m_pModule; } BOOL IsDelegateInterop() const { LIMITED_METHOD_CONTRACT; return m_wFlags & PINVOKE_STATIC_SIGINFO_IS_DELEGATE_INTEROP; } @@ -360,6 +373,7 @@ struct PInvokeStaticSigInfo public: // private getters BOOL GetThrowOnUnmappableChar() const { LIMITED_METHOD_CONTRACT; return m_wFlags & PINVOKE_STATIC_SIGINFO_THROW_ON_UNMAPPABLE_CHAR; } BOOL GetBestFitMapping() const { LIMITED_METHOD_CONTRACT; return m_wFlags & PINVOKE_STATIC_SIGINFO_BEST_FIT; } + BOOL ShouldSuppressGCTransition() const { LIMITED_METHOD_CONTRACT; return m_wFlags & PINVOKE_STATIC_SIGINFO_SUPPRESS_GC_TRANSITION; } private: // setters void SetThrowOnUnmappableChar(BOOL throwOnUnmappableChar) @@ -378,6 +392,14 @@ struct PInvokeStaticSigInfo else m_wFlags &= ~PINVOKE_STATIC_SIGINFO_BEST_FIT; } + void SetShouldSuppressGCTransition(BOOL suppress) + { + LIMITED_METHOD_CONTRACT; + if (suppress) + m_wFlags |= PINVOKE_STATIC_SIGINFO_SUPPRESS_GC_TRANSITION; + else + m_wFlags &= ~PINVOKE_STATIC_SIGINFO_SUPPRESS_GC_TRANSITION; + } void SetIsDelegateInterop(BOOL delegateInterop) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index a8b5981d5adf11..e98a43973ce757 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -5368,7 +5368,7 @@ void CEEInfo::getCallInfo( // of shared generic code calling a shared generic implementation method, which should be rare. // // An alternative design would be to add a new generic dictionary entry kind to hold the MethodDesc - // of the constrained target instead, and use that in some circumstances; however, implementation of + // of the constrained target instead, and use that in some circumstances; however, implementation of // that design requires refactoring variuos parts of the JIT interface as well as // TryResolveConstraintMethodApprox. In particular we would need to be abled to embed a constrained lookup // via EmbedGenericHandle, as well as decide in TryResolveConstraintMethodApprox if the call can be made @@ -9983,12 +9983,15 @@ namespace _ASSERTE(pMD->IsNDirect() || pMD->HasUnmanagedCallersOnlyAttribute()); if (pMD->IsNDirect()) { - if (pSuppressGCTransition) - { - *pSuppressGCTransition = pMD->ShouldSuppressGCTransition(); - } +#ifdef CROSSGEN_COMPILE + // Return CorInfoCallConvExtension::Managed to indicate that crossgen does not support handling UnmanagedCallConv + if (pMD->HasUnmanagedCallConvAttribute()) + return CorInfoCallConvExtension::Managed; +#endif // CROSSGEN_COMPILE - return NDirect::GetCallingConvention_IgnoreErrors(pMD); + CorInfoCallConvExtension unmanagedCallConv; + NDirect::GetCallingConvention_IgnoreErrors(pMD, &unmanagedCallConv, pSuppressGCTransition); + return unmanagedCallConv; } else { diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 75981105f3cdfc..5f19b8ce3f49eb 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -5423,6 +5423,38 @@ void NDirectMethodDesc::InitEarlyBoundNDirectTarget() } #endif // !CROSSGEN_COMPILE +//******************************************************************************* +BOOL MethodDesc::HasUnmanagedCallConvAttribute() +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END; + + MethodDesc* tgt = this; + if (IsILStub()) + { + // From the IL stub, determine if the actual target has been + // marked with UnmanagedCallConv. + PTR_DynamicMethodDesc ilStubMD = AsDynamicMethodDesc(); + PTR_ILStubResolver ilStubResolver = ilStubMD->GetILStubResolver(); + tgt = ilStubResolver->GetStubTargetMethodDesc(); + if (tgt == nullptr) + return FALSE; + } + + _ASSERTE(tgt != nullptr); + HRESULT hr = tgt->GetCustomAttribute( + WellKnownAttribute::UnmanagedCallConv, + nullptr, + nullptr); + + return (hr == S_OK) ? TRUE : FALSE; +} + //******************************************************************************* BOOL MethodDesc::HasUnmanagedCallersOnlyAttribute() { @@ -5460,9 +5492,9 @@ BOOL MethodDesc::ShouldSuppressGCTransition() { CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - FORBID_FAULT; + THROWS; + GC_TRIGGERS; + INJECT_FAULT(COMPlusThrowOM()); } CONTRACTL_END; @@ -5490,11 +5522,9 @@ BOOL MethodDesc::ShouldSuppressGCTransition() } _ASSERTE(tgt != nullptr); - HRESULT hr = tgt->GetCustomAttribute( - WellKnownAttribute::SuppressGCTransition, - nullptr, - nullptr); - return (hr == S_OK) ? TRUE : FALSE; + bool suppressGCTransition; + NDirect::GetCallingConvention_IgnoreErrors(tgt, NULL /*callConv*/, &suppressGCTransition); + return suppressGCTransition ? TRUE : FALSE; } #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 4d816b65885e76..491eeb671683f6 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -668,6 +668,7 @@ class MethodDesc return GetMethodTable()->IsInterface(); } + BOOL HasUnmanagedCallConvAttribute(); BOOL HasUnmanagedCallersOnlyAttribute(); BOOL ShouldSuppressGCTransition(); diff --git a/src/coreclr/vm/wellknownattributes.h b/src/coreclr/vm/wellknownattributes.h index 8da3de283e1c61..b247d62e052d15 100644 --- a/src/coreclr/vm/wellknownattributes.h +++ b/src/coreclr/vm/wellknownattributes.h @@ -28,6 +28,7 @@ enum class WellKnownAttribute : DWORD IsByRefLike, PrimaryInteropAssembly, ManagedToNativeComInteropStub, + UnmanagedCallConv, UnmanagedCallersOnly, NativeCallableInternal, // This is needed to support MCG scenarios TypeIdentifier, @@ -88,6 +89,8 @@ inline const char *GetWellKnownAttributeName(WellKnownAttribute attribute) return "System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute"; case WellKnownAttribute::ManagedToNativeComInteropStub: return "System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute"; + case WellKnownAttribute::UnmanagedCallConv: + return "System.Runtime.InteropServices.UnmanagedCallConvAttribute"; case WellKnownAttribute::UnmanagedCallersOnly: return "System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute"; case WellKnownAttribute::NativeCallableInternal: diff --git a/src/coreclr/zap/zapinfo.cpp b/src/coreclr/zap/zapinfo.cpp index 347f357c7de363..e69335bb110a0b 100644 --- a/src/coreclr/zap/zapinfo.cpp +++ b/src/coreclr/zap/zapinfo.cpp @@ -421,6 +421,13 @@ void ZapInfo::CompileMethod() ThrowHR(E_NOTIMPL); } + if (GetCompileInfo()->IsUnmanagedCallConvMethod(m_currentMethodHandle)) + { + if (m_zapper->m_pOpt->m_verbose) + m_zapper->Warning(W("ReadyToRun: Methods with UnmanagedCallConvAttribute not implemented\n")); + ThrowHR(E_NOTIMPL); + } + m_currentMethodInfo = CORINFO_METHOD_INFO(); if (!getMethodInfo(m_currentMethodHandle, &m_currentMethodInfo)) { diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 291862956e57b4..7e427704dcb9e0 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -801,6 +801,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallConvAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallConvAttribute.cs new file mode 100644 index 00000000000000..cdbc064cf11456 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallConvAttribute.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Runtime.InteropServices +{ + /// + /// Provides an equivalent to for native + /// functions declared in .NET. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class UnmanagedCallConvAttribute : Attribute + { + public UnmanagedCallConvAttribute() + { + } + + /// + /// Types indicating calling conventions for the unmanaged target. + /// + /// + /// If null, the semantics are identical to CallingConvention.Winapi. + /// + public Type[]? CallConvs; + } +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index 7ea73701620a3b..b9179b6de00243 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1091,6 +1091,12 @@ public static void RegisterForTrackerSupport(ComWrappers instance) { } public static void RegisterForMarshalling(ComWrappers instance) { } protected static void GetIUnknownImpl(out System.IntPtr fpQueryInterface, out System.IntPtr fpAddRef, out System.IntPtr fpRelease) { throw null; } } + [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class UnmanagedCallConvAttribute : System.Attribute + { + public UnmanagedCallConvAttribute() { } + public System.Type[]? CallConvs; + } [System.AttributeUsageAttribute(System.AttributeTargets.Method, Inherited = false)] public sealed class UnmanagedCallersOnlyAttribute : System.Attribute { diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 0fa1b9fd3a9684..0b5cdf06407980 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -112,6 +112,7 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, static GENERATE_TRY_GET_CLASS_WITH_CACHE (suppress_gc_transition_attribute, "System.Runtime.InteropServices", "SuppressGCTransitionAttribute") static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callers_only_attribute, "System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute") +static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callconv_attribute, "System.Runtime.InteropServices", "UnmanagedCallConvAttribute") static gboolean type_is_blittable (MonoType *type); @@ -3038,14 +3039,33 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, } } -static void +static void +mono_marshal_set_callconv_for_type(MonoType *type, MonoMethodSignature *csig, gboolean *skip_gc_trans /*out*/) +{ + MonoClass *callconv_class_maybe = mono_class_from_mono_type_internal (type); + if ((m_class_get_image (callconv_class_maybe) == mono_defaults.corlib) && !strcmp (m_class_get_name_space (callconv_class_maybe), "System.Runtime.CompilerServices")) { + const char *class_name = m_class_get_name (callconv_class_maybe); + if (!strcmp (class_name, "CallConvCdecl")) + csig->call_convention = MONO_CALL_C; + else if (!strcmp (class_name, "CallConvStdcall")) + csig->call_convention = MONO_CALL_STDCALL; + else if (!strcmp (class_name, "CallConvFastcall")) + csig->call_convention = MONO_CALL_FASTCALL; + else if (!strcmp (class_name, "CallConvThiscall")) + csig->call_convention = MONO_CALL_THISCALL; + else if (!strcmp (class_name, "CallConvSuppressGCTransition") && skip_gc_trans != NULL) + *skip_gc_trans = TRUE; + } +} + +static void mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature *csig, gboolean set_default) { MonoMethodSignature *sig; int i; #ifdef TARGET_WIN32 - /* + /* * Under windows, delegates passed to native code must use the STDCALL * calling convention. */ @@ -3069,19 +3089,76 @@ mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature * gboolean required; MonoType *cmod_type = mono_type_get_custom_modifier (sig->ret, i, &required, error); mono_error_assert_ok (error); - MonoClass *cmod_class = mono_class_from_mono_type_internal (cmod_type); - if ((m_class_get_image (cmod_class) == mono_defaults.corlib) && !strcmp (m_class_get_name_space (cmod_class), "System.Runtime.CompilerServices")) { - const char *cmod_class_name = m_class_get_name (cmod_class); - if (!strcmp (cmod_class_name, "CallConvCdecl")) - csig->call_convention = MONO_CALL_C; - else if (!strcmp (cmod_class_name, "CallConvStdcall")) - csig->call_convention = MONO_CALL_STDCALL; - else if (!strcmp (cmod_class_name, "CallConvFastcall")) - csig->call_convention = MONO_CALL_FASTCALL; - else if (!strcmp (cmod_class_name, "CallConvThiscall")) - csig->call_convention = MONO_CALL_THISCALL; + mono_marshal_set_callconv_for_type (cmod_type, csig, NULL); + } +} + +static MonoArray* +mono_marshal_get_callconvs_array_from_attribute (MonoCustomAttrEntry *attr, CattrNamedArg **arginfo) +{ + HANDLE_FUNCTION_ENTER (); + + ERROR_DECL (error); + MonoArrayHandleOut typed_args_h = MONO_HANDLE_NEW (MonoArray, NULL); + MonoArrayHandleOut named_args_h = MONO_HANDLE_NEW (MonoArray, NULL); + mono_reflection_create_custom_attr_data_args (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size, typed_args_h, named_args_h, arginfo, error); + if (!is_ok (error)) { + mono_error_cleanup (error); + } + + HANDLE_FUNCTION_RETURN_OBJ (named_args_h); +} + +static void +mono_marshal_set_callconv_from_unmanaged_callconv_attribute (MonoMethod *method, MonoMethodSignature *csig, gboolean *skip_gc_trans /*out*/) +{ + MonoClass *attr_class = mono_class_try_get_unmanaged_callconv_attribute_class (); + if (!attr_class) + return; + + ERROR_DECL (error); + MonoCustomAttrInfo *cinfo = mono_custom_attrs_from_method_checked (method, error); + if (!is_ok (error) || !cinfo) { + mono_error_cleanup (error); + return; + } + + int i; + MonoCustomAttrEntry *attr = NULL; + for (i = 0; i < cinfo->num_attrs; ++i) { + MonoClass *ctor_class = cinfo->attrs [i].ctor->klass; + if (ctor_class == attr_class) { + attr = &cinfo->attrs [i]; + break; } } + + if (attr != NULL) + { + CattrNamedArg *arginfo; + MonoArray *named_args = mono_marshal_get_callconvs_array_from_attribute(attr, &arginfo); + if (named_args) + { + for (i = 0; i < mono_array_length_internal(named_args); ++i) { + CattrNamedArg *info = &arginfo[i]; + g_assert(info->field); + if (strcmp(info->field->name, "CallConvs") != 0) + continue; + + /* CallConvs is an array of types */ + MonoArray *callconv_array = mono_array_get_internal(named_args, MonoArray *, i); + for (int j = 0; j < mono_array_length_internal(callconv_array); ++j) { + MonoReflectionType *callconv_type = mono_array_get_internal(callconv_array, MonoReflectionType *, j); + mono_marshal_set_callconv_for_type(callconv_type->type, csig, skip_gc_trans); + } + } + } + + g_free (arginfo); + } + + if (!cinfo->cached) + mono_custom_attrs_free(cinfo); } /** @@ -3324,6 +3401,11 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, mono_custom_attrs_free (cinfo); } + if (csig->call_convention == MONO_CALL_DEFAULT) { + /* If the calling convention has not been set, check the UnmanagedCallConv attribute */ + mono_marshal_set_callconv_from_unmanaged_callconv_attribute (method, csig, &skip_gc_trans); + } + MonoNativeWrapperFlags flags = aot ? EMIT_NATIVE_WRAPPER_AOT : (MonoNativeWrapperFlags)0; flags |= check_exceptions ? EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS : (MonoNativeWrapperFlags)0; flags |= skip_gc_trans ? EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS : (MonoNativeWrapperFlags)0; diff --git a/src/tests/Interop/CMakeLists.txt b/src/tests/Interop/CMakeLists.txt index 65295cb5688f2f..b8f39f741985f6 100644 --- a/src/tests/Interop/CMakeLists.txt +++ b/src/tests/Interop/CMakeLists.txt @@ -34,6 +34,7 @@ add_subdirectory(PInvoke/Generics) add_subdirectory(PInvoke/AsAny) add_subdirectory(PInvoke/SafeHandles) add_subdirectory(PInvoke/Vector2_3_4) +add_subdirectory(UnmanagedCallConv) add_subdirectory(UnmanagedCallersOnly) add_subdirectory(PrimitiveMarshalling/Bool) add_subdirectory(PrimitiveMarshalling/UIntPtr) diff --git a/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.cs b/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.cs index 2200f1dc4ef1fc..2c494865bef64b 100644 --- a/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.cs +++ b/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.cs @@ -109,33 +109,6 @@ private static IntPtr GetNativeLibrary() unsafe class SuppressGCTransitionTest { - private static bool ExplicitModeCheckEnabled = false; - private static void InitializeExplicitModeCheck() - { - // GetIsInCooperativeGCModeFunctionPointer is conditionally included based on the runtime build configuration, - // so we check for its existence and only do the explicit mode validation if it is available. - Type marshalType = typeof(object).Assembly.GetType(typeof(System.Runtime.InteropServices.Marshal).FullName); - MethodInfo getFunctionPtr = marshalType.GetMethod("GetIsInCooperativeGCModeFunctionPointer", BindingFlags.NonPublic | BindingFlags.Static); - if (getFunctionPtr != null) - { - var isInCooperativeModeFunc = (delegate* unmanaged)(IntPtr)getFunctionPtr.Invoke(null, null); - SuppressGCTransitionNative.SetIsInCooperativeModeFunction(isInCooperativeModeFunc); - ExplicitModeCheckEnabled = true; - Console.WriteLine("Explicit GC mode check is enabled"); - } - } - - private static void ValidateMode(bool transitionSuppressed, int inCooperativeMode) - => ValidateMode(transitionSuppressed, inCooperativeMode != 0); - - private static void ValidateMode(bool transitionSuppressed, bool inCooperativeMode) - { - if (!ExplicitModeCheckEnabled) - return; - - Assert.AreEqual(transitionSuppressed, inCooperativeMode, $"GC transition should{(transitionSuppressed ? "" : " not")} have been suppressed"); - } - [MethodImpl(MethodImplOptions.NoInlining)] private static int Inline_NoGCTransition(int expected) { @@ -143,7 +116,7 @@ private static int Inline_NoGCTransition(int expected) int n; int ret = SuppressGCTransitionNative.NextUInt_Inline_NoGCTransition(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: true, ret); + CheckGCMode.Validate(transitionSuppressed: true, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -153,7 +126,7 @@ private static int Inline_GCTransition(int expected) int n; int ret = SuppressGCTransitionNative.NextUInt_Inline_GCTransition(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -163,7 +136,7 @@ private static int NoInline_NoGCTransition(int expected) int n; bool ret = SuppressGCTransitionNative.NextUInt_NoInline_NoGCTransition(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: true, ret); + CheckGCMode.Validate(transitionSuppressed: true, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -173,7 +146,7 @@ private static int NoInline_GCTransition(int expected) int n; bool ret = SuppressGCTransitionNative.NextUInt_NoInline_GCTransition(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -185,18 +158,18 @@ private static int Mixed(int expected) { bool ret = SuppressGCTransitionNative.NextUInt_NoInline_GCTransition(&n); Assert.AreEqual(expected++, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); ret = SuppressGCTransitionNative.NextUInt_NoInline_NoGCTransition(&n); Assert.AreEqual(expected++, n); - ValidateMode(transitionSuppressed: true, ret); + CheckGCMode.Validate(transitionSuppressed: true, ret); } { int ret = SuppressGCTransitionNative.NextUInt_Inline_GCTransition(&n); Assert.AreEqual(expected++, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); ret = SuppressGCTransitionNative.NextUInt_Inline_NoGCTransition(&n); Assert.AreEqual(expected++, n); - ValidateMode(transitionSuppressed: true, ret); + CheckGCMode.Validate(transitionSuppressed: true, ret); } return n + 1; } @@ -224,7 +197,7 @@ private static int Inline_NoGCTransition_FunctionPointer(int expected) int n; int ret = SuppressGCTransitionNative.GetNextUIntFunctionPointer_Inline_NoGCTransition()(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: true, ret); + CheckGCMode.Validate(transitionSuppressed: true, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -234,7 +207,7 @@ private static int Inline_GCTransition_FunctionPointer(int expected) int n; int ret = SuppressGCTransitionNative.GetNextUIntFunctionPointer_Inline_GCTransition()(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -244,7 +217,7 @@ private static int NoInline_NoGCTransition_FunctionPointer(int expected) int n; bool ret = SuppressGCTransitionNative.GetNextUIntFunctionPointer_NoInline_NoGCTransition()(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: true, ret); + CheckGCMode.Validate(transitionSuppressed: true, ret); return n + 1; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -254,7 +227,7 @@ private static int NoInline_GCTransition_FunctionPointer(int expected) int n; bool ret = SuppressGCTransitionNative.GetNextUIntFunctionPointer_NoInline_GCTransition()(&n); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); return n + 1; } @@ -272,7 +245,7 @@ private static int CallAsFunctionPointer(int expected) MethodInfo callNextUInt = typeof(FunctionPointer).GetMethod("Call_NextUInt"); int ret = (int)callNextUInt.Invoke(null, new object[] { fptr, boxedN }); Assert.AreEqual(expected, n); - ValidateMode(transitionSuppressed: false, ret); + CheckGCMode.Validate(transitionSuppressed: false, ret); return n + 1; } [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] @@ -351,7 +324,7 @@ public static int Main(string[] args) { try { - InitializeExplicitModeCheck(); + CheckGCMode.Initialize(&SuppressGCTransitionNative.SetIsInCooperativeModeFunction); int n = 1; n = Inline_NoGCTransition(n); diff --git a/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.csproj b/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.csproj index b2fe46353a4a28..f2034ae7c1447c 100644 --- a/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.csproj +++ b/src/tests/Interop/SuppressGCTransition/SuppressGCTransitionTest.csproj @@ -4,6 +4,7 @@ True + diff --git a/src/tests/Interop/UnmanagedCallConv/CMakeLists.txt b/src/tests/Interop/UnmanagedCallConv/CMakeLists.txt new file mode 100644 index 00000000000000..4e8d8692a07ba3 --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/CMakeLists.txt @@ -0,0 +1,10 @@ +project(UnmanagedCallConvNative) +Include("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +set(SOURCES UnmanagedCallConvNative.cpp ) + +# add the executable +add_library(${PROJECT_NAME} SHARED ${SOURCES}) +target_link_libraries(${PROJECT_NAME} ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/src/tests/Interop/UnmanagedCallConv/PInvokesCS.cs b/src/tests/Interop/UnmanagedCallConv/PInvokesCS.cs new file mode 100644 index 00000000000000..60dcc10d955c66 --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/PInvokesCS.cs @@ -0,0 +1,232 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using TestLibrary; + +public unsafe static class PInvokesCS +{ + private const string UnmanagedCallConvNative = nameof(UnmanagedCallConvNative); + + private const string Double_Default = nameof(Double_Default); + private const string Double_Cdecl = nameof(Double_Cdecl); + private const string Double_Stdcall = nameof(Double_Stdcall); + + private const string Invert_Stdcall = nameof(Invert_Stdcall); + + [DllImport(nameof(UnmanagedCallConvNative))] + public static extern unsafe void SetIsInCooperativeModeFunction(delegate* unmanaged fn); + + public static class DefaultDllImport + { + public static class Default + { + [UnmanagedCallConv] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default)] + public static extern int Blittable_Double_DefaultUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default)] + public static extern bool NotBlittable_Double_DefaultUnmanagedCallConv(int a, int* b); + } + + public static class Cdecl + { + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv(int a, int* b); + } + + public static class Stdcall + { + // Mismatch + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern int Blittable_Double_StdcallUnmanagedCallConv(int a, int* b); + + // Mismatch + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern bool NotBlittable_Double_StdcallUnmanagedCallConv(int a, int* b); + } + } + + public static class WinapiDllImport + { + public static class Default + { + [UnmanagedCallConv] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default, CallingConvention = CallingConvention.Winapi)] + public static extern int Blittable_Double_DefaultUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default, CallingConvention = CallingConvention.Winapi)] + public static extern bool NotBlittable_Double_DefaultUnmanagedCallConv(int a, int* b); + } + + public static class Cdecl + { + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl, CallingConvention = CallingConvention.Winapi)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl, CallingConvention = CallingConvention.Winapi)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv(int a, int* b); + } + + public static class Stdcall + { + // Mismatch + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.Winapi)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.Winapi)] + public static extern int Blittable_Double_StdcallUnmanagedCallConv(int a, int* b); + + // Mismatch + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.Winapi)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.Winapi)] + public static extern bool NotBlittable_Double_StdcallUnmanagedCallConv(int a, int* b); + } + } + + public static class SuppressGCTransition + { + public static class Default + { + [SuppressGCTransition] + [UnmanagedCallConv] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default)] + public static extern int Blittable_Double_DefaultUnmanagedCallConv_SuppressGCAttr(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default)] + public static extern int Blittable_Double_DefaultUnmanagedCallConv_SuppressGC(int a, int* b); + + [SuppressGCTransition] + [UnmanagedCallConv] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default)] + public static extern bool NotBlittable_Double_DefaultUnmanagedCallConv_SuppressGCAttr(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Default)] + public static extern bool NotBlittable_Double_DefaultUnmanagedCallConv_SuppressGC(int a, int* b); + } + + public static class Cdecl + { + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv_SuppressGCAttr(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl), typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv_SuppressGC(int a, int* b); + + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv_SuppressGCAttr(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl), typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv_SuppressGC(int a, int* b); + } + + public static class Stdcall + { + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern int Blittable_Double_StdcallUnmanagedCallConv_SuppressGCAttr(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall), typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern int Blittable_Double_StdcallUnmanagedCallConv_SuppressGC(int a, int* b); + + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern bool NotBlittable_Double_StdcallUnmanagedCallConv_SuppressGCAttr(int a, int* b); + + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall), typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall)] + public static extern bool NotBlittable_Double_StdcallUnmanagedCallConv_SuppressGC(int a, int* b); + } + } + + public static class MatchingDllImport + { + public static class Cdecl + { + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl, CallingConvention = CallingConvention.Cdecl)] + public static extern int Blittable_Double_StdcallUnmanagedCallConv(int a, int* b); + + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl, CallingConvention = CallingConvention.Cdecl)] + public static extern int Blittable_Double_SuppressGCUnmanagedCallConv(int a, int* b); + + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvStdcall) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl, CallingConvention = CallingConvention.Cdecl)] + public static extern bool NotBlittable_Double_StdcallUnmanagedCallConv(int a, int* b); + + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Cdecl, CallingConvention = CallingConvention.Cdecl)] + public static extern bool NotBlittable_Double_SuppressGCUnmanagedCallConv(int a, int* b); + } + + public static class Stdcall + { + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.StdCall)] + public static extern int Blittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.StdCall)] + public static extern int Blittable_Double_SuppressGCUnmanagedCallConv(int a, int* b); + + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.StdCall)] + public static extern bool NotBlittable_Double_CdeclUnmanagedCallConv(int a, int* b); + + // UnmanagedCallConv should not be used + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvSuppressGCTransition) })] + [DllImport(nameof(UnmanagedCallConvNative), EntryPoint = Double_Stdcall, CallingConvention = CallingConvention.StdCall)] + public static extern bool NotBlittable_Double_SuppressGCUnmanagedCallConv(int a, int* b); + } + } +} diff --git a/src/tests/Interop/UnmanagedCallConv/PInvokesIL.il b/src/tests/Interop/UnmanagedCallConv/PInvokesIL.il new file mode 100644 index 00000000000000..841eba21c1ad95 --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/PInvokesIL.il @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) +} +.assembly extern System.Runtime.InteropServices +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) +} + +.assembly PInvokesIL { } + +.class public auto ansi abstract sealed beforefieldinit PInvokesIL + extends [System.Runtime]System.Object +{ + .class nested public auto ansi abstract sealed beforefieldinit UnsetPInvokeImpl + extends [System.Runtime]System.Object + { + .class nested public auto ansi abstract sealed beforefieldinit Default + extends [System.Runtime]System.Object + { + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Default") + int32 Blittable_Double_DefaultUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 00 00 + ) + } + + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Default") + bool NotBlittable_Double_DefaultUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 00 00 + ) + } + } + + .class nested public auto ansi abstract sealed beforefieldinit Cdecl + extends [System.Runtime]System.Object + { + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Cdecl") + int32 Blittable_Double_CdeclUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 01 00 53 1d 50 09 43 61 6c 6c 43 6f 6e 76 + 73 01 00 00 00 80 88 53 79 73 74 65 6d 2e 52 75 + 6e 74 69 6d 65 2e 43 6f 6d 70 69 6c 65 72 53 65 + 72 76 69 63 65 73 2e 43 61 6c 6c 43 6f 6e 76 43 + 64 65 63 6c 2c 20 53 79 73 74 65 6d 2e 50 72 69 + 76 61 74 65 2e 43 6f 72 65 4c 69 62 2c 20 56 65 + 72 73 69 6f 6e 3d 35 2e 30 2e 30 2e 30 2c 20 43 + 75 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 + 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 37 + 63 65 63 38 35 64 37 62 65 61 37 37 39 38 65 + ) + } + + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Cdecl") + bool NotBlittable_Double_CdeclUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 01 00 53 1d 50 09 43 61 6c 6c 43 6f 6e 76 + 73 01 00 00 00 80 88 53 79 73 74 65 6d 2e 52 75 + 6e 74 69 6d 65 2e 43 6f 6d 70 69 6c 65 72 53 65 + 72 76 69 63 65 73 2e 43 61 6c 6c 43 6f 6e 76 43 + 64 65 63 6c 2c 20 53 79 73 74 65 6d 2e 50 72 69 + 76 61 74 65 2e 43 6f 72 65 4c 69 62 2c 20 56 65 + 72 73 69 6f 6e 3d 35 2e 30 2e 30 2e 30 2c 20 43 + 75 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 + 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 37 + 63 65 63 38 35 64 37 62 65 61 37 37 39 38 65 + ) + } + } + + .class nested public auto ansi abstract sealed beforefieldinit Stdcall + extends [System.Runtime]System.Object + { + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Stdcall") + int32 Blittable_Double_CdeclUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 01 00 53 1d 50 09 43 61 6c 6c 43 6f 6e 76 + 73 01 00 00 00 80 88 53 79 73 74 65 6d 2e 52 75 + 6e 74 69 6d 65 2e 43 6f 6d 70 69 6c 65 72 53 65 + 72 76 69 63 65 73 2e 43 61 6c 6c 43 6f 6e 76 43 + 64 65 63 6c 2c 20 53 79 73 74 65 6d 2e 50 72 69 + 76 61 74 65 2e 43 6f 72 65 4c 69 62 2c 20 56 65 + 72 73 69 6f 6e 3d 35 2e 30 2e 30 2e 30 2c 20 43 + 75 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 + 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 37 + 63 65 63 38 35 64 37 62 65 61 37 37 39 38 65 + ) + } + + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Stdcall") + int32 Blittable_Double_StdcallUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 01 00 53 1d 50 09 43 61 6c 6c 43 6f 6e 76 + 73 01 00 00 00 80 8a 53 79 73 74 65 6d 2e 52 75 + 6e 74 69 6d 65 2e 43 6f 6d 70 69 6c 65 72 53 65 + 72 76 69 63 65 73 2e 43 61 6c 6c 43 6f 6e 76 53 + 74 64 63 61 6c 6c 2c 20 53 79 73 74 65 6d 2e 50 + 72 69 76 61 74 65 2e 43 6f 72 65 4c 69 62 2c 20 + 56 65 72 73 69 6f 6e 3d 35 2e 30 2e 30 2e 30 2c + 20 43 75 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c + 2c 20 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e + 3d 37 63 65 63 38 35 64 37 62 65 61 37 37 39 38 65 + ) + } + + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Stdcall") + bool NotBlittable_Double_CdeclUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 01 00 53 1d 50 09 43 61 6c 6c 43 6f 6e 76 + 73 01 00 00 00 80 88 53 79 73 74 65 6d 2e 52 75 + 6e 74 69 6d 65 2e 43 6f 6d 70 69 6c 65 72 53 65 + 72 76 69 63 65 73 2e 43 61 6c 6c 43 6f 6e 76 43 + 64 65 63 6c 2c 20 53 79 73 74 65 6d 2e 50 72 69 + 76 61 74 65 2e 43 6f 72 65 4c 69 62 2c 20 56 65 + 72 73 69 6f 6e 3d 35 2e 30 2e 30 2e 30 2c 20 43 + 75 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 + 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 37 + 63 65 63 38 35 64 37 62 65 61 37 37 39 38 65 + ) + } + + .method public hidebysig static pinvokeimpl("UnmanagedCallConvNative" as "Double_Stdcall") + bool NotBlittable_Double_StdcallUnmanagedCallConv (int32 a, int32* b) cil managed preservesig + { + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallConvAttribute::.ctor() = ( + 01 00 01 00 53 1d 50 09 43 61 6c 6c 43 6f 6e 76 + 73 01 00 00 00 80 8a 53 79 73 74 65 6d 2e 52 75 + 6e 74 69 6d 65 2e 43 6f 6d 70 69 6c 65 72 53 65 + 72 76 69 63 65 73 2e 43 61 6c 6c 43 6f 6e 76 53 + 74 64 63 61 6c 6c 2c 20 53 79 73 74 65 6d 2e 50 + 72 69 76 61 74 65 2e 43 6f 72 65 4c 69 62 2c 20 + 56 65 72 73 69 6f 6e 3d 35 2e 30 2e 30 2e 30 2c + 20 43 75 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c + 2c 20 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e + 3d 37 63 65 63 38 35 64 37 62 65 61 37 37 39 38 65 + ) + } + } + } +} diff --git a/src/tests/Interop/UnmanagedCallConv/PInvokesIL.ilproj b/src/tests/Interop/UnmanagedCallConv/PInvokesIL.ilproj new file mode 100644 index 00000000000000..329b583c8965fe --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/PInvokesIL.ilproj @@ -0,0 +1,8 @@ + + + library + + + + + diff --git a/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvNative.cpp b/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvNative.cpp new file mode 100644 index 00000000000000..e3ecd95ef8be38 --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvNative.cpp @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +namespace +{ + using IsInCooperativeMode_fn = BOOL(STDMETHODCALLTYPE*)(void); + IsInCooperativeMode_fn s_isInCooperativeMode = nullptr; + + BOOL Double(int a, int* b) + { + if (b != NULL) + *b = a * 2; + + BOOL ret = FALSE; + if (s_isInCooperativeMode != nullptr) + ret = s_isInCooperativeMode(); + + return ret; + } +} + +extern "C" void DLL_EXPORT STDMETHODCALLTYPE SetIsInCooperativeModeFunction(IsInCooperativeMode_fn fn) +{ + s_isInCooperativeMode = fn; +} + +extern "C" DLL_EXPORT BOOL Double_Default(int a, int* b) +{ + return Double(a, b); +} + +extern "C" DLL_EXPORT int __cdecl Double_Cdecl(int a, int* b) +{ + return Double(a, b); +} + +extern "C" DLL_EXPORT int __stdcall Double_Stdcall(int a, int* b) +{ + return Double(a, b); +} diff --git a/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.cs b/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.cs new file mode 100644 index 00000000000000..d6e0b16095731f --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.cs @@ -0,0 +1,414 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using TestLibrary; + +public unsafe class Program +{ + // We test for mismatched callling convention by checking for a failure to + // find the native entry point when the exported function is stdcall, but + // the defined p/invoke is cdecl. This is only relevant on Windows x86. + private static bool ValidateMismatch = OperatingSystem.IsWindows() && TestLibrary.Utilities.IsX86; + + private static void DefaultDllImport_Blittable() + { + Console.WriteLine($"Running {nameof(DefaultDllImport_Blittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: UnmanagedCallConv()"); + int b; + PInvokesCS.DefaultDllImport.Default.Blittable_Double_DefaultUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl)"); + int b; + PInvokesCS.DefaultDllImport.Cdecl.Blittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall)"); + int b; + PInvokesCS.DefaultDllImport.Stdcall.Blittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + + if (ValidateMismatch) + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + Assert.Throws(() => PInvokesCS.DefaultDllImport.Stdcall.Blittable_Double_CdeclUnmanagedCallConv(a, null)); + } + } + + private static void DefaultDllImport_NotBlittable() + { + Console.WriteLine($"Running {nameof(DefaultDllImport_NotBlittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: UnmanagedCallConv()"); + int b; + PInvokesCS.DefaultDllImport.Default.NotBlittable_Double_DefaultUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl)"); + int b; + PInvokesCS.DefaultDllImport.Cdecl.NotBlittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall)"); + int b; + PInvokesCS.DefaultDllImport.Stdcall.NotBlittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + + if (ValidateMismatch) + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + Assert.Throws(() => PInvokesCS.DefaultDllImport.Stdcall.NotBlittable_Double_CdeclUnmanagedCallConv(a, null)); + } + } + + private static void WinapiDllImport_Blittable() + { + Console.WriteLine($"Running {nameof(WinapiDllImport_Blittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: UnmanagedCallConv()"); + int b; + PInvokesCS.WinapiDllImport.Default.Blittable_Double_DefaultUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl)"); + int b; + PInvokesCS.WinapiDllImport.Cdecl.Blittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall)"); + int b; + PInvokesCS.WinapiDllImport.Stdcall.Blittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + + if (ValidateMismatch) + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + Assert.Throws(() => PInvokesCS.WinapiDllImport.Stdcall.Blittable_Double_CdeclUnmanagedCallConv(a, null)); + } + } + + private static void WinapiDllImport_NotBlittable() + { + Console.WriteLine($"Running {nameof(WinapiDllImport_NotBlittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: UnmanagedCallConv()"); + int b; + PInvokesCS.WinapiDllImport.Default.NotBlittable_Double_DefaultUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl)"); + int b; + PInvokesCS.WinapiDllImport.Cdecl.NotBlittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall)"); + int b; + PInvokesCS.WinapiDllImport.Stdcall.NotBlittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + + if (ValidateMismatch) + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + Assert.Throws(() => PInvokesCS.WinapiDllImport.Stdcall.NotBlittable_Double_CdeclUnmanagedCallConv(a, null)); + } + } + + private static void UnsetPInvokeImpl_Blittable() + { + Console.WriteLine($"Running {nameof(UnsetPInvokeImpl_Blittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: UnmanagedCallConv()"); + int b; + PInvokesIL.UnsetPInvokeImpl.Default.Blittable_Double_DefaultUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl)"); + int b; + PInvokesIL.UnsetPInvokeImpl.Cdecl.Blittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall)"); + int b; + PInvokesIL.UnsetPInvokeImpl.Stdcall.Blittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + + if (ValidateMismatch) + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + Assert.Throws(() => PInvokesIL.UnsetPInvokeImpl.Stdcall.Blittable_Double_CdeclUnmanagedCallConv(a, null)); + } + } + + private static void UnsetPInvokeImpl_NotBlittable() + { + Console.WriteLine($"Running {nameof(UnsetPInvokeImpl_NotBlittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: UnmanagedCallConv()"); + int b; + PInvokesIL.UnsetPInvokeImpl.Default.NotBlittable_Double_DefaultUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl)"); + int b; + PInvokesIL.UnsetPInvokeImpl.Cdecl.NotBlittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall)"); + int b; + PInvokesIL.UnsetPInvokeImpl.Stdcall.NotBlittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + + if (ValidateMismatch) + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + Assert.Throws(() => PInvokesIL.UnsetPInvokeImpl.Stdcall.NotBlittable_Double_CdeclUnmanagedCallConv(a, null)); + } + } + + private static void SuppressGCTransition_Blittable() + { + Console.WriteLine($"Running {nameof(SuppressGCTransition_Blittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: SuppressGCTransition, UnmanagedCallConv()"); + int b; + int ret = PInvokesCS.SuppressGCTransition.Default.Blittable_Double_DefaultUnmanagedCallConv_SuppressGCAttr(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- default: UnmanagedCallConv(suppressgctransition)"); + int b; + int ret = PInvokesCS.SuppressGCTransition.Default.Blittable_Double_DefaultUnmanagedCallConv_SuppressGC(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- cdecl: SuppressGCTransition, UnmanagedCallConv(cdecl)"); + int b; + int ret = PInvokesCS.SuppressGCTransition.Cdecl.Blittable_Double_CdeclUnmanagedCallConv_SuppressGCAttr(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl, suppressgctransition)"); + int b; + int ret = PInvokesCS.SuppressGCTransition.Cdecl.Blittable_Double_CdeclUnmanagedCallConv_SuppressGC(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- stdcall: SuppressGCTransition, UnmanagedCallConv(stdcall)"); + int b; + int ret = PInvokesCS.SuppressGCTransition.Stdcall.Blittable_Double_StdcallUnmanagedCallConv_SuppressGCAttr(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall, suppressgctransition)"); + int b; + int ret = PInvokesCS.SuppressGCTransition.Stdcall.Blittable_Double_StdcallUnmanagedCallConv_SuppressGC(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + } + + private static void SuppressGCTransition_NotBlittable() + { + Console.WriteLine($"Running {nameof(SuppressGCTransition_NotBlittable)}..."); + + const int a = 11; + const int expected = a * 2; + { + Console.WriteLine($" -- default: SuppressGCTransition, UnmanagedCallConv()"); + int b; + bool ret = PInvokesCS.SuppressGCTransition.Default.NotBlittable_Double_DefaultUnmanagedCallConv_SuppressGCAttr(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- default: UnmanagedCallConv(suppressgctransition)"); + int b; + bool ret = PInvokesCS.SuppressGCTransition.Default.NotBlittable_Double_DefaultUnmanagedCallConv_SuppressGC(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- cdecl: SuppressGCTransition, UnmanagedCallConv(cdecl)"); + int b; + bool ret = PInvokesCS.SuppressGCTransition.Cdecl.NotBlittable_Double_CdeclUnmanagedCallConv_SuppressGCAttr(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- cdecl: UnmanagedCallConv(cdecl, suppressgctransition)"); + int b; + bool ret = PInvokesCS.SuppressGCTransition.Cdecl.NotBlittable_Double_CdeclUnmanagedCallConv_SuppressGC(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- stdcall: SuppressGCTransition, UnmanagedCallConv(stdcall)"); + int b; + bool ret = PInvokesCS.SuppressGCTransition.Stdcall.NotBlittable_Double_StdcallUnmanagedCallConv_SuppressGCAttr(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + { + Console.WriteLine($" -- stdcall: UnmanagedCallConv(stdcall, suppressgctransition)"); + int b; + bool ret = PInvokesCS.SuppressGCTransition.Stdcall.NotBlittable_Double_StdcallUnmanagedCallConv_SuppressGC(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: true, ret); + } + } + + private static void MatchingDllImport_Blittable() + { + Console.WriteLine($"Running {nameof(MatchingDllImport_Blittable)}..."); + + // Calling convention is set in DllImport. UnmanagedCallConv should be ignored, + const int a = 11; + const int expected = a * 2; + { + // Should work despite the mismatched value in UnmanagedCallConv + Console.WriteLine($" -- cdecl: UnmanagedCallConv(stdcall)"); + int b; + PInvokesCS.MatchingDllImport.Cdecl.Blittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + // Should not suppress GC transition + Console.WriteLine($" -- cdecl: UnmanagedCallConv(suppressgctransition)"); + int b; + int ret = PInvokesCS.MatchingDllImport.Cdecl.Blittable_Double_SuppressGCUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: false, ret); + } + { + // Should work despite the mismatched value in UnmanagedCallConv + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + int b; + PInvokesCS.MatchingDllImport.Stdcall.Blittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + // Should not suppress GC transition + Console.WriteLine($" -- stdcall: UnmanagedCallConv(suppressgctransition)"); + int b; + int ret = PInvokesCS.MatchingDllImport.Stdcall.Blittable_Double_SuppressGCUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: false, ret); + } + } + + private static void MatchingDllImport_NotBlittable() + { + Console.WriteLine($"Running {nameof(MatchingDllImport_NotBlittable)}..."); + + // Calling convention is set in DllImport. UnmanagedCallConv should be ignored, + const int a = 11; + const int expected = a * 2; + { + // Should work despite the mismatched value in UnmanagedCallConv + Console.WriteLine($" -- cdecl: UnmanagedCallConv(stdcall)"); + int b; + PInvokesCS.MatchingDllImport.Cdecl.NotBlittable_Double_StdcallUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + // Should not suppress GC transition + Console.WriteLine($" -- cdecl: UnmanagedCallConv(suppressgctransition)"); + int b; + bool ret = PInvokesCS.MatchingDllImport.Cdecl.NotBlittable_Double_SuppressGCUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: false, ret); + } + { + // Should work despite the mismatched value in UnmanagedCallConv + Console.WriteLine($" -- stdcall: UnmanagedCallConv(cdecl)"); + int b; + PInvokesCS.MatchingDllImport.Stdcall.NotBlittable_Double_CdeclUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + } + { + // Should not suppress GC transition + Console.WriteLine($" -- stdcall: UnmanagedCallConv(suppressgctransition)"); + int b; + bool ret = PInvokesCS.MatchingDllImport.Stdcall.NotBlittable_Double_SuppressGCUnmanagedCallConv(a, &b); + Assert.AreEqual(expected, b); + CheckGCMode.Validate(transitionSuppressed: false, ret); + } + } + + public static int Main(string[] args) + { + try + { + DefaultDllImport_Blittable(); + DefaultDllImport_NotBlittable(); + WinapiDllImport_Blittable(); + WinapiDllImport_NotBlittable(); + UnsetPInvokeImpl_Blittable(); + UnsetPInvokeImpl_NotBlittable(); + + // Following tests explicitly check GC mode when possible + CheckGCMode.Initialize(&PInvokesCS.SetIsInCooperativeModeFunction); + SuppressGCTransition_Blittable(); + SuppressGCTransition_NotBlittable(); + MatchingDllImport_Blittable(); + MatchingDllImport_NotBlittable(); + + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } +} diff --git a/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.csproj b/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.csproj new file mode 100644 index 00000000000000..91b3a6a6a1df79 --- /dev/null +++ b/src/tests/Interop/UnmanagedCallConv/UnmanagedCallConvTest.csproj @@ -0,0 +1,16 @@ + + + Exe + true + + + + + + + + + + + + diff --git a/src/tests/Interop/common/CheckGCMode.cs b/src/tests/Interop/common/CheckGCMode.cs new file mode 100644 index 00000000000000..e895cd594713e6 --- /dev/null +++ b/src/tests/Interop/common/CheckGCMode.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; + +using TestLibrary; + +unsafe internal class CheckGCMode +{ + internal static bool Enabled = false; + internal static void Initialize(delegate* , void> setIsInCooperativeModeFunction) + { + // GetIsInCooperativeGCModeFunctionPointer is conditionally included based on the runtime build configuration, + // so we check for its existence and only do the explicit mode validation if it is available. + Type marshalType = typeof(object).Assembly.GetType(typeof(System.Runtime.InteropServices.Marshal).FullName); + MethodInfo getFunctionPtr = marshalType.GetMethod("GetIsInCooperativeGCModeFunctionPointer", BindingFlags.NonPublic | BindingFlags.Static); + if (getFunctionPtr != null) + { + var isInCooperativeModeFunc = (delegate* unmanaged)(IntPtr)getFunctionPtr.Invoke(null, null); + setIsInCooperativeModeFunction(isInCooperativeModeFunc); + Enabled = true; + Console.WriteLine("Explicit GC mode check is enabled"); + } + } + + internal static void Validate(bool transitionSuppressed, bool inCooperativeMode) + { + if (!Enabled) + return; + + Assert.AreEqual(transitionSuppressed, inCooperativeMode, $"GC transition should{(transitionSuppressed ? "" : " not")} have been suppressed"); + } + + internal static void Validate(bool transitionSuppressed, int inCooperativeMode) + => Validate(transitionSuppressed, inCooperativeMode != 0); +} diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 26836c55e86c0d..4bb604a68b2431 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -2722,6 +2722,9 @@ https://github.com/dotnet/runtime/issues/41519 + + https://github.com/dotnet/runtime/issues/41519 + https://github.com/dotnet/runtime/issues/41519 From 4b7396b53b9121ffed297891a4ecc0445e123a77 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 21 May 2021 08:56:05 +0200 Subject: [PATCH 029/115] Make DSA.Create, AesCcm, AesGcm, ChaCha20Poly1305 throw PNSE on iOS (#52978) --- .../src/Internal/Cryptography/Helpers.cs | 10 +++++ .../Security/Cryptography/DSAOpenSsl.cs | 2 +- .../Cryptography/DSASecurityTransforms.cs | 3 +- .../Cryptography/DSASecurityTransforms.iOS.cs | 25 ------------ .../System/PlatformDetection.Unix.cs | 2 +- .../TestUtilities/System/PlatformDetection.cs | 1 + ...System.Security.Cryptography.Algorithms.cs | 18 +++++++++ ...em.Security.Cryptography.Algorithms.csproj | 20 ++++++---- .../Cryptography/AesCcm.NotSupported.cs | 38 +++++++++++++++++++ .../System/Security/Cryptography/AesCcm.cs | 3 ++ .../Cryptography/AesGcm.NotSupported.cs | 38 +++++++++++++++++++ .../System/Security/Cryptography/AesGcm.cs | 3 ++ .../Security/Cryptography/ChaCha20Poly1305.cs | 3 ++ .../Security/Cryptography/CryptoConfig.cs | 9 ++++- .../Cryptography/DSA.Create.Android.cs | 2 +- .../Cryptography/DSA.Create.NotSupported.cs | 15 ++++++++ .../src/System/Security/Cryptography/DSA.cs | 18 ++++++++- .../System/Security/Cryptography/DSACng.cs | 2 +- .../tests/AesCcmTests.cs | 4 ++ .../tests/AesGcmTests.cs | 4 ++ .../tests/CryptoConfigTests.cs | 7 +++- .../tests/DSACryptoServiceProviderTests.cs | 2 + .../Cryptography/Pal/AnyOS/ManagedPal.cs | 2 +- .../Cryptography/Pkcs/CmsSignature.DSA.cs | 20 +++++++--- .../tests/SignedCms/SignedCmsTests.cs | 12 +++++- .../SignedCms/SignedCmsTests.netcoreapp.cs | 6 ++- .../tests/SignedCms/SignerInfoTests.cs | 13 ++++++- .../SignedCms/SignerInfoTests.netcoreapp.cs | 8 +++- .../tests/CryptoConfigTests.cs | 23 ++++++++++- ...urity.Cryptography.Primitives.Tests.csproj | 2 + ....Security.Cryptography.X509Certificates.cs | 3 ++ .../DSACertificateExtensions.cs | 4 ++ .../X509Certificates/X509Certificate2.cs | 4 +- .../ref/System.Security.Cryptography.Xml.cs | 3 ++ .../Security/Cryptography/Xml/DSAKeyValue.cs | 4 ++ .../tests/DSAKeyValueTest.cs | 7 +--- .../tests/KeyInfoTest.cs | 7 ++-- .../tests/SignedXmlTest.cs | 6 ++- ...tem.Security.Cryptography.Xml.Tests.csproj | 2 + .../ApiCompatBaseline.PreviousNetCoreApp.txt | 6 ++- src/libraries/tests.proj | 8 ---- 41 files changed, 291 insertions(+), 78 deletions(-) delete mode 100644 src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.iOS.cs create mode 100644 src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.NotSupported.cs diff --git a/src/libraries/Common/src/Internal/Cryptography/Helpers.cs b/src/libraries/Common/src/Internal/Cryptography/Helpers.cs index 2440690cd6e19b..c2998444ea1059 100644 --- a/src/libraries/Common/src/Internal/Cryptography/Helpers.cs +++ b/src/libraries/Common/src/Internal/Cryptography/Helpers.cs @@ -4,11 +4,21 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; +using System.Runtime.Versioning; namespace Internal.Cryptography { internal static partial class Helpers { +#if NET5_0_OR_GREATER + [UnsupportedOSPlatformGuard("ios")] + [UnsupportedOSPlatformGuard("tvos")] + [UnsupportedOSPlatformGuard("maccatalyst")] + public static bool IsDSASupported => !OperatingSystem.IsIOS() && !OperatingSystem.IsTvOS() && !OperatingSystem.IsMacCatalyst(); +#else + public static bool IsDSASupported => true; +#endif + [return: NotNullIfNotNull("src")] public static byte[]? CloneByteArray(this byte[]? src) { diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs index 6993d59a33f739..7c75208f8a2ea0 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs @@ -11,7 +11,7 @@ namespace System.Security.Cryptography #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS public partial class DSA : AsymmetricAlgorithm { - public static new DSA Create() + private static DSA CreateCore() { return new DSAImplementation.DSAOpenSsl(); } diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs index d991928f7779d1..8b7e0dbb4ec710 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs @@ -12,10 +12,9 @@ namespace System.Security.Cryptography { #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS - public partial class DSA : AsymmetricAlgorithm { - public static new DSA Create() + private static DSA CreateCore() { return new DSAImplementation.DSASecurityTransforms(); } diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.iOS.cs b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.iOS.cs deleted file mode 100644 index 2773e65dbc74e0..00000000000000 --- a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.iOS.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Buffers; -using System.Diagnostics; -using System.Formats.Asn1; -using System.IO; -using System.Runtime.InteropServices; -using System.Security.Cryptography.Apple; -using Internal.Cryptography; - -namespace System.Security.Cryptography -{ - internal static partial class DSAImplementation - { - public sealed partial class DSASecurityTransforms : DSA - { - public override DSAParameters ExportParameters(bool includePrivateParameters) - => throw new PlatformNotSupportedException(); - - public override void ImportParameters(DSAParameters parameters) - => throw new PlatformNotSupportedException(); - } - } -} diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs index b162a25ba11c30..096616937019eb 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs @@ -105,7 +105,7 @@ public static bool OpenSslPresentOnSystem { get { - if (IsAndroid || IsiOS || IstvOS || IsMacCatalyst || IsBrowser) + if (IsAndroid || UsesMobileAppleCrypto || IsBrowser) { return false; } diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 6c0d4a1978999e..ecf16031fe9dba 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -138,6 +138,7 @@ public static bool IsNonZeroLowerBoundArraySupported public static bool IsOpenSslSupported => IsLinux || IsFreeBSD || Isillumos || IsSolaris; public static bool UsesAppleCrypto => IsOSX || IsMacCatalyst || IsiOS || IstvOS; + public static bool UsesMobileAppleCrypto => IsMacCatalyst || IsiOS || IstvOS; // Changed to `true` when linking public static bool IsBuiltWithAggressiveTrimming => false; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs index f55f635e6b7626..c11560bdb71799 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs @@ -15,6 +15,9 @@ protected Aes() { } public static new System.Security.Cryptography.Aes? Create(string algorithmName) { throw null; } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public sealed partial class AesCcm : System.IDisposable { public AesCcm(byte[] key) { } @@ -29,6 +32,9 @@ public void Encrypt(byte[] nonce, byte[] plaintext, byte[] ciphertext, byte[] ta public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public sealed partial class AesGcm : System.IDisposable { public AesGcm(byte[] key) { } @@ -101,6 +107,9 @@ protected AsymmetricSignatureFormatter() { } public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public sealed partial class ChaCha20Poly1305 : System.IDisposable { public ChaCha20Poly1305(byte[] key) { } @@ -154,8 +163,17 @@ protected DES() { } public abstract partial class DSA : System.Security.Cryptography.AsymmetricAlgorithm { protected DSA() { } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public static new System.Security.Cryptography.DSA Create() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public static System.Security.Cryptography.DSA Create(int keySizeInBits) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public static System.Security.Cryptography.DSA Create(System.Security.Cryptography.DSAParameters parameters) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.DSA? Create(string algName) { throw null; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index b829552cc56cc2..566656df50a0b7 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -520,8 +520,6 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeCreateHandle.OSX.cs" /> - + - + + + + - - + + + - @@ -676,6 +678,8 @@ Link="Common\Interop\Android\System.Security.Cryptography.Native.Android\Interop.Rsa.cs" /> + diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.NotSupported.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.NotSupported.cs index 170540eec2cee7..6cbfe82d10ab73 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.NotSupported.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.NotSupported.cs @@ -1,10 +1,48 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Security.Cryptography { public partial class AesCcm { public static bool IsSupported => false; + +#if !BROWSER // allow GenFacades to handle browser target + private void ImportKey(ReadOnlySpan key) + { + Debug.Fail("Instance ctor should fail before we reach this point."); + throw new NotImplementedException(); + } + + private void EncryptCore( + ReadOnlySpan nonce, + ReadOnlySpan plaintext, + Span ciphertext, + Span tag, + ReadOnlySpan associatedData = default) + { + Debug.Fail("Instance ctor should fail before we reach this point."); + throw new NotImplementedException(); + } + + private void DecryptCore( + ReadOnlySpan nonce, + ReadOnlySpan ciphertext, + ReadOnlySpan tag, + Span plaintext, + ReadOnlySpan associatedData = default) + { + Debug.Fail("Instance ctor should fail before we reach this point."); + throw new NotImplementedException(); + } + + public void Dispose() + { + Debug.Fail("Instance ctor should fail before we reach this point."); + // no-op + } +#endif } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs index 91c73dcfb0be05..50377c3aee3e8c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs @@ -7,6 +7,9 @@ namespace System.Security.Cryptography { [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public sealed partial class AesCcm : IDisposable { public static KeySizes NonceByteSizes { get; } = new KeySizes(7, 13, 1); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.NotSupported.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.NotSupported.cs index efbf1a729b57c7..0950177836646c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.NotSupported.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.NotSupported.cs @@ -1,10 +1,48 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Security.Cryptography { public partial class AesGcm { public static bool IsSupported => false; + +#if !BROWSER // allow GenFacades to handle browser target + private void ImportKey(ReadOnlySpan key) + { + Debug.Fail("Instance ctor should fail before we reach this point."); + throw new NotImplementedException(); + } + + private void EncryptCore( + ReadOnlySpan nonce, + ReadOnlySpan plaintext, + Span ciphertext, + Span tag, + ReadOnlySpan associatedData = default) + { + Debug.Fail("Instance ctor should fail before we reach this point."); + throw new NotImplementedException(); + } + + private void DecryptCore( + ReadOnlySpan nonce, + ReadOnlySpan ciphertext, + ReadOnlySpan tag, + Span plaintext, + ReadOnlySpan associatedData = default) + { + Debug.Fail("Instance ctor should fail before we reach this point."); + throw new NotImplementedException(); + } + + public void Dispose() + { + Debug.Fail("Instance ctor should fail before we reach this point."); + // no-op + } +#endif } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs index 78b0ce86db240d..89c98f7866d08b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs @@ -7,6 +7,9 @@ namespace System.Security.Cryptography { [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public sealed partial class AesGcm : IDisposable { private const int NonceSize = 12; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs index 874133cc39f717..115edee5514a4e 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs @@ -7,6 +7,9 @@ namespace System.Security.Cryptography { [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public sealed partial class ChaCha20Poly1305 : IDisposable { // Per https://tools.ietf.org/html/rfc7539, ChaCha20Poly1305 AEAD requires a 256-bit key and 96-bit nonce, diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs index 898cf554a8bc39..ff73ce605054d7 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/CryptoConfig.cs @@ -185,8 +185,13 @@ private static Dictionary DefaultNameHT ht.Add("System.Security.Cryptography.RSA", RSACryptoServiceProviderType); ht.Add("System.Security.Cryptography.AsymmetricAlgorithm", RSACryptoServiceProviderType); - ht.Add("DSA", DSACryptoServiceProviderType); - ht.Add("System.Security.Cryptography.DSA", DSACryptoServiceProviderType); + if (!OperatingSystem.IsIOS() && + !OperatingSystem.IsTvOS() && + !OperatingSystem.IsMacCatalyst()) + { + ht.Add("DSA", DSACryptoServiceProviderType); + ht.Add("System.Security.Cryptography.DSA", DSACryptoServiceProviderType); + } // Windows will register the public ECDsaCng type. Non-Windows gets a special handler. if (OperatingSystem.IsWindows()) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.Android.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.Android.cs index 446a3e56f72bf9..7dff1107e8dc80 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.Android.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.Android.cs @@ -5,7 +5,7 @@ namespace System.Security.Cryptography { public partial class DSA : AsymmetricAlgorithm { - public static new DSA Create() + private static DSA CreateCore() { return new DSAImplementation.DSAAndroid(); } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.NotSupported.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.NotSupported.cs new file mode 100644 index 00000000000000..c9421b066260ab --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.NotSupported.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. + +using System.Runtime.Versioning; + +namespace System.Security.Cryptography +{ + public partial class DSA : AsymmetricAlgorithm + { + private static DSA CreateCore() + { + throw new PlatformNotSupportedException(); + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs index e5d90e5d6eadb8..2e06904214f420 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs @@ -35,9 +35,20 @@ protected DSA() { } return (DSA?)CryptoConfig.CreateFromName(algName); } + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] + public static new DSA Create() + { + return CreateCore(); + } + + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public static DSA Create(int keySizeInBits) { - DSA dsa = Create(); + DSA dsa = CreateCore(); try { @@ -51,9 +62,12 @@ public static DSA Create(int keySizeInBits) } } + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public static DSA Create(DSAParameters parameters) { - DSA dsa = Create(); + DSA dsa = CreateCore(); try { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSACng.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSACng.cs index 9cdf2b83cab31b..8ede9bb6dcf5ce 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSACng.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSACng.cs @@ -8,7 +8,7 @@ namespace System.Security.Cryptography { public partial class DSA : AsymmetricAlgorithm { - public static new DSA Create() + private static DSA CreateCore() { return new DSAImplementation.DSACng(); } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/AesCcmTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/AesCcmTests.cs index 7ee3d6c76d72f8..eeb1f7edac2dcc 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/AesCcmTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/AesCcmTests.cs @@ -707,6 +707,10 @@ public static void CheckIsSupported() { expectedIsSupported = PlatformDetection.OpenSslPresentOnSystem; } + else if (PlatformDetection.UsesMobileAppleCrypto) + { + expectedIsSupported = false; + } Assert.Equal(expectedIsSupported, AesCcm.IsSupported); } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/AesGcmTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/AesGcmTests.cs index 514c189496f244..0322e37aac23ca 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/AesGcmTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/AesGcmTests.cs @@ -875,6 +875,10 @@ public static void CheckIsSupported() { expectedIsSupported = PlatformDetection.OpenSslPresentOnSystem; } + else if (PlatformDetection.UsesMobileAppleCrypto) + { + expectedIsSupported = false; + } Assert.Equal(expectedIsSupported, AesGcm.IsSupported); } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs index 245f023acb53e7..067a50a10015de 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/CryptoConfigTests.cs @@ -222,8 +222,11 @@ public static IEnumerable AllValidNames yield return new object[] { "RSA", "System.Security.Cryptography.RSACryptoServiceProvider", true }; yield return new object[] { "System.Security.Cryptography.RSA", "System.Security.Cryptography.RSACryptoServiceProvider", true }; yield return new object[] { "System.Security.Cryptography.AsymmetricAlgorithm", "System.Security.Cryptography.RSACryptoServiceProvider", true }; - yield return new object[] { "DSA", "System.Security.Cryptography.DSACryptoServiceProvider", true }; - yield return new object[] { "System.Security.Cryptography.DSA", "System.Security.Cryptography.DSACryptoServiceProvider", true }; + if (!PlatformDetection.UsesMobileAppleCrypto) + { + yield return new object[] { "DSA", "System.Security.Cryptography.DSACryptoServiceProvider", true }; + yield return new object[] { "System.Security.Cryptography.DSA", "System.Security.Cryptography.DSACryptoServiceProvider", true }; + } yield return new object[] { "ECDsa", "System.Security.Cryptography.ECDsaCng", true }; yield return new object[] { "ECDsaCng", "System.Security.Cryptography.ECDsaCng", false }; yield return new object[] { "System.Security.Cryptography.ECDsaCng", null, false }; diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/DSACryptoServiceProviderTests.cs b/src/libraries/System.Security.Cryptography.Csp/tests/DSACryptoServiceProviderTests.cs index a766c5fe36688d..8a703c33d1d25a 100644 --- a/src/libraries/System.Security.Cryptography.Csp/tests/DSACryptoServiceProviderTests.cs +++ b/src/libraries/System.Security.Cryptography.Csp/tests/DSACryptoServiceProviderTests.cs @@ -2,10 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Security.Cryptography.Dsa.Tests; +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.Csp.Tests { + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public class DSACryptoServiceProviderTests { const int PROV_DSS_DH = 13; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs index 94e8c460e4ce52..1a23c5d0be81e9 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Internal/Cryptography/Pal/AnyOS/ManagedPal.cs @@ -84,7 +84,7 @@ public override byte[] GetSubjectKeyIdentifier(X509Certificate2 certificate) if (typeof(T) == typeof(ECDsa)) return (T?)(object?)certificate.GetECDsaPrivateKey(); #if NETCOREAPP || NETSTANDARD2_1 - if (typeof(T) == typeof(DSA)) + if (typeof(T) == typeof(DSA) && Internal.Cryptography.Helpers.IsDSASupported) return (T?)(object?)certificate.GetDSAPrivateKey(); #endif diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs index c2c51f6dc3ef8e..d6d6c5b4bafab7 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; using Internal.Cryptography; -using System.Diagnostics.CodeAnalysis; namespace System.Security.Cryptography.Pkcs { @@ -13,11 +14,14 @@ internal partial class CmsSignature { static partial void PrepareRegistrationDsa(Dictionary lookup) { - lookup.Add(Oids.DsaWithSha1, new DSACmsSignature(Oids.DsaWithSha1, HashAlgorithmName.SHA1)); - lookup.Add(Oids.DsaWithSha256, new DSACmsSignature(Oids.DsaWithSha256, HashAlgorithmName.SHA256)); - lookup.Add(Oids.DsaWithSha384, new DSACmsSignature(Oids.DsaWithSha384, HashAlgorithmName.SHA384)); - lookup.Add(Oids.DsaWithSha512, new DSACmsSignature(Oids.DsaWithSha512, HashAlgorithmName.SHA512)); - lookup.Add(Oids.Dsa, new DSACmsSignature(null, default)); + if (Helpers.IsDSASupported) + { + lookup.Add(Oids.DsaWithSha1, new DSACmsSignature(Oids.DsaWithSha1, HashAlgorithmName.SHA1)); + lookup.Add(Oids.DsaWithSha256, new DSACmsSignature(Oids.DsaWithSha256, HashAlgorithmName.SHA256)); + lookup.Add(Oids.DsaWithSha384, new DSACmsSignature(Oids.DsaWithSha384, HashAlgorithmName.SHA384)); + lookup.Add(Oids.DsaWithSha512, new DSACmsSignature(Oids.DsaWithSha512, HashAlgorithmName.SHA512)); + lookup.Add(Oids.Dsa, new DSACmsSignature(null, default)); + } } private sealed class DSACmsSignature : CmsSignature @@ -58,6 +62,8 @@ internal override bool VerifySignature( _signatureAlgorithm)); } + Debug.Assert(Helpers.IsDSASupported); + DSA? dsa = certificate.GetDSAPublicKey(); if (dsa == null) @@ -105,6 +111,8 @@ protected override bool Sign( [NotNullWhen(true)] out string? signatureAlgorithm, [NotNullWhen(true)] out byte[]? signatureValue) { + Debug.Assert(Helpers.IsDSASupported); + // If there's no private key, fall back to the public key for a "no private key" exception. DSA? dsa = key as DSA ?? PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs index ce65f7a76e6451..c53e966a72d9e5 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.cs @@ -535,6 +535,7 @@ public static void AddSignerWithNegativeSerial() [Theory] [InlineData(SubjectIdentifierType.IssuerAndSerialNumber, false)] [InlineData(SubjectIdentifierType.IssuerAndSerialNumber, true)] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void AddFirstSigner_DSA(SubjectIdentifierType identifierType, bool detached) { ContentInfo contentInfo = new ContentInfo(new byte[] { 9, 8, 7, 6, 5 }); @@ -1036,7 +1037,16 @@ public static void EnsureExtraCertsAdded(bool newDocument) else { cms = new SignedCms(); - cms.Decode(SignedDocuments.OneDsa1024); + + // DSA is not supported on mobile Apple platforms, so use ECDsa signed document instead + if (PlatformDetection.UsesMobileAppleCrypto) + { + cms.Decode(SignedDocuments.SHA256ECDSAWithRsaSha256DigestIdentifier); + } + else + { + cms.Decode(SignedDocuments.OneDsa1024); + } } int preCount = cms.Certificates.Count; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs index a24a66d1f39127..9d90fe7905550f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs @@ -70,6 +70,7 @@ public static void SignCmsUsingExplicitRSAKey() } [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void SignCmsUsingExplicitDSAKey() { using (X509Certificate2 cert = Certificates.Dsa1024.TryGetCertificateWithPrivateKey()) @@ -100,6 +101,7 @@ public static void SignCmsUsingExplicitECDsaP521Key() } [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void CounterSignCmsUsingExplicitRSAKeyForFirstSignerAndDSAForCounterSignature() { using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) @@ -112,6 +114,7 @@ public static void CounterSignCmsUsingExplicitRSAKeyForFirstSignerAndDSAForCount } [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void CounterSignCmsUsingExplicitDSAKeyForFirstSignerAndECDsaForCounterSignature() { using (X509Certificate2 cert = Certificates.Dsa1024.TryGetCertificateWithPrivateKey()) @@ -202,7 +205,7 @@ public static void SignCmsUsingRSACertWithNotMatchingKeyThrows() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX, "Creating DSA keys is not supported on OSX")] + [SkipOnPlatform(PlatformSupport.AppleCrypto, "Creating DSA keys is not supported on OSX")] public static void SignCmsUsingDSACertWithNotMatchingKeyThrows() { byte[] content = { 9, 8, 7, 6, 5 }; @@ -401,6 +404,7 @@ public static void AddSigner_RSA_EphemeralKey() } [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void AddSigner_DSA_EphemeralKey() { using (DSA dsa = DSA.Create()) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs index ff67c37e9ec9dd..9c558870210a0a 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.cs @@ -444,6 +444,7 @@ public static void RemoveCounterSignature_WithNoMatch() [InlineData(0)] [InlineData(1)] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "NetFx bug")] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void RemoveCounterSignature_EncodedInSingleAttribute(int indexToRemove) { SignedCms cms = new SignedCms(); @@ -698,6 +699,7 @@ public static void AddCounterSignerToUnsortedAttributeSignature() } [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public static void AddCounterSigner_DSA() { SignedCms cms = new SignedCms(); @@ -1027,7 +1029,16 @@ private static void AddSecondCounterSignature_NoSignature(bool withCertificate, public static void EnsureExtraCertsAdded() { SignedCms cms = new SignedCms(); - cms.Decode(SignedDocuments.OneDsa1024); + + // DSA is not supported on mobile Apple platforms, so use ECDsa signed document instead + if (PlatformDetection.UsesMobileAppleCrypto) + { + cms.Decode(SignedDocuments.SHA256ECDSAWithRsaSha256DigestIdentifier); + } + else + { + cms.Decode(SignedDocuments.OneDsa1024); + } int preCount = cms.Certificates.Count; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs index 3bdef6bd3decd6..cda2262f782058 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignerInfoTests.netcoreapp.cs @@ -246,7 +246,13 @@ public static void SignerInfo_AddRemoveUnsignedAttributes_JoinCounterSignaturesA cms.ComputeSignature(signer); } - using (X509Certificate2 counterSigner1cert = Certificates.Dsa1024.TryGetCertificateWithPrivateKey()) + // DSA is not supported on mobile Apple platforms, so use ECDsa key instead + X509Certificate2 counterSigner1cert = + PlatformDetection.UsesMobileAppleCrypto ? + Certificates.ECDsaP521Win.TryGetCertificateWithPrivateKey() : + Certificates.Dsa1024.TryGetCertificateWithPrivateKey(); + + using (counterSigner1cert) { CmsSigner counterSigner = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, counterSigner1cert); counterSigner.IncludeOption = X509IncludeOption.EndCertOnly; diff --git a/src/libraries/System.Security.Cryptography.Primitives/tests/CryptoConfigTests.cs b/src/libraries/System.Security.Cryptography.Primitives/tests/CryptoConfigTests.cs index 36bb7f85caffce..205de5e17212c5 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/tests/CryptoConfigTests.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/tests/CryptoConfigTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.CryptoConfigTests @@ -126,9 +127,20 @@ public static void NamedSymmetricAlgorithmCreate(string identifier, Type baseTyp [InlineData("RSA", typeof(RSA))] [InlineData("System.Security.Cryptography.RSA", typeof(RSA))] [InlineData("ECDsa", typeof(ECDsa))] + public static void NamedAsymmetricAlgorithmCreate(string identifier, Type baseType) + { + using (AsymmetricAlgorithm created = AsymmetricAlgorithm.Create(identifier)) + { + Assert.NotNull(created); + Assert.IsAssignableFrom(baseType, created); + } + } + + [Theory] [InlineData("DSA", typeof(DSA))] [InlineData("System.Security.Cryptography.DSA", typeof(DSA))] - public static void NamedAsymmetricAlgorithmCreate(string identifier, Type baseType) + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] + public static void NamedAsymmetricAlgorithmCreate_DSA(string identifier, Type baseType) { using (AsymmetricAlgorithm created = AsymmetricAlgorithm.Create(identifier)) { @@ -137,6 +149,15 @@ public static void NamedAsymmetricAlgorithmCreate(string identifier, Type baseTy } } + [Theory] + [InlineData("DSA")] + [InlineData("System.Security.Cryptography.DSA")] + [PlatformSpecific(PlatformSupport.MobileAppleCrypto)] + public static void NamedAsymmetricAlgorithmCreate_DSA_NotSupported(string identifier) + { + Assert.Null(AsymmetricAlgorithm.Create(identifier)); + } + [Fact] public static void NamedCreate_Mismatch() { diff --git a/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj b/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj index ab43c57e984c49..3131378207d2d4 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj @@ -4,6 +4,8 @@ true + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs index 992d44d0824b9d..4b7bdf649bd79a 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs @@ -34,6 +34,9 @@ public CertificateRequest(string subjectName, System.Security.Cryptography.RSA k public byte[] CreateSigningRequest() { throw null; } public byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public static partial class DSACertificateExtensions { public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) { throw null; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs index 42744defa1cdab..7d54eaa38b13f3 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs @@ -3,6 +3,7 @@ using Internal.Cryptography; using Internal.Cryptography.Pal; +using System.Runtime.Versioning; namespace System.Security.Cryptography.X509Certificates { @@ -10,6 +11,9 @@ namespace System.Security.Cryptography.X509Certificates /// Provides extension methods for retrieving implementations for the /// public and private keys of a . /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public static class DSACertificateExtensions { /// diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs index b16df4a367f996..76022ec91b6abb 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs @@ -943,7 +943,7 @@ public static X509Certificate2 CreateFromPem(ReadOnlySpan certPem, ReadOnl return keyAlgorithm switch { Oids.Rsa => ExtractKeyFromPem(keyPem, s_RsaPublicKeyPrivateKeyLabels, RSA.Create, certificate.CopyWithPrivateKey), - Oids.Dsa => ExtractKeyFromPem(keyPem, s_DsaPublicKeyPrivateKeyLabels, DSA.Create, certificate.CopyWithPrivateKey), + Oids.Dsa when Helpers.IsDSASupported => ExtractKeyFromPem(keyPem, s_DsaPublicKeyPrivateKeyLabels, DSA.Create, certificate.CopyWithPrivateKey), Oids.EcPublicKey when IsECDsa(certificate) => ExtractKeyFromPem( keyPem, @@ -1013,7 +1013,7 @@ public static X509Certificate2 CreateFromEncryptedPem(ReadOnlySpan certPem return keyAlgorithm switch { Oids.Rsa => ExtractKeyFromEncryptedPem(keyPem, password, RSA.Create, certificate.CopyWithPrivateKey), - Oids.Dsa => ExtractKeyFromEncryptedPem(keyPem, password, DSA.Create, certificate.CopyWithPrivateKey), + Oids.Dsa when Helpers.IsDSASupported => ExtractKeyFromEncryptedPem(keyPem, password, DSA.Create, certificate.CopyWithPrivateKey), Oids.EcPublicKey when IsECDsa(certificate) => ExtractKeyFromEncryptedPem( keyPem, diff --git a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs index b8b7593f96b8c3..f0c200066ae436 100644 --- a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs +++ b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs @@ -43,6 +43,9 @@ public DataReference(string uri, System.Security.Cryptography.Xml.TransformChain } public partial class DSAKeyValue : System.Security.Cryptography.Xml.KeyInfoClause { + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] public DSAKeyValue() { } public DSAKeyValue(System.Security.Cryptography.DSA key) { } public System.Security.Cryptography.DSA Key { get { throw null; } set { } } diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs index e1c4d4a7c3cbef..e491e065ccfceb 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; using System.Xml; #pragma warning disable CA5384 // Do Not Use Digital Signature Algorithm (DSA) @@ -15,6 +16,9 @@ public class DSAKeyValue : KeyInfoClause // public constructors // + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [UnsupportedOSPlatform("maccatalyst")] public DSAKeyValue() { _key = DSA.Create(); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs index a26582120fd2a9..14863aff908106 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/DSAKeyValueTest.cs @@ -13,11 +13,12 @@ using System.Linq; using System.Runtime.InteropServices; using System.Xml; +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.Xml.Tests { - + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public class DSAKeyValueTest { [Fact] @@ -51,7 +52,6 @@ public void Ctor_Dsa_Null() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/20575", TestPlatforms.OSX)] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void GetXml() { DSAKeyValue dsa = new DSAKeyValue(); @@ -80,7 +80,6 @@ public void GetXml() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/20575", TestPlatforms.OSX)] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void GetXml_SameDsa() { using (DSA dsa = DSA.Create()) @@ -92,7 +91,6 @@ public void GetXml_SameDsa() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void LoadXml() { const string pValue = "oDZlcdJA1Kf6UeNEIZqm4KDqA6zpX7CmEtAGWi9pgnBhWOUDVEfhswfsvTLR5BCbKfE6KoHvt5Hh8D1RcAko//iZkLZ+gds9y/5Oxape8tu3TUi1BnNPWu8ieXjMtdnpyudKFsCymssJked1rBeRePG23HTVwOV1DpopjRkjBEU="; @@ -132,7 +130,6 @@ public void LoadXml_Null() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void ImportDSAKeyValue() { string p = "6zJxhRqpk5yQ7sjFSr6mPepyVwpTAXSmw1oh+5Cn/z1DjFSpW6rC6sTOkE3CMNwWOwIzrpVS3bWep7wo9CaBrOPIIVe+E4sqpPeyM2wr10mQThHEsCQAjnxBhJJindf9amaBhi6sOtVNnyETFWV6yKDptZEm9c3xdl4L7ogEbX8="; diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTest.cs index 9812572ae6abd7..61534f61c2ba01 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/KeyInfoTest.cs @@ -13,6 +13,7 @@ using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Xml; +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.Xml.Tests @@ -69,7 +70,7 @@ public void KeyInfoNode() private static string xmlDSA = "

" + dsaP + "

" + dsaQ + "" + dsaG + "" + dsaY + "
"; [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public void DSAKeyValue() { using (DSA key = DSA.Create()) @@ -148,7 +149,7 @@ public void X509Data() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public void Complex() { KeyInfoName name = new KeyInfoName(); @@ -199,7 +200,7 @@ public void Complex() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public void ImportKeyNode() { string keyName = "Mono::"; diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs index 54caa519ac66bf..c6ad9ba72e8e6f 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs @@ -15,6 +15,7 @@ using System.Text; using System.Xml; using System.Xml.XPath; +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.Xml.Tests @@ -288,7 +289,7 @@ public void AsymmetricRSAMixedCaseAttributesVerifyWindows() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/20575", TestPlatforms.OSX)] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public void AsymmetricDSASignature() { SignedXml signedXml = MSDNSample(); @@ -388,7 +389,7 @@ public void AsymmetricRSAVerify() // Using empty constructor // The two other constructors don't seems to apply in verifying signatures [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public void AsymmetricDSAVerify() { string value = "/Vvq6sXEVbtZC8GwNtLQnGOy/VI=BYz/qRGjGsN1yMFPxWa3awUZm1y4I/IxOQroMxkOteRGgk1HIwhRYw==

iglVaZ+LsSL8Y0aDXmFMBwva3xHqIypr3l/LtqBH9ziV2Sh1M4JVasAiKqytWIWt/s/Uk8Ckf2tO2Ww1vsNi1NL+Kg9T7FE52sn380/rF0miwGkZeidzm74OWhykb3J+wCTXaIwOzAWI1yN7FoeoN7wzF12jjlSXAXeqPMlViqk=

u4sowiJMHilNRojtdmIuQY2YnB8=SdnN7d+wn1n+HH4Hr8MIryIRYgcXdbZ5TH7jAnuWc1koqRc1AZfcYAZ6RDf+orx6Lzn055FTFiN+1NHQfGUtXJCWW0zz0FVV1NJux7WRj8vGTldjJ5ef0oCenkpwDjcIxWsZgVobve4GPoyN1sAc1scnkJB59oupibklmF4y72A=XejzS8Z51yfl0zbYnxSYYbHqreSLjNCoGPB/KjM1TOyV5sMjz0StKtGrFWryTWc7EgvFY7kUth4e04VKf9HbK8z/FifHTXj8+Tszbjzw8GfInnBwLN+vJgbpnjtypmiI5Bm2nLiRbfkdAHP+OrKtr/EauM9GQfYuaxm3/Vj8B84=vGwGg9wqwwWP9xsoPoXu6kHArJtadiNKe9azBiUx5Ob883gd5wlKfEcGuKkBmBySGbgwxyOsIBovd9Kk48hF01ymfQzAAuHR0EdJECSsTsTTKVTLQNBU32O+PRbLYpv4E8kt6rNL83JLJCBYsqzn8J6fd2gtEyq6YOqiUSHgPE8=sQ==
This is some text
"; @@ -539,6 +540,7 @@ public void ComputeSignatureNoSigningKey() } [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] public void ComputeSignatureMissingReferencedObject() { XmlDocument doc = new XmlDocument(); diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index 61ba24acb4c46c..bdd0e35bf9b1be 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -3,6 +3,8 @@ $(NetCoreAppCurrent);net461 + diff --git a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt index 2d6940197b4f69..ae74975ddda7b1 100644 --- a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt +++ b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt @@ -171,4 +171,8 @@ Compat issues with assembly System.Security.Cryptography.Algorithms: CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.CryptoConfig' in the contract but not the implementation. Compat issues with assembly System.Threading.Tasks.Extensions: CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the implementation. -Total Issues: 158 +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +Total Issues: 162 diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 11e851a2cee925..020c562cdde8c5 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -143,10 +143,6 @@ - - - - @@ -158,15 +154,11 @@ - - - - From 6e93da23b3fcab99e34ac8f3d127a2d519bf15f4 Mon Sep 17 00:00:00 2001 From: Jo Shields Date: Fri, 21 May 2021 03:07:34 -0400 Subject: [PATCH 030/115] Rename Mac Catalyst dylib to libmonosgen, not libcoreclr (#53038) --- src/mono/mono.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono.proj b/src/mono/mono.proj index b1546603d6720f..8989fcac775d42 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -31,7 +31,7 @@ coreclr $(LibPrefix)$(CoreClrLibName)$(SharedLibExt) monosgen-2.0 - $(MonoLibName) + $(MonoLibName) $(CoreClrLibName) $(LibPrefix)$(MonoSharedLibName)$(SharedLibExt) $(LibPrefix)$(MonoLibName)$(StaticLibExt) From b4e3b8291c9d7372a3a961bfb51ab5738bb25465 Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Fri, 21 May 2021 09:29:14 +0200 Subject: [PATCH 031/115] [wasm] Fix few paths (#53049) To avoid parts of the path like: artifacts\bin\native\net6.0-Browser-Debug-wasm\/dotnet.wasm --- src/mono/wasm/wasm.proj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index d397b3808e5602..3bb7a55cfa8e2e 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -117,7 +117,7 @@ $(EmccFlags) -s MODULARIZE=1 -s EXPORT_ES6=1 -g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1 -Oz --llvm-opts 2 -DENABLE_NETCORE=1 - "$(EMSDK_PATH)/upstream/bin/wasm-opt" --strip-dwarf "$(NativeBinDir)/dotnet.wasm" -o "$(NativeBinDir)/dotnet.wasm" + "$(EMSDK_PATH)/upstream/bin/wasm-opt" --strip-dwarf "$(NativeBinDir)dotnet.wasm" -o "$(NativeBinDir)dotnet.wasm" $(ArtifactsObjDir)wasm $(WasmObjDir)\emcc-version.txt $(MonoArtifactsPath)include/mono-2.0 @@ -178,7 +178,7 @@ Overwrite="true" /> '%(Filename)%(Extension)')" /> + @@ -76,7 +77,7 @@ Exclude="mscordaccore.dll" CertificateName="MicrosoftSHA2" /> - + - true + true false true true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 56f2f777c2832d..fdbf7f3cad3d83 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -5,7 +5,7 @@ true Microsoft.NETCore.Platforms.BuildTasks - true + true false true From 4095d03c3ff593693e66a8e0abd0052da8f62685 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Fri, 21 May 2021 06:12:46 -0700 Subject: [PATCH 037/115] Com trimming related work (#52940) * COM related work and native host name changes * FB --- docs/workflow/trimming/feature-switches.md | 4 +- .../src/ILLink/ILLink.Substitutions.xml | 4 +- .../InteropServices/ComponentActivator.cs | 2 +- .../InteropServices/InMemoryAssemblyLoader.cs | 2 +- src/coreclr/vm/corelib.h | 39 +++++++++++++++---- .../ComWrappersTestsBuiltInComDisabled.csproj | 17 ++++++++ .../GlobalInstance.Marshalling.cs | 27 +++++++++++-- ...eMarshallingTestsBuiltInComDisabled.csproj | 33 ++++++++++++++++ 8 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 src/tests/Interop/COM/ComWrappers/API/ComWrappersTestsBuiltInComDisabled.csproj create mode 100644 src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstanceMarshallingTestsBuiltInComDisabled.csproj diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md index e780f9bbd388e5..ea884b411b0e06 100644 --- a/docs/workflow/trimming/feature-switches.md +++ b/docs/workflow/trimming/feature-switches.md @@ -21,8 +21,8 @@ configurations but their defaults might vary as any SDK can set the defaults dif | CustomResourceTypesSupport | System.Resources.ResourceManager.AllowCustomResourceTypes | Use of custom resource types is disabled when set to false. ResourceManager code paths that use reflection for custom types can be trimmed. | | EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization | System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization | BinaryFormatter serialization support is trimmed when set to false. | | BuiltInComInteropSupport | System.Runtime.InteropServices.BuiltInComInterop.IsSupported | Built-in COM support is trimmed when set to false. | -| EnableCPlusPlusCLIHostActivation | Internal.Runtime.InteropServices.InMemoryAssemblyLoader.IsSupported | C++/CLI host activation code is disabled when set to false and related functionality can be trimmed. | -| _EnableCallingManagedFunctionFromNativeHosting | Internal.Runtime.InteropServices.ComponentActivator.IsSupported | Getting a managed function from native hosting is disabled when set to false and related functionality can be trimmed. | +| EnableCppCLIHostActivation | System.Runtime.InteropServices.EnableCppCLIHostActivation | C++/CLI host activation code is disabled when set to false and related functionality can be trimmed. | +| _EnableConsumingManagedCodeFromNativeHosting | System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting | Getting a managed function from native hosting is disabled when set to false and related functionality can be trimmed. | Any feature-switch which defines property can be set in csproj file or on the command line as any other MSBuild property. Those without predefined property name diff --git a/src/coreclr/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml b/src/coreclr/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml index ec19ddf8d340e3..e7d1dd3482d8e7 100644 --- a/src/coreclr/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml +++ b/src/coreclr/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml @@ -3,10 +3,10 @@ - + - + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs index 205de7a9b35765..e276025cfd37bf 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs @@ -23,7 +23,7 @@ public static class ComponentActivator private static bool IsSupported { get; } = InitializeIsSupported(); - private static bool InitializeIsSupported() => AppContext.TryGetSwitch("Internal.Runtime.InteropServices.ComponentActivator.IsSupported", out bool isSupported) ? isSupported : true; + private static bool InitializeIsSupported() => AppContext.TryGetSwitch("System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting", out bool isSupported) ? isSupported : true; public delegate int ComponentEntryPoint(IntPtr args, int sizeBytes); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs index cf6dc6adc3102d..311ce31bdc95ac 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/InMemoryAssemblyLoader.cs @@ -14,7 +14,7 @@ public static class InMemoryAssemblyLoader { private static bool IsSupported { get; } = InitializeIsSupported(); - private static bool InitializeIsSupported() => AppContext.TryGetSwitch("Internal.Runtime.InteropServices.InMemoryAssemblyLoader.IsSupported", out bool isSupported) ? isSupported : true; + private static bool InitializeIsSupported() => AppContext.TryGetSwitch("System.Runtime.InteropServices.EnableCppCLIHostActivation", out bool isSupported) ? isSupported : true; /// /// Loads into an isolated AssemblyLoadContext an assembly that has already been loaded into memory by the OS loader as a native module. diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index f9e0de124108b5..5fe53b824e83a9 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -68,6 +68,21 @@ #define DEFINE_FIELD_U(stringName, unmanagedContainingType, unmanagedOffset) #endif +// +// BEGIN_ILLINK_FEATURE_SWITCH and END_ILLINK_FEATURE_SWITCH allow IL linker to guard types behind a feature switch. +// Current support is only around class scope and not for standalone members of classes. +// See usage in this file itself and on the link (the assembly name for feature switch in this file will be System.Private.CoreLib), +// https://github.com/dotnet/designs/blob/main/accepted/2020/feature-switch.md#generate-the-right-input-for-the-linker-in-sdk +// +#ifndef BEGIN_ILLINK_FEATURE_SWITCH +#define BEGIN_ILLINK_FEATURE_SWITCH(featureName, featureValue, featureDefault) +#endif + +#ifndef END_ILLINK_FEATURE_SWITCH +#define END_ILLINK_FEATURE_SWITCH() +#endif + + // NOTE: Make this window really wide if you want to read the table... DEFINE_CLASS(ACTIVATOR, System, Activator) @@ -176,6 +191,7 @@ DEFINE_METHOD(CLASS, GET_PROPERTY_INFO, GetPropertyInfo, DEFINE_METHOD(CLASS, FORWARD_CALL_TO_INVOKE, ForwardCallToInvokeMember, IM_Str_BindingFlags_Obj_ArrObj_ArrBool_ArrInt_ArrType_Type_RetObj) #endif // FEATURE_COMINTEROP +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(BSTR_WRAPPER, Interop, BStrWrapper) DEFINE_CLASS(CURRENCY_WRAPPER, Interop, CurrencyWrapper) @@ -184,7 +200,9 @@ DEFINE_CLASS(ERROR_WRAPPER, Interop, ErrorWrapper) DEFINE_CLASS(UNKNOWN_WRAPPER, Interop, UnknownWrapper) DEFINE_CLASS(VARIANT_WRAPPER, Interop, VariantWrapper) #endif // FEATURE_COMINTEROP +END_ILLINK_FEATURE_SWITCH() +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS_U(System, __ComObject, ComObject) DEFINE_FIELD_U(m_ObjectToDataMap, ComObject, m_ObjectToDataMap) @@ -201,6 +219,7 @@ DEFINE_METHOD(LICENSE_INTEROP_PROXY, GETCURRENTCONTEXTINFO, GetCurrentContextI DEFINE_METHOD(LICENSE_INTEROP_PROXY, SAVEKEYINCURRENTCONTEXT, SaveKeyInCurrentContext, IM_IntPtr_RetVoid) #endif // FEATURE_COMINTEROP +END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS_U(Interop, CriticalHandle, CriticalHandle) DEFINE_FIELD_U(handle, CriticalHandle, m_handle) @@ -285,10 +304,6 @@ DEFINE_METHOD(CURRENCY, DECIMAL_CTOR, .ctor, DEFINE_CLASS(DATE_TIME, System, DateTime) DEFINE_METHOD(DATE_TIME, LONG_CTOR, .ctor, IM_Long_RetVoid) -#ifdef FEATURE_COMINTEROP -DEFINE_CLASS(DATE_TIME_OFFSET, System, DateTimeOffset) -#endif // FEATURE_COMINTEROP - DEFINE_CLASS(DECIMAL, System, Decimal) DEFINE_METHOD(DECIMAL, CURRENCY_CTOR, .ctor, IM_Currency_RetVoid) @@ -402,6 +417,7 @@ DEFINE_METHOD(FIELD_INFO, GET_VALUE, GetValue, DEFINE_CLASS(GUID, System, Guid) +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(VARIANT, System, Variant) DEFINE_METHOD(VARIANT, CONVERT_OBJECT_TO_VARIANT,MarshalHelperConvertObjectToVariant,SM_Obj_RefVariant_RetVoid) @@ -413,6 +429,7 @@ DEFINE_FIELD_U(_objref, VariantData, m_objref) DEFINE_FIELD_U(_data, VariantData, m_data) DEFINE_FIELD_U(_flags, VariantData, m_flags) #endif // FEATURE_COMINTEROP +END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS(IASYNCRESULT, System, IAsyncResult) @@ -431,11 +448,13 @@ DEFINE_CLASS(DYNAMICINTERFACECASTABLEHELPERS, Interop, DynamicInterfaceCasta DEFINE_METHOD(DYNAMICINTERFACECASTABLEHELPERS, IS_INTERFACE_IMPLEMENTED, IsInterfaceImplemented, SM_IDynamicInterfaceCastable_RuntimeType_Bool_RetBool) DEFINE_METHOD(DYNAMICINTERFACECASTABLEHELPERS, GET_INTERFACE_IMPLEMENTATION, GetInterfaceImplementation, SM_IDynamicInterfaceCastable_RuntimeType_RetRtType) +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(ICUSTOM_QUERYINTERFACE, Interop, ICustomQueryInterface) DEFINE_METHOD(ICUSTOM_QUERYINTERFACE, GET_INTERFACE, GetInterface, IM_RefGuid_OutIntPtr_RetCustomQueryInterfaceResult) DEFINE_CLASS(CUSTOMQUERYINTERFACERESULT, Interop, CustomQueryInterfaceResult) #endif //FEATURE_COMINTEROP +END_ILLINK_FEATURE_SWITCH() #ifdef FEATURE_COMWRAPPERS DEFINE_CLASS(COMWRAPPERS, Interop, ComWrappers) @@ -467,11 +486,11 @@ DEFINE_METHOD(IREFLECT, GET_FIELDS, GetFields, DEFINE_METHOD(IREFLECT, GET_METHODS, GetMethods, IM_BindingFlags_RetArrMethodInfo) DEFINE_METHOD(IREFLECT, INVOKE_MEMBER, InvokeMember, IM_Str_BindingFlags_Binder_Obj_ArrObj_ArrParameterModifier_CultureInfo_ArrStr_RetObj) - +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(LCID_CONVERSION_TYPE, Interop, LCIDConversionAttribute) #endif // FEATURE_COMINTEROP - +END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS(MARSHAL, Interop, Marshal) #ifdef FEATURE_COMINTEROP @@ -618,10 +637,11 @@ DEFINE_METHOD(SINGLE, GET_HASH_CODE, GetHashCode, IM_RetI DEFINE_CLASS(__CANON, System, __Canon) - +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(OLE_AUT_BINDER, System, OleAutBinder) #endif // FEATURE_COMINTEROP +END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS(MONITOR, Threading, Monitor) DEFINE_METHOD(MONITOR, ENTER, Enter, SM_Obj_RetVoid) @@ -1060,6 +1080,7 @@ DEFINE_METHOD(ANSIBSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, DEFINE_METHOD(ANSIBSTRMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_IntPtr_RetStr) DEFINE_METHOD(ANSIBSTRMARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RetVoid) +BEGIN_ILLINK_FEATURE_SWITCH(System.Runtime.InteropServices.BuiltInComInterop.IsSupported, true, true) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(OBJECTMARSHALER, StubHelpers, ObjectMarshaler) DEFINE_METHOD(OBJECTMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_ObjIntPtr_RetVoid) @@ -1080,6 +1101,7 @@ DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CONVERT_SPACE_TO_MANAGED, ConvertSpa DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_MANAGED, ConvertContentsToManaged, SM_IntPtr_RefObj_IntPtr_RetVoid) DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RefObj_IntPtr_RetVoid) #endif // FEATURE_COMINTEROP +END_ILLINK_FEATURE_SWITCH() DEFINE_CLASS(DATEMARSHALER, StubHelpers, DateMarshaler) DEFINE_METHOD(DATEMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_DateTime_RetDbl) @@ -1274,9 +1296,10 @@ DEFINE_FIELD_U(_generationInfo2, GCMemoryInfoData, generationInfo2) DEFINE_FIELD_U(_generationInfo3, GCMemoryInfoData, generationInfo3) DEFINE_FIELD_U(_generationInfo4, GCMemoryInfoData, generationInfo4) - #undef DEFINE_CLASS #undef DEFINE_METHOD #undef DEFINE_FIELD #undef DEFINE_CLASS_U #undef DEFINE_FIELD_U +#undef BEGIN_ILLINK_FEATURE_SWITCH +#undef END_ILLINK_FEATURE_SWITCH diff --git a/src/tests/Interop/COM/ComWrappers/API/ComWrappersTestsBuiltInComDisabled.csproj b/src/tests/Interop/COM/ComWrappers/API/ComWrappersTestsBuiltInComDisabled.csproj new file mode 100644 index 00000000000000..a51b1eb40779fc --- /dev/null +++ b/src/tests/Interop/COM/ComWrappers/API/ComWrappersTestsBuiltInComDisabled.csproj @@ -0,0 +1,17 @@ + + + Exe + true + + + + + + + + + + + + + diff --git a/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.Marshalling.cs b/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.Marshalling.cs index 7a03a67a05100e..d01d79f153db49 100644 --- a/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.Marshalling.cs +++ b/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.Marshalling.cs @@ -22,18 +22,37 @@ static int Main(string[] doNotUse) { try { + bool builtInComDisabled=false; + var comConfig = AppContext.GetData("System.Runtime.InteropServices.BuiltInComInterop.IsSupported"); + if(comConfig != null && !bool.Parse(comConfig.ToString())) + { + builtInComDisabled=true; + } + Console.WriteLine($"Built-in COM Disabled?: {builtInComDisabled}"); + + // The first test registers a global ComWrappers instance for marshalling // Subsequents tests assume the global instance has already been registered. ValidateRegisterForMarshalling(); ValidateMarshalAPIs(validateUseRegistered: true); - ValidateMarshalAPIs(validateUseRegistered: false); + if(!builtInComDisabled) + { + ValidateMarshalAPIs(validateUseRegistered: false); + } ValidatePInvokes(validateUseRegistered: true); - ValidatePInvokes(validateUseRegistered: false); + if(!builtInComDisabled) + { + ValidatePInvokes(validateUseRegistered: false); + } - ValidateComActivation(validateUseRegistered: true); - ValidateComActivation(validateUseRegistered: false); + if(!builtInComDisabled) + { + // This calls ValidateNativeServerActivation which calls Marshal.GetTypeFromCLSID that is not supported + ValidateComActivation(validateUseRegistered: true); + ValidateComActivation(validateUseRegistered: false); + } ValidateNotRegisteredForTrackerSupport(); diff --git a/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstanceMarshallingTestsBuiltInComDisabled.csproj b/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstanceMarshallingTestsBuiltInComDisabled.csproj new file mode 100644 index 00000000000000..11622e1c77524c --- /dev/null +++ b/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstanceMarshallingTestsBuiltInComDisabled.csproj @@ -0,0 +1,33 @@ + + + Exe + App.manifest + true + true + true + + + + + + + + + + + + + false + Content + Always + + + + + PreserveNewest + + + + + + From fd693619f9a99744ea3d28c87a602c900fbe01e8 Mon Sep 17 00:00:00 2001 From: Maxim Lipnin Date: Fri, 21 May 2021 16:48:49 +0300 Subject: [PATCH 038/115] Mark some APIs as unsupported on MacCatalyst (#53075) --- .../src/AnsiParsingLogConsole.cs | 1 + .../ref/Microsoft.VisualBasic.Core.cs | 49 +++++++++++-------- .../CompilerServices/VB6BinaryFile.vb | 2 + .../VisualBasic/CompilerServices/VB6File.vb | 6 +++ .../CompilerServices/VB6RandomFile.vb | 2 + .../src/Microsoft/VisualBasic/FileSystem.vb | 7 +++ .../System.Console/ref/System.Console.cs | 35 ++++++++++--- .../System.Console/src/System/Console.cs | 27 ++++++++++ .../ref/System.Diagnostics.Process.cs | 11 ++++- .../src/System/Diagnostics/Process.NonUap.cs | 1 + .../src/System/Diagnostics/Process.Unix.cs | 1 + .../src/System/Diagnostics/Process.Windows.cs | 1 + .../src/System/Diagnostics/Process.cs | 7 +++ .../src/System/IO/FileStream.cs | 2 + .../System.Runtime/ref/System.Runtime.cs | 14 +++--- ...System.Security.Cryptography.Algorithms.cs | 12 ++--- .../System/Security/Cryptography/AesCcm.cs | 2 +- .../System/Security/Cryptography/AesGcm.cs | 2 +- .../Security/Cryptography/ChaCha20Poly1305.cs | 2 +- .../src/System/Security/Cryptography/DSA.cs | 6 +-- ....Security.Cryptography.X509Certificates.cs | 2 +- .../DSACertificateExtensions.cs | 2 +- .../ref/System.Security.Cryptography.Xml.cs | 2 +- .../Security/Cryptography/Xml/DSAKeyValue.cs | 2 +- 24 files changed, 145 insertions(+), 53 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs index 8c22f9d93ca4df..ce041e917876fe 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParsingLogConsole.cs @@ -10,6 +10,7 @@ namespace Microsoft.Extensions.Logging.Console [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] internal sealed class AnsiParsingLogConsole : IConsole { diff --git a/src/libraries/Microsoft.VisualBasic.Core/ref/Microsoft.VisualBasic.Core.cs b/src/libraries/Microsoft.VisualBasic.Core/ref/Microsoft.VisualBasic.Core.cs index 0dc88f97333ee4..2f3be043a3a020 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/ref/Microsoft.VisualBasic.Core.cs +++ b/src/libraries/Microsoft.VisualBasic.Core/ref/Microsoft.VisualBasic.Core.cs @@ -403,24 +403,28 @@ public static void Input(int FileNumber, ref long Value) { } public static void Input(int FileNumber, ref object Value) { } public static void Input(int FileNumber, ref float Value) { } public static void Input(int FileNumber, ref string Value) { } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static string InputString(int FileNumber, int CharCount) { throw null; } public static void Kill(string PathName) { } public static string LineInput(int FileNumber) { throw null; } public static long Loc(int FileNumber) { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Lock(int FileNumber) { } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Lock(int FileNumber, long Record) { } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Lock(int FileNumber, long FromRecord, long ToRecord) { } public static long LOF(int FileNumber) { throw null; } public static void MkDir(string Path) { } @@ -436,17 +440,20 @@ public static void SetAttr(string PathName, Microsoft.VisualBasic.FileAttribute public static Microsoft.VisualBasic.SpcInfo SPC(short Count) { throw null; } public static Microsoft.VisualBasic.TabInfo TAB() { throw null; } public static Microsoft.VisualBasic.TabInfo TAB(short Column) { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Unlock(int FileNumber) { } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Unlock(int FileNumber, long Record) { } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Unlock(int FileNumber, long FromRecord, long ToRecord) { } public static void Write(int FileNumber, params object[] Output) { } public static void WriteLine(int FileNumber, params object[] Output) { } diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6BinaryFile.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6BinaryFile.vb index e43d3822eacfcc..faca3de1bb5b63 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6BinaryFile.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6BinaryFile.vb @@ -27,6 +27,7 @@ Namespace Microsoft.VisualBasic.CompilerServices ' the implementation of Lock in base class VB6RandomFile does not handle m_lRecordLen=-1 + Friend Overloads Overrides Sub Lock(ByVal lStart As Long, ByVal lEnd As Long) @@ -53,6 +54,7 @@ Namespace Microsoft.VisualBasic.CompilerServices ' see Lock description + Friend Overloads Overrides Sub Unlock(ByVal lStart As Long, ByVal lEnd As Long) diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6File.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6File.vb index 1a6793bd160053..4ab67a1c7b34d6 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6File.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6File.vb @@ -604,6 +604,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Function + Friend Overridable Overloads Sub Lock() @@ -612,6 +613,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overridable Overloads Sub Unlock() @@ -619,6 +621,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overridable Overloads Sub Lock(ByVal Record As Long) @@ -630,6 +633,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overridable Overloads Sub Unlock(ByVal Record As Long) @@ -641,6 +645,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overridable Overloads Sub Lock(ByVal RecordStart As Long, ByVal RecordEnd As Long) @@ -652,6 +657,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overridable Overloads Sub Unlock(ByVal RecordStart As Long, ByVal RecordEnd As Long) diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6RandomFile.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6RandomFile.vb index 7d47dfa1e191d0..f325494ba2eb85 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6RandomFile.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/CompilerServices/VB6RandomFile.vb @@ -123,6 +123,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overloads Overrides Sub Lock(ByVal lStart As Long, ByVal lEnd As Long) @@ -140,6 +141,7 @@ Namespace Microsoft.VisualBasic.CompilerServices End Sub + Friend Overloads Overrides Sub Unlock(ByVal lStart As Long, ByVal lEnd As Long) diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileSystem.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileSystem.vb index 2590c49e89fe4f..a19189d80e21c5 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileSystem.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileSystem.vb @@ -1010,6 +1010,7 @@ Namespace Microsoft.VisualBasic End Sub + Public Function InputString(ByVal FileNumber As Integer, ByVal CharCount As Integer) As String @@ -1050,6 +1051,7 @@ Namespace Microsoft.VisualBasic End Function + Public Sub Lock(ByVal FileNumber As Integer) @@ -1058,6 +1060,7 @@ Namespace Microsoft.VisualBasic End Sub + Public Sub Lock(ByVal FileNumber As Integer, ByVal Record As Long) @@ -1066,6 +1069,7 @@ Namespace Microsoft.VisualBasic End Sub + Public Sub Lock(ByVal FileNumber As Integer, ByVal FromRecord As Long, ByVal ToRecord As Long) @@ -1074,6 +1078,7 @@ Namespace Microsoft.VisualBasic End Sub + Public Sub Unlock(ByVal FileNumber As Integer) @@ -1082,6 +1087,7 @@ Namespace Microsoft.VisualBasic End Sub + Public Sub Unlock(ByVal FileNumber As Integer, ByVal Record As Long) @@ -1090,6 +1096,7 @@ Namespace Microsoft.VisualBasic End Sub + Public Sub Unlock(ByVal FileNumber As Integer, ByVal FromRecord As Long, ByVal ToRecord As Long) diff --git a/src/libraries/System.Console/ref/System.Console.cs b/src/libraries/System.Console/ref/System.Console.cs index 56300be32fdde3..a64e57726c2f6c 100644 --- a/src/libraries/System.Console/ref/System.Console.cs +++ b/src/libraries/System.Console/ref/System.Console.cs @@ -11,38 +11,44 @@ public static partial class Console [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.ConsoleColor BackgroundColor { get { throw null; } set { } } - public static int BufferHeight { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public static int BufferWidth { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public static int BufferHeight { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public static int BufferWidth { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static bool CapsLock { get { throw null; } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static int CursorLeft { get { throw null; } set { } } - public static int CursorSize { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public static int CursorSize { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static int CursorTop { get { throw null; } set { } } - public static bool CursorVisible { [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] get { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] set { } } + public static bool CursorVisible { [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] get { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] set { } } public static System.IO.TextWriter Error { get { throw null; } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.ConsoleColor ForegroundColor { get { throw null; } set { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.IO.TextReader In { get { throw null; } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Text.Encoding InputEncoding { get { throw null; } set { } } public static bool IsErrorRedirected { get { throw null; } } @@ -52,46 +58,53 @@ public static partial class Console [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static int LargestWindowHeight { get { throw null; } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static int LargestWindowWidth { get { throw null; } } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static bool NumberLock { get { throw null; } } public static System.IO.TextWriter Out { get { throw null; } } - public static System.Text.Encoding OutputEncoding { get { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] set { } } - public static string Title { [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] get { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] set { } } + public static System.Text.Encoding OutputEncoding { get { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] set { } } + public static string Title { [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] get { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] set { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static bool TreatControlCAsInput { get { throw null; } set { } } - public static int WindowHeight { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public static int WindowHeight { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } public static int WindowLeft { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } public static int WindowTop { get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public static int WindowWidth { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public static int WindowWidth { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static event System.ConsoleCancelEventHandler? CancelKeyPress { add { } remove { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Beep() { } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static void Beep(int frequency, int duration) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void Clear() { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static (int Left, int Top) GetCursorPosition() { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] @@ -103,6 +116,7 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.IO.Stream OpenStandardInput() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] @@ -116,11 +130,13 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.ConsoleKeyInfo ReadKey() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.ConsoleKeyInfo ReadKey(bool intercept) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] @@ -129,6 +145,7 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void ResetColor() { } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] @@ -136,12 +153,14 @@ public static void SetBufferSize(int width, int height) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void SetCursorPosition(int left, int top) { } public static void SetError(System.IO.TextWriter newError) { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static void SetIn(System.IO.TextReader newIn) { } public static void SetOut(System.IO.TextWriter newOut) { } diff --git a/src/libraries/System.Console/src/System/Console.cs b/src/libraries/System.Console/src/System/Console.cs index fe4a36ea400946..6bbcb9f0dea414 100644 --- a/src/libraries/System.Console/src/System/Console.cs +++ b/src/libraries/System.Console/src/System/Console.cs @@ -36,6 +36,7 @@ public static class Console [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static TextReader In { @@ -63,6 +64,7 @@ static TextReader EnsureInitialized() [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static Encoding InputEncoding { @@ -121,6 +123,7 @@ public static Encoding OutputEncoding } [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] set { @@ -166,6 +169,7 @@ public static bool KeyAvailable [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static ConsoleKeyInfo ReadKey() { @@ -175,6 +179,7 @@ public static ConsoleKeyInfo ReadKey() [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static ConsoleKeyInfo ReadKey(bool intercept) { @@ -298,6 +303,7 @@ public static int CursorSize [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { return ConsolePal.CursorSize; } [SupportedOSPlatform("windows")] @@ -321,6 +327,7 @@ public static bool CapsLock [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static ConsoleColor BackgroundColor { @@ -331,6 +338,7 @@ public static ConsoleColor BackgroundColor [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static ConsoleColor ForegroundColor { @@ -341,6 +349,7 @@ public static ConsoleColor ForegroundColor [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static void ResetColor() { @@ -352,6 +361,7 @@ public static int BufferWidth [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { return ConsolePal.BufferWidth; } [SupportedOSPlatform("windows")] @@ -363,6 +373,7 @@ public static int BufferHeight [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { return ConsolePal.BufferHeight; } [SupportedOSPlatform("windows")] @@ -394,6 +405,7 @@ public static int WindowWidth [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { return ConsolePal.WindowWidth; } [SupportedOSPlatform("windows")] @@ -405,6 +417,7 @@ public static int WindowHeight [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { return ConsolePal.WindowHeight; } [SupportedOSPlatform("windows")] @@ -426,6 +439,7 @@ public static void SetWindowSize(int width, int height) [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static int LargestWindowWidth { @@ -435,6 +449,7 @@ public static int LargestWindowWidth [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static int LargestWindowHeight { @@ -448,6 +463,7 @@ public static bool CursorVisible [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] set { ConsolePal.CursorVisible = value; } } @@ -455,6 +471,7 @@ public static bool CursorVisible [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static int CursorLeft { @@ -465,6 +482,7 @@ public static int CursorLeft [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static int CursorTop { @@ -480,6 +498,7 @@ public static int CursorTop [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static (int Left, int Top) GetCursorPosition() { @@ -493,6 +512,7 @@ public static string Title [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] set { @@ -503,6 +523,7 @@ public static string Title [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static void Beep() { @@ -529,6 +550,7 @@ public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static void Clear() { @@ -538,6 +560,7 @@ public static void Clear() [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static void SetCursorPosition(int left, int top) { @@ -553,6 +576,7 @@ public static void SetCursorPosition(int left, int top) [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static event ConsoleCancelEventHandler? CancelKeyPress { @@ -590,6 +614,7 @@ public static event ConsoleCancelEventHandler? CancelKeyPress [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static bool TreatControlCAsInput { @@ -600,6 +625,7 @@ public static bool TreatControlCAsInput [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static Stream OpenStandardInput() { @@ -651,6 +677,7 @@ public static Stream OpenStandardError(int bufferSize) [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static void SetIn(TextReader newIn) { diff --git a/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs b/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs index 1dd4f03e018953..c26aab9f911a48 100644 --- a/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs +++ b/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs @@ -43,8 +43,8 @@ public Process() { } public System.Diagnostics.ProcessModule? MainModule { get { throw null; } } public System.IntPtr MainWindowHandle { get { throw null; } } public string MainWindowTitle { get { throw null; } } - public System.IntPtr MaxWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public System.IntPtr MinWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public System.IntPtr MaxWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public System.IntPtr MinWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } public System.Diagnostics.ProcessModuleCollection Modules { get { throw null; } } [System.ObsoleteAttribute("This property has been deprecated because the type of the property can't represent all valid results. Please use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead. https://go.microsoft.com/fwlink/?linkid=14202")] public int NonpagedSystemMemorySize { get { throw null; } } @@ -109,27 +109,34 @@ public static void EnterDebugMode() { } public static System.Diagnostics.Process[] GetProcessesByName(string? processName) { throw null; } public static System.Diagnostics.Process[] GetProcessesByName(string? processName, string machineName) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public void Kill() { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public void Kill(bool entireProcessTree) { } public static void LeaveDebugMode() { } protected void OnExited() { } public void Refresh() { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public bool Start() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Diagnostics.Process? Start(System.Diagnostics.ProcessStartInfo startInfo) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Diagnostics.Process Start(string fileName) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Diagnostics.Process Start(string fileName, string arguments) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Diagnostics.Process Start(string fileName, System.Collections.Generic.IEnumerable arguments) { throw null; } [System.CLSCompliantAttribute(false)] diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs index 0dff87802214e9..5ead2f7c4b6009 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs @@ -10,6 +10,7 @@ namespace System.Diagnostics public partial class Process : IDisposable { [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public void Kill(bool entireProcessTree) { diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs index 7ae9eeec8d614f..0894dd9e6f7a01 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs @@ -55,6 +55,7 @@ public static Process Start(string fileName, string arguments, string userName, /// Terminates the associated process immediately. [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public void Kill() { diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs index 475f31853f4d9a..d30525589ef67d 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs @@ -90,6 +90,7 @@ public static void LeaveDebugMode() /// Terminates the associated process immediately. [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public void Kill() { diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs index 937efa0cab48a3..e1305a0b60d559 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs @@ -261,6 +261,7 @@ public string MachineName public IntPtr MaxWorkingSet { [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { @@ -283,6 +284,7 @@ public IntPtr MaxWorkingSet public IntPtr MinWorkingSet { [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] get { @@ -1202,6 +1204,7 @@ private void SetProcessId(int processId) /// /// [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public bool Start() { @@ -1245,6 +1248,7 @@ public bool Start() /// /// [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static Process Start(string fileName) { @@ -1263,6 +1267,7 @@ public static Process Start(string fileName) /// /// [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static Process Start(string fileName, string arguments) { @@ -1276,6 +1281,7 @@ public static Process Start(string fileName, string arguments) /// Starts a process resource by specifying the name of an application and a set of command line arguments /// [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static Process Start(string fileName, IEnumerable arguments) { @@ -1302,6 +1308,7 @@ public static Process Start(string fileName, IEnumerable arguments) /// /// [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("tvos")] public static Process? Start(ProcessStartInfo startInfo) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs index b3b2791d84367a..7cbe9e32bcbd4e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs @@ -246,6 +246,7 @@ private FileStream(string path, FileMode mode, FileAccess access, FileShare shar public virtual IntPtr Handle => _strategy.Handle; [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("macos")] [UnsupportedOSPlatform("tvos")] public virtual void Lock(long position, long length) @@ -263,6 +264,7 @@ public virtual void Lock(long position, long length) } [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] [UnsupportedOSPlatform("macos")] [UnsupportedOSPlatform("tvos")] public virtual void Unlock(long position, long length) diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 005a751d646215..60408fe300c677 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -7354,9 +7354,10 @@ public override void EndWrite(System.IAsyncResult asyncResult) { } public override void Flush() { } public virtual void Flush(bool flushToDisk) { } public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public virtual void Lock(long position, long length) { } public override int Read(byte[] buffer, int offset, int count) { throw null; } public override int Read(System.Span buffer) { throw null; } @@ -7365,9 +7366,10 @@ public virtual void Lock(long position, long length) { } public override int ReadByte() { throw null; } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; } public override void SetLength(long value) { } - [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatform("macos")] - [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("macos")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public virtual void Unlock(long position, long length) { } public override void Write(byte[] buffer, int offset, int count) { } public override void Write(System.ReadOnlySpan buffer) { } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs index c11560bdb71799..a12fae41849625 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs @@ -16,8 +16,8 @@ protected Aes() { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public sealed partial class AesCcm : System.IDisposable { public AesCcm(byte[] key) { } @@ -33,8 +33,8 @@ public void Encrypt(byte[] nonce, byte[] plaintext, byte[] ciphertext, byte[] ta } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public sealed partial class AesGcm : System.IDisposable { public AesGcm(byte[] key) { } @@ -108,8 +108,8 @@ protected AsymmetricSignatureFormatter() { } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public sealed partial class ChaCha20Poly1305 : System.IDisposable { public ChaCha20Poly1305(byte[] key) { } @@ -164,16 +164,16 @@ public abstract partial class DSA : System.Security.Cryptography.AsymmetricAlgor { protected DSA() { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static new System.Security.Cryptography.DSA Create() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Security.Cryptography.DSA Create(int keySizeInBits) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static System.Security.Cryptography.DSA Create(System.Security.Cryptography.DSAParameters parameters) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")] public static new System.Security.Cryptography.DSA? Create(string algName) { throw null; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs index 50377c3aee3e8c..ef7b8dcc287dcc 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesCcm.cs @@ -8,8 +8,8 @@ namespace System.Security.Cryptography { [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public sealed partial class AesCcm : IDisposable { public static KeySizes NonceByteSizes { get; } = new KeySizes(7, 13, 1); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs index 89c98f7866d08b..b787eb783b95e0 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/AesGcm.cs @@ -8,8 +8,8 @@ namespace System.Security.Cryptography { [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public sealed partial class AesGcm : IDisposable { private const int NonceSize = 12; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs index 115edee5514a4e..93fd614c36fa25 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ChaCha20Poly1305.cs @@ -8,8 +8,8 @@ namespace System.Security.Cryptography { [UnsupportedOSPlatform("browser")] [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public sealed partial class ChaCha20Poly1305 : IDisposable { // Per https://tools.ietf.org/html/rfc7539, ChaCha20Poly1305 AEAD requires a 256-bit key and 96-bit nonce, diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs index 2e06904214f420..06026bd7cddec9 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs @@ -36,16 +36,16 @@ protected DSA() { } } [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public static new DSA Create() { return CreateCore(); } [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public static DSA Create(int keySizeInBits) { DSA dsa = CreateCore(); @@ -63,8 +63,8 @@ public static DSA Create(int keySizeInBits) } [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public static DSA Create(DSAParameters parameters) { DSA dsa = CreateCore(); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs index 4b7bdf649bd79a..4fe04afb5d1b45 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs @@ -35,8 +35,8 @@ public CertificateRequest(string subjectName, System.Security.Cryptography.RSA k public byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) { throw null; } } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public static partial class DSACertificateExtensions { public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) { throw null; } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs index 7d54eaa38b13f3..aad0185afb3dce 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/DSACertificateExtensions.cs @@ -12,8 +12,8 @@ namespace System.Security.Cryptography.X509Certificates /// public and private keys of a . ///
[UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public static class DSACertificateExtensions { /// diff --git a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs index f0c200066ae436..27c0ac0a18f607 100644 --- a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs +++ b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.cs @@ -44,8 +44,8 @@ public DataReference(string uri, System.Security.Cryptography.Xml.TransformChain public partial class DSAKeyValue : System.Security.Cryptography.Xml.KeyInfoClause { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] public DSAKeyValue() { } public DSAKeyValue(System.Security.Cryptography.DSA key) { } public System.Security.Cryptography.DSA Key { get { throw null; } set { } } diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs index e491e065ccfceb..f77dbe56e34af6 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSAKeyValue.cs @@ -17,8 +17,8 @@ public class DSAKeyValue : KeyInfoClause // [UnsupportedOSPlatform("ios")] - [UnsupportedOSPlatform("tvos")] [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] public DSAKeyValue() { _key = DSA.Create(); From 3d72de2450e081459bb3b35b1ef24567206ea803 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Fri, 21 May 2021 11:30:56 -0400 Subject: [PATCH 039/115] Disable UnmanagedCallConvTest on Android (#53079) --- src/tests/issues.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 4bb604a68b2431..86911b4d6b1428 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -3394,6 +3394,9 @@ https://github.com/dotnet/runtime/issues/52763 + + https://github.com/dotnet/runtime/issues/53077 + From 80ca507240ac047031a572a6fecd050d34265669 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Fri, 21 May 2021 22:26:17 +0600 Subject: [PATCH 040/115] Allow more efficient marshalling to IDispatch (#53065) In NativeAOT scenario this allow to not rely on reflection to get GUID of the IDispatch, since it is well known. Related to https://github.com/dotnet/runtimelab/pull/1142 --- .../Common/src/System/Runtime/InteropServices/Variant.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs b/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs index ab2210cdda15c8..60e880a4ffe8c9 100644 --- a/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs +++ b/src/libraries/Common/src/System/Runtime/InteropServices/Variant.cs @@ -202,7 +202,7 @@ public unsafe void CopyFromIndirect(object value) break; case VarEnum.VT_DISPATCH: - *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.GetComInterfaceForObject(value); + *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.GetIDispatchForObject(value); break; case VarEnum.VT_BSTR: @@ -698,7 +698,7 @@ public object? AsDispatch } else { - _typeUnion._unionTypes._dispatch = Marshal.GetComInterfaceForObject(value); + _typeUnion._unionTypes._dispatch = Marshal.GetIDispatchForObject(value); } } } From f3033d8c622ffb32b3ce1734ba377ffe72a2a0ab Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 21 May 2021 10:44:25 -0700 Subject: [PATCH 041/115] [main] Update dependencies from dnceng/internal/dotnet-optimization (#52966) * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20210518.8 optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.21267.7 -> To Version 1.0.0-prerelease.21268.8 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20210519.5 optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.21267.7 -> To Version 1.0.0-prerelease.21269.5 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20210520.4 optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.21267.7 -> To Version 1.0.0-prerelease.21270.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9a910eb67683c1..1e6ad72ce29e95 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -190,21 +190,21 @@ https://github.com/dotnet/arcade 42de78a825b575a1ddeb73020a01fb8cd9311d09 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - d14db66c7ab1c74a36af752a0eab96ad0c34e978 + 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - d14db66c7ab1c74a36af752a0eab96ad0c34e978 + 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - d14db66c7ab1c74a36af752a0eab96ad0c34e978 + 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - d14db66c7ab1c74a36af752a0eab96ad0c34e978 + 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 https://github.com/dotnet/emsdk diff --git a/eng/Versions.props b/eng/Versions.props index 38db5e0f63c019..5c97a5f3076091 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -121,10 +121,10 @@ 6.0.0-beta.21267.1 6.0.0-beta.21267.1 - 1.0.0-prerelease.21267.7 - 1.0.0-prerelease.21267.7 - 1.0.0-prerelease.21267.7 - 1.0.0-prerelease.21267.7 + 1.0.0-prerelease.21270.4 + 1.0.0-prerelease.21270.4 + 1.0.0-prerelease.21270.4 + 1.0.0-prerelease.21270.4 16.9.0-beta1.21055.5 2.0.0-beta1.20253.1 From fa494f73a4fb3fb6c957d368d0cc40e1bc4cc289 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 21 May 2021 11:22:39 -0700 Subject: [PATCH 042/115] Fixing nullability annotations on DateOnly and TimeOnly (#53088) * Fixing nullability annotations on DateOnly and TimeOnly * Fix nullability annotatations for formats parameter on TryParseExact --- .../src/System/DateOnly.cs | 18 +++++------ .../src/System/TimeOnly.cs | 18 +++++------ .../System.Runtime/ref/System.Runtime.cs | 32 +++++++++---------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs index 0f977d2b5368fc..1ca9b084ee0aac 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs @@ -509,7 +509,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read /// An array of allowable formats of s. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a date. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(ReadOnlySpan s, string[] formats, out DateOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); + public static bool TryParseExact(ReadOnlySpan s, [NotNullWhen(true)] string?[]? formats, out DateOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); /// /// Converts the specified char span of a date to its DateOnly equivalent and returns a value that indicates whether the conversion succeeded. @@ -520,10 +520,10 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read /// A bitwise combination of enumeration values that defines how to interpret the parsed date. A typical value to specify is None. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a date. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(ReadOnlySpan s, string[] formats, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) => + public static bool TryParseExact(ReadOnlySpan s, [NotNullWhen(true)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) => TryParseExactInternal(s, formats, provider, style, out result) == ParseFailureKind.None; - private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, string[] formats, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) + private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) { if ((style & ~DateTimeStyles.AllowWhiteSpaces) != 0 || formats == null) { @@ -582,7 +582,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri /// A string containing the characters representing the date to convert. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is empty string, or does not contain a valid string representation of a date. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParse(string s, out DateOnly result) => TryParse(s, null, DateTimeStyles.None, out result); + public static bool TryParse([NotNullWhen(true)] string? s, out DateOnly result) => TryParse(s, null, DateTimeStyles.None, out result); /// /// Converts the specified string representation of a date to its DateOnly equivalent using the specified array of formats, culture-specific format information, and style. And returns a value that indicates whether the conversion succeeded. @@ -592,7 +592,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri /// A bitwise combination of enumeration values that indicates the permitted format of s. A typical value to specify is None. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is empty string, or does not contain a valid string representation of a date. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParse(string s, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) + public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) { if (s == null) { @@ -611,7 +611,7 @@ public static bool TryParse(string s, IFormatProvider? provider, DateTimeStyles /// The required format of s. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s is empty string, or does not contain a date that correspond to the pattern specified in format. This parameter is passed uninitialized. /// true if s was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string format, out DateOnly result) => TryParseExact(s, format, null, DateTimeStyles.None, out result); + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string? format, out DateOnly result) => TryParseExact(s, format, null, DateTimeStyles.None, out result); /// /// Converts the specified span representation of a date to its DateOnly equivalent using the specified format, culture-specific format information, and style. @@ -623,7 +623,7 @@ public static bool TryParse(string s, IFormatProvider? provider, DateTimeStyles /// A bitwise combination of one or more enumeration values that indicate the permitted format of s. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s is empty string, or does not contain a date that correspond to the pattern specified in format. This parameter is passed uninitialized. /// true if s was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string format, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string? format, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) { if (s == null || format == null) { @@ -641,7 +641,7 @@ public static bool TryParseExact(string s, string format, IFormatProvider? provi /// An array of allowable formats of s. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a date. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string[] formats, out DateOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string?[]? formats, out DateOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); /// /// Converts the specified string of a date to its DateOnly equivalent and returns a value that indicates whether the conversion succeeded. @@ -652,7 +652,7 @@ public static bool TryParseExact(string s, string format, IFormatProvider? provi /// A bitwise combination of enumeration values that defines how to interpret the parsed date. A typical value to specify is None. /// When this method returns, contains the DateOnly value equivalent to the date contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a date. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string[] formats, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out DateOnly result) { if (s == null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs index 74d08f67513c7e..1cdaf38586a185 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs @@ -585,7 +585,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read /// An array of allowable formats of s. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a time. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(ReadOnlySpan s, string[] formats, out TimeOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); + public static bool TryParseExact(ReadOnlySpan s, [NotNullWhen(true)] string?[]? formats, out TimeOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); /// /// Converts the specified char span of a time to its TimeOnly equivalent and returns a value that indicates whether the conversion succeeded. @@ -596,10 +596,10 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read /// A bitwise combination of enumeration values that defines how to interpret the parsed time. A typical value to specify is None. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a time. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(ReadOnlySpan s, string[] formats, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) => + public static bool TryParseExact(ReadOnlySpan s, [NotNullWhen(true)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) => TryParseExactInternal(s, formats, provider, style, out result) == ParseFailureKind.None; - private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, string[] formats, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) + private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) { if ((style & ~DateTimeStyles.AllowWhiteSpaces) != 0 || formats == null) { @@ -658,7 +658,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri /// A string containing the characters representing the time to convert. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is empty string, or does not contain a valid string representation of a time. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParse(string s, out TimeOnly result) => TryParse(s, null, DateTimeStyles.None, out result); + public static bool TryParse([NotNullWhen(true)] string? s, out TimeOnly result) => TryParse(s, null, DateTimeStyles.None, out result); /// /// Converts the specified string representation of a time to its TimeOnly equivalent using the specified array of formats, culture-specific format information, and style. And returns a value that indicates whether the conversion succeeded. @@ -668,7 +668,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri /// A bitwise combination of enumeration values that indicates the permitted format of s. A typical value to specify is None. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is empty string, or does not contain a valid string representation of a time. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParse(string s, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) + public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) { if (s == null) { @@ -687,7 +687,7 @@ public static bool TryParse(string s, IFormatProvider? provider, DateTimeStyles /// The required format of s. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s is empty string, or does not contain a time that correspond to the pattern specified in format. This parameter is passed uninitialized. /// true if s was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string format, out TimeOnly result) => TryParseExact(s, format, null, DateTimeStyles.None, out result); + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string? format, out TimeOnly result) => TryParseExact(s, format, null, DateTimeStyles.None, out result); /// /// Converts the specified span representation of a time to its TimeOnly equivalent using the specified format, culture-specific format information, and style. @@ -699,7 +699,7 @@ public static bool TryParse(string s, IFormatProvider? provider, DateTimeStyles /// A bitwise combination of one or more enumeration values that indicate the permitted format of s. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s is empty string, or does not contain a time that correspond to the pattern specified in format. This parameter is passed uninitialized. /// true if s was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string format, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string? format, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) { if (s == null || format == null) { @@ -717,7 +717,7 @@ public static bool TryParseExact(string s, string format, IFormatProvider? provi /// An array of allowable formats of s. /// When this method returns, contains the timeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a time. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string[] formats, out TimeOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string?[]? formats, out TimeOnly result) => TryParseExact(s, formats, null, DateTimeStyles.None, out result); /// /// Converts the specified string of a time to its TimeOnly equivalent and returns a value that indicates whether the conversion succeeded. @@ -728,7 +728,7 @@ public static bool TryParseExact(string s, string format, IFormatProvider? provi /// A bitwise combination of enumeration values that defines how to interpret the parsed date. A typical value to specify is None. /// When this method returns, contains the TimeOnly value equivalent to the time contained in s, if the conversion succeeded, or MinValue if the conversion failed. The conversion fails if the s parameter is Empty, or does not contain a valid string representation of a time. This parameter is passed uninitialized. /// true if the s parameter was converted successfully; otherwise, false. - public static bool TryParseExact(string s, string[] formats, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) + public static bool TryParseExact([NotNullWhen(true)] string? s, [NotNullWhen(true)] string?[]? formats, IFormatProvider? provider, DateTimeStyles style, out TimeOnly result) { if (s == null) { diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 60408fe300c677..9561d2353f89b4 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -1344,14 +1344,14 @@ public static partial class Convert public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, out System.DateOnly result) { throw null; } public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan s, string[] formats, out System.DateOnly result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan s, string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } - public static bool TryParse(string s, out System.DateOnly result) { throw null; } - public static bool TryParse(string s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } - public static bool TryParseExact(string s, string format, out System.DateOnly result) { throw null; } - public static bool TryParseExact(string s, string format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } - public static bool TryParseExact(string s, string[] formats, out System.DateOnly result) { throw null; } - public static bool TryParseExact(string s, string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, out System.DateOnly result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.DateOnly result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? format, out System.DateOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, out System.DateOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) { throw null; } public string ToLongDateString() { throw null; } public string ToShortDateString() { throw null; } public override string ToString() { throw null; } @@ -3861,14 +3861,14 @@ public ThreadStaticAttribute() { } public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, out System.TimeOnly result) { throw null; } public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan s, string[] formats, out System.TimeOnly result) { throw null; } - public static bool TryParseExact(System.ReadOnlySpan s, string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } - public static bool TryParse(string s, out System.TimeOnly result) { throw null; } - public static bool TryParse(string s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } - public static bool TryParseExact(string s, string format, out System.TimeOnly result) { throw null; } - public static bool TryParseExact(string s, string format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } - public static bool TryParseExact(string s, string[] formats, out System.TimeOnly result) { throw null; } - public static bool TryParseExact(string s, string[] formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, out System.TimeOnly result) { throw null; } + public static bool TryParseExact(System.ReadOnlySpan s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.TimeOnly result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? format, out System.TimeOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? format, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, out System.TimeOnly result) { throw null; } + public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) { throw null; } public string ToLongTimeString() { throw null; } public string ToShortTimeString() { throw null; } public override string ToString() { throw null; } From b013fde3326e0e950f5ea8ef74cd2020e199b3ca Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Fri, 21 May 2021 20:35:06 +0200 Subject: [PATCH 043/115] Override BaseType in TypeRefTypeSystemType (#52963) * Override BaseType in TypeRefTypeSystemType BaseType is being used to determine whether the type is a value type or class type. This meant that `dotnet-pgo merge` would always produce metadata saying that all types were class types. In practice, this meant that we had the following behavior: ``` .\dotnet-pgo.exe merge --input IBCTrace28800.mibc --output identity.mibc .\dotnet-pgo.exe merge --input IBCTrace28800.mibc --input identity.mibc --output foo.mibc Opening D:\dev\dotnet\dotnet-optimization\output\temp\IBCTrace28800.mibc Opening D:\dev\dotnet\runtime\artifacts\bin\coreclr\windows.x64.Debug\dotnet-pgo\foo.mibc Unhandled exception. System.Exception: Same type `[S.P.CoreLib]System.ReadOnlySpan`1` used as both ValueType and non-ValueType at Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem.TypeRefTypeSystemType.SetIsValueType(Boolean isValueType) at Microsoft.Diagnostics.Tools.Pgo.TypeRefTypeSystem.TypeRefTypeSystemContext.TypeRefSignatureParserProvider.GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, Byte rawTypeKind) ``` The same problem would occur when using compare-mibc to compare a merged mibc file with some of its constituents. These scenarios work now. * Re-abstract BaseType in MetadataType --- src/coreclr/tools/Common/TypeSystem/Common/MetadataType.cs | 3 +++ .../dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataType.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataType.cs index 061fca6790c9ab..72b0aeadba86c4 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataType.cs @@ -60,6 +60,9 @@ public virtual bool IsModuleType /// public abstract MetadataType MetadataBaseType { get; } + // Make sure children remember to override both MetadataBaseType and BaseType. + public abstract override DefType BaseType { get; } + /// /// If true, the type cannot be used as a base type of any other type. /// diff --git a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs index cb94b02ebe969c..6b5689805e93cf 100644 --- a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs +++ b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs @@ -151,6 +151,8 @@ public FieldDesc GetOrAddField(string name, TypeDesc fieldType) public override ModuleDesc Module => _module; + public override DefType BaseType => MetadataBaseType; + public override MetadataType MetadataBaseType { get From 11c969a82665ee1dd72447f0b667d83ac044cd94 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Fri, 21 May 2021 15:18:14 -0400 Subject: [PATCH 044/115] Skip flakey mobile library test crashes (#52931) * [mobile][libraries] Skip test suites failing on CI * [libraries] Add more flakey test suite crashes * [Android][libraries] Add DynamicChainTests.MismatchKeyIdentifiers failure * Add issue to DynamicChainTests ActiveIssue * [Android] Add more flakey test suite crashes for Android arm64 * [libraries] Add RunDisabledAndroidTests condition to be able to run tests on build lane * [Android] Add even more flakey test suites that crash * [iOS] Add System.Net.Security.Tests X509 Certificate not supported skips * [libraries][Android] Add another round of test suite flakes for Android arm64 * Remove suites that had Package Installation Error failures * [Android][libraries] Add more process crashed test suites * Add more process crashed for Android arm and arm64 * Remove test suites that failed due to Package Installation Failure * [Android][libraries] Add System.Diagnostics.Process.Tests active issue * [Android] Add more flakey test suite crashing from json error * [Android][libraries] JSON parsing exception section for suite skips Co-authored-by: Mitchell Hwang --- .../tests/ProcessTests.cs | 1 + .../SslStreamStreamToStreamTest.cs | 4 ++ src/libraries/tests.proj | 60 +++++++++++++++++-- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index 71edaaa3c40674..47c538af8077f4 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -2096,6 +2096,7 @@ public void TestLongProcessIsWorking() [ActiveIssue("https://github.com/dotnet/runtime/issues/29330", TestPlatforms.OSX)] [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/52852", TestPlatforms.MacCatalyst)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/53095", TestPlatforms.Android)] public void LongProcessNamesAreSupported() { string sleepPath; diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs index f7ca5892fc052f..3ecfbc4e92493f 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs @@ -68,6 +68,7 @@ public static IEnumerable SslStream_StreamToStream_Authentication_Succ [Theory] [MemberData(nameof(SslStream_StreamToStream_Authentication_Success_MemberData))] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "X509 certificate store is not supported on iOS or tvOS.")] public async Task SslStream_StreamToStream_Authentication_Success(X509Certificate serverCert = null, X509Certificate clientCert = null) { (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); @@ -126,6 +127,7 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout(client.AuthenticateAsClien } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "X509 certificate store is not supported on iOS or tvOS.")] public async Task Read_CorrectlyUnlocksAfterFailure() { (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); @@ -153,6 +155,7 @@ public async Task Read_CorrectlyUnlocksAfterFailure() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "X509 certificate store is not supported on iOS or tvOS.")] public async Task Write_CorrectlyUnlocksAfterFailure() { (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); @@ -201,6 +204,7 @@ public async Task Read_InvokedSynchronously() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "X509 certificate store is not supported on iOS or tvOS.")] public async Task Write_InvokedSynchronously() { (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 020c562cdde8c5..e62cabe7ba503c 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -106,9 +106,12 @@ + + + - + @@ -118,14 +121,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + @@ -153,12 +191,17 @@ + + - + - - + + + + + @@ -167,6 +210,7 @@ + @@ -174,6 +218,10 @@ + + + + From 92f7ba9dccd00629af10af3f38be65f8e4e49436 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 21 May 2021 12:19:25 -0700 Subject: [PATCH 045/115] JIT: fix relop flags for peeled switch compare (#53096) In particular we need to set `GTF_DONT_CSE` so that CSE doesn't introduce commas under `GT_JTRUE` nodes. Fixes #52785. --- src/coreclr/jit/fgopt.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 12220bb2ef8984..fb2c991063aad1 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -3804,7 +3804,6 @@ bool Compiler::fgOptimizeSwitchJumps() GenTree* const jmpTree = gtNewOperNode(GT_JTRUE, TYP_VOID, dominantCaseCompare); Statement* const jmpStmt = fgNewStmtFromTree(jmpTree, switchStmt->GetILOffsetX()); fgInsertStmtAtEnd(block, jmpStmt); - dominantCaseCompare->gtFlags |= GTF_RELOP_JMP_USED; // Reattach switch value to the switch. This may introduce a comma // in the upstream compare tree, if the switch value expression is complex. @@ -3815,7 +3814,7 @@ bool Compiler::fgOptimizeSwitchJumps() // dominantCaseCompare->gtFlags |= dominantCaseCompare->AsOp()->gtOp1->gtFlags; jmpTree->gtFlags |= dominantCaseCompare->gtFlags; - dominantCaseCompare->gtFlags |= GTF_RELOP_JMP_USED; + dominantCaseCompare->gtFlags |= GTF_RELOP_JMP_USED | GTF_DONT_CSE; // Wire up the new control flow. // From bd833ee0f6a1db62ed59a798b79cb8f4241679cb Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Fri, 21 May 2021 12:35:08 -0700 Subject: [PATCH 046/115] Remove unused field (#53100) --- .../tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs b/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs index 6c84993d3fae92..f73d72d3dd32db 100644 --- a/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs +++ b/src/libraries/Common/tests/Tests/System/Net/aspnetcore/Http2/HPackDecoderTest.cs @@ -44,8 +44,6 @@ public class HPackDecoderTests private const string _userAgentString = "user-agent"; - private static readonly byte[] _userAgentBytes = Encoding.ASCII.GetBytes(_userAgentString); - private const string _headerNameString = "new-header"; private static readonly byte[] _headerNameBytes = Encoding.ASCII.GetBytes(_headerNameString); From 19140e696fe59c084ebb3ed92598d48d9646248d Mon Sep 17 00:00:00 2001 From: Geoff Kizer Date: Fri, 21 May 2021 14:25:01 -0700 Subject: [PATCH 047/115] ensure we flush when a window limit is hit (#52797) Co-authored-by: Geoffrey Kizer --- .../SocketsHttpHandler/Http2Connection.cs | 19 +- .../Http/SocketsHttpHandler/Http2Stream.cs | 20 +- .../HttpClientHandlerTest.Http2.cs | 182 +++++++++++++----- 3 files changed, 172 insertions(+), 49 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index 356fb1a9b03a1d..703a340d5128e3 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -1452,7 +1452,7 @@ await PerformWriteAsync(totalSize, (thisRef: this, http2Stream, headerBytes, end } } - private async Task SendStreamDataAsync(int streamId, ReadOnlyMemory buffer, CancellationToken cancellationToken) + private async Task SendStreamDataAsync(int streamId, ReadOnlyMemory buffer, bool finalFlush, CancellationToken cancellationToken) { ReadOnlyMemory remaining = buffer; @@ -1464,9 +1464,22 @@ private async Task SendStreamDataAsync(int streamId, ReadOnlyMemory buffer ReadOnlyMemory current; (current, remaining) = SplitBuffer(remaining, frameSize); + + bool flush = false; + if (finalFlush && remaining.Length == 0) + { + flush = true; + } + + // Force a flush if we are out of credit, because we don't know that we will be sending more data any time soon + if (!_connectionWindow.IsCreditAvailable) + { + flush = true; + } + try { - await PerformWriteAsync(FrameHeader.Size + current.Length, (thisRef: this, streamId, current), static (s, writeBuffer) => + await PerformWriteAsync(FrameHeader.Size + current.Length, (thisRef: this, streamId, current, flush), static (s, writeBuffer) => { // Invoked while holding the lock: if (NetEventSource.Log.IsEnabled()) s.thisRef.Trace(s.streamId, $"Started writing. {nameof(writeBuffer.Length)}={writeBuffer.Length}"); @@ -1474,7 +1487,7 @@ await PerformWriteAsync(FrameHeader.Size + current.Length, (thisRef: this, strea FrameHeader.WriteTo(writeBuffer.Span, s.current.Length, FrameType.Data, FrameFlags.None, s.streamId); s.current.CopyTo(writeBuffer.Slice(FrameHeader.Size)); - return false; // no need to flush, as the request content may do so explicitly, or worst case we'll do so as part of the end data frame + return s.flush; }, cancellationToken).ConfigureAwait(false); } catch diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index 40cb2924d21173..d7d7a88970375e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -1223,12 +1223,19 @@ private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationT while (buffer.Length > 0) { int sendSize = -1; + bool flush = false; lock (_creditSyncObject) { if (_availableCredit > 0) { sendSize = Math.Min(buffer.Length, _availableCredit); _availableCredit -= sendSize; + + // Force a flush if we are out of credit, because we don't know that we will be sending more data any time soon + if (_availableCredit == 0) + { + flush = true; + } } else { @@ -1249,12 +1256,23 @@ private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationT // Logically this is part of the else block above, but we can't await while holding the lock. Debug.Assert(_creditWaiter != null); sendSize = await _creditWaiter.AsValueTask().ConfigureAwait(false); + + lock (_creditSyncObject) + { + // Force a flush if we are out of credit, because we don't know that we will be sending more data any time soon + if (_availableCredit == 0) + { + flush = true; + } + } } + Debug.Assert(sendSize > 0); + ReadOnlyMemory current; (current, buffer) = SplitBuffer(buffer, sendSize); - await _connection.SendStreamDataAsync(StreamId, current, _requestBodyCancellationSource.Token).ConfigureAwait(false); + await _connection.SendStreamDataAsync(StreamId, current, flush, _requestBodyCancellationSource.Token).ConfigureAwait(false); } } finally diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs index 08939b91f5f607..668d194ebef1c9 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs @@ -1396,6 +1396,23 @@ public async Task GoAwayFrame_AbortAllPendingStreams_StreamFailWithExpectedExcep } } + private static async Task ReadExactDataSizeFromStream(Http2LoopbackConnection connection, int size, int streamId) + { + int bytesReceived = 0; + while (bytesReceived < size) + { + Frame frame = await connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); + Assert.Equal(streamId, frame.StreamId); + Assert.Equal(FrameType.Data, frame.Type); + Assert.Equal(FrameFlags.None, frame.Flags); + Assert.True(frame.Length > 0); + + bytesReceived += frame.Length; + } + + Assert.Equal(size, bytesReceived); + } + private static async Task ReadToEndOfStream(Http2LoopbackConnection connection, int streamId) { int bytesReceived = 0; @@ -1420,11 +1437,12 @@ private static async Task ReadToEndOfStream(Http2LoopbackConnection connect return bytesReceived; } + const int DefaultInitialWindowSize = 65535; + [OuterLoop("Uses Task.Delay")] [ConditionalFact(nameof(SupportsAlpn))] public async Task Http2_FlowControl_ClientDoesNotExceedWindows() { - const int InitialWindowSize = 65535; const int ContentSize = 100_000; var content = new ByteAtATimeContent(ContentSize); @@ -1442,19 +1460,8 @@ public async Task Http2_FlowControl_ClientDoesNotExceedWindows() Assert.Equal(FrameFlags.EndHeaders, frame.Flags); // Receive up to initial window size - int bytesReceived = 0; - while (bytesReceived < InitialWindowSize) - { - frame = await connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); - Assert.Equal(streamId, frame.StreamId); - Assert.Equal(FrameType.Data, frame.Type); - Assert.Equal(FrameFlags.None, frame.Flags); - Assert.True(frame.Length > 0); - - bytesReceived += frame.Length; - } - - Assert.Equal(InitialWindowSize, bytesReceived); + int bytesReceived = DefaultInitialWindowSize; + await ReadExactDataSizeFromStream(connection, bytesReceived, streamId); // Issue another read. It shouldn't complete yet. Wait a brief period of time to ensure it doesn't complete. Task readFrameTask = connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); @@ -1528,7 +1535,6 @@ public async Task Http2_FlowControl_ClientDoesNotExceedWindows() [ConditionalFact(nameof(SupportsAlpn))] public async Task Http2_InitialWindowSize_ClientDoesNotExceedWindows() { - const int DefaultInitialWindowSize = 65535; const int ContentSize = DefaultInitialWindowSize + 1000; var content = new ByteAtATimeContent(ContentSize); @@ -1548,20 +1554,8 @@ public async Task Http2_InitialWindowSize_ClientDoesNotExceedWindows() Assert.Equal(FrameType.Headers, frame.Type); Assert.Equal(FrameFlags.EndHeaders, frame.Flags); - // Receive up to initial window size - int bytesReceived = 0; - while (bytesReceived < DefaultInitialWindowSize) - { - frame = await connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); - Assert.Equal(streamId, frame.StreamId); - Assert.Equal(FrameType.Data, frame.Type); - Assert.Equal(FrameFlags.None, frame.Flags); - Assert.True(frame.Length > 0); - - bytesReceived += frame.Length; - } - - Assert.Equal(DefaultInitialWindowSize, bytesReceived); + int bytesReceived = DefaultInitialWindowSize; + await ReadExactDataSizeFromStream(connection, bytesReceived, streamId); // Issue another read. It shouldn't complete yet. Wait a brief period of time to ensure it doesn't complete. Task readFrameTask = connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); @@ -1648,6 +1642,115 @@ public async Task Http2_InitialWindowSize_ClientDoesNotExceedWindows() } } + // Flush behavior is heuristic-based and may change in the future. + // Try various content sizes here to ensure we are not simply getting lucky with the flush heuristic. + [ConditionalTheory(nameof(SupportsAlpn))] + [InlineData(DefaultInitialWindowSize + 1)] + [InlineData(DefaultInitialWindowSize + 4 * 1024)] + [InlineData(DefaultInitialWindowSize + 8 * 1024)] + [InlineData(DefaultInitialWindowSize + 16 * 1024)] + [InlineData(DefaultInitialWindowSize + 32 * 1024)] + [InlineData(DefaultInitialWindowSize + 64 * 1024)] + [InlineData(DefaultInitialWindowSize + 96 * 1024)] + public async Task Http2_SendOverStreamWindowSizeWithoutExplicitFlush_ClientSendsUpToFullWindowSize(int contentSize) + { + var content = new ByteArrayContent(new byte[contentSize]); + + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task clientTask = client.PostAsync(server.Address, content); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + // Bump connection window so it won't block the client. + await connection.WriteFrameAsync(new WindowUpdateFrame(contentSize - DefaultInitialWindowSize, 0)); + + Frame frame = await connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); + int streamId = frame.StreamId; + Assert.Equal(FrameType.Headers, frame.Type); + Assert.Equal(FrameFlags.EndHeaders, frame.Flags); + + // Bump stream window so the client should send the entire body minus one byte. + if ((contentSize - 1) > DefaultInitialWindowSize) + { + await connection.WriteFrameAsync(new WindowUpdateFrame((contentSize - 1) - DefaultInitialWindowSize, streamId)); + } + + int bytesReceived = contentSize - 1; + await ReadExactDataSizeFromStream(connection, bytesReceived, streamId); + + // Bump stream window so the client should send the final byte. + await connection.WriteFrameAsync(new WindowUpdateFrame(1, streamId)); + + // Read to end of stream + bytesReceived += await ReadToEndOfStream(connection, streamId); + + Assert.Equal(contentSize, bytesReceived); + + await connection.SendDefaultResponseAsync(streamId); + + HttpResponseMessage response = await clientTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + } + + // Flush behavior is heuristic-based and may change in the future. + // Try various content sizes here to ensure we are not simply getting lucky with the flush heuristic. + [ConditionalTheory(nameof(SupportsAlpn))] + [InlineData(DefaultInitialWindowSize + 1)] + [InlineData(DefaultInitialWindowSize + 4 * 1024)] + [InlineData(DefaultInitialWindowSize + 8 * 1024)] + [InlineData(DefaultInitialWindowSize + 16 * 1024)] + [InlineData(DefaultInitialWindowSize + 32 * 1024)] + [InlineData(DefaultInitialWindowSize + 64 * 1024)] + [InlineData(DefaultInitialWindowSize + 96 * 1024)] + public async Task Http2_SendOverConnectionWindowSizeWithoutExplicitFlush_ClientSendsUpToFullWindowSize(int contentSize) + { + var content = new ByteArrayContent(new byte[contentSize]); + + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task clientTask = client.PostAsync(server.Address, content); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + // Bump connection window so the client should send the entire body minus one byte. + if ((contentSize - 1) > DefaultInitialWindowSize) + { + await connection.WriteFrameAsync(new WindowUpdateFrame((contentSize - 1) - DefaultInitialWindowSize, 0)); + } + + Frame frame = await connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); + int streamId = frame.StreamId; + Assert.Equal(FrameType.Headers, frame.Type); + Assert.Equal(FrameFlags.EndHeaders, frame.Flags); + + // Bump stream window so it won't block the client. + await connection.WriteFrameAsync(new WindowUpdateFrame(contentSize - DefaultInitialWindowSize, streamId)); + + // Receive up to window size (i.e. contentSize - 1) + int bytesReceived = contentSize - 1; + await ReadExactDataSizeFromStream(connection, bytesReceived, streamId); + + Assert.Equal((contentSize - 1), bytesReceived); + + // Bump connection window so the client should send the final byte. + await connection.WriteFrameAsync(new WindowUpdateFrame(1, 0)); + + // Read to end of stream + bytesReceived += await ReadToEndOfStream(connection, streamId); + + Assert.Equal(contentSize, bytesReceived); + + await connection.SendDefaultResponseAsync(streamId); + + HttpResponseMessage response = await clientTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + } + public static IEnumerable KeepAliveTestDataSource() { yield return new object[] { Timeout.InfiniteTimeSpan, HttpKeepAlivePingPolicy.Always, false }; @@ -1901,8 +2004,7 @@ public async Task Http2_WaitingOnWindowCredit_Cancellation() // The goal of this test is to get the client into the state where it has sent the headers, // but is waiting on window credit before it will send the body. We then issue a cancellation // to ensure the request is cancelled as expected. - const int InitialWindowSize = 65535; - const int ContentSize = InitialWindowSize + 1; + const int ContentSize = DefaultInitialWindowSize + 1; HttpClientHandler handler = CreateHttpClientHandler(); handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; @@ -1923,17 +2025,8 @@ public async Task Http2_WaitingOnWindowCredit_Cancellation() Assert.Equal(FrameFlags.EndHeaders, frame.Flags); // Receive up to initial window size - int bytesReceived = 0; - while (bytesReceived < InitialWindowSize) - { - frame = await connection.ReadFrameAsync(TimeSpan.FromSeconds(30)); - Assert.Equal(streamId, frame.StreamId); - Assert.Equal(FrameType.Data, frame.Type); - Assert.Equal(FrameFlags.None, frame.Flags); - Assert.True(frame.Length > 0); - - bytesReceived += frame.Length; - } + int bytesReceived = DefaultInitialWindowSize; + await ReadExactDataSizeFromStream(connection, bytesReceived, streamId); // The client is waiting for more credit in order to send the last byte of the // request body. Test cancellation at this point. @@ -1957,8 +2050,7 @@ public async Task Http2_PendingSend_Cancellation() { // The goal of this test is to get the client into the state where it is sending content, // but the send pends because the TCP window is full. - const int InitialWindowSize = 65535; - const int ContentSize = InitialWindowSize * 2; // Double the default TCP window size. + const int ContentSize = DefaultInitialWindowSize * 2; // Double the default TCP window size. var content = new ByteArrayContent(TestHelper.GenerateRandomContent(ContentSize)); @@ -1978,7 +2070,7 @@ public async Task Http2_PendingSend_Cancellation() // Increase the size of the HTTP/2 Window, so that it is large enough to fill the // TCP window when we do not perform any reads on the server side. - await connection.WriteFrameAsync(new WindowUpdateFrame(InitialWindowSize, streamId)); + await connection.WriteFrameAsync(new WindowUpdateFrame(DefaultInitialWindowSize, streamId)); // Give the client time to read the window update frame, and for the write to pend. await Task.Delay(1000); From 5b0f256ae18801e81a6e05e6bfc2c78130a5c243 Mon Sep 17 00:00:00 2001 From: Jonas Nyrup Date: Sat, 22 May 2021 00:03:21 +0200 Subject: [PATCH 048/115] Fix typo tihs -> this (#52398) --- .../src/System/Diagnostics/Process.cs | 4 ++-- src/libraries/System.Text.RegularExpressions/src/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs index e1305a0b60d559..7cc5538ddb4b1c 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs @@ -1254,7 +1254,7 @@ public static Process Start(string fileName) { // the underlying Start method can only return null on Windows platforms, // when the ProcessStartInfo.UseShellExecute property is set to true. - // We can thus safely assert non-nullability for tihs overload. + // We can thus safely assert non-nullability for this overload. return Start(new ProcessStartInfo(fileName))!; } @@ -1273,7 +1273,7 @@ public static Process Start(string fileName, string arguments) { // the underlying Start method can only return null on Windows platforms, // when the ProcessStartInfo.UseShellExecute property is set to true. - // We can thus safely assert non-nullability for tihs overload. + // We can thus safely assert non-nullability for this overload. return Start(new ProcessStartInfo(fileName, arguments))!; } diff --git a/src/libraries/System.Text.RegularExpressions/src/README.md b/src/libraries/System.Text.RegularExpressions/src/README.md index 5d93648e04c9ba..bdc154e86bd78d 100644 --- a/src/libraries/System.Text.RegularExpressions/src/README.md +++ b/src/libraries/System.Text.RegularExpressions/src/README.md @@ -61,7 +61,7 @@ In particular, we must keep this API stable in order to remain compatible with r * Representation of a "character class", which defines what characters should be considered a match. It supports ranges, Unicode categories, and character class subtraction. As part of reduction / optimization of a `RegexNode` as well as during compilation, trivial character classes may be replaced by faster equivalent forms, e.g. replacing a character class that represents just one character with the corresponding "one" `RegexNode`. * Created by `RegexParser` -* Creates packed string to be held on `RegexNode`. During execution, tihs string is passed to `CharInClass` to determine whether a given character is in the set, although the implementation (in particular in the compiler) may emit faster equivalent checks when possible. +* Creates packed string to be held on `RegexNode`. During execution, this string is passed to `CharInClass` to determine whether a given character is in the set, although the implementation (in particular in the compiler) may emit faster equivalent checks when possible. * Has utility methods for examining the packed string, in particular for testing membership of the class (`CharInClass(..)`) ### RegexNode From 6eea7a348ffb9dec4a11f745f18009a6318efb36 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 21 May 2021 18:12:18 -0400 Subject: [PATCH 049/115] Implement Initialize on HashAlgorithm (#51402) * Implement Initialize on HashAlgorithm derived types. * Add test for SHA CryptoServiceProviders * Implement reset for HMAC * Remove const * Fix header. [sigh] * Remove ZeroMemory * Fix performance of CSP hash providers. --- .../src/Internal/Cryptography/HashProvider.cs | 2 + .../Internal/Cryptography/HashProviderCng.cs | 12 +++-- .../Interop.Digest.cs | 3 ++ .../pal_digest.c | 48 +++++++++++-------- .../pal_digest.h | 8 ++++ .../src/Internal/Cryptography/HMACCommon.cs | 2 + .../Cryptography/HashProviderDispenser.OSX.cs | 21 ++++++++ .../HashProviderDispenser.Unix.cs | 32 ++++++++++++- .../Cryptography/SHAHashProvider.Browser.cs | 6 +++ .../System/Security/Cryptography/HMACMD5.cs | 6 +-- .../System/Security/Cryptography/HMACSHA1.cs | 6 +-- .../Security/Cryptography/HMACSHA256.cs | 6 +-- .../Security/Cryptography/HMACSHA384.cs | 6 +-- .../Security/Cryptography/HMACSHA512.cs | 6 +-- .../src/System/Security/Cryptography/MD5.cs | 6 +-- .../src/System/Security/Cryptography/SHA1.cs | 6 +-- .../Security/Cryptography/SHA1Managed.cs | 6 +-- .../System/Security/Cryptography/SHA256.cs | 6 +-- .../Security/Cryptography/SHA256Managed.cs | 6 +-- .../System/Security/Cryptography/SHA384.cs | 6 +-- .../Security/Cryptography/SHA384Managed.cs | 6 +-- .../System/Security/Cryptography/SHA512.cs | 6 +-- .../Security/Cryptography/SHA512Managed.cs | 6 +-- .../tests/HashAlgorithmTest.cs | 43 +++++++++++++++++ .../tests/HmacTests.cs | 24 +++++++++- .../Cryptography/MD5CryptoServiceProvider.cs | 40 ++++++++++++---- .../Cryptography/SHA1CryptoServiceProvider.cs | 40 ++++++++++++---- .../SHA256CryptoServiceProvider.cs | 40 ++++++++++++---- .../SHA384CryptoServiceProvider.cs | 40 ++++++++++++---- .../SHA512CryptoServiceProvider.cs | 40 ++++++++++++---- .../tests/SHAxCryptoServiceProviderTests.cs | 8 ++++ 31 files changed, 357 insertions(+), 136 deletions(-) diff --git a/src/libraries/Common/src/Internal/Cryptography/HashProvider.cs b/src/libraries/Common/src/Internal/Cryptography/HashProvider.cs index e77355e5a163a1..cc47097a9b2992 100644 --- a/src/libraries/Common/src/Internal/Cryptography/HashProvider.cs +++ b/src/libraries/Common/src/Internal/Cryptography/HashProvider.cs @@ -72,5 +72,7 @@ public void Dispose() // Releases any native resources and keys used by the HashProvider. public abstract void Dispose(bool disposing); + + public abstract void Reset(); } } diff --git a/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs b/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs index 0f5a7fceccad0b..4644bf61e3575f 100644 --- a/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs +++ b/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs @@ -45,7 +45,7 @@ internal HashProviderCng(string hashAlgId, ReadOnlySpan key, bool isHmac) hHash.Dispose(); // If we got here, we're running on a downlevel OS (pre-Win8) that doesn't support reusable CNG hash objects. Fall back to creating a // new HASH object each time. - ResetHashObject(); + Reset(); } else if (ntStatus != NTSTATUS.STATUS_SUCCESS) { @@ -68,6 +68,8 @@ public sealed override unsafe void AppendHashData(ReadOnlySpan source) { throw Interop.BCrypt.CreateCryptographicException(ntStatus); } + + _running = true; } public override int FinalizeHashAndReset(Span destination) @@ -81,7 +83,8 @@ public override int FinalizeHashAndReset(Span destination) throw Interop.BCrypt.CreateCryptographicException(ntStatus); } - ResetHashObject(); + _running = false; + Reset(); return _hashSize; } @@ -120,9 +123,9 @@ public sealed override void Dispose(bool disposing) public sealed override int HashSizeInBytes => _hashSize; - private void ResetHashObject() + public override void Reset() { - if (_reusable) + if (_reusable && !_running) return; DestroyHash(); @@ -152,5 +155,6 @@ private void DestroyHash() private readonly bool _reusable; private readonly int _hashSize; + private bool _running; } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs index b27ce0dd5b06a7..144b66d2a11498 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs @@ -35,6 +35,9 @@ internal static int DigestCurrent(SafeDigestCtxHandle ctx, Span output) => [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestOneShot")] internal static unsafe extern int DigestOneShot(PAL_HashAlgorithm algorithm, byte* pbData, int cbData, byte* pbOutput, int cbOutput, out int cbDigest); + + [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestReset")] + internal static extern int DigestReset(SafeDigestCtxHandle ctx); } } diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.c index 4011e40e66f12a..dba8026dd31547 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.c @@ -142,25 +142,7 @@ int32_t AppleCryptoNative_DigestFinal(DigestCtx* ctx, uint8_t* pOutput, int32_t return ret; } - switch (ctx->algorithm) - { - case PAL_MD5: -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - return CC_MD5_Init(&ctx->d.md5); -#pragma clang diagnostic pop - case PAL_SHA1: - return CC_SHA1_Init(&ctx->d.sha1); - case PAL_SHA256: - return CC_SHA256_Init(&ctx->d.sha256); - case PAL_SHA384: - return CC_SHA384_Init(&ctx->d.sha384); - case PAL_SHA512: - return CC_SHA512_Init(&ctx->d.sha512); - default: - assert(false); - return -2; - } + return AppleCryptoNative_DigestReset(ctx); } int32_t AppleCryptoNative_DigestCurrent(const DigestCtx* ctx, uint8_t* pOutput, int32_t cbOutput) @@ -226,3 +208,31 @@ int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pB return -1; } } + +int32_t AppleCryptoNative_DigestReset(DigestCtx* ctx) +{ + if (ctx == NULL) + return -1; + + switch (ctx->algorithm) + { + case PAL_MD5: +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + return CC_MD5_Init(&ctx->d.md5); +#pragma clang diagnostic pop + case PAL_SHA1: + return CC_SHA1_Init(&ctx->d.sha1); + case PAL_SHA256: + return CC_SHA256_Init(&ctx->d.sha256); + case PAL_SHA384: + return CC_SHA384_Init(&ctx->d.sha384); + case PAL_SHA512: + return CC_SHA512_Init(&ctx->d.sha512); + default: + assert(false); + return -2; + } + + return 1; +} diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.h index cb48e191b7953b..99eed6af0760e5 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_digest.h @@ -63,3 +63,11 @@ Combines DigestCreate, DigestUpdate, and DigestFinal in to a single operation. Returns 1 on success, 0 on failure, any other value on invalid inputs/state. */ PALEXPORT int32_t AppleCryptoNative_DigestOneShot(PAL_HashAlgorithm algorithm, uint8_t* pBuf, int32_t cbBuf, uint8_t* pOutput, int32_t cbOutput, int32_t* pcbDigest); + + +/* +Re-initializes a digest context to an initial state. + +Returns 1 on success, 0 on failure, any other value on invalid inputs/state. +*/ +PALEXPORT int32_t AppleCryptoNative_DigestReset(DigestCtx* ctx); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HMACCommon.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HMACCommon.cs index 4f5db07e1812cc..8a9a0491a6c88e 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HMACCommon.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HMACCommon.cs @@ -97,6 +97,8 @@ public bool TryFinalizeHashAndReset(Span destination, out int bytesWritten public int GetCurrentHash(Span destination) => _hMacProvider.GetCurrentHash(destination); + public void Reset() => _hMacProvider.Reset(); + public void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs index c01debbde58c1d..3a9901337f9c65 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs @@ -160,11 +160,14 @@ public override void Dispose(bool disposing) Array.Clear(_key, 0, _key.Length); } } + + public override void Reset() => _running = false; } private sealed class AppleDigestProvider : HashProvider { private readonly SafeDigestCtxHandle _ctx; + private bool _running; public override int HashSizeInBytes { get; } @@ -193,6 +196,7 @@ internal AppleDigestProvider(Interop.AppleCrypto.PAL_HashAlgorithm algorithm) public override void AppendHashData(ReadOnlySpan data) { + _running = true; int ret = Interop.AppleCrypto.DigestUpdate(_ctx, data); if (ret != 1) @@ -207,6 +211,7 @@ public override int FinalizeHashAndReset(Span destination) Debug.Assert(destination.Length >= HashSizeInBytes); int ret = Interop.AppleCrypto.DigestFinal(_ctx, destination); + _running = false; if (ret != 1) { @@ -232,6 +237,22 @@ public override int GetCurrentHash(Span destination) return HashSizeInBytes; } + public override void Reset() + { + if (_running) + { + int ret = Interop.AppleCrypto.DigestReset(_ctx); + + if (ret != 1) + { + Debug.Assert(ret == 0, $"DigestReset return value {ret} was not 0 or 1"); + throw new CryptographicException(); + } + + _running = false; + } + } + public override void Dispose(bool disposing) { if (disposing) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs index 8c4a851572c4ba..af984e5344557b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs @@ -52,6 +52,7 @@ private sealed class EvpHashProvider : HashProvider private readonly IntPtr _algorithmEvp; private readonly int _hashSize; private readonly SafeEvpMdCtxHandle _ctx; + private bool _running; public EvpHashProvider(IntPtr algorithmEvp) { @@ -69,8 +70,11 @@ public EvpHashProvider(IntPtr algorithmEvp) Interop.Crypto.CheckValidOpenSslHandle(_ctx); } - public override void AppendHashData(ReadOnlySpan data) => + public override void AppendHashData(ReadOnlySpan data) + { + _running = true; Check(Interop.Crypto.EvpDigestUpdate(_ctx, data, data.Length)); + } public override int FinalizeHashAndReset(Span destination) { @@ -82,6 +86,7 @@ public override int FinalizeHashAndReset(Span destination) // Reset the algorithm provider. Check(Interop.Crypto.EvpDigestReset(_ctx, _algorithmEvp)); + _running = false; return _hashSize; } @@ -106,12 +111,22 @@ public override void Dispose(bool disposing) _ctx.Dispose(); } } + + public override void Reset() + { + if (_running) + { + Check(Interop.Crypto.EvpDigestReset(_ctx, _algorithmEvp)); + _running = false; + } + } } private sealed class HmacHashProvider : HashProvider { private readonly int _hashSize; private SafeHmacCtxHandle _hmacCtx; + private bool _running; public HmacHashProvider(IntPtr algorithmEvp, ReadOnlySpan key) { @@ -127,8 +142,11 @@ public HmacHashProvider(IntPtr algorithmEvp, ReadOnlySpan key) Interop.Crypto.CheckValidOpenSslHandle(_hmacCtx); } - public override void AppendHashData(ReadOnlySpan data) => + public override void AppendHashData(ReadOnlySpan data) + { + _running = true; Check(Interop.Crypto.HmacUpdate(_hmacCtx, data, data.Length)); + } public override int FinalizeHashAndReset(Span destination) { @@ -139,6 +157,7 @@ public override int FinalizeHashAndReset(Span destination) Debug.Assert(length == _hashSize); Check(Interop.Crypto.HmacReset(_hmacCtx)); + _running = false; return _hashSize; } @@ -163,6 +182,15 @@ public override void Dispose(bool disposing) _hmacCtx = null!; } } + + public override void Reset() + { + if (_running) + { + Check(Interop.Crypto.HmacReset(_hmacCtx)); + _running = false; + } + } } private static void Check(int result) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs index dff66e5ab8b619..7a83e35ce13bf1 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs @@ -74,6 +74,12 @@ public override int GetCurrentHash(Span destination) public override int HashSizeInBytes => hashSizeInBytes; + public override void Reset() + { + buffer = null; + impl.Initialize(); + } + public override void Dispose(bool disposing) { } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs index b408c4ae422385..ad652572ead976 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACMD5.cs @@ -65,11 +65,7 @@ protected override byte[] HashFinal() => protected override bool TryHashFinal(Span destination, out int bytesWritten) => _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); - public override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public override void Initialize() => _hMacCommon.Reset(); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs index 5f7b12ea64ebae..1d090d1b8f33a7 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA1.cs @@ -72,11 +72,7 @@ protected override byte[] HashFinal() => protected override bool TryHashFinal(Span destination, out int bytesWritten) => _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); - public override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public override void Initialize() => _hMacCommon.Reset(); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs index 01212cabc15b08..0bc11095fc7044 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA256.cs @@ -68,11 +68,7 @@ protected override byte[] HashFinal() => protected override bool TryHashFinal(Span destination, out int bytesWritten) => _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); - public override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public override void Initialize() => _hMacCommon.Reset(); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs index 4a3c79ccd5e7fe..05548b082885db 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA384.cs @@ -84,11 +84,7 @@ protected override byte[] HashFinal() => protected override bool TryHashFinal(Span destination, out int bytesWritten) => _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); - public override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public override void Initialize() => _hMacCommon.Reset(); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs index 0e685cd3a23abd..556dd54f392887 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/HMACSHA512.cs @@ -82,11 +82,7 @@ protected override byte[] HashFinal() => protected override bool TryHashFinal(Span destination, out int bytesWritten) => _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); - public override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public override void Initialize() => _hMacCommon.Reset(); protected override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs index 256df522ce6aa6..e10d36adf225df 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/MD5.cs @@ -127,11 +127,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs index cc13f6998ea987..e11d49619678b9 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1.cs @@ -126,11 +126,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs index 123b3591ee4342..5f523f6de4d305 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA1Managed.cs @@ -31,11 +31,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs index a0ded322beb5d8..1b1684c86bbe76 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256.cs @@ -126,11 +126,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs index 66b294f8fe15a5..f17d34b07023fb 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA256Managed.cs @@ -31,11 +31,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs index 273590eae720e4..0cf032895d5bf5 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384.cs @@ -125,11 +125,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs index d03bf45b288b65..eab4cad1705ebe 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA384Managed.cs @@ -31,11 +31,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs index b36f4c24ccd7d8..d50f33ebe801e4 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512.cs @@ -125,11 +125,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs index 1de1577d602f16..77536a2b545661 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/SHA512Managed.cs @@ -31,11 +31,7 @@ protected sealed override byte[] HashFinal() => protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); - public sealed override void Initialize() - { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. - } + public sealed override void Initialize() => _hashProvider.Reset(); protected sealed override void Dispose(bool disposing) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs index 82cd8d5da4a26c..dc5738441db564 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs @@ -445,6 +445,49 @@ public void Dispose_TryComputeHash_ThrowsException() Assert.Throws(() => hash.TryComputeHash(new byte[1], new byte[1], out int bytesWritten)); } + [Fact] + public void Initialize_TransformBlock() + { + byte[] hashInput = new byte[] { 1, 2, 3, 4, 5 }; + byte[] expectedDigest; + + using (HashAlgorithm hash = Create()) + { + expectedDigest = hash.ComputeHash(hashInput); + } + + using (HashAlgorithm hash = Create()) + { + hash.TransformBlock(hashInput, 0, hashInput.Length, hashInput, 0); + hash.Initialize(); + hash.TransformBlock(hashInput, 0, hashInput.Length, hashInput, 0); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + + Assert.Equal(expectedDigest, hash.Hash); + } + } + + [Fact] + public void Initialize_TransformBlock_Unused() + { + byte[] hashInput = new byte[] { 1, 2, 3, 4, 5 }; + byte[] expectedDigest; + + using (HashAlgorithm hash = Create()) + { + expectedDigest = hash.ComputeHash(hashInput); + } + + using (HashAlgorithm hash = Create()) + { + hash.Initialize(); + hash.TransformBlock(hashInput, 0, hashInput.Length, hashInput, 0); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + + Assert.Equal(expectedDigest, hash.Hash); + } + } + protected class DataRepeatingStream : Stream { private int _remaining; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/HmacTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/HmacTests.cs index bcabf0c3e69c70..13a24682867722 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/HmacTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/HmacTests.cs @@ -34,6 +34,7 @@ protected void VerifyHmac( int truncateSize = -1) { byte[] digestBytes = ByteUtils.HexToByteArray(digest); + byte[] data = _testData[testCaseId]; byte[] computedDigest; using (HMAC hmac = Create()) @@ -51,7 +52,28 @@ protected void VerifyHmac( key[0] = (byte)(key[0] + 1); Assert.NotEqual(key, hmac.Key); - computedDigest = hmac.ComputeHash(_testData[testCaseId]); + computedDigest = hmac.ComputeHash(data); + } + + if (truncateSize != -1) + { + byte[] tmp = new byte[truncateSize]; + Array.Copy(computedDigest, tmp, truncateSize); + computedDigest = tmp; + } + + Assert.Equal(digestBytes, computedDigest); + + using (HMAC hmac = Create()) + { + byte[] key = (byte[])_testKeys[testCaseId].Clone(); + hmac.Key = key; + + hmac.TransformBlock(data, 0, data.Length, null, 0); + hmac.Initialize(); + hmac.TransformBlock(data, 0, data.Length, null, 0); + hmac.TransformFinalBlock(Array.Empty(), 0, 0); + computedDigest = hmac.Hash; } if (truncateSize != -1) diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs index 03ac76255f0239..1adf8231508a7d 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/MD5CryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics; namespace System.Security.Cryptography { @@ -11,6 +12,7 @@ public sealed class MD5CryptoServiceProvider : MD5 { private const int HashSizeBits = 128; private readonly IncrementalHash _incrementalHash; + private bool _running; public MD5CryptoServiceProvider() { @@ -20,21 +22,43 @@ public MD5CryptoServiceProvider() public override void Initialize() { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. + if (_running) + { + Span destination = stackalloc byte[HashSizeBits / 8]; + + if (!_incrementalHash.TryGetHashAndReset(destination, out _)) + { + Debug.Fail("Reset expected a properly sized buffer."); + throw new CryptographicException(); + } + + _running = false; + } } - protected override void HashCore(byte[] array, int ibStart, int cbSize) => + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + _running = true; _incrementalHash.AppendData(array, ibStart, cbSize); + } - protected override void HashCore(ReadOnlySpan source) => + protected override void HashCore(ReadOnlySpan source) + { + _running = true; _incrementalHash.AppendData(source); + } - protected override byte[] HashFinal() => - _incrementalHash.GetHashAndReset(); + protected override byte[] HashFinal() + { + _running = false; + return _incrementalHash.GetHashAndReset(); + } - protected override bool TryHashFinal(Span destination, out int bytesWritten) => - _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + protected override bool TryHashFinal(Span destination, out int bytesWritten) + { + _running = false; + return _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + } // The Hash and HashSize properties are not overridden since the correct values are returned from base. diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs index 75371fa9a0c8c9..d04fab61a30b73 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA1CryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics; namespace System.Security.Cryptography { @@ -14,6 +15,7 @@ public sealed class SHA1CryptoServiceProvider : SHA1 { private const int HashSizeBits = 160; private readonly IncrementalHash _incrementalHash; + private bool _running; public SHA1CryptoServiceProvider() { @@ -23,21 +25,43 @@ public SHA1CryptoServiceProvider() public override void Initialize() { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. + if (_running) + { + Span destination = stackalloc byte[HashSizeBits / 8]; + + if (!_incrementalHash.TryGetHashAndReset(destination, out _)) + { + Debug.Fail("Reset expected a properly sized buffer."); + throw new CryptographicException(); + } + + _running = false; + } } - protected override void HashCore(byte[] array, int ibStart, int cbSize) => + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + _running = true; _incrementalHash.AppendData(array, ibStart, cbSize); + } - protected override void HashCore(ReadOnlySpan source) => + protected override void HashCore(ReadOnlySpan source) + { + _running = true; _incrementalHash.AppendData(source); + } - protected override byte[] HashFinal() => - _incrementalHash.GetHashAndReset(); + protected override byte[] HashFinal() + { + _running = false; + return _incrementalHash.GetHashAndReset(); + } - protected override bool TryHashFinal(Span destination, out int bytesWritten) => - _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + protected override bool TryHashFinal(Span destination, out int bytesWritten) + { + _running = false; + return _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + } // The Hash and HashSize properties are not overridden since the correct values are returned from base. diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs index 0d21bea5f330dd..066f47937630de 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA256CryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics; namespace System.Security.Cryptography { @@ -14,6 +15,7 @@ public sealed class SHA256CryptoServiceProvider : SHA256 { private const int HashSizeBits = 256; private readonly IncrementalHash _incrementalHash; + private bool _running; public SHA256CryptoServiceProvider() { @@ -23,21 +25,43 @@ public SHA256CryptoServiceProvider() public override void Initialize() { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. + if (_running) + { + Span destination = stackalloc byte[HashSizeBits / 8]; + + if (!_incrementalHash.TryGetHashAndReset(destination, out _)) + { + Debug.Fail("Reset expected a properly sized buffer."); + throw new CryptographicException(); + } + + _running = false; + } } - protected override void HashCore(byte[] array, int ibStart, int cbSize) => + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + _running = true; _incrementalHash.AppendData(array, ibStart, cbSize); + } - protected override void HashCore(ReadOnlySpan source) => + protected override void HashCore(ReadOnlySpan source) + { + _running = true; _incrementalHash.AppendData(source); + } - protected override byte[] HashFinal() => - _incrementalHash.GetHashAndReset(); + protected override byte[] HashFinal() + { + _running = false; + return _incrementalHash.GetHashAndReset(); + } - protected override bool TryHashFinal(Span destination, out int bytesWritten) => - _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + protected override bool TryHashFinal(Span destination, out int bytesWritten) + { + _running = false; + return _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + } // The Hash and HashSize properties are not overridden since the correct values are returned from base. diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs index 710aec29e5c27e..4734eb0f29a303 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA384CryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics; namespace System.Security.Cryptography { @@ -14,6 +15,7 @@ public sealed class SHA384CryptoServiceProvider : SHA384 { private const int HashSizeBits = 384; private readonly IncrementalHash _incrementalHash; + private bool _running; public SHA384CryptoServiceProvider() { @@ -23,21 +25,43 @@ public SHA384CryptoServiceProvider() public override void Initialize() { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. + if (_running) + { + Span destination = stackalloc byte[HashSizeBits / 8]; + + if (!_incrementalHash.TryGetHashAndReset(destination, out _)) + { + Debug.Fail("Reset expected a properly sized buffer."); + throw new CryptographicException(); + } + + _running = false; + } } - protected override void HashCore(byte[] array, int ibStart, int cbSize) => + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + _running = true; _incrementalHash.AppendData(array, ibStart, cbSize); + } - protected override void HashCore(ReadOnlySpan source) => + protected override void HashCore(ReadOnlySpan source) + { + _running = true; _incrementalHash.AppendData(source); + } - protected override byte[] HashFinal() => - _incrementalHash.GetHashAndReset(); + protected override byte[] HashFinal() + { + _running = false; + return _incrementalHash.GetHashAndReset(); + } - protected override bool TryHashFinal(Span destination, out int bytesWritten) => - _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + protected override bool TryHashFinal(Span destination, out int bytesWritten) + { + _running = false; + return _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + } // The Hash and HashSize properties are not overridden since the correct values are returned from base. diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs index cefbe75e72c256..338090eae1949e 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/SHA512CryptoServiceProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics; namespace System.Security.Cryptography { @@ -14,6 +15,7 @@ public sealed class SHA512CryptoServiceProvider : SHA512 { private const int HashSizeBits = 512; private readonly IncrementalHash _incrementalHash; + private bool _running; public SHA512CryptoServiceProvider() { @@ -23,21 +25,43 @@ public SHA512CryptoServiceProvider() public override void Initialize() { - // Nothing to do here. We expect HashAlgorithm to invoke HashFinal() and Initialize() as a pair. This reflects the - // reality that our native crypto providers (e.g. CNG) expose hash finalization and object reinitialization as an atomic operation. + if (_running) + { + Span destination = stackalloc byte[HashSizeBits / 8]; + + if (!_incrementalHash.TryGetHashAndReset(destination, out _)) + { + Debug.Fail("Reset expected a properly sized buffer."); + throw new CryptographicException(); + } + + _running = false; + } } - protected override void HashCore(byte[] array, int ibStart, int cbSize) => + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + _running = true; _incrementalHash.AppendData(array, ibStart, cbSize); + } - protected override void HashCore(ReadOnlySpan source) => + protected override void HashCore(ReadOnlySpan source) + { + _running = true; _incrementalHash.AppendData(source); + } - protected override byte[] HashFinal() => - _incrementalHash.GetHashAndReset(); + protected override byte[] HashFinal() + { + _running = false; + return _incrementalHash.GetHashAndReset(); + } - protected override bool TryHashFinal(Span destination, out int bytesWritten) => - _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + protected override bool TryHashFinal(Span destination, out int bytesWritten) + { + _running = false; + return _incrementalHash.TryGetHashAndReset(destination, out bytesWritten); + } // The Hash and HashSize properties are not overridden since the correct values are returned from base. diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/SHAxCryptoServiceProviderTests.cs b/src/libraries/System.Security.Cryptography.Csp/tests/SHAxCryptoServiceProviderTests.cs index 2abedd2ba653f7..14552358a9c12a 100644 --- a/src/libraries/System.Security.Cryptography.Csp/tests/SHAxCryptoServiceProviderTests.cs +++ b/src/libraries/System.Security.Cryptography.Csp/tests/SHAxCryptoServiceProviderTests.cs @@ -81,6 +81,14 @@ public void Sha512_Rfc3174_2() actual = hash.Hash; Assert.Equal(expectedBytes, actual); + + hash.TransformBlock(inputBytes, 0, inputBytes.Length, inputBytes, 0); + hash.Initialize(); + hash.TransformBlock(inputBytes, 0, inputBytes.Length, inputBytes, 0); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + + actual = hash.Hash; + Assert.Equal(expectedBytes, actual); } } } From 0b74ae54a9cb27138ffe5cf878922e6e0b388457 Mon Sep 17 00:00:00 2001 From: Matt Johnson-Pint Date: Fri, 21 May 2021 16:00:18 -0700 Subject: [PATCH 050/115] Allow TimeZoneInfo display names to use any of the installed Windows languages (#52992) --- .../Interop/Windows/Kernel32/Interop.MUI.cs | 5 +- .../src/System/TimeZoneInfo.Unix.cs | 2 + .../src/System/TimeZoneInfo.Win32.cs | 149 ++++++++++++++---- .../src/System/TimeZoneInfo.cs | 2 - .../tests/System/TimeZoneInfoTests.cs | 76 +++++++++ 5 files changed, 203 insertions(+), 31 deletions(-) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs index 89f310abbd2f08..779d26d3222959 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs @@ -7,9 +7,10 @@ internal static partial class Interop { internal static partial class Kernel32 { - internal const uint MUI_PREFERRED_UI_LANGUAGES = 0x10; + internal const uint MUI_USER_PREFERRED_UI_LANGUAGES = 0x10; + internal const uint MUI_USE_INSTALLED_LANGUAGES = 0x20; [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] - internal static extern unsafe bool GetFileMUIPath(uint dwFlags, string pcwszFilePath, char* pwszLanguage, ref int pcchLanguage, char* pwszFileMUIPath, ref int pcchFileMUIPath, ref long pululEnumerator); + internal static extern unsafe bool GetFileMUIPath(uint dwFlags, string pcwszFilePath, char* pwszLanguage, ref uint pcchLanguage, char* pwszFileMUIPath, ref uint pcchFileMUIPath, ref ulong pululEnumerator); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index b664b1f9906964..c67b3a261e0ebc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -37,6 +37,8 @@ public sealed partial class TimeZoneInfo "Zulu" }; + private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); + private TimeZoneInfo(byte[] data, string id, bool dstDisabled) { _id = id; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs index c42bfabd6b74ea..b52989b995b557 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs @@ -36,6 +36,9 @@ public sealed partial class TimeZoneInfo private const int MaxKeyLength = 255; private const string InvariantUtcStandardDisplayName = "Coordinated Universal Time"; + private static readonly Dictionary s_FileMuiPathCache = new(); + private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); + private sealed partial class CachedData { private static TimeZoneInfo GetCurrentOneYearLocal() @@ -736,6 +739,106 @@ private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMA } } + /// + /// Helper function for getting the MUI path for a given resource and culture, using a cache to prevent duplicating work. + /// Searches the installed OS languages for either an exact matching culture, or one that has the same parent. + /// If not found, uses the preferred default OS UI language, to align with prior behavior. + /// + private static string GetCachedFileMuiPath(string filePath, CultureInfo cultureInfo) + { + string? result; + string cacheKey = $"{cultureInfo.Name};{filePath}"; + + lock (s_FileMuiPathCache) + { + if (s_FileMuiPathCache.TryGetValue(cacheKey, out result)) + { + return result; + } + } + + result = GetFileMuiPath(filePath, cultureInfo); + + lock (s_FileMuiPathCache) + { + s_FileMuiPathCache.TryAdd(cacheKey, result); + } + + return result; + } + + /// + /// Helper function for getting the MUI path for a given resource and culture. + /// Searches the installed OS languages for either an exact matching culture, or one that has the same parent. + /// If not found, uses the preferred default OS UI language, to align with prior behavior. + /// + private static unsafe string GetFileMuiPath(string filePath, CultureInfo cultureInfo) + { + char* fileMuiPath = stackalloc char[Interop.Kernel32.MAX_PATH + 1]; + char* language = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1]; + uint fileMuiPathLength = Interop.Kernel32.MAX_PATH; + uint languageLength = Interop.Kernel32.LOCALE_NAME_MAX_LENGTH; + ulong enumerator = 0; + + while (true) + { + // Search all installed languages. The enumerator is re-used between loop iterations. + bool succeeded = Interop.Kernel32.GetFileMUIPath( + Interop.Kernel32.MUI_USE_INSTALLED_LANGUAGES, + filePath, language, ref languageLength, + fileMuiPath, ref fileMuiPathLength, ref enumerator); + + if (!succeeded) + { + // Recurse to search using the parent of the desired culture. + if (cultureInfo.Parent.Name != string.Empty) + { + return GetFileMuiPath(filePath, cultureInfo.Parent); + } + + // Final fallback, using the preferred installed UI language. + enumerator = 0; + succeeded = Interop.Kernel32.GetFileMUIPath( + Interop.Kernel32.MUI_USER_PREFERRED_UI_LANGUAGES, + filePath, language, ref languageLength, + fileMuiPath, ref fileMuiPathLength, ref enumerator); + + if (succeeded) + { + fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; + return new string(fileMuiPath); + } + + // Shouldn't get here, as there's always at least one language installed. + return string.Empty; + } + + // Lookup succeeded. Check for exact match to the desired culture. + language[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH] = '\0'; + var lang = new string(language); + if (string.Equals(lang, cultureInfo.Name, StringComparison.OrdinalIgnoreCase)) + { + fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; + return new string(fileMuiPath); + } + + // Check for match of any parent of the language returned to the desired culture. + var ci = CultureInfo.GetCultureInfo(lang); + while (ci.Parent.Name != string.Empty) + { + if (ci.Parent.Name.Equals(cultureInfo.Name, StringComparison.OrdinalIgnoreCase)) + { + fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; + return new string(fileMuiPath); + } + + ci = ci.Parent; + } + + // Not found yet. Continue with next iteration. + } + } + /// /// Helper function for retrieving a localized string resource via MUI. /// The function expects a string in the form: "@resource.dll, -123" @@ -746,13 +849,16 @@ private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMA /// If a localized resource file exists, we LoadString resource ID "123" and /// return it to our caller. /// - private static string TryGetLocalizedNameByMuiNativeResource(string resource) + private static string GetLocalizedNameByMuiNativeResource(string resource, CultureInfo? cultureInfo = null) { if (string.IsNullOrEmpty(resource)) { return string.Empty; } + // Use the current UI culture when culture not specified + cultureInfo ??= CultureInfo.CurrentUICulture; + // parse "@tzres.dll, -100" // // filePath = "C:\Windows\System32\tzres.dll" @@ -782,34 +888,23 @@ private static string TryGetLocalizedNameByMuiNativeResource(string resource) return string.Empty; } - if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int resourceId)) + // Get the MUI File Path + string fileMuiPath = GetCachedFileMuiPath(filePath, cultureInfo); + if (fileMuiPath == string.Empty) { + // not likely, but we could not resolve a MUI path 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) + // Get the resource ID + if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int resourceId)) { return string.Empty; } + resourceId = -resourceId; + + // Finally, get the resource from the resource path + return GetLocalizedNameByNativeResource(fileMuiPath, resourceId); } /// @@ -819,7 +914,7 @@ private static string TryGetLocalizedNameByMuiNativeResource(string resource) /// "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) + private static unsafe string GetLocalizedNameByNativeResource(string filePath, int resource) { IntPtr handle = IntPtr.Zero; try @@ -869,17 +964,17 @@ private static void GetLocalizedNamesByRegistryKey(RegistryKey key, out string? // try to load the strings from the native resource DLL(s) if (!string.IsNullOrEmpty(displayNameMuiResource)) { - displayName = TryGetLocalizedNameByMuiNativeResource(displayNameMuiResource); + displayName = GetLocalizedNameByMuiNativeResource(displayNameMuiResource); } if (!string.IsNullOrEmpty(standardNameMuiResource)) { - standardName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); + standardName = GetLocalizedNameByMuiNativeResource(standardNameMuiResource); } if (!string.IsNullOrEmpty(daylightNameMuiResource)) { - daylightName = TryGetLocalizedNameByMuiNativeResource(daylightNameMuiResource); + daylightName = GetLocalizedNameByMuiNativeResource(daylightNameMuiResource); } // fallback to using the standard registry keys @@ -1003,7 +1098,7 @@ private static string GetUtcStandardDisplayName() // try to load the string from the native resource DLL(s) if (!string.IsNullOrEmpty(standardNameMuiResource)) { - standardDisplayName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); + standardDisplayName = GetLocalizedNameByMuiNativeResource(standardNameMuiResource); } // fallback to using the standard registry key diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs index cb41702cdbd766..5f51b1601e249b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs @@ -54,8 +54,6 @@ private enum TimeZoneInfoResult private const string UtcId = "UTC"; private const string LocalId = "Local"; - private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); - private static CachedData s_cachedData = new CachedData(); // diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 3167476689f0ea..ccf509e6de4463 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Text.RegularExpressions; using Microsoft.DotNet.RemoteExecutor; @@ -2720,7 +2721,31 @@ public static void TestNameWithInvariantCulture() Assert.True(pacific.DisplayName.IndexOf("Pacific", StringComparison.OrdinalIgnoreCase) >= 0, $"'{pacific.DisplayName}' is not the expected display name for Pacific time zone"); }).Dispose(); + } + + private static readonly CultureInfo[] s_CulturesForWindowsNlsDisplayNamesTest = WindowsUILanguageHelper.GetInstalledWin32CulturesWithUniqueLanguages(); + private static bool CanTestWindowsNlsDisplayNames => RemoteExecutor.IsSupported && s_CulturesForWindowsNlsDisplayNamesTest.Length > 1; + + [PlatformSpecific(TestPlatforms.Windows)] + [ConditionalFact(nameof(CanTestWindowsNlsDisplayNames))] + public static void TestWindowsNlsDisplayNames() + { + RemoteExecutor.Invoke(() => + { + CultureInfo[] cultures = s_CulturesForWindowsNlsDisplayNamesTest; + + CultureInfo.CurrentUICulture = cultures[0]; + TimeZoneInfo.ClearCachedData(); + TimeZoneInfo tz1 = TimeZoneInfo.FindSystemTimeZoneById(s_strPacific); + CultureInfo.CurrentUICulture = cultures[1]; + TimeZoneInfo.ClearCachedData(); + TimeZoneInfo tz2 = TimeZoneInfo.FindSystemTimeZoneById(s_strPacific); + + Assert.True(tz1.DisplayName != tz2.DisplayName, $"The display name '{tz1.DisplayName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); + Assert.True(tz1.StandardName != tz2.StandardName, $"The standard name '{tz1.StandardName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); + Assert.True(tz1.DaylightName != tz2.DaylightName, $"The daylight name '{tz1.DaylightName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); + }).Dispose(); } [Theory] @@ -2983,5 +3008,56 @@ private static void VerifyCustomTimeZoneException(string id, TimeSpa } }); } + + // This helper class is used to retrieve information about installed OS languages from Windows. + // Its methods returns empty when run on non-Windows platforms. + private static class WindowsUILanguageHelper + { + public static CultureInfo[] GetInstalledWin32CulturesWithUniqueLanguages() => + GetInstalledWin32Cultures() + .GroupBy(c => c.TwoLetterISOLanguageName) + .Select(g => g.First()) + .ToArray(); + + public static CultureInfo[] GetInstalledWin32Cultures() + { + if (!OperatingSystem.IsWindows()) + { + return new CultureInfo[0]; + } + + var context = new EnumContext(); + EnumUILanguagesProc proc = EnumUiLanguagesCallback; + + EnumUILanguages(proc, MUI_ALL_INSTALLED_LANGUAGES | MUI_LANGUAGE_NAME, context); + GC.KeepAlive(proc); + return context.InstalledCultures.ToArray(); + } + + private static bool EnumUiLanguagesCallback(IntPtr lpUiLanguageString, EnumContext lParam) + { + var cultureName = Marshal.PtrToStringUni(lpUiLanguageString); + if (cultureName != null) + { + lParam.InstalledCultures.Add(CultureInfo.GetCultureInfo(cultureName)); + return true; + } + + return false; + } + + private const uint MUI_LANGUAGE_NAME = 0x8; + private const uint MUI_ALL_INSTALLED_LANGUAGES = 0x20; + + [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] + private static extern bool EnumUILanguages(EnumUILanguagesProc lpUILanguageEnumProc, uint dwFlags, EnumContext lParam); + + private delegate bool EnumUILanguagesProc(IntPtr lpUILanguageString, EnumContext lParam); + + private class EnumContext + { + public readonly List InstalledCultures = new(); + } + } } } From df96ac6d37804f320beba3fdbc31e78e870361d1 Mon Sep 17 00:00:00 2001 From: Matt Johnson-Pint Date: Fri, 21 May 2021 16:35:34 -0700 Subject: [PATCH 051/115] Revert "Allow TimeZoneInfo display names to use any of the installed Windows languages" (#53112) This reverts commit b54dbaf9adb2ec068098394b3f73e8e7cd0ec09c. --- .../Interop/Windows/Kernel32/Interop.MUI.cs | 5 +- .../src/System/TimeZoneInfo.Unix.cs | 2 - .../src/System/TimeZoneInfo.Win32.cs | 149 ++++-------------- .../src/System/TimeZoneInfo.cs | 2 + .../tests/System/TimeZoneInfoTests.cs | 76 --------- 5 files changed, 31 insertions(+), 203 deletions(-) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs index 779d26d3222959..89f310abbd2f08 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs @@ -7,10 +7,9 @@ internal static partial class Interop { internal static partial class Kernel32 { - internal const uint MUI_USER_PREFERRED_UI_LANGUAGES = 0x10; - internal const uint MUI_USE_INSTALLED_LANGUAGES = 0x20; + internal const uint MUI_PREFERRED_UI_LANGUAGES = 0x10; [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] - internal static extern unsafe bool GetFileMUIPath(uint dwFlags, string pcwszFilePath, char* pwszLanguage, ref uint pcchLanguage, char* pwszFileMUIPath, ref uint pcchFileMUIPath, ref ulong pululEnumerator); + internal static extern unsafe bool GetFileMUIPath(uint dwFlags, string pcwszFilePath, char* pwszLanguage, ref int pcchLanguage, char* pwszFileMUIPath, ref int pcchFileMUIPath, ref long pululEnumerator); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index c67b3a261e0ebc..b664b1f9906964 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -37,8 +37,6 @@ public sealed partial class TimeZoneInfo "Zulu" }; - private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); - private TimeZoneInfo(byte[] data, string id, bool dstDisabled) { _id = id; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs index b52989b995b557..c42bfabd6b74ea 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs @@ -36,9 +36,6 @@ public sealed partial class TimeZoneInfo private const int MaxKeyLength = 255; private const string InvariantUtcStandardDisplayName = "Coordinated Universal Time"; - private static readonly Dictionary s_FileMuiPathCache = new(); - private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); - private sealed partial class CachedData { private static TimeZoneInfo GetCurrentOneYearLocal() @@ -739,106 +736,6 @@ private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMA } } - /// - /// Helper function for getting the MUI path for a given resource and culture, using a cache to prevent duplicating work. - /// Searches the installed OS languages for either an exact matching culture, or one that has the same parent. - /// If not found, uses the preferred default OS UI language, to align with prior behavior. - /// - private static string GetCachedFileMuiPath(string filePath, CultureInfo cultureInfo) - { - string? result; - string cacheKey = $"{cultureInfo.Name};{filePath}"; - - lock (s_FileMuiPathCache) - { - if (s_FileMuiPathCache.TryGetValue(cacheKey, out result)) - { - return result; - } - } - - result = GetFileMuiPath(filePath, cultureInfo); - - lock (s_FileMuiPathCache) - { - s_FileMuiPathCache.TryAdd(cacheKey, result); - } - - return result; - } - - /// - /// Helper function for getting the MUI path for a given resource and culture. - /// Searches the installed OS languages for either an exact matching culture, or one that has the same parent. - /// If not found, uses the preferred default OS UI language, to align with prior behavior. - /// - private static unsafe string GetFileMuiPath(string filePath, CultureInfo cultureInfo) - { - char* fileMuiPath = stackalloc char[Interop.Kernel32.MAX_PATH + 1]; - char* language = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1]; - uint fileMuiPathLength = Interop.Kernel32.MAX_PATH; - uint languageLength = Interop.Kernel32.LOCALE_NAME_MAX_LENGTH; - ulong enumerator = 0; - - while (true) - { - // Search all installed languages. The enumerator is re-used between loop iterations. - bool succeeded = Interop.Kernel32.GetFileMUIPath( - Interop.Kernel32.MUI_USE_INSTALLED_LANGUAGES, - filePath, language, ref languageLength, - fileMuiPath, ref fileMuiPathLength, ref enumerator); - - if (!succeeded) - { - // Recurse to search using the parent of the desired culture. - if (cultureInfo.Parent.Name != string.Empty) - { - return GetFileMuiPath(filePath, cultureInfo.Parent); - } - - // Final fallback, using the preferred installed UI language. - enumerator = 0; - succeeded = Interop.Kernel32.GetFileMUIPath( - Interop.Kernel32.MUI_USER_PREFERRED_UI_LANGUAGES, - filePath, language, ref languageLength, - fileMuiPath, ref fileMuiPathLength, ref enumerator); - - if (succeeded) - { - fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; - return new string(fileMuiPath); - } - - // Shouldn't get here, as there's always at least one language installed. - return string.Empty; - } - - // Lookup succeeded. Check for exact match to the desired culture. - language[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH] = '\0'; - var lang = new string(language); - if (string.Equals(lang, cultureInfo.Name, StringComparison.OrdinalIgnoreCase)) - { - fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; - return new string(fileMuiPath); - } - - // Check for match of any parent of the language returned to the desired culture. - var ci = CultureInfo.GetCultureInfo(lang); - while (ci.Parent.Name != string.Empty) - { - if (ci.Parent.Name.Equals(cultureInfo.Name, StringComparison.OrdinalIgnoreCase)) - { - fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; - return new string(fileMuiPath); - } - - ci = ci.Parent; - } - - // Not found yet. Continue with next iteration. - } - } - /// /// Helper function for retrieving a localized string resource via MUI. /// The function expects a string in the form: "@resource.dll, -123" @@ -849,16 +746,13 @@ private static unsafe string GetFileMuiPath(string filePath, CultureInfo culture /// If a localized resource file exists, we LoadString resource ID "123" and /// return it to our caller. /// - private static string GetLocalizedNameByMuiNativeResource(string resource, CultureInfo? cultureInfo = null) + private static string TryGetLocalizedNameByMuiNativeResource(string resource) { if (string.IsNullOrEmpty(resource)) { return string.Empty; } - // Use the current UI culture when culture not specified - cultureInfo ??= CultureInfo.CurrentUICulture; - // parse "@tzres.dll, -100" // // filePath = "C:\Windows\System32\tzres.dll" @@ -888,23 +782,34 @@ private static string GetLocalizedNameByMuiNativeResource(string resource, Cultu return string.Empty; } - // Get the MUI File Path - string fileMuiPath = GetCachedFileMuiPath(filePath, cultureInfo); - if (fileMuiPath == string.Empty) + if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int resourceId)) { - // not likely, but we could not resolve a MUI path return string.Empty; } + resourceId = -resourceId; - // Get the resource ID - if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int 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; } - resourceId = -resourceId; - - // Finally, get the resource from the resource path - return GetLocalizedNameByNativeResource(fileMuiPath, resourceId); } /// @@ -914,7 +819,7 @@ private static string GetLocalizedNameByMuiNativeResource(string resource, Cultu /// "resource.dll" is a language-specific resource DLL. /// If the localized resource DLL exists, LoadString(resource) is returned. /// - private static unsafe string GetLocalizedNameByNativeResource(string filePath, int resource) + private static unsafe string TryGetLocalizedNameByNativeResource(string filePath, int resource) { IntPtr handle = IntPtr.Zero; try @@ -964,17 +869,17 @@ private static void GetLocalizedNamesByRegistryKey(RegistryKey key, out string? // try to load the strings from the native resource DLL(s) if (!string.IsNullOrEmpty(displayNameMuiResource)) { - displayName = GetLocalizedNameByMuiNativeResource(displayNameMuiResource); + displayName = TryGetLocalizedNameByMuiNativeResource(displayNameMuiResource); } if (!string.IsNullOrEmpty(standardNameMuiResource)) { - standardName = GetLocalizedNameByMuiNativeResource(standardNameMuiResource); + standardName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); } if (!string.IsNullOrEmpty(daylightNameMuiResource)) { - daylightName = GetLocalizedNameByMuiNativeResource(daylightNameMuiResource); + daylightName = TryGetLocalizedNameByMuiNativeResource(daylightNameMuiResource); } // fallback to using the standard registry keys @@ -1098,7 +1003,7 @@ private static string GetUtcStandardDisplayName() // try to load the string from the native resource DLL(s) if (!string.IsNullOrEmpty(standardNameMuiResource)) { - standardDisplayName = GetLocalizedNameByMuiNativeResource(standardNameMuiResource); + standardDisplayName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); } // fallback to using the standard registry key diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs index 5f51b1601e249b..cb41702cdbd766 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs @@ -54,6 +54,8 @@ private enum TimeZoneInfoResult private const string UtcId = "UTC"; private const string LocalId = "Local"; + private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); + private static CachedData s_cachedData = new CachedData(); // diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index ccf509e6de4463..3167476689f0ea 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Text.RegularExpressions; using Microsoft.DotNet.RemoteExecutor; @@ -2721,31 +2720,7 @@ public static void TestNameWithInvariantCulture() Assert.True(pacific.DisplayName.IndexOf("Pacific", StringComparison.OrdinalIgnoreCase) >= 0, $"'{pacific.DisplayName}' is not the expected display name for Pacific time zone"); }).Dispose(); - } - - private static readonly CultureInfo[] s_CulturesForWindowsNlsDisplayNamesTest = WindowsUILanguageHelper.GetInstalledWin32CulturesWithUniqueLanguages(); - private static bool CanTestWindowsNlsDisplayNames => RemoteExecutor.IsSupported && s_CulturesForWindowsNlsDisplayNamesTest.Length > 1; - - [PlatformSpecific(TestPlatforms.Windows)] - [ConditionalFact(nameof(CanTestWindowsNlsDisplayNames))] - public static void TestWindowsNlsDisplayNames() - { - RemoteExecutor.Invoke(() => - { - CultureInfo[] cultures = s_CulturesForWindowsNlsDisplayNamesTest; - - CultureInfo.CurrentUICulture = cultures[0]; - TimeZoneInfo.ClearCachedData(); - TimeZoneInfo tz1 = TimeZoneInfo.FindSystemTimeZoneById(s_strPacific); - CultureInfo.CurrentUICulture = cultures[1]; - TimeZoneInfo.ClearCachedData(); - TimeZoneInfo tz2 = TimeZoneInfo.FindSystemTimeZoneById(s_strPacific); - - Assert.True(tz1.DisplayName != tz2.DisplayName, $"The display name '{tz1.DisplayName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); - Assert.True(tz1.StandardName != tz2.StandardName, $"The standard name '{tz1.StandardName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); - Assert.True(tz1.DaylightName != tz2.DaylightName, $"The daylight name '{tz1.DaylightName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); - }).Dispose(); } [Theory] @@ -3008,56 +2983,5 @@ private static void VerifyCustomTimeZoneException(string id, TimeSpa } }); } - - // This helper class is used to retrieve information about installed OS languages from Windows. - // Its methods returns empty when run on non-Windows platforms. - private static class WindowsUILanguageHelper - { - public static CultureInfo[] GetInstalledWin32CulturesWithUniqueLanguages() => - GetInstalledWin32Cultures() - .GroupBy(c => c.TwoLetterISOLanguageName) - .Select(g => g.First()) - .ToArray(); - - public static CultureInfo[] GetInstalledWin32Cultures() - { - if (!OperatingSystem.IsWindows()) - { - return new CultureInfo[0]; - } - - var context = new EnumContext(); - EnumUILanguagesProc proc = EnumUiLanguagesCallback; - - EnumUILanguages(proc, MUI_ALL_INSTALLED_LANGUAGES | MUI_LANGUAGE_NAME, context); - GC.KeepAlive(proc); - return context.InstalledCultures.ToArray(); - } - - private static bool EnumUiLanguagesCallback(IntPtr lpUiLanguageString, EnumContext lParam) - { - var cultureName = Marshal.PtrToStringUni(lpUiLanguageString); - if (cultureName != null) - { - lParam.InstalledCultures.Add(CultureInfo.GetCultureInfo(cultureName)); - return true; - } - - return false; - } - - private const uint MUI_LANGUAGE_NAME = 0x8; - private const uint MUI_ALL_INSTALLED_LANGUAGES = 0x20; - - [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] - private static extern bool EnumUILanguages(EnumUILanguagesProc lpUILanguageEnumProc, uint dwFlags, EnumContext lParam); - - private delegate bool EnumUILanguagesProc(IntPtr lpUILanguageString, EnumContext lParam); - - private class EnumContext - { - public readonly List InstalledCultures = new(); - } - } } } From b3af123a0715cbf99dcbc7917e5c8a44563dea8d Mon Sep 17 00:00:00 2001 From: IchHabeKeineNamen <36535895+Banyc@users.noreply.github.com> Date: Sat, 22 May 2021 09:30:01 +0800 Subject: [PATCH 052/115] Fix typos in comments (#53064) --- src/coreclr/inc/corjit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index c2fe4d9521e356..b6c97d9f5ab73e 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -16,7 +16,7 @@ // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // -// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the +// The JIT/EE interface is versioned. By "interface", we mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. // @@ -112,7 +112,7 @@ enum CorJitResult // to guide the memory allocation for the code, readonly data, and read-write data enum CorJitAllocMemFlag { - CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will be use the normal alignment + CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will use the normal alignment CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN = 0x00000002, // The read-only data will be 16-byte aligned CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN = 0x00000004, // The code will be 32-byte aligned From 738e7fed82d6558a08b6e5c2d721758df6067501 Mon Sep 17 00:00:00 2001 From: hrrrrustic <35951936+hrrrrustic@users.noreply.github.com> Date: Sat, 22 May 2021 12:55:05 +0300 Subject: [PATCH 053/115] remove pragma (#52481) --- .../src/System/Collections/Concurrent/BlockingCollection.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs index dde45b73a07e16..1685d4ee52b00b 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/BlockingCollection.cs @@ -761,12 +761,7 @@ private bool TryTakeWithNoTimeValidation([MaybeNullWhen(false)] out T item, int } } -#pragma warning disable CS8762 - // https://github.com/dotnet/runtime/issues/36132 - // Compiler can't automatically deduce that nullability constraints - // for 'item' are satisfied at this exit point. return waitForSemaphoreWasSuccessful; -#pragma warning restore CS8762 } From 96e09e26a620429d4a3847c1320677ce9667acb1 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sat, 22 May 2021 13:12:19 +0200 Subject: [PATCH 054/115] Move GlobalizationMode initialization into a nested class (#53082) --- .../src/System/Globalization/CultureData.cs | 3 ++- .../src/System/Globalization/GlobalizationMode.Unix.cs | 9 ++++++--- .../src/System/Globalization/GlobalizationMode.cs | 10 +++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs index 3a013a64446468..616a7d1b9f5ca8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -673,8 +673,9 @@ private static CultureData CreateCultureWithInvariantData() return CultureData.Invariant; } - if (GlobalizationMode.PredefinedCulturesOnly && !GlobalizationMode.Invariant) + if (GlobalizationMode.PredefinedCulturesOnly) { + Debug.Assert(!GlobalizationMode.Invariant); if (GlobalizationMode.UseNls ? !NlsIsEnsurePredefinedLocaleName(cultureName): !IcuIsEnsurePredefinedLocaleName(cultureName)) return null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs index cce3ae3a870dee..3ad23b92f4a1ba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs @@ -5,9 +5,12 @@ namespace System.Globalization { internal static partial class GlobalizationMode { - // Order of these properties in Windows matter because GetUseIcuMode is dependent on Invariant. - // So we need Invariant to be initialized first. - internal static bool Invariant { get; } = GetGlobalizationInvariantMode(); + private static partial class Settings + { + internal static readonly bool Invariant = GetGlobalizationInvariantMode(); + } + + internal static bool Invariant => Settings.Invariant; internal static bool UseNls => false; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index 1d2172fb5510cb..e68195ea569850 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -8,15 +8,19 @@ namespace System.Globalization { internal static partial class GlobalizationMode { + private static partial class Settings + { + internal static readonly bool PredefinedCulturesOnly = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY"); + } + + internal static bool PredefinedCulturesOnly => !Invariant && Settings.PredefinedCulturesOnly; + private static bool GetInvariantSwitchValue() => AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); private static bool TryGetAppLocalIcuSwitchValue([NotNullWhen(true)] out string? value) => TryGetStringValue("System.Globalization.AppLocalIcu", "DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU", out value); - internal static bool PredefinedCulturesOnly { get; } = - AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY"); - private static bool TryGetStringValue(string switchName, string envVariable, [NotNullWhen(true)] out string? value) { value = AppContext.GetData(switchName) as string; From ea8a8194e4eb8d2fffe5756c90fa3d4da393bed0 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 22 May 2021 10:01:44 -0700 Subject: [PATCH 055/115] Integrate misc changes from nativeaot (#53063) * Integrate misc changes from nativeaot * Fix RemoteStack serialization * Delete confusing String.Empty comment --- .../src/System/Exception.CoreCLR.cs | 12 ++--- .../SortableDependencyNode.cs | 6 --- .../TypeSystem/Interop/IL/MarshalHelpers.cs | 17 ++++++- .../TypeSystem/Interop/IL/Marshaller.cs | 2 + .../TypeSystem/Interop/MarshalAsDescriptor.cs | 5 ++ .../src/System/Diagnostics/StackTrace.cs | 2 +- .../src/System/Exception.cs | 3 +- .../src/System/String.cs | 6 +-- .../src/System/Exception.Mono.cs | 48 ++++++++++++++----- 9 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs index 81b9be41cdf895..2be63740dc34c5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs @@ -14,8 +14,6 @@ public partial class Exception : ISerializable { partial void RestoreRemoteStackTrace(SerializationInfo info, StreamingContext context) { - _remoteStackTraceString = info.GetString("RemoteStackTraceString"); // Do not rename (binary serialization) - // Get the WatsonBuckets that were serialized - this is particularly // done to support exceptions going across AD transitions. // @@ -106,14 +104,14 @@ public virtual string? StackTrace return remoteStackTraceString; } - return remoteStackTraceString + GetStackTrace(this); + return remoteStackTraceString + GetStackTrace(); } } - private static string GetStackTrace(Exception e) + private string GetStackTrace() { // Do not include a trailing newline for backwards compatibility - return new StackTrace(e, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); + return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); } private string? CreateSourceName() @@ -245,8 +243,6 @@ internal void RestoreDispatchState(in DispatchState dispatchState) // See src\inc\corexcep.h's EXCEPTION_COMPLUS definition: private const int _COMPlusExceptionCode = unchecked((int)0xe0434352); // Win32 exception code for COM+ exceptions - private string? SerializationRemoteStackTraceString => _remoteStackTraceString; - private object? SerializationWatsonBuckets => _watsonBuckets; private string? SerializationStackTraceString @@ -257,7 +253,7 @@ private string? SerializationStackTraceString if (stackTraceString == null && _stackTrace != null) { - stackTraceString = GetStackTrace(this); + stackTraceString = GetStackTrace(); } return stackTraceString; diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs index 427ea4688463c8..44dade4bad521c 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs @@ -96,12 +96,6 @@ protected enum ObjectNodeOrder StackTraceEmbeddedMetadataNode, StackTraceMethodMappingNode, ArrayOfEmbeddedDataNode, - WindowsDebugNeedTypeIndicesStoreNode, - WindowsDebugMethodSignatureMapSectionNode, - WindowsDebugTypeSignatureMapSectionNode, - WindowsDebugManagedNativeDictionaryInfoSectionNode, - WindowsDebugTypeRecordsSectionNode, - WindowsDebugPseudoAssemblySectionNode, } public class EmbeddedObjectNodeComparer : IComparer diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index 28c09cd5e571aa..1989b6514b86af 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -94,10 +94,12 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type, case MarshallerKind.CriticalHandle: return context.GetWellKnownType(WellKnownType.IntPtr); + case MarshallerKind.BSTRString: case MarshallerKind.UnicodeString: case MarshallerKind.UnicodeStringBuilder: return context.GetWellKnownType(WellKnownType.Char).MakePointerType(); + case MarshallerKind.AnsiBSTRString: case MarshallerKind.AnsiString: case MarshallerKind.AnsiStringBuilder: case MarshallerKind.UTF8String: @@ -351,7 +353,7 @@ internal static MarshallerKind GetMarshallerKind( { if (nativeType == NativeTypeKind.Struct || nativeType == NativeTypeKind.Default) return MarshallerKind.Decimal; - else if (nativeType == NativeTypeKind.LPStruct && !isField && !isReturn) + else if (nativeType == NativeTypeKind.LPStruct && !isField) return MarshallerKind.BlittableStructPtr; else return MarshallerKind.Invalid; @@ -360,7 +362,7 @@ internal static MarshallerKind GetMarshallerKind( { if (nativeType == NativeTypeKind.Struct || nativeType == NativeTypeKind.Default) return MarshallerKind.BlittableStruct; - else if (nativeType == NativeTypeKind.LPStruct && !isField && !isReturn) + else if (nativeType == NativeTypeKind.LPStruct && !isField) return MarshallerKind.BlittableStructPtr; else return MarshallerKind.Invalid; @@ -541,6 +543,13 @@ internal static MarshallerKind GetMarshallerKind( return MarshallerKind.ByValUnicodeString; } + case NativeTypeKind.TBStr: + case NativeTypeKind.BStr: + return MarshallerKind.BSTRString; + + case NativeTypeKind.AnsiBStr: + return MarshallerKind.AnsiBSTRString; + case NativeTypeKind.Default: if (isAnsi) return MarshallerKind.AnsiString; @@ -555,6 +564,10 @@ internal static MarshallerKind GetMarshallerKind( { if (nativeType == NativeTypeKind.AsAny) return isAnsi ? MarshallerKind.AsAnyA : MarshallerKind.AsAnyW; + else if ((isField && nativeType == NativeTypeKind.Default) + || nativeType == NativeTypeKind.Intf + || nativeType == NativeTypeKind.IUnknown) + return MarshallerKind.ComInterface; else return MarshallerKind.Invalid; } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs index 5c3b04d650d026..d9d23c55836642 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs @@ -28,6 +28,8 @@ enum MarshallerKind AnsiString, UnicodeString, UTF8String, + AnsiBSTRString, + BSTRString, ByValAnsiString, ByValUnicodeString, AnsiStringBuilder, diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs b/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs index 84b679e7d59043..05c95826e265bd 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs @@ -19,15 +19,20 @@ public enum NativeTypeKind : byte U8 = 0xa, R4 = 0xb, R8 = 0xc, + BStr = 0x13, LPStr = 0x14, LPWStr = 0x15, LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs) + IUnknown = 0x19, Struct = 0x1b, + Intf = 0x1c, SafeArray = 0x1d, ByValArray = 0x1e, SysInt = 0x1f, SysUInt = 0x20, + AnsiBStr = 0x23, + TBStr = 0x24, Func = 0x26, AsAny = 0x28, Array = 0x2a, diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs index 10865d4432158e..f8e46b08a9c75b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs @@ -187,7 +187,6 @@ internal enum TraceFormat TrailingNewLine, // include a trailing new line character } -#if !CORERT /// /// Builds a readable representation of the stack trace, specifying /// the format for backwards compatibility. @@ -199,6 +198,7 @@ internal string ToString(TraceFormat traceFormat) return sb.ToString(); } +#if !CORERT internal void ToString(TraceFormat traceFormat, StringBuilder sb) { // Passing a default string for "at" in case SR.UsingResourceKeys() is true diff --git a/src/libraries/System.Private.CoreLib/src/System/Exception.cs b/src/libraries/System.Private.CoreLib/src/System/Exception.cs index 90bafff1dac4b4..3db9eb77fd5e25 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Exception.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Exception.cs @@ -47,6 +47,7 @@ protected Exception(SerializationInfo info, StreamingContext context) _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) + _remoteStackTraceString = info.GetString("RemoteStackTraceString"); // Do not rename (binary serialization) _HResult = info.GetInt32("HResult"); // Do not rename (binary serialization) _source = info.GetString("Source"); // Do not rename (binary serialization) @@ -110,7 +111,7 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte info.AddValue("InnerException", _innerException, typeof(Exception)); // Do not rename (binary serialization) info.AddValue("HelpURL", _helpURL, typeof(string)); // Do not rename (binary serialization) info.AddValue("StackTraceString", SerializationStackTraceString, typeof(string)); // Do not rename (binary serialization) - info.AddValue("RemoteStackTraceString", SerializationRemoteStackTraceString, typeof(string)); // Do not rename (binary serialization) + info.AddValue("RemoteStackTraceString", _remoteStackTraceString, typeof(string)); // Do not rename (binary serialization) info.AddValue("RemoteStackIndex", 0, typeof(int)); // Do not rename (binary serialization) info.AddValue("ExceptionMethod", null, typeof(string)); // Do not rename (binary serialization) info.AddValue("HResult", _HResult); // Do not rename (binary serialization) diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index 933c35dfa97e6f..ea51bafb0e76dc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -28,17 +28,15 @@ public sealed partial class String : IComparable, IEnumerable, IConvertible, IEn /// Keep in sync with AllocateString in gchelpers.cpp. internal const int MaxLength = 0x3FFFFFDF; +#if !CORERT // The Empty constant holds the empty string value. It is initialized by the EE during startup. // It is treated as intrinsic by the JIT as so the static constructor would never run. // Leaving it uninitialized would confuse debuggers. - // - // We need to call the String constructor so that the compiler doesn't mark this as a literal. - // Marking this as a literal would mean that it doesn't show up as a field which we can access - // from native. #pragma warning disable CS8618 // compiler sees this non-nullable static string as uninitialized [Intrinsic] public static readonly string Empty; #pragma warning restore CS8618 +#endif // // These fields map directly onto the fields in an EE StringObject. See object.h for the layout. diff --git a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs index c59cb78d16a79b..8924a9bfd5b9a8 100644 --- a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs @@ -58,19 +58,30 @@ public MethodBase? TargetSite } } - public virtual string? StackTrace => GetStackTrace(true); - - private string? GetStackTrace(bool needFileInfo) + public virtual string? StackTrace { - string? stackTraceString = _stackTraceString; - string? remoteStackTraceString = _remoteStackTraceString; + get + { + string? stackTraceString = _stackTraceString; + string? remoteStackTraceString = _remoteStackTraceString; - if (stackTraceString != null) - return remoteStackTraceString + stackTraceString; - if (_traceIPs == null) - return remoteStackTraceString; + if (stackTraceString != null) + { + return remoteStackTraceString + stackTraceString; + } + if (_traceIPs == null) + { + return remoteStackTraceString; + } - return remoteStackTraceString + new StackTrace(this, needFileInfo).ToString(Diagnostics.StackTrace.TraceFormat.Normal); + return remoteStackTraceString + GetStackTrace(); + } + } + + private string GetStackTrace() + { + // Do not include a trailing newline for backwards compatibility + return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); } internal DispatchState CaptureDispatchState() @@ -149,7 +160,20 @@ private bool CanSetRemoteStackTrace() private static IDictionary CreateDataContainer() => new ListDictionaryInternal(); private static string? SerializationWatsonBuckets => null; - private string? SerializationRemoteStackTraceString => _remoteStackTraceString; - private string? SerializationStackTraceString => GetStackTrace(true); + + private string? SerializationStackTraceString + { + get + { + string? stackTraceString = _stackTraceString; + + if (stackTraceString == null && _traceIPs != null) + { + stackTraceString = GetStackTrace(); + } + + return stackTraceString; + } + } } } From e9f61b2d1ba9263a3a4cfbe2cc5bc6cb76253d1a Mon Sep 17 00:00:00 2001 From: Matt Johnson-Pint Date: Sat, 22 May 2021 11:50:14 -0700 Subject: [PATCH 056/115] Allow TimeZoneInfo display names to use any of the installed Windows languages (#53119) --- .../Interop/Windows/Kernel32/Interop.MUI.cs | 5 +- .../src/System/TimeZoneInfo.Unix.cs | 2 + .../src/System/TimeZoneInfo.Win32.cs | 149 ++++++++++++++---- .../src/System/TimeZoneInfo.cs | 2 - .../tests/System/TimeZoneInfoTests.cs | 85 ++++++++++ 5 files changed, 212 insertions(+), 31 deletions(-) diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs index 89f310abbd2f08..779d26d3222959 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MUI.cs @@ -7,9 +7,10 @@ internal static partial class Interop { internal static partial class Kernel32 { - internal const uint MUI_PREFERRED_UI_LANGUAGES = 0x10; + internal const uint MUI_USER_PREFERRED_UI_LANGUAGES = 0x10; + internal const uint MUI_USE_INSTALLED_LANGUAGES = 0x20; [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] - internal static extern unsafe bool GetFileMUIPath(uint dwFlags, string pcwszFilePath, char* pwszLanguage, ref int pcchLanguage, char* pwszFileMUIPath, ref int pcchFileMUIPath, ref long pululEnumerator); + internal static extern unsafe bool GetFileMUIPath(uint dwFlags, string pcwszFilePath, char* pwszLanguage, ref uint pcchLanguage, char* pwszFileMUIPath, ref uint pcchFileMUIPath, ref ulong pululEnumerator); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index b664b1f9906964..c67b3a261e0ebc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -37,6 +37,8 @@ public sealed partial class TimeZoneInfo "Zulu" }; + private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); + private TimeZoneInfo(byte[] data, string id, bool dstDisabled) { _id = id; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs index c42bfabd6b74ea..b52989b995b557 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs @@ -36,6 +36,9 @@ public sealed partial class TimeZoneInfo private const int MaxKeyLength = 255; private const string InvariantUtcStandardDisplayName = "Coordinated Universal Time"; + private static readonly Dictionary s_FileMuiPathCache = new(); + private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); + private sealed partial class CachedData { private static TimeZoneInfo GetCurrentOneYearLocal() @@ -736,6 +739,106 @@ private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMA } } + /// + /// Helper function for getting the MUI path for a given resource and culture, using a cache to prevent duplicating work. + /// Searches the installed OS languages for either an exact matching culture, or one that has the same parent. + /// If not found, uses the preferred default OS UI language, to align with prior behavior. + /// + private static string GetCachedFileMuiPath(string filePath, CultureInfo cultureInfo) + { + string? result; + string cacheKey = $"{cultureInfo.Name};{filePath}"; + + lock (s_FileMuiPathCache) + { + if (s_FileMuiPathCache.TryGetValue(cacheKey, out result)) + { + return result; + } + } + + result = GetFileMuiPath(filePath, cultureInfo); + + lock (s_FileMuiPathCache) + { + s_FileMuiPathCache.TryAdd(cacheKey, result); + } + + return result; + } + + /// + /// Helper function for getting the MUI path for a given resource and culture. + /// Searches the installed OS languages for either an exact matching culture, or one that has the same parent. + /// If not found, uses the preferred default OS UI language, to align with prior behavior. + /// + private static unsafe string GetFileMuiPath(string filePath, CultureInfo cultureInfo) + { + char* fileMuiPath = stackalloc char[Interop.Kernel32.MAX_PATH + 1]; + char* language = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH + 1]; + uint fileMuiPathLength = Interop.Kernel32.MAX_PATH; + uint languageLength = Interop.Kernel32.LOCALE_NAME_MAX_LENGTH; + ulong enumerator = 0; + + while (true) + { + // Search all installed languages. The enumerator is re-used between loop iterations. + bool succeeded = Interop.Kernel32.GetFileMUIPath( + Interop.Kernel32.MUI_USE_INSTALLED_LANGUAGES, + filePath, language, ref languageLength, + fileMuiPath, ref fileMuiPathLength, ref enumerator); + + if (!succeeded) + { + // Recurse to search using the parent of the desired culture. + if (cultureInfo.Parent.Name != string.Empty) + { + return GetFileMuiPath(filePath, cultureInfo.Parent); + } + + // Final fallback, using the preferred installed UI language. + enumerator = 0; + succeeded = Interop.Kernel32.GetFileMUIPath( + Interop.Kernel32.MUI_USER_PREFERRED_UI_LANGUAGES, + filePath, language, ref languageLength, + fileMuiPath, ref fileMuiPathLength, ref enumerator); + + if (succeeded) + { + fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; + return new string(fileMuiPath); + } + + // Shouldn't get here, as there's always at least one language installed. + return string.Empty; + } + + // Lookup succeeded. Check for exact match to the desired culture. + language[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH] = '\0'; + var lang = new string(language); + if (string.Equals(lang, cultureInfo.Name, StringComparison.OrdinalIgnoreCase)) + { + fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; + return new string(fileMuiPath); + } + + // Check for match of any parent of the language returned to the desired culture. + var ci = CultureInfo.GetCultureInfo(lang); + while (ci.Parent.Name != string.Empty) + { + if (ci.Parent.Name.Equals(cultureInfo.Name, StringComparison.OrdinalIgnoreCase)) + { + fileMuiPath[Interop.Kernel32.MAX_PATH] = '\0'; + return new string(fileMuiPath); + } + + ci = ci.Parent; + } + + // Not found yet. Continue with next iteration. + } + } + /// /// Helper function for retrieving a localized string resource via MUI. /// The function expects a string in the form: "@resource.dll, -123" @@ -746,13 +849,16 @@ private static bool TryCompareTimeZoneInformationToRegistry(in TIME_ZONE_INFORMA /// If a localized resource file exists, we LoadString resource ID "123" and /// return it to our caller. /// - private static string TryGetLocalizedNameByMuiNativeResource(string resource) + private static string GetLocalizedNameByMuiNativeResource(string resource, CultureInfo? cultureInfo = null) { if (string.IsNullOrEmpty(resource)) { return string.Empty; } + // Use the current UI culture when culture not specified + cultureInfo ??= CultureInfo.CurrentUICulture; + // parse "@tzres.dll, -100" // // filePath = "C:\Windows\System32\tzres.dll" @@ -782,34 +888,23 @@ private static string TryGetLocalizedNameByMuiNativeResource(string resource) return string.Empty; } - if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int resourceId)) + // Get the MUI File Path + string fileMuiPath = GetCachedFileMuiPath(filePath, cultureInfo); + if (fileMuiPath == string.Empty) { + // not likely, but we could not resolve a MUI path 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) + // Get the resource ID + if (!int.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int resourceId)) { return string.Empty; } + resourceId = -resourceId; + + // Finally, get the resource from the resource path + return GetLocalizedNameByNativeResource(fileMuiPath, resourceId); } /// @@ -819,7 +914,7 @@ private static string TryGetLocalizedNameByMuiNativeResource(string resource) /// "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) + private static unsafe string GetLocalizedNameByNativeResource(string filePath, int resource) { IntPtr handle = IntPtr.Zero; try @@ -869,17 +964,17 @@ private static void GetLocalizedNamesByRegistryKey(RegistryKey key, out string? // try to load the strings from the native resource DLL(s) if (!string.IsNullOrEmpty(displayNameMuiResource)) { - displayName = TryGetLocalizedNameByMuiNativeResource(displayNameMuiResource); + displayName = GetLocalizedNameByMuiNativeResource(displayNameMuiResource); } if (!string.IsNullOrEmpty(standardNameMuiResource)) { - standardName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); + standardName = GetLocalizedNameByMuiNativeResource(standardNameMuiResource); } if (!string.IsNullOrEmpty(daylightNameMuiResource)) { - daylightName = TryGetLocalizedNameByMuiNativeResource(daylightNameMuiResource); + daylightName = GetLocalizedNameByMuiNativeResource(daylightNameMuiResource); } // fallback to using the standard registry keys @@ -1003,7 +1098,7 @@ private static string GetUtcStandardDisplayName() // try to load the string from the native resource DLL(s) if (!string.IsNullOrEmpty(standardNameMuiResource)) { - standardDisplayName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource); + standardDisplayName = GetLocalizedNameByMuiNativeResource(standardNameMuiResource); } // fallback to using the standard registry key diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs index cb41702cdbd766..5f51b1601e249b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs @@ -54,8 +54,6 @@ private enum TimeZoneInfoResult private const string UtcId = "UTC"; private const string LocalId = "Local"; - private static readonly TimeZoneInfo s_utcTimeZone = CreateUtcTimeZone(); - private static CachedData s_cachedData = new CachedData(); // diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 3167476689f0ea..9faa4715690373 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Text.RegularExpressions; using Microsoft.DotNet.RemoteExecutor; @@ -2720,7 +2721,31 @@ public static void TestNameWithInvariantCulture() Assert.True(pacific.DisplayName.IndexOf("Pacific", StringComparison.OrdinalIgnoreCase) >= 0, $"'{pacific.DisplayName}' is not the expected display name for Pacific time zone"); }).Dispose(); + } + + private static readonly CultureInfo[] s_CulturesForWindowsNlsDisplayNamesTest = WindowsUILanguageHelper.GetInstalledWin32CulturesWithUniqueLanguages(); + private static bool CanTestWindowsNlsDisplayNames => RemoteExecutor.IsSupported && s_CulturesForWindowsNlsDisplayNamesTest.Length > 1; + + [PlatformSpecific(TestPlatforms.Windows)] + [ConditionalFact(nameof(CanTestWindowsNlsDisplayNames))] + public static void TestWindowsNlsDisplayNames() + { + RemoteExecutor.Invoke(() => + { + CultureInfo[] cultures = s_CulturesForWindowsNlsDisplayNamesTest; + + CultureInfo.CurrentUICulture = cultures[0]; + TimeZoneInfo.ClearCachedData(); + TimeZoneInfo tz1 = TimeZoneInfo.FindSystemTimeZoneById(s_strPacific); + CultureInfo.CurrentUICulture = cultures[1]; + TimeZoneInfo.ClearCachedData(); + TimeZoneInfo tz2 = TimeZoneInfo.FindSystemTimeZoneById(s_strPacific); + + Assert.True(tz1.DisplayName != tz2.DisplayName, $"The display name '{tz1.DisplayName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); + Assert.True(tz1.StandardName != tz2.StandardName, $"The standard name '{tz1.StandardName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); + Assert.True(tz1.DaylightName != tz2.DaylightName, $"The daylight name '{tz1.DaylightName}' should be different between {cultures[0].Name} and {cultures[1].Name}."); + }).Dispose(); } [Theory] @@ -2983,5 +3008,65 @@ private static void VerifyCustomTimeZoneException(string id, TimeSpa } }); } + + // This helper class is used to retrieve information about installed OS languages from Windows. + // Its methods returns empty when run on non-Windows platforms. + private static class WindowsUILanguageHelper + { + public static CultureInfo[] GetInstalledWin32CulturesWithUniqueLanguages() => + GetInstalledWin32Cultures() + .GroupBy(c => c.TwoLetterISOLanguageName) + .Select(g => g.First()) + .ToArray(); + + public static unsafe CultureInfo[] GetInstalledWin32Cultures() + { + if (!OperatingSystem.IsWindows()) + { + return new CultureInfo[0]; + } + + var list = new List(); + GCHandle handle = GCHandle.Alloc(list); + try + { + EnumUILanguages( + &EnumUiLanguagesCallback, + MUI_ALL_INSTALLED_LANGUAGES | MUI_LANGUAGE_NAME, + GCHandle.ToIntPtr(handle)); + } + finally + { + handle.Free(); + } + + return list.ToArray(); + } + + [UnmanagedCallersOnly] + private static unsafe int EnumUiLanguagesCallback(char* lpUiLanguageString, IntPtr lParam) + { + // native string is null terminated + var cultureName = new string(lpUiLanguageString); + + try + { + var handle = GCHandle.FromIntPtr(lParam); + var list = (List) handle.Target; + list!.Add(CultureInfo.GetCultureInfo(cultureName)); + return 1; + } + catch + { + return 0; + } + } + + private const uint MUI_LANGUAGE_NAME = 0x8; + private const uint MUI_ALL_INSTALLED_LANGUAGES = 0x20; + + [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] + private static extern unsafe bool EnumUILanguages(delegate* unmanaged lpUILanguageEnumProc, uint dwFlags, IntPtr lParam); + } } } From f87665e181bb066ec3299c9a17a86979432c71db Mon Sep 17 00:00:00 2001 From: hrrrrustic <35951936+hrrrrustic@users.noreply.github.com> Date: Sat, 22 May 2021 23:54:40 +0300 Subject: [PATCH 057/115] System.Reflection.* missed Equals nullable annotations (#52162) * add NotNullWhen attribute --- .../ref/System.Reflection.Metadata.cs | 28 +++++++++---------- .../Reflection/Metadata/BlobContentId.cs | 3 +- .../Ecma335/EditAndContinueLogEntry.cs | 6 ++-- .../Metadata/Ecma335/Encoding/LabelHandle.cs | 3 +- .../Reflection/Metadata/EntityHandle.cs | 5 ++-- .../src/System/Reflection/Metadata/Handle.cs | 5 ++-- .../PortablePdb/DocumentNameBlobHandle.cs | 5 ++-- .../Metadata/PortablePdb/Handles.Debug.cs | 21 +++++++------- .../Metadata/PortablePdb/SequencePoint.cs | 5 ++-- .../Metadata/Signatures/SignatureHeader.cs | 5 ++-- .../Metadata/TypeSystem/Handles.TypeSystem.cs | 15 +++++----- .../Constructors/RoDefinitionConstructor.cs | 3 +- .../Constructors/RoSyntheticConstructor.cs | 3 +- .../TypeLoading/Events/Ecma/EcmaEvent.cs | 3 +- .../TypeLoading/Fields/Ecma/EcmaField.cs | 3 +- .../TypeLoading/General/RoAssemblyName.cs | 2 +- .../Methods/RoConstructedGenericMethod.cs | 3 +- .../TypeLoading/Methods/RoDefinitionMethod.cs | 3 +- .../TypeLoading/Methods/RoSyntheticMethod.cs | 3 +- .../Properties/Ecma/EcmaProperty.cs | 3 +- .../TypeLoading/Types/RoArrayType.Key.cs | 3 +- .../Types/RoConstructedGenericType.Key.cs | 3 +- 22 files changed, 77 insertions(+), 56 deletions(-) diff --git a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs index 40647b105f9689..27bf37ab916fd0 100644 --- a/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs +++ b/src/libraries/System.Reflection.Metadata/ref/System.Reflection.Metadata.cs @@ -291,7 +291,7 @@ void System.IDisposable.Dispose() { } public System.Guid Guid { get { throw null; } } public bool IsDefault { get { throw null; } } public uint Stamp { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.BlobContentId other) { throw null; } public static System.Reflection.Metadata.BlobContentId FromHash(byte[] hashCode) { throw null; } public static System.Reflection.Metadata.BlobContentId FromHash(System.Collections.Immutable.ImmutableArray hashCode) { throw null; } @@ -304,7 +304,7 @@ void System.IDisposable.Dispose() { } { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.BlobHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.BlobHandle left, System.Reflection.Metadata.BlobHandle right) { throw null; } @@ -538,7 +538,7 @@ public readonly partial struct CustomDebugInformation { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.CustomDebugInformationHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.CustomDebugInformationHandle left, System.Reflection.Metadata.CustomDebugInformationHandle right) { throw null; } @@ -661,7 +661,7 @@ void System.IDisposable.Dispose() { } { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.DocumentNameBlobHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.DocumentNameBlobHandle left, System.Reflection.Metadata.DocumentNameBlobHandle right) { throw null; } @@ -676,7 +676,7 @@ void System.IDisposable.Dispose() { } public static readonly System.Reflection.Metadata.ModuleDefinitionHandle ModuleDefinition; public bool IsNil { get { throw null; } } public System.Reflection.Metadata.HandleKind Kind { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.EntityHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.EntityHandle left, System.Reflection.Metadata.EntityHandle right) { throw null; } @@ -932,7 +932,7 @@ void System.IDisposable.Dispose() { } { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.GuidHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.GuidHandle left, System.Reflection.Metadata.GuidHandle right) { throw null; } @@ -947,7 +947,7 @@ void System.IDisposable.Dispose() { } public static readonly System.Reflection.Metadata.ModuleDefinitionHandle ModuleDefinition; public bool IsNil { get { throw null; } } public System.Reflection.Metadata.HandleKind Kind { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.Handle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.Handle left, System.Reflection.Metadata.Handle right) { throw null; } @@ -1320,7 +1320,7 @@ void System.IDisposable.Dispose() { } { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.ImportScopeHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.ImportScopeHandle left, System.Reflection.Metadata.ImportScopeHandle right) { throw null; } @@ -1400,7 +1400,7 @@ public readonly partial struct LocalConstant { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.LocalConstantHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.LocalConstantHandle left, System.Reflection.Metadata.LocalConstantHandle right) { throw null; } @@ -2006,7 +2006,7 @@ public partial struct NamespaceDefinition { private readonly int _dummyPrimitive; public bool IsNil { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.NamespaceDefinitionHandle other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.Metadata.NamespaceDefinitionHandle left, System.Reflection.Metadata.NamespaceDefinitionHandle right) { throw null; } @@ -2176,7 +2176,7 @@ void System.IDisposable.Dispose() { } public int Offset { get { throw null; } } public int StartColumn { get { throw null; } } public int StartLine { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Reflection.Metadata.SequencePoint other) { throw null; } public override int GetHashCode() { throw null; } } @@ -2248,7 +2248,7 @@ public partial struct SignatureHeader : System.IEquatable, BlobContentId> GetTimeBasedProvider() } public bool Equals(BlobContentId other) => Guid == other.Guid && Stamp == other.Stamp; - public override bool Equals(object? obj) => obj is BlobContentId bcid && Equals(bcid); + public override bool Equals([NotNullWhen(true)] object? obj) => obj is BlobContentId bcid && Equals(bcid); public override int GetHashCode() => Hash.Combine(Stamp, Guid.GetHashCode()); public static bool operator ==(BlobContentId left, BlobContentId right) => left.Equals(right); public static bool operator !=(BlobContentId left, BlobContentId right) => !left.Equals(right); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/EditAndContinueLogEntry.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/EditAndContinueLogEntry.cs index ca7928051a3f49..b3c61fb368c452 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/EditAndContinueLogEntry.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/EditAndContinueLogEntry.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.Reflection.Metadata.Ecma335 { public readonly struct EditAndContinueLogEntry : IEquatable @@ -14,8 +16,8 @@ public EditAndContinueLogEntry(EntityHandle handle, EditAndContinueOperation ope Operation = operation; } - public override bool Equals(object? obj) => - obj is EditAndContinueLogEntry && Equals((EditAndContinueLogEntry)obj); + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is EditAndContinueLogEntry editAndContinue && Equals(editAndContinue); public bool Equals(EditAndContinueLogEntry other) => Operation == other.Operation && Handle == other.Handle; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/Encoding/LabelHandle.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/Encoding/LabelHandle.cs index 16e43967fe501d..3c5b7d83ec78d6 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/Encoding/LabelHandle.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/Encoding/LabelHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata.Ecma335 { @@ -21,7 +22,7 @@ internal LabelHandle(int id) public bool IsNil => Id == 0; public bool Equals(LabelHandle other) => Id == other.Id; - public override bool Equals(object? obj) => obj is LabelHandle && Equals((LabelHandle)obj); + public override bool Equals([NotNullWhen(true)] object? obj) => obj is LabelHandle labelHandle && Equals(labelHandle); public override int GetHashCode() => Id.GetHashCode(); public static bool operator ==(LabelHandle left, LabelHandle right) => left.Equals(right); diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/EntityHandle.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/EntityHandle.cs index cf04510e016039..26757ed7cc535f 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/EntityHandle.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/EntityHandle.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Reflection.Metadata.Ecma335; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -94,9 +95,9 @@ internal int Token } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is EntityHandle && Equals((EntityHandle)obj); + return obj is EntityHandle entityHandle && Equals(entityHandle); } public bool Equals(EntityHandle other) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Handle.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Handle.cs index f9c3981ff8d247..931c7cef6e6474 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Handle.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Handle.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Reflection.Metadata.Ecma335; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -159,9 +160,9 @@ internal int Token } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is Handle && Equals((Handle)obj); + return obj is Handle handle && Equals(handle); } public bool Equals(Handle other) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/DocumentNameBlobHandle.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/DocumentNameBlobHandle.cs index 9cc5cbb2695e75..888467215e20d1 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/DocumentNameBlobHandle.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/DocumentNameBlobHandle.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Reflection.Internal; using System.Reflection.Metadata.Ecma335; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -53,9 +54,9 @@ public bool IsNil get { return _heapOffset == 0; } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is DocumentNameBlobHandle && Equals((DocumentNameBlobHandle)obj); + return obj is DocumentNameBlobHandle documentHandle && Equals(documentHandle); } public bool Equals(DocumentNameBlobHandle other) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/Handles.Debug.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/Handles.Debug.cs index 4f1084939e25ce..b6c00c78a21262 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/Handles.Debug.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/Handles.Debug.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Reflection.Metadata.Ecma335; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -70,7 +71,7 @@ public bool IsNil public override bool Equals(object? obj) { - return obj is DocumentHandle && ((DocumentHandle)obj)._rowId == _rowId; + return obj is DocumentHandle documentHandle && documentHandle._rowId == _rowId; } public bool Equals(DocumentHandle other) @@ -153,7 +154,7 @@ public bool IsNil public override bool Equals(object? obj) { - return obj is MethodDebugInformationHandle && ((MethodDebugInformationHandle)obj)._rowId == _rowId; + return obj is MethodDebugInformationHandle mdih && mdih._rowId == _rowId; } public bool Equals(MethodDebugInformationHandle other) @@ -248,7 +249,7 @@ public bool IsNil public override bool Equals(object? obj) { - return obj is LocalScopeHandle && ((LocalScopeHandle)obj)._rowId == _rowId; + return obj is LocalScopeHandle lsh && lsh._rowId == _rowId; } public bool Equals(LocalScopeHandle other) @@ -331,7 +332,7 @@ public bool IsNil public override bool Equals(object? obj) { - return obj is LocalVariableHandle && ((LocalVariableHandle)obj)._rowId == _rowId; + return obj is LocalVariableHandle lvh && lvh._rowId == _rowId; } public bool Equals(LocalVariableHandle other) @@ -412,9 +413,9 @@ public bool IsNil return left._rowId == right._rowId; } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is LocalConstantHandle && ((LocalConstantHandle)obj)._rowId == _rowId; + return obj is LocalConstantHandle lch && lch._rowId == _rowId; } public bool Equals(LocalConstantHandle other) @@ -495,9 +496,9 @@ public bool IsNil return left._rowId == right._rowId; } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is ImportScopeHandle && ((ImportScopeHandle)obj)._rowId == _rowId; + return obj is ImportScopeHandle ish && ish._rowId == _rowId; } public bool Equals(ImportScopeHandle other) @@ -578,9 +579,9 @@ public bool IsNil return left._rowId == right._rowId; } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is CustomDebugInformationHandle && ((CustomDebugInformationHandle)obj)._rowId == _rowId; + return obj is CustomDebugInformationHandle cdih && cdih._rowId == _rowId; } public bool Equals(CustomDebugInformationHandle other) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/SequencePoint.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/SequencePoint.cs index 01308356c2f530..6038031fbd59ca 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/SequencePoint.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/SequencePoint.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Reflection.Internal; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -47,9 +48,9 @@ public override int GetHashCode() Hash.Combine(EndLine, EndColumn))))); } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is SequencePoint && Equals((SequencePoint)obj); + return obj is SequencePoint sequencePoint && Equals(sequencePoint); } public bool Equals(SequencePoint other) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Signatures/SignatureHeader.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Signatures/SignatureHeader.cs index 0bc5b04252e2ae..f8506bf7634e45 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Signatures/SignatureHeader.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Signatures/SignatureHeader.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -85,9 +86,9 @@ public bool IsGeneric get { return (_rawValue & (byte)SignatureAttributes.Generic) != 0; } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is SignatureHeader && Equals((SignatureHeader)obj); + return obj is SignatureHeader signatureHeader && Equals(signatureHeader); } public bool Equals(SignatureHeader other) diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs index e2667f6018fa6a..0c89482e05c4fc 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeSystem/Handles.TypeSystem.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Reflection.Metadata.Ecma335; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Metadata { @@ -70,7 +71,7 @@ public bool IsNil public override bool Equals(object? obj) { - return obj is ModuleDefinitionHandle && ((ModuleDefinitionHandle)obj)._rowId == _rowId; + return obj is ModuleDefinitionHandle moduleDefinition && moduleDefinition._rowId == _rowId; } public bool Equals(ModuleDefinitionHandle other) @@ -2518,9 +2519,9 @@ internal StringHandle GetFullName() return StringHandle.FromOffset(GetHeapOffset()); } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is NamespaceDefinitionHandle && Equals((NamespaceDefinitionHandle)obj); + return obj is NamespaceDefinitionHandle ndh && Equals(ndh); } public bool Equals(NamespaceDefinitionHandle other) @@ -2649,9 +2650,9 @@ private ushort VirtualValue get { return unchecked((ushort)(_value >> 8)); } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is BlobHandle && Equals((BlobHandle)obj); + return obj is BlobHandle bh && Equals(bh); } public bool Equals(BlobHandle other) @@ -2717,9 +2718,9 @@ internal int Index get { return _index; } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is GuidHandle && Equals((GuidHandle)obj); + return obj is GuidHandle gh && Equals(gh); } public bool Equals(GuidHandle other) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoDefinitionConstructor.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoDefinitionConstructor.cs index ead5a0d0391208..ca28b7d3d3694c 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoDefinitionConstructor.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoDefinitionConstructor.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -35,7 +36,7 @@ internal RoDefinitionConstructor(RoInstantiationProviderType declaringType, TMet protected sealed override MethodSig ComputeMethodSigStrings() => _decoder.SpecializeMethodSigStrings(TypeContext); protected sealed override MethodSig ComputeCustomModifiers() => _decoder.SpecializeCustomModifiers(TypeContext); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is RoDefinitionConstructor other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoSyntheticConstructor.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoSyntheticConstructor.cs index a109019971f166..c50786533bfffb 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoSyntheticConstructor.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Constructors/RoSyntheticConstructor.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Globalization; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -64,7 +65,7 @@ protected sealed override MethodSig ComputeMethodSigStrings() protected sealed override MethodSig ComputeCustomModifiers() => new MethodSig(_parameterTypes.Length); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is RoSyntheticConstructor other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Events/Ecma/EcmaEvent.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Events/Ecma/EcmaEvent.cs index 41d5a51edb8f9e..aa2aa4a7d34777 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Events/Ecma/EcmaEvent.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Events/Ecma/EcmaEvent.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Reflection.Metadata; using System.Text; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading.Ecma { @@ -36,7 +37,7 @@ internal EcmaEvent(RoInstantiationProviderType declaringType, EventDefinitionHan public sealed override int MetadataToken => _handle.GetToken(); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is EcmaEvent other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Fields/Ecma/EcmaField.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Fields/Ecma/EcmaField.cs index 9d132288730b4e..a148fef2cc0e12 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Fields/Ecma/EcmaField.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Fields/Ecma/EcmaField.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using System.Runtime.InteropServices; using System.Text; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading.Ecma { @@ -39,7 +40,7 @@ internal EcmaField(RoInstantiationProviderType declaringType, FieldDefinitionHan public sealed override int MetadataToken => _handle.GetToken(); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is EcmaField other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/RoAssemblyName.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/RoAssemblyName.cs index 46b34719d6f443..4afd7c13ff8004 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/RoAssemblyName.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/RoAssemblyName.cs @@ -66,7 +66,7 @@ public bool Equals(RoAssemblyName? other) return true; } - public sealed override bool Equals(object? obj) => obj is RoAssemblyName other && Equals(other); + public sealed override bool Equals([NotNullWhen(true)] object? obj) => obj is RoAssemblyName other && Equals(other); public sealed override int GetHashCode() => Name.GetHashCode(); public sealed override string ToString() => FullName; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoConstructedGenericMethod.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoConstructedGenericMethod.cs index 84814f81da3708..da6871ecda8b72 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoConstructedGenericMethod.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoConstructedGenericMethod.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -50,7 +51,7 @@ internal RoConstructedGenericMethod(RoDefinitionMethod genericMethodDefinition, public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments) => throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericMethodDefinition, this)); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is RoConstructedGenericMethod other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoDefinitionMethod.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoDefinitionMethod.cs index d3b1c5c3c0aeb8..9906ff4ef3c7c2 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoDefinitionMethod.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoDefinitionMethod.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -75,7 +76,7 @@ public sealed override IEnumerable CustomAttributes protected sealed override MethodSig ComputeMethodSigStrings() => _decoder.SpecializeMethodSigStrings(TypeContext); protected sealed override MethodSig ComputeCustomModifiers() => _decoder.SpecializeCustomModifiers(TypeContext); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is RoDefinitionMethod other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoSyntheticMethod.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoSyntheticMethod.cs index fd6580c784965e..02f35b6f7b249d 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoSyntheticMethod.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Methods/RoSyntheticMethod.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -66,7 +67,7 @@ protected sealed override MethodSig ComputeMethodSigStrings() protected sealed override MethodSig ComputeCustomModifiers() => new MethodSig(_parameterTypes.Length); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is RoSyntheticMethod other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Properties/Ecma/EcmaProperty.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Properties/Ecma/EcmaProperty.cs index 2d17a9089654f7..47731168c63d0f 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Properties/Ecma/EcmaProperty.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Properties/Ecma/EcmaProperty.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Reflection.Metadata; using System.Text; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading.Ecma { @@ -35,7 +36,7 @@ internal EcmaProperty(RoInstantiationProviderType declaringType, PropertyDefinit public sealed override int MetadataToken => _handle.GetToken(); - public sealed override bool Equals(object? obj) + public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (!(obj is EcmaProperty other)) return false; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoArrayType.Key.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoArrayType.Key.cs index ed520fd6320b4d..b1d920cc164bf6 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoArrayType.Key.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoArrayType.Key.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -32,7 +33,7 @@ public bool Equals(Key other) return true; } - public override bool Equals(object? obj) => obj is Key other && Equals(other); + public override bool Equals([NotNullWhen(true)] object? obj) => obj is Key other && Equals(other); public override int GetHashCode() => ElementType.GetHashCode() ^ Rank.GetHashCode(); } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoConstructedGenericType.Key.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoConstructedGenericType.Key.cs index cd6a430e991895..92121c08dee22e 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoConstructedGenericType.Key.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoConstructedGenericType.Key.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -35,7 +36,7 @@ public bool Equals(Key other) return true; } - public override bool Equals(object? obj) => obj is Key other && Equals(other); + public override bool Equals([NotNullWhen(true)] object? obj) => obj is Key other && Equals(other); public override int GetHashCode() { From 40e2b68544fe08e56bdc3ed404fbc6c212b0576f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 22 May 2021 20:58:33 -0700 Subject: [PATCH 058/115] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20210521.2 (#53124) optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.21270.4 -> To Version 1.0.0-prerelease.21271.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1e6ad72ce29e95..e0c39ce90ff884 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -190,21 +190,21 @@ https://github.com/dotnet/arcade 42de78a825b575a1ddeb73020a01fb8cd9311d09 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 + 018b25068e2051c8b03217069d03d7f6f15e44fd - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 + 018b25068e2051c8b03217069d03d7f6f15e44fd - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 + 018b25068e2051c8b03217069d03d7f6f15e44fd - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 5354b5a8fc5c2007c9c045e10ce0e53c4c83ecd3 + 018b25068e2051c8b03217069d03d7f6f15e44fd https://github.com/dotnet/emsdk diff --git a/eng/Versions.props b/eng/Versions.props index 5c97a5f3076091..a13a1b53a09afe 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -121,10 +121,10 @@ 6.0.0-beta.21267.1 6.0.0-beta.21267.1 - 1.0.0-prerelease.21270.4 - 1.0.0-prerelease.21270.4 - 1.0.0-prerelease.21270.4 - 1.0.0-prerelease.21270.4 + 1.0.0-prerelease.21271.2 + 1.0.0-prerelease.21271.2 + 1.0.0-prerelease.21271.2 + 1.0.0-prerelease.21271.2 16.9.0-beta1.21055.5 2.0.0-beta1.20253.1 From 791a674342744131f01a0238d5b47fdaf0fd57d0 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Sun, 23 May 2021 14:14:40 +0200 Subject: [PATCH 059/115] Avoid dependency on LINQ orderby iterators when building exception messsage (#53123) Saves about 2k compressed for Blazor default template --- .../src/ServiceLookup/CallSiteChain.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs index 80182dab6cce9c..f0803f3f96d7e3 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs @@ -47,9 +47,12 @@ private string CreateCircularDependencyExceptionMessage(Type type) return messageBuilder.ToString(); } - private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving = null) + private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving) { - foreach (KeyValuePair pair in _callSiteChain.OrderBy(p => p.Value.Order)) + var ordered = new List>(_callSiteChain); + ordered.Sort((a, b) => a.Value.Order.CompareTo(b.Value.Order)); + + foreach (KeyValuePair pair in ordered) { Type serviceType = pair.Key; Type implementationType = pair.Value.ImplementationType; @@ -70,7 +73,7 @@ private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving builder.Append(TypeNameHelper.GetTypeDisplayName(currentlyResolving)); } - private struct ChainItemInfo + private readonly struct ChainItemInfo { public int Order { get; } public Type ImplementationType { get; } From 8b58d90547782cfab4681c9001068a8a71e22766 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Sun, 23 May 2021 20:46:52 +0200 Subject: [PATCH 060/115] Remove redundant GeneratePackageOnBuild condition (#53107) * Remove redundant GeneratePackageOnBuild condition --- .../src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj | 2 +- .../src/Microsoft.NETCore.Platforms.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj index ee8e43de514ae1..747450d3131898 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj @@ -2,7 +2,7 @@ netstandard2.0 - true + true false true true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index fdbf7f3cad3d83..926335be52e986 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -5,7 +5,7 @@ true Microsoft.NETCore.Platforms.BuildTasks - true + true false true From 81a435c74a2e1e3a577294ce075e6b3adf8be3b3 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 24 May 2021 00:02:08 +0200 Subject: [PATCH 061/115] [iOS] Re-enable System.Xml.XmlSchema.XmlSchemaValidatorApi.Tests (#53068) Fixes #51338 --- src/libraries/tests.proj | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index e62cabe7ba503c..a282a166a1f00a 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -181,8 +181,6 @@ - - From 65ccfd90b5dd7f310f876b1a1e7eef91b4d2da9b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 24 May 2021 00:03:25 +0200 Subject: [PATCH 062/115] [iOS] Re-enable Brotli tests (#53069) --- .../IO/Compression/CompressionStreamUnitTestBase.cs | 10 ---------- .../tests/BrotliGoogleTestData.cs | 2 -- .../tests/CompressionStreamUnitTests.Brotli.cs | 3 --- 3 files changed, 15 deletions(-) diff --git a/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs b/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs index 407d1ee24d7396..2935ef6fd3f829 100644 --- a/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs +++ b/src/libraries/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs @@ -48,7 +48,6 @@ public virtual void FlushAsync_DuringWriteAsync() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task FlushAsync_DuringReadAsync() { byte[] buffer = new byte[32]; @@ -77,7 +76,6 @@ public async Task FlushAsync_DuringReadAsync() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task FlushAsync_DuringFlushAsync() { byte[] buffer = null; @@ -120,7 +118,6 @@ public async Task FlushAsync_DuringFlushAsync() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Dispose_WithUnfinishedReadAsync() { string compressedPath = CompressedTestFile(UncompressedTestFile()); @@ -140,7 +137,6 @@ public virtual async Task Dispose_WithUnfinishedReadAsync() [Theory] [MemberData(nameof(UncompressedTestFiles))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task Read(string testFile) { var uncompressedStream = await LocalMemoryStream.readAppFileAsync(testFile); @@ -177,7 +173,6 @@ public async Task Read(string testFile) [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task Read_EndOfStreamPosition() { var compressedStream = await LocalMemoryStream.readAppFileAsync(CompressedTestFile(UncompressedTestFile())); @@ -198,7 +193,6 @@ public async Task Read_EndOfStreamPosition() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task Read_BaseStreamSlowly() { string testFile = UncompressedTestFile(); @@ -334,7 +328,6 @@ IEnumerable> CtorFunctions() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task TestLeaveOpenAfterValidDecompress() { //Create the Stream @@ -410,7 +403,6 @@ public void BaseStreamTest(CompressionMode mode) [InlineData(CompressionMode.Compress)] [InlineData(CompressionMode.Decompress)] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task BaseStream_Modify(CompressionMode mode) { using (var baseStream = await LocalMemoryStream.readAppFileAsync(CompressedTestFile(UncompressedTestFile()))) @@ -443,7 +435,6 @@ public void BaseStream_NullAfterDisposeWithFalseLeaveOpen(CompressionMode mode) [InlineData(CompressionMode.Compress)] [InlineData(CompressionMode.Decompress)] [ActiveIssue("https://github.com/dotnet/runtime/issues/36845", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task BaseStream_ValidAfterDisposeWithTrueLeaveOpen(CompressionMode mode) { var ms = await LocalMemoryStream.readAppFileAsync(CompressedTestFile(UncompressedTestFile())); @@ -462,7 +453,6 @@ public async Task BaseStream_ValidAfterDisposeWithTrueLeaveOpen(CompressionMode [Theory] [MemberData(nameof(UncompressedTestFiles))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public async Task CompressionLevel_SizeInOrder(string testFile) { using var uncompressedStream = await LocalMemoryStream.readAppFileAsync(testFile); diff --git a/src/libraries/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs b/src/libraries/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs index 78f69aa5128713..dc86a757fc65a1 100644 --- a/src/libraries/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs +++ b/src/libraries/System.IO.Compression.Brotli/tests/BrotliGoogleTestData.cs @@ -32,7 +32,6 @@ public static IEnumerable GoogleTestData() [Theory] [MemberData(nameof(GoogleTestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void DecompressFile(string fileName) { byte[] bytes = File.ReadAllBytes(CompressedTestFile(fileName)); @@ -43,7 +42,6 @@ public void DecompressFile(string fileName) [Theory] [MemberData(nameof(GoogleTestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void RoundtripCompressDecompressFile(string fileName) { byte[] bytes = File.ReadAllBytes(fileName); diff --git a/src/libraries/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs b/src/libraries/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs index 316e3ba7a08454..3960233e5eafa8 100644 --- a/src/libraries/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs +++ b/src/libraries/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs @@ -58,7 +58,6 @@ public void GetMaxCompressedSize_Basic() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void GetMaxCompressedSize() { string uncompressedFile = UncompressedTestFile(); @@ -72,7 +71,6 @@ public void GetMaxCompressedSize() /// Test to ensure that when given an empty Destination span, the decoder will consume no input and write no output. /// [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void Decompress_WithEmptyDestination() { string testFile = UncompressedTestFile(); @@ -116,7 +114,6 @@ public void Decompress_WithEmptySource() /// Test to ensure that when given an empty Destination span, the encoder consume no input and write no output /// [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36884", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void Compress_WithEmptyDestination() { string testFile = UncompressedTestFile(); From a823b605179b8fc26ffaf8256f7227ea7f3adc7d Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Mon, 24 May 2021 07:25:13 +0300 Subject: [PATCH 063/115] Some cleanup of `var_types` - related functions (#52418) * Specified the parameter name for ReinterpretHexAsDecimal * Refactored "genUnsignedType", now "varTypeToUnsigned" Renamed "genUnsignedType" to "varTypeToUnsigned" to conform to the existing naming convention, moved its definition from "compiler.hpp" to "vartype.h", made it a templated function like all the other "varType*" functions. Deleted the equivalent but unused "varTypeSignedToUnsigned". * Deleted "genSignedType" and renamed "varTypeUnsignedToSigned" "genSignedType" had confusing semantics where it only returned the actual signed type for TYP_UINT and TYP_ULONG. Deleted the function and made the callsites explicitly request that behavior. Also renamed "varTypeUnsignedToSigned" to "varTypeToSigned" for parity with "varTypeToUnsigned" and made it a templated function. * Made "genActualType" a templated function * Made "genTypeStSz" a templated function Also renamed the parameters for it and "genTypeSize" to be consistent with "genActualType". --- src/coreclr/jit/assertionprop.cpp | 2 +- src/coreclr/jit/codegenarm.cpp | 2 +- src/coreclr/jit/codegenarm64.cpp | 2 +- src/coreclr/jit/codegenxarch.cpp | 2 +- src/coreclr/jit/compiler.h | 8 +--- src/coreclr/jit/compiler.hpp | 69 +++++------------------------- src/coreclr/jit/decomposelongs.cpp | 2 +- src/coreclr/jit/gentree.cpp | 2 +- src/coreclr/jit/lowerxarch.cpp | 4 +- src/coreclr/jit/morph.cpp | 6 +-- src/coreclr/jit/optimizer.cpp | 12 +++++- src/coreclr/jit/vartype.h | 56 +++++++++++------------- 12 files changed, 60 insertions(+), 107 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index c6a71b6ed7cd98..5cc30eeaaecc2c 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3585,7 +3585,7 @@ GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTree* t // force the fromType to unsigned if GT_UNSIGNED flag is set if (tree->IsUnsigned()) { - fromType = genUnsignedType(fromType); + fromType = varTypeToUnsigned(fromType); } // If we have a cast involving floating point types, then bail. diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 2341ebeba001a2..cc572c663c242c 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -1451,7 +1451,7 @@ void CodeGen::genIntToFloatCast(GenTree* treeNode) // force the srcType to unsigned if GT_UNSIGNED flag is set if (treeNode->gtFlags & GTF_UNSIGNED) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } // We only expect a srcType whose size is EA_4BYTE. diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 2148f5ed0e8aec..694cb55f4d2bc4 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -3367,7 +3367,7 @@ void CodeGen::genIntToFloatCast(GenTree* treeNode) // force the srcType to unsigned if GT_UNSIGNED flag is set if (treeNode->gtFlags & GTF_UNSIGNED) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } // We should never see a srcType whose size is neither EA_4BYTE or EA_8BYTE diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 56be9c16923467..9a8c00dc355381 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -6376,7 +6376,7 @@ void CodeGen::genIntToFloatCast(GenTree* treeNode) // force the srcType to unsigned if GT_UNSIGNED flag is set if (treeNode->gtFlags & GTF_UNSIGNED) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } noway_assert(!varTypeIsGC(srcType)); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index b867331ff21103..c45a6268a5a5a5 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -120,11 +120,7 @@ void* __cdecl operator new(size_t n, void* p, const jitstd::placement_t& syntax_ unsigned genLog2(unsigned value); unsigned genLog2(unsigned __int64 value); -var_types genActualType(var_types type); -var_types genUnsignedType(var_types type); -var_types genSignedType(var_types type); - -unsigned ReinterpretHexAsDecimal(unsigned); +unsigned ReinterpretHexAsDecimal(unsigned in); /*****************************************************************************/ @@ -5200,7 +5196,7 @@ class Compiler else { assert(elemTyp != TYP_STRUCT); - elemTyp = varTypeUnsignedToSigned(elemTyp); + elemTyp = varTypeToSigned(elemTyp); return CORINFO_CLASS_HANDLE(size_t(elemTyp) << 1 | 0x1); } } diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index ff0f0dee54ba06..6de3d3ee7becb1 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -569,11 +569,11 @@ inline bool genSmallTypeCanRepresentValue(var_types type, ssize_t value) extern const BYTE genTypeSizes[TYP_COUNT]; template -inline unsigned genTypeSize(T type) +inline unsigned genTypeSize(T value) { - assert((unsigned)TypeGet(type) < _countof(genTypeSizes)); + assert((unsigned)TypeGet(value) < _countof(genTypeSizes)); - return genTypeSizes[TypeGet(type)]; + return genTypeSizes[TypeGet(value)]; } /***************************************************************************** @@ -584,11 +584,12 @@ inline unsigned genTypeSize(T type) extern const BYTE genTypeStSzs[TYP_COUNT]; -inline unsigned genTypeStSz(var_types type) +template +inline unsigned genTypeStSz(T value) { - assert((unsigned)type < _countof(genTypeStSzs)); + assert((unsigned)TypeGet(value) < _countof(genTypeStSzs)); - return genTypeStSzs[type]; + return genTypeStSzs[TypeGet(value)]; } /***************************************************************************** @@ -604,64 +605,16 @@ inline unsigned genTypeStSz(var_types type) extern const BYTE genActualTypes[TYP_COUNT]; -inline var_types genActualType(var_types type) +template +inline var_types genActualType(T value) { /* Spot check to make certain the table is in synch with the enum */ - assert(genActualTypes[TYP_DOUBLE] == TYP_DOUBLE); assert(genActualTypes[TYP_REF] == TYP_REF); - assert((unsigned)type < sizeof(genActualTypes)); - return (var_types)genActualTypes[type]; -} - -/*****************************************************************************/ - -inline var_types genUnsignedType(var_types type) -{ - /* Force signed types into corresponding unsigned type */ - - switch (type) - { - case TYP_BYTE: - type = TYP_UBYTE; - break; - case TYP_SHORT: - type = TYP_USHORT; - break; - case TYP_INT: - type = TYP_UINT; - break; - case TYP_LONG: - type = TYP_ULONG; - break; - default: - break; - } - - return type; -} - -/*****************************************************************************/ - -inline var_types genSignedType(var_types type) -{ - /* Force non-small unsigned type into corresponding signed type */ - /* Note that we leave the small types alone */ - - switch (type) - { - case TYP_UINT: - type = TYP_INT; - break; - case TYP_ULONG: - type = TYP_LONG; - break; - default: - break; - } + assert((unsigned)TypeGet(value) < sizeof(genActualTypes)); - return type; + return (var_types)genActualTypes[TypeGet(value)]; } /***************************************************************************** diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp index 3ad6ce9b9ff96e..e6a624a901a2ec 100644 --- a/src/coreclr/jit/decomposelongs.cpp +++ b/src/coreclr/jit/decomposelongs.cpp @@ -539,7 +539,7 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use) if ((cast->gtFlags & GTF_UNSIGNED) != 0) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } bool skipDecomposition = false; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 21e6f2f6eac9d2..0440c879480760 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -11681,7 +11681,7 @@ void Compiler::gtDispTree(GenTree* tree, /* if GTF_UNSIGNED is set then force fromType to an unsigned type */ if (tree->gtFlags & GTF_UNSIGNED) { - fromType = genUnsignedType(fromType); + fromType = varTypeToUnsigned(fromType); } if (finalType != toType) diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index bbf7a72b6b5a43..4dfce51448fa43 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -641,7 +641,7 @@ void Lowering::LowerCast(GenTree* tree) // force the srcType to unsigned if GT_UNSIGNED flag is set if (tree->gtFlags & GTF_UNSIGNED) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } // We should never see the following casts as they are expected to be lowered @@ -4877,7 +4877,7 @@ void Lowering::ContainCheckCast(GenTreeCast* node) // force the srcType to unsigned if GT_UNSIGNED flag is set if (node->gtFlags & GTF_UNSIGNED) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } if (!node->gtOverflow() && (varTypeIsFloating(castToType) || varTypeIsFloating(srcType))) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 2aac4cb13604eb..1f6f53fd51d834 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -307,7 +307,7 @@ GenTree* Compiler::fgMorphCast(GenTree* tree) // U8 -> R4 = U8 -> R8 -> R4 else if (tree->IsUnsigned() && varTypeIsFloating(dstType)) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); if (srcType == TYP_ULONG) { @@ -337,7 +337,7 @@ GenTree* Compiler::fgMorphCast(GenTree* tree) // Do we have to do two step U4/8 -> R4/8 ? else if (tree->IsUnsigned() && varTypeIsFloating(dstType)) { - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); if (srcType == TYP_ULONG) { @@ -588,7 +588,7 @@ GenTree* Compiler::fgMorphCast(GenTree* tree) srcType = genActualType(srcType); } - srcType = genUnsignedType(srcType); + srcType = varTypeToUnsigned(srcType); } if (srcType == dstType) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 0dae3cabed81a1..460314a327f8d8 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5149,7 +5149,12 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu if (doit && (dstSize <= genTypeSize(tree->gtType))) { - tree->gtType = genSignedType(dstt); + if (!varTypeIsSmall(dstt)) + { + dstt = varTypeToSigned(dstt); + } + + tree->gtType = dstt; tree->SetVNs(vnpNarrow); /* Make sure we don't mess up the variable type */ @@ -5200,7 +5205,10 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu if (doit) { - dstt = genSignedType(dstt); + if (!varTypeIsSmall(dstt)) + { + dstt = varTypeToSigned(dstt); + } if ((oprSize == dstSize) && ((varTypeIsUnsigned(dstt) == varTypeIsUnsigned(oprt)) || !varTypeIsSmall(dstt))) diff --git a/src/coreclr/jit/vartype.h b/src/coreclr/jit/vartype.h index d6cca019197237..f1b134dbc7af71 100644 --- a/src/coreclr/jit/vartype.h +++ b/src/coreclr/jit/vartype.h @@ -118,13 +118,15 @@ inline bool varTypeIsSigned(T vt) return varTypeIsIntegralOrI(vt) && !varTypeIsUnsigned(vt); } -// If "vt" is an unsigned integral type, returns the corresponding signed integral type, otherwise -// return "vt". -inline var_types varTypeUnsignedToSigned(var_types vt) +// If "vt" represents an unsigned integral type, returns the corresponding signed integral type, +// otherwise returns the original type. +template +inline var_types varTypeToSigned(T vt) { - if (varTypeIsUnsigned(vt)) + var_types type = TypeGet(vt); + if (varTypeIsUnsigned(type)) { - switch (vt) + switch (type) { case TYP_BOOL: case TYP_UBYTE: @@ -139,35 +141,29 @@ inline var_types varTypeUnsignedToSigned(var_types vt) unreached(); } } - else - { - return vt; - } + + return type; } -// If "vt" is a signed integral type, returns the corresponding unsigned integral type, otherwise -// return "vt". -inline var_types varTypeSignedToUnsigned(var_types vt) +// If "vt" represents a signed integral type, returns the corresponding unsigned integral type, +// otherwise returns the original type. +template +inline var_types varTypeToUnsigned(T vt) { - if (varTypeIsSigned(vt)) - { - switch (vt) - { - case TYP_BYTE: - return TYP_UBYTE; - case TYP_SHORT: - return TYP_USHORT; - case TYP_INT: - return TYP_UINT; - case TYP_LONG: - return TYP_ULONG; - default: - unreached(); - } - } - else + // Force signed types into corresponding unsigned type. + var_types type = TypeGet(vt); + switch (type) { - return vt; + case TYP_BYTE: + return TYP_UBYTE; + case TYP_SHORT: + return TYP_USHORT; + case TYP_INT: + return TYP_UINT; + case TYP_LONG: + return TYP_ULONG; + default: + return type; } } From 4cead3fe059131095ef108e29f2a9c23193cf44a Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Mon, 24 May 2021 07:26:04 +0300 Subject: [PATCH 064/115] Fix a 32-bit specific bug in `fgMorphCast` (#52828) * Added a test Verifying that checked '.un' casts from floats to small types are not treated as casts from unsigned types. * Do not mark casts from FP types with GTF_UNSIGNED It used to be that in the importer, whether the cast was to be marked as GTF_UNSIGNED was decided exclusively based on the incoming opcode. However, the flag only makes sense for casts from integral sources, and it turns out morph had a bug where it failed to clear this flag which resulted in bad codegen. The bug went as follows: "gtMorphCast" turns casts from an FP type to a small integer into a chain of casts: CAST(small integer <- FP) => CAST(small integer <- CAST(TYP_INT <- FP)). On 32 bit platforms, the code failed to clear the GTF_UNSIGNED flag from the original tree, which meant that the outer cast thought it had TYP_UINT as the source. This matters for checked casts: conv.ovf.i2.un(-2.0d), which is a legitimate conversion, was interpreted wrongly as an overflowing one as the resulting codegen only checked the upper bound via an unsigned compare. The fix is two-fold: clear GTF_UNSIGNED for GT_CAST nodes with FP sources on creation and unify the 64 bit and 32 bit paths in "gtMorphCast", which, after the removal of GTF_UNSIGNED handling, are identical. This is a zero-diff change across all SPMI collections for Windows x64, Linux x64, Linux ARM64. This **is not** a zero-diff change for Windows x86. Instances of bad codegen have been corrected in some tests. * Assert instead of normalizing Instead of normalizing GTF_UNSIGNED for FP sources in "gtNewCastNode", assert that it is not set in GenTreeCast's constructor and fix the importer to respect that constraint. --- src/coreclr/jit/compiler.hpp | 10 +- src/coreclr/jit/gentree.h | 5 + src/coreclr/jit/importer.cpp | 10 +- src/coreclr/jit/morph.cpp | 15 +- ...conversions_are_not_treated_as_unsigned.il | 409 ++++++++++++++++++ ...ersions_are_not_treated_as_unsigned.ilproj | 12 + src/tests/issues.targets | 3 + 7 files changed, 448 insertions(+), 16 deletions(-) create mode 100644 src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.il create mode 100644 src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.ilproj diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 6de3d3ee7becb1..091758bcdeeca3 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1365,8 +1365,9 @@ inline void GenTree::SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate) inline GenTreeCast* Compiler::gtNewCastNode(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType) { - GenTreeCast* res = new (this, GT_CAST) GenTreeCast(typ, op1, fromUnsigned, castType); - return res; + GenTreeCast* cast = new (this, GT_CAST) GenTreeCast(typ, op1, fromUnsigned, castType); + + return cast; } inline GenTreeCast* Compiler::gtNewCastNodeL(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType) @@ -1378,9 +1379,10 @@ inline GenTreeCast* Compiler::gtNewCastNodeL(var_types typ, GenTree* op1, bool f /* Make a big node first and then change it to be GT_CAST */ - GenTreeCast* res = + GenTreeCast* cast = new (this, LargeOpOpcode()) GenTreeCast(typ, op1, fromUnsigned, castType DEBUGARG(/*largeNode*/ true)); - return res; + + return cast; } inline GenTreeIndir* Compiler::gtNewMethodTableLookup(GenTree* object) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 5808ac20acbf62..856fe78747f86a 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -3531,6 +3531,11 @@ struct GenTreeCast : public GenTreeOp GenTreeCast(var_types type, GenTree* op, bool fromUnsigned, var_types castType DEBUGARG(bool largeNode = false)) : GenTreeOp(GT_CAST, type, op, nullptr DEBUGARG(largeNode)), gtCastType(castType) { + // We do not allow casts from floating point types to be treated as from + // unsigned to avoid bugs related to wrong GTF_UNSIGNED in case the + // CastOp's type changes. + assert(!varTypeIsFloating(op) || !fromUnsigned); + gtFlags |= fromUnsigned ? GTF_UNSIGNED : GTF_EMPTY; } #if DEBUGGABLE_GENTREE diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index b929424c560896..d038eba4a57ccc 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -13456,11 +13456,17 @@ void Compiler::impImportBlockCode(BasicBlock* block) callNode = varTypeIsFloating(impStackTop().val->TypeGet()); } - // At this point uns, ovf, callNode all set - op1 = impPopStack().val; impBashVarAddrsToI(op1); + // Casts from floating point types must not have GTF_UNSIGNED set. + if (varTypeIsFloating(op1)) + { + uns = false; + } + + // At this point uns, ovf, callNode are all set. + if (varTypeIsSmall(lclTyp) && !ovfl && op1->gtType == TYP_INT && op1->gtOper == GT_AND) { op2 = op1->AsOp()->gtOp2; diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 1f6f53fd51d834..9fe30eea23e102 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -183,20 +183,15 @@ GenTree* Compiler::fgMorphCast(GenTree* tree) // do we need to do it in two steps R -> I, '-> smallType CLANG_FORMAT_COMMENT_ANCHOR; -#if defined(TARGET_ARM64) || defined(TARGET_AMD64) if (dstSize < genTypeSize(TYP_INT)) { - oper = gtNewCastNodeL(TYP_INT, oper, tree->IsUnsigned(), TYP_INT); - oper->gtFlags |= (tree->gtFlags & (GTF_OVERFLOW | GTF_EXCEPT)); - tree->gtFlags &= ~GTF_UNSIGNED; - } -#else - if (dstSize < TARGET_POINTER_SIZE) - { - oper = gtNewCastNodeL(TYP_I_IMPL, oper, false, TYP_I_IMPL); + oper = gtNewCastNodeL(TYP_INT, oper, /* fromUnsigned */ false, TYP_INT); oper->gtFlags |= (tree->gtFlags & (GTF_OVERFLOW | GTF_EXCEPT)); + // We must not mistreat the original cast, which was from a floating point type, + // as from an unsigned type, since we now have a TYP_INT node for the source and + // CAST_OVF(BYTE <- INT) != CAST_OVF(BYTE <- UINT). + assert(!tree->IsUnsigned()); } -#endif else { /* Note that if we need to use a helper call then we can not morph oper */ diff --git a/src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.il b/src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.il new file mode 100644 index 00000000000000..e79603733bb77d --- /dev/null +++ b/src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.il @@ -0,0 +1,409 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Console { auto } +.assembly extern System.Runtime { auto } +.assembly SignedOverflowConversionsAreNotTreatedAsUnsigned { } + +.class auto SignedOverflowConversionsAreNotTreatedAsUnsigned extends [System.Runtime]System.Object +{ + .method private static void Print(class [System.Runtime]System.String) cil managed + { + ldarg 0 + call void [System.Console]System.Console::WriteLine(class [System.Runtime]System.String) + ret + } + + .method private hidebysig static int32 Main() cil managed + { + .entrypoint + .locals init + ( + [0] int32 result + ) + + ldc.i4 100 + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I1_Un_FromMinusTwoFloat32() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I2_Un_FromMinusTwoFloat32() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I4_Un_FromMinusTwoFloat32() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I8_Un_FromMinusTwoFloat32() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I1_Un_FromMinusTwoFloat64() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I2_Un_FromMinusTwoFloat64() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I4_Un_FromMinusTwoFloat64() + add + stloc result + + ldloc result + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::TestConv_Ovf_I8_Un_FromMinusTwoFloat64() + add + stloc result + + ldloc result + ldloc result + ldc.i4 100 + ceq + brtrue SUCCESS + + ldstr "FAILED" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + ret + +SUCCESS: + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I1_Un_FromMinusTwoFloat32() cil managed noinlining + { + .locals init + ( + [0] float32 minusTwoFloat32, + [1] int32 result + ) + + ldc.r4 -2.0 + stloc minusTwoFloat32 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat32 + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I1_Un_FromFloat32(float32) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i1.ovf.un(-2.0f) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I2_Un_FromMinusTwoFloat32() cil managed noinlining + { + .locals init + ( + [0] float32 minusTwoFloat32, + [1] int32 result + ) + + ldc.r4 -2.0 + stloc minusTwoFloat32 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat32 + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I2_Un_FromFloat32(float32) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i2.ovf.un(-2.0f) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I4_Un_FromMinusTwoFloat32() cil managed noinlining + { + .locals init + ( + [0] float32 minusTwoFloat32, + [1] int32 result + ) + + ldc.r4 -2.0 + stloc minusTwoFloat32 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat32 + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I4_Un_FromFloat32(float32) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i4.ovf.un(-2.0f) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I8_Un_FromMinusTwoFloat32() cil managed noinlining + { + .locals init + ( + [0] float32 minusTwoFloat32, + [1] int32 result + ) + + ldc.r4 -2.0 + stloc minusTwoFloat32 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat32 + call int64 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I8_Un_FromFloat32(float32) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i8.ovf.un(-2.0f) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I1_Un_FromMinusTwoFloat64() cil managed noinlining + { + .locals init + ( + [0] float64 minusTwoFloat64, + [1] int32 result + ) + + ldc.r8 -2.0 + stloc minusTwoFloat64 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat64 + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I1_Un_FromFloat64(float64) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i1.ovf.un(-2.0d) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I2_Un_FromMinusTwoFloat64() cil managed noinlining + { + .locals init + ( + [0] float64 minusTwoFloat64, + [1] int32 result + ) + + ldc.r8 -2.0 + stloc minusTwoFloat64 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat64 + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I2_Un_FromFloat64(float64) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i2.ovf.un(-2.0d) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I4_Un_FromMinusTwoFloat64() cil managed noinlining + { + .locals init + ( + [0] float64 minusTwoFloat64, + [1] int32 result + ) + + ldc.r8 -2.0 + stloc minusTwoFloat64 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat64 + call int32 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I4_Un_FromFloat64(float64) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i4.ovf.un(-2.0d) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 TestConv_Ovf_I8_Un_FromMinusTwoFloat64() cil managed noinlining + { + .locals init + ( + [0] float64 minusTwoFloat64, + [1] int32 result + ) + + ldc.r8 -2.0 + stloc minusTwoFloat64 + ldc.i4 0 + stloc result + + .try + { + ldloc minusTwoFloat64 + call int64 SignedOverflowConversionsAreNotTreatedAsUnsigned::Conv_Ovf_I8_Un_FromFloat64(float64) + pop + leave END + } + catch [System.Runtime]System.OverflowException + { + ldc.i4 1 + stloc result + ldstr "conv.i8.ovf.un(-2.0d) resulted in an OverflowException!" + call void SignedOverflowConversionsAreNotTreatedAsUnsigned::Print(class [System.Runtime]System.String) + leave END + } + +END: + ldloc result + ret + } + + .method private hidebysig static int32 Conv_Ovf_I1_Un_FromFloat32(float32 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i1.un + ret + } + + .method private hidebysig static int32 Conv_Ovf_I2_Un_FromFloat32(float32 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i2.un + ret + } + + .method private hidebysig static int32 Conv_Ovf_I4_Un_FromFloat32(float32 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i4.un + ret + } + + .method private hidebysig static int64 Conv_Ovf_I8_Un_FromFloat32(float32 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i8.un + ret + } + + .method private hidebysig static int32 Conv_Ovf_I1_Un_FromFloat64(float64 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i1.un + ret + } + + .method private hidebysig static int32 Conv_Ovf_I2_Un_FromFloat64(float64 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i2.un + ret + } + + .method private hidebysig static int32 Conv_Ovf_I4_Un_FromFloat64(float64 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i4.un + ret + } + + .method private hidebysig static int64 Conv_Ovf_I8_Un_FromFloat64(float64 input) cil managed noinlining + { + ldarg 0 + conv.ovf.i8.un + ret + } +} diff --git a/src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.ilproj b/src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.ilproj new file mode 100644 index 00000000000000..36bd563485b251 --- /dev/null +++ b/src/tests/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned.ilproj @@ -0,0 +1,12 @@ + + + Exe + 0 + + + PdbOnly + + + + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 86911b4d6b1428..5a4d501681cec3 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1322,6 +1322,9 @@ needs triage + + https://github.com/dotnet/runtime/issues/51323 + needs triage From a45bdb3e449b1976740febe919d95c3b417bffa2 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 23 May 2021 21:36:09 -0700 Subject: [PATCH 065/115] Optimise GetCustomAttributes - Part 1 (#53152) - Use is/is not instead of ==/!=. Avoids overhead from operator overloading - Pass ListBuilder as ref instead of out. Avoids redundant initialization to default. - Use HashSet instead of Dictionary. Co-authored-by: Ben Adams --- .../src/System/Reflection/CustomAttribute.cs | 288 +++++++++--------- 1 file changed, 143 insertions(+), 145 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs index 4458fc4e6af2a0..5f4aca74b99a5e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs @@ -8,6 +8,8 @@ using System.Runtime.InteropServices; using System.Text; +using Internal.Runtime.CompilerServices; + namespace System.Reflection { public class CustomAttributeData @@ -15,7 +17,7 @@ public class CustomAttributeData #region Public Static Members public static IList GetCustomAttributes(MemberInfo target) { - if (target == null) + if (target is null) throw new ArgumentNullException(nameof(target)); return target.GetCustomAttributesData(); @@ -23,7 +25,7 @@ public static IList GetCustomAttributes(MemberInfo target) public static IList GetCustomAttributes(Module target) { - if (target == null) + if (target is null) throw new ArgumentNullException(nameof(target)); return target.GetCustomAttributesData(); @@ -31,7 +33,7 @@ public static IList GetCustomAttributes(Module target) public static IList GetCustomAttributes(Assembly target) { - if (target == null) + if (target is null) throw new ArgumentNullException(nameof(target)); return target.GetCustomAttributesData(); @@ -39,7 +41,7 @@ public static IList GetCustomAttributes(Assembly target) public static IList GetCustomAttributes(ParameterInfo target) { - if (target == null) + if (target is null) throw new ArgumentNullException(nameof(target)); return target.GetCustomAttributesData(); @@ -49,55 +51,58 @@ public static IList GetCustomAttributes(ParameterInfo targe #region Internal Static Members internal static IList GetCustomAttributesInternal(RuntimeType target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), out RuntimeType.ListBuilder pcas); - return GetCombinedList(cad, ref pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); + return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } internal static IList GetCustomAttributesInternal(RuntimeFieldInfo target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), out RuntimeType.ListBuilder pcas); - return GetCombinedList(cad, ref pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); + return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } internal static IList GetCustomAttributesInternal(RuntimeMethodInfo target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), out RuntimeType.ListBuilder pcas); - return GetCombinedList(cad, ref pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); + return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } internal static IList GetCustomAttributesInternal(RuntimeConstructorInfo target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); } internal static IList GetCustomAttributesInternal(RuntimeEventInfo target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); } internal static IList GetCustomAttributesInternal(RuntimePropertyInfo target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); } internal static IList GetCustomAttributesInternal(RuntimeModule target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); if (target.IsResource()) return new List(); @@ -107,7 +112,7 @@ internal static IList GetCustomAttributesInternal(RuntimeMo internal static IList GetCustomAttributesInternal(RuntimeAssembly target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); // No pseudo attributes for RuntimeAssembly @@ -116,17 +121,17 @@ internal static IList GetCustomAttributesInternal(RuntimeAs internal static IList GetCustomAttributesInternal(RuntimeParameterInfo target) { - Debug.Assert(target != null); + Debug.Assert(target is not null); + RuntimeType.ListBuilder pcas = default; IList cad = GetCustomAttributes(target.GetRuntimeModule()!, target.MetadataToken); - PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), out RuntimeType.ListBuilder pcas); - return GetCombinedList(cad, ref pcas); + PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); + return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } private static IList GetCombinedList(IList customAttributes, ref RuntimeType.ListBuilder pseudoAttributes) { - if (pseudoAttributes.Count == 0) - return customAttributes; + Debug.Assert(pseudoAttributes.Count != 0); CustomAttributeData[] pca = new CustomAttributeData[customAttributes.Count + pseudoAttributes.Count]; customAttributes.CopyTo(pca, pseudoAttributes.Count); @@ -376,12 +381,12 @@ private void Init(MarshalAsAttribute marshalAs) }); int i = 3; // ArraySubType, SizeParamIndex, SizeConst - if (marshalAs.MarshalType != null) i++; - if (marshalAs.MarshalTypeRef != null) i++; - if (marshalAs.MarshalCookie != null) i++; + if (marshalAs.MarshalType is not null) i++; + if (marshalAs.MarshalTypeRef is not null) i++; + if (marshalAs.MarshalCookie is not null) i++; i++; // IidParameterIndex i++; // SafeArraySubType - if (marshalAs.SafeArrayUserDefinedSubType != null) i++; + if (marshalAs.SafeArrayUserDefinedSubType is not null) i++; CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[i]; // For compatibility with previous runtimes, we always include the following 5 attributes, regardless @@ -392,13 +397,13 @@ private void Init(MarshalAsAttribute marshalAs) namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeConst")!, marshalAs.SizeConst); namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("IidParameterIndex")!, marshalAs.IidParameterIndex); namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArraySubType")!, marshalAs.SafeArraySubType); - if (marshalAs.MarshalType != null) + if (marshalAs.MarshalType is not null) namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalType")!, marshalAs.MarshalType); - if (marshalAs.MarshalTypeRef != null) + if (marshalAs.MarshalTypeRef is not null) namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalTypeRef")!, marshalAs.MarshalTypeRef); - if (marshalAs.MarshalCookie != null) + if (marshalAs.MarshalCookie is not null) namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalCookie")!, marshalAs.MarshalCookie); - if (marshalAs.SafeArrayUserDefinedSubType != null) + if (marshalAs.SafeArrayUserDefinedSubType is not null) namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArrayUserDefinedSubType")!, marshalAs.SafeArrayUserDefinedSubType); m_namedArgs = Array.AsReadOnly(namedArgs); @@ -481,7 +486,7 @@ public virtual IList ConstructorArguments { get { - if (m_typedCtorArgs == null) + if (m_typedCtorArgs is null) { CustomAttributeTypedArgument[] typedCtorArgs = new CustomAttributeTypedArgument[m_ctorParams.Length]; @@ -503,9 +508,9 @@ public virtual IList NamedArguments { get { - if (m_namedArgs == null) + if (m_namedArgs is null) { - if (m_namedParams == null) + if (m_namedParams is null) return null!; int cNamedArgs = 0; @@ -609,7 +614,7 @@ private static RuntimeType ResolveType(RuntimeModule scope, string typeName) { RuntimeType type = RuntimeTypeHandle.GetTypeByNameUsingCARules(typeName, scope); - if (type == null) + if (type is null) throw new InvalidOperationException( SR.Format(SR.Arg_CATypeResolutionFailed, typeName)); @@ -619,7 +624,7 @@ private static RuntimeType ResolveType(RuntimeModule scope, string typeName) private static object CanonicalizeValue(object value) { - Debug.Assert(value != null); + Debug.Assert(value is not null); if (value.GetType().IsEnum) { @@ -651,7 +656,7 @@ internal CustomAttributeTypedArgument(RuntimeModule scope, CustomAttributeEncode m_value = null; - if (encodedArg.StringValue != null) + if (encodedArg.StringValue is not null) m_value = ResolveType(scope, encodedArg.StringValue); } else if (encodedType == CustomAttributeEncoding.Array) @@ -670,7 +675,7 @@ internal CustomAttributeTypedArgument(RuntimeModule scope, CustomAttributeEncode m_argumentType = elementType.MakeArrayType(); - if (encodedArg.ArrayValue == null) + if (encodedArg.ArrayValue is null) { m_value = null; } @@ -749,11 +754,11 @@ internal static void ParseAttributeArguments(ConstArray attributeBlob, ref CustomAttributeNamedParameter[] customAttributeNamedParameters, RuntimeModule customAttributeModule) { - if (customAttributeModule == null) + if (customAttributeModule is null) throw new ArgumentNullException(nameof(customAttributeModule)); - Debug.Assert(customAttributeCtorParameters != null); - Debug.Assert(customAttributeNamedParameters != null); + Debug.Assert(customAttributeCtorParameters is not null); + Debug.Assert(customAttributeNamedParameters is not null); if (customAttributeCtorParameters.Length != 0 || customAttributeNamedParameters.Length != 0) { @@ -783,7 +788,7 @@ internal readonly struct CustomAttributeNamedParameter public CustomAttributeNamedParameter(string argumentName, CustomAttributeEncoding fieldOrProperty, CustomAttributeType type) { - if (argumentName == null) + if (argumentName is null) throw new ArgumentNullException(nameof(argumentName)); m_argumentName = argumentName; @@ -845,9 +850,9 @@ internal static unsafe class CustomAttribute #region Internal Static Members internal static bool IsDefined(RuntimeType type, RuntimeType? caType, bool inherit) { - Debug.Assert(type != null); + Debug.Assert(type is not null); - if (type.GetElementType() != null) + if (type.GetElementType() is not null) return false; if (PseudoCustomAttribute.IsDefined(type, caType)) @@ -861,7 +866,7 @@ internal static bool IsDefined(RuntimeType type, RuntimeType? caType, bool inher type = (type.BaseType as RuntimeType)!; - while (type != null) + while (type is not null) { if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType, 0, inherit)) return true; @@ -874,8 +879,8 @@ internal static bool IsDefined(RuntimeType type, RuntimeType? caType, bool inher internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, bool inherit) { - Debug.Assert(method != null); - Debug.Assert(caType != null); + Debug.Assert(method is not null); + Debug.Assert(caType is not null); if (PseudoCustomAttribute.IsDefined(method, caType)) return true; @@ -888,7 +893,7 @@ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, boo method = method.GetParentDefinition()!; - while (method != null) + while (method is not null) { if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType, 0, inherit)) return true; @@ -901,8 +906,8 @@ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, boo internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType) { - Debug.Assert(ctor != null); - Debug.Assert(caType != null); + Debug.Assert(ctor is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeConstructorInfo @@ -911,8 +916,8 @@ internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType) internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType) { - Debug.Assert(property != null); - Debug.Assert(caType != null); + Debug.Assert(property is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimePropertyInfo @@ -921,8 +926,8 @@ internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType) internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType) { - Debug.Assert(e != null); - Debug.Assert(caType != null); + Debug.Assert(e is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeEventInfo @@ -931,8 +936,8 @@ internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType) internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType) { - Debug.Assert(field != null); - Debug.Assert(caType != null); + Debug.Assert(field is not null); + Debug.Assert(caType is not null); if (PseudoCustomAttribute.IsDefined(field, caType)) return true; @@ -942,8 +947,8 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType) internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType) { - Debug.Assert(parameter != null); - Debug.Assert(caType != null); + Debug.Assert(parameter is not null); + Debug.Assert(caType is not null); if (PseudoCustomAttribute.IsDefined(parameter, caType)) return true; @@ -953,8 +958,8 @@ internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caTyp internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType) { - Debug.Assert(assembly != null); - Debug.Assert(caType != null); + Debug.Assert(assembly is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeAssembly return IsCustomAttributeDefined((assembly.ManifestModule as RuntimeModule)!, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType); @@ -962,8 +967,8 @@ internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType) internal static bool IsDefined(RuntimeModule module, RuntimeType caType) { - Debug.Assert(module != null); - Debug.Assert(caType != null); + Debug.Assert(module is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeModule @@ -972,16 +977,17 @@ internal static bool IsDefined(RuntimeModule module, RuntimeType caType) internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool inherit) { - Debug.Assert(type != null); - Debug.Assert(caType != null); + Debug.Assert(type is not null); + Debug.Assert(caType is not null); - if (type.GetElementType() != null) + if (type.GetElementType() is not null) return (caType.IsValueType) ? Array.Empty() : CreateAttributeArrayHelper(caType, 0); if (type.IsGenericType && !type.IsGenericTypeDefinition) type = (type.GetGenericTypeDefinition() as RuntimeType)!; - PseudoCustomAttribute.GetCustomAttributes(type, caType, out RuntimeType.ListBuilder pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(type, caType, ref pcas); // if we are asked to go up the hierarchy chain we have to do it now and regardless of the // attribute usage for the specific attribute because a derived attribute may override the usage... @@ -1018,13 +1024,14 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp internal static object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool inherit) { - Debug.Assert(method != null); - Debug.Assert(caType != null); + Debug.Assert(method is not null); + Debug.Assert(caType is not null); if (method.IsGenericMethod && !method.IsGenericMethodDefinition) method = (method.GetGenericMethodDefinition() as RuntimeMethodInfo)!; - PseudoCustomAttribute.GetCustomAttributes(method, caType, out RuntimeType.ListBuilder pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(method, caType, ref pcas); // if we are asked to go up the hierarchy chain we have to do it now and regardless of the // attribute usage for the specific attribute because a derived attribute may override the usage... @@ -1071,8 +1078,8 @@ internal static object[] GetCustomAttributes(RuntimeConstructorInfo ctor, Runtim internal static object[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType) { - Debug.Assert(property != null); - Debug.Assert(caType != null); + Debug.Assert(property is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimePropertyInfo @@ -1081,8 +1088,8 @@ internal static object[] GetCustomAttributes(RuntimePropertyInfo property, Runti internal static object[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType) { - Debug.Assert(e != null); - Debug.Assert(caType != null); + Debug.Assert(e is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeEventInfo @@ -1091,10 +1098,11 @@ internal static object[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caT internal static object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType) { - Debug.Assert(field != null); - Debug.Assert(caType != null); + Debug.Assert(field is not null); + Debug.Assert(caType is not null); - PseudoCustomAttribute.GetCustomAttributes(field, caType, out RuntimeType.ListBuilder pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(field, caType, ref pcas); object[] attributes = GetCustomAttributes(field.GetRuntimeModule(), field.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); return attributes; @@ -1102,10 +1110,11 @@ internal static object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType internal static object[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType) { - Debug.Assert(parameter != null); - Debug.Assert(caType != null); + Debug.Assert(parameter is not null); + Debug.Assert(caType is not null); - PseudoCustomAttribute.GetCustomAttributes(parameter, caType, out RuntimeType.ListBuilder pcas); + RuntimeType.ListBuilder pcas = default; + PseudoCustomAttribute.GetCustomAttributes(parameter, caType, ref pcas); object[] attributes = GetCustomAttributes(parameter.GetRuntimeModule()!, parameter.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); return attributes; @@ -1113,8 +1122,8 @@ internal static object[] GetCustomAttributes(RuntimeParameterInfo parameter, Run internal static object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType) { - Debug.Assert(assembly != null); - Debug.Assert(caType != null); + Debug.Assert(assembly is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeAssembly @@ -1124,8 +1133,8 @@ internal static object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeTy internal static object[] GetCustomAttributes(RuntimeModule module, RuntimeType caType) { - Debug.Assert(module != null); - Debug.Assert(caType != null); + Debug.Assert(module is not null); + Debug.Assert(caType is not null); // No pseudo attributes for RuntimeModule @@ -1156,7 +1165,7 @@ private static bool IsCustomAttributeDefined( } CustomAttributeRecord record = default; - if (attributeFilterType != null) + if (attributeFilterType is not null) { Debug.Assert(attributeCtorToken == 0); @@ -1177,7 +1186,7 @@ private static bool IsCustomAttributeDefined( } else { - Debug.Assert(attributeFilterType == null); + Debug.Assert(attributeFilterType is null); Debug.Assert(!MetadataToken.IsNullToken(attributeCtorToken)); for (int i = 0; i < attributeTokens.Length; i++) @@ -1202,7 +1211,7 @@ private static object[] GetCustomAttributes( AddCustomAttributes(ref attributes, decoratedModule, decoratedMetadataToken, attributeFilterType, false, default); - bool useObjectArray = attributeFilterType == null || attributeFilterType.IsValueType || attributeFilterType.ContainsGenericParameters; + bool useObjectArray = attributeFilterType is null || attributeFilterType.IsValueType || attributeFilterType.ContainsGenericParameters; RuntimeType arrayType = useObjectArray ? (RuntimeType)typeof(object) : attributeFilterType!; object[] result = CreateAttributeArrayHelper(arrayType, attributes.Count + pcaCount); @@ -1253,7 +1262,7 @@ private static void AddCustomAttributes( // Create custom attribute object int cNamedArgs; object attribute; - if (ctorWithParameters != null) + if (ctorWithParameters is not null) { attribute = CreateCaObject(decoratedModule, attributeType, ctorWithParameters, ref blobStart, blobEnd, out cNamedArgs); } @@ -1269,25 +1278,20 @@ private static void AddCustomAttributes( } else { + int data = Unsafe.ReadUnaligned((void*)blobStart); +#if BIGENDIAN // Metadata is always written in little-endian format. Must account for this on // big-endian platforms. -#if BIGENDIAN - const int CustomAttributeVersion = 0x0100; -#else - const int CustomAttributeVersion = 0x0001; + data = BinaryPrimitives.ReverseEndianness(data); #endif - if (Marshal.ReadInt16(blobStart) != CustomAttributeVersion) + const int CustomAttributeVersion = 0x0001; + if ((data & 0xffff) != CustomAttributeVersion) { throw new CustomAttributeFormatException(); } + cNamedArgs = data >> 16; - blobStart = (IntPtr)((byte*)blobStart + 2); // skip version prefix - - cNamedArgs = Marshal.ReadInt16(blobStart); - blobStart = (IntPtr)((byte*)blobStart + 2); // skip namedArgs count -#if BIGENDIAN - cNamedArgs = ((cNamedArgs & 0xff00) >> 8) | ((cNamedArgs & 0x00ff) << 8); -#endif + blobStart = (IntPtr)((byte*)blobStart + 4); // skip version and namedArgs count } } @@ -1299,7 +1303,7 @@ private static void AddCustomAttributes( { if (isProperty) { - if (type is null && value != null) + if (type is null && value is not null) { type = (RuntimeType)value.GetType(); if (type == Type_RuntimeType) @@ -1313,10 +1317,9 @@ private static void AddCustomAttributes( attributeType.GetProperty(name, type, Type.EmptyTypes); // Did we get a valid property reference? - if (property == null) + if (property is null) { - throw new CustomAttributeFormatException( - SR.Format(SR.RFLCT_InvalidPropFail, name)); + throw new CustomAttributeFormatException(SR.Format(SR.RFLCT_InvalidPropFail, name)); } MethodInfo setMethod = property.GetSetMethod(true)!; @@ -1449,7 +1452,7 @@ private static bool FilterCustomAttributeRecord( RuntimeTypeHandle attributeTypeHandle = attributeType.TypeHandle; bool result = RuntimeMethodHandle.IsCAVisibleFromDecoratedType(new QCallTypeHandle(ref attributeTypeHandle), - ctorWithParameters != null ? ctorWithParameters.Value : RuntimeMethodHandleInternal.EmptyHandle, + ctorWithParameters is not null ? ctorWithParameters.Value : RuntimeMethodHandleInternal.EmptyHandle, new QCallTypeHandle(ref parentTypeHandle), new QCallModule(ref decoratedModule)) != Interop.BOOL.FALSE; @@ -1509,7 +1512,7 @@ internal static AttributeUsageAttribute GetAttributeUsage(RuntimeType decoratedA if (attributeType != (RuntimeType)typeof(AttributeUsageAttribute)) continue; - if (attributeUsageAttribute != null) + if (attributeUsageAttribute is not null) throw new FormatException(SR.Format(SR.Format_AttributeUsage, attributeType)); ParseAttributeUsageAttribute(caRecord.blob, out AttributeTargets targets, out bool inherited, out bool allowMultiple); @@ -1576,11 +1579,11 @@ internal static class PseudoCustomAttribute // the only method that adds values to the Dictionary. For more details on // Dictionary versus Hashtable thread safety: // See code:Dictionary#DictionaryVersusHashtableThreadSafety - private static readonly Dictionary s_pca = CreatePseudoCustomAttributeDictionary(); + private static readonly HashSet s_pca = CreatePseudoCustomAttributeHashSet(); #endregion #region Static Constructor - private static Dictionary CreatePseudoCustomAttributeDictionary() + private static HashSet CreatePseudoCustomAttributeHashSet() { Type[] pcas = new Type[] { @@ -1598,13 +1601,13 @@ private static Dictionary CreatePseudoCustomAttributeD typeof(TypeForwardedToAttribute), // assembly }; - Dictionary dict = new Dictionary(pcas.Length); + HashSet set = new HashSet(pcas.Length); foreach (RuntimeType runtimeType in pcas) { VerifyPseudoCustomAttribute(runtimeType); - dict[runtimeType] = runtimeType; + set.Add(runtimeType); } - return dict; + return set; } [Conditional("DEBUG")] @@ -1621,14 +1624,13 @@ private static void VerifyPseudoCustomAttribute(RuntimeType pca) #endregion #region Internal Static - internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, out RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, ref RuntimeType.ListBuilder pcas) { - Debug.Assert(type != null); - Debug.Assert(caType != null); - pcas = default; + Debug.Assert(type is not null); + Debug.Assert(caType is not null); bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType)) + if (!all && !s_pca.Contains(caType)) return; if (all || caType == typeof(SerializableAttribute)) @@ -1645,7 +1647,7 @@ internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, o internal static bool IsDefined(RuntimeType type, RuntimeType? caType) { bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType!)) + if (!all && !s_pca.Contains(caType!)) return false; if (all || caType == typeof(SerializableAttribute)) @@ -1662,20 +1664,19 @@ internal static bool IsDefined(RuntimeType type, RuntimeType? caType) return false; } - internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, out RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, ref RuntimeType.ListBuilder pcas) { - Debug.Assert(method != null); - Debug.Assert(caType != null); - pcas = default; + Debug.Assert(method is not null); + Debug.Assert(caType is not null); bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType)) + if (!all && !s_pca.Contains(caType)) return; if (all || caType == typeof(DllImportAttribute)) { Attribute? pca = GetDllImportCustomAttribute(method); - if (pca != null) pcas.Add(pca); + if (pca is not null) pcas.Add(pca); } if (all || caType == typeof(PreserveSigAttribute)) { @@ -1686,7 +1687,7 @@ internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType c internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType? caType) { bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType!)) + if (!all && !s_pca.Contains(caType!)) return false; if (all || caType == typeof(DllImportAttribute)) @@ -1703,14 +1704,13 @@ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType? caType) return false; } - internal static void GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, out RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, ref RuntimeType.ListBuilder pcas) { - Debug.Assert(parameter != null); - Debug.Assert(caType != null); - pcas = default; + Debug.Assert(parameter is not null); + Debug.Assert(caType is not null); bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType)) + if (!all && !s_pca.Contains(caType)) return; if (all || caType == typeof(InAttribute)) @@ -1731,13 +1731,13 @@ internal static void GetCustomAttributes(RuntimeParameterInfo parameter, Runtime if (all || caType == typeof(MarshalAsAttribute)) { Attribute? pca = GetMarshalAsCustomAttribute(parameter); - if (pca != null) pcas.Add(pca); + if (pca is not null) pcas.Add(pca); } } internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType? caType) { bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType!)) + if (!all && !s_pca.Contains(caType!)) return false; if (all || caType == typeof(InAttribute)) @@ -1754,21 +1754,19 @@ internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType? caTy } if (all || caType == typeof(MarshalAsAttribute)) { - if (GetMarshalAsCustomAttribute(parameter) != null) return true; + if (GetMarshalAsCustomAttribute(parameter) is not null) return true; } return false; } - internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, out RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, ref RuntimeType.ListBuilder pcas) { - Debug.Assert(field != null); - Debug.Assert(caType != null); - - pcas = default; + Debug.Assert(field is not null); + Debug.Assert(caType is not null); bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType)) + if (!all && !s_pca.Contains(caType)) return; Attribute? pca; @@ -1776,12 +1774,12 @@ internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caT if (all || caType == typeof(MarshalAsAttribute)) { pca = GetMarshalAsCustomAttribute(field); - if (pca != null) pcas.Add(pca); + if (pca is not null) pcas.Add(pca); } if (all || caType == typeof(FieldOffsetAttribute)) { pca = GetFieldOffsetCustomAttribute(field); - if (pca != null) pcas.Add(pca); + if (pca is not null) pcas.Add(pca); } if (all || caType == typeof(NonSerializedAttribute)) { @@ -1792,16 +1790,16 @@ internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caT internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) { bool all = caType == typeof(object) || caType == typeof(Attribute); - if (!all && !s_pca.ContainsKey(caType!)) + if (!all && !s_pca.Contains(caType!)) return false; if (all || caType == typeof(MarshalAsAttribute)) { - if (GetMarshalAsCustomAttribute(field) != null) return true; + if (GetMarshalAsCustomAttribute(field) is not null) return true; } if (all || caType == typeof(FieldOffsetAttribute)) { - if (GetFieldOffsetCustomAttribute(field) != null) return true; + if (GetFieldOffsetCustomAttribute(field) is not null) return true; } if (all || caType == typeof(NonSerializedAttribute)) { @@ -1891,13 +1889,13 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) try { - marshalTypeRef = marshalTypeName == null ? null : RuntimeTypeHandle.GetTypeByNameUsingCARules(marshalTypeName, scope); + marshalTypeRef = marshalTypeName is null ? null : RuntimeTypeHandle.GetTypeByNameUsingCARules(marshalTypeName, scope); } catch (TypeLoadException) { // The user may have supplied a bad type name string causing this TypeLoadException // Regardless, we return the bad type name - Debug.Assert(marshalTypeName != null); + Debug.Assert(marshalTypeName is not null); } MarshalAsAttribute attribute = new MarshalAsAttribute(unmanagedType); @@ -1917,7 +1915,7 @@ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType? caType) private static FieldOffsetAttribute? GetFieldOffsetCustomAttribute(RuntimeFieldInfo field) { - if (field.DeclaringType != null && + if (field.DeclaringType is not null && field.GetRuntimeModule().MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out int fieldOffset)) return new FieldOffsetAttribute(fieldOffset); From 77891744caf3d3bb9a325a6dbf6eab56c18a6483 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Mon, 24 May 2021 08:37:40 +0200 Subject: [PATCH 066/115] Fix formatting of CircularDependencyException error message (#53140) --- .../src/ServiceLookup/CallSiteChain.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs index f0803f3f96d7e3..ca65e64ca557be 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteChain.cs @@ -39,7 +39,7 @@ public void Add(Type serviceType, Type implementationType = null) private string CreateCircularDependencyExceptionMessage(Type type) { var messageBuilder = new StringBuilder(); - messageBuilder.AppendFormat(SR.CircularDependencyException, TypeNameHelper.GetTypeDisplayName(type)); + messageBuilder.Append(SR.Format(SR.CircularDependencyException, TypeNameHelper.GetTypeDisplayName(type))); messageBuilder.AppendLine(); AppendResolutionPath(messageBuilder, type); From 5b05e785b3b725a229fb9278e8c8b41c22320ae1 Mon Sep 17 00:00:00 2001 From: Levi Broderick Date: Mon, 24 May 2021 00:33:06 -0700 Subject: [PATCH 067/115] Reintroduce EnumerateRunes tests (#53114) --- .../tests/Span/EnumerateRunes.cs | 70 +++++++++++++++++++ .../tests/System.Memory.Tests.csproj | 1 + 2 files changed, 71 insertions(+) create mode 100644 src/libraries/System.Memory/tests/Span/EnumerateRunes.cs diff --git a/src/libraries/System.Memory/tests/Span/EnumerateRunes.cs b/src/libraries/System.Memory/tests/Span/EnumerateRunes.cs new file mode 100644 index 00000000000000..8db90c8b649d23 --- /dev/null +++ b/src/libraries/System.Memory/tests/Span/EnumerateRunes.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace System.SpanTests +{ + public static partial class SpanTests + { + [Fact] + public static void EnumerateRunesEmpty() + { + Assert.False(MemoryExtensions.EnumerateRunes(ReadOnlySpan.Empty).GetEnumerator().MoveNext()); + Assert.False(MemoryExtensions.EnumerateRunes(Span.Empty).GetEnumerator().MoveNext()); + } + + [Theory] + [InlineData(new char[0], new int[0])] // empty + [InlineData(new char[] { 'x', 'y', 'z' }, new int[] { 'x', 'y', 'z' })] + [InlineData(new char[] { 'x', '\uD86D', '\uDF54', 'y' }, new int[] { 'x', 0x2B754, 'y' })] // valid surrogate pair + [InlineData(new char[] { 'x', '\uD86D', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // standalone high surrogate + [InlineData(new char[] { 'x', '\uDF54', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // standalone low surrogate + [InlineData(new char[] { 'x', '\uD86D' }, new int[] { 'x', 0xFFFD })] // standalone high surrogate at end of string + [InlineData(new char[] { 'x', '\uDF54' }, new int[] { 'x', 0xFFFD })] // standalone low surrogate at end of string + [InlineData(new char[] { 'x', '\uD86D', '\uD86D', 'y' }, new int[] { 'x', 0xFFFD, 0xFFFD, 'y' })] // two high surrogates should be two replacement chars + [InlineData(new char[] { 'x', '\uFFFD', 'y' }, new int[] { 'x', 0xFFFD, 'y' })] // literal U+FFFD + public static void EnumerateRunes_Battery(char[] chars, int[] expected) + { + // Test data is smuggled as char[] instead of straight-up string since the test framework + // doesn't like invalid UTF-16 literals. + + // first, test Span + + List enumeratedValues = new List(); + foreach (Rune rune in ((Span)chars).EnumerateRunes()) + { + enumeratedValues.Add(rune.Value); + } + Assert.Equal(expected, enumeratedValues.ToArray()); + + // next, ROS + + enumeratedValues.Clear(); + foreach (Rune rune in ((ReadOnlySpan)chars).EnumerateRunes()) + { + enumeratedValues.Add(rune.Value); + } + Assert.Equal(expected, enumeratedValues.ToArray()); + } + + [Fact] + public static void EnumerateRunes_DoesNotReadPastEndOfSpan() + { + // As an optimization, reading scalars from a string *may* read past the end of the string + // to the terminating null. This optimization is invalid for arbitrary spans, so this test + // ensures that we're not performing this optimization here. + + ReadOnlySpan span = "xy\U0002B754z".AsSpan(1, 2); // well-formed string, but span splits surrogate pair + + List enumeratedValues = new List(); + foreach (Rune rune in span.EnumerateRunes()) + { + enumeratedValues.Add(rune.Value); + } + Assert.Equal(new int[] { 'y', '\uFFFD' }, enumeratedValues.ToArray()); + } + } +} diff --git a/src/libraries/System.Memory/tests/System.Memory.Tests.csproj b/src/libraries/System.Memory/tests/System.Memory.Tests.csproj index 3ef893f749cd9c..b9e9e02a838414 100644 --- a/src/libraries/System.Memory/tests/System.Memory.Tests.csproj +++ b/src/libraries/System.Memory/tests/System.Memory.Tests.csproj @@ -64,6 +64,7 @@ + From 1b1cd2045dc71a8cf6c5d779b3c7c412cf271a17 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Mon, 24 May 2021 17:40:34 +1000 Subject: [PATCH 068/115] Add missing space in xml description for IReadOnlySet.Overlaps (#53159) fixes https://github.com/dotnet/runtime/issues/53147 --- .../src/System/Collections/Generic/IReadOnlySet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlySet.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlySet.cs index 5317acd76237d9..94ecf669bc9406 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlySet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlySet.cs @@ -47,7 +47,7 @@ public interface IReadOnlySet : IReadOnlyCollection /// Determines whether the current set overlaps with the specified collection. /// /// The collection to compare to the current set. - /// if the current set and other share at least one common element; otherwise, . + /// if the current set and other share at least one common element; otherwise, . /// other is . bool Overlaps(IEnumerable other); /// From e05bb403728ad3d97c003a0dfcd561709ba738d2 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Mon, 24 May 2021 09:40:52 +0200 Subject: [PATCH 069/115] Add [return: NotNullIfNotNull("str")] to SecurityElement.Escape (#52442) --- .../src/System/Security/SecurityElement.cs | 1 + src/libraries/System.Runtime/ref/System.Runtime.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs index fc331cc57fbf54..b714b64dc26cb4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs @@ -345,6 +345,7 @@ private static string GetEscapeSequence(char c) return c.ToString(); } + [return: NotNullIfNotNull("str")] public static string? Escape(string? str) { if (str == null) diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 9561d2353f89b4..18a82ab2923412 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -10554,6 +10554,7 @@ public void AddChild(System.Security.SecurityElement child) { } public string? Attribute(string name) { throw null; } public System.Security.SecurityElement Copy() { throw null; } public bool Equal([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] System.Security.SecurityElement? other) { throw null; } + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("str")] public static string? Escape(string? str) { throw null; } public static System.Security.SecurityElement? FromString(string xml) { throw null; } public static bool IsValidAttributeName([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? name) { throw null; } From 84887bd608f09bc64ce056503401ca5b4acaeba4 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 24 May 2021 07:42:22 +0000 Subject: [PATCH 070/115] Update dependencies from https://github.com/dotnet/emsdk build 20210520.1 (#53013) [main] Update dependencies from dotnet/emsdk --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e0c39ce90ff884..c342994eb98556 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -206,9 +206,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 018b25068e2051c8b03217069d03d7f6f15e44fd - + https://github.com/dotnet/emsdk - 8c4c21d02d68241859c7c26d33316ca5c5091092 + 5a2a6482a34c2fe9ed4f9f97bb787ef0a7737965 https://github.com/dotnet/hotreload-utils diff --git a/eng/Versions.props b/eng/Versions.props index a13a1b53a09afe..3d0578ea76f54e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -20,7 +20,7 @@ true false false - 6.0.0-preview.6.21268.1 + 6.0.0-preview.6.21270.1 $(MicrosoftNETRuntimeEmscripten2012Nodewinx64Version) - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 2.5.1-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 - 6.0.0-beta.21264.2 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 2.5.1-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 + 6.0.0-beta.21271.3 5.9.0-preview.2 @@ -148,9 +148,9 @@ 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 - 1.0.0-prerelease.21268.1 - 1.0.0-prerelease.21268.1 - 1.0.1-alpha.0.21267.1 + 1.0.0-prerelease.21271.1 + 1.0.0-prerelease.21271.1 + 1.0.1-alpha.0.21271.1 2.4.1 2.4.2 1.3.0 @@ -164,7 +164,7 @@ 6.0.100-preview.5.21267.3 $(MicrosoftNETILLinkTasksVersion) - 6.0.0-preview.5.21267.1 + 6.0.0-preview.6.21268.1 9.0.1-alpha.1.21267.1 9.0.1-alpha.1.21267.1 diff --git a/eng/common/generate-locproject.ps1 b/eng/common/generate-locproject.ps1 index 24c00b5be98b01..de348a2e225c08 100644 --- a/eng/common/generate-locproject.ps1 +++ b/eng/common/generate-locproject.ps1 @@ -14,7 +14,7 @@ $ErrorActionPreference = "Stop" Import-Module -Name (Join-Path $PSScriptRoot 'native\CommonLibrary.psm1') -$exclusionsFilePath = "$SourcesDirectory\Localize\LocExclusions.json" +$exclusionsFilePath = "$SourcesDirectory\eng\Localize\LocExclusions.json" $exclusions = @{ Exclusions = @() } if (Test-Path -Path $exclusionsFilePath) { @@ -92,14 +92,14 @@ Write-Host "LocProject.json generated:`n`n$json`n`n" Pop-Location if (!$UseCheckedInLocProjectJson) { - New-Item "$SourcesDirectory\Localize\LocProject.json" -Force # Need this to make sure the Localize directory is created - Set-Content "$SourcesDirectory\Localize\LocProject.json" $json + New-Item "$SourcesDirectory\eng\Localize\LocProject.json" -Force # Need this to make sure the Localize directory is created + Set-Content "$SourcesDirectory\eng\Localize\LocProject.json" $json } else { - New-Item "$SourcesDirectory\Localize\LocProject-generated.json" -Force # Need this to make sure the Localize directory is created - Set-Content "$SourcesDirectory\Localize\LocProject-generated.json" $json + New-Item "$SourcesDirectory\eng\Localize\LocProject-generated.json" -Force # Need this to make sure the Localize directory is created + Set-Content "$SourcesDirectory\eng\Localize\LocProject-generated.json" $json - if ((Get-FileHash "$SourcesDirectory\Localize\LocProject-generated.json").Hash -ne (Get-FileHash "$SourcesDirectory\Localize\LocProject.json").Hash) { + if ((Get-FileHash "$SourcesDirectory\eng\Localize\LocProject-generated.json").Hash -ne (Get-FileHash "$SourcesDirectory\eng\Localize\LocProject.json").Hash) { Write-PipelineTelemetryError -Category "OneLocBuild" -Message "Existing LocProject.json differs from generated LocProject.json. Download LocProject-generated.json and compare them." exit 1 diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index 958db4064cf024..2acdd5256dd83c 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -53,7 +53,7 @@ jobs: env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) inputs: - locProj: Localize/LocProject.json + locProj: eng/Localize/LocProject.json outDir: $(Build.ArtifactStagingDirectory) lclSource: ${{ parameters.LclSource }} lclPackageId: ${{ parameters.LclPackageId }} @@ -79,7 +79,7 @@ jobs: - task: PublishBuildArtifacts@1 displayName: Publish LocProject.json inputs: - PathtoPublish: '$(Build.SourcesDirectory)/Localize/' + PathtoPublish: '$(Build.SourcesDirectory)/eng/Localize/' PublishLocation: Container ArtifactName: Loc condition: ${{ parameters.condition }} \ No newline at end of file diff --git a/global.json b/global.json index b772842dab0f18..1f4b469162c63b 100644 --- a/global.json +++ b/global.json @@ -12,10 +12,10 @@ "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21264.2", - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21264.2", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21264.2", - "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21264.2", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21271.3", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21271.3", + "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21271.3", + "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21271.3", "Microsoft.Build.NoTargets": "3.0.4", "Microsoft.Build.Traversal": "3.0.23", "Microsoft.NET.Sdk.IL": "6.0.0-preview.5.21267.1" From 32b20665f49b005c7c34dbe6b4a43669be52f13f Mon Sep 17 00:00:00 2001 From: hrrrrustic <35951936+hrrrrustic@users.noreply.github.com> Date: Mon, 24 May 2021 11:55:05 +0300 Subject: [PATCH 072/115] System.Collections.* missed Equals nullable annotations (#52164) * add NotNullWhen attribute * add usings --- .../ref/System.Collections.Immutable.cs | 2 +- .../System/Collections/Immutable/ImmutableArray_1.Minimal.cs | 2 +- .../ref/System.Collections.Specialized.cs | 4 ++-- .../src/System/Collections/Specialized/BitVector32.cs | 5 +++-- .../System/Collections/Generic/SortedSetEqualityComparer.cs | 4 +++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index f050f59517d5e0..2da1db4d2828f4 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -143,7 +143,7 @@ public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int l public void CopyTo(T[] destination) { } public void CopyTo(T[] destination, int destinationIndex) { } public bool Equals(System.Collections.Immutable.ImmutableArray other) { throw null; } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public System.Collections.Immutable.ImmutableArray.Enumerator GetEnumerator() { throw null; } public override int GetHashCode() { throw null; } public int IndexOf(T item) { throw null; } diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Minimal.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Minimal.cs index 31e093c67b7e13..a2294fcc22b326 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Minimal.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Minimal.cs @@ -306,7 +306,7 @@ public override int GetHashCode() /// /// true if the specified is equal to this instance; otherwise, false. /// - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { return obj is IImmutableArray other && this.array == other.Array; } diff --git a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs index 82d3c5b0b0c856..f4da000b1c04cc 100644 --- a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs +++ b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs @@ -18,7 +18,7 @@ public partial struct BitVector32 public static int CreateMask(int previous) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue, System.Collections.Specialized.BitVector32.Section previous) { throw null; } - public override bool Equals(object? o) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } public static string ToString(System.Collections.Specialized.BitVector32 value) { throw null; } @@ -28,7 +28,7 @@ public readonly partial struct Section public short Mask { get { throw null; } } public short Offset { get { throw null; } } public bool Equals(System.Collections.Specialized.BitVector32.Section obj) { throw null; } - public override bool Equals(object? o) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Collections.Specialized.BitVector32.Section a, System.Collections.Specialized.BitVector32.Section b) { throw null; } public static bool operator !=(System.Collections.Specialized.BitVector32.Section a, System.Collections.Specialized.BitVector32.Section b) { throw null; } diff --git a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs index 9ffd7f1d9930bc..12853ebe3622d4 100644 --- a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs +++ b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Text; +using System.Diagnostics.CodeAnalysis; namespace System.Collections.Specialized { @@ -184,7 +185,7 @@ private static Section CreateSectionHelper(short maxValue, short priorMask, shor return new Section(CreateMaskFromHighValue(maxValue), offset); } - public override bool Equals(object? o) + public override bool Equals([NotNullWhen(true)] object? o) { if (!(o is BitVector32)) { @@ -253,7 +254,7 @@ public short Offset } } - public override bool Equals(object? o) + public override bool Equals([NotNullWhen(true)] object? o) { if (o is Section) return Equals((Section)o); diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSetEqualityComparer.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSetEqualityComparer.cs index ffc0b8bafd2731..62b4dfefd1d7d5 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSetEqualityComparer.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSetEqualityComparer.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.Collections.Generic { /// @@ -47,7 +49,7 @@ public int GetHashCode(SortedSet obj) } // Equals method for the comparer itself. - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { SortedSetEqualityComparer? comparer = obj as SortedSetEqualityComparer; return comparer != null && _comparer == comparer._comparer; From 3c9bf09c0cb211e2eaa7399688d15affdee14c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Mon, 24 May 2021 11:29:15 +0200 Subject: [PATCH 073/115] Reflection-annotate obscure API (#53081) I missed the extra `Activator` in Activator.RuntimeType.cs (the rest are in Activator.cs). This was flagged on the NativeAOT side. Also missed the APIs on `ModuleHandle` that I found by accident just now. --- .../src/System/Reflection/CustomAttribute.cs | 2 ++ .../src/System/RuntimeHandles.cs | 9 +++++++++ .../src/System/RuntimeType.CoreCLR.cs | 5 +++++ .../src/System/Activator.RuntimeType.cs | 5 ++++- src/libraries/System.Runtime/ref/System.Runtime.cs | 14 +++++++++++++- .../src/System/ModuleHandle.cs | 9 +++++++++ 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs index 5f4aca74b99a5e..1b825f0dc952f5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs @@ -300,6 +300,8 @@ protected CustomAttributeData() Justification = "Property setters and fields which are accessed by any attribute instantiation which is present in the code linker has analyzed." + "As such enumerating all fields and properties may return different results after trimming" + "but all those which are needed to actually have data will be there.")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "We're getting a MethodBase of a constructor that we found in the metadata. The attribute constructor won't be trimmed.")] private CustomAttributeData(RuntimeModule scope, MetadataToken caCtorToken, in ConstArray blob) { m_scope = scope; diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 1e32455cf282cf..75aff556de7c34 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -1305,8 +1305,11 @@ private static void ValidateModulePointer(RuntimeModule module) } // SQL-CLR LKG9 Compiler dependency + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeTypeHandle GetRuntimeTypeHandleFromMetadataToken(int typeToken) { return ResolveTypeHandle(typeToken); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeTypeHandle ResolveTypeHandle(int typeToken) => ResolveTypeHandle(typeToken, null, null); + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeTypeHandle ResolveTypeHandle(int typeToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext) { RuntimeModule module = GetRuntimeModule(); @@ -1359,8 +1362,11 @@ private static extern void ResolveType(QCallModule module, ObjectHandleOnStack type); // SQL-CLR LKG9 Compiler dependency + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeMethodHandle GetRuntimeMethodHandleFromMetadataToken(int methodToken) { return ResolveMethodHandle(methodToken); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeMethodHandle ResolveMethodHandle(int methodToken) => ResolveMethodHandle(methodToken, null, null); + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeMethodHandle ResolveMethodHandle(int methodToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext) { RuntimeModule module = GetRuntimeModule(); @@ -1407,8 +1413,11 @@ private static extern RuntimeMethodHandleInternal ResolveMethod(QCallModule modu int methodInstCount); // SQL-CLR LKG9 Compiler dependency + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeFieldHandle GetRuntimeFieldHandleFromMetadataToken(int fieldToken) { return ResolveFieldHandle(fieldToken); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeFieldHandle ResolveFieldHandle(int fieldToken) => ResolveFieldHandle(fieldToken, null, null); + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext) { RuntimeModule module = GetRuntimeModule(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 0ff21c0467ab70..1e2ece2cde5c8d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -1089,6 +1089,10 @@ private RuntimeType[] PopulateInterfaces(Filter filter) return list.ToArray(); } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "Calls to ResolveTypeHandle technically require all types to be kept " + + "But this is not a public API to enumerate reflection items, all the public APIs which do that " + + "should be annotated accordingly.")] private RuntimeType[] PopulateNestedClasses(Filter filter) { RuntimeType declaringType = ReflectedType; @@ -1733,6 +1737,7 @@ internal FieldInfo GetField(RuntimeFieldHandleInternal field) typeName, throwOnError, ignoreCase, ref stackMark); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] internal static MethodBase? GetMethodBase(RuntimeModule scope, int typeMetadataToken) { return GetMethodBase(new ModuleHandle(scope).ResolveMethodHandle(typeMetadataToken).GetMethodInfo()); diff --git a/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs index 28b279cd044a52..2ccdc5c741dbf1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs @@ -16,7 +16,7 @@ public static partial class Activator // Note: CreateInstance returns null for Nullable, e.g. CreateInstance(typeof(int?)) returns null. // - public static object? CreateInstance(Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) + public static object? CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicConstructors)] Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { if (type is null) throw new ArgumentNullException(nameof(type)); @@ -39,6 +39,7 @@ public static partial class Activator } [System.Security.DynamicSecurityMethod] + [RequiresUnreferencedCode("Type and its constructor could be removed")] public static ObjectHandle? CreateInstance(string assemblyName, string typeName) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -54,6 +55,7 @@ public static partial class Activator } [System.Security.DynamicSecurityMethod] + [RequiresUnreferencedCode("Type and its constructor could be removed")] public static ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -69,6 +71,7 @@ public static partial class Activator } [System.Security.DynamicSecurityMethod] + [RequiresUnreferencedCode("Type and its constructor could be removed")] public static ObjectHandle? CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 18a82ab2923412..00af59667479c5 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -68,15 +68,18 @@ public AccessViolationException(string? message, System.Exception? innerExceptio public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); public static partial class Activator { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Type and its constructor could be removed")] public static System.Runtime.Remoting.ObjectHandle? CreateInstance(string assemblyName, string typeName) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Type and its constructor could be removed")] public static System.Runtime.Remoting.ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Type and its constructor could be removed")] public static System.Runtime.Remoting.ObjectHandle? CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes) { throw null; } public static object? CreateInstance([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type type) { throw null; } public static object? CreateInstance([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type, bool nonPublic) { throw null; } public static object? CreateInstance([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type, params object?[]? args) { throw null; } public static object? CreateInstance([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type, object?[]? args, object?[]? activationAttributes) { throw null; } public static object? CreateInstance([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture) { throw null; } - public static object? CreateInstance(System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { throw null; } + public static object? CreateInstance([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Type and its constructor could be removed")] public static System.Runtime.Remoting.ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Type and its constructor could be removed")] @@ -3015,16 +3018,25 @@ public partial struct ModuleHandle public bool Equals(System.ModuleHandle handle) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeFieldHandle GetRuntimeFieldHandleFromMetadataToken(int fieldToken) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeMethodHandle GetRuntimeMethodHandleFromMetadataToken(int methodToken) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeTypeHandle GetRuntimeTypeHandleFromMetadataToken(int typeToken) { throw null; } public static bool operator ==(System.ModuleHandle left, System.ModuleHandle right) { throw null; } public static bool operator !=(System.ModuleHandle left, System.ModuleHandle right) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeFieldHandle ResolveFieldHandle(int fieldToken) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeFieldHandle ResolveFieldHandle(int fieldToken, System.RuntimeTypeHandle[]? typeInstantiationContext, System.RuntimeTypeHandle[]? methodInstantiationContext) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeMethodHandle ResolveMethodHandle(int methodToken) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeMethodHandle ResolveMethodHandle(int methodToken, System.RuntimeTypeHandle[]? typeInstantiationContext, System.RuntimeTypeHandle[]? methodInstantiationContext) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeTypeHandle ResolveTypeHandle(int typeToken) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")] public System.RuntimeTypeHandle ResolveTypeHandle(int typeToken, System.RuntimeTypeHandle[]? typeInstantiationContext, System.RuntimeTypeHandle[]? methodInstantiationContext) { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.Method)] diff --git a/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs b/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs index 3b953d8648b6be..757cab26d6ebac 100644 --- a/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs @@ -35,16 +35,19 @@ public int MDStreamVersion } } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeFieldHandle ResolveFieldHandle(int fieldToken) { return ResolveFieldHandle(fieldToken, null, null); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeMethodHandle ResolveMethodHandle(int methodToken) { return ResolveMethodHandle(methodToken, null, null); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeTypeHandle ResolveTypeHandle(int typeToken) { return ResolveTypeHandle(typeToken, null, null); @@ -61,6 +64,7 @@ public RuntimeTypeHandle ResolveTypeHandle(int typeToken) return res; } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeTypeHandle ResolveTypeHandle(int typeToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext) { ResolveTokenError error; @@ -73,6 +77,7 @@ public RuntimeTypeHandle ResolveTypeHandle(int typeToken, RuntimeTypeHandle[]? t return new RuntimeTypeHandle(res); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeMethodHandle ResolveMethodHandle(int methodToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext) { ResolveTokenError error; @@ -85,6 +90,7 @@ public RuntimeMethodHandle ResolveMethodHandle(int methodToken, RuntimeTypeHandl return new RuntimeMethodHandle(res); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext) { ResolveTokenError error; @@ -98,16 +104,19 @@ public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[] return new RuntimeFieldHandle(res); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeFieldHandle GetRuntimeFieldHandleFromMetadataToken(int fieldToken) { return ResolveFieldHandle(fieldToken); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeMethodHandle GetRuntimeMethodHandleFromMetadataToken(int methodToken) { return ResolveMethodHandle(methodToken); } + [RequiresUnreferencedCode("Trimming changes metadata tokens")] public RuntimeTypeHandle GetRuntimeTypeHandleFromMetadataToken(int typeToken) { return ResolveTypeHandle(typeToken); From 323ab5b0379b3fe6405787b89a045d3fe72a3e18 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 24 May 2021 11:45:33 +0200 Subject: [PATCH 074/115] DbgTransportSession: delete message copy when not queued (#50550) --- .../debug/shared/dbgtransportsession.cpp | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/coreclr/debug/shared/dbgtransportsession.cpp b/src/coreclr/debug/shared/dbgtransportsession.cpp index d179288249d431..85fb7901b01c1a 100644 --- a/src/coreclr/debug/shared/dbgtransportsession.cpp +++ b/src/coreclr/debug/shared/dbgtransportsession.cpp @@ -628,6 +628,13 @@ HRESULT DbgTransportSession::SendMessage(Message *pMessage, bool fWaitsForReply) // queue). pMessage->m_sHeader.m_dwLastSeenId = m_dwLastMessageIdSeen; + // Check the session state. + if (m_eState == SS_Closed) + { + // SS_Closed is bad news, we'll never recover from that so error the send immediately. + return E_ABORT; + } + // If the caller isn't waiting around for a reply we must make a copy of the message to place on the // send queue. pMessage->m_pOrigMessage = pMessage; @@ -668,16 +675,14 @@ HRESULT DbgTransportSession::SendMessage(Message *pMessage, bool fWaitsForReply) pMessage = pMessageCopy; } - // Check the session state. - if (m_eState == SS_Closed) + // If the state is SS_Open we can send the message now. + if (m_eState == SS_Open) { - // SS_Closed is bad news, we'll never recover from that so error the send immediately. - if (pMessageCopy) - delete pMessageCopy; - if (pDataBlockCopy) - delete [] pDataBlockCopy; - - return E_ABORT; + // Send the message header block followed by the data block if it's provided. Any network error will + // be reported internally by SendBlock and result in a transition to the SS_Resync_NC state (and an + // eventual resend of the data). + if (SendBlock((PBYTE)&pMessage->m_sHeader, sizeof(MessageHeader)) && pMessage->m_pbDataBlock) + SendBlock(pMessage->m_pbDataBlock, pMessage->m_cbDataBlock); } // Don't queue session management messages. We always recreate these if we need to re-send them. @@ -700,15 +705,12 @@ HRESULT DbgTransportSession::SendMessage(Message *pMessage, bool fWaitsForReply) pMessage->m_pNext = NULL; } } - - // If the state is SS_Open we can send the message now. - if (m_eState == SS_Open) + else { - // Send the message header block followed by the data block if it's provided. Any network error will - // be reported internally by SendBlock and result in a transition to the SS_Resync_NC state (and an - // eventual resend of the data). - if (SendBlock((PBYTE)&pMessage->m_sHeader, sizeof(MessageHeader)) && pMessage->m_pbDataBlock) - SendBlock(pMessage->m_pbDataBlock, pMessage->m_cbDataBlock); + if (pMessageCopy) + delete pMessageCopy; + if (pDataBlockCopy) + delete [] pDataBlockCopy; } // If the state wasn't open there's nothing more to be done. The state will eventually transition to From 76f5ace2b6d46750d4a405fcd7202c3ea0b9d365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 24 May 2021 15:31:23 +0200 Subject: [PATCH 075/115] Disabled failing HTTP/3 tests. (#53092) * Disabled failing HTTP/3 tests. * The test disabling move to code for abstract bases. --- .../System/Net/Http/HttpClientHandlerTest.cs | 6 ++++++ .../HttpClientHandlerTest.Finalization.cs | 6 ++++++ .../HttpClientHandlerTest.Http3.cs | 2 +- .../FunctionalTests/SocketsHttpHandlerTest.cs | 15 +++++++++------ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index ac49da68e4e6bd..2d49eded82fa52 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -895,6 +895,12 @@ public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(boo return; } + if (UseVersion == HttpVersion30 && (chunked is null || chunked is false)) + { + // [ActiveIssue("https://github.com/dotnet/runtime/issues/53087")] + return; + } + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs index a593fb066bc650..ac1ba7ebee4ed7 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs @@ -27,6 +27,12 @@ private static Task GetAndDropResponse(HttpClient client, Uri url) [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] public async Task IncompleteResponseStream_ResponseDropped_CancelsRequestToServer() { + if (UseVersion == HttpVersion30) + { + // [ActiveIssue("https://github.com/dotnet/runtime/issues/53089")] + return; + } + using (HttpClient client = CreateHttpClient()) { bool stopGCs = false; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs index 5efbfcfcd0f6d1..0732797672f82b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -114,8 +114,8 @@ public async Task SendMoreThanStreamLimitRequests_Succeeds(int streamLimit) await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); } - [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/53090")] public async Task ReservedFrameType_Throws() { const int ReservedHttp2PriorityFrameId = 0x2; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index 2cd7cf7da781a7..cbae2a53263aa7 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -3099,7 +3099,8 @@ public SocketsHttpHandlerTest_HttpClientHandlerTest_Http3_Mock(ITestOutputHelper protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } -#if false // TODO: Many Cookie tests are failing for HTTP3. + // TODO: Many Cookie tests are failing for HTTP3. + [ActiveIssue("https://github.com/dotnet/runtime/issues/53093")] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] public sealed class SocketsHttpHandlerTest_Cookies_Http3_MsQuic : HttpClientHandlerTest_Cookies { @@ -3108,13 +3109,13 @@ public SocketsHttpHandlerTest_Cookies_Http3_MsQuic(ITestOutputHelper output) : b protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } + [ActiveIssue("https://github.com/dotnet/runtime/issues/53093")] public sealed class SocketsHttpHandlerTest_Cookies_Http3_Mock : HttpClientHandlerTest_Cookies { public SocketsHttpHandlerTest_Cookies_Http3_Mock(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } -#endif [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3_MsQuic : HttpClientHandlerTest_Headers @@ -3131,7 +3132,8 @@ public SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3_Mock(ITestOutp protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } -#if false // TODO: Many cancellation tests are failing for HTTP3. + // TODO: Many cancellation tests are failing for HTTP3. + [ActiveIssue("https://github.com/dotnet/runtime/issues/53093")] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] public sealed class SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_MsQuic : HttpClientHandler_Cancellation_Test { @@ -3140,15 +3142,16 @@ public SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_MsQuic(ITest protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } + [ActiveIssue("https://github.com/dotnet/runtime/issues/53093")] public sealed class SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_Mock : HttpClientHandler_Cancellation_Test { public SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_Mock(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } -#endif -#if false // TODO: Many AltSvc tests are failing for HTTP3. + // TODO: Many AltSvc tests are failing for HTTP3. + [ActiveIssue("https://github.com/dotnet/runtime/issues/53093")] [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] public sealed class SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_MsQuic : HttpClientHandler_AltSvc_Test { @@ -3157,13 +3160,13 @@ public SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_MsQuic(ITestOutput protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } + [ActiveIssue("https://github.com/dotnet/runtime/issues/53093")] public sealed class SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_Mock : HttpClientHandler_AltSvc_Test { public SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_Mock(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } -#endif [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] public sealed class SocketsHttpHandler_HttpClientHandler_Finalization_Http3_MsQuic : HttpClientHandler_Finalization_Test From aa0f4124b00275237713a6eb67a1218d4c8b908d Mon Sep 17 00:00:00 2001 From: Jan Jahoda Date: Mon, 24 May 2021 15:54:45 +0200 Subject: [PATCH 076/115] Change enterprise test password (#53094) * Change password * Change another occurence --- .../EnterpriseTestConfiguration.cs | 7 ++++--- .../setup/apacheweb/setup-digest.sh | 2 +- .../EnterpriseTests/setup/apacheweb/setup-pdc.sh | 4 ++-- .../Net/EnterpriseTests/setup/kdc/setup-kdc.sh | 16 ++++++++-------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs b/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs index 1b8eca671e8e5c..e6a9cef30777bd 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/EnterpriseTestConfiguration.cs @@ -12,8 +12,9 @@ public static class EnterpriseTestConfiguration public const string DigestAuthWebServer = "http://apacheweb.linux.contoso.com/auth/digest/"; public static bool Enabled => !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_RUNTIME_ENTERPRISETESTS_ENABLED")); - public static NetworkCredential ValidNetworkCredentials => new NetworkCredential("user1", "Password20"); - public static NetworkCredential ValidDomainNetworkCredentials => new NetworkCredential("user1", "Password20", "LINUX" ); - public static NetworkCredential InvalidNetworkCredentials => new NetworkCredential("user1", "passwordxx"); + // Folowing credentials are used only in docker scenario, it is not leaking any secrets. + public static NetworkCredential ValidNetworkCredentials => new NetworkCredential("user1", "PLACEHOLDERcorrect20"); + public static NetworkCredential ValidDomainNetworkCredentials => new NetworkCredential("user1", "PLACEHOLDERcorrect20", "LINUX" ); + public static NetworkCredential InvalidNetworkCredentials => new NetworkCredential("user1", "PLACEHOLDERwong"); } } diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-digest.sh b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-digest.sh index 5ed39dafe5d852..ef3a9c610ee068 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-digest.sh +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-digest.sh @@ -1,4 +1,4 @@ #!/bin/bash echo -n 'user1:Digest Login:' > /setup/digest_pw -echo -n 'user1:Digest Login:Password20' | md5sum | cut -d ' ' -f 1 >> /setup/digest_pw +echo -n 'user1:Digest Login:PLACEHOLDERcorrect20' | md5sum | cut -d ' ' -f 1 >> /setup/digest_pw diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-pdc.sh b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-pdc.sh index d0690bbadc2436..871e8da79e451b 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-pdc.sh +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/apacheweb/setup-pdc.sh @@ -2,12 +2,12 @@ rm -f /etc/samba/smb.conf # Configure domain and start daemons -samba-tool domain provision --use-rfc2307 --domain=linux --adminpass=password20. --realm=LINUX.CONTOSO.COM --server-role=dc +samba-tool domain provision --use-rfc2307 --domain=linux --adminpass=PLACEHOLDERadmin. --realm=LINUX.CONTOSO.COM --server-role=dc /etc/init.d/samba-ad-dc start # make sure Apache can connect usermod -a -G winbindd_priv daemon # Add user for testing -samba-tool user create user1 Password20 +samba-tool user create user1 PLACEHOLDERcorrect20 diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/kdc/setup-kdc.sh b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/kdc/setup-kdc.sh index 0e0f9be3d2c52a..130f88a9d6aea8 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/kdc/setup-kdc.sh +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/kdc/setup-kdc.sh @@ -9,21 +9,21 @@ touch /var/log/kerberos/kadmin.log touch /var/log/kerberos/krb5lib.log # Create Kerberos database -kdb5_util create -r LINUX.CONTOSO.COM -P password -s +kdb5_util create -r LINUX.CONTOSO.COM -P PLACEHOLDERadmin. -s # Start KDC service krb5kdc # Add users -kadmin.local -q "add_principal -pw Password20 root/admin@LINUX.CONTOSO.COM" -kadmin.local -q "add_principal -pw Password20 user1@LINUX.CONTOSO.COM" +kadmin.local -q "add_principal -pw PLACEHOLDERcorrect20 root/admin@LINUX.CONTOSO.COM" +kadmin.local -q "add_principal -pw PLACEHOLDERcorrect20 user1@LINUX.CONTOSO.COM" # Add SPNs for services -kadmin.local -q "add_principal -pw password HTTP/apacheweb.linux.contoso.com" -kadmin.local -q "add_principal -pw password HTTP/altweb.linux.contoso.com:8080" -kadmin.local -q "add_principal -pw password HOST/linuxclient.linux.contoso.com" -kadmin.local -q "add_principal -pw password HOST/localhost" -kadmin.local -q "add_principal -pw password NEWSERVICE/localhost" +kadmin.local -q "add_principal -pw PLACEHOLDERadmin. HTTP/apacheweb.linux.contoso.com" +kadmin.local -q "add_principal -pw PLACEHOLDERadmin. HTTP/altweb.linux.contoso.com:8080" +kadmin.local -q "add_principal -pw PLACEHOLDERadmin. HOST/linuxclient.linux.contoso.com" +kadmin.local -q "add_principal -pw PLACEHOLDERadmin. HOST/localhost" +kadmin.local -q "add_principal -pw PLACEHOLDERadmin. NEWSERVICE/localhost" # Create keytab files for other machines kadmin.local ktadd -k /SHARED/apacheweb.keytab -norandkey -glob "HTTP/*web*" From 599d0cf944f3585b566cf9e614e7d2e8939b5761 Mon Sep 17 00:00:00 2001 From: Gleb Balykov Date: Mon, 24 May 2021 18:01:03 +0300 Subject: [PATCH 077/115] Set NumProc on tizen (#53098) --- eng/native/build-commons.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 9bb323c87f9273..e07b5e0048cf14 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -284,6 +284,8 @@ elif [[ "$platform" == "Darwin" ]]; then else if command -v nproc > /dev/null 2>&1; then __NumProc=$(nproc --all) + elif (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then + __NumProc=$(getconf _NPROCESSORS_ONLN) else __NumProc=1 fi From 319c02533ef55be3a53f938c53203d546cdbc7f0 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 24 May 2021 12:04:53 -0400 Subject: [PATCH 078/115] Implement Get*PublicKey methods on S.S.C.X509Certificates.PublicKey --- ....Security.Cryptography.X509Certificates.cs | 7 ++ .../X509Certificates/PublicKey.cs | 117 ++++++++++++++++++ .../tests/PublicKeyTests.cs | 109 +++++++++++++++- 3 files changed, 232 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs index 4fe04afb5d1b45..c8619ed4408bc1 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/ref/System.Security.Cryptography.X509Certificates.cs @@ -68,6 +68,13 @@ public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptogra public System.Security.Cryptography.Oid Oid { get { throw null; } } public static System.Security.Cryptography.X509Certificates.PublicKey CreateFromSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } public byte[] ExportSubjectPublicKeyInfo() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + public System.Security.Cryptography.DSA? GetDSAPublicKey() { throw null; } + public System.Security.Cryptography.ECDiffieHellman? GetECDiffieHellmanPublicKey() { throw null; } + public System.Security.Cryptography.ECDsa? GetECDsaPublicKey() { throw null; } + public System.Security.Cryptography.RSA? GetRSAPublicKey() { throw null; } public bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) { throw null; } } public static partial class RSACertificateExtensions diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs index 3b1623bf6faa75..a641fe9f0c435d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Formats.Asn1; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Security.Cryptography.Asn1; using Internal.Cryptography; @@ -140,6 +141,122 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan source return new PublicKey(localOid, localParameters, localKeyValue); } + /// + /// Gets the public key, or if the key is not an RSA key. + /// + /// + /// The public key, or if the key is not an RSA key. + /// + /// + /// The key contents are corrupt or could not be read successfully. + /// + public RSA? GetRSAPublicKey() + { + if (_oid.Value != Oids.Rsa) + return null; + + RSA rsa = RSA.Create(); + + try + { + rsa.ImportSubjectPublicKeyInfo(ExportSubjectPublicKeyInfo(), out _); + return rsa; + } + catch + { + rsa.Dispose(); + throw; + } + } + + /// + /// Gets the public key, or if the key is not an DSA key. + /// + /// + /// The public key, or if the key is not an DSA key. + /// + /// + /// The key contents are corrupt or could not be read successfully. + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] + public DSA? GetDSAPublicKey() + { + if (_oid.Value != Oids.Dsa) + return null; + + DSA dsa = DSA.Create(); + + try + { + dsa.ImportSubjectPublicKeyInfo(ExportSubjectPublicKeyInfo(), out _); + return dsa; + } + catch + { + dsa.Dispose(); + throw; + } + } + + /// + /// Gets the public key, or if the key is not an ECDsa key. + /// + /// + /// The public key, or if the key is not an ECDsa key. + /// + /// + /// The key contents are corrupt or could not be read successfully. + /// + public ECDsa? GetECDsaPublicKey() + { + if (_oid.Value != Oids.EcPublicKey) + return null; + + ECDsa ecdsa = ECDsa.Create(); + + try + { + ecdsa.ImportSubjectPublicKeyInfo(ExportSubjectPublicKeyInfo(), out _); + return ecdsa; + } + catch + { + ecdsa.Dispose(); + throw; + } + } + + /// + /// Gets the public key, or + /// if the key is not an ECDiffieHellman key. + /// + /// + /// The public key, or if the key is not an ECDiffieHellman key. + /// + /// + /// The key contents are corrupt or could not be read successfully. + /// + public ECDiffieHellman? GetECDiffieHellmanPublicKey() + { + if (_oid.Value != Oids.EcPublicKey) + return null; + + ECDiffieHellman ecdh = ECDiffieHellman.Create(); + + try + { + ecdh.ImportSubjectPublicKeyInfo(ExportSubjectPublicKeyInfo(), out _); + return ecdh; + } + catch + { + ecdh.Dispose(); + throw; + } + } + private AsnWriter EncodeSubjectPublicKeyInfo() { SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PublicKeyTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PublicKeyTests.cs index 0f19b3bd356101..b4a4487a1ce5fe 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PublicKeyTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PublicKeyTests.cs @@ -490,7 +490,7 @@ public static void TestECDsaPublicKey_BrainpoolP160r1_ValidatesSignature(byte[] Assert.Equal("1.2.840.10045.2.1", cert.PublicKey.Oid.Value); bool isSignatureValid = publicKey.VerifyData(helloBytes, existingSignature, HashAlgorithmName.SHA256); - + if (!isSignatureValid) { Assert.True(PlatformDetection.IsAndroid, "signature invalid on Android only"); @@ -823,6 +823,113 @@ public static void CreateFromSubjectPublicKeyInfo_AnyAlgorithm() Assert.Equal(spki.Length, read); } + [Fact] + public static void GetPublicKey_NullForDifferentAlgorithm() + { + byte[] spki = TestData.GostR3410SubjectPublicKeyInfo; + PublicKey key = PublicKey.CreateFromSubjectPublicKeyInfo(spki, out _); + + Assert.Null(key.GetRSAPublicKey()); + Assert.Null(key.GetECDsaPublicKey()); + Assert.Null(key.GetECDiffieHellmanPublicKey()); + } + + [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] + public static void GetDSAPublicKey_NullForDifferentAlgorithm() + { + byte[] spki = TestData.GostR3410SubjectPublicKeyInfo; + PublicKey key = PublicKey.CreateFromSubjectPublicKeyInfo(spki, out _); + + Assert.Null(key.GetDSAPublicKey()); + } + + [Fact] + public static void GetRSAPublicKey_ReturnsRsaKey() + { + PublicKey key = GetTestRsaKey(); + + using (RSA rsa = key.GetRSAPublicKey()) + { + Assert.NotNull(rsa); + Assert.Equal(rsa.ExportSubjectPublicKeyInfo(), key.ExportSubjectPublicKeyInfo()); + } + } + + [Fact] + public static void GetRSAPublicKey_ThrowsForCorruptKey() + { + AsnEncodedData badData = new AsnEncodedData(new byte[] { 1, 2, 3, 4 }); + PublicKey key = new PublicKey(GetTestRsaKey().Oid, badData, badData); + + Assert.ThrowsAny(() => key.GetRSAPublicKey()); + } + + [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] + public static void GetDSAPublicKey_ReturnsDsaKey() + { + PublicKey key = GetTestDsaKey(); + + using (DSA dsa = key.GetDSAPublicKey()) + { + Assert.NotNull(dsa); + Assert.Equal(dsa.ExportSubjectPublicKeyInfo(), key.ExportSubjectPublicKeyInfo()); + } + } + + [Fact] + [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")] + public static void GetDSAPublicKey_ThrowsForCorruptKey() + { + AsnEncodedData badData = new AsnEncodedData(new byte[] { 1, 2, 3, 4 }); + PublicKey key = new PublicKey(GetTestDsaKey().Oid, badData, badData); + + Assert.ThrowsAny(() => key.GetDSAPublicKey()); + } + + [Fact] + public static void GetECDsaPublicKey_ReturnsECDsaKey() + { + PublicKey key = GetTestECDsaKey(); + + using (ECDsa ecdsa = key.GetECDsaPublicKey()) + { + Assert.NotNull(ecdsa); + Assert.Equal(ecdsa.ExportSubjectPublicKeyInfo(), key.ExportSubjectPublicKeyInfo()); + } + } + + [Fact] + public static void GetECDsaPublicKey_ThrowsForCorruptKey() + { + AsnEncodedData badData = new AsnEncodedData(new byte[] { 1, 2, 3, 4 }); + PublicKey key = new PublicKey(GetTestECDsaKey().Oid, badData, badData); + + Assert.ThrowsAny(() => key.GetECDsaPublicKey()); + } + + [Fact] + public static void GetECDiffieHellmanPublicKey_ReturnsECDHKey() + { + PublicKey key = GetTestECDHKey(); + + using (ECDiffieHellman ecdh = key.GetECDiffieHellmanPublicKey()) + { + Assert.NotNull(ecdh); + Assert.Equal(ecdh.ExportSubjectPublicKeyInfo(), key.ExportSubjectPublicKeyInfo()); + } + } + + [Fact] + public static void GetECDiffieHellmanPublicKey_ThrowsForCorruptKey() + { + AsnEncodedData badData = new AsnEncodedData(new byte[] { 1, 2, 3, 4 }); + PublicKey key = new PublicKey(GetTestECDHKey().Oid, badData, badData); + + Assert.ThrowsAny(() => key.GetECDiffieHellmanPublicKey()); + } + private static void TestKey_ECDsaCng(byte[] certBytes, TestData.ECDsaCngKeyValues expected) { using (X509Certificate2 cert = new X509Certificate2(certBytes)) From e3fc297ae89b5a406a537c0b7d85a693777ca3c0 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Mon, 24 May 2021 18:06:25 +0200 Subject: [PATCH 079/115] install development SSL certificate on Helix agent before xharness run (#53180) --- src/libraries/sendtohelixhelp.proj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 6eb9d125c75c33..27d7f89f521c44 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -105,6 +105,9 @@ + + + From 3b6baedde834ece3b7e8c0fc01dff55830ae1143 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 24 May 2021 09:32:24 -0700 Subject: [PATCH 080/115] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20210523.4 (#53170) optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.21271.2 -> To Version 1.0.0-prerelease.21273.4 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 61fa9c05f4f470..1a2792581302e8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -190,21 +190,21 @@ https://github.com/dotnet/arcade 50f5645789f9119c906755cb1d2549acdeb0d0b7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 018b25068e2051c8b03217069d03d7f6f15e44fd + f2f7434eccc2437b8e38ea803814914ea9e115d5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 018b25068e2051c8b03217069d03d7f6f15e44fd + f2f7434eccc2437b8e38ea803814914ea9e115d5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 018b25068e2051c8b03217069d03d7f6f15e44fd + f2f7434eccc2437b8e38ea803814914ea9e115d5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 018b25068e2051c8b03217069d03d7f6f15e44fd + f2f7434eccc2437b8e38ea803814914ea9e115d5 https://github.com/dotnet/emsdk diff --git a/eng/Versions.props b/eng/Versions.props index 2ad9542b08d72c..9f33fa85db8886 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -121,10 +121,10 @@ 6.0.0-beta.21267.1 6.0.0-beta.21267.1 - 1.0.0-prerelease.21271.2 - 1.0.0-prerelease.21271.2 - 1.0.0-prerelease.21271.2 - 1.0.0-prerelease.21271.2 + 1.0.0-prerelease.21273.4 + 1.0.0-prerelease.21273.4 + 1.0.0-prerelease.21273.4 + 1.0.0-prerelease.21273.4 16.9.0-beta1.21055.5 2.0.0-beta1.20253.1 From 263223ae913e9800408dc712eadcc50c83e846b9 Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Mon, 24 May 2021 19:59:01 +0300 Subject: [PATCH 081/115] Stringify RMWStatus for the dump (#53148) * Stringify RMWStatus for the dump * Use a simpler switch-based implementation * Made the string into a description --- src/coreclr/jit/gentree.h | 25 +++++++++++++++++++++++++ src/coreclr/jit/lowerxarch.cpp | 4 ++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 856fe78747f86a..669a798d5d9870 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -5798,6 +5798,31 @@ enum RMWStatus STOREIND_RMW_INDIR_UNEQUAL // Indir to read value is not equivalent to indir that writes the value }; +#ifdef DEBUG +inline const char* RMWStatusDescription(RMWStatus status) +{ + switch (status) + { + case STOREIND_RMW_STATUS_UNKNOWN: + return "RMW status unknown"; + case STOREIND_RMW_DST_IS_OP1: + return "dst candidate is op1"; + case STOREIND_RMW_DST_IS_OP2: + return "dst candidate is op2"; + case STOREIND_RMW_UNSUPPORTED_ADDR: + return "address mode is not supported"; + case STOREIND_RMW_UNSUPPORTED_OPER: + return "oper is not supported"; + case STOREIND_RMW_UNSUPPORTED_TYPE: + return "type is not supported"; + case STOREIND_RMW_INDIR_UNEQUAL: + return "read indir is not equivalent to write indir"; + default: + unreached(); + } +} +#endif + // StoreInd is just a BinOp, with additional RMW status struct GenTreeStoreInd : public GenTreeIndir { diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 4dfce51448fa43..09cd7c02159cf9 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -5074,8 +5074,8 @@ bool Lowering::LowerRMWMemOp(GenTreeIndir* storeInd) if (!IsRMWMemOpRootedAtStoreInd(storeInd, &indirCandidate, &indirOpSource)) { - JITDUMP("Lower of StoreInd didn't mark the node as self contained for reason: %d\n", - storeInd->AsStoreInd()->GetRMWStatus()); + JITDUMP("Lower of StoreInd didn't mark the node as self contained for reason: %s\n", + RMWStatusDescription(storeInd->AsStoreInd()->GetRMWStatus())); DISPTREERANGE(BlockRange(), storeInd); return false; } From f270775d868b7261f3308c9ed4f4aee34e51abc5 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez <1175054+carlossanlop@users.noreply.github.com> Date: Mon, 24 May 2021 10:48:40 -0700 Subject: [PATCH 082/115] Fix: Avoid throwing if a symbolic link cycle to itself is detected while enumerating (#52749) * Fix: Avoid throwing on FileSystemEntry.Initialize * Add unit tests that verify cyclic symbolic links * Fix Windows-specific unit test failures * Use OperatingSystem.IsWindows() * CHange 'Assert.Equal(1, ' to 'Assert.Single(' * Rename helper method that creates self referencing symlink * Spacing * ConditionalClass for CanCreateSymbolicLinks * ConditionalClass does not work in browser/ios/android, use ConditionalFact/ConditionalTheory Co-authored-by: carlossanlop Co-authored-by: carlossanlop --- .../IO/Enumeration/FileSystemEntry.Unix.cs | 6 +- .../tests/Base/BaseSymbolicLinks.cs | 18 +++++ .../tests/Directory/SymbolicLinks.cs | 39 ++++++++++ .../tests/DirectoryInfo/SymbolicLinks.cs | 78 +++++++++++++++++++ .../tests/Enumeration/SymbolicLinksTests.cs | 65 ++++++++++++++++ .../tests/System.IO.FileSystem.Tests.csproj | 4 + 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 src/libraries/System.IO.FileSystem/tests/Base/BaseSymbolicLinks.cs create mode 100644 src/libraries/System.IO.FileSystem/tests/Directory/SymbolicLinks.cs create mode 100644 src/libraries/System.IO.FileSystem/tests/DirectoryInfo/SymbolicLinks.cs create mode 100644 src/libraries/System.IO.FileSystem/tests/Enumeration/SymbolicLinksTests.cs diff --git a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs index ccf49cdac00af8..61ee454c6b3d03 100644 --- a/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs +++ b/src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs @@ -45,7 +45,8 @@ internal static FileAttributes Initialize( if (isUnknown) { isSymlink = entry.IsSymbolicLink; - isDirectory = entry._status.IsDirectory(entry.FullPath); + // Need to fail silently in case we are enumerating + isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); } // Same idea as the directory check, just repeated for (and tweaked due to the // nature of) symlinks. @@ -53,7 +54,8 @@ internal static FileAttributes Initialize( // so we need to reflect that in our isDirectory variable. else if (isSymlink) { - isDirectory = entry._status.IsDirectory(entry.FullPath); + // Need to fail silently in case we are enumerating + isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); } entry._status.InitiallyDirectory = isDirectory; diff --git a/src/libraries/System.IO.FileSystem/tests/Base/BaseSymbolicLinks.cs b/src/libraries/System.IO.FileSystem/tests/Base/BaseSymbolicLinks.cs new file mode 100644 index 00000000000000..caa5ae9c3e11d5 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/Base/BaseSymbolicLinks.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.IO.Tests +{ + public abstract class BaseSymbolicLinks : FileSystemTest + { + protected DirectoryInfo CreateDirectoryContainingSelfReferencingSymbolicLink() + { + DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath()); + string pathToLink = Path.Join(testDirectory.FullName, GetTestFileName()); + Assert.True(MountHelper.CreateSymbolicLink(pathToLink, pathToLink, isDirectory: true)); // Create a symlink cycle + return testDirectory; + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/Directory/SymbolicLinks.cs b/src/libraries/System.IO.FileSystem/tests/Directory/SymbolicLinks.cs new file mode 100644 index 00000000000000..970c784c7f8198 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/Directory/SymbolicLinks.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.IO.Tests +{ + public class Directory_SymbolicLinks : BaseSymbolicLinks + { + [ConditionalFact(nameof(CanCreateSymbolicLinks))] + public void EnumerateDirectories_LinksWithCycles_ShouldNotThrow() + { + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + // Windows differentiates between dir symlinks and file symlinks + int expected = OperatingSystem.IsWindows() ? 1 : 0; + Assert.Equal(expected, Directory.EnumerateDirectories(testDirectory.FullName).Count()); + } + + [ConditionalFact(nameof(CanCreateSymbolicLinks))] + public void EnumerateFiles_LinksWithCycles_ShouldNotThrow() + { + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + // Windows differentiates between dir symlinks and file symlinks + int expected = OperatingSystem.IsWindows() ? 0 : 1; + Assert.Equal(expected, Directory.EnumerateFiles(testDirectory.FullName).Count()); + } + + [ConditionalFact(nameof(CanCreateSymbolicLinks))] + public void EnumerateFileSystemEntries_LinksWithCycles_ShouldNotThrow() + { + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + Assert.Single(Directory.EnumerateFileSystemEntries(testDirectory.FullName)); + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/SymbolicLinks.cs b/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/SymbolicLinks.cs new file mode 100644 index 00000000000000..5dedc0b7b45285 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/SymbolicLinks.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.IO.Tests +{ + public class DirectoryInfo_SymbolicLinks : BaseSymbolicLinks + { + [ConditionalTheory(nameof(CanCreateSymbolicLinks))] + [InlineData(false)] + [InlineData(true)] + public void EnumerateDirectories_LinksWithCycles_ThrowsTooManyLevelsOfSymbolicLinks(bool recurse) + { + var options = new EnumerationOptions() { RecurseSubdirectories = recurse }; + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + // Windows avoids accessing the cyclic symlink if we do not recurse + if (OperatingSystem.IsWindows() && !recurse) + { + testDirectory.EnumerateDirectories("*", options).Count(); + testDirectory.GetDirectories("*", options).Count(); + } + else + { + // Internally transforms the FileSystemEntry to a DirectoryInfo, which performs a disk hit on the cyclic symlink + Assert.Throws(() => testDirectory.EnumerateDirectories("*", options).Count()); + Assert.Throws(() => testDirectory.GetDirectories("*", options).Count()); + } + } + + [ConditionalTheory(nameof(CanCreateSymbolicLinks))] + [InlineData(false)] + [InlineData(true)] + public void EnumerateFiles_LinksWithCycles_ThrowsTooManyLevelsOfSymbolicLinks(bool recurse) + { + var options = new EnumerationOptions() { RecurseSubdirectories = recurse }; + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + // Windows avoids accessing the cyclic symlink if we do not recurse + if (OperatingSystem.IsWindows() && !recurse) + { + testDirectory.EnumerateFiles("*", options).Count(); + testDirectory.GetFiles("*", options).Count(); + } + else + { + // Internally transforms the FileSystemEntry to a FileInfo, which performs a disk hit on the cyclic symlink + Assert.Throws(() => testDirectory.EnumerateFiles("*", options).Count()); + Assert.Throws(() => testDirectory.GetFiles("*", options).Count()); + } + } + + [ConditionalTheory(nameof(CanCreateSymbolicLinks))] + [InlineData(false)] + [InlineData(true)] + public void EnumerateFileSystemInfos_LinksWithCycles_ThrowsTooManyLevelsOfSymbolicLinks(bool recurse) + { + var options = new EnumerationOptions() { RecurseSubdirectories = recurse }; + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + // Windows avoids accessing the cyclic symlink if we do not recurse + if (OperatingSystem.IsWindows() && !recurse) + { + testDirectory.EnumerateFileSystemInfos("*", options).Count(); + testDirectory.GetFileSystemInfos("*", options).Count(); + } + else + { + // Internally transforms the FileSystemEntry to a FileSystemInfo, which performs a disk hit on the cyclic symlink + Assert.Throws(() => testDirectory.EnumerateFileSystemInfos("*", options).Count()); + Assert.Throws(() => testDirectory.GetFileSystemInfos("*", options).Count()); + } + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/Enumeration/SymbolicLinksTests.cs b/src/libraries/System.IO.FileSystem/tests/Enumeration/SymbolicLinksTests.cs new file mode 100644 index 00000000000000..43ea97540f38b2 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/Enumeration/SymbolicLinksTests.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO.Enumeration; +using System.Linq; +using Xunit; + +namespace System.IO.Tests.Enumeration +{ + public class Enumeration_SymbolicLinksTests : BaseSymbolicLinks + { + [ConditionalFact(nameof(CanCreateSymbolicLinks))] + public void EnumerateDirectories_LinksWithCycles_ShouldNotThrow() + { + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + IEnumerable enumerable = new FileSystemEnumerable( + testDirectory.FullName, + (ref FileSystemEntry entry) => entry.ToFullPath(), + // Skipping attributes would force a disk hit which enters the cyclic symlink + new EnumerationOptions(){ AttributesToSkip = 0 }) + { + ShouldIncludePredicate = (ref FileSystemEntry entry) => entry.IsDirectory + }; + + // Windows differentiates between dir symlinks and file symlinks + int expected = OperatingSystem.IsWindows() ? 1 : 0; + Assert.Equal(expected, enumerable.Count()); + } + + [ConditionalFact(nameof(CanCreateSymbolicLinks))] + public void EnumerateFiles_LinksWithCycles_ShouldNotThrow() + { + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + IEnumerable enumerable = new FileSystemEnumerable( + testDirectory.FullName, + (ref FileSystemEntry entry) => entry.ToFullPath(), + // Skipping attributes would force a disk hit which enters the cyclic symlink + new EnumerationOptions(){ AttributesToSkip = 0 }) + { + ShouldIncludePredicate = (ref FileSystemEntry entry) => !entry.IsDirectory + }; + + // Windows differentiates between dir symlinks and file symlinks + int expected = OperatingSystem.IsWindows() ? 0 : 1; + Assert.Equal(expected, enumerable.Count()); + } + + [ConditionalFact(nameof(CanCreateSymbolicLinks))] + public void EnumerateFileSystemEntries_LinksWithCycles_ShouldNotThrow() + { + DirectoryInfo testDirectory = CreateDirectoryContainingSelfReferencingSymbolicLink(); + + IEnumerable enumerable = new FileSystemEnumerable( + testDirectory.FullName, + (ref FileSystemEntry entry) => entry.ToFullPath(), + // Skipping attributes would force a disk hit which enters the cyclic symlink + new EnumerationOptions(){ AttributesToSkip = 0 }); + + Assert.Single(enumerable); + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 651abf050e5cce..dba6172218ca0d 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -14,7 +14,10 @@ + + + @@ -47,6 +50,7 @@ + From d4b91acb793d4aff7abd9452f511290f5aa574c4 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 24 May 2021 20:11:26 +0200 Subject: [PATCH 083/115] Add runtimeconfig.json support to AppleAppBuilder, reenable affected tests (#53172) --- eng/testing/tests.mobile.targets | 49 +++++++++++-------- .../tests/Encoding/Encoding.cs | 4 -- .../Encoding/EncodingGetEncodingTests.cs | 6 --- .../tests/System.Text.Encoding.Tests.csproj | 4 +- .../tests/UTF7Encoding/UTF7EncodingEncode.cs | 2 - .../tests/UTF7Encoding/UTF7EncodingTests.cs | 13 +---- .../tests/runtimeconfig.template.json | 5 -- .../AndroidAppBuilder/Templates/monodroid.c | 2 + src/tasks/AppleAppBuilder/Templates/runtime.m | 26 ++++++++++ 9 files changed, 59 insertions(+), 52 deletions(-) delete mode 100644 src/libraries/System.Text.Encoding/tests/runtimeconfig.template.json diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 2fedf68d956005..3e5321d57ebdb4 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -14,10 +14,10 @@ false - false + false false false - true + true false false true @@ -25,11 +25,11 @@ false - false + false false false false - true + true true @@ -58,15 +58,35 @@ + + + + + $(PublishDir)$(AssemblyName).runtimeconfig.json + $(PublishDir)runtimeconfig.bin + + + + + + + + + + + + - - + @@ -76,16 +96,12 @@ x86 AndroidTestRunner.dll - $(PublishDir)$(AssemblyName).runtimeconfig.json - $(PublishDir)runtimeconfig.bin @(MonoAOTCompilerDefaultAotArguments, ';') @(MonoAOTCompilerDefaultProcessArguments, ';') - - @@ -94,13 +110,6 @@ Condition="'$(RunAOTCompilation)' == 'true'"/> - - - - adhoc - + diff --git a/src/libraries/System.Text.Encoding/tests/Encoding/Encoding.cs b/src/libraries/System.Text.Encoding/tests/Encoding/Encoding.cs index f4860b20cc314f..e7640cbea8c8b6 100644 --- a/src/libraries/System.Text.Encoding/tests/Encoding/Encoding.cs +++ b/src/libraries/System.Text.Encoding/tests/Encoding/Encoding.cs @@ -67,8 +67,6 @@ public static void GetEncodingsTest() [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json [Theory] [MemberData(nameof(Encoding_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void VerifyCodePageAttributes(int codepage, string name, string bodyName, string headerName, bool isBrowserDisplay, bool isBrowserSave, bool isMailNewsDisplay, bool isMailNewsSave, int windowsCodePage) { @@ -86,8 +84,6 @@ public static void VerifyCodePageAttributes(int codepage, string name, string bo [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json [Theory] [MemberData(nameof(Normalization_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void NormalizationTest(int codepage, bool normalized, bool normalizedC, bool normalizedD, bool normalizedKC, bool normalizedKD) { Encoding encoding = Encoding.GetEncoding(codepage); diff --git a/src/libraries/System.Text.Encoding/tests/Encoding/EncodingGetEncodingTests.cs b/src/libraries/System.Text.Encoding/tests/Encoding/EncodingGetEncodingTests.cs index 608019a68146bb..6a5fc49cf2eb88 100644 --- a/src/libraries/System.Text.Encoding/tests/Encoding/EncodingGetEncodingTests.cs +++ b/src/libraries/System.Text.Encoding/tests/Encoding/EncodingGetEncodingTests.cs @@ -90,8 +90,6 @@ public CodePageMapping(string name, int codepage) [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void TestEncodingNameAndCopdepageNumber() { foreach (var map in s_mapping) @@ -103,8 +101,6 @@ public void TestEncodingNameAndCopdepageNumber() [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void GetEncoding_EncodingName() { using (new ThreadCultureChange(CultureInfo.InvariantCulture)) @@ -125,8 +121,6 @@ public void GetEncoding_EncodingName() [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void GetEncoding_WebName() { foreach (var mapping in s_codePageToWebNameMappings) diff --git a/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj b/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj index dd0551c8c467e3..73021ff5eb92af 100644 --- a/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj +++ b/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj @@ -6,6 +6,7 @@ $(NetCoreAppCurrent) $(NoWarn),SYSLIB0001 + true @@ -85,9 +86,6 @@ - - - diff --git a/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingEncode.cs b/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingEncode.cs index c4a549786a30fa..781c8447ff1d3d 100644 --- a/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingEncode.cs +++ b/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingEncode.cs @@ -61,8 +61,6 @@ public static IEnumerable Encode_Basic_TestData() [Theory] [MemberData(nameof(Encode_Basic_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void Encode_Basic(string source, int index, int count, byte[] expected) { Encode_Advanced(true, source, index, count, expected); diff --git a/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingTests.cs b/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingTests.cs index 0cfe89e4411d7a..c8d628ceca1c73 100644 --- a/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingTests.cs +++ b/src/libraries/System.Text.Encoding/tests/UTF7Encoding/UTF7EncodingTests.cs @@ -52,10 +52,9 @@ public static IEnumerable Encodings_TestData() yield return new object[] { Encoding.UTF7 }; yield return new object[] { Encoding.GetEncoding("utf-7") }; } + [Theory] [MemberData(nameof(Encodings_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void WebName(UTF7Encoding encoding) { Assert.Equal("utf-7", encoding.WebName); @@ -63,8 +62,6 @@ public void WebName(UTF7Encoding encoding) [Theory] [MemberData(nameof(Encodings_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void CodePage(UTF7Encoding encoding) { Assert.Equal(65000, encoding.CodePage); @@ -72,8 +69,6 @@ public void CodePage(UTF7Encoding encoding) [Theory] [MemberData(nameof(Encodings_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void EncodingName(UTF7Encoding encoding) { Assert.NotEmpty(encoding.EncodingName); // Unicode (UTF-7) in en-US @@ -81,8 +76,6 @@ public void EncodingName(UTF7Encoding encoding) [Theory] [MemberData(nameof(Encodings_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void IsSingleByte(UTF7Encoding encoding) { Assert.False(encoding.IsSingleByte); @@ -90,8 +83,6 @@ public void IsSingleByte(UTF7Encoding encoding) [Theory] [MemberData(nameof(Encodings_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void Clone(UTF7Encoding encoding) { UTF7Encoding clone = (UTF7Encoding)encoding.Clone(); @@ -125,8 +116,6 @@ public static IEnumerable Equals_TestData() [Theory] [MemberData(nameof(Equals_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50573", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51394", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void EqualsTest(UTF7Encoding encoding, object value, bool expected) { Assert.Equal(expected, encoding.Equals(value)); diff --git a/src/libraries/System.Text.Encoding/tests/runtimeconfig.template.json b/src/libraries/System.Text.Encoding/tests/runtimeconfig.template.json deleted file mode 100644 index f24ff824948f67..00000000000000 --- a/src/libraries/System.Text.Encoding/tests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.Text.Encoding.EnableUnsafeUTF7Encoding": true - } -} diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index d2ed75763650d2..17f6c2b3ad4ec0 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -239,6 +239,8 @@ mono_droid_runtime_init (const char* executable, int managed_argc, char* managed arg->kind = 0; arg->runtimeconfig.name.path = file_path; monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path); + } else { + free (file_path); } monovm_initialize(2, appctx_keys, appctx_values); diff --git a/src/tasks/AppleAppBuilder/Templates/runtime.m b/src/tasks/AppleAppBuilder/Templates/runtime.m index 8b8d6d181d00de..9b90f44972db37 100644 --- a/src/tasks/AppleAppBuilder/Templates/runtime.m +++ b/src/tasks/AppleAppBuilder/Templates/runtime.m @@ -26,6 +26,8 @@ #define APPLE_RUNTIME_IDENTIFIER "//%APPLE_RUNTIME_IDENTIFIER%" +#define RUNTIMECONFIG_BIN_FILE "runtimeconfig.bin" + const char * get_bundle_path (void) { @@ -205,6 +207,13 @@ //%DllMap% } +void +cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data) +{ + free (args); + free (user_data); +} + #if FORCE_INTERPRETER || FORCE_AOT || (!TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST) void mono_jit_set_aot_mode (MonoAotMode mode); void register_aot_modules (void); @@ -258,6 +267,23 @@ #endif }; + char *file_name = RUNTIMECONFIG_BIN_FILE; + int str_len = strlen (bundle) + strlen (file_name) + 2; + char *file_path = (char *)malloc (sizeof (char) * str_len); + int num_char = snprintf (file_path, str_len, "%s/%s", bundle, file_name); + struct stat buffer; + + assert (num_char > 0 && num_char < str_len); + + if (stat (file_path, &buffer) == 0) { + MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments)); + arg->kind = 0; + arg->runtimeconfig.name.path = file_path; + monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path); + } else { + free (file_path); + } + monovm_initialize (sizeof (appctx_keys) / sizeof (appctx_keys [0]), appctx_keys, appctx_values); #if FORCE_INTERPRETER From bd074cd55a18818312a52d63869e87729f9534e5 Mon Sep 17 00:00:00 2001 From: Jeff Schwartz Date: Mon, 24 May 2021 11:13:09 -0700 Subject: [PATCH 084/115] Add additional area labels that have been added recently (#53183) --- docs/area-owners.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/area-owners.md b/docs/area-owners.md index 28cd71113802cd..a8f4f5cb9da229 100644 --- a/docs/area-owners.md +++ b/docs/area-owners.md @@ -53,6 +53,7 @@ Note: Editing this file doesn't update the mapping used by the `@msftbot` issue | area-Microsoft.VisualBasic | @jaredpar | @cston @333fred | Archived component - limited churn/contributions (see [#27790](https://github.com/dotnet/runtime/issues/27790)) | | area-Microsoft.Win32 | @ericstj | @Anipik @ViktorHofer | Including System.Windows.Extensions | | area-PAL-coreclr | @mangod9 | @janvorli | | +| area-PAL-libraries | @jeffhandley | @bartonjs @GrabYourPitchforks | | | area-Performance-mono | @SamMonoRT | @SamMonoRT | | | area-R2RDump-coreclr | @mangod9 | @nattress | | | area-ReadyToRun-coreclr | @mangod9 | @nattress | | @@ -74,9 +75,14 @@ Note: Editing this file doesn't update the mapping used by the `@msftbot` issue | area-System.Data.OleDB | @ajcvickers | @ajcvickers | | | area-System.Data.SqlClient | @David-Engel | @cheenamalhotra @david-engel @karinazhou @JRahnama | Archived component - limited churn/contributions (see https://devblogs.microsoft.com/dotnet/introducing-the-new-microsoftdatasqlclient/) | | area-System.Diagnostics | @tommcdon | @tommcdon @Anipik @ViktorHofer | Sub-Areas:
  • System.Diagnostics.EventLog - @Anipik @ViktorHofer
| +| area-System.Diagnostics-coreclr | @tommcdon | @tommcdon @Anipik @ViktorHofer | Sub-Areas:
  • System.Diagnostics.EventLog - @Anipik @ViktorHofer
| +| area-System.Diagnostics-mono | @lewing | @thaystg @radical | | | area-System.Diagnostics.Activity | @tommcdon | @tarekgh | | +| area-System.Diagnostics.EventLog | @jeffhandley | @adamsitnik @carlossanlop @jozkee | | +| area-System.Diagnostics.PerformanceCounter | @jeffhandley | @adamsitnik @carlossanlop @jozkee | | | area-System.Diagnostics.Process | @jeffhandley | @adamsitnik @carlossanlop @jozkee | | | area-System.Diagnostics.Tracing | @tommcdon | @noahfalk @tommcdon @Anipik @ViktorHofer @tarekgh | Packages:
  • System.Diagnostics.DiagnosticSource
  • System.Diagnostics.PerformanceCounter - @Anipik @ViktorHofer
  • System.Diagnostics.Tracing - @Anipik @ViktorHofer
  • System.Diagnostics.TraceSource
| +| area-System.Diagnostics.TraceSource | @jeffhandley | @buyaa-n @joperezr @krwq | Consultants: @tquerec @josephisenhour | | area-System.DirectoryServices | @jeffhandley | @buyaa-n @joperezr @krwq | Consultants: @tquerec @josephisenhour | | area-System.Drawing | @ericstj | @maryamariyan @michaelgsharp @safern @tarekgh | | | area-System.Dynamic.Runtime | @jaredpar | @cston @333fred | Archived component - limited churn/contributions (see [#27790](https://github.com/dotnet/runtime/issues/27790)) | From 7134b2d1e06517ceffb94535671cf8097f7e2edf Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 24 May 2021 14:22:10 -0400 Subject: [PATCH 085/115] Fix the token included by HttpClient.HandleFailure (#53133) --- .../src/System/Net/Http/HttpClient.cs | 26 +++++++--- .../tests/FunctionalTests/HttpClientTest.cs | 47 +++++++++++++------ 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs index 5716b669c44617..b09850ec9a4b0d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs @@ -583,17 +583,31 @@ private void HandleFailure(Exception e, bool telemetryStarted, HttpResponseMessa Exception? toThrow = null; - if (e is OperationCanceledException oce && !cancellationToken.IsCancellationRequested && !pendingRequestsCts.IsCancellationRequested) + if (e is OperationCanceledException oce) { - // If this exception is for cancellation, but cancellation wasn't requested, either by the caller's token or by the pending requests source, - // the only other cause could be a timeout. Treat it as such. - e = toThrow = new TaskCanceledException(SR.Format(SR.net_http_request_timedout, _timeout.TotalSeconds), new TimeoutException(e.Message, e), oce.CancellationToken); + if (cancellationToken.IsCancellationRequested) + { + if (oce.CancellationToken != cancellationToken) + { + // We got a cancellation exception, and the caller requested cancellation, but the exception doesn't contain that token. + // Massage things so that the cancellation exception we propagate appropriately contains the caller's token (it's possible + // multiple things caused cancellation, in which case we can attribute it to the caller's token, or it's possible the + // exception contains the linked token source, in which case that token isn't meaningful to the caller). + e = toThrow = new TaskCanceledException(oce.Message, oce.InnerException, cancellationToken); + } + } + else if (!pendingRequestsCts.IsCancellationRequested) + { + // If this exception is for cancellation, but cancellation wasn't requested, either by the caller's token or by the pending requests source, + // the only other cause could be a timeout. Treat it as such. + e = toThrow = new TaskCanceledException(SR.Format(SR.net_http_request_timedout, _timeout.TotalSeconds), new TimeoutException(e.Message, e), oce.CancellationToken); + } } - else if (cts.IsCancellationRequested && e is HttpRequestException) // if cancellationToken is canceled, cts will also be canceled + else if (e is HttpRequestException && cts.IsCancellationRequested) // if cancellationToken is canceled, cts will also be canceled { // If the cancellation token source was canceled, race conditions abound, and we consider the failure to be // caused by the cancellation (e.g. WebException when reading from canceled response stream). - e = toThrow = new OperationCanceledException(cts.Token); + e = toThrow = new OperationCanceledException(cancellationToken.IsCancellationRequested ? cancellationToken : cts.Token); } if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, e); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs index 883bb8cf725834..06d3f2a5ed47d2 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs @@ -289,11 +289,18 @@ public async Task GetPutPostDeleteAsync_Canceled_Throws() cts.Cancel(); - await Assert.ThrowsAsync(() => t1); - await Assert.ThrowsAsync(() => t2); - await Assert.ThrowsAsync(() => t3); - await Assert.ThrowsAsync(() => t4); - await Assert.ThrowsAsync(() => t5); + async Task ValidateCancellationAsync(Task t) + { + TaskCanceledException tce = await Assert.ThrowsAsync(() => t); + Assert.Equal(cts.Token, tce.CancellationToken); + + } + + await ValidateCancellationAsync(t1); + await ValidateCancellationAsync(t2); + await ValidateCancellationAsync(t3); + await ValidateCancellationAsync(t4); + await ValidateCancellationAsync(t5); } } @@ -382,7 +389,9 @@ await LoopbackServer.CreateClientAndServerAsync( var cts = new CancellationTokenSource(); cts.Cancel(); - await Assert.ThrowsAsync(() => httpClient.GetStringAsync(uri, cts.Token)); + TaskCanceledException tce = await Assert.ThrowsAsync(() => httpClient.GetStringAsync(uri, cts.Token)); + Assert.Equal(cts.Token, tce.CancellationToken); + onClientFinished.Release(); }, async server => @@ -402,7 +411,8 @@ await LoopbackServer.CreateClientAndServerAsync( { using HttpClient httpClient = CreateHttpClient(); - await Assert.ThrowsAsync(() => httpClient.GetStringAsync(uri, cts.Token)); + TaskCanceledException tce = await Assert.ThrowsAsync(() => httpClient.GetStringAsync(uri, cts.Token)); + Assert.Equal(cts.Token, tce.CancellationToken); }, async server => { @@ -549,7 +559,9 @@ await LoopbackServer.CreateClientAndServerAsync( var cts = new CancellationTokenSource(); cts.Cancel(); - await Assert.ThrowsAsync(() => httpClient.GetByteArrayAsync(uri, cts.Token)); + TaskCanceledException tce = await Assert.ThrowsAsync(() => httpClient.GetByteArrayAsync(uri, cts.Token)); + Assert.Equal(cts.Token, tce.CancellationToken); + onClientFinished.Release(); }, async server => @@ -569,7 +581,8 @@ await LoopbackServer.CreateClientAndServerAsync( { using HttpClient httpClient = CreateHttpClient(); - await Assert.ThrowsAsync(() => httpClient.GetByteArrayAsync(uri, cts.Token)); + TaskCanceledException tce = await Assert.ThrowsAsync(() => httpClient.GetByteArrayAsync(uri, cts.Token)); + Assert.Equal(cts.Token, tce.CancellationToken); }, async server => { @@ -623,7 +636,9 @@ await LoopbackServer.CreateClientAndServerAsync( var cts = new CancellationTokenSource(); cts.Cancel(); - await Assert.ThrowsAsync(() => httpClient.GetStreamAsync(uri, cts.Token)); + TaskCanceledException tce = await Assert.ThrowsAsync(() => httpClient.GetStreamAsync(uri, cts.Token)); + Assert.Equal(cts.Token, tce.CancellationToken); + onClientFinished.Release(); }, async server => @@ -643,7 +658,8 @@ await LoopbackServer.CreateClientAndServerAsync( { using HttpClient httpClient = CreateHttpClient(); - await Assert.ThrowsAsync(() => httpClient.GetStreamAsync(uri, cts.Token)); + TaskCanceledException tce = await Assert.ThrowsAsync(() => httpClient.GetStreamAsync(uri, cts.Token)); + Assert.Equal(cts.Token, tce.CancellationToken); }, async server => { @@ -729,7 +745,7 @@ public async Task Timeout_CallerCanceledTokenAfterTimeout_TimeoutIsNotDetected(H cts.Cancel(); Task task = client.GetAsync(CreateFakeUri(), completionOption, token); OperationCanceledException e = await Assert.ThrowsAnyAsync(async () => await task); - Assert.Null(e.InnerException); + Assert.Equal(e.CancellationToken, token); } } @@ -746,7 +762,7 @@ public void Timeout_CallerCanceledTokenBeforeTimeout_TimeoutIsNotDetected(HttpCo Task task = client.GetAsync(CreateFakeUri(), completionOption, cts.Token); cts.Cancel(); OperationCanceledException e = Assert.ThrowsAny(() => task.GetAwaiter().GetResult()); - Assert.Null(e.InnerException); + Assert.Equal(e.CancellationToken, cts.Token); } } @@ -821,7 +837,8 @@ public async Task PatchAsync_Canceled_Throws() cts.Cancel(); - await Assert.ThrowsAsync(() => t1); + TaskCanceledException tce = await Assert.ThrowsAsync(() => t1); + Assert.Equal(cts.Token, tce.CancellationToken); } } @@ -966,6 +983,7 @@ await LoopbackServer.CreateClientAndServerAsync( }); TaskCanceledException ex = await Assert.ThrowsAsync(() => sendTask); + Assert.Equal(cts.Token, ex.CancellationToken); Assert.IsNotType(ex.InnerException); }, async server => @@ -1050,6 +1068,7 @@ await LoopbackServer.CreateClientAndServerAsync( }); TaskCanceledException ex = await Assert.ThrowsAsync(() => sendTask); + Assert.Equal(cts.Token, ex.CancellationToken); Assert.IsNotType(ex.InnerException); }, async server => From 254953ae008a44a66076d8a7ebcc4ea77b8f7b92 Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Mon, 24 May 2021 11:32:15 -0700 Subject: [PATCH 086/115] Fix another bug in the backport action (#53187) - #52938 was incomplete - see also dotnet/aspnetcore#32930 --- eng/actions/backport/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/actions/backport/index.js b/eng/actions/backport/index.js index 775c910784badb..49a2c740108813 100644 --- a/eng/actions/backport/index.js +++ b/eng/actions/backport/index.js @@ -86,7 +86,7 @@ async function run() { if (git_am_failed) { const git_am_failed_body = `@${github.context.payload.comment.user.login} backporting to ${target_branch} failed, the patch most likely resulted in conflicts:\n\n\`\`\`shell\n${git_am_output}\n\`\`\`\n\nPlease backport manually!`; - await octokit.issues.createComment({ + await octokit.rest.issues.createComment({ owner: repo_owner, repo: repo_name, issue_number: pr_number, From 47498e233ba354a2ffc4dc149ebcb1d357683c2d Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Mon, 24 May 2021 20:45:21 +0200 Subject: [PATCH 087/115] Update testing docs with x86 instructions (#48715) * Update testing docs with x86 instructions * Apply suggestions from code review Co-authored-by: Santiago Fernandez Madero * add more examples * Apply suggestions from code review Co-authored-by: Dan Moseley * Update docs/workflow/testing/libraries/testing.md Co-authored-by: Santiago Fernandez Madero Co-authored-by: Santiago Fernandez Madero Co-authored-by: Dan Moseley Co-authored-by: Eric StJohn --- docs/workflow/testing/libraries/testing.md | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/workflow/testing/libraries/testing.md b/docs/workflow/testing/libraries/testing.md index 2182a959a2f8ee..fe4d76255a7913 100644 --- a/docs/workflow/testing/libraries/testing.md +++ b/docs/workflow/testing/libraries/testing.md @@ -2,7 +2,7 @@ We use the OSS testing framework [xunit](https://github.com/xunit/xunit). -To build the tests and run them you can call the libraries build script. +To build the tests and run them you can call the libraries build script. For libraries tests to work, you must have built the coreclr or mono runtime for them to run on. **Examples** - The following shows how to build only the tests but not run them: @@ -10,11 +10,31 @@ To build the tests and run them you can call the libraries build script. build.cmd/sh -subset libs.tests ``` +- The following builds and runs all tests using clr: +``` +build.cmd/sh -subset clr+libs.tests -test +``` + +- The following builds and runs all tests using mono: +``` +build.cmd/sh -subset mono+libs.tests -test +``` + - The following builds and runs all tests in release configuration: ``` build.cmd/sh -subset libs.tests -test -c Release ``` +- The following builds clr in release, libs in debug and runs all tests: +``` +build.cmd/sh -subset clr+libs+libs.tests -test -rc Release +``` + +- The following builds mono and libs for x86 architecture and runs all tests: +``` +build.cmd/sh -subset mono+libs+libs.tests -test -arch x86 +``` + - The following example shows how to pass extra msbuild properties to ignore tests ignored in CI: ``` build.cmd/sh -subset libs.tests -test /p:WithoutCategories=IgnoreForCI @@ -41,6 +61,11 @@ It is possible to pass parameters to the underlying xunit runner via the `XUnitO dotnet build /t:Test /p:XUnitOptions="-class Test.ClassUnderTests" ``` +Which is very useful when you want to run tests as `x86` on a `x64` machine: +```cmd +dotnet build /t:Test /p:TargetArchitecture=x86 +``` + There may be multiple projects in some directories so you may need to specify the path to a specific test project to get it to build and run the tests. #### Running a single test on the command line From e323026ba15def31a9965f8cd40a0d3e5ad37060 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 24 May 2021 13:42:52 -0700 Subject: [PATCH 088/115] Fix EventSource default channel allocation (#48864) --- .../src/System/Diagnostics/Tracing/EventSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index 0492071dba4a34..919839f0d42fbb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -5486,7 +5486,7 @@ public ulong GetChannelKeyword(EventChannel channel, ulong channelKeyword = 0) if (!channelTab.TryGetValue((int)channel, out ChannelInfo? info)) { // If we were not given an explicit channel, allocate one. - if (channelKeyword != 0) + if (channelKeyword == 0) { channelKeyword = nextChannelKeywordBit; nextChannelKeywordBit >>= 1; From a723e83aa8d914ecaa942da84c234cefcfdf0235 Mon Sep 17 00:00:00 2001 From: imhameed Date: Mon, 24 May 2021 13:43:28 -0700 Subject: [PATCH 089/115] [mono] LLVM build fixes (#53139) Don't copy files from an LLVM header and library directory to `artifacts/obj/mono` if the directory was supplied as a user-specified `MonoLLVMDir` or `MonoAOTLLVMDir` property. --- src/mono/Directory.Build.props | 11 +++++++++-- src/mono/llvm/llvm-init.proj | 4 ++-- src/mono/mono.proj | 5 ----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/mono/Directory.Build.props b/src/mono/Directory.Build.props index 356a3175019ad8..fc54d02cf42315 100644 --- a/src/mono/Directory.Build.props +++ b/src/mono/Directory.Build.props @@ -47,8 +47,15 @@ $(TargetOS).$(Platform).$(Configuration) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'mono', '$(TargetOS).$(Platform).$(Configuration)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsObjDir)', 'mono', '$(PlatformConfigPathPart)')) - $([MSBuild]::NormalizeDirectory('$(MonoObjDir)', 'llvm')) - $([MSBuild]::NormalizeDirectory('$(MonoObjDir)', 'cross', 'llvm')) + true + true + true + true + true + <_MonoUseLLVMPackage Condition="'$(MonoLLVMDir)' == '' and '$(MonoEnableLLVM)' == 'true'">true + <_MonoUseAOTLLVMPackage Condition="'$(MonoAOTLLVMDir)' == '' and '$(MonoAOTEnableLLVM)' == 'true'">true + $([MSBuild]::NormalizeDirectory('$(MonoObjDir)', 'llvm')) + $([MSBuild]::NormalizeDirectory('$(MonoObjDir)', 'cross', 'llvm')) diff --git a/src/mono/llvm/llvm-init.proj b/src/mono/llvm/llvm-init.proj index 6f7477b1e5b3c1..2571f7ce2d9de2 100644 --- a/src/mono/llvm/llvm-init.proj +++ b/src/mono/llvm/llvm-init.proj @@ -39,11 +39,11 @@
- + - + diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 8989fcac775d42..fb52c1ad691c71 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -48,11 +48,6 @@ true true true - true - true - true - true - true $([MSBuild]::NormalizeDirectory('$(MonoObjDir)', 'cross')) $([MSBuild]::NormalizePath('$(MonoObjCrossDir)', 'config.h')) true From b171ea6cc91bc8aeb91a560475a8f14118dd0bc7 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Mon, 24 May 2021 17:20:10 -0400 Subject: [PATCH 090/115] Reenable extract unicode System.IO.Compression.ZipFile tests on iOS (#53176) As a result of https://github.com/dotnet/xharness/pull/605, the tests should be good to run Fixes https://github.com/dotnet/runtime/issues/52471 --- .../System.IO.Compression.ZipFile/tests/ZipFile.Extract.cs | 1 - .../tests/ZipFileExtensions.ZipArchive.Extract.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Extract.cs index b71e03f7558b21..9bbfd271d2e474 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Extract.cs @@ -34,7 +34,6 @@ public void ExtractToDirectoryNull() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52616", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void ExtractToDirectoryUnicode() { string zipFileName = zfile("unicode.zip"); diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFileExtensions.ZipArchive.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFileExtensions.ZipArchive.Extract.cs index d7b97eb9681d20..e0dfc37788d936 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/ZipFileExtensions.ZipArchive.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/tests/ZipFileExtensions.ZipArchive.Extract.cs @@ -22,7 +22,6 @@ public void ExtractToDirectoryExtension() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52616", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void ExtractToDirectoryExtension_Unicode() { using (ZipArchive archive = ZipFile.OpenRead(zfile("unicode.zip"))) From 254850203fbb08f3a65403aea89e5f9baad23535 Mon Sep 17 00:00:00 2001 From: Anirudh Agnihotry Date: Mon, 24 May 2021 14:48:17 -0700 Subject: [PATCH 091/115] Use the new Microsoft.DotNet.PackageValidation on Microsoft.Extensions* packages. (#52741) * enabling the new validation on extensions packages * use most recent version namespace fixes * use the new pacakge version with the path fix * editing the comments --- global.json | 1 + src/libraries/Directory.Build.props | 2 ++ src/libraries/Directory.Build.targets | 7 +++++++ ...tensions.DependencyInjection.Specification.Tests.csproj | 1 + .../src/Microsoft.Extensions.DependencyInjection.csproj | 2 ++ .../src/Microsoft.Extensions.DependencyModel.csproj | 2 ++ ...Microsoft.Extensions.HostFactoryResolver.Sources.csproj | 2 ++ 7 files changed, 17 insertions(+) diff --git a/global.json b/global.json index 1f4b469162c63b..28faaff1826b4a 100644 --- a/global.json +++ b/global.json @@ -13,6 +13,7 @@ }, "msbuild-sdks": { "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21271.3", + "Microsoft.DotNet.PackageValidation" : "1.0.0-preview.6.21274.7", "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21271.3", "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21271.3", "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21271.3", diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index 44936579a60838..e9cd76e9b19592 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -73,6 +73,8 @@ + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'ref')) diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index cb27773a52aae9..f166ddc4aadef0 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -146,6 +146,13 @@ + + + + $([MSBuild]::Subtract($(MajorVersion), 1)).0.0 + true + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj index 2364f7bbfa0827..8a2a6e74cc7bab 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj @@ -5,6 +5,7 @@ true false false + 3.1.15 Suite of xUnit.net tests to check for container compatibility with Microsoft.Extensions.DependencyInjection. diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj index 59a299936d8fd1..9884fdceeaecb1 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj @@ -5,6 +5,8 @@ False Annotations + + $(NoWarn);CP0001 Default implementation of dependency injection for Microsoft.Extensions.DependencyInjection. diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj index 81b60b71352053..b7ccc5b0db1ae3 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/Microsoft.Extensions.DependencyModel.csproj @@ -2,6 +2,8 @@ netstandard2.0;net461 true + + $(NoWarn);PKV006 Abstractions for reading `.deps` files. Commonly Used Types: diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj index 747450d3131898..8d18a805d2d8e8 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj @@ -6,6 +6,8 @@ false true true + + false Internal package for sharing Microsoft.Extensions.Hosting.HostFactoryResolver type. From 82053b51b6cc0f0587dcb863113350c83bd65c06 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 24 May 2021 16:36:31 -0700 Subject: [PATCH 092/115] Delete redundant area-owners entries (#53188) --- docs/area-owners.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/area-owners.md b/docs/area-owners.md index a8f4f5cb9da229..2472a3f72637ae 100644 --- a/docs/area-owners.md +++ b/docs/area-owners.md @@ -81,7 +81,7 @@ Note: Editing this file doesn't update the mapping used by the `@msftbot` issue | area-System.Diagnostics.EventLog | @jeffhandley | @adamsitnik @carlossanlop @jozkee | | | area-System.Diagnostics.PerformanceCounter | @jeffhandley | @adamsitnik @carlossanlop @jozkee | | | area-System.Diagnostics.Process | @jeffhandley | @adamsitnik @carlossanlop @jozkee | | -| area-System.Diagnostics.Tracing | @tommcdon | @noahfalk @tommcdon @Anipik @ViktorHofer @tarekgh | Packages:
  • System.Diagnostics.DiagnosticSource
  • System.Diagnostics.PerformanceCounter - @Anipik @ViktorHofer
  • System.Diagnostics.Tracing - @Anipik @ViktorHofer
  • System.Diagnostics.TraceSource
| +| area-System.Diagnostics.Tracing | @tommcdon | @noahfalk @tommcdon @Anipik @ViktorHofer @tarekgh | Included:
  • System.Diagnostics.DiagnosticSource
  • System.Diagnostics.TraceSource
| | area-System.Diagnostics.TraceSource | @jeffhandley | @buyaa-n @joperezr @krwq | Consultants: @tquerec @josephisenhour | | area-System.DirectoryServices | @jeffhandley | @buyaa-n @joperezr @krwq | Consultants: @tquerec @josephisenhour | | area-System.Drawing | @ericstj | @maryamariyan @michaelgsharp @safern @tarekgh | | From 9853434ccc83f82d55ce535b743214b0e17a99e7 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 24 May 2021 17:12:37 -0700 Subject: [PATCH 093/115] Add more natvis visualizations for base VM types. (#53052) --- src/coreclr/vm/vm.natvis | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/coreclr/vm/vm.natvis b/src/coreclr/vm/vm.natvis index f7bdbb1c30ca00..c06165f6eb5c60 100644 --- a/src/coreclr/vm/vm.natvis +++ b/src/coreclr/vm/vm.natvis @@ -13,4 +13,27 @@ The .NET Foundation licenses this file to you under the MIT license. m_value + + {m_val} + + m_val + + + + + m_pMethTab + *(((PTR_ObjHeader)this)-1) + + + + + (PTR_Object)(this + 1) + g_pSyncTable [m_SyncBlockValue.m_val & ((1<<26)-1)].m_SyncBlock + + + + + debug_m_szClassName,s8 + + From 1eb08990dc4619eb6daca8e7fda045da13a73c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Mon, 24 May 2021 20:25:17 -0400 Subject: [PATCH 094/115] Hot Reload: test on WebAssembly (#53050) * Hot Reload: test on WebAssembly 1. Always build the assemblies in the ApplyUpdate/ subdirectory without optimization, with debug info. Hot reload depends on it. 2. Pass the required environment variable to the runtime via xharness to enable support for applying updates. * Add ApplyUpdate test assemblies to test project linker descriptor * Fix wasm EnableAggressiveTrimming lane --- .../tests/ApplyUpdate/Directory.Build.props | 6 ++++ .../tests/ApplyUpdateUtil.cs | 15 ++-------- .../tests/System.Runtime.Loader.Tests.csproj | 28 +++++++++++++++++++ src/mono/mono/metadata/metadata-update.c | 4 ++- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/Directory.Build.props b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/Directory.Build.props index e2d777b74f8bc2..765d890a2cb756 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/Directory.Build.props +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/Directory.Build.props @@ -12,4 +12,10 @@ + + + false + true + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs index baa5ac27b76b1b..51873c0a14a36c 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateUtil.cs @@ -20,10 +20,9 @@ public class NoParallelTests { } /// We need: /// 1. Either DOTNET_MODIFIABLE_ASSEMBLIES=debug is set, or we can use the RemoteExecutor to run a child process with that environment; and, /// 2. Either Mono in a supported configuration (interpreter as the execution engine, and the hot reload feature enabled), or CoreCLR; and, - /// 3. The test assemblies are compiled in the Debug configuration. + /// 3. The test assemblies are compiled with Debug information (this is configured by setting EmitDebugInformation in ApplyUpdate\Directory.Build.props) public static bool IsSupported => (IsModifiableAssembliesSet || IsRemoteExecutorSupported) && - (!IsMonoRuntime || IsSupportedMonoConfiguration) && - IsSupportedTestConfiguration(); + (!IsMonoRuntime || IsSupportedMonoConfiguration); public static bool IsModifiableAssembliesSet => String.Equals(DotNetModifiableAssembliesValue, Environment.GetEnvironmentVariable(DotNetModifiableAssembliesSwitch), StringComparison.InvariantCultureIgnoreCase); @@ -61,16 +60,6 @@ internal static bool HasApplyUpdateCapabilities() return caps is string {Length: > 0}; } - // Only Debug assemblies are editable - internal static bool IsSupportedTestConfiguration() - { -#if DEBUG - return true; -#else - return false; -#endif - } - private static System.Collections.Generic.Dictionary assembly_count = new(); internal static void ApplyUpdate (System.Reflection.Assembly assm) diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index 3e8e0bcea43745..a69b4fe0a42c46 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -6,6 +6,8 @@ true false + + --setenv=DOTNET_MODIFIABLE_ASSEMBLIES=debug @@ -43,4 +45,30 @@ + + + + + + + + + + + + + + + + + diff --git a/src/mono/mono/metadata/metadata-update.c b/src/mono/mono/metadata/metadata-update.c index d5e9fc7c18115c..21797dae123bf7 100644 --- a/src/mono/mono/metadata/metadata-update.c +++ b/src/mono/mono/metadata/metadata-update.c @@ -85,8 +85,10 @@ mono_metadata_update_enabled (int *modifiable_assemblies_out) if (!inited) { char *val = g_getenv (DOTNET_MODIFIABLE_ASSEMBLIES); - if (val && !g_strcasecmp (val, "debug")) + if (val && !g_strcasecmp (val, "debug")) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "Metadata update enabled for debuggable assemblies"); modifiable = MONO_MODIFIABLE_ASSM_DEBUG; + } g_free (val); inited = TRUE; } From e3d66af5fc451335c2729c571710c51a7848bcff Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 24 May 2021 21:04:52 -0400 Subject: [PATCH 095/115] Fix handling of non-mergeable char classes in regex prefix analyzer (#53135) --- .../System/Text/RegularExpressions/RegexCharClass.cs | 12 ++++++++++++ .../Text/RegularExpressions/RegexPrefixAnalyzer.cs | 6 +++++- .../tests/Regex.Match.Tests.cs | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs index a569614032f026..219fed81e301c3 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs @@ -329,6 +329,18 @@ public void AddCharClass(RegexCharClass cc) } } + /// Adds a regex char class if the classes are mergeable. + public bool TryAddCharClass(RegexCharClass cc) + { + if (cc.CanMerge && CanMerge) + { + AddCharClass(cc); + return true; + } + + return false; + } + private StringBuilder EnsureCategories() => _categories ??= new StringBuilder(); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs index 2f8d5d15efcebc..ef20212565a33d 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexPrefixAnalyzer.cs @@ -223,7 +223,11 @@ public static (string CharClass, bool CaseInsensitive)[]? ComputeMultipleCharCla (classes[classPos++] ??= new RegexCharClass()).AddChar(concatChild.Ch); break; case RegexNode.Set: - (classes[classPos++] ??= new RegexCharClass()).AddCharClass(RegexCharClass.Parse(concatChild.Str!)); + if (!(classes[classPos++] ??= new RegexCharClass()).TryAddCharClass(RegexCharClass.Parse(concatChild.Str!))) + { + // If the classes can't be merged, give up. + return null; + } break; case RegexNode.Multi: for (int c = 0; c < concatChild.Str!.Length && classPos < classes.Length; c++) diff --git a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs index d2cd6b4e3e1a70..d5d690b0c29c1f 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs @@ -284,6 +284,7 @@ public static IEnumerable Match_Basic_TestData() yield return new object[] { "(?(cat)|dog)", "oof", RegexOptions.None, 0, 3, false, string.Empty }; yield return new object[] { "(?(a:b))", "a", RegexOptions.None, 0, 1, true, string.Empty }; yield return new object[] { "(?(a:))", "a", RegexOptions.None, 0, 1, true, string.Empty }; + yield return new object[] { "[^a-z0-9]etag|[^a-z0-9]digest", "this string has .digest as a substring", RegexOptions.None, 16, 7, true, ".digest" }; // No Negation yield return new object[] { "[abcd-[abcd]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; From e6d833c607919266130a466a2c250634ef4196c4 Mon Sep 17 00:00:00 2001 From: hrrrrustic <35951936+hrrrrustic@users.noreply.github.com> Date: Tue, 25 May 2021 04:15:04 +0300 Subject: [PATCH 096/115] System.ComponentModel.* missed Equals nullable annotations (#52163) * add NotNullWhen attribute * add usings --- .../ref/System.ComponentModel.Annotations.cs | 4 +-- .../DataAnnotations/FilterUIHintAttribute.cs | 3 +- .../DataAnnotations/UIHintAttribute.cs | 5 ++-- .../GenericSpecializationPartCreationInfo.cs | 2 +- .../ref/System.ComponentModel.Primitives.cs | 28 +++++++++---------- .../ComponentModel/BrowsableAttribute.cs | 4 ++- .../ComponentModel/CategoryAttribute.cs | 4 ++- .../ComponentModel/DescriptionAttribute.cs | 4 ++- .../ComponentModel/DesignOnlyAttribute.cs | 4 ++- .../DesignerCategoryAttribute.cs | 4 ++- ...esignerSerializationVisibilityAttribute.cs | 4 ++- .../ComponentModel/DisplayNameAttribute.cs | 4 ++- .../ImmutableObjectAttribute.cs | 4 ++- .../ComponentModel/LocalizableAttribute.cs | 4 ++- .../MergablePropertyAttribute.cs | 4 ++- .../NotifyParentPropertyAttribute.cs | 4 ++- .../ParenthesizePropertyNameAttribute.cs | 4 ++- .../ComponentModel/ReadOnlyAttribute.cs | 4 ++- .../RefreshPropertiesAttribute.cs | 4 ++- 19 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs index 2bc7c17b3415a0..298592f3fc3a31 100644 --- a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs +++ b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs @@ -174,7 +174,7 @@ public FilterUIHintAttribute(string filterUIHint, string? presentationLayer, par public System.Collections.Generic.IDictionary ControlParameters { get { throw null; } } public string FilterUIHint { get { throw null; } } public string? PresentationLayer { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } } public partial interface IValidatableObject @@ -280,7 +280,7 @@ public UIHintAttribute(string uiHint, string? presentationLayer, params object?[ public System.Collections.Generic.IDictionary ControlParameters { get { throw null; } } public string? PresentationLayer { get { throw null; } } public string UIHint { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } } [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)] diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FilterUIHintAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FilterUIHintAttribute.cs index bb5138ef3900ac..b2aa25fcfcc1be 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FilterUIHintAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FilterUIHintAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel.DataAnnotations { @@ -82,7 +83,7 @@ public FilterUIHintAttribute(string filterUIHint, string? presentationLayer, /// An System.Object. /// true if obj is a FilterUIHintAttribute and its value is the same /// as this instance; otherwise, false. - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is FilterUIHintAttribute otherAttribute && _implementation.Equals(otherAttribute._implementation); } } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/UIHintAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/UIHintAttribute.cs index b97ad7b7c6550e..1bb8419ee2a8bd 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/UIHintAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/UIHintAttribute.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Globalization; using System.Linq; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel.DataAnnotations { @@ -65,7 +66,7 @@ public UIHintAttribute(string uiHint, string? presentationLayer, params object?[ public override int GetHashCode() => _implementation.GetHashCode(); - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is UIHintAttribute otherAttribute && _implementation.Equals(otherAttribute._implementation); internal sealed class UIHintImplementation @@ -118,7 +119,7 @@ public override int GetHashCode() ///
/// An System.Object. /// true if obj is a UIHintAttribute and its value is the same as this instance; otherwise, false. - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { var otherImplementation = obj as UIHintImplementation; diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/GenericSpecializationPartCreationInfo.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/GenericSpecializationPartCreationInfo.cs index d0e4ac2324edc4..fe017bf5bafb82 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/GenericSpecializationPartCreationInfo.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/GenericSpecializationPartCreationInfo.cs @@ -550,7 +550,7 @@ public ICompositionElement? Origin get { return _originalPartCreationInfo.Origin; } } - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { return obj is GenericSpecializationPartCreationInfo that && (_originalPartCreationInfo.Equals(that._originalPartCreationInfo)) && (_specialization.IsArrayEqual(that._specialization)); diff --git a/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs b/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs index 45d664d1ddf63e..2575dcf5013de0 100644 --- a/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs +++ b/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs @@ -14,7 +14,7 @@ public sealed partial class BrowsableAttribute : System.Attribute public static readonly System.ComponentModel.BrowsableAttribute Yes; public BrowsableAttribute(bool browsable) { } public bool Browsable { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -38,7 +38,7 @@ public CategoryAttribute(string category) { } public static System.ComponentModel.CategoryAttribute Layout { get { throw null; } } public static System.ComponentModel.CategoryAttribute Mouse { get { throw null; } } public static System.ComponentModel.CategoryAttribute WindowStyle { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } protected virtual string? GetLocalizedString(string value) { throw null; } public override bool IsDefaultAttribute() { throw null; } @@ -82,7 +82,7 @@ public DescriptionAttribute() { } public DescriptionAttribute(string description) { } public virtual string Description { get { throw null; } } protected string DescriptionValue { get { throw null; } set { } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -113,7 +113,7 @@ public DesignerCategoryAttribute() { } public DesignerCategoryAttribute(string category) { } public string Category { get { throw null; } } public override object TypeId { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -132,7 +132,7 @@ public sealed partial class DesignerSerializationVisibilityAttribute : System.At public static readonly System.ComponentModel.DesignerSerializationVisibilityAttribute Visible; public DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility visibility) { } public System.ComponentModel.DesignerSerializationVisibility Visibility { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -144,7 +144,7 @@ public sealed partial class DesignOnlyAttribute : System.Attribute public static readonly System.ComponentModel.DesignOnlyAttribute Yes; public DesignOnlyAttribute(bool isDesignOnly) { } public bool IsDesignOnly { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -156,7 +156,7 @@ public DisplayNameAttribute() { } public DisplayNameAttribute(string displayName) { } public virtual string DisplayName { get { throw null; } } protected string DisplayNameValue { get { throw null; } set { } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -208,7 +208,7 @@ public sealed partial class ImmutableObjectAttribute : System.Attribute public static readonly System.ComponentModel.ImmutableObjectAttribute Yes; public ImmutableObjectAttribute(bool immutable) { } public bool Immutable { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -260,7 +260,7 @@ public sealed partial class LocalizableAttribute : System.Attribute public static readonly System.ComponentModel.LocalizableAttribute Yes; public LocalizableAttribute(bool isLocalizable) { } public bool IsLocalizable { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -272,7 +272,7 @@ public sealed partial class MergablePropertyAttribute : System.Attribute public static readonly System.ComponentModel.MergablePropertyAttribute Yes; public MergablePropertyAttribute(bool allowMerge) { } public bool AllowMerge { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -284,7 +284,7 @@ public sealed partial class NotifyParentPropertyAttribute : System.Attribute public static readonly System.ComponentModel.NotifyParentPropertyAttribute Yes; public NotifyParentPropertyAttribute(bool notifyParent) { } public bool NotifyParent { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -295,7 +295,7 @@ public sealed partial class ParenthesizePropertyNameAttribute : System.Attribute public ParenthesizePropertyNameAttribute() { } public ParenthesizePropertyNameAttribute(bool needParenthesis) { } public bool NeedParenthesis { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -307,7 +307,7 @@ public sealed partial class ReadOnlyAttribute : System.Attribute public static readonly System.ComponentModel.ReadOnlyAttribute Yes; public ReadOnlyAttribute(bool isReadOnly) { } public bool IsReadOnly { get { throw null; } } - public override bool Equals(object? value) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } @@ -325,7 +325,7 @@ public sealed partial class RefreshPropertiesAttribute : System.Attribute public static readonly System.ComponentModel.RefreshPropertiesAttribute Repaint; public RefreshPropertiesAttribute(System.ComponentModel.RefreshProperties refresh) { } public System.ComponentModel.RefreshProperties RefreshProperties { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public override bool IsDefaultAttribute() { throw null; } } diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/BrowsableAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/BrowsableAttribute.cs index 6fcf5f465ff77e..2361a9cef6cd18 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/BrowsableAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/BrowsableAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -42,7 +44,7 @@ public BrowsableAttribute(bool browsable) /// public bool Browsable { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is BrowsableAttribute other && other.Browsable == Browsable; public override int GetHashCode() => Browsable.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs index e9c6414aaf311d..ecad394cbf6c5d 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -189,7 +191,7 @@ public string Category } } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is CategoryAttribute other && other.Category == Category; public override int GetHashCode() => Category?.GetHashCode() ?? 0; diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DescriptionAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DescriptionAttribute.cs index 35d92078534eb4..6b0f66f6fbecfc 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DescriptionAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DescriptionAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -39,7 +41,7 @@ public DescriptionAttribute(string description) /// protected string DescriptionValue { get; set; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is DescriptionAttribute other && other.Description == Description; public override int GetHashCode() => Description?.GetHashCode() ?? 0; diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignOnlyAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignOnlyAttribute.cs index f8b9f738b571da..883134a16854f8 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignOnlyAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignOnlyAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -41,7 +43,7 @@ public DesignOnlyAttribute(bool isDesignOnly) /// public bool IsDesignOnly { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is DesignOnlyAttribute other && other.IsDesignOnly == IsDesignOnly; public override int GetHashCode() => IsDesignOnly.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerCategoryAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerCategoryAttribute.cs index 2791d973e39e77..a13a9a75e30785 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerCategoryAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerCategoryAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -55,7 +57,7 @@ public DesignerCategoryAttribute(string category) /// public string Category { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is DesignerCategoryAttribute other && other.Category == Category; public override int GetHashCode() => Category?.GetHashCode() ?? 0; diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerSerializationVisibilityAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerSerializationVisibilityAttribute.cs index 43cf7edd626e80..2a6161ac268712 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerSerializationVisibilityAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DesignerSerializationVisibilityAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -51,7 +53,7 @@ public DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility /// public DesignerSerializationVisibility Visibility { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is DesignerSerializationVisibilityAttribute other && other.Visibility == Visibility; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DisplayNameAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DisplayNameAttribute.cs index 31d2448ee7180d..132696372ed327 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DisplayNameAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/DisplayNameAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -38,7 +40,7 @@ public DisplayNameAttribute(string displayName) /// protected string DisplayNameValue { get; set; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is DisplayNameAttribute other && other.DisplayName == DisplayName; public override int GetHashCode() => DisplayName?.GetHashCode() ?? 0; diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ImmutableObjectAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ImmutableObjectAttribute.cs index c59f2eb3504ef5..a039462f73fef5 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ImmutableObjectAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ImmutableObjectAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -41,7 +43,7 @@ public ImmutableObjectAttribute(bool immutable) public bool Immutable { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is ImmutableObjectAttribute other && other.Immutable == Immutable; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/LocalizableAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/LocalizableAttribute.cs index ea937b3fcc7712..0025cb98d814eb 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/LocalizableAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/LocalizableAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -41,7 +43,7 @@ public LocalizableAttribute(bool isLocalizable) /// public static readonly LocalizableAttribute Default = No; - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is LocalizableAttribute other && other.IsLocalizable == IsLocalizable; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/MergablePropertyAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/MergablePropertyAttribute.cs index 30c48385af1f6d..4d882b41c62987 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/MergablePropertyAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/MergablePropertyAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -47,7 +49,7 @@ public MergablePropertyAttribute(bool allowMerge) /// public bool AllowMerge { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is MergablePropertyAttribute other && other.AllowMerge == AllowMerge; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/NotifyParentPropertyAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/NotifyParentPropertyAttribute.cs index d9a26cf8133ab7..d88cfb468fa1da 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/NotifyParentPropertyAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/NotifyParentPropertyAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -49,7 +51,7 @@ public NotifyParentPropertyAttribute(bool notifyParent) /// /// Tests whether the specified object is the same as the current object. /// - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is NotifyParentPropertyAttribute other && other.NotifyParent == NotifyParent; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ParenthesizePropertyNameAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ParenthesizePropertyNameAttribute.cs index a13cfb52fd087f..718e6fa19a35ef 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ParenthesizePropertyNameAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ParenthesizePropertyNameAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -39,7 +41,7 @@ public ParenthesizePropertyNameAttribute(bool needParenthesis) /// /// Compares the specified object to this object and tests for equality. /// - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is ParenthesizePropertyNameAttribute other && other.NeedParenthesis == NeedParenthesis; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ReadOnlyAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ReadOnlyAttribute.cs index cec9df948e8f7b..87cba59b412e8b 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ReadOnlyAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ReadOnlyAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -42,7 +44,7 @@ public sealed class ReadOnlyAttribute : Attribute /// public bool IsReadOnly { get; } - public override bool Equals(object? value) => + public override bool Equals([NotNullWhen(true)] object? value) => value is ReadOnlyAttribute other && other.IsReadOnly == IsReadOnly; public override int GetHashCode() => base.GetHashCode(); diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/RefreshPropertiesAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/RefreshPropertiesAttribute.cs index 36dbd4470fe8a8..8ec46b497c1090 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/RefreshPropertiesAttribute.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/RefreshPropertiesAttribute.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -37,7 +39,7 @@ public RefreshPropertiesAttribute(RefreshProperties refresh) /// public RefreshProperties RefreshProperties { get; } - public override bool Equals(object? obj) => + public override bool Equals([NotNullWhen(true)] object? obj) => obj is RefreshPropertiesAttribute other && other.RefreshProperties == RefreshProperties; public override int GetHashCode() => base.GetHashCode(); From 129d20e06273e3e2b3f4fcb7990836e37ccbd69e Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Mon, 24 May 2021 18:23:22 -0700 Subject: [PATCH 097/115] GT_COPY source should be marked as consume during resolution (#53041) --- docs/design/coreclr/jit/lsra-detail.md | 6 ++-- src/coreclr/jit/clrjit.natvis | 38 ++++++++++++++++++++++++++ src/coreclr/jit/lsra.cpp | 14 ++++++++-- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/docs/design/coreclr/jit/lsra-detail.md b/docs/design/coreclr/jit/lsra-detail.md index e3cb0c0c01f11f..12c8969b374635 100644 --- a/docs/design/coreclr/jit/lsra-detail.md +++ b/docs/design/coreclr/jit/lsra-detail.md @@ -170,11 +170,11 @@ There are four main phases to LSRA: - For fork edges (the source block has multiple targets, but each target has only that one source), any required - resolution is placed at the target. + resolution is placed at the individual target(s). - For join edges (a single target block has multiple sources, but each source has only that one target), any required - resolution is placed at the source. + resolution is placed at the individual source(s). - Critical edges require more complicated handling, and may require splitting of the edge for placement of resolution. @@ -707,7 +707,7 @@ LinearScanAllocation(List refPositions) - Next, for the remaining variables, classify them as either: - In different registers at one or more targets. These require that the edge be split so that we can insert the move on the edge (this is the `diffResolutionSet`). - - In the same register at each target (this is the `sameResolutionSet`). + - In the same register at each target (this is the `sameResolutionSet`), but different from the end of this block. For these, we can insert a move at the end of this block, as long as they don't write to any of the registers read by the `diffResolutionSet` as those must remain live into the split block. diff --git a/src/coreclr/jit/clrjit.natvis b/src/coreclr/jit/clrjit.natvis index c242727719bc8f..07cfc192b5ae04 100644 --- a/src/coreclr/jit/clrjit.natvis +++ b/src/coreclr/jit/clrjit.natvis @@ -57,6 +57,44 @@ The .NET Foundation licenses this file to you under the MIT license. LinearScan + "InVarToRegMaps" + + + + + + + block->bbNum,2u + varIndex = 0 + inVarMap = this->inVarToRegMaps[block->bbNum] + bbLiveInMap = block->bbLiveIn[0] + + ((regNumber)inVarMap[varIndex]),en + varIndex++ + bbLiveInMap = bbLiveInMap >> 1 + + block = block->bbNext + + + "OutVarToRegMaps" + + + + + + + block->bbNum,2u + varIndex = 0 + outVarMap = this->outVarToRegMaps[block->bbNum] + bbLiveInMap = block->bbLiveIn[0] + + ((regNumber)outVarMap[varIndex]),en + varIndex++ + bbLiveInMap = bbLiveInMap >> 1 + + block = block->bbNext + + this->m_AvailableRegs diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 8417b1d63e9a77..d5c4e952067631 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -7589,6 +7589,14 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) assert(varTypeIsIntegralOrI(op1) && varTypeIsIntegralOrI(op2)); consumedRegs |= genRegMask(op1->GetRegNum()); consumedRegs |= genRegMask(op2->GetRegNum()); + + // Special handling for GT_COPY to not resolve into the source + // of switch's operand. + if (op1->OperIs(GT_COPY)) + { + GenTree* srcOp1 = op1->gtGetOp1(); + consumedRegs |= genRegMask(srcOp1->GetRegNum()); + } } #ifdef TARGET_ARM64 @@ -7717,7 +7725,7 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) // // Another way to achieve similar resolution for vars live only at split edges is by removing them // from consideration up-front but it requires that we traverse those edges anyway to account for - // the registers that must note be overwritten. + // the registers that must not be overwritten. if (liveOnlyAtSplitEdge && maybeSameLivePaths) { sameToReg = REG_NA; @@ -9578,7 +9586,7 @@ void LinearScan::dumpLsraAllocationEvent( // Conflicting def/use case LSRA_EVENT_DEFUSE_CONFLICT: dumpRefPositionShort(activeRefPosition, currentBlock); - printf("DUconflict "); + printf("DUconflict "); dumpRegRecords(); break; case LSRA_EVENT_DEFUSE_CASE1: @@ -10056,7 +10064,7 @@ void LinearScan::dumpNewBlock(BasicBlock* currentBlock, LsraLocation location) if (activeRefPosition->refType == RefTypeDummyDef) { dumpEmptyRefPosition(); - printf("DDefs "); + printf("DDefs "); printf(regNameFormat, ""); return; } From 5cea8ebac3f320970a6af5e1872bdb9b9392665f Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 24 May 2021 21:42:06 -0400 Subject: [PATCH 098/115] Delete now unused *AsyncResult files from Sockets (#53192) --- .../Sockets/BaseOverlappedAsyncResult.Unix.cs | 31 --- .../BaseOverlappedAsyncResult.Windows.cs | 200 ------------------ .../Net/Sockets/BaseOverlappedAsyncResult.cs | 25 --- 3 files changed, 256 deletions(-) delete mode 100644 src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Unix.cs delete mode 100644 src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs delete mode 100644 src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.cs diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Unix.cs deleted file mode 100644 index 5864b569a87eae..00000000000000 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Unix.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Diagnostics; -using System.Net; -using System.Runtime.InteropServices; -using System.Threading; -using Microsoft.Win32; - -namespace System.Net.Sockets -{ - // BaseOverlappedAsyncResult - // - // This class is used to track state for async Socket operations such as the BeginSend, BeginSendTo, - // BeginReceive, BeginReceiveFrom, BeginSendFile, and BeginAccept calls. - internal partial class BaseOverlappedAsyncResult : ContextAwareResult - { - public BaseOverlappedAsyncResult(Socket socket, object? asyncState, AsyncCallback? asyncCallback) - : base(socket, asyncState, asyncCallback) - { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, socket); - } - - protected void CompletionCallback(int numBytes, SocketError errorCode) - { - ErrorCode = (int)errorCode; - InvokeCallback(PostCompletion(numBytes)); - } - } -} diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs deleted file mode 100644 index 14e2b0ea10f0d9..00000000000000 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.Windows.cs +++ /dev/null @@ -1,200 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Threading; - -namespace System.Net.Sockets -{ - // BaseOverlappedAsyncResult - // - // This class is used to track state for async Socket operations such as the BeginSend, BeginSendTo, - // BeginReceive, BeginReceiveFrom, BeginSendFile, and BeginAccept calls. - internal partial class BaseOverlappedAsyncResult : ContextAwareResult - { - private int _cleanupCount; - private SafeNativeOverlapped? _nativeOverlapped; - - // The WinNT Completion Port callback. - private static readonly unsafe IOCompletionCallback s_ioCallback = new IOCompletionCallback(CompletionPortCallback); - - internal BaseOverlappedAsyncResult(Socket socket, object? asyncState, AsyncCallback? asyncCallback) - : base(socket, asyncState, asyncCallback) - { - _cleanupCount = 1; - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, socket); - } - - // SetUnmanagedStructures - // - // This needs to be called for overlapped IO to function properly. - // - // Fills in overlapped Structures used in an async overlapped Winsock call. - // These calls are outside the runtime and are unmanaged code, so we need - // to prepare specific structures and ints that lie in unmanaged memory - // since the overlapped calls may complete asynchronously. - internal void SetUnmanagedStructures(object? objectsToPin) - { - Socket s = (Socket)AsyncObject!; - - // Bind the Win32 Socket Handle to the ThreadPool - Debug.Assert(s != null, "m_CurrentSocket is null"); - Debug.Assert(s.SafeHandle != null, "m_CurrentSocket.SafeHandle is null"); - - if (s.SafeHandle.IsInvalid) - { - throw new ObjectDisposedException(s.GetType().FullName); - } - - ThreadPoolBoundHandle boundHandle = s.GetOrAllocateThreadPoolBoundHandle(); - - unsafe - { - Debug.Assert(OperatingSystem.IsWindows()); - NativeOverlapped* overlapped = boundHandle.AllocateNativeOverlapped(s_ioCallback, this, objectsToPin); - _nativeOverlapped = new SafeNativeOverlapped(s.SafeHandle, overlapped); - } - - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{boundHandle}::AllocateNativeOverlapped. return={_nativeOverlapped}"); - } - - private static unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) - { - Debug.Assert(OperatingSystem.IsWindows()); - BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped)!; - - Debug.Assert(!asyncResult.InternalPeekCompleted, $"asyncResult.IsCompleted: {asyncResult}"); - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(null, $"errorCode:{errorCode} numBytes:{numBytes} nativeOverlapped:{(IntPtr)nativeOverlapped}"); - - // Complete the IO and invoke the user's callback. - SocketError socketError = (SocketError)errorCode; - - if (socketError != SocketError.Success && socketError != SocketError.OperationAborted) - { - // There are cases where passed errorCode does not reflect the details of the underlined socket error. - // "So as of today, the key is the difference between WSAECONNRESET and ConnectionAborted, - // .e.g remote party or network causing the connection reset or something on the local host (e.g. closesocket - // or receiving data after shutdown (SD_RECV)). With Winsock/TCP stack rewrite in longhorn, there may - // be other differences as well." - - Socket? socket = asyncResult.AsyncObject as Socket; - if (socket == null) - { - socketError = SocketError.NotSocket; - } - else if (socket.Disposed) - { - socketError = SocketError.OperationAborted; - } - else - { - try - { - // The async IO completed with a failure. - // Here we need to call WSAGetOverlappedResult() just so GetLastSocketError() will return the correct error. - SocketFlags ignore; - bool success = Interop.Winsock.WSAGetOverlappedResult( - socket.SafeHandle, - nativeOverlapped, - out numBytes, - false, - out ignore); - Debug.Assert(!success, $"Unexpectedly succeeded. errorCode:{errorCode} numBytes:{numBytes}"); - if (!success) - { - socketError = SocketPal.GetLastSocketError(); - } - } - catch (ObjectDisposedException) - { - // Disposed check above does not always work since this code is subject to race conditions - socketError = SocketError.OperationAborted; - } - } - } - - // Set results and invoke callback - asyncResult.CompletionCallback((int)numBytes, socketError); - } - - // Called either synchronously from SocketPal async routines or asynchronously via CompletionPortCallback above. - private void CompletionCallback(int numBytes, SocketError socketError) - { - ErrorCode = (int)socketError; - object? result = PostCompletion(numBytes); - ReleaseUnmanagedStructures(); // must come after PostCompletion, as overrides may use these resources - InvokeCallback(result); - } - - internal unsafe NativeOverlapped* DangerousOverlappedPointer => (NativeOverlapped*)_nativeOverlapped!.DangerousGetHandle(); - - // Check the result of the overlapped operation. - // Handle synchronous success by completing the asyncResult here. - // Handle synchronous failure by cleaning up and returning a SocketError. - internal SocketError ProcessOverlappedResult(bool success, int bytesTransferred) - { - if (success) - { - // Synchronous success. - Socket socket = (Socket)AsyncObject!; - if (socket.SafeHandle.SkipCompletionPortOnSuccess) - { - // The socket handle is configured to skip completion on success, - // so we can complete this asyncResult right now. - CompletionCallback(bytesTransferred, SocketError.Success); - return SocketError.Success; - } - - // Socket handle is going to post a completion to the completion port (may have done so already). - // Return pending and we will continue in the completion port callback. - return SocketError.IOPending; - } - - // Get the socket error (which may be IOPending) - SocketError errorCode = SocketPal.GetLastSocketError(); - - if (errorCode == SocketError.IOPending) - { - // Operation is pending. - // We will continue when the completion arrives (may have already at this point). - return SocketError.IOPending; - } - - // Synchronous failure. - // Release overlapped and pinned structures. - ReleaseUnmanagedStructures(); - - return errorCode; - } - - internal void ReleaseUnmanagedStructures() - { - if (Interlocked.Decrement(ref _cleanupCount) == 0) - { - ForceReleaseUnmanagedStructures(); - } - } - - protected override void Cleanup() - { - base.Cleanup(); - - // If we get all the way to here and it's still not cleaned up... - if (_cleanupCount > 0 && Interlocked.Exchange(ref _cleanupCount, 0) > 0) - { - ForceReleaseUnmanagedStructures(); - } - } - - // Utility cleanup routine. Frees the overlapped structure. - // This should be overridden to free pinned and unmanaged memory in the subclass. - // It needs to also be invoked from the subclass. - protected virtual void ForceReleaseUnmanagedStructures() - { - // Free the unmanaged memory if allocated. - _nativeOverlapped!.Dispose(); - _nativeOverlapped = null; - GC.SuppressFinalize(this); - } - } -} diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.cs deleted file mode 100644 index a60cbb975dafea..00000000000000 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/BaseOverlappedAsyncResult.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Sockets -{ - // BaseOverlappedAsyncResult - // - // This class is used to track state for async Socket operations such as the BeginSend, BeginSendTo, - // BeginReceive, BeginReceiveFrom, BeginSendFile, and BeginAccept calls. - internal partial class BaseOverlappedAsyncResult : ContextAwareResult - { - // Sentinel object passed to callers of PostCompletion to use as the - // "result" of this operation, in order to avoid boxing the actual result. - private static readonly object s_resultObjectSentinel = new object(); - // The actual result (number of bytes transferred) - internal int _numBytes; - - // PostCompletion returns the result object to be set before the user's callback is invoked. - internal virtual object? PostCompletion(int numBytes) - { - _numBytes = numBytes; - return s_resultObjectSentinel; // return sentinel rather than boxing numBytes - } - } -} From d0d7705c79f81e8ec9381d60896b7271d41273a7 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 24 May 2021 22:42:26 -0700 Subject: [PATCH 099/115] Parse `DOTNET_PROCESSOR_COUNT` with a 10 radix not 16 (#53208) * Parse DOTNET_PROCESSOR_COUNT with a 10 radix not 16 * Update test for DOTNET_PROCESSOR_COUNT --- src/coreclr/inc/clrconfig.h | 6 +++++- src/coreclr/inc/clrconfigvalues.h | 2 +- src/coreclr/utilcode/clrconfig.cpp | 6 +++++- .../tests/System/Environment.ProcessorCount.cs | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/clrconfig.h b/src/coreclr/inc/clrconfig.h index 97a76badaded66..f067824d241b5c 100644 --- a/src/coreclr/inc/clrconfig.h +++ b/src/coreclr/inc/clrconfig.h @@ -31,7 +31,11 @@ class CLRConfig // Remove any whitespace at beginning and end of value. (Only applicable for // *string* configuration values.) - TrimWhiteSpaceFromStringValue = 0x2 + TrimWhiteSpaceFromStringValue = 0x2, + + // The configuration should be parsed using a 10 radix as opposed to the + // default of 16. + ParseIntegerAsBase10 = 0x4, }; // Struct used to store information about where/how to find a Config DWORD. diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 8498c87adbf53b..5dc7e5d34b20bd 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -555,7 +555,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadCountThresholdForGCTrigger, W RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadGCTriggerPeriodMilliseconds, W("Thread_DeadThreadGCTriggerPeriodMilliseconds"), 1000 * 60 * 30, "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") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_UseAllCpuGroups, W("Thread_UseAllCpuGroups"), 0, "Specifies whether to query and use CPU group information for determining the processor count.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_AssignCpuGroups, W("Thread_AssignCpuGroups"), 1, "Specifies whether to automatically distribute threads created by the CLR across CPU Groups. Effective only when Thread_UseAllCpuGroups and GCCpuGroup are enabled.") -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProcessorCount, W("PROCESSOR_COUNT"), 0, "Specifies the number of processors available for the process, which is returned by Environment.ProcessorCount") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_ProcessorCount, W("PROCESSOR_COUNT"), 0, "Specifies the number of processors available for the process, which is returned by Environment.ProcessorCount", CLRConfig::LookupOptions::ParseIntegerAsBase10) /// /// Threadpool diff --git a/src/coreclr/utilcode/clrconfig.cpp b/src/coreclr/utilcode/clrconfig.cpp index f21f49ed8d1053..59d32c0c43091d 100644 --- a/src/coreclr/utilcode/clrconfig.cpp +++ b/src/coreclr/utilcode/clrconfig.cpp @@ -233,12 +233,16 @@ namespace FAULT_NOT_FATAL(); // We don't report OOM errors here, we return a default value. + int radix = CheckLookupOption(options, LookupOptions::ParseIntegerAsBase10) + ? 10 + : 16; // Parse as hex by default. + NewArrayHolder val = EnvGetString(name, options); if (val != NULL) { errno = 0; LPWSTR endPtr; - DWORD configMaybe = wcstoul(val, &endPtr, 16); // treat it has hex + DWORD configMaybe = wcstoul(val, &endPtr, radix); BOOL fSuccess = ((errno != ERANGE) && (endPtr != val)); if (fSuccess) { diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Environment.ProcessorCount.cs b/src/libraries/System.Runtime.Extensions/tests/System/Environment.ProcessorCount.cs index dda81c26b21f7c..7ec112a2c481a8 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/Environment.ProcessorCount.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/Environment.ProcessorCount.cs @@ -30,7 +30,7 @@ private static unsafe int ParseProcessorCount(string settingValue) fixed (char *ptr = settingValue) { char *endptr; - int value = (int)wcstoul(ptr, &endptr, 16); + int value = (int)wcstoul(ptr, &endptr, 10); if (0 < value && value <= MAX_PROCESSOR_COUNT) return value; @@ -69,7 +69,7 @@ public void ProcessorCount_Windows_MatchesGetSystemInfo() [InlineData(8000, 2000, null)] [InlineData(8000, 0, "1")] [InlineData(2000, 0, null)] - [InlineData(2000, 0, " 0x11 ")] + [InlineData(2000, 0, " 17 ")] [InlineData(0, 0, "3")] public static unsafe void ProcessorCount_Windows_RespectsJobCpuRateAndConfigurationSetting( ushort maxRate, ushort minRate, string procCountConfig) From fff0076c25efc5dad0c6a188cb41930270c36088 Mon Sep 17 00:00:00 2001 From: Johan Lorensson Date: Tue, 25 May 2021 10:32:44 +0200 Subject: [PATCH 100/115] Emit JITStarting, MethodLoad, ModuleLoad and AssemblyLoad EventPipe events on Mono. (#53020) * Add native JIT event into EventPipe. * Emit module/assembly load native events into EventPipe. * Emit MethodDCEnd_V1 and MethodILToNativeMap EventPipe events. --- src/coreclr/scripts/genEventPipe.py | 6 +- src/coreclr/scripts/genEventing.py | 11 +- src/mono/mono/eventpipe/ep-rt-mono.c | 645 +++++++++++++++++- src/mono/mono/eventpipe/ep-rt-mono.h | 70 +- .../mono/eventpipe/gen-eventing-event-inc.lst | 19 +- .../mono/eventpipe/test/ep-teardown-tests.c | 2 + src/mono/mono/eventpipe/test/ep-tests.c | 82 +++ 7 files changed, 802 insertions(+), 33 deletions(-) diff --git a/src/coreclr/scripts/genEventPipe.py b/src/coreclr/scripts/genEventPipe.py index 8ec9e2154bd765..380710d4a009b2 100644 --- a/src/coreclr/scripts/genEventPipe.py +++ b/src/coreclr/scripts/genEventPipe.py @@ -166,13 +166,11 @@ def generateClrEventPipeWriteEventsImpl( WriteEventImpl.append("\n return ERROR_SUCCESS;\n}\n\n") # EventPipeProvider and EventPipeEvent initialization - callbackName = "" + callbackName = 'EventPipeEtwCallback' + providerPrettyName createProviderFunc = "" if runtimeFlavor.coreclr: - callbackName = 'EventPipeEtwCallback' + providerPrettyName createProviderFunc = "EventPipeAdapter::CreateProvider" elif runtimeFlavor.mono: - callbackName = "NULL" createProviderFunc = "create_provider" eventPipeCallbackCastExpr = "" @@ -181,6 +179,8 @@ def generateClrEventPipeWriteEventsImpl( else: eventPipeCallbackCastExpr = "(EventPipeCallback)" + if runtimeFlavor.mono: + WriteEventImpl.append("void " + callbackName + "(const uint8_t *, unsigned long, uint8_t, uint64_t, uint64_t, EventFilterDescriptor *, void *);\n\n") if extern: WriteEventImpl.append('extern "C" ') WriteEventImpl.append( diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index 43fd56b08ec8e9..f1e341a36b297e 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -714,6 +714,10 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern else: Clrallevents.write("\n") + if not is_windows and not write_xplatheader: + Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT + Clrallevents.write("\n") + for providerNode in tree.getElementsByTagName('provider'): templateNodes = providerNode.getElementsByTagName('template') allTemplates = parseTemplateNodes(templateNodes) @@ -725,9 +729,12 @@ def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern providerName = providerNode.getAttribute('name') providerSymbol = providerNode.getAttribute('symbol') + eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" if is_windows: - eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" - Clrallevents.write(('constexpr ' if target_cpp else 'const ') + 'EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + Clrallevents.write(('constexpr ' if target_cpp else '') + 'EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + + if not is_windows and not write_xplatheader: + Clrallevents.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') if write_xplatheader: clrproviders = os.path.join(incDir, "clrproviders.h") diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index 9cbf9805eda855..1fe111926a0046 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,9 @@ char *_ep_rt_mono_managed_cmd_line = NULL; static GArray * _ep_rt_mono_sampled_thread_callstacks = NULL; static uint32_t _ep_rt_mono_max_sampled_thread_count = 32; +// Mono profiler. +static MonoProfilerHandle _ep_rt_mono_profiler = NULL; + // Rundown types. typedef bool @@ -64,6 +66,8 @@ bool const uint16_t count_of_map_entries, const uint32_t *il_offsets, const uint32_t *native_offsets, + bool aot_method, + bool verbose, void *user_data); typedef @@ -118,6 +122,8 @@ typedef struct _EventPipeSampleProfileData { #define METHOD_FLAGS_SHARED_GENERIC_METHOD 0x4 #define METHOD_FLAGS_JITTED_METHOD 0x8 #define METHOD_FLAGS_JITTED_HELPER_METHOD 0x10 +#define METHOD_FLAGS_EXTENT_HOT_SECTION 0x00000000 +#define METHOD_FLAGS_EXTENT_COLD_SECTION 0x10000000 #define MODULE_FLAGS_NATIVE_MODULE 0x2 #define MODULE_FLAGS_DYNAMIC_MODULE 0x4 @@ -149,6 +155,8 @@ fire_method_rundown_events_func ( const uint16_t count_of_map_entries, const uint32_t *il_offsets, const uint32_t *native_offsets, + bool aot_method, + bool verbose, void *user_data); static @@ -228,6 +236,37 @@ profiler_eventpipe_thread_exited ( MonoProfiler *prof, uintptr_t tid); +static +void +profiler_jit_begin ( + MonoProfiler *prof, + MonoMethod *method); + +static +void +profiler_jit_failed ( + MonoProfiler *prof, + MonoMethod *method); + +static +void +profiler_jit_done ( + MonoProfiler *prof, + MonoMethod *method, + MonoJitInfo *ji); + +static +void +profiler_image_loaded ( + MonoProfiler *prof, + MonoImage *image); + +static +void +profiler_assembly_loaded ( + MonoProfiler *prof, + MonoAssembly *assembly); + /* * Forward declares of all private functions (accessed using extern in ep-rt-mono.h). */ @@ -276,6 +315,12 @@ ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array); void ep_rt_mono_init_providers_and_events (void); +void +ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config); + +bool +ep_rt_mono_providers_validate_all_disabled (void); + void ep_rt_mono_fini_providers_and_events (void); @@ -328,6 +373,8 @@ fire_method_rundown_events_func ( const uint16_t count_of_map_entries, const uint32_t *il_offsets, const uint32_t *native_offsets, + bool aot_method, + bool verbose, void *user_data) { FireEtwMethodDCEndILToNativeMap ( @@ -341,19 +388,59 @@ fire_method_rundown_events_func ( NULL, NULL); - FireEtwMethodDCEndVerbose_V1 ( - method_id, - module_id, - method_start_address, - method_size, - method_token, - method_flags, - method_namespace, - method_name, - method_signature, - clr_instance_get_id (), - NULL, - NULL); + if (verbose) { + FireEtwMethodDCEndVerbose_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + + if (aot_method) + FireEtwMethodDCEndVerbose_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + } else { + FireEtwMethodDCEnd_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + clr_instance_get_id (), + NULL, + NULL); + + if (aot_method) + FireEtwMethodDCEnd_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + clr_instance_get_id (), + NULL, + NULL); + } return true; } @@ -461,6 +548,7 @@ eventpipe_fire_method_events ( char *method_namespace = NULL; const char *method_name = NULL; char *method_signature = NULL; + bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE); //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc. @@ -483,16 +571,20 @@ eventpipe_fire_method_events ( if (method->is_generic || method->is_inflated) method_flags |= METHOD_FLAGS_GENERIC_METHOD; - method_name = method->name; - method_signature = mono_signature_full_name (method->signature); - if (method->klass) { module_id = (uint64_t)m_class_get_image (method->klass); kind = m_class_get_class_kind (method->klass); if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST) method_flags |= METHOD_FLAGS_GENERIC_METHOD; - method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); } + + if (verbose) { + method_name = method->name; + method_signature = mono_signature_full_name (method->signature); + if (method->klass) + method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); + } + } uint16_t offset_entries = 0; @@ -545,6 +637,8 @@ eventpipe_fire_method_events ( offset_entries, il_offsets, native_offsets, + (ji->from_aot || ji->from_llvm), + verbose, NULL); g_free (method_namespace); @@ -793,8 +887,8 @@ ep_rt_mono_init (void) _ep_rt_mono_initialized = TRUE; - MonoProfilerHandle profiler = mono_profiler_create (NULL); - mono_profiler_set_thread_stopped_callback (profiler, profiler_eventpipe_thread_exited); + _ep_rt_mono_profiler = mono_profiler_create (NULL); + mono_profiler_set_thread_stopped_callback (_ep_rt_mono_profiler, profiler_eventpipe_thread_exited); } void @@ -1157,6 +1251,24 @@ ep_rt_mono_init_providers_and_events (void) InitProvidersAndEvents (); } +void +ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config) +{ + if (!ep_rt_utf8_string_compare (ep_config_get_rundown_provider_name_utf8 (), ep_provider_config_get_provider_name (provider_config))) { + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = ep_provider_config_get_logging_level (provider_config); + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = ep_provider_config_get_keywords (provider_config); + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = true; + } +} + +bool +ep_rt_mono_providers_validate_all_disabled (void) +{ + return (!MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled && + !MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled && + !MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled); +} + void ep_rt_mono_fini_providers_and_events (void) { @@ -1349,6 +1461,499 @@ ep_rt_mono_write_event_ee_startup_start (void) NULL); } +bool +ep_rt_mono_write_event_jit_start (MonoMethod *method) +{ + if (!EventEnabledMethodJittingStarted_V1 ()) + return true; + + //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc. + if (method) { + uint64_t method_id = 0; + uint64_t module_id = 0; + uint32_t code_size = 0; + uint32_t method_token = 0; + char *method_namespace = NULL; + const char *method_name = NULL; + char *method_signature = NULL; + + //TODO: SendMethodDetailsEvent + + method_id = (uint64_t)method; + + if (!method->dynamic) + method_token = method->token; + + if (!mono_method_has_no_body (method)) { + ERROR_DECL (error); + MonoMethodHeader *header = mono_method_get_header_internal (method, error); + if (header) + code_size = header->code_size; + } + + method_name = method->name; + method_signature = mono_signature_full_name (method->signature); + + if (method->klass) { + module_id = (uint64_t)m_class_get_image (method->klass); + method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); + } + + FireEtwMethodJittingStarted_V1 ( + method_id, + module_id, + method_token, + code_size, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + + g_free (method_namespace); + g_free (method_signature); + } + + return true; +} + +bool +ep_rt_mono_write_event_method_il_to_native_map ( + MonoMethod *method, + MonoJitInfo *ji) +{ + if (!EventEnabledMethodILToNativeMap ()) + return true; + + if (method) { + // Under netcore we only have root domain. + MonoDomain *root_domain = mono_get_root_domain (); + + uint64_t method_id = (uint64_t)method; + uint32_t fixed_buffer [64]; + uint8_t *buffer = NULL; + + uint16_t offset_entries = 0; + uint32_t *il_offsets = NULL; + uint32_t *native_offsets = NULL; + + MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, root_domain) : NULL; + if (debug_info) { + offset_entries = debug_info->num_line_numbers; + size_t needed_size = (offset_entries * sizeof (uint32_t) * 2); + if (needed_size > sizeof (fixed_buffer)) { + buffer = g_new (uint8_t, needed_size); + il_offsets = (uint32_t*)buffer; + } else { + il_offsets = fixed_buffer; + } + if (il_offsets) { + native_offsets = il_offsets + offset_entries; + for (int offset_count = 0; offset_count < offset_entries; ++offset_count) { + il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset; + native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset; + } + } + + mono_debug_free_method_jit_info (debug_info); + } + + if (!il_offsets && !native_offsets) { + // No IL offset -> Native offset mapping available. Put all code on IL offset 0. + EP_ASSERT (sizeof (fixed_buffer) >= sizeof (uint32_t) * 2); + offset_entries = 1; + il_offsets = fixed_buffer; + native_offsets = il_offsets + offset_entries; + il_offsets [0] = 0; + native_offsets [0] = ji ? (uint32_t)ji->code_size : 0; + } + + FireEtwMethodILToNativeMap ( + method_id, + 0, + 0, + offset_entries, + il_offsets, + native_offsets, + clr_instance_get_id (), + NULL, + NULL); + + g_free (buffer); + } + + return true; +} + +bool +ep_rt_mono_write_event_method_load ( + MonoMethod *method, + MonoJitInfo *ji) +{ + if (!EventEnabledMethodLoad_V1 () && !EventEnabledMethodLoadVerbose_V1()) + return true; + + //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc. + if (method) { + uint64_t method_id = 0; + uint64_t module_id = 0; + uint64_t method_code_start = ji ? (uint64_t)ji->code_start : 0; + uint32_t method_code_size = ji ? (uint32_t)ji->code_size : 0; + uint32_t method_token = 0; + uint32_t method_flags = 0; + uint8_t kind = MONO_CLASS_DEF; + char *method_namespace = NULL; + const char *method_name = NULL; + char *method_signature = NULL; + bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE); + + method_id = (uint64_t)method; + + if (!method->dynamic) + method_token = method->token; + + if (ji && mono_jit_info_get_generic_sharing_context (ji)) { + method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD; + verbose = true; + } + + if (method->dynamic) { + method_flags |= METHOD_FLAGS_DYNAMIC_METHOD; + verbose = true; + } + + if (ji && !ji->from_aot && !ji->from_llvm) { + method_flags |= METHOD_FLAGS_JITTED_METHOD; + if (method->wrapper_type != MONO_WRAPPER_NONE) + method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD; + } + + if (method->is_generic || method->is_inflated) { + method_flags |= METHOD_FLAGS_GENERIC_METHOD; + verbose = true; + } + + if (method->klass) { + module_id = (uint64_t)m_class_get_image (method->klass); + kind = m_class_get_class_kind (method->klass); + if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST) + method_flags |= METHOD_FLAGS_GENERIC_METHOD; + } + + //TODO: SendMethodDetailsEvent + + if (verbose) { + method_name = method->name; + method_signature = mono_signature_full_name (method->signature); + + if (method->klass) + method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); + + FireEtwMethodLoadVerbose_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + + if (ji && (ji->from_aot || ji->from_llvm)) + FireEtwMethodLoadVerbose_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + } else { + FireEtwMethodLoad_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + clr_instance_get_id (), + NULL, + NULL); + + if (ji && (ji->from_aot || ji->from_llvm)) + FireEtwMethodLoad_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + clr_instance_get_id (), + NULL, + NULL); + } + + g_free (method_namespace); + g_free (method_signature); + } + + return true; +} + +bool +ep_rt_mono_write_event_module_load (MonoImage *image) +{ + if (!EventEnabledModuleLoad_V2 () && !EventEnabledDomainModuleLoad_V1()) + return true; + + if (image) { + // Under netcore we only have root domain. + MonoDomain *root_domain = mono_get_root_domain (); + + uint64_t domain_id = (uint64_t)root_domain; + uint64_t module_id = (uint64_t)image; + uint64_t assembly_id = (uint64_t)image->assembly; + + // TODO: Extract all module IL/Native paths and pdb metadata when available. + const char *module_il_path = ""; + const char *module_il_pdb_path = ""; + const char *module_native_path = ""; + const char *module_native_pdb_path = ""; + uint8_t signature [EP_GUID_SIZE] = { 0 }; + uint32_t module_il_pdb_age = 0; + uint32_t module_native_pdb_age = 0; + + uint32_t reserved_flags = 0; + + // Netcore has a 1:1 between assemblies and modules, so its always a manifest module. + uint32_t module_flags = MODULE_FLAGS_MANIFEST_MODULE; + if (image->dynamic) + module_flags |= MODULE_FLAGS_DYNAMIC_MODULE; + if (image->aot_module) + module_flags |= MODULE_FLAGS_NATIVE_MODULE; + + module_il_path = image->filename ? image->filename : ""; + + FireEtwModuleLoad_V2 ( + module_id, + assembly_id, + module_flags, + reserved_flags, + module_il_path, + module_native_path, + clr_instance_get_id (), + signature, + module_il_pdb_age, + module_il_pdb_path, + signature, + module_native_pdb_age, + module_native_pdb_path, + NULL, + NULL); + + FireEtwDomainModuleLoad_V1 ( + module_id, + assembly_id, + domain_id, + module_flags, + reserved_flags, + module_il_path, + module_native_path, + clr_instance_get_id (), + NULL, + NULL); + } + + return true; +} + +bool +ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly) +{ + if (!EventEnabledAssemblyLoad_V1 ()) + return true; + + if (assembly) { + // Under netcore we only have root domain. + MonoDomain *root_domain = mono_get_root_domain (); + + uint64_t domain_id = (uint64_t)root_domain; + uint64_t assembly_id = (uint64_t)assembly; + uint64_t binding_id = 0; + + uint32_t assembly_flags = 0; + if (assembly->dynamic) + assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY; + + if (assembly->image && assembly->image->aot_module) + assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY; + + char *assembly_name = mono_stringify_assembly_name (&assembly->aname); + + FireEtwAssemblyLoad_V1 ( + assembly_id, + domain_id, + binding_id, + assembly_flags, + assembly_name, + clr_instance_get_id (), + NULL, + NULL); + + g_free (assembly_name); + } + + return true; +} + +static +void +profiler_jit_begin ( + MonoProfiler *prof, + MonoMethod *method) +{ + ep_rt_mono_write_event_jit_start (method); +} + +static +void +profiler_jit_failed ( + MonoProfiler *prof, + MonoMethod *method) +{ + //TODO: CoreCLR doesn't have this case, so no failure event currently exists. +} + +static +void +profiler_jit_done ( + MonoProfiler *prof, + MonoMethod *method, + MonoJitInfo *ji) +{ + ep_rt_mono_write_event_method_load (method, ji); + ep_rt_mono_write_event_method_il_to_native_map (method, ji); +} + +static +void +profiler_image_loaded ( + MonoProfiler *prof, + MonoImage *image) +{ + if (image && image->heap_pdb.size == 0) + ep_rt_mono_write_event_module_load (image); +} + +static +void +profiler_assembly_loaded ( + MonoProfiler *prof, + MonoAssembly *assembly) +{ + ep_rt_mono_write_event_assembly_load (assembly); +} + +void +EventPipeEtwCallbackDotNETRuntime ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data) +{ + ep_rt_config_requires_lock_not_held (); + + EP_ASSERT(is_enabled == 0 || is_enabled == 1) ; + EP_ASSERT (_ep_rt_mono_profiler != NULL); + + EP_LOCK_ENTER (section1) + if (is_enabled == 1 && !MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled) { + // Add profiler callbacks for DotNETRuntime provider events. + mono_profiler_set_jit_begin_callback (_ep_rt_mono_profiler, profiler_jit_begin); + mono_profiler_set_jit_failed_callback (_ep_rt_mono_profiler, profiler_jit_failed); + mono_profiler_set_jit_done_callback (_ep_rt_mono_profiler, profiler_jit_done); + mono_profiler_set_image_loaded_callback (_ep_rt_mono_profiler, profiler_image_loaded); + mono_profiler_set_assembly_loaded_callback (_ep_rt_mono_profiler, profiler_assembly_loaded); + } else if (is_enabled == 0 && MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled) { + // Remove profiler callbacks for DotNETRuntime provider events. + mono_profiler_set_assembly_loaded_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_image_loaded_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_jit_done_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_jit_failed_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_jit_begin_callback (_ep_rt_mono_profiler, NULL); + } + EP_LOCK_EXIT (section1) + + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +void +EventPipeEtwCallbackDotNETRuntimeRundown ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data) +{ + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); +} + +void +EventPipeEtwCallbackDotNETRuntimePrivate ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data) +{ + MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); +} + +void +EventPipeEtwCallbackDotNETRuntimeStress ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data) +{ + MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); +} + #endif /* ENABLE_PERFTRACING */ MONO_EMPTY_SOURCE_FILE(eventpipe_rt_mono); diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h index 920f5b6c26b9f5..985e7d847a3c24 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-mono.h @@ -707,7 +707,8 @@ inline void ep_rt_provider_config_init (EventPipeProviderConfiguration *provider_config) { - ; + extern void ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config); + ep_rt_mono_provider_config_init (provider_config); } static @@ -724,7 +725,8 @@ inline bool ep_rt_providers_validate_all_disabled (void) { - return true; + extern bool ep_rt_mono_providers_validate_all_disabled (void); + return ep_rt_mono_providers_validate_all_disabled (); } static @@ -2144,5 +2146,69 @@ ep_rt_volatile_store_ptr_without_barrier ( bool ep_rt_mono_write_event_ee_startup_start (void); +bool +ep_rt_mono_write_event_jit_start (MonoMethod *method); + +bool +ep_rt_mono_write_event_method_il_to_native_map ( + MonoMethod *method, + MonoJitInfo *ji); + +bool +ep_rt_mono_write_event_method_load ( + MonoMethod *method, + MonoJitInfo *ji); + +bool +ep_rt_mono_write_event_module_load (MonoImage *image); + +bool +ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly); + +/* +* EventPipe provider callbacks. +*/ + +void +EventPipeEtwCallbackDotNETRuntime ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data); + +void +EventPipeEtwCallbackDotNETRuntimeRundown ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data); + +void +EventPipeEtwCallbackDotNETRuntimePrivate ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data); + +void +EventPipeEtwCallbackDotNETRuntimeStress ( + const uint8_t *source_id, + unsigned long is_enabled, + uint8_t level, + uint64_t match_any_keywords, + uint64_t match_all_keywords, + EventFilterDescriptor *filter_data, + void *callback_data); + + #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_RT_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/gen-eventing-event-inc.lst b/src/mono/mono/eventpipe/gen-eventing-event-inc.lst index b9945b13810fce..b80a674a65abd4 100644 --- a/src/mono/mono/eventpipe/gen-eventing-event-inc.lst +++ b/src/mono/mono/eventpipe/gen-eventing-event-inc.lst @@ -1,13 +1,20 @@ # Native runtime events supported by Mono runtime. -RuntimeInformationDCStart -RuntimeInformationDCStart AppDomainDCEnd_V1 -DCEndInit_V1 +AssemblyDCEnd_V1 +AssemblyLoad_V1 DCEndComplete_V1 +DCEndInit_V1 +DomainModuleDCEnd_V1 +DomainModuleLoad_V1 EEStartupStart_V1 MethodDCEndILToNativeMap +MethodDCEnd_V1 MethodDCEndVerbose_V1 -DomainModuleDCEnd_V1 -AssemblyDCEnd_V1 -ModuleDCEnd_V2 \ No newline at end of file +MethodILToNativeMap +MethodJittingStarted_V1 +MethodLoad_V1 +MethodLoadVerbose_V1 +ModuleDCEnd_V2 +ModuleLoad_V2 +RuntimeInformationDCStart diff --git a/src/mono/mono/eventpipe/test/ep-teardown-tests.c b/src/mono/mono/eventpipe/test/ep-teardown-tests.c index 8a074206c498f9..2d663a528bc186 100644 --- a/src/mono/mono/eventpipe/test/ep-teardown-tests.c +++ b/src/mono/mono/eventpipe/test/ep-teardown-tests.c @@ -3,6 +3,7 @@ #include #define TEST_FILE "./ep_test_create_file.txt" +#define TEST_FILE_2 "./ep_test_create_file_2.txt" extern MonoDomain *eventpipe_test_domain; @@ -12,6 +13,7 @@ test_teardown (void) if (eventpipe_test_domain) mono_jit_cleanup (eventpipe_test_domain); + unlink (TEST_FILE_2); unlink (TEST_FILE); return NULL; diff --git a/src/mono/mono/eventpipe/test/ep-tests.c b/src/mono/mono/eventpipe/test/ep-tests.c index b0e7803924551d..ce8ae4805d4e84 100644 --- a/src/mono/mono/eventpipe/test/ep-tests.c +++ b/src/mono/mono/eventpipe/test/ep-tests.c @@ -13,6 +13,7 @@ #define TEST_PROVIDER_NAME "MyTestProvider" #define TEST_FILE "./ep_test_create_file.txt" +#define TEST_FILE_2 "./ep_test_create_file_2.txt" //#define TEST_PERF @@ -379,6 +380,86 @@ test_enable_disable_default_provider_config (void) ep_exit_error_handler (); } +static RESULT +test_enable_disable_multiple_default_provider_config (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSessionID session_id_1 = 0; + EventPipeSessionID session_id_2 = 0; + + session_id_1 = ep_enable_2 ( + TEST_FILE, + 1, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + NULL); + + if (!session_id_1) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 2; + + result = validate_default_provider_config ((EventPipeSession *)session_id_1); + ep_raise_error_if_nok (result == NULL); + + test_location = 3; + + ep_start_streaming (session_id_1); + + if (!ep_enabled ()) { + result = FAILED ("event pipe disabled"); + ep_raise_error (); + } + + test_location = 4; + + session_id_2 = ep_enable_2 ( + TEST_FILE_2, + 1, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + NULL); + + if (!session_id_2) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 5; + + result = validate_default_provider_config ((EventPipeSession *)session_id_2); + ep_raise_error_if_nok (result == NULL); + + test_location = 6; + + ep_start_streaming (session_id_2); + + if (!ep_enabled ()) { + result = FAILED ("event pipe disabled"); + ep_raise_error (); + } + +ep_on_exit: + ep_disable (session_id_1); + ep_disable (session_id_2); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + static RESULT test_enable_disable_provider_config (void) { @@ -1327,6 +1408,7 @@ static Test ep_tests [] = { #endif {"test_eventpipe_mem_checkpoint", test_eventpipe_mem_checkpoint}, {"test_enable_disable_default_provider_config", test_enable_disable_default_provider_config}, + {"test_enable_disable_multiple_default_provider_config", test_enable_disable_multiple_default_provider_config}, {"test_enable_disable_provider_parse_default_config", test_enable_disable_provider_parse_default_config}, {"test_eventpipe_reset_mem_checkpoint", test_eventpipe_reset_mem_checkpoint}, {"test_eventpipe_teardown", test_eventpipe_teardown}, From 9e81f6d10900f2ba46d00395efb8184bcfc0ef2f Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Tue, 25 May 2021 11:16:32 +0200 Subject: [PATCH 101/115] make networking easier to debug with console (#53178) --- src/libraries/System.Net.Http/src/System.Net.Http.csproj | 2 +- src/libraries/System.Net.Quic/src/System.Net.Quic.csproj | 1 + .../System.Net.Security/src/System.Net.Security.csproj | 2 +- src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 3824e3fb25380c..cf6c743ce044b1 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -619,6 +619,7 @@ + @@ -644,7 +645,6 @@ - diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 9534d9212821d5..e1f29c77f0f322 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -46,6 +46,7 @@ + diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index abaec887591401..100115a0920a2c 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -408,6 +408,7 @@ + @@ -424,7 +425,6 @@ - diff --git a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj index e33132df5f2ee0..9f56ca5250a529 100644 --- a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj +++ b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj @@ -275,6 +275,7 @@ + From 138877544d970a12039dfffa0b161a1c6e77bb71 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 25 May 2021 08:22:40 -0400 Subject: [PATCH 102/115] Fix missing nullable enable in Microsoft.Extensions.Logging.Abstractions ref (#53199) --- .../ref/Microsoft.Extensions.Logging.Abstractions.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj index 905c8b20bbecc3..0086184386da10 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.csproj @@ -1,6 +1,7 @@ netstandard2.0;net461 + enable From ae88cc09912516d97a776db4e90cb51c8f350dcb Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Tue, 25 May 2021 15:49:29 +0200 Subject: [PATCH 103/115] Deterministic bundling issue 3601 (#52930) https://github.com/dotnet/runtime/issues/3601 Bundling should generate id based on the content in order to secure unique but reproducible ids --- .../Microsoft.NET.HostModel/Bundle/Bundler.cs | 2 +- .../Bundle/Manifest.cs | 40 +++++++++++++++-- .../BundlerConsistencyTests.cs | 44 +++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs index 83a6762129ec68..603ddbac7729ff 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs +++ b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs @@ -322,7 +322,7 @@ public string GenerateBundle(IReadOnlyList fileSpecs) { FileType targetType = Target.TargetSpecificFileType(type); (long startOffset, long compressedSize) = AddToBundle(bundle, file, targetType); - FileEntry entry = BundleManifest.AddEntry(targetType, relativePath, startOffset, file.Length, compressedSize, Target.BundleMajorVersion); + FileEntry entry = BundleManifest.AddEntry(targetType, file, relativePath, startOffset, compressedSize, Target.BundleMajorVersion); Tracer.Log($"Embed: {entry}"); } } diff --git a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs index 73e7b3b10fd243..5d58732cb7594c 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs +++ b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Cryptography; namespace Microsoft.NET.HostModel.Bundle { @@ -65,7 +66,10 @@ private enum HeaderFlags : ulong // identify this bundle. It is choosen to be compatible // with path-names so that the AppHost can use it in // extraction path. - public readonly string BundleID; + public string BundleID { get; private set; } + //Same as Path.GetRandomFileName + private const int BundleIdLength = 12; + private SHA256 bundleHash = SHA256.Create(); public readonly uint BundleMajorVersion; // The Minor version is currently unused, and is always zero public const uint BundleMinorVersion = 0; @@ -79,15 +83,23 @@ public Manifest(uint bundleMajorVersion, bool netcoreapp3CompatMode = false) { BundleMajorVersion = bundleMajorVersion; Files = new List(); - BundleID = Path.GetRandomFileName(); Flags = (netcoreapp3CompatMode) ? HeaderFlags.NetcoreApp3CompatMode : HeaderFlags.None; } - public FileEntry AddEntry(FileType type, string relativePath, long offset, long size, long compressedSize, uint bundleMajorVersion) + public FileEntry AddEntry(FileType type, FileStream fileContent, string relativePath, long offset, long compressedSize, uint bundleMajorVersion) { - FileEntry entry = new FileEntry(type, relativePath, offset, size, compressedSize, bundleMajorVersion); + if (bundleHash == null) + { + throw new InvalidOperationException("It is forbidden to change Manifest state after it was written or BundleId was obtained."); + } + + FileEntry entry = new FileEntry(type, relativePath, offset, fileContent.Length, compressedSize, bundleMajorVersion); Files.Add(entry); + fileContent.Position = 0; + byte[] hashBytes = ComputeSha256Hash(fileContent); + bundleHash.TransformBlock(hashBytes, 0, hashBytes.Length, hashBytes, 0); + switch (entry.Type) { case FileType.DepsJson: @@ -107,8 +119,28 @@ public FileEntry AddEntry(FileType type, string relativePath, long offset, long return entry; } + private static byte[] ComputeSha256Hash(Stream stream) + { + using (SHA256 sha = SHA256.Create()) + { + return sha.ComputeHash(stream); + } + } + + private string GenerateDeterministicId() + { + bundleHash.TransformFinalBlock(Array.Empty(), 0, 0); + byte[] manifestHash = bundleHash.Hash; + bundleHash.Dispose(); + bundleHash = null; + + return Convert.ToBase64String(manifestHash).Substring(BundleIdLength).Replace('/', '_'); + } + public long Write(BinaryWriter writer) { + BundleID = BundleID ?? GenerateDeterministicId(); + long startOffset = writer.BaseStream.Position; // Write the bundle header diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs index 75d9e44e961ccd..6a843806c2f177 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs @@ -144,6 +144,50 @@ public void TestWithCaseSensitiveDuplicateEntriesPasses() bundler.BundleManifest.Files.Where(entry => entry.RelativePath.Equals("rel/app.Repeat.dll")).Single().Type.Should().Be(FileType.Assembly); } + private (string bundleFileName, string bundleId) CreateSampleBundle(bool bundleMultipleFiles) + { + var fixture = sharedTestState.TestFixture.Copy(); + + var hostName = BundleHelper.GetHostName(fixture); + var bundleDir = Directory.CreateDirectory( + Path.Combine(BundleHelper.GetBundleDir(fixture).FullName, Path.GetRandomFileName())); + var targetOS = BundleHelper.GetTargetOS(fixture.CurrentRid); + var targetArch = BundleHelper.GetTargetArch(fixture.CurrentRid); + + var fileSpecs = new List(); + fileSpecs.Add(new FileSpec(BundleHelper.GetHostPath(fixture), BundleHelper.GetHostName(fixture))); + if (bundleMultipleFiles) + { + fileSpecs.Add(new FileSpec(BundleHelper.GetAppPath(fixture), "rel/app.repeat.dll")); + } + + Bundler bundler = new Bundler(hostName, bundleDir.FullName, targetOS: targetOS, targetArch: targetArch); + return (bundler.GenerateBundle(fileSpecs), bundler.BundleManifest.BundleID); + } + + [Fact] + public void TestWithIdenticalBundlesShouldBeBinaryEqualPasses() + { + var firstBundle = CreateSampleBundle(true); + byte[] firstBundleContent = File.ReadAllBytes(firstBundle.bundleFileName); + var secondBundle = CreateSampleBundle(true); + byte[] secondBundleContent = File.ReadAllBytes(secondBundle.bundleFileName); + + firstBundle.bundleId.ShouldBeEquivalentTo(secondBundle.bundleId, + "Deterministic/Reproducible build should produce identical bundle id for identical inputs"); + firstBundleContent.ShouldBeEquivalentTo(secondBundleContent, + "Deterministic/Reproducible build should produce identical binary for identical inputs"); + } + + [Fact] + public void TestWithUniqueBundlesShouldHaveUniqueBundleIdsPasses() + { + string firstBundle = CreateSampleBundle(true).bundleId; + string secondBundle = CreateSampleBundle(false).bundleId; + + Assert.NotEqual(firstBundle, secondBundle, StringComparer.Ordinal); + } + [Fact] public void TestWithMultipleDuplicateEntriesFails() { From 60c0b909b120345d67d6e0086c158bb3cbaaf7c4 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 25 May 2021 10:30:35 -0400 Subject: [PATCH 104/115] [Android] Revert arm and arm64 device PR runs (#53210) We're still having capacity issues even after doubling the number of devices. Only run device tests on the rolling build for the time being. Co-authored-by: Steve Pfister --- eng/pipelines/runtime-staging.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index 2abbda21953ae3..384af6fbef1c88 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -162,16 +162,19 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), eq(variables['isFullMatrix'], true)) - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - condition: >- - or( - eq(variables['librariesContainsChange'], true), - eq(variables['monoContainsChange'], true), - eq(variables['isFullMatrix'], true)) + + # don't run tests on PRs until we can get significantly more devices + ${{ if eq(variables['isFullMatrix'], true) }}: + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isFullMatrix'], true)) # # Build the whole product using Mono and run libraries tests From d8efff256db64683ac9f7f0f3543e68710f1fb1e Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 25 May 2021 08:02:16 -0700 Subject: [PATCH 105/115] Integrate selected changes from nativeaot branch (#53185) - More code sharing for System.Exception - Some support for default interface methods - Move callling convention helpers around to avoid duplication - Unify Environment.StackTrace --- .../src/System/Environment.CoreCLR.cs | 6 -- .../src/System/Exception.CoreCLR.cs | 46 +----------- .../tools/Common/Compiler/TypeExtensions.cs | 59 +++++++++++++++ .../Common/JitInterface/CallConvHelper.cs | 42 ----------- .../tools/Common/JitInterface/CorInfoImpl.cs | 13 ++-- .../Common/MetadataVirtualMethodAlgorithm.cs | 74 +++++++++++++++++++ .../TypeSystem/Common/TypeSystemHelpers.cs | 5 ++ .../Common/VirtualMethodAlgorithm.cs | 25 +++++++ .../TypeSystem/Interop/CallConvHelpers.cs} | 59 ++++++++------- .../ILCompiler.ReadyToRun.csproj | 9 +-- .../TestUtilities/System/PlatformDetection.cs | 2 +- .../System/Diagnostics/Tracing/EventSource.cs | 2 + .../src/System/Environment.cs | 7 ++ .../src/System/Exception.cs | 44 +++++++++++ .../System/Runtime/InteropServices/Marshal.cs | 32 +++++++- .../src/System/Environment.Mono.cs | 6 -- .../src/System/Exception.Mono.cs | 43 +---------- 17 files changed, 296 insertions(+), 178 deletions(-) delete mode 100644 src/coreclr/tools/Common/JitInterface/CallConvHelper.cs rename src/coreclr/tools/{aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs => Common/TypeSystem/Interop/CallConvHelpers.cs} (57%) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs index b375cfddc7ba50..56ac1ec84dfa8b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs @@ -90,12 +90,6 @@ public static string[] GetCommandLineArgs() // Used by VM internal static string? GetResourceStringLocal(string key) => SR.GetResourceString(key); - public static string StackTrace - { - [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts - get => new StackTrace(true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); - } - /// Gets the number of milliseconds elapsed since the system started. /// A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started. public static extern int TickCount diff --git a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs index 2be63740dc34c5..8a0c9402cb54cd 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs @@ -85,35 +85,6 @@ public MethodBase? TargetSite } } - // Returns the stack trace as a string. If no stack trace is - // available, null is returned. - public virtual string? StackTrace - { - get - { - string? stackTraceString = _stackTraceString; - string? remoteStackTraceString = _remoteStackTraceString; - - // if no stack trace, try to get one - if (stackTraceString != null) - { - return remoteStackTraceString + stackTraceString; - } - if (_stackTrace == null) - { - return remoteStackTraceString; - } - - return remoteStackTraceString + GetStackTrace(); - } - } - - private string GetStackTrace() - { - // Do not include a trailing newline for backwards compatibility - return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); - } - private string? CreateSourceName() { StackTrace st = new StackTrace(this, fNeedFileInfo: false); @@ -243,22 +214,9 @@ internal void RestoreDispatchState(in DispatchState dispatchState) // See src\inc\corexcep.h's EXCEPTION_COMPLUS definition: private const int _COMPlusExceptionCode = unchecked((int)0xe0434352); // Win32 exception code for COM+ exceptions - private object? SerializationWatsonBuckets => _watsonBuckets; - - private string? SerializationStackTraceString - { - get - { - string? stackTraceString = _stackTraceString; + private bool HasBeenThrown => _stackTrace != null; - if (stackTraceString == null && _stackTrace != null) - { - stackTraceString = GetStackTrace(); - } - - return stackTraceString; - } - } + private object? SerializationWatsonBuckets => _watsonBuckets; // This piece of infrastructure exists to help avoid deadlocks // between parts of CoreLib that might throw an exception while diff --git a/src/coreclr/tools/Common/Compiler/TypeExtensions.cs b/src/coreclr/tools/Common/Compiler/TypeExtensions.cs index c9418961afd9bb..428ca4b1d13977 100644 --- a/src/coreclr/tools/Common/Compiler/TypeExtensions.cs +++ b/src/coreclr/tools/Common/Compiler/TypeExtensions.cs @@ -199,6 +199,42 @@ public static bool IsGenericDepthGreaterThan(this TypeDesc type, int depth) return false; } + /// + /// What is the maximum number of steps that need to be taken from this type to its most contained generic type. + /// i.e. + /// SomeGenericType<System.Int32>.Method<System.Int32> => 1 + /// SomeType.Method<System.Int32> => 0 + /// SomeType.Method<List<System.Int32>> => 1 + /// + public static int GetGenericDepth(this MethodDesc method) + { + int genericDepth = method.OwningType.GetGenericDepth(); + foreach (TypeDesc type in method.Instantiation) + { + genericDepth = Math.Max(genericDepth, type.GetGenericDepth()); + } + return genericDepth; + } + + /// + /// Determine if a type has a generic depth greater than a given value + /// + /// + /// + public static bool IsGenericDepthGreaterThan(this MethodDesc method, int depth) + { + if (method.OwningType.IsGenericDepthGreaterThan(depth)) + return true; + + foreach (TypeDesc type in method.Instantiation) + { + if (type.IsGenericDepthGreaterThan(depth)) + return true; + } + + return false; + } + /// /// Determines whether an array type does implements the generic collection interfaces. This is the case /// for multi-dimensional arrays, and arrays of pointers. @@ -508,5 +544,28 @@ public static bool IsNonVersionable(this MetadataType type) { return type.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute"); } + + /// + /// Return true when the method is marked as non-versionable. Non-versionable methods + /// may be freely inlined into ReadyToRun images even when they don't reside in the + /// same version bubble as the module being compiled. + /// + /// Method to check + /// True when the method is marked as non-versionable, false otherwise. + public static bool IsNonVersionable(this MethodDesc method) + { + return method.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute"); + } + + /// + /// Returns true if is an actual native entrypoint. + /// There's a distinction between when a method reports it's a PInvoke in the metadata + /// versus how it's treated in the compiler. For many PInvoke methods the compiler will generate + /// an IL body. The methods with an IL method body shouldn't be treated as PInvoke within the compiler. + /// + public static bool IsRawPInvoke(this MethodDesc method) + { + return method.IsPInvoke && (method is Internal.IL.Stubs.PInvokeTargetNativeMethod); + } } } diff --git a/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs b/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs deleted file mode 100644 index ad92b5b36e34c1..00000000000000 --- a/src/coreclr/tools/Common/JitInterface/CallConvHelper.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Reflection.Metadata; - -using Internal.TypeSystem; - -namespace Internal.JitInterface -{ - internal static unsafe class CallConvHelper - { - internal static IEnumerable EnumerateCallConvsFromAttribute(CustomAttributeValue attributeWithCallConvsArray) - { - ImmutableArray> callConvArray = default; - foreach (var arg in attributeWithCallConvsArray.NamedArguments) - { - if (arg.Name == "CallConvs") - { - callConvArray = (ImmutableArray>)arg.Value; - } - } - - // No calling convention was specified in the attribute - if (callConvArray.IsDefault) - yield break; - - foreach (CustomAttributeTypedArgument type in callConvArray) - { - if (!(type.Value is DefType defType)) - continue; - - if (defType.Namespace != "System.Runtime.CompilerServices") - continue; - - yield return defType; - } - } - } -} diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index d0cd0f7bc069f3..8ec87f59d4a113 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -646,7 +646,7 @@ private CorInfoCallConvExtension GetUnmanagedCallingConventionFromAttribute(Cust bool found = false; bool memberFunctionVariant = false; - foreach (DefType defType in CallConvHelper.EnumerateCallConvsFromAttribute(attributeWithCallConvsArray)) + foreach (DefType defType in attributeWithCallConvsArray.EnumerateCallConvsFromAttribute()) { if (defType.Name == "CallConvMemberFunction") { @@ -1371,7 +1371,7 @@ private static object ResolveTokenInScope(MethodIL methodIL, object typeOrMethod if (typeOrMethodContext is TypeDesc typeContext) { - Debug.Assert(typeContext.HasSameTypeDefinition(owningMethod.OwningType)); + Debug.Assert(typeContext.HasSameTypeDefinition(owningMethod.OwningType) || typeContext.IsArray); typeInst = typeContext.Instantiation; } else @@ -3484,7 +3484,7 @@ private PgoSchemaElem[] getPgoInstrumentationResults(MethodDesc method) return _compilation.ProfileData[method]?.SchemaData; } - public static void ComputeJitPgoInstrumentationSchema(Func objectToHandle, PgoSchemaElem[] pgoResultsSchemas, out PgoInstrumentationSchema[] nativeSchemas, out byte[] instrumentationData) + public static void ComputeJitPgoInstrumentationSchema(Func objectToHandle, PgoSchemaElem[] pgoResultsSchemas, out PgoInstrumentationSchema[] nativeSchemas, out byte[] instrumentationData, Func typeFilter = null) { nativeSchemas = new PgoInstrumentationSchema[pgoResultsSchemas.Length]; MemoryStream msInstrumentationData = new MemoryStream(); @@ -3524,9 +3524,12 @@ public static void ComputeJitPgoInstrumentationSchema(Func objec { foreach (TypeSystemEntityOrUnknown typeVal in typeArray) { - IntPtr ptrVal = IntPtr.Zero; - if (typeVal.AsType != null) + IntPtr ptrVal; + + if (typeVal.AsType != null && (typeFilter == null || typeFilter(typeVal.AsType))) + { ptrVal = (IntPtr)objectToHandle(typeVal.AsType); + } else { // The "Unknown types are the values from 1-33 diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs index a14d558df03612..a3af0aa5faa272 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs @@ -586,6 +586,9 @@ public override MethodDesc ResolveVariantInterfaceMethodToVirtualMethodOnType(Me // See current interface call resolution for details on how that happens. private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType) { + if (currentType.IsInterface) + return null; + MethodDesc methodImpl = FindImplFromDeclFromMethodImpls(currentType, interfaceMethod); if (methodImpl != null) return methodImpl; @@ -723,6 +726,77 @@ private static MethodDesc FindNameSigOverrideForInterfaceMethodRecursive(MethodD } } + public override DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, TypeDesc currentType, out MethodDesc impl) + { + return ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, (MetadataType)currentType, out impl); + } + + private static DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, MetadataType currentType, out MethodDesc impl) + { + TypeDesc interfaceMethodOwningType = interfaceMethod.OwningType; + MetadataType mostSpecificInterface = null; + bool diamondCase = false; + impl = null; + + foreach (MetadataType runtimeInterface in currentType.RuntimeInterfaces) + { + if (runtimeInterface == interfaceMethodOwningType) + { + // Also consider the default interface method implementation on the interface itself + // if we don't have anything else yet + if (mostSpecificInterface == null && !interfaceMethod.IsAbstract) + { + mostSpecificInterface = runtimeInterface; + impl = interfaceMethod; + } + } + else if (Array.IndexOf(runtimeInterface.RuntimeInterfaces, interfaceMethodOwningType) != -1) + { + // This interface might provide a default implementation + MethodImplRecord[] possibleImpls = runtimeInterface.FindMethodsImplWithMatchingDeclName(interfaceMethod.Name); + if (possibleImpls != null) + { + foreach (MethodImplRecord implRecord in possibleImpls) + { + if (implRecord.Decl == interfaceMethod) + { + // This interface provides a default implementation. + // Is it also most specific? + if (mostSpecificInterface == null || Array.IndexOf(runtimeInterface.RuntimeInterfaces, mostSpecificInterface) != -1) + { + mostSpecificInterface = runtimeInterface; + impl = implRecord.Body; + diamondCase = false; + } + else if (Array.IndexOf(mostSpecificInterface.RuntimeInterfaces, runtimeInterface) == -1) + { + diamondCase = true; + } + + break; + } + } + } + } + } + + if (diamondCase) + { + impl = null; + return DefaultInterfaceMethodResolution.Diamond; + } + else if (impl == null) + { + return DefaultInterfaceMethodResolution.None; + } + else if (impl.IsAbstract) + { + return DefaultInterfaceMethodResolution.Reabstraction; + } + + return DefaultInterfaceMethodResolution.DefaultImplementation; + } + public override IEnumerable ComputeAllVirtualSlots(TypeDesc type) { return EnumAllVirtualSlots((MetadataType)type); diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs index 75a95154f66d60..76bb19921aaeab 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs @@ -280,6 +280,11 @@ public static MethodDesc ResolveVariantInterfaceMethodToVirtualMethodOnType(this return type.Context.GetVirtualMethodAlgorithmForType(type).ResolveVariantInterfaceMethodToVirtualMethodOnType(interfaceMethod, type); } + public static DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(this TypeDesc type, MethodDesc interfaceMethod, out MethodDesc implMethod) + { + return type.Context.GetVirtualMethodAlgorithmForType(type).ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, type, out implMethod); + } + /// /// Resolves a virtual method call. /// diff --git a/src/coreclr/tools/Common/TypeSystem/Common/VirtualMethodAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/VirtualMethodAlgorithm.cs index 2ccf630949362b..e13e61d3862da6 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/VirtualMethodAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/VirtualMethodAlgorithm.cs @@ -24,6 +24,8 @@ public abstract class VirtualMethodAlgorithm public abstract MethodDesc ResolveVariantInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, TypeDesc currentType); + public abstract DefaultInterfaceMethodResolution ResolveInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, TypeDesc currentType, out MethodDesc impl); + /// /// Resolves a virtual method call. /// @@ -34,4 +36,27 @@ public abstract class VirtualMethodAlgorithm /// public abstract IEnumerable ComputeAllVirtualSlots(TypeDesc type); } + + public enum DefaultInterfaceMethodResolution + { + /// + /// No default implementation was found. + /// + None, + + /// + /// A default implementation was found. + /// + DefaultImplementation, + + /// + /// The implementation was reabstracted. + /// + Reabstraction, + + /// + /// The default implementation conflicts. + /// + Diamond, + } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs b/src/coreclr/tools/Common/TypeSystem/Interop/CallConvHelpers.cs similarity index 57% rename from src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs rename to src/coreclr/tools/Common/TypeSystem/Interop/CallConvHelpers.cs index f9b363778a6b04..91a4d0c8da778b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/CallConvHelpers.cs @@ -1,26 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Internal.TypeSystem; -using Internal.TypeSystem.Ecma; +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Reflection.Metadata; -using Debug = System.Diagnostics.Debug; +using Internal.TypeSystem.Ecma; -namespace ILCompiler +namespace Internal.TypeSystem { - static class MethodExtensions + internal static unsafe class CallConvHelpers { - /// - /// Returns true if is an actual native entrypoint. - /// There's a distinction between when a method reports it's a PInvoke in the metadata - /// versus how it's treated in the compiler. For many PInvoke methods the compiler will generate - /// an IL body. The methods with an IL method body shouldn't be treated as PInvoke within the compiler. - /// - public static bool IsRawPInvoke(this MethodDesc method) - { - return method.IsPInvoke && (method is Internal.IL.Stubs.PInvokeTargetNativeMethod); - } - /// /// Gets a value indicating whether the method has the SuppressGCTransition attribute /// @@ -58,7 +50,7 @@ public static bool IsSuppressGCTransition(this MethodDesc method) if (unmanagedCallConvAttribute == null) return false; - foreach (DefType defType in Internal.JitInterface.CallConvHelper.EnumerateCallConvsFromAttribute(unmanagedCallConvAttribute.Value)) + foreach (DefType defType in unmanagedCallConvAttribute.Value.EnumerateCallConvsFromAttribute()) { if (defType.Name == "CallConvSuppressGCTransition") { @@ -69,16 +61,31 @@ public static bool IsSuppressGCTransition(this MethodDesc method) return false; } - /// - /// Return true when the method is marked as non-versionable. Non-versionable methods - /// may be freely inlined into ReadyToRun images even when they don't reside in the - /// same version bubble as the module being compiled. - /// - /// Method to check - /// True when the method is marked as non-versionable, false otherwise. - public static bool IsNonVersionable(this MethodDesc method) + public static IEnumerable EnumerateCallConvsFromAttribute(this CustomAttributeValue attributeWithCallConvsArray) { - return method.HasCustomAttribute("System.Runtime.Versioning", "NonVersionableAttribute"); + ImmutableArray> callConvArray = default; + foreach (var arg in attributeWithCallConvsArray.NamedArguments) + { + if (arg.Name == "CallConvs") + { + callConvArray = (ImmutableArray>)arg.Value; + } + } + + // No calling convention was specified in the attribute + if (callConvArray.IsDefault) + yield break; + + foreach (CustomAttributeTypedArgument type in callConvArray) + { + if (!(type.Value is DefType defType)) + continue; + + if (defType.Namespace != "System.Runtime.CompilerServices") + continue; + + yield return defType; + } } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 6299418227bde3..bedb1ce62e3a8f 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -1,4 +1,4 @@ - + Library ILCompiler.ReadyToRun @@ -186,7 +186,6 @@ - @@ -245,12 +244,12 @@ IL\HelperExtensions.cs + + Interop\CallConvHelpers.cs + JitInterface\TypeString.cs - - JitInterface\CallConvHelper.cs - JitInterface\CorInfoBase.cs diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index ecf16031fe9dba..c30fbb254733a5 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -245,7 +245,7 @@ private static Version GetICUVersion() int version = 0; try { - Type interopGlobalization = Type.GetType("Interop+Globalization"); + Type interopGlobalization = Type.GetType("Interop+Globalization, System.Private.CoreLib"); if (interopGlobalization != null) { MethodInfo methodInfo = interopGlobalization.GetMethod("GetICUVersion", BindingFlags.NonPublic | BindingFlags.Static); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index 919839f0d42fbb..321d60de739b32 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -3657,6 +3657,7 @@ private static void DebugCheckEvent(ref Dictionary? eventsByName #endif private static int GetHelperCallFirstArg(MethodInfo method) { +#if !CORERT // Currently searches for the following pattern // // ... // CAN ONLY BE THE INSTRUCTIONS BELOW @@ -3773,6 +3774,7 @@ private static int GetHelperCallFirstArg(MethodInfo method) } idx++; } +#endif return -1; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 15e19465cae31d..6c6c8ced629d03 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Diagnostics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Threading; namespace System @@ -203,6 +204,12 @@ public static Version Version } } + public static string StackTrace + { + [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts + get => new StackTrace(true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); + } + private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget target) { Debug.Assert(target != EnvironmentVariableTarget.Process); diff --git a/src/libraries/System.Private.CoreLib/src/System/Exception.cs b/src/libraries/System.Private.CoreLib/src/System/Exception.cs index 3db9eb77fd5e25..a6760916f93061 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Exception.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Exception.cs @@ -201,6 +201,35 @@ public int HResult partial void RestoreRemoteStackTrace(SerializationInfo info, StreamingContext context); + // Returns the stack trace as a string. If no stack trace is + // available, null is returned. + public virtual string? StackTrace + { + get + { + string? stackTraceString = _stackTraceString; + string? remoteStackTraceString = _remoteStackTraceString; + + // if no stack trace, try to get one + if (stackTraceString != null) + { + return remoteStackTraceString + stackTraceString; + } + if (!HasBeenThrown) + { + return remoteStackTraceString; + } + + return remoteStackTraceString + GetStackTrace(); + } + } + + private string GetStackTrace() + { + // Do not include a trailing newline for backwards compatibility + return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); + } + [StackTraceHidden] internal void SetCurrentStackTrace() { @@ -229,5 +258,20 @@ internal void SetRemoteStackTrace(string stackTrace) // would have generated. _remoteStackTraceString = stackTrace + Environment.NewLineConst + SR.Exception_EndStackTraceFromPreviousThrow + Environment.NewLineConst; } + + private string? SerializationStackTraceString + { + get + { + string? stackTraceString = _stackTraceString; + + if (stackTraceString == null && HasBeenThrown) + { + stackTraceString = GetStackTrace(); + } + + return stackTraceString; + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs index 64269561d7e016..6b0838fc691182 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs @@ -142,7 +142,16 @@ public static int SizeOf(Type t) return SizeOfHelper(t, throwIfNotMarshalable: true); } - public static int SizeOf() => SizeOf(typeof(T)); + public static int SizeOf() + { + Type t = typeof(T); + if (t.IsGenericType) + { + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(T)); + } + + return SizeOfHelper(t, throwIfNotMarshalable: true); + } public static unsafe int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv) { @@ -1153,7 +1162,26 @@ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) public static TDelegate GetDelegateForFunctionPointer(IntPtr ptr) { - return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate)); + if (ptr == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(ptr)); + } + + Type t = typeof(TDelegate); + if (t.IsGenericType) + { + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(TDelegate)); + } + + // For backward compatibility, we allow lookup of existing delegate to + // function pointer mappings using abstract MulticastDelegate type. We will check + // for the non-abstract delegate type later if no existing mapping is found. + if (t.BaseType != typeof(MulticastDelegate) && t != typeof(MulticastDelegate)) + { + throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(TDelegate)); + } + + return (TDelegate)(object)GetDelegateForFunctionPointerInternal(ptr, t); } public static IntPtr GetFunctionPointerForDelegate(Delegate d) diff --git a/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs index 69c6bf09ab2dd0..43350fe683f2b2 100644 --- a/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Environment.Mono.cs @@ -24,12 +24,6 @@ public static extern int ExitCode [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int GetProcessorCount(); - public static string StackTrace - { - [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts - get => new StackTrace(true).ToString(Diagnostics.StackTrace.TraceFormat.Normal); - } - public static extern int TickCount { [MethodImplAttribute(MethodImplOptions.InternalCall)] diff --git a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs index 8924a9bfd5b9a8..a8fda176114d66 100644 --- a/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs @@ -46,6 +46,8 @@ public DispatchState(MonoStackFrame[]? stackFrames) private int caught_in_unmanaged; #endregion + private bool HasBeenThrown => _traceIPs != null; + public MethodBase? TargetSite { get @@ -58,32 +60,6 @@ public MethodBase? TargetSite } } - public virtual string? StackTrace - { - get - { - string? stackTraceString = _stackTraceString; - string? remoteStackTraceString = _remoteStackTraceString; - - if (stackTraceString != null) - { - return remoteStackTraceString + stackTraceString; - } - if (_traceIPs == null) - { - return remoteStackTraceString; - } - - return remoteStackTraceString + GetStackTrace(); - } - } - - private string GetStackTrace() - { - // Do not include a trailing newline for backwards compatibility - return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); - } - internal DispatchState CaptureDispatchState() { MonoStackFrame[]? stackFrames; @@ -160,20 +136,5 @@ private bool CanSetRemoteStackTrace() private static IDictionary CreateDataContainer() => new ListDictionaryInternal(); private static string? SerializationWatsonBuckets => null; - - private string? SerializationStackTraceString - { - get - { - string? stackTraceString = _stackTraceString; - - if (stackTraceString == null && _traceIPs != null) - { - stackTraceString = GetStackTrace(); - } - - return stackTraceString; - } - } } } From 1e5199b30946963227bd5238838e38e07775d1b3 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 25 May 2021 08:15:39 -0700 Subject: [PATCH 106/115] Cleanup internal ComWrappers cache when object enters Finalization queue (#52771) * Clean up the ExternalObjectContext cache for ComWrappers' RCWs. * Add testing for verifying internal cache clean up. --- src/coreclr/interop/comwrappers.cpp | 5 +- src/coreclr/vm/gcenv.ee.cpp | 6 +- src/coreclr/vm/interoplibinterface.cpp | 68 +++++++++++++++++++ src/coreclr/vm/interoplibinterface.h | 11 ++- src/coreclr/vm/interoplibinterface_shared.cpp | 19 ++++-- .../Interop/COM/ComWrappers/API/Program.cs | 51 ++++++++++++++ src/tests/Interop/COM/ComWrappers/Common.cs | 11 ++- 7 files changed, 158 insertions(+), 13 deletions(-) diff --git a/src/coreclr/interop/comwrappers.cpp b/src/coreclr/interop/comwrappers.cpp index 8485125c8b76e7..90c366cead4b9b 100644 --- a/src/coreclr/interop/comwrappers.cpp +++ b/src/coreclr/interop/comwrappers.cpp @@ -357,7 +357,8 @@ ManagedObjectWrapper* ManagedObjectWrapper::MapFromIUnknown(_In_ IUnknown* pUnk) // If the first Vtable entry is part of the ManagedObjectWrapper IUnknown impl, // we know how to interpret the IUnknown. void** vtable = *reinterpret_cast(pUnk); - if (*vtable != ManagedObjectWrapper_IUnknownImpl.QueryInterface) + if (*vtable != ManagedObjectWrapper_IUnknownImpl.QueryInterface + && *vtable != ManagedObjectWrapper_IReferenceTrackerTargetImpl.QueryInterface) return nullptr; ABI::ComInterfaceDispatch* disp = reinterpret_cast(pUnk); @@ -841,7 +842,7 @@ void* NativeObjectWrapperContext::GetRuntimeContext() const noexcept IReferenceTracker* NativeObjectWrapperContext::GetReferenceTracker() const noexcept { - return ((_trackerObjectState == TrackerObjectState::NotSet) ? nullptr : _trackerObject); + return ((_trackerObjectState == TrackerObjectState::NotSet || _trackerObjectDisconnected) ? nullptr : _trackerObject); } // See TrackerObjectManager::AfterWrapperCreated() for AddRefFromTrackerSource() usage. diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index 650e91247f9a48..4df3e3ae1cb53a 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -66,8 +66,7 @@ void GCToEEInterface::BeforeGcScanRoots(int condemned, bool is_bgc, bool is_conc } #endif // VERIFY_HEAP - if (!is_concurrent) - Interop::OnBeforeGCScanRoots(); + Interop::OnBeforeGCScanRoots(is_concurrent); } //EE can perform post stack scanning action, while the @@ -88,8 +87,7 @@ VOID GCToEEInterface::AfterGcScanRoots (int condemned, int max_gen, ::GetAppDomain()->DetachRCWs(); #endif // FEATURE_COMINTEROP - if (!sc->concurrent) - Interop::OnAfterGCScanRoots(); + Interop::OnAfterGCScanRoots(sc->concurrent); } /* diff --git a/src/coreclr/vm/interoplibinterface.cpp b/src/coreclr/vm/interoplibinterface.cpp index f8804e32d25980..b027d6b9d4bbdc 100644 --- a/src/coreclr/vm/interoplibinterface.cpp +++ b/src/coreclr/vm/interoplibinterface.cpp @@ -30,9 +30,16 @@ namespace enum { Flags_None = 0, + + // The EOC has been collected and is no longer visible from managed code. Flags_Collected = 1, + Flags_ReferenceTracker = 2, Flags_InCache = 4, + + // The EOC is "detached" and no longer used to map between identity and a managed object. + // This will only be set if the EOC was inserted into the cache. + Flags_Detached = 8, }; DWORD Flags; @@ -80,6 +87,17 @@ namespace Flags |= Flags_Collected; } + void MarkDetached() + { + _ASSERTE(GCHeapUtilities::IsGCInProgress()); + Flags |= Flags_Detached; + } + + void MarkNotInCache() + { + ::InterlockedAnd((LONG*)&Flags, (~Flags_InCache)); + } + OBJECTREF GetObjectRef() { CONTRACTL @@ -428,6 +446,32 @@ namespace _hashMap.Remove(cxt->GetKey()); } + + void DetachNotPromotedEOCs() + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + PRECONDITION(GCHeapUtilities::IsGCInProgress()); // GC is in progress and the runtime is suspended + } + CONTRACTL_END; + + Iterator curr = _hashMap.Begin(); + Iterator end = _hashMap.End(); + + ExternalObjectContext* cxt; + for (; curr != end; ++curr) + { + cxt = *curr; + if (!cxt->IsSet(ExternalObjectContext::Flags_Detached) + && !GCHeapUtilities::GetGCHeap()->IsPromoted(OBJECTREFToObject(cxt->GetObjectRef()))) + { + cxt->MarkDetached(); + } + } + } }; // Global instance of the external object cache @@ -727,6 +771,15 @@ namespace handle = handleLocal; } } + else if (extObjCxt != NULL && extObjCxt->IsSet(ExternalObjectContext::Flags_Detached)) + { + // If an EOC has been found but is marked detached, then we will remove it from the + // cache here instead of letting the GC do it later and pretend like it wasn't found. + STRESS_LOG1(LF_INTEROP, LL_INFO10, "Detached EOC requested: 0x%p\n", extObjCxt); + cache->Remove(extObjCxt); + extObjCxt->MarkNotInCache(); + extObjCxt = NULL; + } } STRESS_LOG2(LF_INTEROP, LL_INFO1000, "EOC: 0x%p or Handle: 0x%p\n", extObjCxt, handle); @@ -1796,4 +1849,19 @@ void ComWrappersNative::OnFullGCFinished() } } +void ComWrappersNative::AfterRefCountedHandleCallbacks() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + ExtObjCxtCache* cache = ExtObjCxtCache::GetInstanceNoThrow(); + if (cache != NULL) + cache->DetachNotPromotedEOCs(); +} + #endif // FEATURE_COMWRAPPERS diff --git a/src/coreclr/vm/interoplibinterface.h b/src/coreclr/vm/interoplibinterface.h index 28139dbbee6634..367b419e2a3342 100644 --- a/src/coreclr/vm/interoplibinterface.h +++ b/src/coreclr/vm/interoplibinterface.h @@ -63,6 +63,7 @@ class ComWrappersNative public: // GC interaction static void OnFullGCStarted(); static void OnFullGCFinished(); + static void AfterRefCountedHandleCallbacks(); }; class GlobalComWrappersForMarshalling @@ -181,13 +182,19 @@ class Interop _Outptr_ void** context); // Notify started/finished when GC is running. + // These methods are called in a blocking fashion when a + // GC of generation is started. These calls may overlap + // so care must be taken when taking locks. static void OnGCStarted(_In_ int nCondemnedGeneration); static void OnGCFinished(_In_ int nCondemnedGeneration); // Notify before/after when GC is scanning roots. // Present assumption is that calls will never be nested. - static void OnBeforeGCScanRoots(); - static void OnAfterGCScanRoots(); + // The input indicates if the call is from a concurrent GC + // thread or not. These will be nested within OnGCStarted + // and OnGCFinished. + static void OnBeforeGCScanRoots(_In_ bool isConcurrent); + static void OnAfterGCScanRoots(_In_ bool isConcurrent); }; #endif // _INTEROPLIBINTERFACE_H_ diff --git a/src/coreclr/vm/interoplibinterface_shared.cpp b/src/coreclr/vm/interoplibinterface_shared.cpp index 19ee32f2585456..f31b128e47cfb1 100644 --- a/src/coreclr/vm/interoplibinterface_shared.cpp +++ b/src/coreclr/vm/interoplibinterface_shared.cpp @@ -116,7 +116,7 @@ void Interop::OnGCFinished(_In_ int nCondemnedGeneration) } } -void Interop::OnBeforeGCScanRoots() +void Interop::OnBeforeGCScanRoots(_In_ bool isConcurrent) { CONTRACTL { @@ -126,11 +126,16 @@ void Interop::OnBeforeGCScanRoots() CONTRACTL_END; #ifdef FEATURE_OBJCMARSHAL - ObjCMarshalNative::BeforeRefCountedHandleCallbacks(); + // The Objective-C interop begin/end for reference counted + // handles only occurs in non-concurrent scenarios. This contract + // is because of the potential for locking as a synchronization + // mechanism for Objective-C lifetime management. + if (!isConcurrent) + ObjCMarshalNative::BeforeRefCountedHandleCallbacks(); #endif // FEATURE_OBJCMARSHAL } -void Interop::OnAfterGCScanRoots() +void Interop::OnAfterGCScanRoots(_In_ bool isConcurrent) { CONTRACTL { @@ -139,7 +144,13 @@ void Interop::OnAfterGCScanRoots() } CONTRACTL_END; +#ifdef FEATURE_COMWRAPPERS + ComWrappersNative::AfterRefCountedHandleCallbacks(); +#endif // FEATURE_COMWRAPPERS + #ifdef FEATURE_OBJCMARSHAL - ObjCMarshalNative::AfterRefCountedHandleCallbacks(); + // See Interop::OnBeforeGCScanRoots for why non-concurrent. + if (!isConcurrent) + ObjCMarshalNative::AfterRefCountedHandleCallbacks(); #endif // FEATURE_OBJCMARSHAL } diff --git a/src/tests/Interop/COM/ComWrappers/API/Program.cs b/src/tests/Interop/COM/ComWrappers/API/Program.cs index b934ac95b9e80d..1a779a7da6155e 100644 --- a/src/tests/Interop/COM/ComWrappers/API/Program.cs +++ b/src/tests/Interop/COM/ComWrappers/API/Program.cs @@ -280,6 +280,56 @@ static void ValidatePrecreatedExternalWrapper() }); } + static void ValidateExternalWrapperCacheCleanUp() + { + Console.WriteLine($"Running {nameof(ValidateExternalWrapperCacheCleanUp)}..."); + + var cw = new TestComWrappers(); + + // Get an object from a tracker runtime. + IntPtr trackerObjRaw = MockReferenceTrackerRuntime.CreateTrackerObject(); + + // Create a wrapper for the object instance. + var weakRef1 = CreateAndRegisterWrapper(cw, trackerObjRaw); + + // Run the GC to have the wrapper marked for collection. + ForceGC(); + + // Create a new wrapper for the same external object. + var weakRef2 = CreateAndRegisterWrapper(cw, trackerObjRaw); + + // We are using a tracking resurrection WeakReference so we should be able + // to get back the objects as they are all continually re-registering for Finalization. + Assert.IsTrue(weakRef1.TryGetTarget(out ITrackerObjectWrapper wrapper1)); + Assert.IsTrue(weakRef2.TryGetTarget(out ITrackerObjectWrapper wrapper2)); + + // Check that the two wrappers aren't equal, meaning we created a new wrapper since + // the first wrapper was removed from the internal cache. + Assert.AreNotEqual(wrapper1, wrapper2); + + // Let the wrappers Finalize. + wrapper1.ReregisterForFinalize = false; + wrapper2.ReregisterForFinalize = false; + + static WeakReference CreateAndRegisterWrapper(ComWrappers cw, IntPtr trackerObjRaw) + { + // Manually create a wrapper + var iid = typeof(ITrackerObject).GUID; + IntPtr iTestComObject; + int hr = Marshal.QueryInterface(trackerObjRaw, ref iid, out iTestComObject); + Assert.AreEqual(0, hr); + var nativeWrapper = new ITrackerObjectWrapper(iTestComObject); + + nativeWrapper = (ITrackerObjectWrapper)cw.GetOrRegisterObjectForComInstance(trackerObjRaw, CreateObjectFlags.None, nativeWrapper); + + // Set this on the return instead of during creation since the returned wrapper may be the one from + // the internal cache and not the one passed in above. + nativeWrapper.ReregisterForFinalize = true; + + return new WeakReference(nativeWrapper, trackResurrection: true); + } + } + static void ValidateSuppliedInnerNotAggregation() { Console.WriteLine($"Running {nameof(ValidateSuppliedInnerNotAggregation)}..."); @@ -566,6 +616,7 @@ static int Main(string[] doNotUse) ValidateCreateObjectCachingScenario(); ValidateWrappersInstanceIsolation(); ValidatePrecreatedExternalWrapper(); + ValidateExternalWrapperCacheCleanUp(); ValidateSuppliedInnerNotAggregation(); ValidateIUnknownImpls(); ValidateBadComWrapperImpl(); diff --git a/src/tests/Interop/COM/ComWrappers/Common.cs b/src/tests/Interop/COM/ComWrappers/Common.cs index 3e505c114753be..d100744cb271fc 100644 --- a/src/tests/Interop/COM/ComWrappers/Common.cs +++ b/src/tests/Interop/COM/ComWrappers/Common.cs @@ -213,9 +213,18 @@ static IntPtr CreateInstance(IntPtr outer, out IntPtr inner) ~ITrackerObjectWrapper() { - ComWrappersHelper.Cleanup(ref this.classNative); + if (this.ReregisterForFinalize) + { + GC.ReRegisterForFinalize(this); + } + else + { + ComWrappersHelper.Cleanup(ref this.classNative); + } } + public bool ReregisterForFinalize { get; set; } = false; + public int AddObjectRef(IntPtr obj) { int id; From 8162eb2b2a488170a6cd7c2bee9cc4cdfaa200f2 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Tue, 25 May 2021 09:06:52 -0700 Subject: [PATCH 107/115] Remove unused code from old IJW path (#53190) --- src/coreclr/debug/daccess/nidump.cpp | 4 ---- src/coreclr/vm/appdomain.cpp | 4 ---- src/coreclr/vm/ceeload.cpp | 2 -- src/coreclr/vm/ceeload.h | 19 +---------------- src/coreclr/vm/domainfile.cpp | 29 -------------------------- src/coreclr/vm/domainfile.h | 31 ---------------------------- 6 files changed, 1 insertion(+), 88 deletions(-) diff --git a/src/coreclr/debug/daccess/nidump.cpp b/src/coreclr/debug/daccess/nidump.cpp index 0cfa3951ba5ee1..e421e15aadd00b 100644 --- a/src/coreclr/debug/daccess/nidump.cpp +++ b/src/coreclr/debug/daccess/nidump.cpp @@ -3691,10 +3691,6 @@ void NativeImageDumper::DumpModule( PTR_Module module ) DisplayWriteFieldPointer( m_file, DPtrToPreferredAddr(file), Module, MODULE ); - PTR_MethodDesc dllMain( TO_TADDR(module->m_pDllMain) ); - WriteFieldMethodDesc( m_pDllMain, dllMain, Module, - MODULE ); - _ASSERTE(module->m_dwTransientFlags == 0U); DisplayWriteFieldUInt(m_dwTransientFlags, module->m_dwTransientFlags, Module, MODULE ); diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 960b3fa799fb57..8fa02c4f12179b 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3528,10 +3528,6 @@ DomainAssembly * AppDomain::FindAssembly(PEAssembly * pFile, FindAssemblyOptions return NULL; } -static const AssemblyIterationFlags STANDARD_IJW_ITERATOR_FLAGS = - (AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution | kExcludeCollectible); - - void AppDomain::SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares/*=TRUE*/) { CONTRACTL diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index f84714c9ce673a..e1003c8cff6347 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -8899,8 +8899,6 @@ void Module::Fixup(DataImage *image) image->ZeroField(this, offsetof(Module, m_file), sizeof(m_file)); - image->FixupPointerField(this, offsetof(Module, m_pDllMain)); - image->ZeroField(this, offsetof(Module, m_dwTransientFlags), sizeof(m_dwTransientFlags)); image->ZeroField(this, offsetof(Module, m_pVASigCookieBlock), sizeof(m_pVASigCookieBlock)); diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 1f4b9b3b4ac6d4..13a78ec96f4ef9 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -1330,8 +1330,6 @@ class Module PTR_PEFile m_file; - MethodDesc *m_pDllMain; - enum { // These are the values set in m_dwTransientFlags. // Note that none of these flags survive a prejit save/restore. @@ -2503,18 +2501,6 @@ class Module // Enregisters a VASig. VASigCookie *GetVASigCookie(Signature vaSignature); - // DLL entry point - MethodDesc *GetDllEntryPoint() - { - LIMITED_METHOD_CONTRACT; - return m_pDllMain; - } - void SetDllEntryPoint(MethodDesc *pMD) - { - LIMITED_METHOD_CONTRACT; - 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() @@ -2525,10 +2511,7 @@ class Module } #endif - private: - - - public: +public: #ifndef DACCESS_COMPILE BOOL Equals(Module *pModule) { WRAPPER_NO_CONTRACT; return m_file->Equals(pModule->m_file); } BOOL Equals(PEFile *pFile) { WRAPPER_NO_CONTRACT; return m_file->Equals(pFile); } diff --git a/src/coreclr/vm/domainfile.cpp b/src/coreclr/vm/domainfile.cpp index d929576fa0d6ab..963c8efc27a6f8 100644 --- a/src/coreclr/vm/domainfile.cpp +++ b/src/coreclr/vm/domainfile.cpp @@ -1273,35 +1273,6 @@ OBJECTREF DomainAssembly::GetExposedAssemblyObject() } // DomainAssembly::GetExposedAssemblyObject #endif // CROSSGEN_COMPILE -DomainFile* DomainAssembly::FindIJWModule(HMODULE hMod) -{ - CONTRACT (DomainFile*) - { - INSTANCE_CHECK; - THROWS; - GC_NOTRIGGER; - MODE_ANY; - POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); - } - CONTRACT_END; - - ModuleIterator i = IterateModules(kModIterIncludeLoaded); - while (i.Next()) - { - PEFile *pFile = i.GetDomainFile()->GetFile(); - - if ( !pFile->IsResource() - && !pFile->IsDynamic() - && !pFile->IsILOnly() - && pFile->GetIJWBase() == hMod) - { - RETURN i.GetDomainFile(); - } - } - RETURN NULL; -} - - void DomainAssembly::Begin() { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/vm/domainfile.h b/src/coreclr/vm/domainfile.h index fb140846e06394..8ed8774c70ac67 100644 --- a/src/coreclr/vm/domainfile.h +++ b/src/coreclr/vm/domainfile.h @@ -19,7 +19,6 @@ // -------------------------------------------------------------------------------- class AppDomain; class DomainAssembly; -class DomainModule; class Assembly; class Module; class DynamicMethodTable; @@ -493,9 +492,6 @@ class DomainAssembly : public DomainFile return m_pLoaderAllocator; } - // Finds only loaded hmods - DomainFile *FindIJWModule(HMODULE hMod); - void SetAssembly(Assembly* pAssembly); BOOL IsAssembly() @@ -601,26 +597,6 @@ class DomainAssembly : public DomainFile return ModuleIterator::Create(this, moduleIterationOption); } - DomainFile *LookupDomainFile(DWORD index) - { - WRAPPER_NO_CONTRACT; - if (index >= m_Modules.GetCount()) - return NULL; - else - return dac_cast(m_Modules.Get(index)); - } - - Module *LookupModule(DWORD index) - { - WRAPPER_NO_CONTRACT; - DomainFile *pModule = LookupDomainFile(index); - if (pModule == NULL) - return NULL; - else - return pModule->GetModule(); - } - - // ------------------------------------------------------------ // Resource access // ------------------------------------------------------------ @@ -678,7 +654,6 @@ class DomainAssembly : public DomainFile friend class AppDomain; friend class Assembly; - friend class AssemblyNameNative; #ifndef DACCESS_COMPILE public: @@ -691,12 +666,9 @@ class DomainAssembly : public DomainFile // Internal routines // ------------------------------------------------------------ - void SetSecurityError(Exception *ex); - #ifndef DACCESS_COMPILE void Begin(); void Allocate(); - void LoadSharers(); void DeliverSyncEvents(); void DeliverAsyncEvents(); #endif @@ -744,7 +716,4 @@ class DomainAssembly : public DomainFile typedef DomainAssembly::ModuleIterator DomainModuleIterator; -// -------------------------------------------------------------------------------- -// DomainModule is a subclass of DomainFile which specifically represents a module. -// -------------------------------------------------------------------------------- #endif // _DOMAINFILE_H_ From 6218d6e1e87667f6b6612081ea36283f4a54aacd Mon Sep 17 00:00:00 2001 From: Artem Kliatchkine Date: Tue, 25 May 2021 18:11:50 +0200 Subject: [PATCH 108/115] Closing opened handles to avoid resource leak. (#51950) SymReader::InitializeFromFile opens file handles which were not closed causing resource leaks on each call. Fix #50422 Co-authored-by: Artem Kliatchkine --- src/coreclr/debug/ildbsymlib/symread.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/coreclr/debug/ildbsymlib/symread.cpp b/src/coreclr/debug/ildbsymlib/symread.cpp index dc12d4fd8c7252..168d84fc6e2195 100644 --- a/src/coreclr/debug/ildbsymlib/symread.cpp +++ b/src/coreclr/debug/ildbsymlib/symread.cpp @@ -722,6 +722,12 @@ SymReader::InitializeFromFile( } ErrExit: + if (hMod) + UnmapViewOfFile(hMod); + if (hMapFile != INVALID_HANDLE_VALUE) + CloseHandle(hMapFile); + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); return hr; } From b0cb47ad38b4cc9248310d52a6353570b45d7682 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Tue, 25 May 2021 18:25:54 +0200 Subject: [PATCH 109/115] [wasm][testing] create dev cert via powershell on helix (#53225) create SSL dev cert via powershell on helix --- src/libraries/sendtohelixhelp.proj | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 27d7f89f521c44..92bd93bf687461 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -106,7 +106,13 @@ - + + From faeba228d14cc7a1194591d4b6de5d58447c1d83 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Tue, 25 May 2021 12:46:40 -0700 Subject: [PATCH 110/115] Reduce DefaultPooledConnectionIdleTimeout default (#52687) * Reduce DefaultPooledConnectionIdleTimeout default - Change DefaultPooledConnectionIdleTimeout from 120 seconds to 60 seconds - This should reduce the occurrence of socket errors when connected to IIS or Kestrel --- .../Common/src/System/Net/Http/HttpHandlerDefaults.cs | 2 +- .../tests/FunctionalTests/SocketsHttpHandlerTest.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs b/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs index 537519288734b4..3bf335ec33cea4 100644 --- a/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs +++ b/src/libraries/Common/src/System/Net/Http/HttpHandlerDefaults.cs @@ -25,7 +25,7 @@ internal static partial class HttpHandlerDefaults public const bool DefaultUseDefaultCredentials = false; public const bool DefaultCheckCertificateRevocationList = false; public static readonly TimeSpan DefaultPooledConnectionLifetime = Timeout.InfiniteTimeSpan; - public static readonly TimeSpan DefaultPooledConnectionIdleTimeout = TimeSpan.FromMinutes(2); + public static readonly TimeSpan DefaultPooledConnectionIdleTimeout = TimeSpan.FromMinutes(1); public static readonly TimeSpan DefaultExpect100ContinueTimeout = TimeSpan.FromSeconds(1); public static readonly TimeSpan DefaultConnectTimeout = Timeout.InfiniteTimeSpan; } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index cbae2a53263aa7..e74684eb384ba7 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -1774,7 +1774,7 @@ public void PooledConnectionIdleTimeout_GetSet_Roundtrips() { using (var handler = new SocketsHttpHandler()) { - Assert.Equal(TimeSpan.FromMinutes(2), handler.PooledConnectionIdleTimeout); + Assert.Equal(TimeSpan.FromMinutes(1), handler.PooledConnectionIdleTimeout); handler.PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan; Assert.Equal(Timeout.InfiniteTimeSpan, handler.PooledConnectionIdleTimeout); @@ -1957,7 +1957,7 @@ await Assert.ThrowsAnyAsync(() => Assert.Equal(int.MaxValue, handler.MaxConnectionsPerServer); Assert.Equal(64, handler.MaxResponseHeadersLength); Assert.False(handler.PreAuthenticate); - Assert.Equal(TimeSpan.FromMinutes(2), handler.PooledConnectionIdleTimeout); + Assert.Equal(TimeSpan.FromMinutes(1), handler.PooledConnectionIdleTimeout); Assert.Equal(Timeout.InfiniteTimeSpan, handler.PooledConnectionLifetime); Assert.NotNull(handler.Properties); Assert.Null(handler.Proxy); From 3c0cf22dbacedbdd11f45241988cd0f980995fb3 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 17:08:10 -0400 Subject: [PATCH 111/115] Addressed some PR comments --- src/mono/sample/mbr/browser/runtime.js | 4 ++-- src/mono/sample/wasm/browser-bench/runtime.js | 4 ++-- src/mono/sample/wasm/browser-profile/runtime.js | 4 ++-- src/mono/sample/wasm/browser/runtime.js | 4 ++-- .../tests/debugger-test/runtime-debugger.js | 14 +++++++------- src/mono/wasm/runtime/js_support.js | 10 +++++++--- .../WebAssembly/Browser/AOT/runtime.js | 6 +++--- .../WebAssembly/Browser/NormalInterp/runtime.js | 4 ++-- 8 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index a0179a97ae5a78..1f311ca4811aff 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -3,10 +3,10 @@ var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index 39ebf6c0c276b6..5ecacd345993f4 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 96572c69592d9e..df506c9f651a98 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -4,10 +4,10 @@ var Module = { is_testing: false, onRuntimeInitialized: function () { - JSSupportLib.load_config(Module.setupConfig); + JSSupportLib.load_config(Module.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { Module.init(); diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 0c996cac3de58a..9d74612aef2238 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -4,12 +4,12 @@ var Module = { // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, // Called once the config file is loaded. THe contents of the config file // are passed as a JS object within the config parameter - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index 6d3a83dfaaa24a..a8baa920f78bfd 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -2,12 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); - }, + onRuntimeInitialized: function () { + JSSupportLib.load_config(this.onConfigLoaded); + }, - setupConfig: function (config) { - config.loaded_cb = function () { + onConfigLoaded: function (config) { + config.loaded_cb = function () { App.init (); }; // For custom logging patch the functions below @@ -20,5 +20,5 @@ var Module = { MONO.mono_wasm_setenv ("MONO_LOG_MASK", "all"); */ MONO.mono_load_runtime_and_bcl_args (config) - }, -}; \ No newline at end of file + }, +}; diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index e4ef25c30ad125..032c0eaef193c4 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMZIED +// THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMIZED // IT I MEANT AS A SET OF JS TOOLS TO SUPPORT THE SDK var JSSupportLib = { @@ -9,7 +9,9 @@ var JSSupportLib = { load_config: function (callback) { if (ENVIRONMENT_IS_NODE){ const config = require('./mono-config.json'); - callback(config); + if (callback){ + callback(config); + } } var xobj = new XMLHttpRequest(); xobj.overrideMimeType("application/json"); @@ -17,7 +19,9 @@ var JSSupportLib = { xobj.onreadystatechange = function () { if (xobj.readyState == 4 && xobj.status == "200") { const config = JSON.parse(xobj.responseText); - callback(config); + if (callback){ + callback(config); + } } }; xobj.send(); diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js index 5588740f8efe99..6488f420c27c3d 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js @@ -3,10 +3,10 @@ var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); @@ -27,4 +27,4 @@ var Module = { throw(error); } }, -}; \ No newline at end of file +}; diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js index f15dfa7274d999..6488f420c27c3d 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js @@ -3,10 +3,10 @@ var Module = { onRuntimeInitialized: function () { - JSSupportLib.load_config(this.setupConfig); + JSSupportLib.load_config(this.onConfigLoaded); }, - setupConfig: function (config) { + onConfigLoaded: function (config) { config.loaded_cb = function () { try { App.init (); From 9469eeca2a8a4044df80660a1079cb95b4b6dc07 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Tue, 25 May 2021 19:26:38 -0400 Subject: [PATCH 112/115] Addressed a few more PR comments --- src/mono/sample/mbr/browser/runtime.js | 5 +++ src/mono/sample/wasm/browser-bench/runtime.js | 5 +++ .../sample/wasm/browser-profile/runtime.js | 5 +++ src/mono/sample/wasm/browser/runtime.js | 5 +++ .../tests/debugger-test/runtime-debugger.js | 5 +++ src/mono/wasm/runtime/js_support.js | 40 ++++++++++++++----- .../WebAssembly/Browser/AOT/runtime.js | 5 +++ .../Browser/NormalInterp/runtime.js | 5 +++ 8 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index 1f311ca4811aff..b26dcce86e1c2e 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index 5ecacd345993f4..ea10bc2b822cd3 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -6,6 +6,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index df506c9f651a98..553d7ce2800ef8 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -8,6 +8,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { Module.init(); diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 9d74612aef2238..5e13da47258a27 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -10,6 +10,11 @@ var Module = { // Called once the config file is loaded. THe contents of the config file // are passed as a JS object within the config parameter onConfigLoaded: function (config) { + if (!config || config.error){ + alert("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index a8baa920f78bfd..a74836490c6379 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { App.init (); }; diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index 032c0eaef193c4..099c57ec3e6162 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -12,18 +12,36 @@ var JSSupportLib = { if (callback){ callback(config); } - } - var xobj = new XMLHttpRequest(); - xobj.overrideMimeType("application/json"); - xobj.open('GET', './mono-config.json', true); - xobj.onreadystatechange = function () { - if (xobj.readyState == 4 && xobj.status == "200") { - const config = JSON.parse(xobj.responseText); - if (callback){ - callback(config); + } else { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function() { + if (callback && xobj.readyState == XMLHttpRequest.DONE) { + if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { + const config = JSON.parse(xobj.responseText); + callback(config); + } else { + // error if the request to load the file was successful but loading failed + callback({error: "Error loading mono-config.json file from current directory"}); + } + } + }; + xobj.onerror = function() { + // error if the request failed + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); + } + } + + try { + xobj.send() + } catch(e) { + // other kinds of errors + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); } } - }; - xobj.send(); + } }, } diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js index 6488f420c27c3d..d60354b01d042a 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/AOT/runtime.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js index 6488f420c27c3d..d60354b01d042a 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js +++ b/src/tests/FunctionalTests/WebAssembly/Browser/NormalInterp/runtime.js @@ -7,6 +7,11 @@ var Module = { }, onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + config.loaded_cb = function () { try { App.init (); From 9e8af0130fa33fa717ceeffc86050722a28075dd Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Wed, 26 May 2021 18:20:13 -0400 Subject: [PATCH 113/115] changed post-js to pre-js --- src/mono/sample/wasm/browser/runtime.js | 28 ++++++---- src/mono/wasm/Makefile | 2 +- src/mono/wasm/runtime/js_support.js | 70 +++++++++++++------------ src/mono/wasm/wasm.proj | 2 +- 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 5e13da47258a27..9bfacdfbd6d460 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -2,20 +2,28 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - // Called when the runtime is initialized and wasm is ready - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, - // Called once the config file is loaded. THe contents of the config file + config: null, + + // Called once the config file is loaded. The contents of the config file // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ - alert("An error occured while loading the config file"); + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ + alert("No config found"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { try { App.init (); } catch (error) { @@ -23,16 +31,16 @@ var Module = { throw (error); } }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } try { - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); } catch (error) { test_exit(1); throw(error); } }, -}; +}; \ No newline at end of file diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index b3442e44b63e18..699630e0850e55 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -102,7 +102,7 @@ $(BUILDS_OBJ_DIR): mkdir -p $$@ $(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js runtime/js_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --post-js runtime/js_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) + $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --pre-js runtime/js_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index 099c57ec3e6162..9fecab85a2ca1e 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -4,44 +4,46 @@ // THIS FILE IS COPIED DIRECTLY INTO THE DOTNET.JS FILE WITHOUT BEING RUN OR COMPILED/OPTIMIZED // IT I MEANT AS A SET OF JS TOOLS TO SUPPORT THE SDK -var JSSupportLib = { - // Loads the config file located in the root of the project - load_config: function (callback) { - if (ENVIRONMENT_IS_NODE){ - const config = require('./mono-config.json'); - if (callback){ - callback(config); - } - } else { - var xobj = new XMLHttpRequest(); - xobj.overrideMimeType("application/json"); - xobj.open('GET', './mono-config.json', true); - xobj.onreadystatechange = function() { - if (callback && xobj.readyState == XMLHttpRequest.DONE) { - if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { - const config = JSON.parse(xobj.responseText); - callback(config); - } else { - // error if the request to load the file was successful but loading failed - callback({error: "Error loading mono-config.json file from current directory"}); - } - } - }; - xobj.onerror = function() { - // error if the request failed - if (callback){ +// Loads the config file located in the root of the project +// Not meant to be used outside of this class (TODO make private to this file when project converted to TS) +function load_config() { + callback = Module['onConfigLoaded'] + + if (ENVIRONMENT_IS_NODE){ + const config = require('./mono-config.json'); + if (callback){ + callback(config); + } + } else { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', './mono-config.json', true); + xobj.onreadystatechange = function() { + if (callback && xobj.readyState == XMLHttpRequest.DONE) { + if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { + const config = JSON.parse(xobj.responseText); + callback(config); + } else { + // error if the request to load the file was successful but loading failed callback({error: "Error loading mono-config.json file from current directory"}); } } + }; + xobj.onerror = function() { + // error if the request failed + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); + } + } - try { - xobj.send() - } catch(e) { - // other kinds of errors - if (callback){ - callback({error: "Error loading mono-config.json file from current directory"}); - } + try { + xobj.send() + } catch(e) { + // other kinds of errors + if (callback){ + callback({error: "Error loading mono-config.json file from current directory"}); } } - }, + } } +load_config() \ No newline at end of file diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 3bb7a55cfa8e2e..2d0006bfe14eb1 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -153,7 +153,7 @@ EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" /> - From c0ba6d44e16ac801f3fdab04b3816cd7668d5439 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Wed, 26 May 2021 18:37:46 -0400 Subject: [PATCH 114/115] Fixed samples --- src/mono/sample/mbr/browser/runtime.js | 24 ++++++++++---- src/mono/sample/wasm/browser-bench/runtime.js | 28 +++++++++++----- .../sample/wasm/browser-profile/runtime.js | 33 ++++++++++++------- .../tests/debugger-test/runtime-debugger.js | 24 ++++++++++---- 4 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index b26dcce86e1c2e..3a63c214f2ff65 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -2,26 +2,36 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, + config: null, + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ alert("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { App.init (); }; - config.environment_variables = { + Module.config.environment_variables = { "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); }, }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index ea10bc2b822cd3..cbebc617ba82d7 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -1,17 +1,27 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, + config: null, + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ alert("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { try { App.init (); } catch (error) { @@ -19,13 +29,13 @@ var Module = { throw (error); } }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } - if (config.enable_profiler) + if (Module.config.enable_profiler) { - config.aot_profiler_options = { + Module.config.aot_profiler_options = { write_at:"Sample.Test::StopProfile", send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" } @@ -33,10 +43,10 @@ var Module = { try { - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); } catch (error) { test_exit(1); throw(error); } }, -}; \ No newline at end of file +}; diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index 553d7ce2800ef8..e385167eaec223 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -2,18 +2,27 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { is_testing: false, + config: null, - onRuntimeInitialized: function () { - JSSupportLib.load_config(Module.onConfigLoaded); - }, - + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter onConfigLoaded: function (config) { if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ alert("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { try { Module.init(); } catch (error) { @@ -21,13 +30,13 @@ var Module = { throw (error); } }; - config.fetch_file_cb = function (asset) { + Module.config.fetch_file_cb = function (asset) { return fetch (asset, { credentials: 'same-origin' }); } - if (config.enable_profiler) + if (Module.config.enable_profiler) { - config.aot_profiler_options = { + Module.config.aot_profiler_options = { write_at:"Sample.Test::StopProfile", send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" } @@ -35,7 +44,7 @@ var Module = { try { - MONO.mono_load_runtime_and_bcl_args (config); + MONO.mono_load_runtime_and_bcl_args (Module.config); } catch (error) { Module.test_exit(1); throw(error); @@ -55,7 +64,7 @@ var Module = { Module.test_exit(exit_code); } - if (config.enable_profiler) { + if (Module.config.enable_profiler) { BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []); Module.saveProfile(); } @@ -64,7 +73,7 @@ var Module = { onLoad: function() { var url = new URL(decodeURI(window.location)); let args = url.searchParams.getAll('arg'); - is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); + Module.is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); }, test_exit: function(exit_code) { @@ -94,4 +103,4 @@ var Module = { // Remove anchor from body document.body.removeChild(a); } -}; \ No newline at end of file +}; diff --git a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js index a74836490c6379..da8da61bd92fd3 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js +++ b/src/mono/wasm/debugger/tests/debugger-test/runtime-debugger.js @@ -2,17 +2,27 @@ // The .NET Foundation licenses this file to you under the MIT license. var Module = { - onRuntimeInitialized: function () { - JSSupportLib.load_config(this.onConfigLoaded); - }, + config: null, + + // Called once the config file is loaded. The contents of the config file + // are passed as a JS object within the config parameter + onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + }, - onConfigLoaded: function (config) { - if (!config || config.error){ + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error){ console.log("An error occured while loading the config file"); return; } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { App.init (); }; // For custom logging patch the functions below @@ -24,6 +34,6 @@ var Module = { MONO.mono_wasm_setenv ("MONO_LOG_LEVEL", "debug"); MONO.mono_wasm_setenv ("MONO_LOG_MASK", "all"); */ - MONO.mono_load_runtime_and_bcl_args (config) + MONO.mono_load_runtime_and_bcl_args (Module.config) }, }; From 9c93d7a377d1273f67e425ce48aa0fcc81028f69 Mon Sep 17 00:00:00 2001 From: Daniel-Genkin Date: Thu, 27 May 2021 11:39:34 -0400 Subject: [PATCH 115/115] Fixed console sample --- src/mono/sample/wasm/browser/runtime.js | 2 +- src/mono/wasm/runtime-test.js | 34 ++++++++++++++------- src/mono/wasm/runtime/js_support.js | 39 ++++++++++++++++--------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 9bfacdfbd6d460..0a99c174a01f62 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -43,4 +43,4 @@ var Module = { throw(error); } }, -}; \ No newline at end of file +}; diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index cfc25430c13db5..6d8f45bf75b187 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -204,14 +204,14 @@ function loadScript (url) } } -JSSupportLib.load_config(); +//var module = require ('./dotnet.js')(Module).then ((va) => console.log (va)); +//globalThis.Module = Module; var Module = { mainScriptUrlOrBlob: "dotnet.js", - print, printErr, - + config: null, onAbort: function(x) { print ("ABORT: " + x); var err = new Error(); @@ -220,6 +220,21 @@ var Module = { test_exit (1); }, + onConfigLoaded: function (config) { + if (!config || config.error){ + console.log("An error occured while loading the config file"); + return; + } + + Module.config = config; + + if (is_node) { + eval (read ("dotnet.js").toString()); + } else { + loadScript ("dotnet.js"); + } + }, + onRuntimeInitialized: function () { // Have to set env vars here to enable setting MONO_LOG_LEVEL etc. for (var variable in setenv) { @@ -230,7 +245,7 @@ var Module = { Module.ccall ('mono_wasm_enable_on_demand_gc', 'void', ['number'], [0]); } - config.loaded_cb = function () { + Module.config.loaded_cb = function () { let wds = FS.stat (working_dir); if (wds === undefined || !FS.isDir (wds.mode)) { fail_exec (`Could not find working directory ${working_dir}`); @@ -240,13 +255,13 @@ var Module = { FS.chdir (working_dir); App.init (); }; - config.fetch_file_cb = function (asset) { - // console.log("fetch_file_cb('" + asset + "')"); + Module.config.fetch_file_cb = function (asset) { + //console.log("fetch_file_cb('" + asset + "')"); // for testing purposes add BCL assets to VFS until we special case File.Open // to identify when an assembly from the BCL is being open and resolve it correctly. /* var content = new Uint8Array (read (asset, 'binary')); - var path = asset.substr(config.deploy_prefix.length); + var path = asset.substr(Module.config.deploy_prefix.length); writeContentToFile(content, path); */ @@ -279,13 +294,10 @@ var Module = { }) } }; - - MONO.mono_load_runtime_and_bcl_args (config); + Module.mono_load_runtime_and_bcl_args (Module.config); }, }; -loadScript ("dotnet.js"); - const IGNORE_PARAM_COUNT = -1; var App = { diff --git a/src/mono/wasm/runtime/js_support.js b/src/mono/wasm/runtime/js_support.js index 9fecab85a2ca1e..80353e35fa0b25 100644 --- a/src/mono/wasm/runtime/js_support.js +++ b/src/mono/wasm/runtime/js_support.js @@ -7,21 +7,29 @@ // Loads the config file located in the root of the project // Not meant to be used outside of this class (TODO make private to this file when project converted to TS) function load_config() { - callback = Module['onConfigLoaded'] + // since this file loads before emsdk we don't have environment vars yet, so we define them locally + var ENVIRONMENT_IS_NODE = typeof process === 'object'; + var ENVIRONMENT_IS_WEB = typeof window === 'object'; + // var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; + // var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + + callback = Module['onConfigLoaded']; if (ENVIRONMENT_IS_NODE){ - const config = require('./mono-config.json'); - if (callback){ + try { + var config = JSON.parse(require('./mono-config.json')); callback(config); + } catch(e) { + callback({error: "Error loading mono-config.json file from current directory"}); } - } else { + } else if (ENVIRONMENT_IS_WEB){ var xobj = new XMLHttpRequest(); xobj.overrideMimeType("application/json"); xobj.open('GET', './mono-config.json', true); xobj.onreadystatechange = function() { - if (callback && xobj.readyState == XMLHttpRequest.DONE) { + if (xobj.readyState == XMLHttpRequest.DONE) { if (xobj.status === 0 || (xobj.status >= 200 && xobj.status < 400)) { - const config = JSON.parse(xobj.responseText); + var config = JSON.parse(xobj.responseText); callback(config); } else { // error if the request to load the file was successful but loading failed @@ -31,19 +39,22 @@ function load_config() { }; xobj.onerror = function() { // error if the request failed - if (callback){ - callback({error: "Error loading mono-config.json file from current directory"}); - } + callback({error: "Error loading mono-config.json file from current directory"}); } try { - xobj.send() + xobj.send(); } catch(e) { // other kinds of errors - if (callback){ - callback({error: "Error loading mono-config.json file from current directory"}); - } + callback({error: "Error loading mono-config.json file from current directory"}); + } + } else { + try { + var config = JSON.parse(load("./mono-config.json")); + callback(config); + } catch(e) { + callback({error: "Error loading mono-config.json file from current directory"}); } } } -load_config() \ No newline at end of file +load_config();