From 15ab9f985ed45feaa619df70d288fbd0acd5c45f Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Fri, 5 Feb 2021 18:52:05 -0500 Subject: [PATCH] mono: remove ENABLE_NETCORE and associated framework code (#47925) * mono: remove ENABLE_NETCORE and associated framework code * Remove g_assert_not_netcore * No more locales.h * No more filewatcher.h * Fix Windows build * Remove g_assert_netcore I don't see anything calling this * Add now-needed include --- src/mono/CMakeLists.txt | 2 - src/mono/cmake/config.h.in | 3 - src/mono/cmake/options.cmake | 2 - src/mono/mono/eglib/glib.h | 8 - src/mono/mono/metadata/CMakeLists.txt | 15 - src/mono/mono/metadata/appdomain.c | 2295 +---------- src/mono/mono/metadata/assembly-internals.h | 9 - src/mono/mono/metadata/assembly-load-context.c | 6 - src/mono/mono/metadata/assembly.c | 490 +-- src/mono/mono/metadata/class-init.c | 16 +- src/mono/mono/metadata/class-internals.h | 21 - src/mono/mono/metadata/class-setup-vtable.c | 2 - src/mono/mono/metadata/class.c | 2 - src/mono/mono/metadata/cominterop.c | 25 +- src/mono/mono/metadata/console-io.h | 25 - src/mono/mono/metadata/console-null.c | 11 - src/mono/mono/metadata/console-unix.c | 526 --- src/mono/mono/metadata/console-win32.c | 11 - src/mono/mono/metadata/custom-attrs.c | 16 +- src/mono/mono/metadata/domain-internals.h | 77 - src/mono/mono/metadata/domain.c | 255 -- src/mono/mono/metadata/environment.c | 48 - src/mono/mono/metadata/exception.c | 15 - src/mono/mono/metadata/filewatcher.c | 194 - src/mono/mono/metadata/filewatcher.h | 38 - src/mono/mono/metadata/gc.c | 88 - src/mono/mono/metadata/icall-decl.h | 53 +- src/mono/mono/metadata/icall-def.h | 1029 ----- src/mono/mono/metadata/icall-eventpipe.c | 4 - src/mono/mono/metadata/icall.c | 1437 +------ src/mono/mono/metadata/image.c | 133 +- src/mono/mono/metadata/loaded-images-global.c | 65 - src/mono/mono/metadata/loaded-images-internals.h | 5 - src/mono/mono/metadata/loaded-images-netcore.c | 38 - src/mono/mono/metadata/loaded-images.c | 35 +- src/mono/mono/metadata/loader-internals.h | 14 - src/mono/mono/metadata/locales.h | 60 - src/mono/mono/metadata/marshal-ilgen.c | 9 - src/mono/mono/metadata/marshal-windows.c | 32 - src/mono/mono/metadata/marshal.c | 436 +- src/mono/mono/metadata/metadata-internals.h | 15 - src/mono/mono/metadata/metadata.c | 4 - src/mono/mono/metadata/monitor.c | 23 +- src/mono/mono/metadata/monitor.h | 2 - src/mono/mono/metadata/mono-mlist.c | 4 - src/mono/mono/metadata/mono-perfcounters.c | 83 - src/mono/mono/metadata/mono-route.c | 161 - src/mono/mono/metadata/mono-security.c | 675 --- src/mono/mono/metadata/native-library.c | 355 +- src/mono/mono/metadata/object-internals.h | 212 +- src/mono/mono/metadata/object-offsets.h | 8 - src/mono/mono/metadata/object.c | 231 -- src/mono/mono/metadata/object.h | 4 - src/mono/mono/metadata/rand.c | 56 - src/mono/mono/metadata/rand.h | 22 - src/mono/mono/metadata/reflection-internals.h | 5 - src/mono/mono/metadata/reflection.c | 23 - src/mono/mono/metadata/runtime.c | 19 - src/mono/mono/metadata/sre.c | 33 - src/mono/mono/metadata/support.c | 11 - src/mono/mono/metadata/sysmath.c | 4 - src/mono/mono/metadata/threadpool-io-epoll.c | 139 - src/mono/mono/metadata/threadpool-io-kqueue.c | 137 - src/mono/mono/metadata/threadpool-io-poll.c | 228 -- src/mono/mono/metadata/threadpool-io.c | 751 ---- src/mono/mono/metadata/threadpool-io.h | 33 - src/mono/mono/metadata/threadpool-worker-default.c | 1236 ------ src/mono/mono/metadata/threadpool-worker-wasm.c | 81 - src/mono/mono/metadata/threadpool-worker.h | 42 - src/mono/mono/metadata/threadpool.c | 828 ---- src/mono/mono/metadata/threadpool.h | 36 - src/mono/mono/metadata/threads-types.h | 13 - src/mono/mono/metadata/threads.c | 689 +--- src/mono/mono/metadata/w32event-unix.c | 14 - src/mono/mono/metadata/w32file-unix.c | 34 - src/mono/mono/metadata/w32file.c | 920 ----- src/mono/mono/metadata/w32file.h | 137 - src/mono/mono/metadata/w32process-unix.c | 3410 ---------------- src/mono/mono/metadata/w32process-win32.c | 1 - src/mono/mono/metadata/w32process.c | 113 - src/mono/mono/metadata/w32socket-unix.c | 17 - src/mono/mono/metadata/w32socket.c | 2646 ------------ src/mono/mono/metadata/w32socket.h | 6 - src/mono/mono/mini/CMakeLists.txt | 3 - src/mono/mono/mini/alias-analysis.c | 3 +- src/mono/mono/mini/aot-compiler.c | 38 - src/mono/mono/mini/debugger-agent.c | 16 - src/mono/mono/mini/driver.c | 25 - src/mono/mono/mini/exceptions-amd64.c | 63 - src/mono/mono/mini/exceptions-x86.c | 53 - src/mono/mono/mini/interp/interp.c | 47 +- src/mono/mono/mini/interp/transform.c | 18 - src/mono/mono/mini/intrinsics.c | 30 +- src/mono/mono/mini/jit-icalls.c | 2 - src/mono/mono/mini/main-core.c | 6 - src/mono/mono/mini/memory-access.c | 4 - src/mono/mono/mini/method-to-ir.c | 24 +- src/mono/mono/mini/mini-arm64.h | 2 +- src/mono/mono/mini/mini-cross-helpers.c | 1 - src/mono/mono/mini/mini-exceptions.c | 40 - src/mono/mono/mini/mini-llvm-cpp.cpp | 2 - src/mono/mono/mini/mini-llvm.c | 12 +- src/mono/mono/mini/mini-runtime.c | 23 - src/mono/mono/mini/mini-runtime.h | 2 - src/mono/mono/mini/mini-wasm.c | 8 - src/mono/mono/mini/mini-wasm.h | 2 - src/mono/mono/mini/mini-x86.h | 7 - src/mono/mono/mini/mini.c | 3 - src/mono/mono/mini/mini.h | 3 - src/mono/mono/mini/monovm.c | 24 - src/mono/mono/mini/simd-intrinsics-netcore.c | 2329 ----------- src/mono/mono/mini/simd-intrinsics.c | 4301 +++++++++----------- src/mono/mono/mini/tasklets.c | 220 - src/mono/mono/mini/tasklets.h | 38 - src/mono/mono/sgen/sgen-debug.c | 15 - src/mono/mono/tools/offsets-tool/offsets-tool.py | 3 - src/mono/mono/utils/CMakeLists.txt | 1 - src/mono/mono/utils/mono-complex.h | 65 - src/mono/mono/utils/mono-dl-posix.c | 4 - src/mono/mono/utils/mono-dl-wasm.c | 4 - src/mono/mono/utils/mono-dl.c | 14 +- src/mono/mono/utils/mono-merp.c | 4 +- src/mono/mono/utils/mono-threads-posix.c | 6 - src/mono/mono/utils/mono-threads-windows.c | 4 - src/mono/wasm/Makefile | 4 +- src/mono/wasm/runtime/driver.c | 6 - 126 files changed, 2148 insertions(+), 26342 deletions(-) delete mode 100644 src/mono/mono/metadata/console-io.h delete mode 100644 src/mono/mono/metadata/console-unix.c delete mode 100644 src/mono/mono/metadata/filewatcher.c delete mode 100644 src/mono/mono/metadata/filewatcher.h delete mode 100644 src/mono/mono/metadata/loaded-images-global.c delete mode 100644 src/mono/mono/metadata/loaded-images-netcore.c delete mode 100644 src/mono/mono/metadata/locales.h delete mode 100644 src/mono/mono/metadata/mono-security.c delete mode 100644 src/mono/mono/metadata/rand.c delete mode 100644 src/mono/mono/metadata/rand.h delete mode 100644 src/mono/mono/metadata/support.c delete mode 100644 src/mono/mono/metadata/threadpool-io-epoll.c delete mode 100644 src/mono/mono/metadata/threadpool-io-kqueue.c delete mode 100644 src/mono/mono/metadata/threadpool-io-poll.c delete mode 100644 src/mono/mono/metadata/threadpool-io.c delete mode 100644 src/mono/mono/metadata/threadpool-io.h delete mode 100644 src/mono/mono/metadata/threadpool-worker-default.c delete mode 100644 src/mono/mono/metadata/threadpool-worker-wasm.c delete mode 100644 src/mono/mono/metadata/threadpool-worker.h delete mode 100644 src/mono/mono/metadata/threadpool.c delete mode 100644 src/mono/mono/metadata/threadpool.h delete mode 100644 src/mono/mono/metadata/w32file.c delete mode 100644 src/mono/mono/metadata/w32socket.c delete mode 100644 src/mono/mono/mini/simd-intrinsics-netcore.c delete mode 100644 src/mono/mono/mini/tasklets.c delete mode 100644 src/mono/mono/mini/tasklets.h delete mode 100644 src/mono/mono/utils/mono-complex.h diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 62faaa4..8000bf5 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -69,8 +69,6 @@ endif() # set(MONO_CORLIB_VERSION 1A5E0066-58DC-428A-B21C-0AD6CDAE2789) -set(ENABLE_NETCORE 1) - set(DISABLE_REMOTING 1) set(DISABLE_REFLECTION_EMIT_SAVE 1) set(DISABLE_APPDOMAINS 1) diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index 29b83f4..187ad23 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -338,9 +338,6 @@ /* The size of `long long', as computed by sizeof. */ #define SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@ -/* Enables the support for .NET Core Features in the MonoVM */ -#cmakedefine ENABLE_NETCORE 1 - /* Xen-specific behaviour */ #cmakedefine MONO_XEN_OPT 1 diff --git a/src/mono/cmake/options.cmake b/src/mono/cmake/options.cmake index 3550787..fe6f8df 100644 --- a/src/mono/cmake/options.cmake +++ b/src/mono/cmake/options.cmake @@ -2,8 +2,6 @@ # Configure options # -option (ENABLE_NETCORE "Enables the support for .NET Core Features in the MonoVM") - option (DISABLE_PORTABILITY "Disables the IO portability layer") option (DISABLE_AOT "Disable AOT Compiler") option (DISABLE_PROFILER "Disable default profiler support") diff --git a/src/mono/mono/eglib/glib.h b/src/mono/mono/eglib/glib.h index 7bdace9..dbcc399 100644 --- a/src/mono/mono/eglib/glib.h +++ b/src/mono/mono/eglib/glib.h @@ -959,14 +959,6 @@ GUnicodeBreakType g_unichar_break_type (gunichar c); #define g_assert_not_reached() G_STMT_START { mono_assertion_message_unreachable (__FILE__, __LINE__); eg_unreachable(); } G_STMT_END -#if ENABLE_NETCORE -#define g_assert_netcore() /* nothing */ -#define g_assert_not_netcore() g_assert (!"This function should only be called on mono-notnetcore.") -#else -#define g_assert_netcore() g_assert (!"This function should only be called on mono-netcore.") -#define g_assert_not_netcore() /* nothing */ -#endif - /* f is format -- like printf and scanf * Where you might have said: * if (!(expr)) diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt index b974a97..4898f17 100644 --- a/src/mono/mono/metadata/CMakeLists.txt +++ b/src/mono/mono/metadata/CMakeLists.txt @@ -43,7 +43,6 @@ set(metadata_win32_sources w32error-win32.c) set(metadata_unix_sources - console-unix.c w32mutex-unix.c w32semaphore-unix.c w32event-unix.c @@ -86,7 +85,6 @@ set(metadata_common_sources class-setup-vtable.c cominterop.c cominterop.h - console-io.h coree.c coree.h coree-internals.h @@ -101,11 +99,8 @@ set(metadata_common_sources exception.c exception.h exception-internals.h - w32file.c w32file.h w32file-internals.h - filewatcher.c - filewatcher.h gc-internals.h icall.c icall-internals.h @@ -160,7 +155,6 @@ set(metadata_common_sources opcodes.c property-bag.h property-bag.c - w32socket.c w32socket.h w32socket-internals.h w32process.c @@ -168,12 +162,9 @@ set(metadata_common_sources w32process-internals.h profiler.c profiler-private.h - rand.h - rand.c remoting.h remoting.c runtime.c - mono-security.c security.h security-core-clr.c security-core-clr.h @@ -185,11 +176,6 @@ set(metadata_common_sources tabledefs.h threads.c threads-types.h - threadpool.c - threadpool.h - threadpool-worker.h - threadpool-io.c - threadpool-io.h verify.c verify-internals.h wrapper-types.h @@ -237,7 +223,6 @@ set(metadata_common_sources qcall-def.h loaded-images-internals.h loaded-images.c - loaded-images-netcore.c abi-details.h abi.c memory-manager.c diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c index 750dc81..268866c 100644 --- a/src/mono/mono/metadata/appdomain.c +++ b/src/mono/mono/metadata/appdomain.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -55,7 +54,6 @@ #include #include #include -#include #include #include #include @@ -93,18 +91,11 @@ typedef struct gchar *filename; } RuntimeConfig; -#ifndef ENABLE_NETCORE -static gunichar2 process_guid [36]; -static gboolean process_guid_set = FALSE; -#endif - static gboolean no_exec = FALSE; -#ifdef ENABLE_NETCORE static int n_appctx_props; static gunichar2 **appctx_keys; static gunichar2 **appctx_values; -#endif static const char * mono_check_corlib_version_internal (void); @@ -135,22 +126,9 @@ mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assemb static void add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht); -#if ENABLE_NETCORE - static void add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass); -#endif - -#ifndef ENABLE_NETCORE -static MonoAppDomainHandle -mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error); - -static MonoDomain * -mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error); - -#endif - static void mono_context_set_default_context (MonoDomain *domain); @@ -161,21 +139,13 @@ static MonoLoadFunc load_function = NULL; /* Lazy class loading functions */ static GENERATE_GET_CLASS_WITH_CACHE (assembly, "System.Reflection", "Assembly"); -#ifdef ENABLE_NETCORE static GENERATE_GET_CLASS_WITH_CACHE (app_context, "System", "AppContext"); -#endif -#ifndef ENABLE_NETCORE -GENERATE_GET_CLASS_WITH_CACHE (appdomain, MONO_APPDOMAIN_CLASS_NAME_SPACE, MONO_APPDOMAIN_CLASS_NAME); -GENERATE_GET_CLASS_WITH_CACHE (appdomain_setup, MONO_APPDOMAIN_SETUP_CLASS_NAME_SPACE, MONO_APPDOMAIN_SETUP_CLASS_NAME); -#else MonoClass* mono_class_get_appdomain_class (void) { return mono_defaults.object_class; } -#endif - static MonoDomain * mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain); @@ -335,36 +305,17 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE), FALSE, TRUE, FALSE); mono_install_assembly_load_hook_v2 (mono_domain_fire_assembly_load, NULL, FALSE); -#ifndef ENABLE_NETCORE // refonly hooks - mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE), TRUE, FALSE); - mono_install_assembly_search_hook_v2 (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE), TRUE, FALSE, FALSE); - mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE), TRUE, TRUE, FALSE); - mono_install_assembly_asmctx_from_path_hook (mono_domain_asmctx_from_path, NULL); -#endif - mono_thread_init (start_cb, attach_cb); if (!mono_runtime_get_no_exec ()) { MonoClass *klass; -#ifndef ENABLE_NETCORE - klass = mono_class_get_appdomain_setup_class (); - MonoAppDomainSetupHandle setup; - setup = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_pinned_handle (domain, klass, error)); - goto_if_nok (error, exit); -#endif klass = mono_class_get_appdomain_class (); ad = MONO_HANDLE_CAST (MonoAppDomain, mono_object_new_pinned_handle (domain, klass, error)); goto_if_nok (error, exit); -#ifndef ENABLE_NETCORE - MONO_HANDLE_SETVAL (ad, data, MonoDomain*, domain); -#endif domain->domain = MONO_HANDLE_RAW (ad); -#ifndef ENABLE_NETCORE - domain->setup = MONO_HANDLE_RAW (setup); -#endif } mono_thread_internal_attach (domain); @@ -382,20 +333,9 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT /* GC init has to happen after thread init */ mono_gc_init (); - /* contexts use GC handles, so they must be initialized after the GC */ -#ifndef ENABLE_NETCORE - mono_context_init_checked (domain, error); - goto_if_nok (error, exit); - mono_context_set_default_context (domain); -#endif - -#ifdef ENABLE_NETCORE if (!mono_runtime_get_no_exec ()) mono_runtime_install_appctx_properties (); -#endif - mono_network_init (); - mono_console_init (); mono_attach_init (); mono_locks_tracer_init (); @@ -556,7 +496,6 @@ mono_runtime_cleanup (MonoDomain *domain) mono_gc_cleanup (); mono_thread_cleanup (); - mono_network_cleanup (); mono_marshal_cleanup (); mono_type_initialization_cleanup (); @@ -603,71 +542,6 @@ mono_runtime_quit_internal (void) quit_function (mono_get_root_domain (), NULL); } -#ifndef ENABLE_NETCORE - -/** - * mono_domain_create_appdomain: - * \param friendly_name The friendly name of the appdomain to create - * \param configuration_file The configuration file to initialize the appdomain with - * \returns a \c MonoDomain initialized with the appdomain - */ -MonoDomain * -mono_domain_create_appdomain (char *friendly_name, char *configuration_file) -{ - HANDLE_FUNCTION_ENTER (); - MonoDomain *domain; - MONO_ENTER_GC_UNSAFE; - ERROR_DECL (error); - domain = mono_domain_create_appdomain_checked (friendly_name, configuration_file, error); - mono_error_cleanup (error); - MONO_EXIT_GC_UNSAFE; - HANDLE_FUNCTION_RETURN_VAL (domain); -} - -/** - * mono_domain_create_appdomain_checked: - * \param friendly_name The friendly name of the appdomain to create - * \param configuration_file The configuration file to initialize the appdomain with - * \param error Set on error. - * - * \returns a MonoDomain initialized with the appdomain. On failure sets \p error and returns NULL. - */ -MonoDomain * -mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - error_init (error); - MonoDomain *result = NULL; - -#ifndef ENABLE_NETCORE - MonoClass *klass = mono_class_get_appdomain_setup_class (); - MonoAppDomainSetupHandle setup = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_handle (mono_domain_get (), klass, error)); - goto_if_nok (error, leave); - MonoStringHandle config_file; - if (configuration_file != NULL) { - config_file = mono_string_new_handle (mono_domain_get (), configuration_file, error); - goto_if_nok (error, leave); - } else { - config_file = MONO_HANDLE_NEW (MonoString, NULL); - } - MONO_HANDLE_SET (setup, configuration_file, config_file); -#endif - - MonoAppDomainHandle ad; -#ifndef ENABLE_NETCORE - ad = mono_domain_create_appdomain_internal (friendly_name, setup, error); -#else - ad = MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); -#endif - goto_if_nok (error, leave); - - result = mono_domain_from_appdomain_handle (ad); -leave: - HANDLE_FUNCTION_RETURN_VAL (result); -} - -#endif - /** * mono_domain_set_config: * \param domain \c MonoDomain initialized with the appdomain we want to change @@ -683,175 +557,8 @@ leave: void mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *config_file_name) { -#ifndef ENABLE_NETCORE - HANDLE_FUNCTION_ENTER (); - MONO_ENTER_GC_UNSAFE; - ERROR_DECL (error); - mono_domain_set_config_checked (domain, base_dir, config_file_name, error); - mono_error_cleanup (error); - MONO_EXIT_GC_UNSAFE; - HANDLE_FUNCTION_RETURN (); -#else g_assert_not_reached (); -#endif -} - -#ifndef ENABLE_NETCORE -gboolean -mono_domain_set_config_checked (MonoDomain *domain, const char *base_dir, const char *config_file_name, MonoError *error) -{ - error_init (error); - MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup); - MonoStringHandle base_dir_str = mono_string_new_handle (domain, base_dir, error); - goto_if_nok (error, leave); - MONO_HANDLE_SET (setup, application_base, base_dir_str); - MonoStringHandle config_file_name_str; - config_file_name_str = mono_string_new_handle (domain, config_file_name, error); - goto_if_nok (error, leave); - MONO_HANDLE_SET (setup, configuration_file, config_file_name_str); -leave: - return is_ok (error); -} -#endif - -#ifndef ENABLE_NETCORE -static MonoAppDomainSetupHandle -copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetupHandle setup, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - MonoDomain *caller_domain; - MonoClass *ads_class; - MonoAppDomainSetupHandle result = MONO_HANDLE_NEW (MonoAppDomainSetup, NULL); - - error_init (error); - - caller_domain = mono_domain_get (); - ads_class = mono_class_get_appdomain_setup_class (); - - MonoAppDomainSetupHandle copy = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_handle(domain, ads_class, error)); - goto_if_nok (error, leave); - - mono_domain_set_internal_with_options (domain, TRUE); - -#define XCOPY_FIELD(type, dst, field, src, error) \ - do { \ - TYPED_HANDLE_NAME (type) src_val = MONO_HANDLE_NEW_GET (type, (src), field); \ - TYPED_HANDLE_NAME (type) copied_val = MONO_HANDLE_CAST (type, mono_marshal_xdomain_copy_value_handle (MONO_HANDLE_CAST (MonoObject, src_val), error)); \ - goto_if_nok (error, leave); \ - MONO_HANDLE_SET ((dst),field,copied_val); \ - } while (0) - -#define COPY_VAL(dst,field,type,src) \ - do { \ - MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \ - } while (0) - - XCOPY_FIELD (MonoString, copy, application_base, setup, error); - XCOPY_FIELD (MonoString, copy, application_name, setup, error); - XCOPY_FIELD (MonoString, copy, cache_path, setup, error); - XCOPY_FIELD (MonoString, copy, configuration_file, setup, error); - XCOPY_FIELD (MonoString, copy, dynamic_base, setup, error); - XCOPY_FIELD (MonoString, copy, license_file, setup, error); - XCOPY_FIELD (MonoString, copy, private_bin_path, setup, error); - XCOPY_FIELD (MonoString, copy, private_bin_path_probe, setup, error); - XCOPY_FIELD (MonoString, copy, shadow_copy_directories, setup, error); - XCOPY_FIELD (MonoString, copy, shadow_copy_files, setup, error); - COPY_VAL (copy, publisher_policy, MonoBoolean, setup); - COPY_VAL (copy, path_changed, MonoBoolean, setup); - COPY_VAL (copy, loader_optimization, int, setup); - COPY_VAL (copy, disallow_binding_redirects, MonoBoolean, setup); - COPY_VAL (copy, disallow_code_downloads, MonoBoolean, setup); - XCOPY_FIELD (MonoArray, copy, domain_initializer_args, setup, error); - COPY_VAL (copy, disallow_appbase_probe, MonoBoolean, setup); - XCOPY_FIELD (MonoObject, copy, application_trust, setup, error); - XCOPY_FIELD (MonoArray, copy, configuration_bytes, setup, error); - XCOPY_FIELD (MonoArray, copy, serialized_non_primitives, setup, error); - -#undef XCOPY_FIELD -#undef COPY_VAL - - mono_domain_set_internal_with_options (caller_domain, TRUE); - - MONO_HANDLE_ASSIGN (result, copy); -leave: - HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup, result); -} -#endif - -#ifndef ENABLE_NETCORE -static MonoAppDomainHandle -mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - MonoAppDomainHandle result = MONO_HANDLE_NEW (MonoAppDomain, NULL); - MonoClass *adclass; - MonoDomain *data; - - error_init (error); - - adclass = mono_class_get_appdomain_class (); - - /* FIXME: pin all those objects */ - data = mono_domain_create(); - - MonoAppDomainHandle ad = MONO_HANDLE_CAST (MonoAppDomain, mono_object_new_handle (data, adclass, error)); - goto_if_nok (error, leave); - MONO_HANDLE_SETVAL (ad, data, MonoDomain*, data); - data->domain = MONO_HANDLE_RAW (ad); - data->friendly_name = g_strdup (friendly_name); - - MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name)); - - MonoStringHandle app_base; - app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base); - if (MONO_HANDLE_IS_NULL (app_base)) { - /* Inherit from the root domain since MS.NET does this */ - MonoDomain *root = mono_get_root_domain (); - MonoAppDomainSetupHandle root_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, root->setup); - MonoStringHandle root_app_base = MONO_HANDLE_NEW_GET (MonoString, root_setup, application_base); - if (!MONO_HANDLE_IS_NULL (root_app_base)) { - /* N.B. new string is in the new domain */ - MonoGCHandle gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, root_app_base), TRUE); - MonoStringHandle s = mono_string_new_utf16_handle (data, mono_string_chars_internal (MONO_HANDLE_RAW (root_app_base)), mono_string_handle_length (root_app_base), error); - mono_gchandle_free_internal (gchandle); - if (!is_ok (error)) { - g_free (data->friendly_name); - goto leave; - } - MONO_HANDLE_SET (setup, application_base, s); - } - } - mono_context_init_checked (data, error); - goto_if_nok (error, leave); - - data->setup = MONO_HANDLE_RAW (copy_app_domain_setup (data, setup, error)); - if (!is_ok (error)) { - g_free (data->friendly_name); - goto leave; - } - - mono_domain_set_options_from_config (data); - add_assemblies_to_domain (data, mono_defaults.corlib->assembly, NULL); - -#ifndef DISABLE_SHADOW_COPY - /*FIXME, guard this for when the debugger is not running */ - char *shadow_location; - shadow_location = get_shadow_assembly_location_base (data, error); - if (!is_ok (error)) { - g_free (data->friendly_name); - goto leave; - } - - g_free (shadow_location); -#endif - - create_domain_objects (data); - - MONO_HANDLE_ASSIGN (result, ad); -leave: - HANDLE_FUNCTION_RETURN_REF (MonoAppDomain, result); } -#endif /** * mono_domain_has_type_resolve: @@ -866,21 +573,7 @@ mono_domain_has_type_resolve (MonoDomain *domain) if (!domain->domain) return FALSE; -#ifdef ENABLE_NETCORE return TRUE; -#else - MonoObject *o; - - MONO_STATIC_POINTER_INIT (MonoClassField, field) - - field = mono_class_get_field_from_name_full (mono_defaults.appdomain_class, "TypeResolve", NULL); - g_assert (field); - - MONO_STATIC_POINTER_INIT_END (MonoClassField, field) - - mono_field_get_value_internal ((MonoObject*)(domain->domain), field, &o); - return o != NULL; -#endif } /** @@ -912,13 +605,8 @@ mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *typebu goto_if_nok (error, exit); ret = mono_domain_try_type_resolve_name (domain, NULL, name_handle, error); } else { -#ifndef ENABLE_NETCORE - MONO_HANDLE_DCL (MonoObject, typebuilder); - ret = mono_domain_try_type_resolve_typebuilder (domain, MONO_HANDLE_CAST (MonoReflectionTypeBuilder, typebuilder), error); -#else // TODO: make this work on netcore when working on SRE.TypeBuilder g_assert_not_reached (); -#endif } exit: @@ -926,7 +614,6 @@ exit: HANDLE_FUNCTION_RETURN_OBJ (ret); } -#ifdef ENABLE_NETCORE MonoReflectionAssemblyHandle mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error) { @@ -977,127 +664,6 @@ return_null: exit: HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret)); } -#else -/** - * mono_class_get_appdomain_do_type_resolve_method: - * - * This routine returns System.AppDomain.DoTypeResolve. - */ -static MonoMethod * -mono_class_get_appdomain_do_type_resolve_method (MonoError *error) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, method) - - method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeResolve", -1, 0, error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, method) - - if (method == NULL) - g_warning ("%s method AppDomain.DoTypeResolve not found. %s\n", __func__, mono_error_get_message (error)); - - return method; -} - -/** - * mono_class_get_appdomain_do_type_builder_resolve_method: - * - * This routine returns System.AppDomain.DoTypeBuilderResolve. - */ -static MonoMethod * -mono_class_get_appdomain_do_type_builder_resolve_method (MonoError *error) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, method) - - method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeBuilderResolve", -1, 0, error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, method) - - if (method == NULL) - g_warning ("%s method AppDomain.DoTypeBuilderResolve not found. %s\n", __func__, mono_error_get_message (error)); - - return method; -} - -/** - * mono_domain_try_type_resolve_name: - * \param domain application domain in which to resolve the type - * \param name the name of the type to resolve. - * - * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns - * the assembly that matches name. - * - * \returns A \c MonoReflectionAssembly or NULL if not found - */ -MonoReflectionAssemblyHandle -mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - - void *params [1] = { 0 }; - - g_assert (domain); - g_assert (MONO_HANDLE_BOOL (name)); - g_assert (error); - - error_init (error); - - MonoMethod *method; - method = mono_class_get_appdomain_do_type_resolve_method (error); - goto_if_nok (error, return_null); - - MonoAppDomainHandle appdomain; - appdomain = MONO_HANDLE_NEW (MonoAppDomain, domain->domain); - - MonoObjectHandle ret; - params [0] = MONO_HANDLE_RAW (name); - ret = mono_runtime_invoke_handle (method, MONO_HANDLE_CAST (MonoObject, appdomain), params, error); - goto_if_nok (error, return_null); - goto exit; -return_null: - ret = NULL_HANDLE; -exit: - HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret)); -} - -/** - * mono_domain_try_type_resolve_typebuilder: - * \param domain application domain in which to resolve the type - * \param typebuilder A \c System.Reflection.Emit.TypeBuilder; typebuilder.FullName is the name of the type to resolve. - * - * This routine invokes the internal \c System.AppDomain.DoTypeBuilderResolve and returns - * the assembly that matches typebuilder.FullName. - * - * \returns A \c MonoReflectionAssembly or NULL_HANDLE if not found - */ -MonoReflectionAssemblyHandle -mono_domain_try_type_resolve_typebuilder (MonoDomain *domain, MonoReflectionTypeBuilderHandle typebuilder, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - - g_assert (domain); - g_assert (MONO_HANDLE_BOOL (typebuilder)); - g_assert (error); - - error_init (error); - - MonoMethod * const method = mono_class_get_appdomain_do_type_builder_resolve_method (error); - goto_if_nok (error, return_null); - - MonoAppDomainHandle appdomain; - appdomain = MONO_HANDLE_NEW (MonoAppDomain, domain->domain); - void *args [1]; - args [0] = MONO_HANDLE_RAW (typebuilder); - - MonoObjectHandle ret; - ret = mono_runtime_invoke_handle (method, MONO_HANDLE_CAST (MonoObject, appdomain), args, error); - goto_if_nok (error, return_null); - goto exit; -return_null: - ret = NULL_HANDLE; -exit: - HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret)); -} -#endif /** * mono_domain_owns_vtable_slot: @@ -1126,341 +692,49 @@ mono_domain_set_fast (MonoDomain *domain, gboolean force) return TRUE; } -#ifndef ENABLE_NETCORE -MonoObjectHandle -ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error) +static gboolean +add_assembly_to_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error) { + HANDLE_FUNCTION_ENTER (); error_init (error); - - if (MONO_HANDLE_IS_NULL (name)) { - mono_error_set_argument_null (error, "name", ""); - return NULL_HANDLE; - } - - g_assert (!MONO_HANDLE_IS_NULL (ad)); - MonoDomain *add = MONO_HANDLE_GETVAL (ad, data); - g_assert (add); - - char *str = mono_string_handle_to_utf8 (name, error); - return_val_if_nok (error, NULL_HANDLE); - - mono_domain_lock (add); - - MonoAppDomainSetupHandle ad_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, add->setup); - MonoStringHandle o; - if (!strcmp (str, "APPBASE")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_base); - else if (!strcmp (str, "APP_CONFIG_FILE")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, configuration_file); - else if (!strcmp (str, "DYNAMIC_BASE")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, dynamic_base); - else if (!strcmp (str, "APP_NAME")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_name); - else if (!strcmp (str, "CACHE_BASE")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, cache_path); - else if (!strcmp (str, "PRIVATE_BINPATH")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path); - else if (!strcmp (str, "BINPATH_PROBE_ONLY")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path_probe); - else if (!strcmp (str, "SHADOW_COPY_DIRS")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_directories); - else if (!strcmp (str, "FORCE_CACHE_INSTALL")) - o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_files); - else - o = MONO_HANDLE_NEW (MonoString, (MonoString*)mono_g_hash_table_lookup (add->env, MONO_HANDLE_RAW (name))); - - mono_domain_unlock (add); - g_free (str); - - return MONO_HANDLE_CAST (MonoObject, o); + MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, assm, error); + goto_if_nok (error, leave); + MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, assm_obj); +leave: + HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); } -void -ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error) +static MonoArrayHandle +get_assembly_array_from_domain (MonoDomain *domain, MonoBoolean refonly, MonoError *error) { - error_init (error); - - if (MONO_HANDLE_IS_NULL (name)) { - mono_error_set_argument_null (error, "name", ""); - return; - } - - g_assert (!MONO_HANDLE_IS_NULL (ad)); - MonoDomain *add = MONO_HANDLE_GETVAL (ad, data); - g_assert (add); + int i; + GPtrArray *assemblies; - mono_domain_lock (add); + assemblies = mono_domain_get_assemblies (domain, refonly); - mono_g_hash_table_insert_internal (add->env, MONO_HANDLE_RAW (name), MONO_HANDLE_RAW (data)); + MonoArrayHandle res = mono_array_new_handle (domain, mono_class_get_assembly_class (), assemblies->len, error); + goto_if_nok (error, leave); + for (i = 0; i < assemblies->len; ++i) { + if (!add_assembly_to_array (domain, res, i, (MonoAssembly *)g_ptr_array_index (assemblies, i), error)) + goto leave; + } - mono_domain_unlock (add); +leave: + g_ptr_array_free (assemblies, TRUE); + return res; } -#ifndef ENABLE_NETCORE -MonoAppDomainSetupHandle -ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error) +MonoArrayHandle +ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError *error) { - error_init (error); - g_assert (!MONO_HANDLE_IS_NULL (ad)); - MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); - g_assert (domain); - - return MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup); + MonoDomain *domain = mono_domain_get (); + return get_assembly_array_from_domain (domain, FALSE, error); } -#endif -MonoStringHandle -ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error) +MonoAssembly* +mono_try_assembly_resolve (MonoAssemblyLoadContext *alc, const char *fname_raw, MonoAssembly *requesting, gboolean refonly, MonoError *error) { - error_init (error); - g_assert (!MONO_HANDLE_IS_NULL (ad)); - MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); - g_assert (domain); - - return mono_string_new_handle (domain, domain->friendly_name, error); -} - -MonoAppDomainHandle -ves_icall_System_AppDomain_getCurDomain (MonoError *error) -{ - error_init (error); - MonoDomain *add = mono_domain_get (); - - return MONO_HANDLE_NEW (MonoAppDomain, add->domain); -} - -MonoAppDomainHandle -ves_icall_System_AppDomain_getRootDomain (MonoError *error) -{ - error_init (error); - MonoDomain *root = mono_get_root_domain (); - - return MONO_HANDLE_NEW (MonoAppDomain, root->domain); -} - -MonoBoolean -ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions (MonoError *error) -{ - MonoDomain *domain = mono_domain_get (); - - return domain->throw_unobserved_task_exceptions; -} -#endif - -#ifndef ENABLE_NETCORE -static char* -get_attribute_value (const gchar **attribute_names, - const gchar **attribute_values, - const char *att_name) -{ - int n; - for (n = 0; attribute_names [n] != NULL; n++) { - if (strcmp (attribute_names [n], att_name) == 0) - return g_strdup (attribute_values [n]); - } - return NULL; -} - -static void -start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **gerror) -{ - RuntimeConfig *runtime_config = (RuntimeConfig *)user_data; - - if (strcmp (element_name, "runtime") == 0) { - runtime_config->runtime_count++; - return; - } - - if (strcmp (element_name, "assemblyBinding") == 0) { - runtime_config->assemblybinding_count++; - return; - } - - if (runtime_config->runtime_count != 1) - return; - - if (strcmp (element_name, "ThrowUnobservedTaskExceptions") == 0) { - const char *value = get_attribute_value (attribute_names, attribute_values, "enabled"); - - if (value && g_ascii_strcasecmp (value, "true") == 0) - runtime_config->domain->throw_unobserved_task_exceptions = TRUE; - } - - if (runtime_config->assemblybinding_count != 1) - return; - - if (strcmp (element_name, "probing") != 0) - return; - - g_free (runtime_config->domain->private_bin_path); - runtime_config->domain->private_bin_path = get_attribute_value (attribute_names, attribute_values, "privatePath"); - if (runtime_config->domain->private_bin_path && !runtime_config->domain->private_bin_path [0]) { - g_free (runtime_config->domain->private_bin_path); - runtime_config->domain->private_bin_path = NULL; - return; - } -} - -static void -end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **gerror) -{ - RuntimeConfig *runtime_config = (RuntimeConfig *)user_data; - if (strcmp (element_name, "runtime") == 0) - runtime_config->runtime_count--; - else if (strcmp (element_name, "assemblyBinding") == 0) - runtime_config->assemblybinding_count--; -} - -static void -parse_error (GMarkupParseContext *context, GError *gerror, gpointer user_data) -{ - RuntimeConfig *state = (RuntimeConfig *)user_data; - const gchar *msg; - const gchar *filename; - - filename = state && state->filename ? (gchar *) state->filename : ""; - msg = gerror && gerror->message ? gerror->message : ""; - g_warning ("Error parsing %s: %s", filename, msg); -} - -static const GMarkupParser -mono_parser = { - start_element, - end_element, - NULL, - NULL, - parse_error -}; - -void -mono_domain_set_options_from_config (MonoDomain *domain) -{ - ERROR_DECL (error); - gchar *config_file_name = NULL, *text = NULL, *config_file_path = NULL; - gsize len; - GMarkupParseContext *context; - RuntimeConfig runtime_config; - gint offset; - - if (!domain || !domain->setup || !domain->setup->configuration_file) - return; - - config_file_name = mono_string_to_utf8_checked_internal (domain->setup->configuration_file, error); - if (!is_ok (error)) { - mono_error_cleanup (error); - goto free_and_out; - } - - config_file_path = mono_portability_find_file (config_file_name, TRUE); - if (!config_file_path) - config_file_path = config_file_name; - - if (!g_file_get_contents (config_file_path, &text, &len, NULL)) - goto free_and_out; - - runtime_config.runtime_count = 0; - runtime_config.assemblybinding_count = 0; - runtime_config.domain = domain; - runtime_config.filename = config_file_path; - - offset = 0; - if (len > 3 && text [0] == '\xef' && text [1] == (gchar) '\xbb' && text [2] == '\xbf') - offset = 3; /* Skip UTF-8 BOM */ - - context = g_markup_parse_context_new (&mono_parser, (GMarkupParseFlags)0, &runtime_config, NULL); - if (g_markup_parse_context_parse (context, text + offset, len - offset, NULL)) - g_markup_parse_context_end_parse (context, NULL); - g_markup_parse_context_free (context); - - free_and_out: - g_free (text); - if (config_file_name != config_file_path) - g_free (config_file_name); - g_free (config_file_path); -} -#endif - -#ifndef ENABLE_NETCORE -MonoAppDomainHandle -ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error) -{ - error_init (error); - MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL); - -#ifdef DISABLE_APPDOMAINS - mono_error_set_not_supported (error, "AppDomain creation is not supported on this runtime."); -#else - char *fname; - - fname = mono_string_handle_to_utf8 (friendly_name, error); - return_val_if_nok (error, ad); - ad = mono_domain_create_appdomain_internal (fname, setup, error); - g_free (fname); -#endif - return ad; -} -#endif - -static gboolean -add_assembly_to_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - error_init (error); - MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, assm, error); - goto_if_nok (error, leave); - MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, assm_obj); -leave: - HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); -} - -static MonoArrayHandle -get_assembly_array_from_domain (MonoDomain *domain, MonoBoolean refonly, MonoError *error) -{ - int i; - GPtrArray *assemblies; - - assemblies = mono_domain_get_assemblies (domain, refonly); - - MonoArrayHandle res = mono_array_new_handle (domain, mono_class_get_assembly_class (), assemblies->len, error); - goto_if_nok (error, leave); - for (i = 0; i < assemblies->len; ++i) { - if (!add_assembly_to_array (domain, res, i, (MonoAssembly *)g_ptr_array_index (assemblies, i), error)) - goto leave; - } - -leave: - g_ptr_array_free (assemblies, TRUE); - return res; -} - -#ifdef ENABLE_NETCORE -MonoArrayHandle -ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError *error) -{ - MonoDomain *domain = mono_domain_get (); - return get_assembly_array_from_domain (domain, FALSE, error); -} -#else -MonoArrayHandle -ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad, MonoBoolean refonly, MonoError *error) -{ - MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); - return get_assembly_array_from_domain (domain, refonly, error); -} -#endif - -MonoAssembly* -mono_try_assembly_resolve (MonoAssemblyLoadContext *alc, const char *fname_raw, MonoAssembly *requesting, gboolean refonly, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); + HANDLE_FUNCTION_ENTER (); error_init (error); MonoAssembly *result = NULL; MonoStringHandle fname = mono_string_new_handle (mono_alc_domain (alc), fname_raw, error); @@ -1481,47 +755,6 @@ mono_try_assembly_resolve_handle (MonoAssemblyLoadContext *alc, MonoStringHandle if (mono_runtime_get_no_exec ()) goto leave; -#ifndef ENABLE_NETCORE - - static MonoMethod *method; - MonoBoolean isrefonly; - gpointer params [3]; - - g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname)); - - // FIXME cache? - - method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoAssemblyResolve", -1, 0, error); - g_assert (method != NULL); - - isrefonly = refonly ? 1 : 0; - MonoReflectionAssemblyHandle requesting_handle; - if (requesting) { - requesting_handle = mono_assembly_get_object_handle (domain, requesting, error); - goto_if_nok (error, leave); - } - params [0] = MONO_HANDLE_RAW (fname); - params [1] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL; - params [2] = &isrefonly; - MonoObject *exc; - exc = NULL; - MonoReflectionAssemblyHandle result; - result = MONO_HANDLE_CAST (MonoReflectionAssembly, MONO_HANDLE_NEW (MonoObject, mono_runtime_try_invoke (method, domain->domain, params, &exc, error))); - if (!is_ok (error) || exc != NULL) { - if (is_ok (error)) - mono_error_set_exception_instance (error, (MonoException*)exc); - goto leave; - } - ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL; - - if (ret && !refonly && mono_asmctx_get_kind (&ret->context) == MONO_ASMCTX_REFONLY) { - /* .NET Framework throws System.IO.FileNotFoundException in this case */ - filename = mono_string_handle_to_utf8 (fname, error); - mono_error_set_file_not_found (error, filename, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only: %s", filename); - ret = NULL; - goto leave; - } -#else MONO_STATIC_POINTER_INIT (MonoMethod, method) ERROR_DECL (local_error); @@ -1556,7 +789,6 @@ mono_try_assembly_resolve_handle (MonoAssemblyLoadContext *alc, MonoStringHandle if (MONO_HANDLE_BOOL (result)) ret = MONO_HANDLE_GETVAL (result, assembly); -#endif leave: g_free (filename); @@ -1614,18 +846,6 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to domain %s, ref_count=%d", ass->aname.name, ass, domain->friendly_name, ass->ref_count); } -#ifndef ENABLE_NETCORE - if (ass->image->references) { - for (int i = 0; i < ass->image->nreferences; i++) { - MonoAssembly *ref = ass->image->references [i]; - if (ref && ref != REFERENCE_MISSING) { - if (!g_hash_table_lookup (ht, ref)) - add_assemblies_to_domain (domain, ref, ht); - } - } - } -#endif - if (destroy_ht) g_hash_table_destroy (ht); } @@ -1633,7 +853,6 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht) /* * LOCKING: assumes the ALC's assemblies lock is taken */ -#ifdef ENABLE_NETCORE static void add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass) { @@ -1656,7 +875,6 @@ add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass) mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to ALC (%p), ref_count=%d", ass->aname.name, ass, (gpointer)alc, ass->ref_count); } -#endif static void mono_domain_fire_assembly_load_event (MonoDomain *domain, MonoAssembly *assembly, MonoError *error) @@ -1666,7 +884,6 @@ mono_domain_fire_assembly_load_event (MonoDomain *domain, MonoAssembly *assembly g_assert (domain); g_assert (assembly); -#ifdef ENABLE_NETCORE MONO_STATIC_POINTER_INIT (MonoMethod, method) static gboolean inited; @@ -1690,35 +907,6 @@ mono_domain_fire_assembly_load_event (MonoDomain *domain, MonoAssembly *assembly gpointer args [1]; args [0] = MONO_HANDLE_RAW (assembly_handle); mono_runtime_try_invoke_handle (method, NULL_HANDLE, args, error); -#else - MonoObjectHandle appdomain = MONO_HANDLE_NEW (MonoObject, &domain->domain->mbr.obj); - MonoClass *klass = mono_handle_class (appdomain); - - MONO_STATIC_POINTER_INIT (MonoClassField, assembly_load_field) - - assembly_load_field = mono_class_get_field_from_name_full (klass, "AssemblyLoad", NULL); - g_assert (assembly_load_field); - - MONO_STATIC_POINTER_INIT_END (MonoClassField, assembly_load_field) - - if (!MONO_HANDLE_GET_FIELD_BOOL (appdomain, MonoObject*, assembly_load_field)) - goto exit; // No events waiting to be triggered - - MonoReflectionAssemblyHandle reflection_assembly; - reflection_assembly = mono_assembly_get_object_handle (domain, assembly, error); - goto_if_nok (error, exit); - - MONO_STATIC_POINTER_INIT (MonoMethod, assembly_load_method) - - assembly_load_method = mono_class_get_method_from_name_checked (klass, "DoAssemblyLoad", -1, 0, error); - g_assert (assembly_load_method); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, assembly_load_method) - - void *params [1]; - params [0] = MONO_HANDLE_RAW (reflection_assembly); - mono_runtime_invoke_handle_void (assembly_load_method, appdomain, params, error); -#endif exit: HANDLE_FUNCTION_RETURN (); @@ -1742,14 +930,12 @@ mono_domain_fire_assembly_load (MonoAssemblyLoadContext *alc, MonoAssembly *asse mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Loading assembly %s (%p) into domain %s (%p) and ALC %p", assembly->aname.name, assembly, domain->friendly_name, domain, alc); mono_domain_assemblies_lock (domain); -#ifdef ENABLE_NETCORE mono_alc_assemblies_lock (alc); -#endif + add_assemblies_to_domain (domain, assembly, NULL); -#ifdef ENABLE_NETCORE add_assembly_to_alc (alc, assembly); + mono_alc_assemblies_unlock (alc); -#endif mono_domain_assemblies_unlock (domain); if (assembly->context.kind != MONO_ASMCTX_INTERNAL) @@ -1774,160 +960,6 @@ mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assemb return FALSE; } -#ifndef ENABLE_NETCORE -/* - * LOCKING: Acquires the domain assemblies lock. - */ -static void -set_domain_search_path (MonoDomain *domain) -{ - HANDLE_FUNCTION_ENTER (); - ERROR_DECL (error); - MonoAppDomainSetupHandle setup; - gchar **tmp; - gchar *search_path = NULL; - gint npaths = 1; - gchar **pvt_split = NULL; - GError *gerror = NULL; - gint appbaselen = -1; - - /* - * We use the low-level domain assemblies lock, since this is called from - * assembly loads hooks, which means this thread might hold the loader lock. - */ - mono_domain_assemblies_lock (domain); - - if (!MONO_BOOL (domain->setup)) - goto exit; - - setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup); - - if (domain->search_path && !MONO_HANDLE_GET_BOOL (setup, path_changed)) - goto exit; - - if (!MONO_HANDLE_GET_BOOL (setup, application_base)) - goto exit; // Must set application base to get private path working - - if (MONO_HANDLE_GET_BOOL (setup, private_bin_path)) { - search_path = mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString, setup, private_bin_path), error); - if (!is_ok (error)) { /*FIXME maybe we should bubble up the error.*/ - g_warning ("Could not decode AppDomain search path since it contains invalid characters"); - goto exit; - } - } - - if (domain->private_bin_path) { - if (search_path == NULL) - search_path = domain->private_bin_path; - else { - gchar *tmp2 = search_path; - search_path = g_strjoin (";", search_path, domain->private_bin_path, (const char*)NULL); - g_free (tmp2); - } - } - - if (search_path) { - /* - * As per MSDN documentation, AppDomainSetup.PrivateBinPath contains a list of - * directories relative to ApplicationBase separated by semicolons (see - * http://msdn2.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx) - * The loop below copes with the fact that some Unix applications may use ':' (or - * System.IO.Path.PathSeparator) as the path search separator. We replace it with - * ';' for the subsequent split. - * - * The issue was reported in bug #81446 - */ -#ifndef TARGET_WIN32 - g_strdelimit (search_path, ':', ';'); -#endif - pvt_split = g_strsplit (search_path, ";", 1000); - g_free (search_path); - for (tmp = pvt_split; *tmp; tmp++, npaths++); - } - - g_strfreev (domain->search_path); - domain->search_path = NULL; - - tmp = g_new (gchar*, npaths + 1); - tmp [npaths] = NULL; - - *tmp = mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString, setup, application_base), error); - if (!is_ok (error)) { - g_free (tmp); - goto exit; - } - - domain->search_path = tmp; - - /* FIXME: is this needed? */ - if (strncmp (*tmp, "file://", 7) == 0) { - gchar *file = *tmp; - gchar *uri = *tmp; - gchar *tmpuri; - - if (uri [7] != '/') - uri = g_strdup_printf ("file:///%s", uri + 7); - - tmpuri = uri; - uri = mono_escape_uri_string (tmpuri); - *tmp = g_filename_from_uri (uri, NULL, &gerror); - g_free (uri); - - if (tmpuri != file) - g_free (tmpuri); - - if (gerror != NULL) { - g_warning ("%s\n", gerror->message); - g_error_free (gerror); - *tmp = file; - } else { - g_free (file); - } - } - - for (gsize i = 1; pvt_split && i < npaths; i++) { - if (g_path_is_absolute (pvt_split [i - 1])) { - tmp [i] = g_strdup (pvt_split [i - 1]); - } else { - tmp [i] = g_build_filename (tmp [0], pvt_split [i - 1], (const char*)NULL); - } - - if (strchr (tmp [i], '.')) { - gchar *reduced; - gchar *freeme; - - reduced = mono_path_canonicalize (tmp [i]); - if (appbaselen == -1) - appbaselen = strlen (tmp [0]); - - if (strncmp (tmp [0], reduced, appbaselen)) { - g_free (reduced); - g_free (tmp [i]); - tmp [i] = g_strdup (""); - continue; - } - - freeme = tmp [i]; - tmp [i] = reduced; - g_free (freeme); - } - } - - if (MONO_HANDLE_GET_BOOL (setup, private_bin_path_probe)) { - g_free (tmp [0]); - tmp [0] = g_strdup (""); - } - - MONO_HANDLE_SETVAL (setup, path_changed, MonoBoolean, FALSE); -exit: - mono_error_cleanup (error); - g_strfreev (pvt_split); - mono_domain_assemblies_unlock (domain); - HANDLE_FUNCTION_RETURN (); -} -#endif - -#ifdef DISABLE_SHADOW_COPY gboolean mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name) { @@ -1940,492 +972,34 @@ mono_make_shadow_copy (const char *filename, MonoError *error) error_init (error); return (char *) filename; } -#else - -typedef enum { - SHADOW_COPY_SIBLING_EXT_APPEND, - SHADOW_COPY_SIBLING_EXT_REPLACE, -} ShadowCopySiblingExt; -static -gchar * -make_sibling_path (const gchar *path, gint pathlen, const char *extension, ShadowCopySiblingExt extopt) +/** + * mono_domain_from_appdomain: + */ +MonoDomain * +mono_domain_from_appdomain (MonoAppDomain *appdomain_raw) { - gchar *result = NULL; - switch (extopt) { - case SHADOW_COPY_SIBLING_EXT_APPEND: { - result = g_strconcat (path, extension, (const char*)NULL); - break; - } - case SHADOW_COPY_SIBLING_EXT_REPLACE: { - /* expect path to be a .dll or .exe (or some case insensitive variant) */ - g_assert (pathlen >= 4 && path[pathlen - 4] == '.'); - GString *s = g_string_sized_new (pathlen - 4 + strlen (extension)); - g_string_append_len (s, path, pathlen - 4); - g_string_append (s, extension); - result = g_string_free (s, FALSE); - break; - } - default: - g_assert_not_reached (); - } - return result; + return mono_domain_get (); } -static gboolean -shadow_copy_sibling (const gchar *src_pristine, gint srclen, const char *extension, ShadowCopySiblingExt extopt, const gchar *target_pristine, gint targetlen) +MonoDomain * +mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain) { - gchar *file = NULL; - gunichar2 *orig = NULL; - gunichar2 *dest = NULL; - gboolean copy_result = TRUE; - gchar *target = NULL; - - char *src = make_sibling_path (src_pristine, srclen, extension, extopt); - - if (IS_PORTABILITY_CASE) { - file = mono_portability_find_file (src, TRUE); - if (file == NULL) - goto exit; - } else if (!g_file_test (src, G_FILE_TEST_IS_REGULAR)) - goto exit; - - orig = g_utf8_to_utf16 (src, strlen (src), NULL, NULL, NULL); + return mono_get_root_domain (); +} - target = make_sibling_path (target_pristine, targetlen, extension, extopt); - dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL); +static gboolean +try_load_from (MonoAssembly **assembly, + const gchar *path1, const gchar *path2, + const gchar *path3, const gchar *path4, + const MonoAssemblyOpenRequest *req) +{ + gchar *fullpath; + gboolean found = FALSE; - mono_w32file_delete (dest); - - gint32 copy_error; - copy_result = mono_w32file_copy (orig, dest, TRUE, ©_error); - - /* Fix for bug #556884 - make sure the files have the correct mode so that they can be - * overwritten when updated in their original locations. */ - if (copy_result) - copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL); - -exit: - g_free (file); - g_free (orig); - g_free (dest); - g_free (src); - g_free (target); - return copy_result; -} - -static gint32 -get_cstring_hash (const char *str) -{ - const char *p; - gint32 h = 0; - - if (!str || !str [0]) - return 0; - - gsize const len = strlen (str); - p = str; - for (gsize i = 0; i < len; i++) { - h = (h << 5) - h + *p; - p++; - } - - return h; -} - -/* - * Returned memory is malloc'd. Called must free it - */ -static char * -get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error) -{ - MonoAppDomainSetup *setup; - char *cache_path = NULL; - char *appname = NULL; - char *userdir = NULL; - char *location; - - error_init (error); - - setup = domain->setup; - if (setup->cache_path != NULL && setup->application_name != NULL) { - cache_path = mono_string_to_utf8_checked_internal (setup->cache_path, error); - return_val_if_nok (error, NULL); - -#ifndef TARGET_WIN32 - { - gint i; - for (i = strlen (cache_path) - 1; i >= 0; i--) - if (cache_path [i] == '\\') - cache_path [i] = '/'; - } -#endif - - appname = mono_string_to_utf8_checked_internal (setup->application_name, error); - if (!is_ok (error)) { - g_free (cache_path); - return NULL; - } - - location = g_build_filename (cache_path, appname, "assembly", "shadow", (const char*)NULL); - } else { - userdir = g_strdup_printf ("%s-mono-cachepath", g_get_user_name ()); - location = g_build_filename (g_get_tmp_dir (), userdir, "assembly", "shadow", (const char*)NULL); - } - g_free (appname); - g_free (cache_path); - g_free (userdir); - return location; -} - -static char * -get_shadow_assembly_location (const char *filename, MonoError *error) -{ - gint32 hash = 0, hash2 = 0; - char name_hash [9]; - char path_hash [30]; - char *bname = g_path_get_basename (filename); - char *dirname = g_path_get_dirname (filename); - char *location, *tmploc; - MonoDomain *domain = mono_domain_get (); - - error_init (error); - - hash = get_cstring_hash (bname); - hash2 = get_cstring_hash (dirname); - g_snprintf (name_hash, sizeof (name_hash), "%08x", hash); - g_snprintf (path_hash, sizeof (path_hash), "%08x_%08x_%08x", hash ^ hash2, hash2, domain->shadow_serial); - tmploc = get_shadow_assembly_location_base (domain, error); - if (!is_ok (error)) { - g_free (bname); - g_free (dirname); - return NULL; - } - - location = g_build_filename (tmploc, name_hash, path_hash, bname, (const char*)NULL); - g_free (tmploc); - g_free (bname); - g_free (dirname); - return location; -} - -static gboolean -private_file_needs_copying (const char *src, struct stat *sbuf_src, char *dest) -{ - struct stat sbuf_dest; - gchar *stat_src; - gchar *real_src = mono_portability_find_file (src, TRUE); - - if (!real_src) - stat_src = (gchar*)src; - else - stat_src = real_src; - - if (stat (stat_src, sbuf_src) == -1) { - time_t tnow = time (NULL); - - if (real_src) - g_free (real_src); - - memset (sbuf_src, 0, sizeof (*sbuf_src)); - sbuf_src->st_mtime = tnow; - sbuf_src->st_atime = tnow; - return TRUE; - } - - if (real_src) - g_free (real_src); - - if (stat (dest, &sbuf_dest) == -1) - return TRUE; - - if (sbuf_src->st_size == sbuf_dest.st_size && - sbuf_src->st_mtime == sbuf_dest.st_mtime) - return FALSE; - - return TRUE; -} - -static gboolean -shadow_copy_create_ini (const char *shadow, const char *filename) -{ - gunichar2 *u16_ini = NULL; - gboolean result = FALSE; - guint32 n; - HANDLE handle = INVALID_HANDLE_VALUE; - gchar *full_path = NULL; - - char *dir_name = g_path_get_dirname (shadow); - char *ini_file = g_build_filename (dir_name, "__AssemblyInfo__.ini", (const char*)NULL); - g_free (dir_name); - result = g_file_test (ini_file, G_FILE_TEST_IS_REGULAR); - if (result) - goto exit; - - u16_ini = g_utf8_to_utf16 (ini_file, strlen (ini_file), NULL, NULL, NULL); - if (!u16_ini) - goto exit; - - handle = mono_w32file_create (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, CREATE_NEW, FileAttributes_Normal); - if (handle == INVALID_HANDLE_VALUE) - goto exit; - - full_path = mono_path_resolve_symlinks (filename); - gint32 win32error; - win32error = 0; - result = mono_w32file_write (handle, full_path, strlen (full_path), &n, &win32error); -exit: - if (handle != INVALID_HANDLE_VALUE) - mono_w32file_close (handle); - g_free (u16_ini); - g_free (full_path); - g_free (ini_file); - return result; -} - -gboolean -mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name) -{ - ERROR_DECL (error); - MonoAppDomainSetup *setup; - gchar *all_dirs = NULL; - gchar **dir_ptr; - gchar **directories = NULL; - gchar *shadow_status_string; - gchar *base_dir = NULL; - gboolean shadow_enabled; - gboolean found = FALSE; - - if (domain == NULL) - goto exit; - - setup = domain->setup; - if (setup == NULL || setup->shadow_copy_files == NULL) - goto exit; - - shadow_status_string = mono_string_to_utf8_checked_internal (setup->shadow_copy_files, error); - if (!is_ok (error)) - goto exit; - - shadow_enabled = !g_ascii_strncasecmp (shadow_status_string, "true", 4); - g_free (shadow_status_string); - - if (!shadow_enabled) - goto exit; - - found = (setup->shadow_copy_directories == NULL); - if (found) - goto exit; - - /* Is dir_name a shadow_copy destination already? */ - base_dir = get_shadow_assembly_location_base (domain, error); - if (!is_ok (error)) - goto exit; - - found = strstr (dir_name, base_dir) != 0; - if (found) - goto exit; - - all_dirs = mono_string_to_utf8_checked_internal (setup->shadow_copy_directories, error); - if (!is_ok (error)) - goto exit; - - directories = g_strsplit (all_dirs, G_SEARCHPATH_SEPARATOR_S, 1000); - dir_ptr = directories; - while (!found && *dir_ptr) { - found = (**dir_ptr != '\0' && !strcmp (*dir_ptr, dir_name)); - dir_ptr++; - } -exit: - mono_error_cleanup (error); - g_free (base_dir); - g_strfreev (directories); - g_free (all_dirs); - return found; -} - -/* -This function raises exceptions so it can cause as sorts of nasty stuff if called -while holding a lock. -Returns old file name if shadow copy is disabled, new shadow copy file name if successful -or NULL if source file not found. -FIXME bubble up the error instead of raising it here -*/ -char * -mono_make_shadow_copy (const char *filename, MonoError *oerror) -{ - ERROR_DECL (error); - gint filename_len, shadow_len; - gunichar2 *orig, *dest; - guint32 attrs; - char *shadow; - gboolean copy_result; - struct stat src_sbuf; - struct utimbuf utbuf; - char *dir_name = g_path_get_dirname (filename); - MonoDomain *domain = mono_domain_get (); - char *shadow_dir; - gint32 copy_error; - -#ifndef ENABLE_NETCORE - set_domain_search_path (domain); -#endif - - if (!mono_is_shadow_copy_enabled (domain, dir_name)) { - g_free (dir_name); - return (char *) filename; - } - - /* Is dir_name a shadow_copy destination already? */ - shadow_dir = get_shadow_assembly_location_base (domain, error); - if (!is_ok (error)) { - mono_error_cleanup (error); - g_free (dir_name); - mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in shadow directory name)."); - return NULL; - } - - if (strstr (dir_name, shadow_dir)) { - g_free (shadow_dir); - g_free (dir_name); - return (char *) filename; - } - g_free (shadow_dir); - g_free (dir_name); - - shadow = get_shadow_assembly_location (filename, error); - if (!is_ok (error)) { - mono_error_cleanup (error); - mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in file name)."); - return NULL; - } - - if (g_ensure_directory_exists (shadow) == FALSE) { - g_free (shadow); - mono_error_set_execution_engine (oerror, "Failed to create shadow copy (ensure directory exists)."); - return NULL; - } - - if (!private_file_needs_copying (filename, &src_sbuf, shadow)) - return (char*) shadow; - - orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL); - dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL); - mono_w32file_delete (dest); - - /* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather - * let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly) - * and not have it runtime error" */ - attrs = mono_w32file_get_attributes (orig); - if (attrs == INVALID_FILE_ATTRIBUTES) { - g_free (shadow); - return (char *)filename; - } - - copy_result = mono_w32file_copy (orig, dest, TRUE, ©_error); - - /* Fix for bug #556884 - make sure the files have the correct mode so that they can be - * overwritten when updated in their original locations. */ - if (copy_result) - copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL); - - g_free (dest); - g_free (orig); - - if (copy_result == FALSE) { - g_free (shadow); - - /* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */ - if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND || mono_w32error_get_last() == ERROR_PATH_NOT_FOUND) - return NULL; /* file not found, shadow copy failed */ - - mono_error_set_execution_engine (oerror, "Failed to create shadow copy (mono_w32file_copy)."); - return NULL; - } - - /* attempt to copy .mdb, .pdb and .config if they exist */ - filename_len = strlen (filename); - shadow_len = strlen (shadow); - - copy_result = shadow_copy_sibling (filename, filename_len, ".mdb", SHADOW_COPY_SIBLING_EXT_APPEND, shadow, shadow_len); - if (copy_result) - copy_result = shadow_copy_sibling (filename, filename_len, ".pdb", SHADOW_COPY_SIBLING_EXT_REPLACE, shadow, shadow_len); - if (copy_result) - copy_result = shadow_copy_sibling (filename, filename_len, ".config", SHADOW_COPY_SIBLING_EXT_APPEND, shadow, shadow_len); - - if (!copy_result) { - g_free (shadow); - mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (mono_w32file_copy)."); - return NULL; - } - - /* Create a .ini file containing the original assembly location */ - if (!shadow_copy_create_ini (shadow, filename)) { - g_free (shadow); - mono_error_set_execution_engine (oerror, "Failed to create shadow copy .ini file."); - return NULL; - } - - utbuf.actime = src_sbuf.st_atime; - utbuf.modtime = src_sbuf.st_mtime; - utime (shadow, &utbuf); - - return shadow; -} -#endif /* DISABLE_SHADOW_COPY */ - -/** - * mono_domain_from_appdomain: - */ -MonoDomain * -mono_domain_from_appdomain (MonoAppDomain *appdomain_raw) -{ - HANDLE_FUNCTION_ENTER (); - MonoDomain *result; - MONO_ENTER_GC_UNSAFE; - MONO_HANDLE_DCL (MonoAppDomain, appdomain); - result = mono_domain_from_appdomain_handle (appdomain); - MONO_EXIT_GC_UNSAFE; - HANDLE_FUNCTION_RETURN_VAL (result); -} - -MonoDomain * -mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain) -{ -#ifndef ENABLE_NETCORE - HANDLE_FUNCTION_ENTER (); - MonoDomain *dom = NULL; - if (MONO_HANDLE_IS_NULL (appdomain)) - goto leave; - - if (mono_class_is_transparent_proxy (mono_handle_class (appdomain))) { - MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, appdomain); - MonoRealProxyHandle rp = MONO_HANDLE_NEW_GET (MonoRealProxy, tp, rp); - - dom = mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp, target_domain_id)); - } else - dom = MONO_HANDLE_GETVAL (appdomain, data); - -leave: - HANDLE_FUNCTION_RETURN_VAL (dom); -#else - return mono_get_root_domain (); -#endif -} - - -static gboolean -try_load_from (MonoAssembly **assembly, - const gchar *path1, const gchar *path2, - const gchar *path3, const gchar *path4, - const MonoAssemblyOpenRequest *req) -{ - gchar *fullpath; - gboolean found = FALSE; - - *assembly = NULL; - fullpath = g_build_filename (path1, path2, path3, path4, (const char*)NULL); + *assembly = NULL; + fullpath = g_build_filename (path1, path2, path3, path4, (const char*)NULL); if (IS_PORTABILITY_SET) { gchar *new_fullpath = mono_portability_find_file (fullpath, TRUE); @@ -2494,7 +1068,6 @@ real_load (gchar **search_path, const gchar *culture, const gchar *name, const M return result; } -#ifdef ENABLE_NETCORE static char * get_app_context_base_directory (MonoError *error) { @@ -2515,7 +1088,6 @@ get_app_context_base_directory (MonoError *error) HANDLE_FUNCTION_RETURN_VAL (base_dir); } -#endif /* * Try loading the assembly from ApplicationBase and PrivateBinPath @@ -2533,14 +1105,9 @@ mono_domain_assembly_preload (MonoAssemblyLoadContext *alc, { MonoDomain *domain = mono_alc_domain (alc); MonoAssembly *result = NULL; -#ifdef ENABLE_NETCORE + g_assert (alc); g_assert (domain == mono_domain_get ()); -#endif - -#ifndef ENABLE_NETCORE - set_domain_search_path (domain); -#endif MonoAssemblyCandidatePredicate predicate = NULL; void* predicate_ud = NULL; @@ -2553,7 +1120,6 @@ mono_domain_assembly_preload (MonoAssemblyLoadContext *alc, req.request.predicate = predicate; req.request.predicate_ud = predicate_ud; -#ifdef ENABLE_NETCORE if (!mono_runtime_get_no_exec ()) { char *search_path [2]; search_path [1] = NULL; @@ -2566,19 +1132,6 @@ mono_domain_assembly_preload (MonoAssemblyLoadContext *alc, g_free (base_dir); } -#else - if (domain->search_path && domain->search_path [0] != NULL) { - if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s search path is:", domain->friendly_name); - for (int i = 0; domain->search_path [i]; i++) { - const char *p = domain->search_path[i]; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "\tpath[%d] = '%s'", i, p); - } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "End of domain %s search path.", domain->friendly_name); - } - result = real_load (domain->search_path, aname->culture, aname->name, &req); - } -#endif if (result == NULL && assemblies_path && assemblies_path [0] != NULL) { result = real_load (assemblies_path, aname->culture, aname->name, &req); @@ -2602,7 +1155,6 @@ mono_domain_assembly_search (MonoAssemblyLoadContext *alc, MonoAssembly *request GSList *tmp; MonoAssembly *ass; -#ifdef ENABLE_NETCORE const MonoAssemblyNameEqFlags eq_flags = MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE; mono_alc_assemblies_lock (alc); @@ -2617,35 +1169,10 @@ mono_domain_assembly_search (MonoAssemblyLoadContext *alc, MonoAssembly *request return ass; } mono_alc_assemblies_unlock (alc); -#else - MonoDomain *domain = mono_alc_domain (alc); - - const gboolean strong_name = aname->public_key_token[0] != 0; - /* If it's not a strong name, any version that has the right simple - * name is good enough to satisfy the request. .NET Framework also - * ignores case differences in this case. */ - const MonoAssemblyNameEqFlags eq_flags = (MonoAssemblyNameEqFlags)(strong_name ? MONO_ANAME_EQ_IGNORE_CASE : - (MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE)); - - mono_domain_assemblies_lock (domain); - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - ass = (MonoAssembly *)tmp->data; - g_assert (ass != NULL); - /* Dynamic assemblies can't match here in MS.NET */ - gboolean ass_ref_only = mono_asmctx_get_kind (&ass->context) == MONO_ASMCTX_REFONLY; - if (assembly_is_dynamic (ass) || refonly != ass_ref_only || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags)) - continue; - - mono_domain_assemblies_unlock (domain); - return ass; - } - mono_domain_assemblies_unlock (domain); -#endif return NULL; } -#if ENABLE_NETCORE MonoReflectionAssemblyHandle ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle, MonoStackCrawlMark *stack_mark, gpointer load_Context, MonoError *error) { @@ -2708,54 +1235,6 @@ ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle, fail: return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); } -#endif - -#ifndef ENABLE_NETCORE -MonoReflectionAssemblyHandle -ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoolean refOnly, MonoStackCrawlMark *stack_mark, MonoError *error) -{ - error_init (error); - MonoDomain *domain = mono_domain_get (); - char *name, *filename; - MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); - - name = NULL; - - if (MONO_HANDLE_IS_NULL (fname)) { - mono_error_set_argument_null (error, "assemblyFile", ""); - goto leave; - } - - name = filename = mono_string_handle_to_utf8 (fname, error); - goto_if_nok (error, leave); - - MonoAssembly *requesting_assembly; - requesting_assembly = NULL; - if (!refOnly) - requesting_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark); - - MonoAssembly *ass; - MonoAssemblyOpenRequest req; - mono_assembly_request_prepare_open (&req, refOnly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_LOADFROM, mono_domain_default_alc (domain)); - req.requesting_assembly = requesting_assembly; - ass = mono_assembly_request_open (filename, &req, &status); - - if (!ass) { - if (status == MONO_IMAGE_IMAGE_INVALID) - mono_error_set_bad_image_by_name (error, name, "Invalid Image: %s", name); - else - mono_error_set_simple_file_not_found (error, name, refOnly); - goto leave; - } - - result = mono_assembly_get_object_handle (domain, ass, error); - -leave: - g_free (name); - return result; -} -#endif static MonoAssembly * @@ -2794,22 +1273,6 @@ leave: HANDLE_FUNCTION_RETURN_VAL (ass); } -#ifndef ENABLE_NETCORE -MonoReflectionAssemblyHandle -ves_icall_System_Reflection_Assembly_LoadFile_internal (MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error) -{ - MonoDomain *domain = mono_domain_get (); - MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); - MonoAssembly *executing_assembly; - executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark); - MonoAssembly *ass = mono_alc_load_file (mono_domain_default_alc (domain), fname, executing_assembly, MONO_ASMCTX_INDIVIDUAL, error); - goto_if_nok (error, leave); - - result = mono_assembly_get_object_handle (domain, ass, error); -leave: - return result; -} -#else MonoReflectionAssemblyHandle ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer alc_ptr, MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error) { @@ -2827,12 +1290,10 @@ ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer a leave: return result; } -#endif static MonoAssembly* mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *raw_assembly, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error); -#ifdef ENABLE_NETCORE MonoReflectionAssemblyHandle ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFromStream (gpointer native_alc, gpointer raw_assembly_ptr, gint32 raw_assembly_len, gpointer raw_symbols_ptr, gint32 raw_symbols_len, MonoError *error) { @@ -2848,47 +1309,13 @@ ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFromStream (gpoi leave: return result; } -#else -MonoReflectionAssemblyHandle -ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad, - MonoArrayHandle raw_assembly, - MonoArrayHandle raw_symbol_store, MonoObjectHandle evidence, - MonoBoolean refonly, - MonoError *error) -{ - MonoAssembly *ass; - MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); - MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); - MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain); - - guint8 *raw_assembly_ptr = (guint8 *)mono_array_handle_addr (raw_assembly, sizeof (guint8), 0); - guint32 raw_assembly_len = mono_array_handle_length (raw_assembly); - - guint8 *raw_symbols_ptr = NULL; - guint32 raw_symbols_len = 0; - if (!MONO_HANDLE_IS_NULL (raw_symbol_store)) { - raw_symbols_ptr = (guint8 *)mono_array_handle_addr (raw_symbol_store, sizeof (guint8), 0); - raw_symbols_len = mono_array_handle_length (raw_symbol_store); - } - ass = mono_alc_load_raw_bytes (alc, raw_assembly_ptr, raw_assembly_len, raw_symbols_ptr, raw_symbols_len, refonly, error); - goto_if_nok (error, leave); - - refass = mono_assembly_get_object_handle (domain, ass, error); - if (!MONO_HANDLE_IS_NULL (refass)) - MONO_HANDLE_SET (refass, evidence, evidence); - -leave: - return refass; -} -#endif /* ENABLE_NETCORE */ - -static MonoAssembly* -mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error) -{ - MonoAssembly *ass = NULL; - MonoImageOpenStatus status; - MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, TRUE, NULL, refonly, FALSE, NULL, NULL); +static MonoAssembly* +mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error) +{ + MonoAssembly *ass = NULL; + MonoImageOpenStatus status; + MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, TRUE, NULL, refonly, FALSE, NULL, NULL); if (!image) { mono_error_set_bad_image_by_name (error, "In memory assembly", "0x%p", assembly_data); @@ -2898,21 +1325,6 @@ mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, gu if (raw_symbol_data) mono_debug_open_image_from_memory (image, raw_symbol_data, raw_symbol_len); -#ifndef ENABLE_NETCORE - MonoAssembly* redirected_asm = NULL; - MonoImageOpenStatus new_status = MONO_IMAGE_OK; - // http://blogs.microsoft.co.il/sasha/2010/06/09/assemblyreflectiononlyload-ignores-assembly-binding-redirects/ - if (!refonly && (redirected_asm = mono_assembly_binding_applies_to_image (alc, image, &new_status))) { - mono_image_close (image); - image = redirected_asm->image; - mono_image_addref (image); /* so that mono_image close, below, has something to do */ - } else if (new_status != MONO_IMAGE_OK) { - mono_image_close (image); - mono_error_set_bad_image_by_name (error, "In Memory assembly", "0x%p was assembly binding redirected to another assembly that failed to load", assembly_data); - return ass; - } -#endif - MonoAssemblyLoadRequest req; mono_assembly_request_prepare_load (&req, refonly? MONO_ASMCTX_REFONLY : MONO_ASMCTX_INDIVIDUAL, alc); ass = mono_assembly_request_load_from (image, "", &req, &status); @@ -2929,263 +1341,6 @@ mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, gu return ass; } -#ifndef ENABLE_NETCORE -MonoReflectionAssemblyHandle -ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad, MonoStringHandle assRef, MonoObjectHandle evidence, MonoBoolean refOnly, MonoStackCrawlMark *stack_mark, MonoError *error) -{ - MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); - MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *ass; - MonoAssemblyName aname; - gchar *name = NULL; - gboolean parsed; - - g_assert (!MONO_HANDLE_IS_NULL (assRef)); - - name = mono_string_handle_to_utf8 (assRef, error); - goto_if_nok (error, fail); - parsed = mono_assembly_name_parse (name, &aname); - g_free (name); - - if (!parsed) { - MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); - /* This is a parse error... */ - if (!refOnly) { - MonoAssembly *assm = mono_try_assembly_resolve_handle (mono_domain_default_alc (domain), assRef, NULL, refOnly, error); - goto_if_nok (error, fail); - if (assm) { - refass = mono_assembly_get_object_handle (domain, assm, error); - goto_if_nok (error, fail); - } - } - return refass; - } - - MonoAssemblyContextKind asmctx; - asmctx = refOnly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_DEFAULT; - const char *basedir; - basedir = NULL; - if (!refOnly) { - /* Determine if the current assembly is in LoadFrom context. - * If it is, we must include the executing assembly's basedir - * when probing for the given assembly name, and also load the - * requested assembly in LoadFrom context. - */ - MonoAssembly *executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark); - if (executing_assembly && mono_asmctx_get_kind (&executing_assembly->context) == MONO_ASMCTX_LOADFROM) { - asmctx = MONO_ASMCTX_LOADFROM; - basedir = executing_assembly->basedir; - } - } - - - MonoAssemblyByNameRequest req; - mono_assembly_request_prepare_byname (&req, asmctx, mono_domain_default_alc (domain)); - req.basedir = basedir; - req.no_postload_search = TRUE; - ass = mono_assembly_request_byname (&aname, &req, &status); - mono_assembly_name_free_internal (&aname); - - if (!ass) { - /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */ - if (!refOnly) { - ass = mono_try_assembly_resolve_handle (mono_domain_default_alc (domain), assRef, NULL, refOnly, error); - goto_if_nok (error, fail); - } - if (!ass) - goto fail; - } - - g_assert (ass); - MonoReflectionAssemblyHandle refass; - refass = mono_assembly_get_object_handle (domain, ass, error); - goto_if_nok (error, fail); - - MONO_HANDLE_SET (refass, evidence, evidence); - - return refass; -fail: - return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); -} - -void -ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error) -{ - MonoDomain * domain = mono_domain_get_by_id (domain_id); - - if (NULL == domain) { - mono_error_set_execution_engine (error, "Failed to unload domain, domain id not found"); - return; - } - - if (domain == mono_get_root_domain ()) { - mono_error_set_generic_error (error, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded."); - return; - } - - /* - * Unloading seems to cause problems when running NUnit/NAnt, hence - * this workaround. - */ - if (g_hasenv ("MONO_NO_UNLOAD")) - return; - - MonoException *exc = NULL; - mono_domain_try_unload (domain, (MonoObject**)&exc); - if (exc) - mono_error_set_exception_instance (error, exc); -} - -MonoBoolean -ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error) -{ - MonoDomain *domain = mono_domain_get_by_id (domain_id); - - if (!domain) - return TRUE; - - return mono_domain_is_unloading (domain); -} - -void -ves_icall_System_AppDomain_DoUnhandledException (MonoAppDomainHandle ad, MonoExceptionHandle exc, MonoError *error) -{ - mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject, exc), error); - mono_error_assert_ok (error); -} - -gint32 -ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad, - MonoReflectionAssemblyHandle refass, MonoArrayHandle args, - MonoError *error) -{ - MonoImage *image; - MonoMethod *method; - - g_assert (!MONO_HANDLE_IS_NULL (refass)); - MonoAssembly *assembly = MONO_HANDLE_GETVAL (refass, assembly); - image = assembly->image; - g_assert (image); - - method = mono_get_method_checked (image, mono_image_get_entry_point (image), NULL, NULL, error); - - if (!method) - g_error ("No entry point method found in %s due to %s", image->name, mono_error_get_message (error)); - - if (MONO_HANDLE_IS_NULL (args)) { - MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data); - MONO_HANDLE_ASSIGN (args , mono_array_new_handle (domain, mono_defaults.string_class, 0, error)); - mono_error_assert_ok (error); - } - - int res = mono_runtime_exec_main_checked (method, MONO_HANDLE_RAW (args), error); - return res; -} - -MonoAppDomainHandle -ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error) -{ - error_init (error); - MonoDomain *old_domain = mono_domain_get (); - - if (!mono_domain_set_fast (MONO_HANDLE_GETVAL (ad, data), FALSE)) { - mono_error_set_appdomain_unloaded (error); - return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); - } - - return MONO_HANDLE_NEW (MonoAppDomain, old_domain->domain); -} - -MonoAppDomainHandle -ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *error) -{ - MonoDomain *current_domain = mono_domain_get (); - MonoDomain *domain = mono_domain_get_by_id (domainid); - - if (!domain || !mono_domain_set_fast (domain, FALSE)) { - mono_error_set_appdomain_unloaded (error); - return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE); - } - - return MONO_HANDLE_NEW (MonoAppDomain, current_domain->domain); -} - -void -ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error) -{ - error_init (error); - mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data)); -} - -void -ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error) -{ - error_init (error); - MonoDomain *domain = mono_domain_get_by_id (domain_id); - - if (!domain) { - /* - * Raise an exception to prevent the managed code from executing a pop - * later. - */ - mono_error_set_appdomain_unloaded (error); - return; - } - - mono_thread_push_appdomain_ref (domain); -} - -void -ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error) -{ - error_init (error); - mono_thread_pop_appdomain_ref (); -} - -MonoAppContextHandle -ves_icall_System_AppDomain_InternalGetContext (MonoError *error) -{ - error_init (error); - return mono_context_get_handle (); -} - -MonoAppContextHandle -ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError *error) -{ - error_init (error); - return MONO_HANDLE_NEW (MonoAppContext, mono_domain_get ()->default_context); -} - -MonoAppContextHandle -ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc, MonoError *error) -{ - error_init (error); - MonoAppContextHandle old_context = mono_context_get_handle (); - - mono_context_set_handle (mc); - - return old_context; -} - -MonoStringHandle -ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error) -{ - error_init (error); - MonoDomain* mono_root_domain = mono_get_root_domain (); - mono_domain_lock (mono_root_domain); - if (process_guid_set) { - mono_domain_unlock (mono_root_domain); - return mono_string_new_utf16_handle (mono_domain_get (), process_guid, sizeof(process_guid)/2, error); - } - MonoGCHandle gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, newguid), TRUE); - memcpy (process_guid, mono_string_chars_internal (MONO_HANDLE_RAW (newguid)), sizeof(process_guid)); - mono_gchandle_free_internal (gchandle); - process_guid_set = TRUE; - mono_domain_unlock (mono_root_domain); - return newguid; -} -#endif - /** * mono_domain_is_unloading: */ @@ -3198,338 +1353,6 @@ mono_domain_is_unloading (MonoDomain *domain) return FALSE; } -#ifndef ENABLE_NETCORE - -static void -clear_cached_vtable (MonoVTable *vtable) -{ - MonoClass *klass = vtable->klass; - MonoDomain *domain = vtable->domain; - MonoClassRuntimeInfo *runtime_info; - void *data; - - runtime_info = m_class_get_runtime_info (klass); - if (runtime_info && runtime_info->max_domain >= domain->domain_id) - runtime_info->domain_vtables [domain->domain_id] = NULL; - if (m_class_has_static_refs (klass) && (data = mono_vtable_get_static_field_data (vtable))) - mono_gc_free_fixed (data); -} - -static G_GNUC_UNUSED void -zero_static_data (MonoVTable *vtable) -{ - MonoClass *klass = vtable->klass; - void *data; - - if (m_class_has_static_refs (klass) && (data = mono_vtable_get_static_field_data (vtable))) - mono_gc_bzero_aligned (data, mono_class_data_size (klass)); -} - -typedef struct unload_data { - gboolean done; - MonoDomain *domain; - char *failure_reason; - gint32 refcount; -} unload_data; - -static void -unload_data_unref (unload_data *data) -{ - if (!data) - return; - gint32 count; - do { - mono_atomic_load_acquire (count, gint32, &data->refcount); - g_assert (count >= 1 && count <= 2); - if (count == 1) { - g_free (data); - return; - } - } while (mono_atomic_cas_i32 (&data->refcount, count - 1, count) != count); -} - -static void -deregister_reflection_info_roots_from_list (MonoImage *image) -{ - GSList *list = image->reflection_info_unregister_classes; - - while (list) { - MonoClass *klass = (MonoClass *)list->data; - - mono_class_free_ref_info (klass); - - list = list->next; - } - - image->reflection_info_unregister_classes = NULL; -} - -static void -deregister_reflection_info_roots (MonoDomain *domain) -{ - GSList *list; - - mono_domain_assemblies_lock (domain); - for (list = domain->domain_assemblies; list; list = list->next) { - MonoAssembly *assembly = (MonoAssembly *)list->data; - MonoImage *image = assembly->image; - int i; - - /* - * No need to take the image lock here since dynamic images are appdomain bound and - * at this point the mutator is gone. Taking the image lock here would mean - * promoting it from a simple lock to a complex lock, which we better avoid if - * possible. - */ - if (image_is_dynamic (image)) - deregister_reflection_info_roots_from_list (image); - - for (i = 0; i < image->module_count; ++i) { - MonoImage *module = image->modules [i]; - if (module && image_is_dynamic (module)) - deregister_reflection_info_roots_from_list (module); - } - } - mono_domain_assemblies_unlock (domain); -} - -static gsize WINAPI -unload_thread_main (void *arg) -{ - unload_data *data = (unload_data*)arg; - MonoDomain *domain = data->domain; - MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); - int i; - gsize result = 1; // failure - - mono_thread_set_name_constant_ignore_error (mono_thread_internal_current (), "Domain unloader", MonoSetThreadNameFlag_Permanent); - - /* - * FIXME: Abort our parent thread last, so we can return a failure - * indication if aborting times out. - */ - if (!mono_threads_abort_appdomain_threads (domain, -1)) { - data->failure_reason = g_strdup_printf ("Aborting of threads in domain %s timed out.", domain->friendly_name); - goto failure; - } - - if (!mono_threadpool_remove_domain_jobs (domain, -1)) { - data->failure_reason = g_strdup_printf ("Cleanup of threadpool jobs of domain %s timed out.", domain->friendly_name); - goto failure; - } - - /* Finalize all finalizable objects in the doomed appdomain */ - if (!mono_domain_finalize (domain, -1)) { - data->failure_reason = g_strdup_printf ("Finalization of domain %s timed out.", domain->friendly_name); - goto failure; - } - - /* Clear references to our vtables in class->runtime_info. - * We also hold the loader lock because we're going to change - * class->runtime_info. - */ - - mono_loader_lock (); - mono_domain_lock (domain); - mono_mem_manager_lock (memory_manager); - /* - * We need to make sure that we don't have any remsets - * pointing into static data of the to-be-freed domain because - * at the next collections they would be invalid. So what we - * do is we first zero all static data and then do a minor - * collection. Because all references in the static data will - * now be null we won't do any unnecessary copies and after - * the collection there won't be any more remsets. - */ - for (i = 0; i < memory_manager->class_vtable_array->len; ++i) - zero_static_data ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i)); -#if !HAVE_BOEHM_GC - mono_gc_collect (0); -#endif - for (i = 0; i < memory_manager->class_vtable_array->len; ++i) - clear_cached_vtable ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i)); - deregister_reflection_info_roots (domain); - - mono_assembly_cleanup_domain_bindings (domain->domain_id); - - mono_mem_manager_unlock (memory_manager); - mono_domain_unlock (domain); - mono_loader_unlock (); - - domain->state = MONO_APPDOMAIN_UNLOADED; - - /* printf ("UNLOADED %s.\n", domain->friendly_name); */ - - /* remove from the handle table the items related to this domain */ - mono_gchandle_free_domain (domain); - - mono_domain_free (domain, FALSE); - - result = 0; // success -exit: - mono_atomic_store_release (&data->done, TRUE); - unload_data_unref (data); - return result; - -failure: - result = 1; - goto exit; -} - -/** - * mono_domain_unload: - * \param domain The domain to unload - * - * Unloads an appdomain. Follows the process outlined in the comment - * for \c mono_domain_try_unload. - */ -void -mono_domain_unload (MonoDomain *domain) -{ - MONO_ENTER_GC_UNSAFE; - MonoObject *exc = NULL; - mono_domain_try_unload (domain, &exc); - MONO_EXIT_GC_UNSAFE; -} - -static MonoThreadInfoWaitRet -guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable) -{ - MonoThreadInfoWaitRet result; - - MONO_ENTER_GC_SAFE; - result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable); - MONO_EXIT_GC_SAFE; - - return result; -} - -/** - * mono_domain_unload: - * \param domain The domain to unload - * \param exc Exception information - * - * Unloads an appdomain. Follows the process outlined in: - * http://blogs.gotdotnet.com/cbrumme - * - * If doing things the 'right' way is too hard or complex, we do it the - * 'simple' way, which means do everything needed to avoid crashes and - * memory leaks, but not much else. - * - * It is required to pass a valid reference to the exc argument, upon return - * from this function *exc will be set to the exception thrown, if any. - * - * If this method is not called from an icall (embedded scenario for instance), - * it must not be called with any managed frames on the stack, since the unload - * process could end up trying to abort the current thread. - */ -void -mono_domain_try_unload (MonoDomain *domain, MonoObject **exc) -{ - HANDLE_FUNCTION_ENTER (); - ERROR_DECL (error); - MonoThreadHandle *thread_handle = NULL; - MonoAppDomainState prev_state; - MonoMethod *method; - unload_data *thread_data = NULL; - MonoInternalThreadHandle internal; - MonoDomain *caller_domain = mono_domain_get (); - - /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */ - - /* Atomically change our state to UNLOADING */ - prev_state = (MonoAppDomainState)mono_atomic_cas_i32 ((gint32*)&domain->state, - MONO_APPDOMAIN_UNLOADING_START, - MONO_APPDOMAIN_CREATED); - if (prev_state != MONO_APPDOMAIN_CREATED) { - switch (prev_state) { - case MONO_APPDOMAIN_UNLOADING_START: - case MONO_APPDOMAIN_UNLOADING: - *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded."); - goto exit; - case MONO_APPDOMAIN_UNLOADED: - *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded."); - goto exit; - default: - g_warning ("Invalid appdomain state %d", prev_state); - g_assert_not_reached (); - } - } - - mono_domain_set_fast (domain, FALSE); - /* Notify OnDomainUnload listeners */ - method = mono_class_get_method_from_name_checked (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload", -1, 0, error); - g_assert (method); - - mono_runtime_try_invoke (method, domain->domain, NULL, exc, error); - - if (!is_ok (error)) { - if (*exc) - mono_error_cleanup (error); - else - *exc = (MonoObject*)mono_error_convert_to_exception (error); - } - - if (*exc) { - /* Roll back the state change */ - domain->state = MONO_APPDOMAIN_CREATED; - mono_domain_set_fast (caller_domain, FALSE); - goto exit; - } - mono_domain_set_fast (caller_domain, FALSE); - - thread_data = g_new0 (unload_data, 1); - thread_data->domain = domain; - thread_data->failure_reason = NULL; - thread_data->done = FALSE; - thread_data->refcount = 2; /*Must be 2: unload thread + initiator */ - - /*The managed callback finished successfully, now we start tearing down the appdomain*/ - domain->state = MONO_APPDOMAIN_UNLOADING; - /* - * First we create a separate thread for unloading, since - * we might have to abort some threads, including the current one. - * - * Have to attach to the runtime so shutdown can wait for this thread. - * - * Force it to be attached to avoid racing during shutdown. - */ - internal = mono_thread_create_internal_handle (mono_get_root_domain (), unload_thread_main, thread_data, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE, error); - mono_error_assert_ok (error); - - thread_handle = mono_threads_open_thread_handle (MONO_HANDLE_GETVAL (internal, handle)); - - /* Wait for the thread */ - while (!thread_data->done && guarded_wait (thread_handle, MONO_INFINITE_WAIT, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) { - if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) { - /* The unload thread tries to abort us */ - /* The icall wrapper will execute the abort */ - goto exit; - } - } - - if (thread_data->failure_reason) { - /* Roll back the state change */ - domain->state = MONO_APPDOMAIN_CREATED; - - g_warning ("%s", thread_data->failure_reason); - - *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain (thread_data->failure_reason); - - g_free (thread_data->failure_reason); - thread_data->failure_reason = NULL; - } - -exit: - mono_threads_close_thread_handle (thread_handle); - unload_data_unref (thread_data); - HANDLE_FUNCTION_RETURN (); -} - -#endif /* ENABLE_NETCORE */ - -#ifdef ENABLE_NETCORE - /* Remember properties so they can be be installed in AppContext during runtime init */ void mono_runtime_register_appctx_properties (int nprops, const char **keys, const char **values) @@ -3576,5 +1399,3 @@ mono_runtime_install_appctx_properties (void) appctx_keys = NULL; appctx_values = NULL; } - -#endif diff --git a/src/mono/mono/metadata/assembly-internals.h b/src/mono/mono/metadata/assembly-internals.h index 5b31716..9e54790 100644 --- a/src/mono/mono/metadata/assembly-internals.h +++ b/src/mono/mono/metadata/assembly-internals.h @@ -11,11 +11,7 @@ #include #include -#ifndef ENABLE_NETCORE -#define MONO_ASSEMBLY_CORLIB_NAME "mscorlib" -#else #define MONO_ASSEMBLY_CORLIB_NAME "System.Private.CoreLib" -#endif #define MONO_ASSEMBLY_RESOURCE_SUFFIX ".resources" #define MONO_ASSEMBLY_CORLIB_RESOURCE_NAME (MONO_ASSEMBLY_CORLIB_NAME MONO_ASSEMBLY_RESOURCE_SUFFIX) @@ -139,11 +135,6 @@ mono_assembly_candidate_predicate_sn_same_name (MonoAssembly *candidate, gpointe gboolean mono_assembly_check_name_match (MonoAssemblyName *wanted_name, MonoAssemblyName *candidate_name); -#ifndef ENABLE_NETCORE -MonoAssembly* -mono_assembly_binding_applies_to_image (MonoAssemblyLoadContext *alc, MonoImage* image, MonoImageOpenStatus *status); -#endif - MonoAssembly * mono_assembly_loaded_internal (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname, gboolean refonly); diff --git a/src/mono/mono/metadata/assembly-load-context.c b/src/mono/mono/metadata/assembly-load-context.c index 3f5066d..d925fa3 100644 --- a/src/mono/mono/metadata/assembly-load-context.c +++ b/src/mono/mono/metadata/assembly-load-context.c @@ -1,8 +1,6 @@ #include "config.h" #include "mono/utils/mono-compiler.h" -#ifdef ENABLE_NETCORE // MonoAssemblyLoadContext support only in netcore Mono - #include "mono/metadata/assembly.h" #include "mono/metadata/domain-internals.h" #include "mono/metadata/exception-internals.h" @@ -410,7 +408,3 @@ mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext return result; } - -#endif /* ENABLE_NETCORE */ - -MONO_EMPTY_SOURCE_FILE (assembly_load_context) diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index 8421df9..1c9f501 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -386,10 +386,8 @@ static GSList *loaded_assembly_bindings = NULL; static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute") static MonoAssembly* mono_assembly_invoke_search_hook_internal (MonoAssemblyLoadContext *alc, MonoAssembly *requesting, MonoAssemblyName *aname, gboolean refonly, gboolean postload); -#ifdef ENABLE_NETCORE static MonoAssembly* mono_assembly_request_byname_nosearch (MonoAssemblyName *aname, const MonoAssemblyByNameRequest *req, MonoImageOpenStatus *status); -#endif static MonoAssembly* mono_assembly_load_full_gac_base_default (MonoAssemblyName *aname, const char *basedir, MonoAssemblyLoadContext *alc, MonoAssemblyContextKind asmctx, MonoImageOpenStatus *status); static MonoAssembly* @@ -402,10 +400,6 @@ invoke_assembly_preload_hook (MonoAssemblyLoadContext *alc, MonoAssemblyName *an static MonoBoolean mono_assembly_is_in_gac (const gchar *filanem); -#ifndef ENABLE_NETCORE -static MonoAssemblyName* -mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_name); -#endif static MonoAssembly* prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly); @@ -1553,120 +1547,6 @@ mono_assembly_get_assemblyref (MonoImage *image, int index, MonoAssemblyName *an } } -#ifndef ENABLE_NETCORE -static MonoAssembly* -load_reference_by_aname_refonly_asmctx (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, MonoAssembly *assm, MonoImageOpenStatus *status) -{ - MonoAssembly *reference = NULL; - g_assert (assm != NULL); - g_assert (status != NULL); - *status = MONO_IMAGE_OK; - { - /* We use the loaded corlib */ - if (!strcmp (aname->name, MONO_ASSEMBLY_CORLIB_NAME)) { - MonoAssemblyByNameRequest req; - mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, alc); - req.requesting_assembly = assm; - req.basedir = assm->basedir; - reference = mono_assembly_request_byname (aname, &req, status); - } else { - reference = mono_assembly_loaded_internal (alc, aname, TRUE); - if (!reference) - /* Try a postload search hook */ - reference = mono_assembly_invoke_search_hook_internal (NULL, assm, aname, TRUE, TRUE); - } - - /* - * Here we must advice that the error was due to - * a non loaded reference using the ReflectionOnly api - */ - if (!reference) - reference = (MonoAssembly *)REFERENCE_MISSING; - } - return reference; -} - -static MonoAssembly* -load_reference_by_aname_default_asmctx (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, MonoAssembly *assm, MonoImageOpenStatus *status) -{ - MonoAssembly *reference = NULL; - g_assert (status != NULL); - *status = MONO_IMAGE_OK; - { - /* we first try without setting the basedir: this can eventually result in a ResolveAssembly - * event which is the MS .net compatible behaviour (the assemblyresolve_event3.cs test has been fixed - * accordingly, it would fail on the MS runtime before). - * The second load attempt has the basedir set to keep compatibility with the old mono behavior, for - * example bug-349190.2.cs and who knows how much more code in the wild. - */ - MonoAssemblyByNameRequest req; - mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, alc); - req.requesting_assembly = assm; - reference = mono_assembly_request_byname (aname, &req, status); - if (!reference && assm) { - memset (&req, 0, sizeof (req)); - req.request.asmctx = MONO_ASMCTX_DEFAULT; - req.requesting_assembly = assm; - req.basedir = assm->basedir; - reference = mono_assembly_request_byname (aname, &req, status); - } - } - return reference; -} - -static MonoAssembly* -load_reference_by_aname_loadfrom_asmctx (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, MonoAssembly *requesting, MonoImageOpenStatus *status) -{ - MonoAssembly *reference = NULL; - MonoAssemblyByNameRequest req; - mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_LOADFROM, alc); - req.requesting_assembly = requesting; - req.basedir = requesting->basedir; - /* Just like default search, but look in the requesting assembly basedir right away */ - reference = mono_assembly_request_byname (aname, &req, status); - return reference; - -} - -static MonoAssembly* -load_reference_by_aname_individual_asmctx (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, MonoAssembly *requesting, MonoImageOpenStatus *status) -{ - /* For an individual assembly, all references must already be loaded or - * else we fire the assembly resolve event - similar to refonly - but - * subject to remaping and binding. - */ - - g_assert (status != NULL); - - MonoAssembly *reference = NULL; - *status = MONO_IMAGE_OK; - MonoAssemblyName maped_aname; - MonoAssemblyName maped_name_pp; - - aname = mono_assembly_remap_version (aname, &maped_aname); - aname = mono_assembly_apply_binding (aname, &maped_name_pp); - - reference = mono_assembly_loaded_internal (alc, aname, FALSE); - /* Still try to load from application base directory, MONO_PATH or the - * GAC. This is consistent with what .NET Framework (4.7) actually - * does, rather than what the documentation implies: If `LoadFile` is - * used to load an assembly into "no context"/individual assembly - * context, the runtime will still load assemblies from the GAC or the - * application base directory (e.g. `System.Runtime` will be loaded if - * it wasn't already). - * Moreover, those referenced assemblies are loaded in the default context. - */ - if (!reference) { - MonoAssemblyByNameRequest req; - mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, mono_domain_default_alc (mono_alc_domain (alc))); - req.requesting_assembly = requesting; - reference = mono_assembly_request_byname (aname, &req, status); - } - if (!reference) - reference = (MonoAssembly*)REFERENCE_MISSING; - return reference; -} -#else static MonoAssembly * search_bundle_for_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname) { @@ -1838,8 +1718,6 @@ open_from_satellite_bundle (MonoAssemblyLoadContext *alc, const char *filename, return image; } -#endif /* ENABLE_NETCORE */ - /** * mono_assembly_get_assemblyref_checked: * \param image pointer to the \c MonoImage to extract the information from. @@ -1946,38 +1824,14 @@ mono_assembly_load_reference (MonoImage *image, int index) aname_str); g_free (aname_str); } -#ifndef ENABLE_NETCORE - switch (mono_asmctx_get_kind (&image->assembly->context)) { - case MONO_ASMCTX_DEFAULT: - reference = load_reference_by_aname_default_asmctx (&aname, mono_image_get_alc (image), image->assembly, &status); - break; - case MONO_ASMCTX_REFONLY: - reference = load_reference_by_aname_refonly_asmctx (&aname, mono_image_get_alc (image), image->assembly, &status); - break; - case MONO_ASMCTX_LOADFROM: - reference = load_reference_by_aname_loadfrom_asmctx (&aname, mono_image_get_alc (image), image->assembly, &status); - break; - case MONO_ASMCTX_INDIVIDUAL: - reference = load_reference_by_aname_individual_asmctx (&aname, mono_image_get_alc (image), image->assembly, &status); - break; - default: - g_error ("Unexpected assembly load context kind %d for image %s.", mono_asmctx_get_kind (&image->assembly->context), image->name); - break; - } -#else + MonoAssemblyByNameRequest req; mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, mono_image_get_alc (image)); req.requesting_assembly = image->assembly; //req.no_postload_search = TRUE; // FIXME: should this be set? reference = mono_assembly_request_byname (&aname, &req, NULL); -#endif } else { -#ifndef ENABLE_NETCORE - /* FIXME: can we establish that image->assembly is never NULL and this code is dead? */ - reference = load_reference_by_aname_default_asmctx (&aname, mono_image_get_alc (image), image->assembly, &status); -#else g_assertf (image->assembly, "While loading reference %d MonoImage %s doesn't have a MonoAssembly", index, image->name); -#endif } if (reference == NULL){ @@ -2310,13 +2164,9 @@ invoke_assembly_preload_hook (MonoAssemblyLoadContext *alc, MonoAssemblyName *an if (hook->version == 2) assembly = hook->func.v2 (alc, aname, apath, FALSE, hook->user_data, error); else { // v3 -#ifdef ENABLE_NETCORE MonoGCHandle strong_gchandle = mono_gchandle_from_handle (mono_gchandle_get_target_handle (alc->gchandle), TRUE); assembly = hook->func.v3 (strong_gchandle, aname, apath, hook->user_data, error); mono_gchandle_free_internal (strong_gchandle); -#else - assembly = hook->func.v3 (NULL, aname, apath, hook->user_data, error); -#endif } /* TODO: propagage error out to callers */ mono_error_assert_ok (error); @@ -2593,12 +2443,8 @@ open_from_bundle_internal (MonoAssemblyLoadContext *alc, const char *filename, M char *name = is_satellite ? g_strdup (filename) : g_path_get_basename (filename); for (int i = 0; !image && bundles [i]; ++i) { if (strcmp (bundles [i]->name, name) == 0) { -#ifdef ENABLE_NETCORE // Since bundled images don't exist on disk, don't give them a legit filename image = mono_image_open_from_data_internal (alc, (char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, FALSE, name, NULL); -#else - image = mono_image_open_from_data_internal (alc, (char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, FALSE, name, name); -#endif break; } } @@ -2624,21 +2470,12 @@ mono_assembly_open_from_bundle (MonoAssemblyLoadContext *alc, const char *filena * purpose assembly loading mechanism. */ MonoImage *image = NULL; -#ifndef ENABLE_NETCORE - if (!bundles) - return NULL; + gboolean is_satellite = culture && culture [0] != 0; - gchar *lowercase_filename = g_utf8_strdown (filename, -1); - gboolean is_satellite = g_str_has_suffix (lowercase_filename, ".resources.dll"); - g_free (lowercase_filename); - image = open_from_bundle_internal (alc, filename, status, refonly, is_satellite); -#else - gboolean is_satellite = culture && culture [0] != 0;; if (is_satellite) image = open_from_satellite_bundle (alc, filename, status, refonly, culture); else image = open_from_bundle_internal (alc, filename, status, refonly, FALSE); -#endif if (image) { mono_image_addref (image); @@ -2857,10 +2694,6 @@ mono_assembly_request_open (const char *filename, const MonoAssemblyOpenRequest if (!loaded_from_bundle) mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly Loader loaded assembly from location: '%s'.", filename); -#ifndef ENABLE_NETCORE // no XML file loading on netcore - if (!refonly) - mono_config_for_assembly_internal (ass->image); -#endif } /* Clear the reference added by mono_image_open */ @@ -3034,14 +2867,6 @@ chain_redirections_loadfrom (MonoAssemblyLoadContext *alc, MonoImage *image, Mon MonoImageOpenStatus status = MONO_IMAGE_OK; MonoAssembly *redirected = NULL; -#ifndef ENABLE_NETCORE - redirected = mono_assembly_binding_applies_to_image (alc, image, &status); - if (redirected || status != MONO_IMAGE_OK) { - *out_status = status; - return redirected; - } -#endif - redirected = mono_problematic_image_reprobe (alc, image, &status); if (redirected || status != MONO_IMAGE_OK) { *out_status = status; @@ -3052,72 +2877,6 @@ chain_redirections_loadfrom (MonoAssemblyLoadContext *alc, MonoImage *image, Mon return NULL; } -#ifndef ENABLE_NETCORE -/** - * mono_assembly_binding_applies_to_image: - * \param alc AssemblyLoadContext to load into - * \param image The image whose assembly name we should check - * \param status sets on error; - * - * Get the \c MonoAssemblyName from the given \p image metadata and apply binding redirects to it. - * If the resulting name is different from the name in the image, load that \c MonoAssembly instead - * - * \returns the loaded \c MonoAssembly, or NULL if no binding redirection applied. - * - */ -MonoAssembly* -mono_assembly_binding_applies_to_image (MonoAssemblyLoadContext *alc, MonoImage* image, MonoImageOpenStatus *status) -{ - g_assert (status != NULL); - - /* This is a "fun" one now. - * For LoadFrom ("/basedir/some.dll") or LoadFile("/basedir/some.dll") or Load(byte[])), - * apparently what we're meant to do is: - * 1. probe the assembly name from some.dll (or the byte array) - * 2. apply binding redirects - * 3. If we get some other different name, drop this image and use - * the binding redirected name to probe. - * 4. Return the new assembly. - */ - MonoAssemblyName probed_aname, dest_name; - if (!mono_assembly_fill_assembly_name_full (image, &probed_aname, TRUE)) { - if (*status == MONO_IMAGE_OK) - *status = MONO_IMAGE_IMAGE_INVALID; - return NULL; - } - MonoAssembly *result_ass = NULL; - MonoAssemblyName *result_name = &probed_aname; - result_name = mono_assembly_apply_binding (result_name, &dest_name); - if (result_name != &probed_aname && !mono_assembly_names_equal (result_name, &probed_aname)) { - if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY)) { - char *probed_fullname = mono_stringify_assembly_name (&probed_aname); - char *result_fullname = mono_stringify_assembly_name (result_name); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Request to load from %s in (%s) remapped to %s", probed_fullname, image->name, result_fullname); - g_free (probed_fullname); - g_free (result_fullname); - } - const char *new_basedir = NULL; /* FIXME: null? - do a test of this */ - MonoAssemblyContextKind new_asmctx = MONO_ASMCTX_DEFAULT; /* FIXME: default? or? */ - MonoAssembly *new_requesting = NULL; /* this seems okay */ - MonoImageOpenStatus new_status = MONO_IMAGE_OK; - - MonoAssemblyByNameRequest new_req; - mono_assembly_request_prepare_byname (&new_req, new_asmctx, alc); - new_req.requesting_assembly = new_requesting; - new_req.basedir = new_basedir; - result_ass = mono_assembly_request_byname (result_name, &new_req, &new_status); - - if (result_ass && new_status == MONO_IMAGE_OK) { - g_assert (result_ass->image->assembly != NULL); - } else { - *status = new_status; - } - } - mono_assembly_name_free_internal (&probed_aname); - return result_ass; -} -#endif - /** * mono_problematic_image_reprobe: * \param alc AssemblyLoadContex to load into @@ -3547,7 +3306,6 @@ build_assembly_name (const char *name, const char *version, const char *culture, memset (aname, 0, sizeof (MonoAssemblyName)); if (version) { -#ifdef ENABLE_NETCORE int parts [4]; int i; int part_len; @@ -3588,27 +3346,6 @@ build_assembly_name (const char *name, const char *version, const char *culture, aname->revision = parts [3]; else aname->revision = -1; -#else - gint major, minor, build, revision; - - version_parts = sscanf (version, "%u.%u.%u.%u", &major, &minor, &build, &revision); - if (version_parts < 2 || version_parts > 4) - return FALSE; - - /* FIXME: we should set build & revision to -1 (instead of 0) - if these are not set in the version string. That way, later on, - we can still determine if these were specified. */ - aname->major = major; - aname->minor = minor; - if (version_parts >= 3) - aname->build = build; - else - aname->build = 0; - if (version_parts == 4) - aname->revision = revision; - else - aname->revision = 0; -#endif } aname->flags = flags; @@ -3838,9 +3575,7 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole goto cleanup_and_fail; } -#ifdef ENABLE_NETCORE flags |= arch << 4; -#endif g_free (procarch_uq); tmp++; @@ -4492,121 +4227,6 @@ mono_domain_parse_assembly_bindings (MonoDomain *domain, int amajor, int aminor, mono_domain_unlock (domain); } -#ifndef ENABLE_NETCORE -static MonoAssemblyName* -mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_name) -{ - HANDLE_FUNCTION_ENTER (); - - ERROR_DECL (error); - MonoAssemblyBindingInfo *info, *info2; - MonoImage *ppimage; - MonoDomain *domain; - - if (aname->public_key_token [0] == 0) - goto return_aname; - - domain = mono_domain_get (); - - mono_assembly_binding_lock (); - info = search_binding_loaded (aname); - mono_assembly_binding_unlock (); - - if (!info) { - mono_domain_lock (domain); - info = get_per_domain_assembly_binding_info (domain, aname); - mono_domain_unlock (domain); - } - - if (info) { - if (!check_policy_versions (info, aname)) - goto return_aname; - - mono_assembly_bind_version (info, aname, dest_name); - goto return_dest_name; - } - - MonoAppDomainSetupHandle setup; - MonoStringHandle configuration_file; - - if (domain - && !MONO_HANDLE_IS_NULL (setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup)) - && !MONO_HANDLE_IS_NULL (configuration_file = MONO_HANDLE_NEW_GET (MonoString, setup, configuration_file))) { - char *domain_config_file_name = mono_string_handle_to_utf8 (configuration_file, error); - /* expect this to succeed because mono_domain_set_options_from_config () did - * the same thing when the domain was created. */ - mono_error_assert_ok (error); - mono_domain_parse_assembly_bindings (domain, aname->major, aname->minor, domain_config_file_name); - g_free (domain_config_file_name); - - mono_domain_lock (domain); - info2 = get_per_domain_assembly_binding_info (domain, aname); - - if (info2) { - info = (MonoAssemblyBindingInfo *)g_memdup (info2, sizeof (MonoAssemblyBindingInfo)); - info->name = g_strdup (info2->name); - info->culture = g_strdup (info2->culture); - info->domain_id = domain->domain_id; - } - - mono_domain_unlock (domain); - } - - if (!info) { - info = g_new0 (MonoAssemblyBindingInfo, 1); - info->major = aname->major; - info->minor = aname->minor; - } - - if (!info->is_valid) { - ppimage = mono_assembly_load_publisher_policy (aname); - if (ppimage) { - get_publisher_policy_info (ppimage, aname, info); - mono_image_close (ppimage); - } - } - - /* Define default error value if needed */ - if (!info->is_valid) { - info->name = g_strdup (aname->name); - info->culture = g_strdup (aname->culture); - g_strlcpy ((char *)info->public_key_token, (const char *)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH); - } - - mono_assembly_binding_lock (); - info2 = search_binding_loaded (aname); - if (info2) { - /* This binding was added by another thread - * before us */ - mono_assembly_binding_info_free (info); - g_free (info); - - info = info2; - } else - loaded_assembly_bindings = g_slist_prepend (loaded_assembly_bindings, info); - - mono_assembly_binding_unlock (); - - if (!info->is_valid || !check_policy_versions (info, aname)) - goto return_aname; - - mono_assembly_bind_version (info, aname, dest_name); - goto return_dest_name; - - MonoAssemblyName* result; - -return_dest_name: - result = dest_name; - goto exit; - -return_aname: - result = aname; - goto exit; -exit: - HANDLE_FUNCTION_RETURN_VAL (result); -} -#endif - #ifndef DISABLE_GAC /** * mono_assembly_load_from_gac @@ -4699,7 +4319,6 @@ mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus * return corlib; } -#ifdef ENABLE_NETCORE aname = mono_assembly_name_new (MONO_ASSEMBLY_CORLIB_NAME); corlib = invoke_assembly_preload_hook (req.request.alc, aname, NULL); /* MonoCore preload hook should know how to find it */ @@ -4716,39 +4335,6 @@ mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus * corlib = mono_assembly_request_open (corlib_name, &req, status); } g_assert (corlib); -#else - // A nonstandard preload hook may provide a special mscorlib assembly - aname = mono_assembly_name_new ("mscorlib.dll"); - corlib = invoke_assembly_preload_hook (req.request.alc, aname, assemblies_path); - mono_assembly_name_free_internal (aname); - g_free (aname); - if (corlib != NULL) - goto return_corlib_and_facades; - - // This unusual directory layout can occur if mono is being built and run out of its own source repo - if (assemblies_path) { // Custom assemblies path set via MONO_PATH or mono_set_assemblies_path - corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, &req, status); - if (corlib) - goto return_corlib_and_facades; - } - - /* Normal case: Load corlib from mono/ */ - char *corlib_file; - corlib_file = g_build_filename ("mono", runtime->framework_version, "mscorlib.dll", (const char*)NULL); - if (assemblies_path) { // Custom assemblies path - corlib = load_in_path (corlib_file, (const char**)assemblies_path, &req, status); - if (corlib) { - g_free (corlib_file); - goto return_corlib_and_facades; - } - } - corlib = load_in_path (corlib_file, (const char**) default_path, &req, status); - g_free (corlib_file); - -return_corlib_and_facades: - if (corlib) // FIXME: stop hardcoding 4.5 here - default_path [1] = g_strdup_printf ("%s/Facades", corlib->basedir); -#endif /*!ENABLE_NETCORE*/ return corlib; } @@ -4785,36 +4371,15 @@ mono_assembly_candidate_predicate_sn_same_name (MonoAssembly *candidate, gpointe g_free (s); } -#ifdef ENABLE_NETCORE return mono_assembly_check_name_match (wanted_name, candidate_name); -#else - /* Wanted name has no token, not strongly named: always matches. */ - if (0 == wanted_name->public_key_token [0]) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Predicate: wanted has no token, returning TRUE"); - return TRUE; - } - - /* Candidate name has no token, not strongly named: never matches */ - if (0 == candidate_name->public_key_token [0]) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Predicate: candidate has no token, returning FALSE"); - return FALSE; - } - - return mono_assembly_check_name_match (wanted_name, candidate_name) || - framework_assembly_sn_match (wanted_name, candidate_name); -#endif } gboolean mono_assembly_check_name_match (MonoAssemblyName *wanted_name, MonoAssemblyName *candidate_name) { -#if ENABLE_NETCORE gboolean result = mono_assembly_names_equal_flags (wanted_name, candidate_name, MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_PUBKEY); if (result && assembly_names_compare_versions (wanted_name, candidate_name, -1) > 0) result = FALSE; -#else - gboolean result = mono_assembly_names_equal_flags (wanted_name, candidate_name, MONO_ANAME_EQ_NONE); -#endif mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Predicate: candidate and wanted names %s", result ? "match, returning TRUE" : "don't match, returning FALSE"); @@ -4856,39 +4421,6 @@ framework_assembly_sn_match (MonoAssemblyName *wanted_name, MonoAssemblyName *ca return FALSE; } -#ifndef ENABLE_NETCORE -static MonoAssembly* -mono_assembly_request_byname_nosearch (MonoAssemblyName *aname, - const MonoAssemblyByNameRequest *req, - MonoImageOpenStatus *status) -{ - MonoAssembly *result = NULL; - MonoAssemblyName maped_aname; - MonoAssemblyName maped_name_pp; - - aname = mono_assembly_remap_version (aname, &maped_aname); - - const gboolean refonly = req->request.asmctx == MONO_ASMCTX_REFONLY; - - /* Reflection only assemblies don't get assembly binding */ - if (!refonly) - aname = mono_assembly_apply_binding (aname, &maped_name_pp); - - result = mono_assembly_loaded_internal (req->request.alc, aname, refonly); - if (result) - return result; - - result = refonly ? invoke_assembly_refonly_preload_hook (req->request.alc, aname, assemblies_path) : invoke_assembly_preload_hook (req->request.alc, aname, assemblies_path); - if (result) { - result->in_gac = FALSE; - return result; - } - - result = mono_assembly_load_full_gac_base_default (aname, req->basedir, req->request.alc, req->request.asmctx, status); - return result; -} -#endif - /* Like mono_assembly_request_byname_nosearch, but don't ask the preload look (ie, * the appdomain) to run. Just looks in the gac, the specified base dir or the * default_path. Does NOT look in the appdomain application base or in the @@ -4987,18 +4519,7 @@ mono_assembly_request_byname (MonoAssemblyName *aname, const MonoAssemblyByNameR MonoAssembly *result; if (status) *status = MONO_IMAGE_OK; -#ifndef ENABLE_NETCORE - result = mono_assembly_request_byname_nosearch (aname, req, status); - const gboolean refonly = req->request.asmctx == MONO_ASMCTX_REFONLY; - - if (!result && !req->no_postload_search) { - /* Try a postload search hook */ - result = mono_assembly_invoke_search_hook_internal (req->request.alc, req->requesting_assembly, aname, refonly, TRUE); - result = prevent_reference_assembly_from_running (result, refonly); - } -#else result = netcore_load_reference (aname, req->request.alc, req->requesting_assembly, !req->no_postload_search); -#endif return result; } @@ -5008,11 +4529,8 @@ mono_assembly_load_full_alc (MonoGCHandle alc_gchandle, MonoAssemblyName *aname, MonoAssembly *res; MONO_ENTER_GC_UNSAFE; MonoAssemblyByNameRequest req; -#ifdef ENABLE_NETCORE MonoAssemblyLoadContext *alc = mono_alc_from_gchandle (alc_gchandle); -#else - MonoAssemblyLoadContext *alc = mono_domain_default_alc (mono_domain_get ()); -#endif + mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, alc); req.requesting_assembly = NULL; req.basedir = basedir; @@ -5416,9 +4934,7 @@ mono_create_new_bundled_satellite_assembly (const char *name, const char *cultur void mono_register_bundled_satellite_assemblies (const MonoBundledSatelliteAssembly **assemblies) { -#ifdef ENABLE_NETCORE satellite_bundles = assemblies; -#endif } #define MONO_DECLSEC_FORMAT_10 0x3C diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index b849dca..11cb507 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -34,16 +34,13 @@ #undef REALLY_INCLUDE_CLASS_DEF #endif -#ifdef ENABLE_NETCORE #define FEATURE_COVARIANT_RETURNS -#endif gboolean mono_print_vtable = FALSE; gboolean mono_align_small_structs = FALSE; -#ifdef ENABLE_NETCORE + /* Set by the EE */ gint32 mono_simd_register_size; -#endif /* Statistics */ static gint32 classes_size; @@ -298,12 +295,10 @@ mono_class_setup_fields (MonoClass *klass) if (explicit_size) instance_size += real_size; -#ifdef ENABLE_NETCORE if (mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System.Numerics") && !strcmp (klass->name, "Register")) { if (mono_simd_register_size) instance_size += mono_simd_register_size; } -#endif /* * This function can recursively call itself. @@ -643,11 +638,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError /* reserve space to store vector pointer in arrays */ if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) { klass->instance_size += 2 * TARGET_SIZEOF_VOID_P; -#ifndef ENABLE_NETCORE - g_assert (mono_class_get_field_count (klass) == 0); -#else /* TODO: check that array has 0 non-const fields */ -#endif } if (klass->enumtype) { @@ -865,14 +856,13 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0])) klass->simd_type = 1; } -#ifdef ENABLE_NETCORE + if (mono_is_corlib_image (gklass->image) && (!strcmp (gklass->name, "Vector`1") || !strcmp (gklass->name, "Vector128`1") || !strcmp (gklass->name, "Vector256`1"))) { MonoType *etype = gclass->context.class_inst->type_argv [0]; if (mono_type_is_primitive (etype) && etype->type != MONO_TYPE_CHAR && etype->type != MONO_TYPE_BOOLEAN) klass->simd_type = 1; } -#endif klass->is_array_special_interface = gklass->is_array_special_interface; @@ -2165,7 +2155,6 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ } /* check for incorrectly aligned or overlapped by a non-object field */ -#ifdef ENABLE_NETCORE guint8 *layout_check; if (has_references) { layout_check = g_new0 (guint8, real_size); @@ -2192,7 +2181,6 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ } g_free (layout_check); } -#endif instance_size = MAX (real_size, instance_size); if (!((layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && explicit_size)) { diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 0e9c76a..a15fa59 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -1004,9 +1004,6 @@ typedef struct { MonoClass *iremotingtypeinfo_class; #endif MonoClass *mono_method_message_class; -#ifndef ENABLE_NETCORE - MonoClass *appdomain_class; -#endif MonoClass *field_info_class; MonoClass *method_info_class; MonoClass *stack_frame_class; @@ -1021,13 +1018,8 @@ typedef struct { MonoClass *critical_finalizer_object; /* MAYBE NULL */ MonoClass *generic_ireadonlylist_class; MonoClass *generic_ienumerator_class; -#ifdef ENABLE_NETCORE MonoClass *alc_class; MonoClass *appcontext_class; -#endif -#ifndef ENABLE_NETCORE - MonoMethod *threadpool_perform_wait_callback_method; -#endif } MonoDefaults; #ifdef DISABLE_REMOTING @@ -1101,9 +1093,6 @@ GENERATE_GET_CLASS_WITH_CACHE_DECL (variant) #endif MonoClass* mono_class_get_appdomain_class (void); -#ifndef ENABLE_NETCORE -GENERATE_GET_CLASS_WITH_CACHE_DECL (appdomain_setup); -#endif GENERATE_GET_CLASS_WITH_CACHE_DECL (appdomain_unloaded_exception) GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (appdomain_unloaded_exception) @@ -1112,10 +1101,8 @@ GENERATE_GET_CLASS_WITH_CACHE_DECL (valuetype) GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL(handleref) -#ifdef ENABLE_NETCORE GENERATE_GET_CLASS_WITH_CACHE_DECL (assembly_load_context) GENERATE_GET_CLASS_WITH_CACHE_DECL (native_library) -#endif /* If you need a MonoType, use one of the mono_get_*_type () functions in class-inlines.h */ extern MonoDefaults mono_defaults; @@ -1614,12 +1601,8 @@ m_field_get_offset (MonoClassField *field) static inline MonoMemoryManager* m_class_get_mem_manager (MonoDomain *domain, MonoClass *klass) { -#ifdef ENABLE_NETCORE // FIXME: return mono_domain_memory_manager (domain); -#else - return mono_domain_memory_manager (domain); -#endif } static inline void * @@ -1637,12 +1620,8 @@ m_class_alloc0 (MonoDomain *domain, MonoClass *klass, guint size) static inline MonoMemoryManager* m_method_get_mem_manager (MonoDomain *domain, MonoMethod *method) { -#ifdef ENABLE_NETCORE // FIXME: return mono_domain_memory_manager (domain); -#else - return mono_domain_memory_manager (domain); -#endif } static inline void * diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index 486fed9..500d59c 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -23,9 +23,7 @@ #undef REALLY_INCLUDE_CLASS_DEF #endif -#ifdef ENABLE_NETCORE #define FEATURE_COVARIANT_RETURNS -#endif static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup); diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 7835e5a..3f95d66 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -6286,10 +6286,8 @@ gboolean mono_type_is_valid_enum_basetype (MonoType * type) { case MONO_TYPE_U8: case MONO_TYPE_I: case MONO_TYPE_U: -#if ENABLE_NETCORE case MONO_TYPE_R8: case MONO_TYPE_R4: -#endif return TRUE; default: return FALSE; diff --git a/src/mono/mono/metadata/cominterop.c b/src/mono/mono/metadata/cominterop.c index e80cca9..b02b00a 100644 --- a/src/mono/mono/metadata/cominterop.c +++ b/src/mono/mono/metadata/cominterop.c @@ -3160,17 +3160,10 @@ default_ptr_to_bstr (const gunichar2* ptr, int slen) // The allocation pre-string is pointer-sized, and then only 4 bytes are used for the length regardless. Additionally, // the total length is also aligned to a 16-byte boundary. This preserves the old behavior on legacy and fixes it for // netcore moving forward. -#ifdef ENABLE_NETCORE mono_bstr const s = (mono_bstr)mono_bstr_alloc ((slen + 1) * sizeof (gunichar2)); if (s == NULL) return NULL; -#else - /* allocate len + 1 utf16 characters plus 4 byte integer for length*/ - guint32 * const ret = (guint32 *)g_malloc ((slen + 1) * sizeof (gunichar2) + sizeof (guint32)); - if (ret == NULL) - return NULL; - mono_bstr const s = (mono_bstr)(ret + 1); -#endif + mono_bstr_set_length (s, slen); if (ptr) memcpy (s, ptr, slen * sizeof (gunichar2)); @@ -3286,11 +3279,7 @@ mono_free_bstr (/*mono_bstr_const*/gpointer bstr) #ifndef DISABLE_COM if (com_provider == MONO_COM_DEFAULT) { #endif -#ifdef ENABLE_NETCORE g_free (((char *)bstr) - SIZEOF_VOID_P); -#else // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform - g_free (((char *)bstr) - 4); -#endif #ifndef DISABLE_COM } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { sys_free_string_ms ((mono_bstr_const)bstr); @@ -4205,18 +4194,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (MonoIUn #endif /* HOST_WIN32 */ #endif /* DISABLE_COM */ -#ifndef ENABLE_NETCORE -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (mono_bstr_const ptr, MonoError *error) -{ - if (ptr == NULL) { - mono_error_set_argument_null (error, "ptr", NULL); - return NULL_HANDLE_STRING; - } - return mono_string_from_bstr_checked (ptr, error); -} -#endif - mono_bstr ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (const gunichar2* ptr, int len) { diff --git a/src/mono/mono/metadata/console-io.h b/src/mono/mono/metadata/console-io.h deleted file mode 100644 index e08505d..0000000 --- a/src/mono/mono/metadata/console-io.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * \file - * Console IO internal calls - * - * Author: - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * Copyright (c) 2005 Novell, Inc. (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#ifndef _MONO_METADATA_CONSOLEIO_H -#define _MONO_METADATA_CONSOLEIO_H - -#include -#include - -#include -#include -#include - -void mono_console_init (void); -void mono_console_handle_async_ops (void); - -#endif /* _MONO_METADATA_CONSOLEIO_H */ diff --git a/src/mono/mono/metadata/console-null.c b/src/mono/mono/metadata/console-null.c index f512974..bb99168 100644 --- a/src/mono/mono/metadata/console-null.c +++ b/src/mono/mono/metadata/console-null.c @@ -14,22 +14,11 @@ #include #include #include -#include #include #include #include #include "icall-decl.h" -void -mono_console_init (void) -{ -} - -void -mono_console_handle_async_ops (void) -{ -} - MonoBoolean ves_icall_System_ConsoleDriver_Isatty (HANDLE handle, MonoError* error) { diff --git a/src/mono/mono/metadata/console-unix.c b/src/mono/mono/metadata/console-unix.c deleted file mode 100644 index 908b2d6..0000000 --- a/src/mono/mono/metadata/console-unix.c +++ /dev/null @@ -1,526 +0,0 @@ -/** - * \file - * ConsoleDriver internal calls for Unix systems. - * - * Author: - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * Copyright (C) 2005-2009 Novell, Inc. (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "icall-decl.h" - -#ifndef ENABLE_NETCORE - -/* On solaris, curses.h must come before both termios.h and term.h */ -#ifdef HAVE_CURSES_H -# include -#endif -#ifdef HAVE_TERMIOS_H -# include -#endif -#ifdef HAVE_TERM_H -# include -#endif - -/* Needed for FIONREAD under solaris */ -#ifdef HAVE_SYS_FILIO_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif - -static gboolean setup_finished; -static gboolean atexit_called; - -/* The string used to return the terminal to its previous state */ -static gchar *teardown_str; - -/* The string used to set the terminal into keypad xmit mode after SIGCONT is received */ -static gchar *keypad_xmit_str; - -#ifdef HAVE_TERMIOS_H -/* This is the last state used by Mono, used after a CONT signal is received */ -static struct termios mono_attr; -#endif - -/* static void console_restore_signal_handlers (void); */ -static void console_set_signal_handlers (void); - -static GENERATE_TRY_GET_CLASS_WITH_CACHE (console, "System", "Console"); - -void -mono_console_init (void) -{ - int fd; - - /* Make sure the standard file descriptors are opened */ - fd = open ("/dev/null", O_RDWR); - while (fd >= 0 && fd < 3) { - fd = open ("/dev/null", O_RDWR); - } - close (fd); -} - -static struct termios initial_attr; - -MonoBoolean -ves_icall_System_ConsoleDriver_Isatty (HANDLE handle, MonoError* error) -{ - return isatty (GPOINTER_TO_INT (handle)); -} - -static MonoBoolean -set_property (gint property, gboolean value) -{ - struct termios attr; - gboolean callset = FALSE; - gboolean check; - - if (tcgetattr (STDIN_FILENO, &attr) == -1) - return FALSE; - - check = (attr.c_lflag & property) != 0; - if ((value || check) && !(value && check)) { - callset = TRUE; - if (value) - attr.c_lflag |= property; - else - attr.c_lflag &= ~property; - } - - if (!callset) - return TRUE; - - if (tcsetattr (STDIN_FILENO, TCSANOW, &attr) == -1) - return FALSE; - - mono_attr = attr; - return TRUE; -} - -MonoBoolean -ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean want_echo, MonoError* error) -{ - return set_property (ECHO, want_echo); -} - -MonoBoolean -ves_icall_System_ConsoleDriver_SetBreak (MonoBoolean want_break, MonoError* error) -{ - return set_property (IGNBRK, !want_break); -} - -gint32 -ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout, MonoError* error) -{ - fd_set rfds; - struct timeval tv; - struct timeval *tvptr; - div_t divvy; - int ret, nbytes; - - do { - FD_ZERO (&rfds); - FD_SET (STDIN_FILENO, &rfds); - if (timeout >= 0) { - divvy = div (timeout, 1000); - tv.tv_sec = divvy.quot; - tv.tv_usec = divvy.rem; - tvptr = &tv; - } else { - tvptr = NULL; - } - ret = select (STDIN_FILENO + 1, &rfds, NULL, NULL, tvptr); - } while (ret == -1 && errno == EINTR); - - if (ret > 0) { - nbytes = 0; - ret = ioctl (STDIN_FILENO, FIONREAD, &nbytes); - if (ret >= 0) - ret = nbytes; - } - - return (ret > 0) ? ret : 0; -} - -static gint32 cols_and_lines; - -#ifdef TIOCGWINSZ -static int -terminal_get_dimensions (void) -{ - struct winsize ws; - int ret; - int save_errno = errno; - - if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) == 0){ - ret = (ws.ws_col << 16) | ws.ws_row; - mono_set_errno (save_errno); - return ret; - } - return -1; -} -#else -static int -terminal_get_dimensions (void) -{ - return -1; -} -#endif - -static void -tty_teardown (void) -{ - int unused G_GNUC_UNUSED; - - if (!setup_finished) - return; - - if (teardown_str != NULL) { - unused = write (STDOUT_FILENO, teardown_str, strlen (teardown_str)); - g_free (teardown_str); - teardown_str = NULL; - } - - tcflush (STDIN_FILENO, TCIFLUSH); - tcsetattr (STDIN_FILENO, TCSANOW, &initial_attr); - set_property (ECHO, TRUE); - setup_finished = FALSE; -} - -static void -do_console_cancel_event (void) -{ - static MonoMethod *System_Console_DoConsoleCancelEventBackground_method = (MonoMethod*)(intptr_t)-1; - ERROR_DECL (error); - - if (mono_class_try_get_console_class () == NULL) - return; - - if (System_Console_DoConsoleCancelEventBackground_method == (gpointer)(intptr_t)-1) { - System_Console_DoConsoleCancelEventBackground_method = mono_class_get_method_from_name_checked (mono_class_try_get_console_class (), "DoConsoleCancelEventInBackground", 0, 0, error); - mono_error_assert_ok (error); - } - if (System_Console_DoConsoleCancelEventBackground_method == NULL) - return; - - mono_runtime_invoke_checked (System_Console_DoConsoleCancelEventBackground_method, NULL, NULL, error); - mono_error_assert_ok (error); -} - -static int need_cancel = FALSE; -/* this is executed from the finalizer thread */ -void -mono_console_handle_async_ops (void) -{ - if (need_cancel) { - need_cancel = FALSE; - do_console_cancel_event (); - } -} - -static gboolean in_sigint; - -MONO_SIG_HANDLER_FUNC (static, sigint_handler) -{ - int save_errno; - - if (in_sigint) - return; - - in_sigint = TRUE; - save_errno = errno; - need_cancel = TRUE; - mono_gc_finalize_notify (); - mono_set_errno (save_errno); - in_sigint = FALSE; -} - -static struct sigaction save_sigcont, save_sigwinch; - -#if HAVE_SIGACTION -static struct sigaction save_sigint; -#endif - -MONO_SIG_HANDLER_FUNC (static, sigcont_handler) -{ - int unused G_GNUC_UNUSED; - // Ignore error, there is not much we can do in the sigcont handler. - tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr); - - if (keypad_xmit_str != NULL) - unused = write (STDOUT_FILENO, keypad_xmit_str, strlen (keypad_xmit_str)); - - // Call previous handler - if (save_sigcont.sa_sigaction != NULL && - save_sigcont.sa_sigaction != (void *)SIG_DFL && - save_sigcont.sa_sigaction != (void *)SIG_IGN) - (*save_sigcont.sa_sigaction) (MONO_SIG_HANDLER_PARAMS); -} - -MONO_SIG_HANDLER_FUNC (static, sigwinch_handler) -{ - int dims = terminal_get_dimensions (); - if (dims != -1) - cols_and_lines = dims; - - // Call previous handler - if (save_sigwinch.sa_sigaction != NULL && - save_sigwinch.sa_sigaction != (void *)SIG_DFL && - save_sigwinch.sa_sigaction != (void *)SIG_IGN) - (*save_sigwinch.sa_sigaction) (MONO_SIG_HANDLER_PARAMS); -} - -/* - * console_set_signal_handlers: - * - * Installs various signals handlers for the use of the console, as - * follows: - * - * SIGCONT: this is received after the application has resumed execution - * if it was suspended with Control-Z before. This signal handler needs - * to resend the terminal sequence to send keyboard in keypad mode (this - * is the difference between getting a cuu1 code or a kcuu1 code for up-arrow - * for example - * - * SIGINT: invokes the System.Console.DoConsoleCancelEvent method using - * a thread from the thread pool which notifies all registered cancel_event - * listeners. - * - * SIGWINCH: is used to track changes to the console window when a GUI - * terminal is resized. It sets an internal variable that is checked - * by System.Console when the Terminfo driver has been activated. - */ -static void -console_set_signal_handlers () -{ -#if defined(HAVE_SIGACTION) - struct sigaction sigcont, sigint, sigwinch; - - memset (&sigcont, 0, sizeof (struct sigaction)); - memset (&sigint, 0, sizeof (struct sigaction)); - memset (&sigwinch, 0, sizeof (struct sigaction)); - - // Continuing - sigcont.sa_handler = (void (*)(int)) sigcont_handler; - sigcont.sa_flags = SA_RESTART; - sigemptyset (&sigcont.sa_mask); - sigaction (SIGCONT, &sigcont, &save_sigcont); - - // Interrupt handler - sigint.sa_handler = (void (*)(int)) sigint_handler; - sigint.sa_flags = SA_RESTART; - sigemptyset (&sigint.sa_mask); - sigaction (SIGINT, &sigint, &save_sigint); - - // Window size changed - sigwinch.sa_handler = (void (*)(int)) sigwinch_handler; - sigwinch.sa_flags = SA_RESTART; - sigemptyset (&sigwinch.sa_mask); - sigaction (SIGWINCH, &sigwinch, &save_sigwinch); -#endif -} - -#if currently_unuused -// -// Currently unused, should we ever call the restore handler? -// Perhaps before calling into Process.Start? -// -void -console_restore_signal_handlers () -{ - sigaction (SIGCONT, &save_sigcont, NULL); - sigaction (SIGINT, &save_sigint, NULL); - sigaction (SIGWINCH, &save_sigwinch, NULL); -} -#endif - -static void -set_control_chars (gchar *control_chars, const guchar *cc) -{ - /* The index into the array comes from corlib/System/ControlCharacters.cs */ -#ifdef VINTR - control_chars [0] = cc [VINTR]; -#endif -#ifdef VQUIT - control_chars [1] = cc [VQUIT]; -#endif -#ifdef VERASE - control_chars [2] = cc [VERASE]; -#endif -#ifdef VKILL - control_chars [3] = cc [VKILL]; -#endif -#ifdef VEOF - control_chars [4] = cc [VEOF]; -#endif -#ifdef VTIME - control_chars [5] = cc [VTIME]; -#endif -#ifdef VMIN - control_chars [6] = cc [VMIN]; -#endif -#ifdef VSWTC - control_chars [7] = cc [VSWTC]; -#endif -#ifdef VSTART - control_chars [8] = cc [VSTART]; -#endif -#ifdef VSTOP - control_chars [9] = cc [VSTOP]; -#endif -#ifdef VSUSP - control_chars [10] = cc [VSUSP]; -#endif -#ifdef VEOL - control_chars [11] = cc [VEOL]; -#endif -#ifdef VREPRINT - control_chars [12] = cc [VREPRINT]; -#endif -#ifdef VDISCARD - control_chars [13] = cc [VDISCARD]; -#endif -#ifdef VWERASE - control_chars [14] = cc [VWERASE]; -#endif -#ifdef VLNEXT - control_chars [15] = cc [VLNEXT]; -#endif -#ifdef VEOL2 - control_chars [16] = cc [VEOL2]; -#endif -} - -MonoBoolean -ves_icall_System_ConsoleDriver_TtySetup (MonoStringHandle keypad, MonoStringHandle teardown, MonoArrayHandleOut control_chars, int **size, MonoError* error) -{ - // FIXME Lock around the globals? - - int dims; - - dims = terminal_get_dimensions (); - if (dims == -1){ - int cols = 0, rows = 0; - - char *str = g_getenv ("COLUMNS"); - if (str != NULL) { - cols = atoi (str); - g_free (str); - } - str = g_getenv ("LINES"); - if (str != NULL) { - rows = atoi (str); - g_free (str); - } - - if (cols != 0 && rows != 0) - cols_and_lines = (cols << 16) | rows; - else - cols_and_lines = -1; - } else { - cols_and_lines = dims; - } - - *size = &cols_and_lines; - - /* 17 is the number of entries set in set_control_chars() above. - * NCCS is the total size, but, by now, we only care about those 17 values*/ - MonoArrayHandle control_chars_arr = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, 17, error); - return_val_if_nok (error, FALSE); - - MONO_HANDLE_ASSIGN (control_chars, control_chars_arr); - if (tcgetattr (STDIN_FILENO, &initial_attr) == -1) - return FALSE; - - mono_attr = initial_attr; - mono_attr.c_lflag &= ~(ICANON); - mono_attr.c_iflag &= ~(IXON|IXOFF); - mono_attr.c_cc [VMIN] = 1; - mono_attr.c_cc [VTIME] = 0; -#ifdef VDSUSP - /* Disable C-y being used as a suspend character on OSX */ - mono_attr.c_cc [VDSUSP] = 255; -#endif - gint ret; - do { - MONO_ENTER_GC_SAFE; - ret = tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr); - MONO_EXIT_GC_SAFE; - } while (ret == -1 && errno == EINTR); - - if (ret == -1) - return FALSE; - - MonoGCHandle h; - set_control_chars (MONO_ARRAY_HANDLE_PIN (control_chars_arr, gchar, 0, &h), mono_attr.c_cc); - mono_gchandle_free_internal (h); - /* If initialized from another appdomain... */ - if (setup_finished) - return TRUE; - - keypad_xmit_str = NULL; - if (!MONO_HANDLE_IS_NULL (keypad)) { - keypad_xmit_str = mono_string_handle_to_utf8 (keypad, error); - return_val_if_nok (error, FALSE); - } - - console_set_signal_handlers (); - setup_finished = TRUE; - if (!atexit_called) { - if (!MONO_HANDLE_IS_NULL (teardown)) { - teardown_str = mono_string_handle_to_utf8 (teardown, error); - return_val_if_nok (error, FALSE); - } - - mono_atexit (tty_teardown); - } - - return TRUE; -} - -#else /* ENABLE_NETCORE */ - -void -mono_console_init (void) -{ -} - -void -mono_console_handle_async_ops (void) -{ -} - -#endif diff --git a/src/mono/mono/metadata/console-win32.c b/src/mono/mono/metadata/console-win32.c index 90ed52c..afa383d 100644 --- a/src/mono/mono/metadata/console-win32.c +++ b/src/mono/mono/metadata/console-win32.c @@ -26,21 +26,10 @@ #include #include #include -#include #include #include #include "icall-decl.h" -void -mono_console_init (void) -{ -} - -void -mono_console_handle_async_ops (void) -{ -} - #if HAVE_API_SUPPORT_WIN32_CONSOLE MonoBoolean ves_icall_System_ConsoleDriver_Isatty (HANDLE handle, MonoError* error) diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index fe3165f..13791f2 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -1435,16 +1435,9 @@ ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoRe } MONO_HANDLE_ASSIGN_RAW (minfo_h, minfo); -#if ENABLE_NETCORE namedarg = create_cattr_named_arg (minfo, obj, error); MONO_HANDLE_ASSIGN_RAW (namedarg_h, namedarg); -#else - MonoObject* typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error); - MONO_HANDLE_ASSIGN_RAW (typedarg_h, typedarg); - goto_if_nok (error, leave); - namedarg = create_cattr_named_arg (minfo, typedarg, error); - MONO_HANDLE_ASSIGN_RAW (namedarg_h, namedarg); -#endif + goto_if_nok (error, leave); mono_array_setref_internal (named_args, i, namedarg); @@ -2219,15 +2212,8 @@ mono_reflection_get_custom_attrs_info_checked (MonoObjectHandle obj, MonoError * MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs); cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs); } else if (strcmp ("ConstructorBuilder", klass_name) == 0) { -#ifdef ENABLE_NETCORE mono_error_set_not_supported (error, ""); goto leave; -#else - MonoReflectionCtorBuilderHandle cb = MONO_HANDLE_CAST (MonoReflectionCtorBuilder, obj); - MonoMethod *mhandle = MONO_HANDLE_GETVAL (cb, mhandle); - MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, cb, cattrs); - cinfo = mono_custom_attrs_from_builders_handle (NULL, m_class_get_image (mhandle->klass), cattrs); -#endif } else if (strcmp ("MethodBuilder", klass_name) == 0) { MonoReflectionMethodBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionMethodBuilder, obj); MonoMethod *mhandle = MONO_HANDLE_GETVAL (mb, mhandle); diff --git a/src/mono/mono/metadata/domain-internals.h b/src/mono/mono/metadata/domain-internals.h index b33b88e..eb095e7 100644 --- a/src/mono/mono/metadata/domain-internals.h +++ b/src/mono/mono/metadata/domain-internals.h @@ -21,27 +21,6 @@ #include #include -/* Mono appdomain support is deeply itegrated in the runtime, as a result, even - * though .NET Standard does not include System.AppDomain in - * System.Private.CoreLib, we still depend on having an appdomain class. - * So we move it to Mono.MonoDomain - * - */ -#ifndef ENABLE_NETCORE -#define MONO_APPDOMAIN_CLASS_NAME_SPACE "System" -#define MONO_APPDOMAIN_CLASS_NAME "AppDomain" -#define MONO_APPDOMAIN_SETUP_CLASS_NAME_SPACE "System" -#define MONO_APPDOMAIN_SETUP_CLASS_NAME "AppDomainSetup" -#else -/* We don't care anymore about the managed appdomain representation - * so we just use a sentinel System.Object in the parts of the code that still care - */ -/* -#define MONO_APPDOMAIN_CLASS_NAME_SPACE "System" -#define MONO_APPDOMAIN_CLASS_NAME "Object" -*/ -#endif - G_BEGIN_DECLS /* @@ -52,35 +31,6 @@ G_BEGIN_DECLS */ extern gboolean mono_dont_free_domains; -#ifndef ENABLE_NETCORE -/* This is a copy of System.AppDomainSetup */ -typedef struct { - MonoObject object; - MonoString *application_base; - MonoString *application_name; - MonoString *cache_path; - MonoString *configuration_file; - MonoString *dynamic_base; - MonoString *license_file; - MonoString *private_bin_path; - MonoString *private_bin_path_probe; - MonoString *shadow_copy_directories; - MonoString *shadow_copy_files; - MonoBoolean publisher_policy; - MonoBoolean path_changed; - int loader_optimization; - MonoBoolean disallow_binding_redirects; - MonoBoolean disallow_code_downloads; - MonoObject *activation_arguments; /* it is System.Object in 1.x, ActivationArguments in 2.0 */ - MonoObject *domain_initializer; - MonoObject *application_trust; /* it is System.Object in 1.x, ApplicationTrust in 2.0 */ - MonoArray *domain_initializer_args; - MonoBoolean disallow_appbase_probe; - MonoArray *configuration_bytes; - MonoArray *serialized_non_primitives; -} MonoAppDomainSetup; -#endif - typedef struct _MonoJitInfoTable MonoJitInfoTable; typedef struct _MonoJitInfoTableChunk MonoJitInfoTableChunk; @@ -349,12 +299,7 @@ struct _MonoDomain { * keep all the managed objects close to each other for the precise GC * For the Boehm GC we additionally keep close also other GC-tracked pointers. */ -#ifndef ENABLE_NETCORE -#define MONO_DOMAIN_FIRST_OBJECT setup - MonoAppDomainSetup *setup; -#else #define MONO_DOMAIN_FIRST_OBJECT domain -#endif MonoAppDomain *domain; MonoAppContext *default_context; MonoException *out_of_memory_ex; @@ -465,16 +410,9 @@ struct _MonoDomain { guint32 execution_context_field_offset; -#ifdef ENABLE_NETCORE GSList *alcs; MonoAssemblyLoadContext *default_alc; MonoCoopMutex alcs_lock; /* Used when accessing 'alcs' */ -#endif - -#ifndef ENABLE_NETCORE - // Holds domain code memory - MonoMemoryManager *memory_manager; -#endif }; typedef struct { @@ -595,11 +533,6 @@ mono_domain_unset (void); void mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception); -#ifndef ENABLE_NETCORE -gboolean -mono_domain_set_config_checked (MonoDomain *domain, const char *base_dir, const char *config_file_name, MonoError *error); -#endif - MonoTryBlockHoleTableJitInfo* mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji); @@ -655,10 +588,6 @@ mono_try_assembly_resolve (MonoAssemblyLoadContext *alc, const char *fname, Mono MonoAssembly * mono_domain_assembly_postload_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting, MonoAssemblyName *aname, gboolean refonly, gboolean postload, gpointer user_data, MonoError *error); -#ifndef ENABLE_NETCORE -void mono_domain_set_options_from_config (MonoDomain *domain); -#endif - int mono_framework_version (void); void mono_assembly_cleanup_domain_bindings (guint32 domain_id); @@ -696,7 +625,6 @@ mono_domain_set_fast (MonoDomain *domain, gboolean force); MonoAssemblyLoadContext * mono_domain_default_alc (MonoDomain *domain); -#ifdef ENABLE_NETCORE static inline void mono_domain_alcs_lock (MonoDomain *domain) { @@ -708,7 +636,6 @@ mono_domain_alcs_unlock (MonoDomain *domain) { mono_coop_mutex_unlock (&domain->alcs_lock); } -#endif static inline MonoAssemblyLoadContext * @@ -724,11 +651,7 @@ mono_domain_ambient_alc (MonoDomain *domain) static inline MonoMemoryManager * mono_domain_memory_manager (MonoDomain *domain) { -#ifdef ENABLE_NETCORE return (MonoMemoryManager *)mono_domain_default_alc (domain)->memory_manager; -#else - return domain->memory_manager; -#endif } static inline MonoMemoryManager * diff --git a/src/mono/mono/metadata/domain.c b/src/mono/mono/metadata/domain.c index 4af4b21..ccc923c 100644 --- a/src/mono/mono/metadata/domain.c +++ b/src/mono/mono/metadata/domain.c @@ -66,13 +66,8 @@ mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \ } while (FALSE) -#ifndef ENABLE_NETCORE -#define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext) -#define SET_APPCONTEXT(x) MONO_OBJECT_SETREF_INTERNAL (mono_thread_internal_current (), current_appcontext, (x)) -#else #define GET_APPCONTEXT() NULL #define SET_APPCONTEXT(x) -#endif static guint16 appdomain_list_size = 0; static guint16 appdomain_next = 0; @@ -432,18 +427,11 @@ mono_domain_create (void) domain->shadow_serial = shadow_serial; domain->domain = NULL; -#ifndef ENABLE_NETCORE - domain->setup = NULL; -#endif domain->friendly_name = NULL; domain->search_path = NULL; MONO_PROFILER_RAISE (domain_loading, (domain)); -#ifndef ENABLE_NETCORE - domain->memory_manager = (MonoMemoryManager *)mono_mem_manager_create_singleton (NULL, domain, TRUE); -#endif - domain->lock_free_mp = lock_free_mempool_new (); domain->env = mono_g_hash_table_new_type_internal ((GHashFunc)mono_string_hash_internal, (GCompareFunc)mono_string_equal_internal, MONO_HASH_KEY_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Environment Variable Table"); domain->domain_assemblies = NULL; @@ -464,9 +452,7 @@ mono_domain_create (void) mono_os_mutex_init_recursive (&domain->jit_code_hash_lock); mono_os_mutex_init_recursive (&domain->finalizable_objects_hash_lock); -#ifdef ENABLE_NETCORE mono_coop_mutex_init (&domain->alcs_lock); -#endif mono_appdomains_lock (); domain_id_alloc (domain); @@ -479,9 +465,7 @@ mono_domain_create (void) mono_debug_domain_create (domain); -#ifdef ENABLE_NETCORE mono_alc_create_default (domain); -#endif if (create_domain_hook) create_domain_hook (domain); @@ -705,11 +689,6 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.multicastdelegate_class = mono_class_load_from_name ( mono_defaults.corlib, "System", "MulticastDelegate"); -#ifndef ENABLE_NETCORE - mono_defaults.manualresetevent_class = mono_class_load_from_name ( - mono_defaults.corlib, "System.Threading", "ManualResetEvent"); -#endif - mono_defaults.typehandle_class = mono_class_load_from_name ( mono_defaults.corlib, "System", "RuntimeTypeHandle"); @@ -731,20 +710,8 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.thread_class = mono_class_load_from_name ( mono_defaults.corlib, "System.Threading", "Thread"); -#ifdef ENABLE_NETCORE /* There is only one thread class */ mono_defaults.internal_thread_class = mono_defaults.thread_class; -#else - mono_defaults.internal_thread_class = mono_class_load_from_name ( - mono_defaults.corlib, "System.Threading", "InternalThread"); - - mono_defaults.threadabortexception_class = mono_class_load_from_name ( - mono_defaults.corlib, "System.Threading", "ThreadAbortException"); -#endif - -#ifndef ENABLE_NETCORE - mono_defaults.appdomain_class = mono_class_get_appdomain_class (); -#endif #ifndef DISABLE_REMOTING mono_defaults.transparent_proxy_class = mono_class_load_from_name ( @@ -761,25 +728,14 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * #endif - /* FIXME pretty sure this is wrong and netcore has messages... */ -#ifndef ENABLE_NETCORE - mono_defaults.mono_method_message_class = mono_class_load_from_name ( - mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage"); -#endif - mono_defaults.field_info_class = mono_class_load_from_name ( mono_defaults.corlib, "System.Reflection", "FieldInfo"); mono_defaults.method_info_class = mono_class_load_from_name ( mono_defaults.corlib, "System.Reflection", "MethodInfo"); -#ifdef ENABLE_NETCORE mono_defaults.stack_frame_class = mono_class_load_from_name ( mono_defaults.corlib, "System.Diagnostics", "MonoStackFrame"); -#else - mono_defaults.stack_frame_class = mono_class_load_from_name ( - mono_defaults.corlib, "System.Diagnostics", "StackFrame"); -#endif mono_defaults.marshal_class = mono_class_load_from_name ( mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal"); @@ -813,20 +769,8 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.generic_ienumerator_class = mono_class_try_load_from_name ( mono_defaults.corlib, "System.Collections.Generic", "IEnumerator`1"); -#ifdef ENABLE_NETCORE mono_defaults.alc_class = mono_class_get_assembly_load_context_class (); mono_defaults.appcontext_class = mono_class_try_load_from_name (mono_defaults.corlib, "System", "AppContext"); -#endif - -#ifndef ENABLE_NETCORE - MonoClass *threadpool_wait_callback_class = mono_class_load_from_name ( - mono_defaults.corlib, "System.Threading", "_ThreadPoolWaitCallback"); - - ERROR_DECL (error); - mono_defaults.threadpool_perform_wait_callback_method = mono_class_get_method_from_name_checked ( - threadpool_wait_callback_class, "PerformWaitCallback", 0, 0, error); - mono_error_assert_ok (error); -#endif domain->friendly_name = g_path_get_basename (filename); @@ -1036,25 +980,6 @@ mono_domain_ensure_entry_assembly (MonoDomain *domain, MonoAssembly *assembly) if (!mono_runtime_get_no_exec () && !domain->entry_assembly && assembly) { domain->entry_assembly = assembly; -#ifndef ENABLE_NETCORE - gchar *str; - ERROR_DECL (error); - /* Domains created from another domain already have application_base and configuration_file set */ - if (domain->setup->application_base == NULL) { - MonoString *basedir = mono_string_new_checked (domain, assembly->basedir, error); - mono_error_assert_ok (error); - MONO_OBJECT_SETREF_INTERNAL (domain->setup, application_base, basedir); - } - - if (domain->setup->configuration_file == NULL) { - str = g_strconcat (assembly->image->name, ".config", (const char*)NULL); - MonoString *config_file = mono_string_new_checked (domain, str, error); - mono_error_assert_ok (error); - MONO_OBJECT_SETREF_INTERNAL (domain->setup, configuration_file, config_file); - g_free (str); - mono_domain_set_options_from_config (domain); - } -#endif } } @@ -1097,9 +1022,7 @@ mono_domain_assembly_open_internal (MonoDomain *domain, MonoAssemblyLoadContext // On netcore, this is necessary because we check the AppContext.BaseDirectory property as part of the assembly lookup algorithm // AppContext.BaseDirectory can sometimes fall back to checking the location of the entry_assembly, which should be non-null -#ifdef ENABLE_NETCORE mono_domain_ensure_entry_assembly (domain, ass); -#endif return ass; } @@ -1118,181 +1041,7 @@ mono_domain_assembly_open_internal (MonoDomain *domain, MonoAssemblyLoadContext void mono_domain_free (MonoDomain *domain, gboolean force) { -#ifndef ENABLE_NETCORE - int code_size, code_alloc; - GSList *tmp; - gpointer *p; - - if ((domain == mono_root_domain) && !force) { - g_warning ("cant unload root domain"); - return; - } - - if (mono_dont_free_domains) - return; - - MONO_PROFILER_RAISE (domain_unloading, (domain)); - - mono_debug_domain_unload (domain); - - /* must do this early as it accesses fields and types */ - if (domain->special_static_fields) { - mono_alloc_special_static_data_free (domain->special_static_fields); - g_hash_table_destroy (domain->special_static_fields); - domain->special_static_fields = NULL; - } - - /* - * We must destroy all these hash tables here because they - * contain references to managed objects belonging to the - * domain. Once we let the GC clear the domain there must be - * no more such references, or we'll crash if a collection - * occurs. - */ - mono_g_hash_table_destroy (domain->ldstr_table); - domain->ldstr_table = NULL; - - mono_g_hash_table_destroy (domain->env); - domain->env = NULL; - - mono_mem_manager_free_objects_singleton ((MonoSingletonMemoryManager *)domain->memory_manager); - - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - MonoAssembly *ass = (MonoAssembly *)tmp->data; - mono_assembly_release_gc_roots (ass); - } - - /* Have to zero out reference fields since they will be invalidated by the clear_domain () call below */ - for (p = (gpointer*)&domain->MONO_DOMAIN_FIRST_OBJECT; p < (gpointer*)&domain->MONO_DOMAIN_FIRST_GC_TRACKED; ++p) - *p = NULL; - - /* This needs to be done before closing assemblies */ - mono_gc_clear_domain (domain); - - /* Close dynamic assemblies first, since they have no ref count */ - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - MonoAssembly *ass = (MonoAssembly *)tmp->data; - if (!ass->image || !image_is_dynamic (ass->image)) - continue; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count); - if (!mono_assembly_close_except_image_pools (ass)) - tmp->data = NULL; - } - - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - MonoAssembly *ass = (MonoAssembly *)tmp->data; - if (!ass) - continue; - if (!ass->image || image_is_dynamic (ass->image)) - continue; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count); - if (!mono_assembly_close_except_image_pools (ass)) - tmp->data = NULL; - } - - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - MonoAssembly *ass = (MonoAssembly *)tmp->data; - if (ass) - mono_assembly_close_finish (ass); - } - g_slist_free (domain->domain_assemblies); - domain->domain_assemblies = NULL; - - /* - * Send this after the assemblies have been unloaded and the domain is still in a - * usable state. - */ - MONO_PROFILER_RAISE (domain_unloaded, (domain)); - - if (free_domain_hook) - free_domain_hook (domain); - - /* FIXME: free delegate_hash_table when it's used */ - if (domain->search_path) { - g_strfreev (domain->search_path); - domain->search_path = NULL; - } - domain->create_proxy_for_type_method = NULL; - domain->private_invoke_method = NULL; - domain->default_context = NULL; - domain->out_of_memory_ex = NULL; - domain->null_reference_ex = NULL; - domain->stack_overflow_ex = NULL; - domain->ephemeron_tombstone = NULL; - domain->entry_assembly = NULL; - - g_free (domain->friendly_name); - domain->friendly_name = NULL; - g_hash_table_destroy (domain->proxy_vtable_hash); - domain->proxy_vtable_hash = NULL; - mono_internal_hash_table_destroy (&domain->jit_code_hash); - - /* - * There might still be jit info tables of this domain which - * are not freed. Since the domain cannot be in use anymore, - * this will free them. - */ - mono_thread_hazardous_try_free_all (); - if (domain->aot_modules) - mono_jit_info_table_free (domain->aot_modules); - g_assert (domain->num_jit_info_table_duplicates == 0); - mono_jit_info_table_free (domain->jit_info_table); - domain->jit_info_table = NULL; - g_assert (!domain->jit_info_free_queue); - - // Collect statistics - code_alloc = mono_code_manager_size (domain->memory_manager->code_mp, &code_size); - total_domain_code_alloc += code_alloc; - max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc); - max_domain_code_size = MAX (max_domain_code_size, code_size); - - mono_mem_manager_free_singleton ((MonoSingletonMemoryManager *)domain->memory_manager, debug_domain_unload); - domain->memory_manager = NULL; - - lock_free_mempool_free (domain->lock_free_mp); - domain->lock_free_mp = NULL; - - g_hash_table_destroy (domain->finalizable_objects_hash); - domain->finalizable_objects_hash = NULL; - if (domain->generic_virtual_cases) { - g_hash_table_destroy (domain->generic_virtual_cases); - domain->generic_virtual_cases = NULL; - } - if (domain->ftnptrs_hash) { - g_hash_table_destroy (domain->ftnptrs_hash); - domain->ftnptrs_hash = NULL; - } - if (domain->method_to_dyn_method) { - g_hash_table_destroy (domain->method_to_dyn_method); - domain->method_to_dyn_method = NULL; - } - - mono_os_mutex_destroy (&domain->finalizable_objects_hash_lock); - mono_coop_mutex_destroy (&domain->assemblies_lock); - mono_os_mutex_destroy (&domain->jit_code_hash_lock); - - mono_coop_mutex_destroy (&domain->lock); - - domain->setup = NULL; - - if (mono_gc_is_moving ()) - mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED)); - - mono_appdomains_lock (); - appdomains_list [domain->domain_id] = NULL; - mono_appdomains_unlock (); - - mono_gc_free_fixed (domain); - -#ifndef DISABLE_PERFCOUNTERS - mono_atomic_dec_i32 (&mono_perfcounters->loader_appdomains); -#endif - - if (domain == mono_root_domain) - mono_root_domain = NULL; -#else g_assert_not_reached (); -#endif } /** @@ -1961,9 +1710,5 @@ mono_domain_get_assemblies (MonoDomain *domain, gboolean refonly) MonoAssemblyLoadContext * mono_domain_default_alc (MonoDomain *domain) { -#ifndef ENABLE_NETCORE - return NULL; -#else return domain->default_alc; -#endif } diff --git a/src/mono/mono/metadata/environment.c b/src/mono/mono/metadata/environment.c index cabd095..42567ac 100644 --- a/src/mono/mono/metadata/environment.c +++ b/src/mono/mono/metadata/environment.c @@ -61,51 +61,3 @@ mono_get_os_cmd_line (void) { return mono_runtime_get_cmd_line (mini_argc, mini_argv); } - -#ifndef ENABLE_NETCORE -/* note: we better manipulate the string in managed code (easier and safer) */ -MonoStringHandle -ves_icall_System_Environment_GetOSVersionString (MonoError *error) -{ - error_init (error); -#ifdef HOST_WIN32 - MONO_DISABLE_WARNING (4996) // 'GetVersionExW': was declared deprecated - OSVERSIONINFOEXW verinfo; - verinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - if (GetVersionExW ((OSVERSIONINFO*)&verinfo)) { - char version [128]; - /* maximum string length is 45 bytes - 4 x 10 bytes per number, 1 byte for 0, 3 x 1 byte for dots, 1 for NULL */ - sprintf (version, "%ld.%ld.%ld.%d", - verinfo.dwMajorVersion, - verinfo.dwMinorVersion, - verinfo.dwBuildNumber, - verinfo.wServicePackMajor << 16); - return mono_string_new_handle (mono_domain_get (), version, error); - } - MONO_RESTORE_WARNING -#elif defined(HAVE_SYS_UTSNAME_H) && defined(_AIX) - /* - * AIX puts the major version number in .version and minor in .release; so make a - * version string based on that; other Unices seem to cram everything in .release - * and .version is for things like kernel variants. - */ - struct utsname name; - char version [sizeof(name)]; - - if (uname (&name) >= 0) { - sprintf (version, "%s.%s", name.version, name.release); - return mono_string_new_handle (mono_domain_get (), version, error); - } -#elif defined(HAVE_SYS_UTSNAME_H) - struct utsname name; - - memset (&name, 0, sizeof (name)); // WSL does not always nul terminate. - - if (uname (&name) >= 0) { - return mono_string_new_handle (mono_domain_get (), name.release, error); - } -#endif - return mono_string_new_handle (mono_domain_get (), "0.0.0.0", error); -} -#endif diff --git a/src/mono/mono/metadata/exception.c b/src/mono/mono/metadata/exception.c index db668d2..16d1078 100644 --- a/src/mono/mono/metadata/exception.c +++ b/src/mono/mono/metadata/exception.c @@ -680,14 +680,9 @@ mono_get_exception_argument (const char *arg, const char *msg) return mono_get_exception_argument_internal ("ArgumentException", arg, msg); } -#ifndef ENABLE_NETCORE -TYPED_HANDLE_DECL (MonoArgumentException); -#endif - static MonoExceptionHandle mono_exception_new_argument_internal (const char *type, const char *arg, const char *msg, MonoError *error) { -#ifdef ENABLE_NETCORE MonoStringHandle arg_str = arg ? mono_string_new_handle (mono_domain_get (), arg, error) : NULL_HANDLE_STRING; MonoStringHandle msg_str = msg ? mono_string_new_handle (mono_domain_get (), msg, error) : NULL_HANDLE_STRING; @@ -695,16 +690,6 @@ mono_exception_new_argument_internal (const char *type, const char *arg, const c return mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", type, msg_str, arg_str, error); else return mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", type, arg_str, msg_str, error); -#else - MonoExceptionHandle ex = mono_exception_new_by_name_msg (mono_get_corlib (), "System", type, msg, error); - - if (arg && !MONO_HANDLE_IS_NULL (ex)) { - MonoArgumentExceptionHandle argex = MONO_HANDLE_CAST (MonoArgumentException, ex); - MonoStringHandle arg_str = mono_string_new_handle (MONO_HANDLE_DOMAIN (ex), arg, error); - MONO_HANDLE_SET (argex, param_name, arg_str); - } - return ex; -#endif } MonoExceptionHandle diff --git a/src/mono/mono/metadata/filewatcher.c b/src/mono/mono/metadata/filewatcher.c deleted file mode 100644 index cf16461..0000000 --- a/src/mono/mono/metadata/filewatcher.c +++ /dev/null @@ -1,194 +0,0 @@ -/** - * \file - * File System Watcher internal calls - * - * Authors: - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * Copyright 2004-2009 Novell, Inc (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#include - -#if !ENABLE_NETCORE - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_EVENT_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HOST_WIN32 - -/* - * TODO: - * We use the managed watcher on windows, so the code inside this #if is never used - */ -gint -ves_icall_System_IO_FSW_SupportsFSW (void) -{ - return 1; -} - -int -ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn, - MonoStringHandleOut filename, - int *code, - int *reqnum, MonoError *error) -{ - return FALSE; -} - -#else - -static int (*FAMNextEvent) (gpointer, gpointer); - -#if defined(HAVE_SYS_INOTIFY_H) -#include -#endif - -gint -ves_icall_System_IO_FSW_SupportsFSW (void) -{ -#if defined(__APPLE__) - if (getenv ("MONO_DARWIN_USE_KQUEUE_FSW")) - return 3; /* kqueue */ - else - return 6; /* CoreFX */ -#elif defined(HAVE_SYS_INOTIFY_H) - int inotify_instance = inotify_init (); - if (inotify_instance == -1) - return 0; /* DefaultWatcher */ - close (inotify_instance); - return 6; /* CoreFX */ -#elif HAVE_KQUEUE - return 3; /* kqueue */ -#else - MonoDl *fam_module; - int lib_used = 4; /* gamin */ - char *err; - - fam_module = mono_dl_open ("libgamin-1.so", MONO_DL_LAZY, NULL); - if (fam_module == NULL) { - lib_used = 2; /* FAM */ - fam_module = mono_dl_open ("libfam.so", MONO_DL_LAZY, NULL); - } - - if (fam_module == NULL) - return 0; /* DefaultWatcher */ - - err = mono_dl_symbol (fam_module, "FAMNextEvent", (gpointer *) &FAMNextEvent); - g_free (err); - if (FAMNextEvent == NULL) - return 0; - - return lib_used; /* DefaultWatcher */ -#endif -} - -/* Almost copied from fam.h. Weird, I know */ -typedef struct { - gint reqnum; -} FAMRequest; - -typedef struct FAMEvent { - gpointer fc; - FAMRequest fr; - gchar *hostname; - gchar filename [PATH_MAX]; - gpointer userdata; - gint code; -} FAMEvent; - -int -ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn, - MonoStringHandleOut filename, - int *code, - int *reqnum, - MonoError *error) -{ - FAMEvent ev; - - if (FAMNextEvent (conn, &ev) == 1) { - MONO_HANDLE_ASSIGN_RAW (filename, mono_string_new_checked (mono_domain_get (), ev.filename, error)); - return_val_if_nok (error, FALSE); - *code = ev.code; - *reqnum = ev.fr.reqnum; - return TRUE; - } - - return FALSE; -} -#endif - -#if HAVE_KQUEUE - -static void -interrupt_kevent (gpointer data) -{ - int *kq_ptr = (int*)data; - - /* Interrupt the kevent () call by closing the fd */ - close (*kq_ptr); - /* Signal to managed code that the fd is closed */ - *kq_ptr = -1; -} - -/* - * ves_icall_System_IO_KqueueMonitor_kevent_notimeout: - * - * Call kevent (), while handling runtime interruptions. - */ -int -ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents) -{ - int res; - gboolean interrupted; - - mono_thread_info_install_interrupt (interrupt_kevent, kq_ptr, &interrupted); - if (interrupted) { - close (*kq_ptr); - *kq_ptr = -1; - return -1; - } - - MONO_ENTER_GC_SAFE; - res = kevent (*kq_ptr, (const struct kevent*)changelist, nchanges, (struct kevent*)eventlist, nevents, NULL); - MONO_EXIT_GC_SAFE; - - mono_thread_info_uninstall_interrupt (&interrupted); - - return res; -} - -#else - -int -ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents) -{ - g_assert_not_reached (); - return -1; -} - -#endif /* #if HAVE_KQUEUE */ - -#else - -MONO_EMPTY_SOURCE_FILE (filewatcher); - -#endif /* !ENABLE_NETCORE */ diff --git a/src/mono/mono/metadata/filewatcher.h b/src/mono/mono/metadata/filewatcher.h deleted file mode 100644 index 3d484b9..0000000 --- a/src/mono/mono/metadata/filewatcher.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * \file - * File System Watcher internal calls - * - * Authors: - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * (C) 2004 Novell, Inc. (http://www.novell.com) - */ - -#ifndef _MONO_METADATA_FILEWATCHER_H -#define _MONO_METADATA_FILEWATCHER_H - -#include -#include "mono/utils/mono-compiler.h" -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#if !ENABLE_NETCORE - -ICALL_EXPORT -gint ves_icall_System_IO_FSW_SupportsFSW (void); - -ICALL_EXPORT -int ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq, gpointer changelist, int nchanges, gpointer eventlist, int nevents); - -#endif - -#ifdef HOST_IOS // This will obsoleted by System.Native as soon as it's ported to iOS -MONO_API char* SystemNative_RealPath(const char* path); -MONO_API void SystemNative_Sync (void); -#endif - -#endif diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index f81963b..b459e40 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -25,13 +25,11 @@ #include #include #include -#include #include #include #include #include /* for mono_delegate_free_ftnptr () */ #include -#include #include #include #include @@ -650,8 +648,6 @@ ves_icall_System_GC_get_ephemeron_tombstone (MonoError *error) return MONO_HANDLE_NEW (MonoObject, mono_domain_get ()->ephemeron_tombstone); } -#if ENABLE_NETCORE - MonoGCHandle ves_icall_System_GCHandle_InternalAlloc (MonoObjectHandle obj, gint32 type, MonoError *error) { @@ -694,88 +690,6 @@ ves_icall_System_GCHandle_InternalSet (MonoGCHandle handle, MonoObjectHandle obj mono_gchandle_set_target_handle (handle, obj); } -#else - -MonoObjectHandle -ves_icall_System_GCHandle_GetTarget (MonoGCHandle handle, MonoError *error) -{ - return mono_gchandle_get_target_handle (handle); -} - -/* - * if type == -1, change the target of the handle, otherwise allocate a new handle. - */ -MonoGCHandle -ves_icall_System_GCHandle_GetTargetHandle (MonoObjectHandle obj, MonoGCHandle handle, gint32 type, MonoError *error) -{ - if (type == -1) { - mono_gchandle_set_target_handle (handle, obj); - /* the handle doesn't change */ - return handle; - } - switch (type) { - case HANDLE_WEAK: - return mono_gchandle_new_weakref_from_handle (obj); - case HANDLE_WEAK_TRACK: - return mono_gchandle_new_weakref_from_handle_track_resurrection (obj); - case HANDLE_NORMAL: - return mono_gchandle_from_handle (obj, FALSE); - case HANDLE_PINNED: - return mono_gchandle_from_handle (obj, TRUE); - default: - g_assert_not_reached (); - } - return NULL; -} - -void -ves_icall_System_GCHandle_FreeHandle (MonoGCHandle handle) -{ - mono_gchandle_free_internal (handle); -} - -gpointer -ves_icall_System_GCHandle_GetAddrOfPinnedObject (MonoGCHandle handle) -{ - // Handles seem to only be in the way here, and the object is pinned. - - MonoObject *obj; - guint32 gch = MONO_GC_HANDLE_TO_UINT (handle); - - if (MONO_GC_HANDLE_TYPE (gch) != HANDLE_PINNED) - return (gpointer)-2; - - obj = mono_gchandle_get_target_internal (handle); - if (obj) { - MonoClass *klass = mono_object_class (obj); - - // FIXME This would be a good place for - // object->GetAddrOfPinnedObject() - // or klass->GetAddrOfPinnedObject(obj); - - if (klass == mono_defaults.string_class) { - return mono_string_chars_internal ((MonoString*)obj); - } else if (m_class_get_rank (klass)) { - return mono_array_addr_internal ((MonoArray*)obj, char, 0); - } else { - /* the C# code will check and throw the exception */ - /* FIXME: missing !klass->blittable test, see bug #61134 */ - if (mono_class_is_auto_layout (klass)) - return (gpointer)-1; - return mono_object_get_data (obj); - } - } - return NULL; -} - -MonoBoolean -ves_icall_System_GCHandle_CheckCurrentDomain (MonoGCHandle gchandle) -{ - return mono_gchandle_is_in_domain (gchandle, mono_domain_get ()); -} - -#endif - static MonoCoopSem finalizer_sem; static volatile gboolean finished; @@ -923,8 +837,6 @@ mono_runtime_do_background_work (void) { mono_threads_perform_thread_dump (); - mono_console_handle_async_ops (); - mono_attach_maybe_start (); finalize_domain_objects (); diff --git a/src/mono/mono/metadata/icall-decl.h b/src/mono/mono/metadata/icall-decl.h index b00b1aa..a00bd5c 100644 --- a/src/mono/mono/metadata/icall-decl.h +++ b/src/mono/mono/metadata/icall-decl.h @@ -8,27 +8,21 @@ #include "appdomain-icalls.h" #include "class.h" -#include "console-io.h" #include "environment.h" #include "file-mmap.h" -#include "filewatcher.h" #include "gc-internals.h" #include "handle-decl.h" #include "handle.h" -#include "locales.h" #include "marshal.h" #include "monitor.h" #include "mono-perfcounters.h" #include "object-forward.h" #include "object-internals.h" -#include "rand.h" #include "reflection.h" #include "security-core-clr.h" #include "security-manager.h" #include "security.h" #include "string-icalls.h" -#include "threadpool-io.h" -#include "threadpool.h" #include "mono/utils/mono-digest.h" #include "mono/utils/mono-forward-internal.h" #include "w32event.h" @@ -136,20 +130,16 @@ ICALL_EXPORT float ves_icall_System_MathF_Sqrt (float); ICALL_EXPORT float ves_icall_System_MathF_Tan (float); ICALL_EXPORT float ves_icall_System_MathF_Tanh (float); ICALL_EXPORT float ves_icall_System_Math_Abs_single (float); -#if ENABLE_NETCORE ICALL_EXPORT gint32 ves_icall_System_Math_ILogB (double); ICALL_EXPORT double ves_icall_System_Math_Log2 (double); ICALL_EXPORT double ves_icall_System_Math_FusedMultiplyAdd (double, double, double); ICALL_EXPORT gint32 ves_icall_System_MathF_ILogB (float); ICALL_EXPORT float ves_icall_System_MathF_Log2 (float); ICALL_EXPORT float ves_icall_System_MathF_FusedMultiplyAdd (float, float, float); -#endif ICALL_EXPORT gint ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void); ICALL_EXPORT gint32 ves_icall_System_Environment_get_ProcessorCount (void); ICALL_EXPORT gint32 ves_icall_System_Environment_get_TickCount (void); -#if ENABLE_NETCORE ICALL_EXPORT gint64 ves_icall_System_Environment_get_TickCount64 (void); -#endif ICALL_EXPORT gint64 ves_icall_System_DateTime_GetSystemTimeAsFileTime (void); ICALL_EXPORT gint64 ves_icall_System_Diagnostics_Process_GetProcessData (int, gint32, MonoProcessError*); ICALL_EXPORT gint64 ves_icall_System_Diagnostics_Stopwatch_GetTimestamp (void); @@ -157,9 +147,6 @@ ICALL_EXPORT gint64 ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollect ICALL_EXPORT gint64 ves_icall_System_Threading_Timer_GetTimeMonotonic (void); ICALL_EXPORT gpointer ves_icall_System_GCHandle_GetAddrOfPinnedObject (MonoGCHandle handle); ICALL_EXPORT int ves_icall_Interop_Sys_DoubleToString (double, char*, char*, int); -#if !ENABLE_NETCORE -ICALL_EXPORT int ves_icall_System_Environment_get_Platform (void); -#endif ICALL_EXPORT int ves_icall_System_GC_GetCollectionCount (int); ICALL_EXPORT int ves_icall_System_GC_GetMaxGeneration (void); ICALL_EXPORT gint64 ves_icall_System_GC_GetAllocatedBytesForCurrentThread (void); @@ -177,44 +164,12 @@ ICALL_EXPORT void ves_icall_System_GC_RecordPressure (gint64); ICALL_EXPORT void ves_icall_System_GC_WaitForPendingFinalizers (void); ICALL_EXPORT void ves_icall_System_GC_GetGCMemoryInfo (gint64*, gint64*, gint64*, gint64*, gint64*); -#if !ENABLE_NETCORE -ICALL_EXPORT void ves_icall_System_IO_LogcatTextWriter_Log (const char*, gint32, const char*); -#endif ICALL_EXPORT void ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const**, gint32 const**, gunichar2 const**, gunichar2 const**, gint64 const**, gint32 const**); -#if ENABLE_NETCORE ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_Memmove (guint8*, guint8*, size_t); ICALL_EXPORT void ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *, guint8 *, size_t, MonoType *); -#else -ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_Memmove (guint8*, guint8*, guint); -ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_Memmove_wbarrier (guint8*, guint8*, guint, MonoType*); -#endif -#if ENABLE_NETCORE ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8*, size_t); -#else -ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8*, guint); -#endif ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_ecvt_s(char*, size_t, double, int, int*, int*); -#if !defined(ENABLE_NETCORE) -#if defined(ENABLE_MONODROID) || defined(ENABLE_MONOTOUCH) || defined(TARGET_WASM) -ICALL_EXPORT gpointer ves_icall_System_IO_Compression_DeflateStreamNative_CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data); -ICALL_EXPORT gint32 ves_icall_System_IO_Compression_DeflateStreamNative_CloseZStream (gpointer stream); -ICALL_EXPORT gint32 ves_icall_System_IO_Compression_DeflateStreamNative_Flush (gpointer stream); -ICALL_EXPORT gint32 ves_icall_System_IO_Compression_DeflateStreamNative_ReadZStream (gpointer stream, gpointer buffer, gint32 length); -ICALL_EXPORT gint32 ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream (gpointer stream, gpointer buffer, gint32 length); -#endif - -#if defined(TARGET_WASM) -ICALL_EXPORT void ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name (MonoString **result); -#endif - -#if defined(ENABLE_MONODROID) -ICALL_EXPORT gpointer ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CreateNLSocket (void); -ICALL_EXPORT gint32 ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size); -ICALL_EXPORT gpointer ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket (gpointer sock); -#endif -#endif - ICALL_EXPORT MonoBoolean ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle); ICALL_EXPORT gpointer ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void); ICALL_EXPORT gint32 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void); @@ -241,7 +196,6 @@ ICALL_EXPORT MonoBoolean ves_icall_System_Diagnostics_Debugger_IsAttached_intern ICALL_EXPORT MonoBoolean ves_icall_System_Diagnostics_Debugger_IsLogging (void); ICALL_EXPORT void ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *volatile* category, MonoString *volatile* message); -#ifdef ENABLE_NETCORE ICALL_EXPORT intptr_t ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DefineEvent (intptr_t prov_handle, uint32_t event_id, int64_t keywords, uint32_t event_version, uint32_t level, const uint8_t *metadata, uint32_t metadata_len); ICALL_EXPORT void ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DeleteProvider (intptr_t prov_handle); ICALL_EXPORT void ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Disable (uint64_t session_id); @@ -252,7 +206,6 @@ ICALL_EXPORT intptr_t ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Get ICALL_EXPORT MonoBoolean ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetSessionInfo (uint64_t session_id, void *session_info); ICALL_EXPORT intptr_t ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t session_id); ICALL_EXPORT void ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (intptr_t event_handle, void *event_data, uint32_t event_data_len, const uint8_t *activity_id, const uint8_t *related_activity_id); -#endif ICALL_EXPORT void ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array); ICALL_EXPORT void ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, MonoBoolean free_struct); @@ -295,18 +248,16 @@ ICALL_EXPORT gpointer ves_icall_System_Threading_Semaphore_CreateSemaphore_ic ICALL_EXPORT gpointer ves_icall_System_Threading_Semaphore_OpenSemaphore_icall (const gunichar2 *name, gint32 name_length, gint32 rights, gint32 *win32error); ICALL_EXPORT MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount); -#ifdef ENABLE_NETCORE ICALL_EXPORT gpointer ves_icall_System_Threading_LowLevelLifoSemaphore_InitInternal (void); ICALL_EXPORT void ves_icall_System_Threading_LowLevelLifoSemaphore_DeleteInternal (gpointer sem_ptr); ICALL_EXPORT gint32 ves_icall_System_Threading_LowLevelLifoSemaphore_TimedWaitInternal (gpointer sem_ptr, gint32 timeout_ms); ICALL_EXPORT void ves_icall_System_Threading_LowLevelLifoSemaphore_ReleaseInternal (gpointer sem_ptr, gint32 count); -#endif -#if defined(ENABLE_NETCORE) && defined(TARGET_AMD64) +#ifdef TARGET_AMD64 ICALL_EXPORT void ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id); #endif -#if defined(ENABLE_NETCORE) && defined(ENABLE_METADATA_UPDATE) +#ifdef ENABLE_METADATA_UPDATE ICALL_EXPORT void ves_icall_Mono_Runtime_LoadMetadataUpdate (MonoAssembly *assm, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dil_bytes, int32_t dil_len); #endif diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index 56dd99b..723ef8d 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -107,1036 +107,7 @@ // "HandleIn" is the default for managed types, and is just called "Handle". // -#if ENABLE_NETCORE #include "icall-def-netcore.h" -#else - -ICALL_TYPE(CLR_INTEROP_SYS, "Interop/Sys", CLR_INTEROP_SYS_1) -NOHANDLES(ICALL(CLR_INTEROP_SYS_1, "DoubleToString", ves_icall_Interop_Sys_DoubleToString)) - -#ifndef DISABLE_PROCESSES -ICALL_TYPE(NATIVEMETHODS, "Microsoft.Win32.NativeMethods", NATIVEMETHODS_1) -NOHANDLES(ICALL(NATIVEMETHODS_1, "CloseProcess", ves_icall_Microsoft_Win32_NativeMethods_CloseProcess)) -NOHANDLES(ICALL(NATIVEMETHODS_2, "GetCurrentProcess", ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess)) -NOHANDLES(ICALL(NATIVEMETHODS_3, "GetCurrentProcessId", ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId)) -NOHANDLES(ICALL(NATIVEMETHODS_4, "GetExitCodeProcess", ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess)) -NOHANDLES(ICALL(NATIVEMETHODS_5, "GetPriorityClass", ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass)) -NOHANDLES(ICALL(NATIVEMETHODS_6, "GetProcessTimes", ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes)) -NOHANDLES(ICALL(NATIVEMETHODS_7, "GetProcessWorkingSetSize", ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize)) -NOHANDLES(ICALL(NATIVEMETHODS_8, "SetPriorityClass", ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass)) -NOHANDLES(ICALL(NATIVEMETHODS_9, "SetProcessWorkingSetSize", ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize)) -NOHANDLES(ICALL(NATIVEMETHODS_10, "TerminateProcess", ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess)) -NOHANDLES(ICALL(NATIVEMETHODS_11, "WaitForInputIdle", ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle)) -#else -ICALL_TYPE(NATIVEMETHODS, "Microsoft.Win32.NativeMethods", NATIVEMETHODS_11) -NOHANDLES(ICALL(NATIVEMETHODS_11, "WaitForInputIdle", ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle)) -#endif - -#ifndef DISABLE_COM -ICALL_TYPE(COMPROX, "Mono.Interop.ComInteropProxy", COMPROX_1) -NOHANDLES(ICALL(COMPROX_1, "AddProxy", ves_icall_Mono_Interop_ComInteropProxy_AddProxy)) -NOHANDLES(ICALL(COMPROX_2, "FindProxy", ves_icall_Mono_Interop_ComInteropProxy_FindProxy)) -#endif - -ICALL_TYPE(TLS_PROVIDER_FACTORY, "Mono.Net.Security.MonoTlsProviderFactory", TLS_PROVIDER_FACTORY_1) -NOHANDLES(ICALL(TLS_PROVIDER_FACTORY_1, "IsBtlsSupported", ves_icall_Mono_TlsProviderFactory_IsBtlsSupported)) - -ICALL_TYPE(RUNTIME, "Mono.Runtime", RUNTIME_20) -NOHANDLES(ICALL(RUNTIME_20, "AnnotateMicrosoftTelemetry_internal", ves_icall_Mono_Runtime_AnnotateMicrosoftTelemetry)) -NOHANDLES(ICALL(RUNTIME_19, "CheckCrashReportLog_internal", ves_icall_Mono_Runtime_CheckCrashReportingLog)) -NOHANDLES(ICALL(RUNTIME_1, "DisableMicrosoftTelemetry", ves_icall_Mono_Runtime_DisableMicrosoftTelemetry)) -HANDLES(RUNTIME_15, "DumpStateSingle_internal", ves_icall_Mono_Runtime_DumpStateSingle, MonoString, 2, (guint64_ref, guint64_ref)) -HANDLES(RUNTIME_16, "DumpStateTotal_internal", ves_icall_Mono_Runtime_DumpStateTotal, MonoString, 2, (guint64_ref, guint64_ref)) -NOHANDLES(ICALL(RUNTIME_18, "EnableCrashReportLog_internal", ves_icall_Mono_Runtime_EnableCrashReportingLog)) -HANDLES(RUNTIME_2, "EnableMicrosoftTelemetry_internal", ves_icall_Mono_Runtime_EnableMicrosoftTelemetry, void, 6, (const_char_ptr, const_char_ptr, const_char_ptr, const_char_ptr, const_char_ptr, const_char_ptr)) -HANDLES(RUNTIME_3, "ExceptionToState_internal", ves_icall_Mono_Runtime_ExceptionToState, MonoString, 3, (MonoException, guint64_ref, guint64_ref)) -HANDLES(RUNTIME_4, "GetDisplayName", ves_icall_Mono_Runtime_GetDisplayName, MonoString, 0, ()) -HANDLES(RUNTIME_12, "GetNativeStackTrace", ves_icall_Mono_Runtime_GetNativeStackTrace, MonoString, 1, (MonoException)) -NOHANDLES(ICALL(RUNTIME_21, "RegisterReportingForAllNativeLibs_internal", ves_icall_Mono_Runtime_RegisterReportingForAllNativeLibs)) -NOHANDLES(ICALL(RUNTIME_17, "RegisterReportingForNativeLib_internal", ves_icall_Mono_Runtime_RegisterReportingForNativeLib)) -HANDLES(RUNTIME_13, "SendMicrosoftTelemetry_internal", ves_icall_Mono_Runtime_SendMicrosoftTelemetry, void, 3, (const_char_ptr, guint64, guint64)) -HANDLES(RUNTIME_14, "WriteStateToFile_internal", ves_icall_Mono_Runtime_DumpTelemetry, void, 3, (const_char_ptr, guint64, guint64)) - -ICALL_TYPE(RTCLASS, "Mono.RuntimeClassHandle", RTCLASS_1) -NOHANDLES(ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass)) - -ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1) -NOHANDLES(ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree)) - -ICALL_TYPE(RTMARSHAL, "Mono.RuntimeMarshal", RTMARSHAL_1) -NOHANDLES(ICALL(RTMARSHAL_1, "FreeAssemblyName", ves_icall_Mono_RuntimeMarshal_FreeAssemblyName)) - -ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1) -NOHANDLES(ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree)) -NOHANDLES(ICALL(SAFESTRMARSHAL_2, "StringToUtf8_icall", ves_icall_Mono_SafeStringMarshal_StringToUtf8)) - -#ifndef PLATFORM_RO_FS -ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1) -NOHANDLES(ICALL(KPAIR_1, "_CanSecure", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure)) -NOHANDLES(ICALL(KPAIR_2, "_IsMachineProtected", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsMachineProtected)) -NOHANDLES(ICALL(KPAIR_3, "_IsUserProtected", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsUserProtected)) -NOHANDLES(ICALL(KPAIR_4, "_ProtectMachine", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine)) -NOHANDLES(ICALL(KPAIR_5, "_ProtectUser", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser)) -#endif /* !PLATFORM_RO_FS */ - -ICALL_TYPE(APPDOM, "System.AppDomain", APPDOM_23) -HANDLES(APPDOM_23, "DoUnhandledException", ves_icall_System_AppDomain_DoUnhandledException, void, 2, (MonoAppDomain, MonoException)) -HANDLES(APPDOM_1, "ExecuteAssembly", ves_icall_System_AppDomain_ExecuteAssembly, gint32, 3, (MonoAppDomain, MonoReflectionAssembly, MonoArray)) -HANDLES(APPDOM_2, "GetAssemblies", ves_icall_System_AppDomain_GetAssemblies, MonoArray, 2, (MonoAppDomain, MonoBoolean)) -HANDLES(APPDOM_3, "GetData", ves_icall_System_AppDomain_GetData, MonoObject, 2, (MonoAppDomain, MonoString)) -HANDLES(APPDOM_4, "InternalGetContext", ves_icall_System_AppDomain_InternalGetContext, MonoAppContext, 0, ()) -HANDLES(APPDOM_5, "InternalGetDefaultContext", ves_icall_System_AppDomain_InternalGetDefaultContext, MonoAppContext, 0, ()) -HANDLES(APPDOM_6, "InternalGetProcessGuid", ves_icall_System_AppDomain_InternalGetProcessGuid, MonoString, 1, (MonoString)) -HANDLES(APPDOM_7, "InternalIsFinalizingForUnload", ves_icall_System_AppDomain_InternalIsFinalizingForUnload, MonoBoolean, 1, (gint32)) -HANDLES(APPDOM_8, "InternalPopDomainRef", ves_icall_System_AppDomain_InternalPopDomainRef, void, 0, ()) -HANDLES(APPDOM_9, "InternalPushDomainRef", ves_icall_System_AppDomain_InternalPushDomainRef, void, 1, (MonoAppDomain)) -HANDLES(APPDOM_10, "InternalPushDomainRefByID", ves_icall_System_AppDomain_InternalPushDomainRefByID, void, 1, (gint32)) -HANDLES(APPDOM_11, "InternalSetContext", ves_icall_System_AppDomain_InternalSetContext, MonoAppContext, 1, (MonoAppContext)) -HANDLES(APPDOM_12, "InternalSetDomain", ves_icall_System_AppDomain_InternalSetDomain, MonoAppDomain, 1, (MonoAppDomain)) -HANDLES(APPDOM_13, "InternalSetDomainByID", ves_icall_System_AppDomain_InternalSetDomainByID, MonoAppDomain, 1, (gint32)) -HANDLES(APPDOM_14, "InternalUnload", ves_icall_System_AppDomain_InternalUnload, void, 1, (gint32)) -HANDLES(APPDOM_15, "LoadAssembly", ves_icall_System_AppDomain_LoadAssembly, MonoReflectionAssembly, 5, (MonoAppDomain, MonoString, MonoObject, MonoBoolean, MonoStackCrawlMark_ptr)) -HANDLES(APPDOM_16, "LoadAssemblyRaw", ves_icall_System_AppDomain_LoadAssemblyRaw, MonoReflectionAssembly, 5, (MonoAppDomain, MonoArray, MonoArray, MonoObject, MonoBoolean)) -HANDLES(APPDOM_17, "SetData", ves_icall_System_AppDomain_SetData, void, 3, (MonoAppDomain, MonoString, MonoObject)) -HANDLES(APPDOM_18, "createDomain", ves_icall_System_AppDomain_createDomain, MonoAppDomain, 2, (MonoString, MonoAppDomainSetup)) -HANDLES(APPDOM_19, "getCurDomain", ves_icall_System_AppDomain_getCurDomain, MonoAppDomain, 0, ()) -HANDLES(APPDOM_20, "getFriendlyName", ves_icall_System_AppDomain_getFriendlyName, MonoString, 1, (MonoAppDomain)) -HANDLES(APPDOM_21, "getRootDomain", ves_icall_System_AppDomain_getRootDomain, MonoAppDomain, 0, ()) -HANDLES(APPDOM_22, "getSetup", ves_icall_System_AppDomain_getSetup, MonoAppDomainSetup, 1, (MonoAppDomain)) - -ICALL_TYPE(ARGI, "System.ArgIterator", ARGI_1) -NOHANDLES(ICALL(ARGI_1, "IntGetNextArg", ves_icall_System_ArgIterator_IntGetNextArg)) -NOHANDLES(ICALL(ARGI_2, "IntGetNextArgType", ves_icall_System_ArgIterator_IntGetNextArgType)) -NOHANDLES(ICALL(ARGI_3, "IntGetNextArgWithType", ves_icall_System_ArgIterator_IntGetNextArgWithType)) -NOHANDLES(ICALL(ARGI_4, "Setup", ves_icall_System_ArgIterator_Setup)) - -ICALL_TYPE(ARRAY, "System.Array", ARRAY_1) -HANDLES(ARRAY_1, "ClearInternal", ves_icall_System_Array_ClearInternal, void, 3, (MonoArray, int, int)) -HANDLES(ARRAY_3, "CreateInstanceImpl", ves_icall_System_Array_CreateInstanceImpl, MonoArray, 3, (MonoReflectionType, MonoArray, MonoArray)) -HANDLES(ARRAY_4, "FastCopy", ves_icall_System_Array_FastCopy, MonoBoolean, 5, (MonoArray, int, MonoArray, int, int)) -NOHANDLES(ICALL(ARRAY_5, "GetGenericValue_icall", ves_icall_System_Array_GetGenericValue_icall)) -HANDLES(ARRAY_6, "GetLength", ves_icall_System_Array_GetLength, gint32, 2, (MonoArray, gint32)) -HANDLES(ARRAY_15, "GetLongLength", ves_icall_System_Array_GetLongLength, gint64, 2, (MonoArray, gint32)) -HANDLES(ARRAY_7, "GetLowerBound", ves_icall_System_Array_GetLowerBound, gint32, 2, (MonoArray, gint32)) -HANDLES(ARRAY_8, "GetRank", ves_icall_System_Array_GetRank, gint32, 1, (MonoObject)) -HANDLES(ARRAY_9, "GetValue", ves_icall_System_Array_GetValue, MonoObject, 2, (MonoArray, MonoArray)) -HANDLES(ARRAY_10, "GetValueImpl", ves_icall_System_Array_GetValueImpl, MonoObject, 2, (MonoArray, guint32)) -NOHANDLES(ICALL(ARRAY_11, "SetGenericValue_icall", ves_icall_System_Array_SetGenericValue_icall)) -HANDLES(ARRAY_12, "SetValue", ves_icall_System_Array_SetValue, void, 3, (MonoArray, MonoObject, MonoArray)) -HANDLES(ARRAY_13, "SetValueImpl", ves_icall_System_Array_SetValueImpl, void, 3, (MonoArray, MonoObject, guint32)) - -ICALL_TYPE(BUFFER, "System.Buffer", BUFFER_1) -HANDLES(BUFFER_1, "InternalBlockCopy", ves_icall_System_Buffer_BlockCopyInternal, MonoBoolean, 5, (MonoArray, gint32, MonoArray, gint32, gint32)) -NOHANDLES(ICALL(BUFFER_5, "InternalMemcpy", ves_icall_System_Buffer_MemcpyInternal)) -HANDLES(BUFFER_2, "_ByteLength", ves_icall_System_Buffer_ByteLengthInternal, gint32, 1, (MonoArray)) - -ICALL_TYPE(CLRCONFIG, "System.CLRConfig", CLRCONFIG_1) -HANDLES(CLRCONFIG_1, "CheckThrowUnobservedTaskExceptions", ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions, MonoBoolean, 0, ()) - -ICALL_TYPE(DEFAULTC, "System.Configuration.DefaultConfig", DEFAULTC_1) -HANDLES(DEFAULTC_1, "get_bundled_machine_config", ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config, MonoString, 0, ()) -HANDLES(DEFAULTC_2, "get_machine_config_path", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path, MonoString, 0, ()) - -/* Note that the below icall shares the same function as DefaultConfig uses */ -ICALL_TYPE(INTCFGHOST, "System.Configuration.InternalConfigurationHost", INTCFGHOST_1) -HANDLES(INTCFGHOST_1, "get_bundled_app_config", ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_app_config, MonoString, 0, ()) -HANDLES(INTCFGHOST_2, "get_bundled_machine_config", ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config, MonoString, 0, ()) - -ICALL_TYPE(CONSOLE, "System.ConsoleDriver", CONSOLE_1) -HANDLES(CONSOLE_1, "InternalKeyAvailable", ves_icall_System_ConsoleDriver_InternalKeyAvailable, gint32, 1, (gint32)) -HANDLES(CONSOLE_2, "Isatty", ves_icall_System_ConsoleDriver_Isatty, MonoBoolean, 1, (gpointer/*HANDLE*/)) -HANDLES(CONSOLE_3, "SetBreak", ves_icall_System_ConsoleDriver_SetBreak, MonoBoolean, 1, (MonoBoolean)) -HANDLES(CONSOLE_4, "SetEcho", ves_icall_System_ConsoleDriver_SetEcho, MonoBoolean, 1, (MonoBoolean)) -HANDLES(CONSOLE_5, "TtySetup", ves_icall_System_ConsoleDriver_TtySetup, MonoBoolean, 4, (MonoString, MonoString, MonoArrayOut, int_ptr_ref)) - -ICALL_TYPE(DTIME, "System.DateTime", DTIME_1) -NOHANDLES(ICALL(DTIME_1, "GetSystemTimeAsFileTime", ves_icall_System_DateTime_GetSystemTimeAsFileTime)) - -ICALL_TYPE(DELEGATE, "System.Delegate", DELEGATE_1) -HANDLES(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal, MonoMulticastDelegate, 1, (MonoDelegate)) -HANDLES(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal, MonoObject, 4, (MonoReflectionType, MonoObject, MonoReflectionMethod, MonoBoolean)) -HANDLES(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal, MonoReflectionMethod, 1, (MonoDelegate)) - -ICALL_TYPE(DEBUGR, "System.Diagnostics.Debugger", DEBUGR_1) -NOHANDLES(ICALL(DEBUGR_1, "IsAttached_internal", ves_icall_System_Diagnostics_Debugger_IsAttached_internal)) -NOHANDLES(ICALL(DEBUGR_2, "IsLogging", ves_icall_System_Diagnostics_Debugger_IsLogging)) -NOHANDLES(ICALL(DEBUGR_3, "Log_icall", ves_icall_System_Diagnostics_Debugger_Log)) - -ICALL_TYPE(TRACEL, "System.Diagnostics.DefaultTraceListener", TRACEL_1) -HANDLES(TRACEL_1, "WriteWindowsDebugString", ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString, void, 1, (const_gunichar2_ptr)) - -ICALL_TYPE(FILEV, "System.Diagnostics.FileVersionInfo", FILEV_1) -HANDLES(FILEV_1, "GetVersionInfo_icall", ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal, void, 3, (MonoObject, const_gunichar2_ptr, int)) - -ICALL_TYPE(PERFCTR, "System.Diagnostics.PerformanceCounter", PERFCTR_1) -NOHANDLES(ICALL(PERFCTR_1, "FreeData", mono_perfcounter_free_data)) -HANDLES(PERFCTR_2, "GetImpl_icall", mono_perfcounter_get_impl, gpointer, 8, - (const_gunichar2_ptr, gint32, const_gunichar2_ptr, gint32, const_gunichar2_ptr, gint32, gint32_ref, MonoBoolean_ref)) -NOHANDLES(ICALL(PERFCTR_3, "GetSample", mono_perfcounter_get_sample)) -NOHANDLES(ICALL(PERFCTR_4, "UpdateValue", mono_perfcounter_update_value)) - -ICALL_TYPE(PERFCTRCAT, "System.Diagnostics.PerformanceCounterCategory", PERFCTRCAT_1) -HANDLES(PERFCTRCAT_1, "CategoryDelete_icall", mono_perfcounter_category_del, MonoBoolean, 2, (const_gunichar2_ptr, gint32)) -HANDLES(PERFCTRCAT_2, "CategoryHelpInternal_icall", mono_perfcounter_category_help, MonoString, 2, (const_gunichar2_ptr, gint32)) -HANDLES(PERFCTRCAT_3, "CounterCategoryExists_icall", mono_perfcounter_category_exists, MonoBoolean, 4, (const_gunichar2_ptr, gint32, const_gunichar2_ptr, gint32)) -HANDLES(PERFCTRCAT_4, "Create_icall", mono_perfcounter_create, MonoBoolean, 6, (const_gunichar2_ptr, gint32, const_gunichar2_ptr, gint32, gint32, MonoArray)) -HANDLES(PERFCTRCAT_5, "GetCategoryNames", mono_perfcounter_category_names, MonoArray, 0, ()) -HANDLES(PERFCTRCAT_6, "GetCounterNames_icall", mono_perfcounter_counter_names, MonoArray, 2, (const_gunichar2_ptr, gint32)) -HANDLES(PERFCTRCAT_7, "GetInstanceNames_icall", mono_perfcounter_instance_names, MonoArray, 2, (const_gunichar2_ptr, gint32)) -HANDLES(PERFCTRCAT_8, "InstanceExistsInternal_icall", mono_perfcounter_instance_exists, MonoBoolean, 4, (const_gunichar2_ptr, gint32, const_gunichar2_ptr, gint32)) - -#ifndef DISABLE_PROCESSES -ICALL_TYPE(PROCESS, "System.Diagnostics.Process", PROCESS_1) -HANDLES(PROCESS_1, "CreateProcess_internal", ves_icall_System_Diagnostics_Process_CreateProcess_internal, - MonoBoolean, 5, (MonoW32ProcessStartInfo, gpointer, gpointer, gpointer, MonoW32ProcessInfo_ref)) -HANDLES(PROCESS_4, "GetModules_icall", ves_icall_System_Diagnostics_Process_GetModules_internal, MonoArray, 2, (MonoObject, PROCESS_HANDLE)) -NOHANDLES(ICALL(PROCESS_5H, "GetProcessData", ves_icall_System_Diagnostics_Process_GetProcessData)) -HANDLES(PROCESS_6, "GetProcess_internal", ves_icall_System_Diagnostics_Process_GetProcess_internal, gpointer, 1, (guint32)) -HANDLES(PROCESS_7, "GetProcesses_internal", ves_icall_System_Diagnostics_Process_GetProcesses_internal, MonoArray, 0, ()) -HANDLES(PROCESS_14, "MainWindowHandle_icall", ves_icall_System_Diagnostics_Process_MainWindowHandle_internal, gpointer, 1, (guint32)) -HANDLES(PROCESS_10, "ProcessName_icall", ves_icall_System_Diagnostics_Process_ProcessName_internal, MonoString, 1, (PROCESS_HANDLE)) -HANDLES(PROCESS_13, "ShellExecuteEx_internal", ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal, MonoBoolean, 2, (MonoW32ProcessStartInfo, MonoW32ProcessInfo_ref)) -#endif - -ICALL_TYPE(STOPWATCH, "System.Diagnostics.Stopwatch", STOPWATCH_1) -NOHANDLES(ICALL(STOPWATCH_1, "GetTimestamp", ves_icall_System_Diagnostics_Stopwatch_GetTimestamp)) - -ICALL_TYPE(ENUM, "System.Enum", ENUM_1) -HANDLES(ENUM_1, "GetEnumValuesAndNames", ves_icall_System_Enum_GetEnumValuesAndNames, MonoBoolean, 3, (MonoReflectionType, MonoArrayOut, MonoArrayOut)) -HANDLES(ENUM_2, "InternalBoxEnum", ves_icall_System_Enum_ToObject, MonoObject, 2, (MonoReflectionType, guint64)) -HANDLES(ENUM_3, "InternalCompareTo", ves_icall_System_Enum_compare_value_to, int, 2, (MonoObject, MonoObject)) -HANDLES(ENUM_3a, "InternalGetCorElementType", ves_icall_System_Enum_InternalGetCorElementType, int, 1, (MonoObject)) -HANDLES(ENUM_4, "InternalGetUnderlyingType", ves_icall_System_Enum_get_underlying_type, MonoReflectionType, 1, (MonoReflectionType)) -HANDLES(ENUM_5, "InternalHasFlag", ves_icall_System_Enum_InternalHasFlag, MonoBoolean, 2, (MonoObject, MonoObject)) -HANDLES(ENUM_6, "get_hashcode", ves_icall_System_Enum_get_hashcode, int, 1, (MonoObject)) -HANDLES(ENUM_7, "get_value", ves_icall_System_Enum_get_value, MonoObject, 1, (MonoObject)) - -ICALL_TYPE(ENV, "System.Environment", ENV_1) -NOHANDLES(ICALL(ENV_1, "Exit", ves_icall_System_Environment_Exit)) -HANDLES(ENV_1a, "FailFast", ves_icall_System_Environment_FailFast, void, 3, (MonoString, MonoException, MonoString)) -HANDLES(ENV_2, "GetCommandLineArgs", ves_icall_System_Environment_GetCommandLineArgs, MonoArray, 0, ()) -HANDLES(ENV_3, "GetEnvironmentVariableNames", ves_icall_System_Environment_GetEnvironmentVariableNames, MonoArray, 0, ()) -NOHANDLES(ICALL(ENV_31, "GetIs64BitOperatingSystem", ves_icall_System_Environment_GetIs64BitOperatingSystem)) -HANDLES(ENV_4, "GetLogicalDrivesInternal", ves_icall_System_Environment_GetLogicalDrivesInternal, MonoArray, 0, ()) -HANDLES_REUSE_WRAPPER(ENV_5, "GetMachineConfigPath", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path, MonoString, 0, ()) -HANDLES(ENV_51, "GetNewLine", ves_icall_System_Environment_get_NewLine, MonoString, 0, ()) -HANDLES(ENV_6, "GetOSVersionString", ves_icall_System_Environment_GetOSVersionString, MonoString, 0, ()) -NOHANDLES(ICALL(ENV_6a, "GetPageSize", mono_pagesize)) -HANDLES(ENV_7, "GetWindowsFolderPath", ves_icall_System_Environment_GetWindowsFolderPath, MonoString, 1, (int)) -HANDLES(ENV_8, "InternalSetEnvironmentVariable", ves_icall_System_Environment_InternalSetEnvironmentVariable, void, 4, (const_gunichar2_ptr, gint32, const_gunichar2_ptr, gint32)) -NOHANDLES(ICALL(ENV_9, "get_ExitCode", mono_environment_exitcode_get)) -NOHANDLES(ICALL(ENV_10, "get_HasShutdownStarted", ves_icall_System_Environment_get_HasShutdownStarted)) -HANDLES(ENV_11, "get_MachineName", ves_icall_System_Environment_get_MachineName, MonoString, 0, ()) -NOHANDLES(ICALL(ENV_13, "get_Platform", ves_icall_System_Environment_get_Platform)) -NOHANDLES(ICALL(ENV_14, "get_ProcessorCount", ves_icall_System_Environment_get_ProcessorCount)) -NOHANDLES(ICALL(ENV_15, "get_TickCount", ves_icall_System_Environment_get_TickCount)) -HANDLES(ENV_16, "get_UserName", ves_icall_System_Environment_get_UserName, MonoString, 0, ()) -HANDLES(ENV_16b, "get_bundled_machine_config", ves_icall_System_Environment_get_bundled_machine_config, MonoString, 0, ()) -HANDLES(ENV_16m, "internalBroadcastSettingChange", ves_icall_System_Environment_BroadcastSettingChange, void, 0, ()) -HANDLES(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Environment_GetEnvironmentVariable_native, MonoString, 1, (const_char_ptr)) -HANDLES(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath, MonoString, 0, ()) -HANDLES(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome, MonoString, 0, ()) -NOHANDLES(ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set)) -ICALL_TYPE(GC, "System.GC", GC_10) -NOHANDLES(ICALL(GC_10, "GetAllocatedBytesForCurrentThread", ves_icall_System_GC_GetAllocatedBytesForCurrentThread)) -NOHANDLES(ICALL(GC_0, "GetCollectionCount", ves_icall_System_GC_GetCollectionCount)) -HANDLES(GC_0a, "GetGeneration", ves_icall_System_GC_GetGeneration, int, 1, (MonoObject)) -NOHANDLES(ICALL(GC_0b, "GetMaxGeneration", ves_icall_System_GC_GetMaxGeneration)) -NOHANDLES(ICALL(GC_1, "GetTotalMemory", ves_icall_System_GC_GetTotalMemory)) -NOHANDLES(ICALL(GC_2, "InternalCollect", ves_icall_System_GC_InternalCollect)) -NOHANDLES(ICALL(GC_4a, "RecordPressure", ves_icall_System_GC_RecordPressure)) -NOHANDLES(ICALL(GC_6, "WaitForPendingFinalizers", ves_icall_System_GC_WaitForPendingFinalizers)) -HANDLES(GC_6b, "_ReRegisterForFinalize", ves_icall_System_GC_ReRegisterForFinalize, void, 1, (MonoObject)) -HANDLES(GC_7, "_SuppressFinalize", ves_icall_System_GC_SuppressFinalize, void, 1, (MonoObject)) -HANDLES(GC_9, "get_ephemeron_tombstone", ves_icall_System_GC_get_ephemeron_tombstone, MonoObject, 0, ()) -HANDLES(GC_8, "register_ephemeron_array", ves_icall_System_GC_register_ephemeron_array, void, 1, (MonoObject)) - -ICALL_TYPE(CALDATA, "System.Globalization.CalendarData", CALDATA_1) -HANDLES(CALDATA_1, "fill_calendar_data", ves_icall_System_Globalization_CalendarData_fill_calendar_data, MonoBoolean, 3, (MonoCalendarData, MonoString, gint32)) - -ICALL_TYPE(COMPINF, "System.Globalization.CompareInfo", COMPINF_4) -NOHANDLES(ICALL(COMPINF_4, "internal_compare_icall", ves_icall_System_Globalization_CompareInfo_internal_compare)) -NOHANDLES(ICALL(COMPINF_6, "internal_index_icall", ves_icall_System_Globalization_CompareInfo_internal_index)) - -ICALL_TYPE(CULDATA, "System.Globalization.CultureData", CULDATA_1) -HANDLES(CULDATA_1, "fill_culture_data", ves_icall_System_Globalization_CultureData_fill_culture_data, void, 2, (MonoCultureData, gint32)) -NOHANDLES(ICALL(CULDATA_2, "fill_number_data", ves_icall_System_Globalization_CultureData_fill_number_data)) - -ICALL_TYPE(CULINF, "System.Globalization.CultureInfo", CULINF_5) -HANDLES(CULINF_5, "construct_internal_locale_from_lcid", ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid, MonoBoolean, 2, (MonoCultureInfo, gint32)) -HANDLES(CULINF_6, "construct_internal_locale_from_name", ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name, MonoBoolean, 2, (MonoCultureInfo, MonoString)) -HANDLES(CULINF_7, "get_current_locale_name", ves_icall_System_Globalization_CultureInfo_get_current_locale_name, MonoString, 0, ()) -HANDLES(CULINF_9, "internal_get_cultures", ves_icall_System_Globalization_CultureInfo_internal_get_cultures, MonoArray, 3, (MonoBoolean, MonoBoolean, MonoBoolean)) - -ICALL_TYPE(REGINF, "System.Globalization.RegionInfo", REGINF_2) -HANDLES(REGINF_2, "construct_internal_region_from_name", ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_name, MonoBoolean, 2, (MonoRegionInfo, MonoString)) - -#if defined(ENABLE_MONODROID) || defined(ENABLE_MONOTOUCH) || defined(TARGET_WASM) -ICALL_TYPE(DEFLATESTREAM, "System.IO.Compression.DeflateStreamNative", DEFLATESTREAM_1) -NOHANDLES(ICALL(DEFLATESTREAM_1, "CloseZStream", ves_icall_System_IO_Compression_DeflateStreamNative_CloseZStream)) -NOHANDLES(ICALL(DEFLATESTREAM_2, "CreateZStream", ves_icall_System_IO_Compression_DeflateStreamNative_CreateZStream)) -NOHANDLES(ICALL(DEFLATESTREAM_3, "Flush", ves_icall_System_IO_Compression_DeflateStreamNative_Flush)) -NOHANDLES(ICALL(DEFLATESTREAM_4, "ReadZStream", ves_icall_System_IO_Compression_DeflateStreamNative_ReadZStream)) -NOHANDLES(ICALL(DEFLATESTREAM_5, "WriteZStream", ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream)) -#endif - -#ifndef PLATFORM_NO_DRIVEINFO -ICALL_TYPE(IODRIVEINFO, "System.IO.DriveInfo", IODRIVEINFO_1) -NOHANDLES(ICALL(IODRIVEINFO_1, "GetDiskFreeSpaceInternal", ves_icall_System_IO_DriveInfo_GetDiskFreeSpace)) -HANDLES(IODRIVEINFO_2, "GetDriveFormatInternal", ves_icall_System_IO_DriveInfo_GetDriveFormat, MonoString, 2, (const_gunichar2_ptr, int)) -HANDLES(IODRIVEINFO_3, "GetDriveTypeInternal", ves_icall_System_IO_DriveInfo_GetDriveType, guint32, 2, (const_gunichar2_ptr, int)) -#endif - -ICALL_TYPE(FAMW, "System.IO.FAMWatcher", FAMW_1) -HANDLES(FAMW_1, "InternalFAMNextEvent", ves_icall_System_IO_FAMW_InternalFAMNextEvent, int, 4, (gpointer, MonoStringOut, int_ref, int_ref)) - -ICALL_TYPE(FILEW, "System.IO.FileSystemWatcher", FILEW_4) -NOHANDLES(ICALL(FILEW_4, "InternalSupportsFSW", ves_icall_System_IO_FSW_SupportsFSW)) - -ICALL_TYPE(KQUEM, "System.IO.KqueueMonitor", KQUEM_1) -NOHANDLES(ICALL(KQUEM_1, "kevent_notimeout", ves_icall_System_IO_KqueueMonitor_kevent_notimeout)) - -ICALL_TYPE(LOGCATEXTWRITER, "System.IO.LogcatTextWriter", LOGCATEXTWRITER_1) -NOHANDLES(ICALL(LOGCATEXTWRITER_1, "Log", ves_icall_System_IO_LogcatTextWriter_Log)) - -ICALL_TYPE(MMAPIMPL, "System.IO.MemoryMappedFiles.MemoryMapImpl", MMAPIMPL_1) -// FIXME rename to ves_icall... -HANDLES(MMAPIMPL_1, "CloseMapping", mono_mmap_close, void, 1, (gpointer)) -HANDLES(MMAPIMPL_2, "ConfigureHandleInheritability", mono_mmap_configure_inheritability, void, 2, (gpointer, gint32)) -HANDLES(MMAPIMPL_3, "Flush", mono_mmap_flush, void, 1, (gpointer)) -HANDLES(MMAPIMPL_4, "MapInternal", mono_mmap_map, int, 6, (gpointer, gint64, gint64_ref, int, gpointer_ref, gpointer_ref)) -HANDLES(MMAPIMPL_5, "OpenFileInternal", mono_mmap_open_file, gpointer, 9, (const_gunichar2_ptr, int, int, const_gunichar2_ptr, int, gint64_ref, int, int, int_ref)) -HANDLES(MMAPIMPL_6, "OpenHandleInternal", mono_mmap_open_handle, gpointer, 7, (gpointer, const_gunichar2_ptr, int, gint64_ref, int, int, int_ref)) -HANDLES(MMAPIMPL_7, "Unmap", mono_mmap_unmap, MonoBoolean, 1, (gpointer)) - -ICALL_TYPE(MONOIO, "System.IO.MonoIO", MONOIO_39) -NOHANDLES(ICALL(MONOIO_39, "Cancel_internal", ves_icall_System_IO_MonoIO_Cancel)) -NOHANDLES(ICALL(MONOIO_1, "Close(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Close)) -#ifndef PLATFORM_RO_FS -NOHANDLES(ICALL(MONOIO_2, "CopyFile(char*,char*,bool,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_CopyFile)) -NOHANDLES(ICALL(MONOIO_3, "CreateDirectory(char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_CreateDirectory)) -NOHANDLES(ICALL(MONOIO_4, "CreatePipe", ves_icall_System_IO_MonoIO_CreatePipe)) -NOHANDLES(ICALL(MONOIO_5, "DeleteFile(char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_DeleteFile)) -#endif /* !PLATFORM_RO_FS */ -NOHANDLES(ICALL(MONOIO_38, "DumpHandles", ves_icall_System_IO_MonoIO_DumpHandles)) -NOHANDLES(ICALL(MONOIO_34, "DuplicateHandle", ves_icall_System_IO_MonoIO_DuplicateHandle)) -NOHANDLES(ICALL(MONOIO_37a, "FindCloseFile", ves_icall_System_IO_MonoIO_FindCloseFile)) -HANDLES(MONOIO_35a, "FindFirstFile", ves_icall_System_IO_MonoIO_FindFirstFile, gpointer, 4, (const_gunichar2_ptr, MonoStringOut, gint32_ref, gint32_ref)) -HANDLES(MONOIO_36a, "FindNextFile", ves_icall_System_IO_MonoIO_FindNextFile, MonoBoolean, 4, (gpointer, MonoStringOut, gint32_ref, gint32_ref)) -NOHANDLES(ICALL(MONOIO_6, "Flush(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Flush)) -HANDLES(MONOIO_7, "GetCurrentDirectory(System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetCurrentDirectory, MonoString, 1, (gint32_ref)) -NOHANDLES(ICALL(MONOIO_8, "GetFileAttributes(char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetFileAttributes)) -NOHANDLES(ICALL(MONOIO_9, "GetFileStat(char*,System.IO.MonoIOStat&,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetFileStat)) -NOHANDLES(ICALL(MONOIO_11, "GetFileType(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetFileType)) -NOHANDLES(ICALL(MONOIO_12, "GetLength(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_GetLength)) -#ifndef PLATFORM_RO_FS -NOHANDLES(ICALL(MONOIO_14, "Lock(intptr,long,long,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Lock)) -NOHANDLES(ICALL(MONOIO_15, "MoveFile(char*,char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_MoveFile)) -#endif /* !PLATFORM_RO_FS */ -NOHANDLES(ICALL(MONOIO_16, "Open(char*,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.IO.FileOptions,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Open)) -HANDLES(MONOIO_17, "Read(intptr,byte[],int,int,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Read, gint32, 5, (gpointer, MonoArray, gint32, gint32, gint32_ref)) -#ifndef PLATFORM_RO_FS -NOHANDLES(ICALL(MONOIO_18, "RemoveDirectory(char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_RemoveDirectory)) -NOHANDLES(ICALL(MONOIO_18M, "ReplaceFile(char*,char*,char*,bool,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_ReplaceFile)) -#endif /* !PLATFORM_RO_FS */ -NOHANDLES(ICALL(MONOIO_19, "Seek(intptr,long,System.IO.SeekOrigin,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Seek)) -NOHANDLES(ICALL(MONOIO_20, "SetCurrentDirectory(char*,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetCurrentDirectory)) -NOHANDLES(ICALL(MONOIO_21, "SetFileAttributes(char*,System.IO.FileAttributes,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetFileAttributes)) -NOHANDLES(ICALL(MONOIO_22, "SetFileTime(intptr,long,long,long,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetFileTime)) -NOHANDLES(ICALL(MONOIO_23, "SetLength(intptr,long,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetLength)) -#ifndef PLATFORM_RO_FS -NOHANDLES(ICALL(MONOIO_24, "Unlock(intptr,long,long,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Unlock)) -#endif -HANDLES(MONOIO_25, "Write(intptr,byte[],int,int,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Write, gint32, 5, (gpointer, MonoArray, gint32, gint32, gint32_ref)) -NOHANDLES(ICALL(MONOIO_26, "get_AltDirectorySeparatorChar", ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar)) -NOHANDLES(ICALL(MONOIO_27, "get_ConsoleError", ves_icall_System_IO_MonoIO_get_ConsoleError)) -NOHANDLES(ICALL(MONOIO_28, "get_ConsoleInput", ves_icall_System_IO_MonoIO_get_ConsoleInput)) -NOHANDLES(ICALL(MONOIO_29, "get_ConsoleOutput", ves_icall_System_IO_MonoIO_get_ConsoleOutput)) -NOHANDLES(ICALL(MONOIO_30, "get_DirectorySeparatorChar", ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar)) -HANDLES(MONOIO_31, "get_InvalidPathChars", ves_icall_System_IO_MonoIO_get_InvalidPathChars, MonoArray, 0, ()) -NOHANDLES(ICALL(MONOIO_32, "get_PathSeparator", ves_icall_System_IO_MonoIO_get_PathSeparator)) -NOHANDLES(ICALL(MONOIO_33, "get_VolumeSeparatorChar", ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar)) - -ICALL_TYPE(IOPATH, "System.IO.Path", IOPATH_1) -HANDLES(IOPATH_1, "get_temp_path", ves_icall_System_IO_get_temp_path, MonoString, 0, ()) - -ICALL_TYPE(IOSELECTOR, "System.IOSelector", IOSELECTOR_1) -HANDLES(IOSELECTOR_1, "Add", ves_icall_System_IOSelector_Add, void, 2, (gpointer, MonoIOSelectorJob)) -NOHANDLES(ICALL(IOSELECTOR_2, "Remove", ves_icall_System_IOSelector_Remove)) - -ICALL_TYPE(MATH, "System.Math", MATH_19) -NOHANDLES(ICALL(MATH_19, "Abs(double)", ves_icall_System_Math_Abs_double)) -NOHANDLES(ICALL(MATH_20, "Abs(single)", ves_icall_System_Math_Abs_single)) -NOHANDLES(ICALL(MATH_1, "Acos", ves_icall_System_Math_Acos)) -NOHANDLES(ICALL(MATH_1a, "Acosh", ves_icall_System_Math_Acosh)) -NOHANDLES(ICALL(MATH_2, "Asin", ves_icall_System_Math_Asin)) -NOHANDLES(ICALL(MATH_2a, "Asinh", ves_icall_System_Math_Asinh)) -NOHANDLES(ICALL(MATH_3, "Atan", ves_icall_System_Math_Atan)) -NOHANDLES(ICALL(MATH_4, "Atan2", ves_icall_System_Math_Atan2)) -NOHANDLES(ICALL(MATH_4a, "Atanh", ves_icall_System_Math_Atanh)) -NOHANDLES(ICALL(MATH_4b, "Cbrt", ves_icall_System_Math_Cbrt)) -NOHANDLES(ICALL(MATH_21, "Ceiling", ves_icall_System_Math_Ceiling)) -NOHANDLES(ICALL(MATH_5, "Cos", ves_icall_System_Math_Cos)) -NOHANDLES(ICALL(MATH_6, "Cosh", ves_icall_System_Math_Cosh)) -NOHANDLES(ICALL(MATH_7, "Exp", ves_icall_System_Math_Exp)) -NOHANDLES(ICALL(MATH_7a, "FMod", ves_icall_System_Math_FMod)) -NOHANDLES(ICALL(MATH_8, "Floor", ves_icall_System_Math_Floor)) -NOHANDLES(ICALL(MATH_9, "Log", ves_icall_System_Math_Log)) -NOHANDLES(ICALL(MATH_10, "Log10", ves_icall_System_Math_Log10)) -NOHANDLES(ICALL(MATH_10a, "ModF", ves_icall_System_Math_ModF)) -NOHANDLES(ICALL(MATH_11, "Pow", ves_icall_System_Math_Pow)) -NOHANDLES(ICALL(MATH_12, "Round", ves_icall_System_Math_Round)) -NOHANDLES(ICALL(MATH_14, "Sin", ves_icall_System_Math_Sin)) -NOHANDLES(ICALL(MATH_15, "Sinh", ves_icall_System_Math_Sinh)) -NOHANDLES(ICALL(MATH_16, "Sqrt", ves_icall_System_Math_Sqrt)) -NOHANDLES(ICALL(MATH_17, "Tan", ves_icall_System_Math_Tan)) -NOHANDLES(ICALL(MATH_18, "Tanh", ves_icall_System_Math_Tanh)) - -ICALL_TYPE(MATHF, "System.MathF", MATHF_1) -NOHANDLES(ICALL(MATHF_1, "Acos", ves_icall_System_MathF_Acos)) -NOHANDLES(ICALL(MATHF_2, "Acosh", ves_icall_System_MathF_Acosh)) -NOHANDLES(ICALL(MATHF_3, "Asin", ves_icall_System_MathF_Asin)) -NOHANDLES(ICALL(MATHF_4, "Asinh", ves_icall_System_MathF_Asinh)) -NOHANDLES(ICALL(MATHF_5, "Atan", ves_icall_System_MathF_Atan)) -NOHANDLES(ICALL(MATHF_6, "Atan2", ves_icall_System_MathF_Atan2)) -NOHANDLES(ICALL(MATHF_7, "Atanh", ves_icall_System_MathF_Atanh)) -NOHANDLES(ICALL(MATHF_8, "Cbrt", ves_icall_System_MathF_Cbrt)) -NOHANDLES(ICALL(MATHF_9, "Ceiling", ves_icall_System_MathF_Ceiling)) -NOHANDLES(ICALL(MATHF_10, "Cos", ves_icall_System_MathF_Cos)) -NOHANDLES(ICALL(MATHF_11, "Cosh", ves_icall_System_MathF_Cosh)) -NOHANDLES(ICALL(MATHF_12, "Exp", ves_icall_System_MathF_Exp)) -NOHANDLES(ICALL(MATHF_22, "FMod", ves_icall_System_MathF_FMod)) -NOHANDLES(ICALL(MATHF_13, "Floor", ves_icall_System_MathF_Floor)) -NOHANDLES(ICALL(MATHF_14, "Log", ves_icall_System_MathF_Log)) -NOHANDLES(ICALL(MATHF_15, "Log10", ves_icall_System_MathF_Log10)) -NOHANDLES(ICALL(MATHF_23, "ModF(single,single*)", ves_icall_System_MathF_ModF)) -NOHANDLES(ICALL(MATHF_16, "Pow", ves_icall_System_MathF_Pow)) -NOHANDLES(ICALL(MATHF_17, "Sin", ves_icall_System_MathF_Sin)) -NOHANDLES(ICALL(MATHF_18, "Sinh", ves_icall_System_MathF_Sinh)) -NOHANDLES(ICALL(MATHF_19, "Sqrt", ves_icall_System_MathF_Sqrt)) -NOHANDLES(ICALL(MATHF_20, "Tan", ves_icall_System_MathF_Tan)) -NOHANDLES(ICALL(MATHF_21, "Tanh", ves_icall_System_MathF_Tanh)) - -ICALL_TYPE(MCATTR, "System.MonoCustomAttrs", MCATTR_1) -HANDLES(MCATTR_1, "GetCustomAttributesDataInternal", ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal, MonoArray, 1, (MonoObject)) -HANDLES(MCATTR_2, "GetCustomAttributesInternal", ves_icall_MonoCustomAttrs_GetCustomAttributesInternal, MonoArray, 3, (MonoObject, MonoReflectionType, MonoBoolean)) -HANDLES(MCATTR_3, "IsDefinedInternal", ves_icall_MonoCustomAttrs_IsDefinedInternal, MonoBoolean, 2, (MonoObject, MonoReflectionType)) - -#ifndef DISABLE_SOCKETS -ICALL_TYPE(NDNS, "System.Net.Dns", NDNS_1) -HANDLES(NDNS_1, "GetHostByAddr_icall", ves_icall_System_Net_Dns_GetHostByAddr, MonoBoolean, 5, (MonoString, MonoStringOut, MonoArrayOut, MonoArrayOut, gint32)) -HANDLES(NDNS_2, "GetHostByName_icall", ves_icall_System_Net_Dns_GetHostByName, MonoBoolean, 5, (MonoString, MonoStringOut, MonoArrayOut, MonoArrayOut, gint32)) -HANDLES(NDNS_3, "GetHostName_icall", ves_icall_System_Net_Dns_GetHostName, MonoBoolean, 1, (MonoStringOut)) -#endif - -#if defined(ENABLE_MONODROID) -ICALL_TYPE(LINUXNETWORKCHANGE, "System.Net.NetworkInformation.LinuxNetworkChange", LINUXNETWORKCHANGE_1) -NOHANDLES(ICALL(LINUXNETWORKCHANGE_1, "CloseNLSocket", ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket)) -NOHANDLES(ICALL(LINUXNETWORKCHANGE_2, "CreateNLSocket", ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CreateNLSocket)) -NOHANDLES(ICALL(LINUXNETWORKCHANGE_3, "ReadEvents", ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_ReadEvents)) -#endif - -#if !defined(DISABLE_SOCKETS) -ICALL_TYPE(MAC_IFACE_PROPS, "System.Net.NetworkInformation.MacOsIPInterfaceProperties", MAC_IFACE_PROPS_1) -HANDLES(MAC_IFACE_PROPS_1, "ParseRouteInfo_icall", ves_icall_System_Net_NetworkInformation_MacOsIPInterfaceProperties_ParseRouteInfo, MonoBoolean, 2, (MonoString, MonoArrayOut)) - -ICALL_TYPE(SOCK, "System.Net.Sockets.Socket", SOCK_1) -NOHANDLES(ICALL(SOCK_1, "Accept_icall", ves_icall_System_Net_Sockets_Socket_Accept_icall)) -NOHANDLES(ICALL(SOCK_2, "Available_icall", ves_icall_System_Net_Sockets_Socket_Available_icall)) -HANDLES(SOCK_3, "Bind_icall", ves_icall_System_Net_Sockets_Socket_Bind_icall, void, 3, (gsize, MonoObject, gint32_ref)) -NOHANDLES(ICALL(SOCK_4, "Blocking_icall", ves_icall_System_Net_Sockets_Socket_Blocking_icall)) -NOHANDLES(ICALL(SOCK_5, "Close_icall", ves_icall_System_Net_Sockets_Socket_Close_icall)) -HANDLES(SOCK_6, "Connect_icall", ves_icall_System_Net_Sockets_Socket_Connect_icall, void, 4, (gsize, MonoObject, gint32_ref, MonoBoolean)) -NOHANDLES(ICALL(SOCK_6a, "Disconnect_icall", ves_icall_System_Net_Sockets_Socket_Disconnect_icall)) -NOHANDLES(ICALL(SOCK_6b, "Duplicate_icall", ves_icall_System_Net_Sockets_Socket_Duplicate_icall)) -//FIXME The array is ref but the icall does not write to it. -HANDLES(SOCK_7, "GetSocketOption_arr_icall", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_icall, void, 5, (gsize, gint32, gint32, MonoArray, gint32_ref)) -HANDLES(SOCK_8, "GetSocketOption_obj_icall", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_icall, void, 5, (gsize, gint32, gint32, MonoObjectOut, gint32_ref)) -HANDLES(SOCK_21, "IOControl_icall", ves_icall_System_Net_Sockets_Socket_IOControl_icall, int, 5, (gsize, gint32, MonoArray, MonoArray, gint32_ref)) -NOHANDLES(ICALL(SOCK_9, "Listen_icall", ves_icall_System_Net_Sockets_Socket_Listen_icall)) -HANDLES(SOCK_10, "LocalEndPoint_icall", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_icall, MonoObject, 3, (gsize, gint32, gint32_ref)) -NOHANDLES(ICALL(SOCK_11, "Poll_icall", ves_icall_System_Net_Sockets_Socket_Poll_icall)) -HANDLES(SOCK_13, "ReceiveFrom_icall", ves_icall_System_Net_Sockets_Socket_ReceiveFrom_icall, gint32, 7, (gsize, char_ptr, gint32, gint32, MonoObjectInOut, gint32_ref, MonoBoolean)) -NOHANDLES(ICALL(SOCK_11a, "Receive_array_icall", ves_icall_System_Net_Sockets_Socket_Receive_array_icall)) -NOHANDLES(ICALL(SOCK_12, "Receive_icall", ves_icall_System_Net_Sockets_Socket_Receive_icall)) -HANDLES(SOCK_14, "RemoteEndPoint_icall", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_icall, MonoObject, 3, (gsize, gint32, gint32_ref)) -HANDLES(SOCK_15, "Select_icall", ves_icall_System_Net_Sockets_Socket_Select_icall, void, 3, (MonoArrayInOut, gint32, gint32_ref)) -HANDLES(SOCK_15a, "SendFile_icall", ves_icall_System_Net_Sockets_Socket_SendFile_icall, MonoBoolean, 7, (gsize, MonoString, MonoArray, MonoArray, int, gint32_ref, MonoBoolean)) -HANDLES(SOCK_16, "SendTo_icall", ves_icall_System_Net_Sockets_Socket_SendTo_icall, gint32, 7, (gsize, char_ptr, gint32, gint32, MonoObject, gint32_ref, MonoBoolean)) -NOHANDLES(ICALL(SOCK_16a, "Send_array_icall", ves_icall_System_Net_Sockets_Socket_Send_array_icall)) -NOHANDLES(ICALL(SOCK_17, "Send_icall", ves_icall_System_Net_Sockets_Socket_Send_icall)) -HANDLES(SOCK_18, "SetSocketOption_icall", ves_icall_System_Net_Sockets_Socket_SetSocketOption_icall, void, 7, (gsize, gint32, gint32, MonoObject, MonoArray, gint32, gint32_ref)) -NOHANDLES(ICALL(SOCK_19, "Shutdown_icall", ves_icall_System_Net_Sockets_Socket_Shutdown_icall)) -HANDLES(SOCK_20, "Socket_icall", ves_icall_System_Net_Sockets_Socket_Socket_icall, gpointer, 4, (gint32, gint32, gint32, gint32_ref)) -NOHANDLES(ICALL(SOCK_20a, "SupportsPortReuse", ves_icall_System_Net_Sockets_Socket_SupportPortReuse_icall)) -HANDLES(SOCK_21a, "cancel_blocking_socket_operation", ves_icall_cancel_blocking_socket_operation, void, 1, (MonoThreadObject)) - -ICALL_TYPE(SOCKEX, "System.Net.Sockets.SocketException", SOCKEX_1) -NOHANDLES(ICALL(SOCKEX_1, "WSAGetLastError_icall", ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_icall)) -#endif /* !DISABLE_SOCKETS */ - -ICALL_TYPE(NUMBER_FORMATTER, "System.NumberFormatter", NUMBER_FORMATTER_1) -NOHANDLES(ICALL(NUMBER_FORMATTER_1, "GetFormatterTables", ves_icall_System_NumberFormatter_GetFormatterTables)) - -ICALL_TYPE(OBJ, "System.Object", OBJ_1) -HANDLES(OBJ_1, "GetType", ves_icall_System_Object_GetType, MonoReflectionType, 1, (MonoObject)) -HANDLES(OBJ_2, "InternalGetHashCode", mono_object_hash_icall, int, 1, (MonoObject)) -HANDLES(OBJ_3, "MemberwiseClone", ves_icall_System_Object_MemberwiseClone, MonoObject, 1, (MonoObject)) - -ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_2) -HANDLES(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCallingAssembly, MonoReflectionAssembly, 0, ()) -HANDLES(ASSEM_3, "GetEntryAssembly", ves_icall_System_Reflection_Assembly_GetEntryAssembly, MonoReflectionAssembly, 0, ()) -HANDLES(ASSEM_4, "GetExecutingAssembly", ves_icall_System_Reflection_Assembly_GetExecutingAssembly, MonoReflectionAssembly, 0, ()) -HANDLES(ASSEM_13, "GetTypes", ves_icall_System_Reflection_Assembly_GetTypes, MonoArray, 2, (MonoReflectionAssembly, MonoBoolean)) -HANDLES(ASSEM_14, "InternalGetAssemblyName", ves_icall_System_Reflection_Assembly_InternalGetAssemblyName, void, 3, (MonoString, MonoAssemblyName_ref, MonoStringOut)) -HANDLES(ASSEM_12, "InternalGetReferencedAssemblies", ves_icall_System_Reflection_Assembly_InternalGetReferencedAssemblies, GPtrArray_ptr, 1, (MonoReflectionAssembly)) -HANDLES(ASSEM_15, "InternalGetType", ves_icall_System_Reflection_Assembly_InternalGetType, MonoReflectionType, 5, (MonoReflectionAssembly, MonoReflectionModule, MonoString, MonoBoolean, MonoBoolean)) -HANDLES(ASSEM_16a, "LoadFile_internal", ves_icall_System_Reflection_Assembly_LoadFile_internal, MonoReflectionAssembly, 2, (MonoString, MonoStackCrawlMark_ptr)) -HANDLES(ASSEM_17, "LoadFrom", ves_icall_System_Reflection_Assembly_LoadFrom, MonoReflectionAssembly, 3, (MonoString, MonoBoolean, MonoStackCrawlMark_ptr)) -HANDLES(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_load_with_partial_name, MonoReflectionAssembly, 2, (MonoString, MonoObject)) - -ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0) -NOHANDLES(ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName)) -NOHANDLES(ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName)) -NOHANDLES(ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token)) - -ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1) -HANDLES(CATTR_DATA_1, "ResolveArgumentsInternal", ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal, void, 6, (MonoReflectionMethod, MonoReflectionAssembly, gpointer, guint32, MonoArrayOut, MonoArrayOut)) - -ICALL_TYPE(ASSEMB, "System.Reflection.Emit.AssemblyBuilder", ASSEMB_1) -HANDLES(ASSEMB_1, "UpdateNativeCustomAttributes", ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes, void, 1, (MonoReflectionAssemblyBuilder)) -HANDLES(ASSEMB_2, "basic_init", ves_icall_AssemblyBuilder_basic_init, void, 1, (MonoReflectionAssemblyBuilder)) - -#ifndef DISABLE_REFLECTION_EMIT -ICALL_TYPE(CATTRB, "System.Reflection.Emit.CustomAttributeBuilder", CATTRB_1) -HANDLES(CATTRB_1, "GetBlob", ves_icall_CustomAttributeBuilder_GetBlob, MonoArray, 7, (MonoReflectionAssembly, MonoObject, MonoArray, MonoArray, MonoArray, MonoArray, MonoArray)) -#endif - -ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1) -HANDLES(DYNM_1, "create_dynamic_method", ves_icall_DynamicMethod_create_dynamic_method, void, 1, (MonoReflectionDynamicMethod)) - -ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1) -HANDLES(ENUMB_1, "setup_enum_type", ves_icall_EnumBuilder_setup_enum_type, void, 2, (MonoReflectionType, MonoReflectionType)) - -ICALL_TYPE(MODULEB, "System.Reflection.Emit.ModuleBuilder", MODULEB_10) -HANDLES(MODULEB_10, "GetRegisteredToken", ves_icall_ModuleBuilder_GetRegisteredToken, MonoObject, 2, (MonoReflectionModuleBuilder, guint32)) -HANDLES(MODULEB_8, "RegisterToken", ves_icall_ModuleBuilder_RegisterToken, void, 3, (MonoReflectionModuleBuilder, MonoObject, guint32)) -HANDLES(MODULEB_1, "WriteToFile", ves_icall_ModuleBuilder_WriteToFile, void, 2, (MonoReflectionModuleBuilder, FILE_HANDLE)) -HANDLES(MODULEB_2, "basic_init", ves_icall_ModuleBuilder_basic_init, void, 1, (MonoReflectionModuleBuilder)) -HANDLES(MODULEB_3, "build_metadata", ves_icall_ModuleBuilder_build_metadata, void, 1, (MonoReflectionModuleBuilder)) -HANDLES(MODULEB_5, "getMethodToken", ves_icall_ModuleBuilder_getMethodToken, gint32, 3, (MonoReflectionModuleBuilder, MonoReflectionMethod, MonoArray)) -HANDLES(MODULEB_6, "getToken", ves_icall_ModuleBuilder_getToken, gint32, 3, (MonoReflectionModuleBuilder, MonoObject, MonoBoolean)) -HANDLES(MODULEB_7, "getUSIndex", ves_icall_ModuleBuilder_getUSIndex, guint32, 2, (MonoReflectionModuleBuilder, MonoString)) -HANDLES(MODULEB_9, "set_wrappers_type", ves_icall_ModuleBuilder_set_wrappers_type, void, 2, (MonoReflectionModuleBuilder, MonoReflectionType)) - -ICALL_TYPE(SIGH, "System.Reflection.Emit.SignatureHelper", SIGH_1) -HANDLES(SIGH_1, "get_signature_field", ves_icall_SignatureHelper_get_signature_field, MonoArray, 1, (MonoReflectionSigHelper)) -HANDLES(SIGH_2, "get_signature_local", ves_icall_SignatureHelper_get_signature_local, MonoArray, 1, (MonoReflectionSigHelper)) - -ICALL_TYPE(TYPEB, "System.Reflection.Emit.TypeBuilder", TYPEB_1) -HANDLES(TYPEB_1, "create_runtime_class", ves_icall_TypeBuilder_create_runtime_class, MonoReflectionType, 1, (MonoReflectionTypeBuilder)) - -ICALL_TYPE(EVENTI, "System.Reflection.EventInfo", EVENTI_1) -HANDLES(EVENTI_1, "internal_from_handle_type", ves_icall_System_Reflection_EventInfo_internal_from_handle_type, MonoReflectionEvent, 2, (MonoEvent_ref, MonoType_ref)) - -ICALL_TYPE(FIELDI, "System.Reflection.FieldInfo", FILEDI_1) -HANDLES(FILEDI_1, "get_marshal_info", ves_icall_System_Reflection_FieldInfo_get_marshal_info, MonoReflectionMarshalAsAttribute, 1, (MonoReflectionField)) - -HANDLES(FILEDI_2, "internal_from_handle_type", ves_icall_System_Reflection_FieldInfo_internal_from_handle_type, MonoReflectionField, 2, (MonoClassField_ref, MonoType_ref)) - -ICALL_TYPE(MBASE, "System.Reflection.MethodBase", MBASE_1) -HANDLES(MBASE_1, "GetCurrentMethod", ves_icall_GetCurrentMethod, MonoReflectionMethod, 0, ()) - -ICALL_TYPE(MMETHI, "System.Reflection.MonoMethodInfo", MMETHI_4) -NOHANDLES(ICALL(MMETHI_4, "get_method_attributes", ves_icall_get_method_attributes)) -HANDLES(MMETHI_1, "get_method_info", ves_icall_get_method_info, void, 2, (MonoMethod_ptr, MonoMethodInfo_ref)) -HANDLES(MMETHI_2, "get_parameter_info", ves_icall_System_Reflection_MonoMethodInfo_get_parameter_info, MonoArray, 2, (MonoMethod_ptr, MonoReflectionMethod)) -HANDLES(MMETHI_3, "get_retval_marshal", ves_icall_System_MonoMethodInfo_get_retval_marshal, MonoReflectionMarshalAsAttribute, 1, (MonoMethod_ptr)) - -ICALL_TYPE(RASSEM, "System.Reflection.RuntimeAssembly", RASSEM_1) -HANDLES(RASSEM_1, "GetAotIdInternal", ves_icall_System_Reflection_RuntimeAssembly_GetAotIdInternal, MonoBoolean, 1, (MonoArray)) -HANDLES(RASSEM_2, "GetFilesInternal", ves_icall_System_Reflection_RuntimeAssembly_GetFilesInternal, MonoObject, 3, (MonoReflectionAssembly, MonoString, MonoBoolean)) -HANDLES(RASSEM_3, "GetManifestModuleInternal", ves_icall_System_Reflection_Assembly_GetManifestModuleInternal, MonoReflectionModule, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_4, "GetManifestResourceInfoInternal", ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceInfoInternal, MonoBoolean, 3, (MonoReflectionAssembly, MonoString, MonoManifestResourceInfo)) -HANDLES(RASSEM_5, "GetManifestResourceInternal", ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceInternal, gpointer, 4, (MonoReflectionAssembly, MonoString, gint32_ref, MonoReflectionModuleOut)) -HANDLES(RASSEM_6, "GetManifestResourceNames", ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceNames, MonoArray, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_7, "GetModulesInternal", ves_icall_System_Reflection_RuntimeAssembly_GetModulesInternal, MonoArray, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_8, "InternalImageRuntimeVersion", ves_icall_System_Reflection_RuntimeAssembly_InternalImageRuntimeVersion, MonoString, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_9, "LoadPermissions", ves_icall_System_Reflection_RuntimeAssembly_LoadPermissions, MonoBoolean, 7, (MonoReflectionAssembly, char_ptr_ref, guint32_ref, char_ptr_ref, guint32_ref, char_ptr_ref, guint32_ref)) -HANDLES(RASSEM_10, "get_EntryPoint", ves_icall_System_Reflection_RuntimeAssembly_get_EntryPoint, MonoReflectionMethod, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_11, "get_ReflectionOnly", ves_icall_System_Reflection_RuntimeAssembly_get_ReflectionOnly, MonoBoolean, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_12, "get_code_base", ves_icall_System_Reflection_RuntimeAssembly_get_code_base, MonoString, 2, (MonoReflectionAssembly, MonoBoolean)) -HANDLES(RASSEM_13, "get_fullname", ves_icall_System_Reflection_RuntimeAssembly_get_fullname, MonoString, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_14, "get_global_assembly_cache", ves_icall_System_Reflection_RuntimeAssembly_get_global_assembly_cache, MonoBoolean, 1, (MonoReflectionAssembly)) -HANDLES(RASSEM_15, "get_location", ves_icall_System_Reflection_RuntimeAssembly_get_location, MonoString, 1, (MonoReflectionAssembly)) - -ICALL_TYPE(MCMETH, "System.Reflection.RuntimeConstructorInfo", MCMETH_1) -HANDLES(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition, MonoReflectionMethod, 1, (MonoReflectionMethod)) -HANDLES(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoArray, MonoExceptionOut)) -HANDLES(MCMETH_3, "get_core_clr_security_level", ves_icall_RuntimeMethodInfo_get_core_clr_security_level, int, 1, (MonoReflectionMethod)) -HANDLES_REUSE_WRAPPER(MCMETH_4, "get_metadata_token", ves_icall_reflection_get_token) - -ICALL_TYPE(MEV, "System.Reflection.RuntimeEventInfo", MEV_1) -HANDLES(MEV_1, "get_event_info", ves_icall_RuntimeEventInfo_get_event_info, void, 2, (MonoReflectionMonoEvent, MonoEventInfo_ref)) -HANDLES_REUSE_WRAPPER(MEV_2, "get_metadata_token", ves_icall_reflection_get_token) - -ICALL_TYPE(MFIELD, "System.Reflection.RuntimeFieldInfo", MFIELD_1) -HANDLES(MFIELD_1, "GetFieldOffset", ves_icall_RuntimeFieldInfo_GetFieldOffset, gint32, 1, (MonoReflectionField)) -HANDLES(MFIELD_2, "GetParentType", ves_icall_RuntimeFieldInfo_GetParentType, MonoReflectionType, 2, (MonoReflectionField, MonoBoolean)) -HANDLES(MFIELD_3, "GetRawConstantValue", ves_icall_RuntimeFieldInfo_GetRawConstantValue, MonoObject, 1, (MonoReflectionField)) -HANDLES(MFIELD_4, "GetTypeModifiers", ves_icall_System_Reflection_FieldInfo_GetTypeModifiers, MonoArray, 2, (MonoReflectionField, MonoBoolean)) -HANDLES(MFIELD_5, "GetValueInternal", ves_icall_RuntimeFieldInfo_GetValueInternal, MonoObject, 2, (MonoReflectionField, MonoObject)) -HANDLES(MFIELD_6, "ResolveType", ves_icall_RuntimeFieldInfo_ResolveType, MonoReflectionType, 1, (MonoReflectionField)) -HANDLES(MFIELD_7, "SetValueInternal", ves_icall_RuntimeFieldInfo_SetValueInternal, void, 3, (MonoReflectionField, MonoObject, MonoObject)) -HANDLES_REUSE_WRAPPER(MFIELD_8, "UnsafeGetValue", ves_icall_RuntimeFieldInfo_GetValueInternal) -HANDLES(MFIELD_9, "get_core_clr_security_level", ves_icall_RuntimeFieldInfo_get_core_clr_security_level, int, 1, (MonoReflectionField)) -HANDLES_REUSE_WRAPPER(MFIELD_10, "get_metadata_token", ves_icall_reflection_get_token) - -ICALL_TYPE(RMETHODINFO, "System.Reflection.RuntimeMethodInfo", RMETHODINFO_1) -HANDLES(RMETHODINFO_1, "GetGenericArguments", ves_icall_RuntimeMethodInfo_GetGenericArguments, MonoArray, 1, (MonoReflectionMethod)) -HANDLES_REUSE_WRAPPER(RMETHODINFO_2, "GetGenericMethodDefinition_impl", ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition) -HANDLES(RMETHODINFO_3, "GetMethodBodyInternal", ves_icall_System_Reflection_RuntimeMethodInfo_GetMethodBodyInternal, MonoReflectionMethodBody, 1, (MonoMethod_ptr)) -HANDLES(RMETHODINFO_4, "GetMethodFromHandleInternalType_native", ves_icall_System_Reflection_RuntimeMethodInfo_GetMethodFromHandleInternalType_native, MonoReflectionMethod, 3, (MonoMethod_ptr, MonoType_ptr, MonoBoolean)) -HANDLES(RMETHODINFO_5, "GetPInvoke", ves_icall_RuntimeMethodInfo_GetPInvoke, void, 4, (MonoReflectionMethod, int_ref, MonoStringOut, MonoStringOut)) -HANDLES_REUSE_WRAPPER(RMETHODINFO_6, "InternalInvoke", ves_icall_InternalInvoke) -HANDLES(RMETHODINFO_7, "MakeGenericMethod_impl", ves_icall_RuntimeMethodInfo_MakeGenericMethod_impl, MonoReflectionMethod, 2, (MonoReflectionMethod, MonoArray)) -HANDLES(RMETHODINFO_8, "get_IsGenericMethod", ves_icall_RuntimeMethodInfo_get_IsGenericMethod, MonoBoolean, 1, (MonoReflectionMethod)) -HANDLES(RMETHODINFO_9, "get_IsGenericMethodDefinition", ves_icall_RuntimeMethodInfo_get_IsGenericMethodDefinition, MonoBoolean, 1, (MonoReflectionMethod)) -HANDLES(RMETHODINFO_10, "get_base_method", ves_icall_RuntimeMethodInfo_get_base_method, MonoReflectionMethod, 2, (MonoReflectionMethod, MonoBoolean)) -HANDLES_REUSE_WRAPPER(RMETHODINFO_11, "get_core_clr_security_level", ves_icall_RuntimeMethodInfo_get_core_clr_security_level) -HANDLES_REUSE_WRAPPER(RMETHODINFO_12, "get_metadata_token", ves_icall_reflection_get_token) -HANDLES(RMETHODINFO_13, "get_name", ves_icall_RuntimeMethodInfo_get_name, MonoString, 1, (MonoReflectionMethod)) - -ICALL_TYPE(MODULE, "System.Reflection.RuntimeModule", MODULE_2) -HANDLES(MODULE_2, "GetGlobalType", ves_icall_System_Reflection_RuntimeModule_GetGlobalType, MonoReflectionType, 1, (MonoImage_ptr)) -HANDLES(MODULE_3, "GetGuidInternal", ves_icall_System_Reflection_RuntimeModule_GetGuidInternal, void, 2, (MonoImage_ptr, MonoArray)) -HANDLES(MODULE_14, "GetHINSTANCE", ves_icall_System_Reflection_RuntimeModule_GetHINSTANCE, gpointer, 1, (MonoImage_ptr)) -HANDLES(MODULE_4, "GetMDStreamVersion", ves_icall_System_Reflection_RuntimeModule_GetMDStreamVersion, gint32, 1, (MonoImage_ptr)) -HANDLES(MODULE_5, "GetPEKind", ves_icall_System_Reflection_RuntimeModule_GetPEKind, void, 3, (MonoImage_ptr, gint32_ptr, gint32_ptr)) -HANDLES(MODULE_6, "InternalGetTypes", ves_icall_System_Reflection_RuntimeModule_InternalGetTypes, MonoArray, 1, (MonoImage_ptr)) -HANDLES(MODULE_7, "ResolveFieldToken", ves_icall_System_Reflection_RuntimeModule_ResolveFieldToken, MonoClassField_ptr, 5, (MonoImage_ptr, guint32, MonoArray, MonoArray, MonoResolveTokenError_ref)) -HANDLES(MODULE_8, "ResolveMemberToken", ves_icall_System_Reflection_RuntimeModule_ResolveMemberToken, MonoObject, 5, (MonoImage_ptr, guint32, MonoArray, MonoArray, MonoResolveTokenError_ref)) -HANDLES(MODULE_9, "ResolveMethodToken", ves_icall_System_Reflection_RuntimeModule_ResolveMethodToken, MonoMethod_ptr, 5, (MonoImage_ptr, guint32, MonoArray, MonoArray, MonoResolveTokenError_ref)) -HANDLES(MODULE_10, "ResolveSignature", ves_icall_System_Reflection_RuntimeModule_ResolveSignature, MonoArray, 3, (MonoImage_ptr, guint32, MonoResolveTokenError_ref)) -HANDLES(MODULE_11, "ResolveStringToken", ves_icall_System_Reflection_RuntimeModule_ResolveStringToken, MonoString, 3, (MonoImage_ptr, guint32, MonoResolveTokenError_ref)) -HANDLES(MODULE_12, "ResolveTypeToken", ves_icall_System_Reflection_RuntimeModule_ResolveTypeToken, MonoType_ptr, 5, (MonoImage_ptr, guint32, MonoArray, MonoArray, MonoResolveTokenError_ref)) -HANDLES(MODULE_13, "get_MetadataToken", ves_icall_reflection_get_token, guint32, 1, (MonoObject)) - -ICALL_TYPE(PARAMI, "System.Reflection.RuntimeParameterInfo", MPARAMI_1) -HANDLES_REUSE_WRAPPER(MPARAMI_1, "GetMetadataToken", ves_icall_reflection_get_token) -HANDLES(MPARAMI_2, "GetTypeModifiers", ves_icall_RuntimeParameterInfo_GetTypeModifiers, MonoArray, 4, (MonoReflectionType, MonoObject, int, MonoBoolean)) - -ICALL_TYPE(MPROP, "System.Reflection.RuntimePropertyInfo", MPROP_1) -HANDLES(MPROP_1, "GetTypeModifiers", ves_icall_RuntimePropertyInfo_GetTypeModifiers, MonoArray, 2, (MonoReflectionProperty, MonoBoolean)) -HANDLES(MPROP_2, "get_default_value", ves_icall_property_info_get_default_value, MonoObject, 1, (MonoReflectionProperty)) -HANDLES_REUSE_WRAPPER(MPROP_3, "get_metadata_token", ves_icall_reflection_get_token) -HANDLES(MPROP_4, "get_property_info", ves_icall_RuntimePropertyInfo_get_property_info, void, 3, (MonoReflectionProperty, MonoPropertyInfo_ref, PInfo)) -HANDLES(MPROP_5, "internal_from_handle_type", ves_icall_System_Reflection_RuntimePropertyInfo_internal_from_handle_type, MonoReflectionProperty, 2, (MonoProperty_ptr, MonoType_ptr)) - -ICALL_TYPE(RUNH, "System.Runtime.CompilerServices.RuntimeHelpers", RUNH_1) -HANDLES(RUNH_1, "GetObjectValue", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue, MonoObject, 1, (MonoObject)) -HANDLES(RUNH_3, "InitializeArray", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray, void, 2, (MonoArray, MonoClassField_ptr)) -HANDLES(RUNH_4, "RunClassConstructor", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor, void, 1, (MonoType_ptr)) -HANDLES(RUNH_5, "RunModuleConstructor", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor, void, 1, (MonoImage_ptr)) -NOHANDLES(ICALL(RUNH_5h, "SufficientExecutionStack", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack)) -NOHANDLES(ICALL(RUNH_6, "get_OffsetToStringData", ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData)) - -ICALL_TYPE(GCH, "System.Runtime.InteropServices.GCHandle", GCH_1) -NOHANDLES(ICALL(GCH_1, "CheckCurrentDomain", ves_icall_System_GCHandle_CheckCurrentDomain)) -NOHANDLES(ICALL(GCH_2, "FreeHandle", ves_icall_System_GCHandle_FreeHandle)) -NOHANDLES(ICALL(GCH_3, "GetAddrOfPinnedObject", ves_icall_System_GCHandle_GetAddrOfPinnedObject)) -HANDLES(GCH_4, "GetTarget", ves_icall_System_GCHandle_GetTarget, MonoObject, 1, (gpointer)) -HANDLES(GCH_5, "GetTargetHandle", ves_icall_System_GCHandle_GetTargetHandle, gpointer, 3, (MonoObject, gpointer, gint32)) - -#if !defined(DISABLE_COM) || defined (HOST_WIN32) -ICALL_TYPE(MARSHAL, "System.Runtime.InteropServices.Marshal", MARSHAL_1) -NOHANDLES(ICALL(MARSHAL_1, "AddRefInternal", ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal)) -#else -ICALL_TYPE(MARSHAL, "System.Runtime.InteropServices.Marshal", MARSHAL_2) -#endif -NOHANDLES(ICALL(MARSHAL_2, "AllocCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem)) -NOHANDLES(ICALL(MARSHAL_51,"AllocCoTaskMemSize(uintptr)", ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMemSize)) -NOHANDLES(ICALL(MARSHAL_3, "AllocHGlobal", ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal)) -NOHANDLES(ICALL(MARSHAL_50, "BufferToBSTR", ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR)) -HANDLES(MARSHAL_4, "DestroyStructure", ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure, void, 2, (gpointer, MonoReflectionType)) -NOHANDLES(ICALL(MARSHAL_5, "FreeBSTR", ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR)) -NOHANDLES(ICALL(MARSHAL_6, "FreeCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem)) -NOHANDLES(ICALL(MARSHAL_7, "FreeHGlobal", ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal)) -#ifndef DISABLE_COM -HANDLES(MARSHAL_44, "GetCCW", ves_icall_System_Runtime_InteropServices_Marshal_GetCCW, gpointer, 2, (MonoObject, MonoReflectionType)) -HANDLES(MARSHAL_8, "GetComSlotForMethodInfoInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetComSlotForMethodInfoInternal, guint32, 1, (MonoReflectionMethod)) -#endif -HANDLES(MARSHAL_9, "GetDelegateForFunctionPointerInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal, MonoDelegate, 2, (gpointer, MonoReflectionType)) -HANDLES(MARSHAL_10, "GetFunctionPointerForDelegateInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal, gpointer, 1, (MonoDelegate)) -#ifndef DISABLE_COM -HANDLES(MARSHAL_52, "GetHRForException_WinRT", ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT, int, 1, (MonoException)) -HANDLES(MARSHAL_45, "GetIDispatchForObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal, gpointer, 1, (MonoObject)) -HANDLES(MARSHAL_46, "GetIUnknownForObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal, gpointer, 1, (MonoObject)) -#endif -NOHANDLES(ICALL(MARSHAL_11, "GetLastWin32Error", ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error)) -#ifndef DISABLE_COM -HANDLES(MARSHAL_53, "GetNativeActivationFactory", ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory, MonoObject, 1, (MonoObject)) -HANDLES(MARSHAL_47, "GetObjectForCCW", ves_icall_System_Runtime_InteropServices_Marshal_GetObjectForCCW, MonoObject, 1, (gpointer)) -HANDLES(MARSHAL_54, "GetRawIUnknownForComObjectNoAddRef", ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef, gpointer, 1, (MonoObject)) -HANDLES(MARSHAL_48, "IsComObject", ves_icall_System_Runtime_InteropServices_Marshal_IsComObject, MonoBoolean, 1, (MonoObject)) -#endif -HANDLES(MARSHAL_48a, "IsPinnableType", ves_icall_System_Runtime_InteropServices_Marshal_IsPinnableType, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf, int, 2, (MonoReflectionType, MonoString)) -HANDLES(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Prelink, void, 1, (MonoReflectionMethod)) -HANDLES(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll, void, 1, (MonoReflectionType)) -HANDLES(MARSHAL_15, "PtrToStringAnsi(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi, MonoString, 1, (const_char_ptr)) -HANDLES(MARSHAL_16, "PtrToStringAnsi(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len, MonoString, 2, (const_char_ptr, gint32)) -HANDLES(MARSHAL_17, "PtrToStringBSTR", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR, MonoString, 1, (mono_bstr_const)) -HANDLES(MARSHAL_18, "PtrToStringUni(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni, MonoString, 1, (const_gunichar2_ptr)) -HANDLES(MARSHAL_19, "PtrToStringUni(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len, MonoString, 2, (const_gunichar2_ptr, gint32)) -HANDLES(MARSHAL_20, "PtrToStructure(intptr,System.Type)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type, MonoObject, 2, (gconstpointer, MonoReflectionType)) -HANDLES(MARSHAL_21, "PtrToStructure(intptr,object)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure, void, 2, (gconstpointer, MonoObject)) -#if !defined (DISABLE_COM) || defined (HOST_WIN32) -NOHANDLES(ICALL(MARSHAL_22, "QueryInterfaceInternal", ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal)) -#endif -NOHANDLES(ICALL(MARSHAL_43, "ReAllocCoTaskMem", ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem)) -NOHANDLES(ICALL(MARSHAL_23, "ReAllocHGlobal", ves_icall_System_Runtime_InteropServices_Marshal_ReAllocHGlobal)) -#ifndef DISABLE_COM -HANDLES(MARSHAL_49, "ReleaseComObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal, gint32, 1, (MonoObject)) -#endif -#if !defined (DISABLE_COM) || defined (HOST_WIN32) -NOHANDLES(ICALL(MARSHAL_29, "ReleaseInternal", ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal)) -#endif -NOHANDLES(ICALL(MARSHAL_29a, "SetLastWin32Error", ves_icall_System_Runtime_InteropServices_Marshal_SetLastWin32Error)) -HANDLES(MARSHAL_30, "SizeOf", ves_icall_System_Runtime_InteropServices_Marshal_SizeOf, guint32, 1, (MonoReflectionType)) -HANDLES(MARSHAL_31, "SizeOfHelper", ves_icall_System_Runtime_InteropServices_Marshal_SizeOfHelper, guint32, 2, (MonoReflectionType, MonoBoolean)) -NOHANDLES(ICALL(MARSHAL_32, "StringToHGlobalAnsi", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi)) -NOHANDLES(ICALL(MARSHAL_33, "StringToHGlobalUni", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni)) -HANDLES(MARSHAL_34, "StructureToPtr", ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr, void, 3, (MonoObject, gpointer, MonoBoolean)) -HANDLES(MARSHAL_35, "UnsafeAddrOfPinnedArrayElement", ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement, gpointer, 2, (MonoArray, int)) -HANDLES(MARSHAL_41, "copy_from_unmanaged_fixed", ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged, void, 5, (gconstpointer, gint32, MonoArray, gint32, gpointer)) -HANDLES(MARSHAL_42, "copy_to_unmanaged_fixed", ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged, void, 5, (MonoArray, gint32, gpointer, gint32, gconstpointer)) - -ICALL_TYPE(RUNTIMEINFO, "System.Runtime.InteropServices.RuntimeInformation", RUNTIMEINFO_1) -HANDLES(RUNTIMEINFO_1, "GetOSName", ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetOSName, MonoString, 0, ()) -HANDLES(RUNTIMEINFO_2, "GetRuntimeArchitecture", ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetRuntimeArchitecture, MonoString, 0, ()) - -#ifndef DISABLE_COM -ICALL_TYPE(WINDOWSRUNTIME_UNM, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods", WINDOWSRUNTIME_UNM_0) -HANDLES(WINDOWSRUNTIME_UNM_0, "GetRestrictedErrorInfo", ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo, MonoObject, 0, ()) -HANDLES(WINDOWSRUNTIME_UNM_1, "RoOriginateLanguageException", ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException, MonoBoolean, 3, (int, MonoString, gpointer)) -HANDLES(WINDOWSRUNTIME_UNM_2, "RoReportUnhandledError", ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError, void, 1, (MonoObject)) -HANDLES(WINDOWSRUNTIME_UNM_3, "WindowsCreateString", ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString, int, 3, (MonoString, int, gpointer_ptr)) -HANDLES(WINDOWSRUNTIME_UNM_4, "WindowsDeleteString", ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString, int, 1, (gpointer)) -HANDLES(WINDOWSRUNTIME_UNM_5, "WindowsGetStringRawBuffer", ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer, mono_unichar2_ptr, 2, (gpointer, unsigned_ptr)) -#endif - -ICALL_TYPE(ACTS, "System.Runtime.Remoting.Activation.ActivationServices", ACTS_1) -HANDLES(ACTS_1, "AllocateUninitializedClassInstance", ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance, MonoObject, 1, (MonoReflectionType)) -HANDLES(ACTS_2, "EnableProxyActivation", ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation, void, 2, (MonoReflectionType, MonoBoolean)) - -ICALL_TYPE(CONTEXT, "System.Runtime.Remoting.Contexts.Context", CONTEXT_1) -HANDLES(CONTEXT_1, "RegisterContext", ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext, void, 1, (MonoAppContext)) -HANDLES(CONTEXT_2, "ReleaseContext", ves_icall_System_Runtime_Remoting_Contexts_Context_ReleaseContext, void, 1, (MonoAppContext)) - -ICALL_TYPE(ARES, "System.Runtime.Remoting.Messaging.AsyncResult", ARES_1) -HANDLES(ARES_1, "Invoke", ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke, MonoObject, 1, (MonoAsyncResult)) - -#ifndef DISABLE_REMOTING -ICALL_TYPE(REALP, "System.Runtime.Remoting.Proxies.RealProxy", REALP_1) -HANDLES(REALP_1, "InternalGetProxyType", ves_icall_Remoting_RealProxy_InternalGetProxyType, MonoReflectionType, 1, (MonoTransparentProxy)) -HANDLES(REALP_2, "InternalGetTransparentProxy", ves_icall_Remoting_RealProxy_GetTransparentProxy, MonoObject, 2, (MonoObject, MonoString)) - -ICALL_TYPE(REMSER, "System.Runtime.Remoting.RemotingServices", REMSER_0) -HANDLES(REMSER_0, "GetVirtualMethod", ves_icall_Remoting_RemotingServices_GetVirtualMethod, MonoReflectionMethod, 2, (MonoReflectionType, MonoReflectionMethod)) -HANDLES(REMSER_1, "InternalExecute", ves_icall_InternalExecute, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoArray, MonoArrayOut)) -HANDLES(REMSER_2, "IsTransparentProxy", ves_icall_IsTransparentProxy, MonoBoolean, 1, (MonoObject)) -#endif - -ICALL_TYPE(RUNIMPORT, "System.Runtime.RuntimeImports", RUNIMPORT_1) -NOHANDLES(ICALL(RUNIMPORT_1, "Memmove", ves_icall_System_Runtime_RuntimeImports_Memmove)) -NOHANDLES(ICALL(RUNIMPORT_2, "Memmove_wbarrier", ves_icall_System_Runtime_RuntimeImports_Memmove_wbarrier)) -NOHANDLES(ICALL(RUNIMPORT_3, "ZeroMemory", ves_icall_System_Runtime_RuntimeImports_ZeroMemory)) -NOHANDLES(ICALL(RUNIMPORT_4, "_ecvt_s", ves_icall_System_Runtime_RuntimeImports_ecvt_s)) - -ICALL_TYPE(RVH, "System.Runtime.Versioning.VersioningHelper", RVH_1) -HANDLES(RVH_1, "GetRuntimeId", ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId, gint32, 0, ()) - -ICALL_TYPE(RFH, "System.RuntimeFieldHandle", RFH_1) -HANDLES(RFH_1, "GetValueDirect", ves_icall_System_RuntimeFieldHandle_GetValueDirect, MonoObject, 4, (MonoReflectionField, MonoReflectionType, MonoTypedRef_ptr, MonoReflectionType)) -HANDLES(RFH_1a, "SetValueDirect", ves_icall_System_RuntimeFieldHandle_SetValueDirect, void, 5, (MonoReflectionField, MonoReflectionType, MonoTypedRef_ptr, MonoObject, MonoReflectionType)) -HANDLES_REUSE_WRAPPER(RFH_2, "SetValueInternal", ves_icall_RuntimeFieldInfo_SetValueInternal) - -ICALL_TYPE(MHAN, "System.RuntimeMethodHandle", MHAN_1) -HANDLES(MHAN_1, "GetFunctionPointer", ves_icall_RuntimeMethodHandle_GetFunctionPointer, gpointer, 1, (MonoMethod_ptr)) - -ICALL_TYPE(RT, "System.RuntimeType", RT_1) -HANDLES(RT_1, "CreateInstanceInternal", ves_icall_System_Activator_CreateInstanceInternal, MonoObject, 1, (MonoReflectionType)) -HANDLES(RT_2, "GetConstructors_native", ves_icall_RuntimeType_GetConstructors_native, GPtrArray_ptr, 2, (MonoReflectionType, guint32)) -HANDLES(RT_30, "GetCorrespondingInflatedConstructor", ves_icall_RuntimeType_GetCorrespondingInflatedMethod, MonoReflectionMethod, 2, (MonoReflectionType, MonoReflectionMethod)) -HANDLES_REUSE_WRAPPER(RT_31, "GetCorrespondingInflatedMethod", ves_icall_RuntimeType_GetCorrespondingInflatedMethod) -HANDLES(RT_3, "GetEvents_native", ves_icall_RuntimeType_GetEvents_native, GPtrArray_ptr, 3, (MonoReflectionType, char_ptr, guint32)) -HANDLES(RT_5, "GetFields_native", ves_icall_RuntimeType_GetFields_native, GPtrArray_ptr, 4, (MonoReflectionType, char_ptr, guint32, guint32)) -HANDLES(RT_32, "GetGUID", ves_icall_RuntimeType_GetGUID, void, 2, (MonoReflectionType, MonoArray)) -HANDLES(RT_6, "GetGenericArgumentsInternal", ves_icall_RuntimeType_GetGenericArguments, MonoArray, 2, (MonoReflectionType, MonoBoolean)) -HANDLES(RT_9, "GetGenericParameterPosition", ves_icall_RuntimeType_GetGenericParameterPosition, gint32, 1, (MonoReflectionType)) -HANDLES(RT_10, "GetInterfaceMapData", ves_icall_RuntimeType_GetInterfaceMapData, void, 4, (MonoReflectionType, MonoReflectionType, MonoArrayOut, MonoArrayOut)) -HANDLES(RT_11, "GetInterfaces", ves_icall_RuntimeType_GetInterfaces, MonoArray, 1, (MonoReflectionType)) -HANDLES(RT_12, "GetMethodsByName_native", ves_icall_RuntimeType_GetMethodsByName_native, GPtrArray_ptr, 4, (MonoReflectionType, const_char_ptr, guint32, guint32)) -HANDLES(RT_13, "GetNestedTypes_native", ves_icall_RuntimeType_GetNestedTypes_native, GPtrArray_ptr, 4, (MonoReflectionType, char_ptr, guint32, guint32)) -HANDLES(RT_14, "GetPacking", ves_icall_RuntimeType_GetPacking, void, 3, (MonoReflectionType, guint32_ref, guint32_ref)) -HANDLES(RT_15, "GetPropertiesByName_native", ves_icall_RuntimeType_GetPropertiesByName_native, GPtrArray_ptr, 4, (MonoReflectionType, char_ptr, guint32, guint32)) -HANDLES(RT_16, "GetTypeCodeImplInternal", ves_icall_type_GetTypeCodeInternal, guint32, 1, (MonoReflectionType)) -HANDLES(RT_28, "IsTypeExportedToWindowsRuntime", ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime, MonoBoolean, 0, ()) -HANDLES(RT_29, "IsWindowsRuntimeObjectType", ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType, MonoBoolean, 0, ()) -HANDLES(RT_17, "MakeGenericType", ves_icall_RuntimeType_MakeGenericType, MonoReflectionType, 2, (MonoReflectionType, MonoArray)) -HANDLES(RT_18, "MakePointerType", ves_icall_RuntimeType_MakePointerType, MonoReflectionType, 1, (MonoReflectionType)) -HANDLES(RT_19, "getFullName", ves_icall_System_RuntimeType_getFullName, MonoString, 3, (MonoReflectionType, MonoBoolean, MonoBoolean)) -HANDLES(RT_21, "get_DeclaringMethod", ves_icall_RuntimeType_get_DeclaringMethod, MonoReflectionMethod, 1, (MonoReflectionType)) -HANDLES(RT_22, "get_DeclaringType", ves_icall_RuntimeType_get_DeclaringType, MonoReflectionType, 1, (MonoReflectionType)) -HANDLES(RT_23, "get_Name", ves_icall_RuntimeType_get_Name, MonoString, 1, (MonoReflectionType)) -HANDLES(RT_24, "get_Namespace", ves_icall_RuntimeType_get_Namespace, MonoString, 1, (MonoReflectionType)) -HANDLES(RT_25, "get_core_clr_security_level", ves_icall_RuntimeType_get_core_clr_security_level, int, 1, (MonoReflectionType)) -HANDLES(RT_26, "make_array_type", ves_icall_RuntimeType_make_array_type, MonoReflectionType, 2, (MonoReflectionType, int)) -HANDLES(RT_27, "make_byref_type", ves_icall_RuntimeType_make_byref_type, MonoReflectionType, 1, (MonoReflectionType)) - -ICALL_TYPE(RTH, "System.RuntimeTypeHandle", RTH_1) -HANDLES(RTH_1, "GetArrayRank", ves_icall_RuntimeTypeHandle_GetArrayRank, gint32, 1, (MonoReflectionType)) -HANDLES(RTH_2, "GetAssembly", ves_icall_RuntimeTypeHandle_GetAssembly, MonoReflectionAssembly, 1, (MonoReflectionType)) -HANDLES(RTH_3, "GetAttributes", ves_icall_RuntimeTypeHandle_GetAttributes, guint32, 1, (MonoReflectionType)) -HANDLES(RTH_4, "GetBaseType", ves_icall_RuntimeTypeHandle_GetBaseType, MonoReflectionType, 1, (MonoReflectionType)) -HANDLES(RTH_4a, "GetCorElementType", ves_icall_RuntimeTypeHandle_GetCorElementType, guint32, 1, (MonoReflectionType)) -HANDLES(RTH_5, "GetElementType", ves_icall_RuntimeTypeHandle_GetElementType, MonoReflectionType, 1, (MonoReflectionType)) -HANDLES(RTH_19, "GetGenericParameterInfo", ves_icall_RuntimeTypeHandle_GetGenericParameterInfo, MonoGenericParamInfo_ptr, 1, (MonoReflectionType)) -HANDLES(RTH_6, "GetGenericTypeDefinition_impl", ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl, MonoReflectionType, 1, (MonoReflectionType)) -HANDLES_REUSE_WRAPPER(RTH_7, "GetMetadataToken", ves_icall_reflection_get_token) -HANDLES(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule, MonoReflectionModule, 1, (MonoReflectionType)) -HANDLES(RTH_9, "HasInstantiation", ves_icall_RuntimeTypeHandle_HasInstantiation, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(RTH_20, "HasReferences", ves_icall_RuntimeTypeHandle_HasReferences, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(RTH_21, "IsByRefLike", ves_icall_RuntimeTypeHandle_IsByRefLike, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(RTH_12, "IsComObject", ves_icall_RuntimeTypeHandle_IsComObject, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(RTH_13, "IsGenericTypeDefinition", ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(RTH_14, "IsGenericVariable", ves_icall_RuntimeTypeHandle_IsGenericVariable, MonoBoolean, 1, (MonoReflectionType)) -HANDLES(RTH_15, "IsInstanceOfType", ves_icall_RuntimeTypeHandle_IsInstanceOfType, guint32, 2, (MonoReflectionType, MonoObject)) -//HANDLES(RTH_17a, "is_subclass_of", ves_icall_RuntimeTypeHandle_is_subclass_of, MonoBoolean, 2, (MonoType_ptr, MonoType_ptr)) -HANDLES(RTH_17a, "internal_from_name", ves_icall_System_RuntimeTypeHandle_internal_from_name, MonoReflectionType, 6, (MonoString, MonoStackCrawlMark_ptr, MonoReflectionAssembly, MonoBoolean, MonoBoolean, MonoBoolean)) -NOHANDLES(ICALL(RTH_17b, "is_subclass_of", ves_icall_RuntimeTypeHandle_is_subclass_of)) -HANDLES(RTH_18, "type_is_assignable_from", ves_icall_RuntimeTypeHandle_type_is_assignable_from, guint32, 2, (MonoReflectionType, MonoReflectionType)) - -ICALL_TYPE(RNG, "System.Security.Cryptography.RNGCryptoServiceProvider", RNG_1) -HANDLES(RNG_1, "RngClose", ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngClose, void, 1, (gpointer)) -HANDLES(RNG_2, "RngGetBytes", ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngGetBytes, gpointer, 3, (gpointer, guchar_ptr, gssize)) -HANDLES(RNG_3, "RngInitialize", ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize, gpointer, 2, (const_guchar_ptr, gssize)) -HANDLES(RNG_4, "RngOpen", ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngOpen, MonoBoolean, 0, ()) - -ICALL_TYPE(EVID, "System.Security.Policy.Evidence", EVID_1) -HANDLES(EVID_1, "IsAuthenticodePresent", ves_icall_System_Security_Policy_Evidence_IsAuthenticodePresent, MonoBoolean, 1, (MonoReflectionAssembly)) - -ICALL_TYPE(WINID, "System.Security.Principal.WindowsIdentity", WINID_1) -HANDLES(WINID_1, "GetCurrentToken", ves_icall_System_Security_Principal_WindowsIdentity_GetCurrentToken, gpointer, 0, ()) -HANDLES(WINID_2, "GetTokenName", ves_icall_System_Security_Principal_WindowsIdentity_GetTokenName, MonoString, 1, (gpointer)) -HANDLES(WINID_3, "GetUserToken", ves_icall_System_Security_Principal_WindowsIdentity_GetUserToken, gpointer, 1, (MonoString)) -HANDLES(WINID_4, "_GetRoles", ves_icall_System_Security_Principal_WindowsIdentity_GetRoles, MonoArray, 1, (gpointer)) - -ICALL_TYPE(WINIMP, "System.Security.Principal.WindowsImpersonationContext", WINIMP_1) -HANDLES(WINIMP_1, "CloseToken", ves_icall_System_Security_Principal_WindowsImpersonationContext_CloseToken, MonoBoolean, 1, (gpointer)) -HANDLES(WINIMP_2, "DuplicateToken", ves_icall_System_Security_Principal_WindowsImpersonationContext_DuplicateToken, gpointer, 1, (gpointer)) -HANDLES(WINIMP_3, "RevertToSelf", ves_icall_System_Security_Principal_WindowsImpersonationContext_RevertToSelf, MonoBoolean, 0, ()) -HANDLES(WINIMP_4, "SetCurrentToken", ves_icall_System_Security_Principal_WindowsImpersonationContext_SetCurrentToken, MonoBoolean, 1, (gpointer)) - -ICALL_TYPE(WINPRIN, "System.Security.Principal.WindowsPrincipal", WINPRIN_1) -HANDLES(WINPRIN_1, "IsMemberOfGroupId", ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupId, MonoBoolean, 2, (gpointer, gpointer)) -HANDLES(WINPRIN_2, "IsMemberOfGroupName", ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupName, MonoBoolean, 2, (gpointer, const_char_ptr)) - -ICALL_TYPE(SECSTRING, "System.Security.SecureString", SECSTRING_1) -HANDLES(SECSTRING_1, "DecryptInternal", ves_icall_System_Security_SecureString_DecryptInternal, void, 2, (MonoArray, MonoObject)) -HANDLES(SECSTRING_2, "EncryptInternal", ves_icall_System_Security_SecureString_EncryptInternal, void, 2, (MonoArray, MonoObject)) - -ICALL_TYPE(SECMAN, "System.Security.SecurityManager", SECMAN_1) -NOHANDLES(ICALL(SECMAN_1, "get_RequiresElevatedPermissions", mono_security_core_clr_require_elevated_permissions)) -NOHANDLES(ICALL(SECMAN_2, "get_SecurityEnabled", ves_icall_System_Security_SecurityManager_get_SecurityEnabled)) -NOHANDLES(ICALL(SECMAN_3, "set_SecurityEnabled", ves_icall_System_Security_SecurityManager_set_SecurityEnabled)) - -ICALL_TYPE(STRING, "System.String", STRING_1) -NOHANDLES(ICALL(STRING_1, ".ctor(System.ReadOnlySpan`1)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_1a, ".ctor(char*)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_2, ".ctor(char*,int,int)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_3, ".ctor(char,int)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_4, ".ctor(char[])", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_5, ".ctor(char[],int,int)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_6, ".ctor(sbyte*)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_7, ".ctor(sbyte*,int,int)", ves_icall_System_String_ctor_RedirectToCreateString)) -NOHANDLES(ICALL(STRING_8, ".ctor(sbyte*,int,int,System.Text.Encoding)", ves_icall_System_String_ctor_RedirectToCreateString)) -HANDLES(STRING_9, "FastAllocateString", ves_icall_System_String_FastAllocateString, MonoString, 1, (gint32)) -HANDLES(STRING_10, "InternalIntern", ves_icall_System_String_InternalIntern, MonoString, 1, (MonoString)) -HANDLES(STRING_11, "InternalIsInterned", ves_icall_System_String_InternalIsInterned, MonoString, 1, (MonoString)) - -ICALL_TYPE(TENC, "System.Text.EncodingHelper", TENC_1) -HANDLES(TENC_1, "InternalCodePage", ves_icall_System_Text_EncodingHelper_InternalCodePage, MonoString, 1, (gint32_ref)) - -ICALL_TYPE(UNORM, "System.Text.Normalization", UNORM_1) -HANDLES(UNORM_1, "load_normalization_resource", ves_icall_System_Text_Normalization_load_normalization_resource, void, 6, (guint8_ptr_ref, guint8_ptr_ref, guint8_ptr_ref, guint8_ptr_ref, guint8_ptr_ref, guint8_ptr_ref)) - -ICALL_TYPE(ILOCK, "System.Threading.Interlocked", ILOCK_1) -NOHANDLES(ICALL(ILOCK_1, "Add(int&,int)", ves_icall_System_Threading_Interlocked_Add_Int)) -NOHANDLES(ICALL(ILOCK_2, "Add(long&,long)", ves_icall_System_Threading_Interlocked_Add_Long)) -NOHANDLES(ICALL(ILOCK_4, "CompareExchange(double&,double,double)", ves_icall_System_Threading_Interlocked_CompareExchange_Double)) -NOHANDLES(ICALL(ILOCK_5, "CompareExchange(int&,int,int)", ves_icall_System_Threading_Interlocked_CompareExchange_Int)) -NOHANDLES(ICALL(ILOCK_6, "CompareExchange(int&,int,int,bool&)", ves_icall_System_Threading_Interlocked_CompareExchange_Int_Success)) -NOHANDLES(ICALL(ILOCK_7, "CompareExchange(intptr&,intptr,intptr)", ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr)) -NOHANDLES(ICALL(ILOCK_8, "CompareExchange(long&,long,long)", ves_icall_System_Threading_Interlocked_CompareExchange_Long)) -NOHANDLES(ICALL(ILOCK_9, "CompareExchange(object&,object&,object&,object&)", ves_icall_System_Threading_Interlocked_CompareExchange_Object)) -NOHANDLES(ICALL(ILOCK_10, "CompareExchange(single&,single,single)", ves_icall_System_Threading_Interlocked_CompareExchange_Single)) -NOHANDLES(ICALL(ILOCK_11, "Decrement(int&)", ves_icall_System_Threading_Interlocked_Decrement_Int)) -NOHANDLES(ICALL(ILOCK_12, "Decrement(long&)", ves_icall_System_Threading_Interlocked_Decrement_Long)) -NOHANDLES(ICALL(ILOCK_14, "Exchange(double&,double)", ves_icall_System_Threading_Interlocked_Exchange_Double)) -NOHANDLES(ICALL(ILOCK_15, "Exchange(int&,int)", ves_icall_System_Threading_Interlocked_Exchange_Int)) -NOHANDLES(ICALL(ILOCK_16, "Exchange(intptr&,intptr)", ves_icall_System_Threading_Interlocked_Exchange_IntPtr)) -NOHANDLES(ICALL(ILOCK_17, "Exchange(long&,long)", ves_icall_System_Threading_Interlocked_Exchange_Long)) -NOHANDLES(ICALL(ILOCK_18, "Exchange(object&,object&,object&)", ves_icall_System_Threading_Interlocked_Exchange_Object)) -NOHANDLES(ICALL(ILOCK_19, "Exchange(single&,single)", ves_icall_System_Threading_Interlocked_Exchange_Single)) -NOHANDLES(ICALL(ILOCK_20, "Increment(int&)", ves_icall_System_Threading_Interlocked_Increment_Int)) -NOHANDLES(ICALL(ILOCK_21, "Increment(long&)", ves_icall_System_Threading_Interlocked_Increment_Long)) -NOHANDLES(ICALL(ILOCK_22, "MemoryBarrierProcessWide", ves_icall_System_Threading_Interlocked_MemoryBarrierProcessWide)) -NOHANDLES(ICALL(ILOCK_23, "Read(long&)", ves_icall_System_Threading_Interlocked_Read_Long)) - -ICALL_TYPE(ITHREAD, "System.Threading.InternalThread", ITHREAD_1) -HANDLES(ITHREAD_1, "Thread_free_internal", ves_icall_System_Threading_InternalThread_Thread_free_internal, void, 1, (MonoInternalThread)) - -ICALL_TYPE(MONIT, "System.Threading.Monitor", MONIT_8) -HANDLES(MONIT_8, "Enter", ves_icall_System_Threading_Monitor_Monitor_Enter, void, 1, (MonoObject)) -HANDLES(MONIT_1, "Exit", mono_monitor_exit_icall, void, 1, (MonoObject)) -HANDLES(MONIT_2, "Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse, void, 1, (MonoObject)) -HANDLES(MONIT_3, "Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all, void, 1, (MonoObject)) -HANDLES(MONIT_4, "Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner, MonoBoolean, 1, (MonoObject)) -HANDLES(MONIT_5, "Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised, MonoBoolean, 1, (MonoObject)) -HANDLES(MONIT_7, "Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait, MonoBoolean, 2, (MonoObject, guint32)) -HANDLES(MONIT_9, "try_enter_with_atomic_var", ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var, void, 3, (MonoObject, guint32, MonoBoolean_ref)) - -ICALL_TYPE(MUTEX, "System.Threading.Mutex", MUTEX_1) -HANDLES(MUTEX_1, "CreateMutex_icall", ves_icall_System_Threading_Mutex_CreateMutex_icall, gpointer, 4, (MonoBoolean, const_gunichar2_ptr, gint32, MonoBoolean_ref)) -HANDLES(MUTEX_2, "OpenMutex_icall", ves_icall_System_Threading_Mutex_OpenMutex_icall, gpointer, 4, (const_gunichar2_ptr, gint32, gint32, gint32_ref)) -NOHANDLES(ICALL(MUTEX_3, "ReleaseMutex_internal", ves_icall_System_Threading_Mutex_ReleaseMutex_internal)) - -ICALL_TYPE(NATIVEC, "System.Threading.NativeEventCalls", NATIVEC_1) -NOHANDLES(ICALL(NATIVEC_1, "CloseEvent_internal", ves_icall_System_Threading_Events_CloseEvent_internal)) -HANDLES(NATIVEC_2, "CreateEvent_icall", ves_icall_System_Threading_Events_CreateEvent_icall, gpointer, 5, (MonoBoolean, MonoBoolean, const_gunichar2_ptr, gint32, gint32_ref)) -HANDLES(NATIVEC_3, "OpenEvent_icall", ves_icall_System_Threading_Events_OpenEvent_icall, gpointer, 4, (const_gunichar2_ptr, gint32, gint32, gint32_ref)) -NOHANDLES(ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal)) -NOHANDLES(ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal)) - -ICALL_TYPE(SEMA, "System.Threading.Semaphore", SEMA_1) -NOHANDLES(ICALL(SEMA_1, "CreateSemaphore_icall", ves_icall_System_Threading_Semaphore_CreateSemaphore_icall)) -NOHANDLES(ICALL(SEMA_2, "OpenSemaphore_icall", ves_icall_System_Threading_Semaphore_OpenSemaphore_icall)) -NOHANDLES(ICALL(SEMA_3, "ReleaseSemaphore_internal", ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal)) - -ICALL_TYPE(THREAD, "System.Threading.Thread", THREAD_1) -HANDLES(THREAD_1, "Abort_internal(System.Threading.InternalThread,object)", ves_icall_System_Threading_Thread_Abort, void, 2, (MonoInternalThread, MonoObject)) -HANDLES(THREAD_1a, "ByteArrayToCurrentDomain(byte[])", ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain, MonoArray, 1, (MonoArray)) -HANDLES(THREAD_1b, "ByteArrayToRootDomain(byte[])", ves_icall_System_Threading_Thread_ByteArrayToRootDomain, MonoArray, 1, (MonoArray)) -HANDLES(THREAD_2, "ClrState(System.Threading.InternalThread,System.Threading.ThreadState)", ves_icall_System_Threading_Thread_ClrState, void, 2, (MonoInternalThread, guint32)) -HANDLES(THREAD_2a, "ConstructInternalThread", ves_icall_System_Threading_Thread_ConstructInternalThread, void, 1, (MonoThreadObject)) -HANDLES(THREAD_55, "GetAbortExceptionState", ves_icall_System_Threading_Thread_GetAbortExceptionState, MonoObject, 1, (MonoThreadObject)) -NOHANDLES(ICALL(THREAD_60, "GetCurrentThread_icall", ves_icall_System_Threading_Thread_GetCurrentThread)) -HANDLES(THREAD_7, "GetDomainID", ves_icall_System_Threading_Thread_GetDomainID, gint32, 0, ()) -HANDLES(THREAD_8, "GetName_internal(System.Threading.InternalThread)", ves_icall_System_Threading_Thread_GetName_internal, MonoString, 1, (MonoInternalThread)) -HANDLES(THREAD_57, "GetPriorityNative", ves_icall_System_Threading_Thread_GetPriority, int, 1, (MonoThreadObject)) -HANDLES(THREAD_59, "GetStackTraces", ves_icall_System_Threading_Thread_GetStackTraces, void, 2, (MonoArrayOut, MonoArrayOut)) -HANDLES(THREAD_11, "GetState(System.Threading.InternalThread)", ves_icall_System_Threading_Thread_GetState, guint32, 1, (MonoInternalThread)) -HANDLES(THREAD_53, "InterruptInternal", ves_icall_System_Threading_Thread_Interrupt_internal, void, 1, (MonoThreadObject)) -HANDLES(THREAD_12, "JoinInternal", ves_icall_System_Threading_Thread_Join_internal, MonoBoolean, 2, (MonoThreadObject, int)) -NOHANDLES(ICALL(THREAD_13, "MemoryBarrier", ves_icall_System_Threading_Thread_MemoryBarrier)) -HANDLES(THREAD_14, "ResetAbortNative", ves_icall_System_Threading_Thread_ResetAbort, void, 1, (MonoThreadObject)) -HANDLES(THREAD_15, "ResumeInternal", ves_icall_System_Threading_Thread_Resume, void, 1, (MonoThreadObject)) -HANDLES(THREAD_18, "SetName_icall", ves_icall_System_Threading_Thread_SetName_icall, void, 3, (MonoInternalThread, const_gunichar2_ptr, gint32)) -HANDLES(THREAD_58, "SetPriorityNative", ves_icall_System_Threading_Thread_SetPriority, void, 2, (MonoThreadObject, int)) -HANDLES(THREAD_21, "SetState(System.Threading.InternalThread,System.Threading.ThreadState)", ves_icall_System_Threading_Thread_SetState, void, 2, (MonoInternalThread, guint32)) -HANDLES(THREAD_22, "SleepInternal", ves_icall_System_Threading_Thread_Sleep_internal, void, 1, (gint32)) -HANDLES(THREAD_54, "SpinWait_nop", ves_icall_System_Threading_Thread_SpinWait_nop, void, 0, ()) -HANDLES(THREAD_23, "SuspendInternal", ves_icall_System_Threading_Thread_Suspend, void, 1, (MonoThreadObject)) -// FIXME SystemMaxStackStize should be SystemMaxStackSize -NOHANDLES(ICALL(THREAD_56, "SystemMaxStackStize", ves_icall_System_Threading_Thread_SystemMaxStackSize)) -HANDLES(THREAD_25, "Thread_internal", ves_icall_System_Threading_Thread_Thread_internal, MonoBoolean, 2, (MonoThreadObject, MonoObject)) -NOHANDLES(ICALL(THREAD_26, "VolatileRead(byte&)", ves_icall_System_Threading_Thread_VolatileRead1)) -NOHANDLES(ICALL(THREAD_27, "VolatileRead(double&)", ves_icall_System_Threading_Thread_VolatileReadDouble)) -NOHANDLES(ICALL(THREAD_28, "VolatileRead(int&)", ves_icall_System_Threading_Thread_VolatileRead4)) -NOHANDLES(ICALL(THREAD_29, "VolatileRead(int16&)", ves_icall_System_Threading_Thread_VolatileRead2)) -NOHANDLES(ICALL(THREAD_30, "VolatileRead(intptr&)", ves_icall_System_Threading_Thread_VolatileReadIntPtr)) -NOHANDLES(ICALL(THREAD_31, "VolatileRead(long&)", ves_icall_System_Threading_Thread_VolatileRead8)) -NOHANDLES(ICALL(THREAD_32, "VolatileRead(object&)", ves_icall_System_Threading_Thread_VolatileReadObject)) -NOHANDLES(ICALL(THREAD_33, "VolatileRead(sbyte&)", ves_icall_System_Threading_Thread_VolatileRead1)) -NOHANDLES(ICALL(THREAD_34, "VolatileRead(single&)", ves_icall_System_Threading_Thread_VolatileReadFloat)) -NOHANDLES(ICALL(THREAD_35, "VolatileRead(uint&)", ves_icall_System_Threading_Thread_VolatileRead4)) -NOHANDLES(ICALL(THREAD_36, "VolatileRead(uint16&)", ves_icall_System_Threading_Thread_VolatileRead2)) -NOHANDLES(ICALL(THREAD_37, "VolatileRead(uintptr&)", ves_icall_System_Threading_Thread_VolatileReadIntPtr)) -NOHANDLES(ICALL(THREAD_38, "VolatileRead(ulong&)", ves_icall_System_Threading_Thread_VolatileRead8)) -NOHANDLES(ICALL(THREAD_39, "VolatileWrite(byte&,byte)", ves_icall_System_Threading_Thread_VolatileWrite1)) -NOHANDLES(ICALL(THREAD_40, "VolatileWrite(double&,double)", ves_icall_System_Threading_Thread_VolatileWriteDouble)) -NOHANDLES(ICALL(THREAD_41, "VolatileWrite(int&,int)", ves_icall_System_Threading_Thread_VolatileWrite4)) -NOHANDLES(ICALL(THREAD_42, "VolatileWrite(int16&,int16)", ves_icall_System_Threading_Thread_VolatileWrite2)) -NOHANDLES(ICALL(THREAD_43, "VolatileWrite(intptr&,intptr)", ves_icall_System_Threading_Thread_VolatileWriteIntPtr)) -NOHANDLES(ICALL(THREAD_44, "VolatileWrite(long&,long)", ves_icall_System_Threading_Thread_VolatileWrite8)) -NOHANDLES(ICALL(THREAD_45, "VolatileWrite(object&,object)", ves_icall_System_Threading_Thread_VolatileWriteObject)) -NOHANDLES(ICALL(THREAD_46, "VolatileWrite(sbyte&,sbyte)", ves_icall_System_Threading_Thread_VolatileWrite1)) -NOHANDLES(ICALL(THREAD_47, "VolatileWrite(single&,single)", ves_icall_System_Threading_Thread_VolatileWriteFloat)) -NOHANDLES(ICALL(THREAD_48, "VolatileWrite(uint&,uint)", ves_icall_System_Threading_Thread_VolatileWrite4)) -NOHANDLES(ICALL(THREAD_49, "VolatileWrite(uint16&,uint16)", ves_icall_System_Threading_Thread_VolatileWrite2)) -NOHANDLES(ICALL(THREAD_50, "VolatileWrite(uintptr&,uintptr)", ves_icall_System_Threading_Thread_VolatileWriteIntPtr)) -NOHANDLES(ICALL(THREAD_51, "VolatileWrite(ulong&,ulong)", ves_icall_System_Threading_Thread_VolatileWrite8)) -NOHANDLES(ICALL(THREAD_9, "YieldInternal", ves_icall_System_Threading_Thread_YieldInternal)) - -ICALL_TYPE(THREADP, "System.Threading.ThreadPool", THREADP_2) -HANDLES(THREADP_2, "GetAvailableThreadsNative", ves_icall_System_Threading_ThreadPool_GetAvailableThreadsNative, void, 2, (gint32_ref, gint32_ref)) -HANDLES(THREADP_3, "GetMaxThreadsNative", ves_icall_System_Threading_ThreadPool_GetMaxThreadsNative, void, 2, (gint32_ref, gint32_ref)) -HANDLES(THREADP_4, "GetMinThreadsNative", ves_icall_System_Threading_ThreadPool_GetMinThreadsNative, void, 2, (gint32_ref, gint32_ref)) -HANDLES(THREADP_5, "InitializeVMTp", ves_icall_System_Threading_ThreadPool_InitializeVMTp, void, 1, (MonoBoolean_ref)) -HANDLES(THREADP_7, "NotifyWorkItemComplete", ves_icall_System_Threading_ThreadPool_NotifyWorkItemComplete, MonoBoolean, 0, ()) -HANDLES(THREADP_8, "NotifyWorkItemProgressNative", ves_icall_System_Threading_ThreadPool_NotifyWorkItemProgressNative, void, 0, ()) -HANDLES(THREADP_8m, "NotifyWorkItemQueued", ves_icall_System_Threading_ThreadPool_NotifyWorkItemQueued, void, 0, ()) -HANDLES(THREADP_11, "ReportThreadStatus", ves_icall_System_Threading_ThreadPool_ReportThreadStatus, void, 1, (MonoBoolean)) -HANDLES(THREADP_12, "RequestWorkerThread", ves_icall_System_Threading_ThreadPool_RequestWorkerThread, MonoBoolean, 0, ()) -HANDLES(THREADP_13, "SetMaxThreadsNative", ves_icall_System_Threading_ThreadPool_SetMaxThreadsNative, MonoBoolean, 2, (gint32, gint32)) -HANDLES(THREADP_14, "SetMinThreadsNative", ves_icall_System_Threading_ThreadPool_SetMinThreadsNative, MonoBoolean, 2, (gint32, gint32)) - -ICALL_TYPE(TTIMER, "System.Threading.Timer", TTIMER_1) -NOHANDLES(ICALL(TTIMER_1, "GetTimeMonotonic", ves_icall_System_Threading_Timer_GetTimeMonotonic)) - -ICALL_TYPE(VOLATILE, "System.Threading.Volatile", VOLATILE_1) -NOHANDLES(ICALL(VOLATILE_1, "Read(double&)", ves_icall_System_Threading_Volatile_ReadDouble)) -NOHANDLES(ICALL(VOLATILE_2, "Read(long&)", ves_icall_System_Threading_Volatile_Read8)) -NOHANDLES(ICALL(VOLATILE_3, "Read(ulong&)", ves_icall_System_Threading_Volatile_ReadU8)) -NOHANDLES(ICALL(VOLATILE_4, "Write(double&,double)", ves_icall_System_Threading_Volatile_WriteDouble)) -NOHANDLES(ICALL(VOLATILE_5, "Write(long&,long)", ves_icall_System_Threading_Volatile_Write8)) -NOHANDLES(ICALL(VOLATILE_6, "Write(ulong&,ulong)", ves_icall_System_Threading_Volatile_WriteU8)) - -ICALL_TYPE(WAITH, "System.Threading.WaitHandle", WAITH_1) -HANDLES(WAITH_1, "SignalAndWait_Internal", ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal, gint32, 3, (gpointer, gpointer, gint32)) -HANDLES(WAITH_2, "Wait_internal", ves_icall_System_Threading_WaitHandle_Wait_internal, gint32, 4, (gpointer_ptr, gint32, MonoBoolean, gint32)) - -#if defined(TARGET_WASM) -ICALL_TYPE(TZINFO, "System.TimeZoneInfo", TZINFO_1) -NOHANDLES(ICALL(TZINFO_1, "mono_timezone_get_local_name", ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name)) -#endif - -ICALL_TYPE(TYPE, "System.Type", TYPE_1) -HANDLES(TYPE_1, "internal_from_handle", ves_icall_System_Type_internal_from_handle, MonoReflectionType, 1, (MonoType_ref)) - -ICALL_TYPE(TYPEDR, "System.TypedReference", TYPEDR_1) -HANDLES(TYPEDR_1, "InternalMakeTypedReference", ves_icall_System_TypedReference_InternalMakeTypedReference, void, 4, (MonoTypedRef_ptr, MonoObject, MonoArray, MonoReflectionType)) -HANDLES(TYPEDR_2, "InternalToObject", ves_icall_System_TypedReference_ToObject, MonoObject, 1, (MonoTypedRef_ptr)) - -ICALL_TYPE(VALUET, "System.ValueType", VALUET_1) -HANDLES(VALUET_1, "InternalEquals", ves_icall_System_ValueType_Equals, MonoBoolean, 3, (MonoObject, MonoObject, MonoArrayOut)) -HANDLES(VALUET_2, "InternalGetHashCode", ves_icall_System_ValueType_InternalGetHashCode, gint32, 2, (MonoObject, MonoArrayOut)) - -ICALL_TYPE(WEBIC, "System.Web.Util.ICalls", WEBIC_1) -HANDLES_REUSE_WRAPPER(WEBIC_1, "GetMachineConfigPath", ves_icall_System_Configuration_DefaultConfig_get_machine_config_path, MonoString, 0, ()) -HANDLES(WEBIC_2, "GetMachineInstallDirectory", ves_icall_System_Web_Util_ICalls_get_machine_install_dir, MonoString, 0, ()) -HANDLES(WEBIC_3, "GetUnmanagedResourcesPtr", ves_icall_get_resources_ptr, MonoBoolean, 3, (MonoReflectionAssembly, gpointer_ref, gint32_ref)) - -#ifndef DISABLE_COM -ICALL_TYPE(COMOBJ, "System.__ComObject", COMOBJ_1) -HANDLES(COMOBJ_1, "CreateRCW", ves_icall_System_ComObject_CreateRCW, MonoObject, 1, (MonoReflectionType)) -HANDLES(COMOBJ_2, "GetInterfaceInternal", ves_icall_System_ComObject_GetInterfaceInternal, gpointer, 3, (MonoComObject, MonoReflectionType, MonoBoolean)) -HANDLES(COMOBJ_3, "ReleaseInterfaces", ves_icall_System_ComObject_ReleaseInterfaces, void, 1, (MonoComObject)) -#endif - -#endif // This is similar to HANDLES() but is for icalls passed to register_jit_icall. // There is no metadata for these. No signature matching. diff --git a/src/mono/mono/metadata/icall-eventpipe.c b/src/mono/mono/metadata/icall-eventpipe.c index 87098b5..6c1088f 100644 --- a/src/mono/mono/metadata/icall-eventpipe.c +++ b/src/mono/mono/metadata/icall-eventpipe.c @@ -2,7 +2,6 @@ #include #include -#ifdef ENABLE_NETCORE #include #if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE) @@ -1082,6 +1081,3 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData ( } #endif /* ENABLE_PERFTRACING */ -#endif /* ENABLE_NETCORE */ - -MONO_EMPTY_SOURCE_FILE (icall_eventpipe); diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index c9293be..771119e 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -44,8 +44,6 @@ #include #include #include -#include -#include #include #include #include @@ -55,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -66,15 +63,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include #include #include #include @@ -201,12 +195,10 @@ ves_icall_System_Array_GetValueImpl (MonoArrayHandle array, guint32 pos, MonoErr MonoClass * const array_class = mono_handle_class (array); MonoClass * const element_class = m_class_get_element_class (array_class); -#ifdef ENABLE_NETCORE if (m_class_is_native_pointer (element_class)) { mono_error_set_not_supported (error, NULL); return NULL_HANDLE; } -#endif if (m_class_is_valuetype (element_class)) { gsize element_size = mono_array_element_size (array_class); @@ -278,7 +270,6 @@ set_invalid_cast (MonoError *error, MonoClass *src_class, MonoClass *dst_class) mono_error_set_invalid_cast (error); } -#if ENABLE_NETCORE void ves_icall_System_Array_SetValueRelaxedImpl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error) { @@ -364,7 +355,6 @@ ves_icall_System_Array_CanChangePrimitive (MonoReflectionType *volatile* ref_src // see https://github.com/dotnet/coreclr/pull/25209#issuecomment-505952295 return can_primitive_widen (src_type->type, dst_type->type); } -#endif static void array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, guint32 pos, gboolean strict_enums, gboolean strict_signs, MonoError *error) @@ -392,13 +382,12 @@ array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, esize = mono_array_element_size (ac); if (mono_class_is_nullable (ec)) { -#ifdef ENABLE_NETCORE if (vc && m_class_is_primitive (vc) && vc != m_class_get_nullable_elem_class (ec)) { // T -> Nullable T must be exact set_invalid_cast (error, vc, ec); goto leave; } -#endif + MONO_ENTER_NO_SAFEPOINTS; ea = (gpointer*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (arr_handle), esize, pos); if (!MONO_HANDLE_IS_NULL (value_handle)) @@ -416,13 +405,8 @@ array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, goto leave; } -#ifdef ENABLE_NETCORE #define WIDENING_MSG NULL #define WIDENING_ARG NULL -#else -#define WIDENING_MSG "not a widening conversion" -#define WIDENING_ARG "value" -#endif #define NO_WIDENING_CONVERSION G_STMT_START{ \ mono_error_set_argument (error, WIDENING_ARG, WIDENING_MSG); \ @@ -520,12 +504,10 @@ array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, et_isenum = et == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (ec)->data.klass); vt_isenum = vt == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (vc)->data.klass); -#if ENABLE_NETCORE if (strict_enums && et_isenum && !vt_isenum) { INVALID_CAST; goto leave; } -#endif if (et_isenum) et = mono_class_enum_basetype_internal (m_class_get_byval_arg (ec)->data.klass)->type; @@ -533,7 +515,6 @@ array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, if (vt_isenum) vt = mono_class_enum_basetype_internal (m_class_get_byval_arg (vc)->data.klass)->type; -#if ENABLE_NETCORE // Treat MONO_TYPE_U/I as MONO_TYPE_U8/I8/U4/I4 #if SIZEOF_VOID_P == 8 vt = vt == MONO_TYPE_U ? MONO_TYPE_U8 : (vt == MONO_TYPE_I ? MONO_TYPE_I8 : vt); @@ -542,7 +523,6 @@ array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, vt = vt == MONO_TYPE_U ? MONO_TYPE_U4 : (vt == MONO_TYPE_I ? MONO_TYPE_I4 : vt); et = et == MONO_TYPE_U ? MONO_TYPE_U4 : (et == MONO_TYPE_I ? MONO_TYPE_I4 : et); #endif -#endif #define ASSIGN_UNSIGNED(etype) G_STMT_START{\ switch (vt) { \ @@ -765,11 +745,7 @@ ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value, error_init (error); if (MONO_HANDLE_IS_NULL (idxs)) { -#ifdef ENABLE_NETCORE mono_error_set_argument_null (error, "indices", ""); -#else - mono_error_set_argument_null (error, "idxs", ""); -#endif return; } @@ -778,11 +754,7 @@ ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value, g_assert (m_class_get_rank (ic) == 1); if (mono_handle_array_has_bounds (idxs) || MONO_HANDLE_GETVAL (idxs, max_length) != m_class_get_rank (ac)) { -#ifdef ENABLE_NETCORE mono_error_set_argument (error, NULL, ""); -#else - mono_error_set_argument (error, "idxs", ""); -#endif return; } @@ -820,8 +792,6 @@ ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value, array_set_value_impl (arr, value, pos, TRUE, TRUE, error); } -#ifdef ENABLE_NETCORE - void ves_icall_System_Array_InternalCreate (MonoArray *volatile* result, MonoType* type, gint32 rank, gint32* pLengths, gint32* pLowerBounds) { @@ -884,79 +854,6 @@ exit: mono_error_set_pending_exception (error); } -#endif - -#ifndef ENABLE_NETCORE -MonoArrayHandle -ves_icall_System_Array_CreateInstanceImpl (MonoReflectionTypeHandle type, MonoArrayHandle lengths, MonoArrayHandle bounds, MonoError *error) -{ - // FIXME? fixed could be used for lengths, bounds. - - icallarray_print ("%s type:%p length:%p bounds:%p\n", __func__, type, lengths, bounds); - - MONO_CHECK_ARG_NULL_HANDLE (type, NULL_HANDLE_ARRAY); - MONO_CHECK_ARG_NULL_HANDLE (lengths, NULL_HANDLE_ARRAY); - - MONO_CHECK_ARG (lengths, mono_array_handle_length (lengths) > 0, NULL_HANDLE_ARRAY); - if (!MONO_HANDLE_IS_NULL (bounds)) - MONO_CHECK_ARG (bounds, mono_array_handle_length (lengths) == mono_array_handle_length (bounds), NULL_HANDLE_ARRAY); - - for (uintptr_t i = 0; i < mono_array_handle_length (lengths); ++i) { - gint32 length = 0; - MONO_HANDLE_ARRAY_GETVAL (length, lengths, gint32, i); - if (length < 0) { - mono_error_set_argument_out_of_range (error, NULL, "MonoArgumentException:NULL"); - return NULL_HANDLE_ARRAY; - } - } - - MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type)); - if (!mono_class_init_checked (klass, error)) - return NULL_HANDLE_ARRAY; - - if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_VOID) { - mono_error_set_not_supported (error, "Arrays of System.Void are not supported."); - return NULL_HANDLE_ARRAY; - } - - /* vectors are not the same as one dimensional arrays with non-zero bounds */ - gboolean bounded = FALSE; - if (!MONO_HANDLE_IS_NULL (bounds) && mono_array_handle_length (bounds) == 1) { - gint32 bound0 = 0; - MONO_HANDLE_ARRAY_GETVAL (bound0, bounds, gint32, 0); - bounded = bound0 != 0; - } - - MonoClass * const aklass = mono_class_create_bounded_array (klass, mono_array_handle_length (lengths), bounded); - uintptr_t const aklass_rank = m_class_get_rank (aklass); - uintptr_t * const sizes = g_newa (uintptr_t, aklass_rank); - intptr_t * const lower_bounds = g_newa (intptr_t, aklass_rank); - - // Copy lengths and lower_bounds from gint32 to [u]intptr_t. - - for (uintptr_t i = 0; i < aklass_rank; ++i) { - MONO_HANDLE_ARRAY_GETVAL (sizes [i], lengths, gint32, i); - if (!MONO_HANDLE_IS_NULL (bounds)) - MONO_HANDLE_ARRAY_GETVAL (lower_bounds [i], bounds, gint32, i); - else - lower_bounds [i] = 0; - } - - return mono_array_new_full_handle (MONO_HANDLE_DOMAIN (type), aklass, sizes, lower_bounds, error); -} - -gint32 -ves_icall_System_Array_GetRank (MonoObjectHandle arr, MonoError *error) -{ - gint32 const result = m_class_get_rank (mono_handle_class (arr)); - - icallarray_print ("%s arr:%p res:%d\n", __func__, MONO_HANDLE_RAW (arr), result); - - return result; -} -#endif - -#ifdef ENABLE_NETCORE gint32 ves_icall_System_Array_GetCorElementTypeOfElementType (MonoArrayHandle arr, MonoError *error) { @@ -969,7 +866,6 @@ ves_icall_System_Array_IsValueOfElementType (MonoArrayHandle arr, MonoObjectHand { return m_class_get_element_class (mono_handle_class (arr)) == mono_handle_class (obj); } -#endif static mono_array_size_t mono_array_get_length (MonoArrayHandle arr, gint32 dimension, MonoError *error) @@ -996,16 +892,6 @@ ves_icall_System_Array_GetLength (MonoArrayHandle arr, gint32 dimension, MonoErr return (gint32)length; } -#ifndef ENABLE_NETCORE -gint64 -ves_icall_System_Array_GetLongLength (MonoArrayHandle arr, gint32 dimension, MonoError *error) -{ - icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension); - - return (gint64)mono_array_get_length (arr, dimension, error); -} -#endif - gint32 ves_icall_System_Array_GetLowerBound (MonoArrayHandle arr, gint32 dimension, MonoError *error) { @@ -1020,17 +906,6 @@ ves_icall_System_Array_GetLowerBound (MonoArrayHandle arr, gint32 dimension, Mon : 0; } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Array_ClearInternal (MonoArrayHandle arr, int idx, int length, MonoError *error) -{ - icallarray_print ("%s arr:%p idx:%d len:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)idx, (int)length); - - int sz = mono_array_element_size (mono_handle_class (arr)); - mono_gc_bzero_atomic (mono_array_addr_with_size_fast (MONO_HANDLE_RAW (arr), sz, idx), length * sz); -} -#endif - MonoBoolean ves_icall_System_Array_FastCopy (MonoArrayHandle source, int source_idx, MonoArrayHandle dest, int dest_idx, int length, MonoError *error) { @@ -1145,16 +1020,11 @@ ves_icall_System_Array_SetGenericValue_icall (MonoArray **arr, guint32 pos, gpoi } void -#if ENABLE_NETCORE ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *source, size_t byte_count) -#else -ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *source, guint byte_count) -#endif { mono_gc_memmove_atomic (destination, source, byte_count); } -#if ENABLE_NETCORE void ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *destination, guint8 *source, size_t len, MonoType *type) { @@ -1163,23 +1033,9 @@ ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *destination, guint8 *s else mono_gc_wbarrier_value_copy_internal (destination, source, (guint)len, mono_class_from_mono_type_internal (type)); } -#else -void -ves_icall_System_Runtime_RuntimeImports_Memmove_wbarrier (guint8 *destination, guint8 *source, guint len, MonoType *type) -{ - if (MONO_TYPE_IS_REFERENCE (type)) - mono_gc_wbarrier_arrayref_copy_internal (destination, source, len); - else - mono_gc_wbarrier_value_copy_internal (destination, source, len, mono_class_from_mono_type_internal (type)); -} -#endif void -#if ENABLE_NETCORE ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8 *p, size_t byte_length) -#else -ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8 *p, guint byte_length) -#endif { memset (p, 0, byte_length); } @@ -1306,7 +1162,6 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (M mono_runtime_class_init_full (vtable, error); } -#ifdef ENABLE_NETCORE MonoBoolean ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void) { @@ -1326,48 +1181,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStac return TRUE; } -#else -MonoBoolean -ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void) -{ -#if defined(TARGET_WIN32) || defined(HOST_WIN32) - // It does not work on win32 -#elif defined(TARGET_ANDROID) || defined(__linux__) - // No need for now -#else - guint8 *stack_addr; - guint8 *current; - size_t stack_size; - int min_size; - MonoInternalThread *thread; - - mono_thread_info_get_stack_bounds (&stack_addr, &stack_size); - /* if we have no info we are optimistic and assume there is enough room */ - if (!stack_addr) - return TRUE; - - thread = mono_thread_internal_current (); - // .net seems to check that at least 50% of stack is available - min_size = thread->stack_size / 2; - - // TODO: It's not always set - if (!min_size) - return TRUE; - - current = (guint8 *)&stack_addr; - if (current > stack_addr) { - if ((current - stack_addr) < min_size) - return FALSE; - } else { - if (current - (stack_addr - stack_size) < min_size) - return FALSE; - } -#endif - return TRUE; -} -#endif -#ifdef ENABLE_NETCORE MonoObjectHandle ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetUninitializedObjectInternal (MonoType *handle, MonoError *error) { @@ -1439,7 +1253,6 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_PrepareMethod (MonoMeth // FIXME: Implement } -#endif MonoObjectHandle ves_icall_System_Object_MemberwiseClone (MonoObjectHandle this_obj, MonoError *error) @@ -1686,30 +1499,6 @@ ves_icall_System_ValueType_Equals (MonoObjectHandle this_obj, MonoObjectHandle t } } -#ifndef ENABLE_NETCORE -MonoReflectionTypeHandle -ves_icall_System_Object_GetType (MonoObjectHandle obj, MonoError *error) -{ - MonoDomain *domain = MONO_HANDLE_DOMAIN (obj); - MonoClass *klass = mono_handle_class (obj); -#ifndef DISABLE_REMOTING - if (mono_class_is_transparent_proxy (klass)) { - MonoTransparentProxyHandle proxy_obj = MONO_HANDLE_CAST (MonoTransparentProxy, obj); - MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (proxy_obj, remote_class); - /* If it's a transparent proxy for an interface, return the - * interface type, not the unhelpful proxy_class class (which - * is just MarshalByRefObject). */ - MonoType *proxy_type = - mono_remote_class_is_interface_proxy (remote_class) ? - m_class_get_byval_arg (remote_class->interfaces[0]) : - m_class_get_byval_arg (remote_class->proxy_class); - return mono_type_get_object_handle (domain, proxy_type, error); - } else -#endif - return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error); -} -#endif - static gboolean get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data) { @@ -2017,94 +1806,6 @@ typedef enum { TYPECODE_STRING = 18 } TypeCode; -#ifndef ENABLE_NETCORE -guint32 -ves_icall_type_GetTypeCodeInternal (MonoReflectionTypeHandle ref_type, MonoError *error) -{ - MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - - if (type->byref) - return TYPECODE_OBJECT; - -handle_enum: - switch (type->type) { - case MONO_TYPE_VOID: - return TYPECODE_OBJECT; - case MONO_TYPE_BOOLEAN: - return TYPECODE_BOOLEAN; - case MONO_TYPE_U1: - return TYPECODE_BYTE; - case MONO_TYPE_I1: - return TYPECODE_SBYTE; - case MONO_TYPE_U2: - return TYPECODE_UINT16; - case MONO_TYPE_I2: - return TYPECODE_INT16; - case MONO_TYPE_CHAR: - return TYPECODE_CHAR; - case MONO_TYPE_PTR: - case MONO_TYPE_U: - case MONO_TYPE_I: - return TYPECODE_OBJECT; - case MONO_TYPE_U4: - return TYPECODE_UINT32; - case MONO_TYPE_I4: - return TYPECODE_INT32; - case MONO_TYPE_U8: - return TYPECODE_UINT64; - case MONO_TYPE_I8: - return TYPECODE_INT64; - case MONO_TYPE_R4: - return TYPECODE_SINGLE; - case MONO_TYPE_R8: - return TYPECODE_DOUBLE; - case MONO_TYPE_VALUETYPE: { - MonoClass *klass = type->data.klass; - - if (m_class_is_enumtype (klass)) { - type = mono_class_enum_basetype_internal (klass); - goto handle_enum; - } else if (mono_is_corlib_image (m_class_get_image (klass))) { - if (strcmp (m_class_get_name_space (klass), "System") == 0) { - if (strcmp (m_class_get_name (klass), "Decimal") == 0) - return TYPECODE_DECIMAL; - else if (strcmp (m_class_get_name (klass), "DateTime") == 0) - return TYPECODE_DATETIME; - } - } - return TYPECODE_OBJECT; - } - case MONO_TYPE_STRING: - return TYPECODE_STRING; - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_OBJECT: - case MONO_TYPE_VAR: - case MONO_TYPE_MVAR: - case MONO_TYPE_TYPEDBYREF: - return TYPECODE_OBJECT; - case MONO_TYPE_CLASS: - { - MonoClass *klass = type->data.klass; - if (m_class_get_image (klass) == mono_defaults.corlib && strcmp (m_class_get_name_space (klass), "System") == 0) { - if (strcmp (m_class_get_name (klass), "DBNull") == 0) - return TYPECODE_DBNULL; - } - } - return TYPECODE_OBJECT; - case MONO_TYPE_GENERICINST: - if (m_class_is_enumtype (type->data.generic_class->container_class)) { - type = mono_class_enum_basetype_internal (type->data.generic_class->container_class); - goto handle_enum; - } - return TYPECODE_OBJECT; - default: - g_error ("type 0x%02x not handled in GetTypeCode()", type->type); - } - return 0; -} -#endif - guint32 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_c, MonoError *error) { @@ -2198,10 +1899,8 @@ ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionTypeHandle ref_type, Mo { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); -#ifdef ENABLE_NETCORE if (type->byref || type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) return TYPE_ATTRIBUTE_NOT_PUBLIC; -#endif MonoClass *klass = mono_class_from_mono_type_internal (type); return mono_class_get_flags (klass); @@ -3294,28 +2993,6 @@ leave: HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); } -#ifndef ENABLE_NETCORE -void -ves_icall_RuntimeType_GetGUID (MonoReflectionTypeHandle type_handle, MonoArrayHandle guid_handle, MonoError *error) -{ - error_init (error); - - g_assert (mono_array_handle_length (guid_handle) == 16); - if (MONO_HANDLE_IS_NULL (type_handle)) { - mono_error_set_argument_null (error, "type", ""); - return; - } - - MonoType *type = MONO_HANDLE_GETVAL (type_handle, type); - MonoClass *klass = mono_class_from_mono_type_internal (type); - if (!mono_class_init_checked (klass, error)) - return; - - guint8 *data = (guint8*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (guid_handle), 1, 0); - mono_metadata_get_class_guid (klass, data, error); -} -#endif - MonoArrayHandle ves_icall_RuntimeType_GetGenericArguments (MonoReflectionTypeHandle ref_type, MonoBoolean runtimeTypeArray, MonoError *error) { @@ -3540,24 +3217,6 @@ leave: return ret; } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (MonoError *error) -{ - error_init (error); - mono_error_set_not_implemented (error, "%s", "System.RuntimeType.IsTypeExportedToWindowsRuntime"); - return FALSE; -} - -MonoBoolean -ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (MonoError *error) -{ - error_init (error); - mono_error_set_not_implemented (error, "%s", "System.RuntimeType.IsWindowsRuntimeObjectType"); - return FALSE; -} -#endif /* ENABLE_NETCORE */ - void ves_icall_RuntimeMethodInfo_GetPInvoke (MonoReflectionMethodHandle ref_method, int* flags, MonoStringHandleOut entry_point, MonoStringHandleOut dll_name, MonoError *error) { @@ -3651,7 +3310,6 @@ ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition (MonoReflectionMethodHand return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (ref_method), result, NULL, error); } -#ifdef ENABLE_NETCORE static GENERATE_TRY_GET_CLASS_WITH_CACHE (stream, "System.IO", "Stream") static int io_stream_begin_read_slot = -1; static int io_stream_begin_write_slot = -1; @@ -3731,7 +3389,6 @@ ves_icall_System_IO_Stream_HasOverriddenBeginEndWrite (MonoObjectHandle stream, // return true if BeginWrite or EndWrite were overriden return begin_write_is_overriden || end_write_is_overriden; } -#endif MonoBoolean ves_icall_RuntimeMethodInfo_get_IsGenericMethod (MonoReflectionMethodHandle ref_method, MonoError *erro) @@ -3878,7 +3535,7 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method with stack pointers via reflection"); goto return_null; } -#if ENABLE_NETCORE + if (sig->ret->byref) { MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); if (ret_byval->type == MONO_TYPE_VOID) { @@ -3890,12 +3547,6 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa goto return_null; } } -#else - if (sig->ret->byref) { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"); - goto return_null; - } -#endif pcount = params? mono_array_length_internal (params): 0; if (pcount != sig->param_count) { @@ -4279,32 +3930,6 @@ ves_icall_System_Enum_InternalHasFlag (MonoObjectHandle a, MonoObjectHandle b, M return (a_val & b_val) == b_val; } -#ifndef ENABLE_NETCORE -MonoObjectHandle -ves_icall_System_Enum_get_value (MonoObjectHandle ehandle, MonoError *error) -{ - MonoObjectHandle resultHandle; - MonoClass *enumc; - int size; - - goto_if (MONO_HANDLE_IS_NULL (ehandle), return_null); - - g_assert (m_class_is_enumtype (mono_handle_class (ehandle))); - - enumc = mono_class_from_mono_type_internal (mono_class_enum_basetype_internal (mono_handle_class (ehandle))); - - resultHandle = mono_object_new_handle (MONO_HANDLE_DOMAIN (ehandle), enumc, error); - goto_if_nok (error, return_null); - size = mono_class_value_size (enumc, NULL); - - memcpy (mono_handle_unbox_unsafe (resultHandle), mono_handle_unbox_unsafe (ehandle), size); - - return resultHandle; -return_null: - return MONO_HANDLE_NEW (MonoObject, NULL); -} -#endif - MonoReflectionTypeHandle ves_icall_System_Enum_get_underlying_type (MonoReflectionTypeHandle type, MonoError *error) { @@ -4335,160 +3960,43 @@ ves_icall_System_Enum_InternalGetCorElementType (MonoObjectHandle this_handle, M return (int)m_class_get_byval_arg (m_class_get_element_class (klass))->type; } -#ifndef ENABLE_NETCORE -int -ves_icall_System_Enum_compare_value_to (MonoObjectHandle enumHandle, MonoObjectHandle otherHandle, MonoError *error) +static void +get_enum_field (MonoDomain *domain, MonoArrayHandle names, MonoArrayHandle values, int base_type, MonoClassField *field, guint* j, guint64 *previous_value, gboolean *sorted, MonoError *error) { - if (MONO_HANDLE_IS_NULL (otherHandle)) - return 1; + error_init (error); + HANDLE_FUNCTION_ENTER(); + guint64 field_value; + const char *p; + MonoTypeEnum def_type; - if (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass != MONO_HANDLE_GETVAL (otherHandle, vtable)->klass) - return 2; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) + goto leave; + if (strcmp ("value__", mono_field_get_name (field)) == 0) + goto leave; + if (mono_field_is_deleted (field)) + goto leave; + MonoStringHandle name; + name = mono_string_new_handle (domain, mono_field_get_name (field), error); + goto_if_nok (error, leave); + MONO_HANDLE_ARRAY_SETREF (names, *j, name); - gpointer tdata = mono_handle_unbox_unsafe (enumHandle); - gpointer odata = mono_handle_unbox_unsafe (otherHandle); - MonoType *basetype = mono_class_enum_basetype_internal (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass); - g_assert (basetype); + p = mono_class_get_field_default_value (field, &def_type); + /* len = */ mono_metadata_decode_blob_size (p, &p); -#define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \ - ENUM_TYPE me = *((ENUM_TYPE*)tdata); \ - ENUM_TYPE other = *((ENUM_TYPE*)odata); \ - if (me == other) \ - return 0; \ - return me > other ? 1 : -1; \ - } while (0) + field_value = read_enum_value (p, base_type); + MONO_HANDLE_ARRAY_SETVAL (values, guint64, *j, field_value); - switch (basetype->type) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_U1: - COMPARE_ENUM_VALUES (guint8); - case MONO_TYPE_I1: - COMPARE_ENUM_VALUES (gint8); - case MONO_TYPE_CHAR: - case MONO_TYPE_U2: - COMPARE_ENUM_VALUES (guint16); - case MONO_TYPE_I2: - COMPARE_ENUM_VALUES (gint16); - case MONO_TYPE_U4: - COMPARE_ENUM_VALUES (guint32); - case MONO_TYPE_I4: - COMPARE_ENUM_VALUES (gint32); - case MONO_TYPE_R4: - COMPARE_ENUM_VALUES (gfloat); - case MONO_TYPE_U8: - COMPARE_ENUM_VALUES (guint64); - case MONO_TYPE_I8: - COMPARE_ENUM_VALUES (gint64); - case MONO_TYPE_R8: - COMPARE_ENUM_VALUES (gdouble); - case MONO_TYPE_U: -#if SIZEOF_REGISTER == 8 - COMPARE_ENUM_VALUES (guint64); -#else - COMPARE_ENUM_VALUES (guint32); -#endif - case MONO_TYPE_I: -#if SIZEOF_REGISTER == 8 - COMPARE_ENUM_VALUES (gint64); -#else - COMPARE_ENUM_VALUES (gint32); -#endif - default: - break; - } -#undef COMPARE_ENUM_VALUES - /* indicates that the enum was of an unsupported underlying type */ - return 3; + if (*previous_value > field_value) + *sorted = FALSE; + + *previous_value = field_value; + (*j)++; +leave: + HANDLE_FUNCTION_RETURN(); } -#endif -#ifndef ENABLE_NETCORE -int -ves_icall_System_Enum_get_hashcode (MonoObjectHandle enumHandle, MonoError *error) -{ - gpointer data = mono_handle_unbox_unsafe (enumHandle); - MonoType *basetype = mono_class_enum_basetype_internal (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass); - g_assert (basetype); - - switch (basetype->type) { - case MONO_TYPE_I1: { - gint8 value = *((gint8*)data); - return ((int)value ^ (int)value << 8); - } - case MONO_TYPE_U1: - return *((guint8*)data); - case MONO_TYPE_CHAR: - case MONO_TYPE_U2: - return *((guint16*)data); - - case MONO_TYPE_I2: { - gint16 value = *((gint16*)data); - return ((int)(guint16)value | (((int)value) << 16)); - } - case MONO_TYPE_U4: - case MONO_TYPE_R4: - return *((guint32*)data); - case MONO_TYPE_I4: - return *((gint32*)data); - case MONO_TYPE_U8: - case MONO_TYPE_I8: - case MONO_TYPE_R8: { - gint64 value = *((gint64*)data); - return (gint)(value & 0xffffffff) ^ (int)(value >> 32); - } - case MONO_TYPE_I: - case MONO_TYPE_U: { -#if SIZEOF_REGISTER == 8 - gint64 value = *((gint64*)data); - return (gint)(value & 0xffffffff) ^ (int)(value >> 32); -#else - return *((guint32*)data); -#endif - } - default: - g_error ("Implement type 0x%02x in get_hashcode", basetype->type); - } - return 0; -} -#endif - -static void -get_enum_field (MonoDomain *domain, MonoArrayHandle names, MonoArrayHandle values, int base_type, MonoClassField *field, guint* j, guint64 *previous_value, gboolean *sorted, MonoError *error) -{ - error_init (error); - HANDLE_FUNCTION_ENTER(); - guint64 field_value; - const char *p; - MonoTypeEnum def_type; - - if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) - goto leave; - if (strcmp ("value__", mono_field_get_name (field)) == 0) - goto leave; - if (mono_field_is_deleted (field)) - goto leave; - MonoStringHandle name; - name = mono_string_new_handle (domain, mono_field_get_name (field), error); - goto_if_nok (error, leave); - MONO_HANDLE_ARRAY_SETREF (names, *j, name); - - p = mono_class_get_field_default_value (field, &def_type); - /* len = */ mono_metadata_decode_blob_size (p, &p); - - field_value = read_enum_value (p, base_type); - MONO_HANDLE_ARRAY_SETVAL (values, guint64, *j, field_value); - - if (*previous_value > field_value) - *sorted = FALSE; - - *previous_value = field_value; - (*j)++; -leave: - HANDLE_FUNCTION_RETURN(); -} - -MonoBoolean -ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, MonoArrayHandleOut values, MonoArrayHandleOut names, MonoError *error) +MonoBoolean +ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, MonoArrayHandleOut values, MonoArrayHandleOut names, MonoError *error) { MonoDomain *domain = MONO_HANDLE_DOMAIN (type); MonoClass *enumc = mono_class_from_mono_type_internal (MONO_HANDLE_RAW(type)->type); @@ -4504,11 +4012,7 @@ ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, Mono return_val_if_nok (error, FALSE); if (!m_class_is_enumtype (enumc)) { -#if ENABLE_NETCORE mono_error_set_argument (error, NULL, "Type provided must be an Enum."); -#else - mono_error_set_argument (error, "enumType", "Type provided must be an Enum."); -#endif return TRUE; } @@ -4882,10 +4386,8 @@ property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass) GPtrArray* ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionTypeHandle ref_type, gchar *propname, guint32 bflags, guint32 mlisttype, MonoError *error) { -#if ENABLE_NETCORE // Fetch non-public properties as well because they can hide public properties with the same name in base classes bflags |= BFLAGS_NonPublic; -#endif MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); if (type->byref) { @@ -4960,10 +4462,8 @@ handle_parent: g_hash_table_insert (properties, prop, prop); } if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass))) { -#if ENABLE_NETCORE // BFLAGS_NonPublic should be excluded for base classes bflags &= ~BFLAGS_NonPublic; -#endif goto handle_parent; } @@ -5160,11 +4660,7 @@ ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssemblyHand mono_reflection_free_type_info (&info); mono_error_cleanup (parse_error); if (throwOnError) { -#if ENABLE_NETCORE mono_error_set_argument (error, "typeName@0", "failed to parse the type"); -#else - mono_error_set_argument (error, "typeName", "failed to parse the type"); -#endif goto fail; } /*g_print ("failed parse\n");*/ @@ -5346,37 +4842,6 @@ ves_icall_System_Reflection_RuntimeAssembly_get_code_base (MonoReflectionAssembl return res; } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_Reflection_RuntimeAssembly_get_global_assembly_cache (MonoReflectionAssemblyHandle assembly, MonoError *error) -{ - MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly,assembly); - - return mass->in_gac; -} - -MonoReflectionAssemblyHandle -ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoStringHandle mname, MonoObjectHandle evidence, MonoError *error) -{ - gchar *name; - MonoImageOpenStatus status; - MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE); - - name = mono_string_handle_to_utf8 (mname, error); - goto_if_nok (error, leave); - MonoAssembly *res; - res = mono_assembly_load_with_partial_name_internal (name, mono_domain_default_alc (mono_domain_get ()), &status); - - g_free (name); - - if (res == NULL) - goto leave; - result = mono_assembly_get_object_handle (mono_domain_get (), res, error); -leave: - return result; -} -#endif - MonoStringHandle ves_icall_System_Reflection_RuntimeAssembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error) { @@ -5386,15 +4851,6 @@ ves_icall_System_Reflection_RuntimeAssembly_get_location (MonoReflectionAssembly return mono_string_new_handle (domain, image_name != NULL ? image_name : "", error); } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_Reflection_RuntimeAssembly_get_ReflectionOnly (MonoReflectionAssemblyHandle assembly_h, MonoError *error) -{ - MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly); - return mono_asmctx_get_kind (&assembly->context) == MONO_ASMCTX_REFONLY; -} -#endif - MonoStringHandle ves_icall_System_Reflection_RuntimeAssembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error) { @@ -5463,25 +4919,6 @@ fail: return NULL_HANDLE_ARRAY; } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_Reflection_RuntimeAssembly_GetAotIdInternal (MonoArrayHandle guid_h, MonoError *error) -{ - g_assert (mono_array_handle_length (guid_h) == 16); - - guint8 *aotid = mono_runtime_get_aotid_arr (); - if (!aotid) { - return FALSE; - } else { - MONO_ENTER_NO_SAFEPOINTS; - guint8 *data = (guint8*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (guid_h), 1, 0); - memcpy (data, aotid, 16); - MONO_EXIT_NO_SAFEPOINTS; - return TRUE; - } -} -#endif - static MonoAssemblyName* create_referenced_assembly_name (MonoDomain *domain, MonoImage *image, int i, MonoError *error) { @@ -5551,7 +4988,6 @@ g_concat_dir_and_file (const char *dir, const char *file) return g_strconcat (dir, file, (const char*)NULL); } -#ifdef ENABLE_NETCORE static MonoReflectionAssemblyHandle try_resource_resolve_name (MonoReflectionAssemblyHandle assembly_handle, MonoStringHandle name_handle) { @@ -5595,7 +5031,6 @@ return_null: exit: HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret)); } -#endif static void * get_manifest_resource_internal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, gint32 *size, MonoReflectionModuleHandleOut ref_module, MonoError *error) @@ -5651,13 +5086,11 @@ ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceInternal (MonoRef { gpointer ret = get_manifest_resource_internal (assembly_h, name, size, ref_module, error); -#ifdef ENABLE_NETCORE if (!ret) { MonoReflectionAssemblyHandle event_assembly_h = try_resource_resolve_name (assembly_h, name); if (MONO_HANDLE_BOOL (event_assembly_h)) ret = get_manifest_resource_internal (event_assembly_h, name, size, ref_module, error); } -#endif return ret; } @@ -5992,7 +5425,6 @@ ves_icall_System_Reflection_RuntimeMethodInfo_GetMethodBodyInternal (MonoMethod return mono_method_body_get_object_handle (mono_domain_get (), method, error); } -#if ENABLE_NETCORE MonoReflectionAssemblyHandle ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoStackCrawlMark *stack_mark, MonoError *error) { @@ -6001,16 +5433,6 @@ ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoStackCrawlMark *s g_assert (assembly); return mono_assembly_get_object_handle (mono_domain_get (), assembly, error); } -#else -MonoReflectionAssemblyHandle -ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoError *error) -{ - MonoMethod *dest = NULL; - mono_stack_walk_no_il (get_executing, &dest); - g_assert (dest); - return mono_assembly_get_object_handle (mono_domain_get (), m_class_get_image (dest->klass)->assembly, error); -} -#endif MonoReflectionAssemblyHandle ves_icall_System_Reflection_Assembly_GetEntryAssembly (MonoError *error) @@ -6075,33 +5497,6 @@ ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, MonoB return res; } -#ifndef ENABLE_NETCORE -int -ves_icall_RuntimeType_get_core_clr_security_level (MonoReflectionTypeHandle rfield, MonoError *error) -{ - MonoType *type = MONO_HANDLE_GETVAL (rfield, type); - MonoClass *klass = mono_class_from_mono_type_internal (type); - - mono_class_init_checked (klass, error); - return_val_if_nok (error, -1); - return mono_security_core_clr_class_level (klass); -} - -int -ves_icall_RuntimeFieldInfo_get_core_clr_security_level (MonoReflectionFieldHandle rfield, MonoError *error) -{ - MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field); - return mono_security_core_clr_field_level (field, TRUE); -} - -int -ves_icall_RuntimeMethodInfo_get_core_clr_security_level (MonoReflectionMethodHandle rfield, MonoError *error) -{ - MonoMethod *method = MONO_HANDLE_GETVAL (rfield, method); - return mono_security_core_clr_method_level (method, TRUE); -} -#endif - MonoStringHandle ves_icall_System_Reflection_RuntimeAssembly_get_fullname (MonoReflectionAssemblyHandle assembly, MonoError *error) { @@ -6183,38 +5578,6 @@ ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoStringHandle f g_free (filename); } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_Reflection_RuntimeAssembly_LoadPermissions (MonoReflectionAssemblyHandle assembly_h, - char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength, MonoError *error) -{ - MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly); - MonoBoolean result = FALSE; - MonoDeclSecurityEntry entry; - - /* SecurityAction.RequestMinimum */ - if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQMIN, &entry)) { - *minimum = entry.blob; - *minLength = entry.size; - result = TRUE; - } - /* SecurityAction.RequestOptional */ - if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQOPT, &entry)) { - *optional = entry.blob; - *optLength = entry.size; - result = TRUE; - } - /* SecurityAction.RequestRefuse */ - if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQREFUSE, &entry)) { - *refused = entry.blob; - *refLength = entry.size; - result = TRUE; - } - - return result; -} -#endif - static gboolean mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type) { @@ -6419,15 +5782,6 @@ assembly_get_types (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean ex return res; } -#ifndef ENABLE_NETCORE -MonoArrayHandle -ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean exportedOnly, MonoError *error) -{ - return assembly_get_types (assembly_handle, exportedOnly, error); -} -#endif - -#if ENABLE_NETCORE MonoArrayHandle ves_icall_System_Reflection_RuntimeAssembly_GetExportedTypes (MonoReflectionAssemblyHandle assembly_handle, MonoError *error) { @@ -6525,7 +5879,6 @@ ves_icall_System_Reflection_RuntimeAssembly_GetTopLevelForwardedTypes (MonoRefle return types; } -#endif void ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, MonoBoolean free_struct) @@ -6777,7 +6130,7 @@ ves_icall_Mono_Runtime_DumpStateTotal (guint64 *portable_hash, guint64 *unportab return result; } -#if defined (ENABLE_NETCORE) && defined (ENABLE_METADATA_UPDATE) +#ifdef ENABLE_METADATA_UPDATE void ves_icall_Mono_Runtime_LoadMetadataUpdate (MonoAssembly *assm, gconstpointer dmeta_bytes, int32_t dmeta_len, @@ -6861,14 +6214,6 @@ mono_icall_module_get_hinstance (MonoImage *image) } #endif /* HOST_WIN32 */ -#ifndef ENABLE_NETCORE -gpointer -ves_icall_System_Reflection_RuntimeModule_GetHINSTANCE (MonoImage *image, MonoError *error) -{ - return mono_icall_module_get_hinstance (image); -} -#endif - void ves_icall_System_Reflection_RuntimeModule_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine, MonoError *error) { @@ -7310,11 +6655,7 @@ check_for_invalid_array_type (MonoClass *klass, MonoError *error) static void check_for_invalid_byref_or_pointer_type (MonoClass *klass, MonoError *error) { -#ifdef ENABLE_NETCORE return; -#else - check_for_invalid_array_type (klass, error); -#endif } MonoReflectionTypeHandle @@ -7493,57 +6834,6 @@ mono_array_get_byte_length (MonoArrayHandle array) } } -#ifndef ENABLE_NETCORE -gint32 -ves_icall_System_Buffer_ByteLengthInternal (MonoArrayHandle array, MonoError* error) -{ - return mono_array_get_byte_length (array); -} - -void -ves_icall_System_Buffer_MemcpyInternal (gpointer dest, gconstpointer src, gint32 count) -{ - memcpy (dest, src, count); -} - -MonoBoolean -ves_icall_System_Buffer_BlockCopyInternal (MonoArrayHandle src, gint32 src_offset, MonoArrayHandle dest, gint32 dest_offset, gint32 count, MonoError* error) -{ - if (count < 0) { - mono_error_set_argument (error, "count", "is negative"); - return FALSE; - } - - /* This is called directly from the class libraries without going through the managed wrapper */ - MONO_CHECK_ARG_NULL_HANDLE (src, FALSE); - MONO_CHECK_ARG_NULL_HANDLE (dest, FALSE); - - /* watch out for integer overflow */ - if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count)) - return FALSE; - - MONO_ENTER_NO_SAFEPOINTS; - - guint8 const * const src_buf = (guint8*)MONO_HANDLE_RAW (src)->vector + src_offset; - guint8* const dest_buf = (guint8*)MONO_HANDLE_RAW (dest)->vector + dest_offset; - -#if !HOST_WIN32 - - // Windows memcpy is memmove and checks for overlap anyway, so skip - // the check here that would not help. - - if (MONO_HANDLE_RAW (src) != MONO_HANDLE_RAW (dest)) - memcpy (dest_buf, src_buf, count); - else -#endif - memmove (dest_buf, src_buf, count); /* Source and dest are the same array */ - - MONO_EXIT_NO_SAFEPOINTS; - - return TRUE; -} -#endif - #ifndef DISABLE_REMOTING MonoObjectHandle ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObjectHandle this_obj, MonoStringHandle class_name, MonoError *error) @@ -7597,92 +6887,6 @@ ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxyHandle tp /* System.Environment */ -#ifndef ENABLE_NETCORE -MonoStringHandle -ves_icall_System_Environment_get_UserName (MonoError *error) -{ - /* using glib is more portable */ - const gchar *user_name = g_get_user_name (); - if (user_name != NULL) - return mono_string_new_handle (mono_domain_get (), user_name, error); - else - return NULL_HANDLE_STRING; -} - -#ifndef HOST_WIN32 -static MonoStringHandle -mono_icall_get_machine_name (MonoError *error) -{ -#if !defined(DISABLE_SOCKETS) - MonoStringHandle result; - char *buf; - int n; -#if defined _SC_HOST_NAME_MAX - n = sysconf (_SC_HOST_NAME_MAX); - if (n == -1) -#endif - n = 512; - buf = (char*)g_malloc (n + 1); - -#if defined(HAVE_GETHOSTNAME) - if (gethostname (buf, n) == 0){ - buf [n] = 0; - int i; - // try truncating the string at the first dot - for (i = 0; i < n; i++) { - if (buf [i] == '.') { - buf [i] = 0; - break; - } - } - result = mono_string_new_handle (mono_domain_get (), buf, error); - } else -#endif - result = MONO_HANDLE_CAST (MonoString, NULL_HANDLE); - - g_free (buf); - - return result; -#else - return mono_string_new_handle (mono_domain_get (), "mono", error); -#endif -} -#endif /* !HOST_WIN32 */ - -MonoStringHandle -ves_icall_System_Environment_get_MachineName (MonoError *error) -{ - return mono_icall_get_machine_name (error); -} - -#ifndef HOST_WIN32 -static int -mono_icall_get_platform (void) -{ -#if defined(__MACH__) - /* OSX */ - // - // Notice that the value is hidden from user code, and only exposed - // to mscorlib. This is due to Mono's Unix/MacOS code predating the - // define and making assumptions based on Unix/128/4 values before there - // was a MacOS define. Lots of code would assume that not-Unix meant - // Windows, but in this case, it would be OSX. - // - return 6; -#else - /* Unix */ - return 4; -#endif -} -#endif /* !HOST_WIN32 */ - -int -ves_icall_System_Environment_get_Platform (void) -{ - return mono_icall_get_platform (); -} -#endif /* !ENABLE_NETCORE */ - #ifndef HOST_WIN32 static MonoStringHandle mono_icall_get_new_line (MonoError *error) @@ -7691,14 +6895,6 @@ mono_icall_get_new_line (MonoError *error) } #endif /* !HOST_WIN32 */ -#ifndef ENABLE_NETCORE -MonoStringHandle -ves_icall_System_Environment_get_NewLine (MonoError *error) -{ - return mono_icall_get_new_line (error); -} -#endif - #ifndef HOST_WIN32 static inline MonoBoolean mono_icall_is_64bit_os (void) @@ -7824,39 +7020,6 @@ ves_icall_System_Environment_GetEnvironmentVariableNames (MonoError *error) return mono_icall_get_environment_variable_names (error); } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Environment_InternalSetEnvironmentVariable (const gunichar2 *name, gint32 name_length, - const gunichar2 *value, gint32 value_length, MonoError *error) -{ -#ifdef HOST_WIN32 - if (!value || !value_length || !value [0]) - value = NULL; - - SetEnvironmentVariableW (name, value); -#else - char *utf8_name = NULL; - char *utf8_value = NULL; - - utf8_name = mono_utf16_to_utf8 (name, name_length, error); // FIXME: this should be ascii - goto_if_nok (error, exit); - - if (!value || !value_length || !value [0]) { - g_unsetenv (utf8_name); - goto exit; - } - - utf8_value = mono_utf16_to_utf8 (value, value_length, error); - goto_if_nok (error, exit); - - g_setenv (utf8_name, utf8_value, TRUE); -exit: - g_free (utf8_name); - g_free (utf8_value); -#endif -} -#endif - void ves_icall_System_Environment_Exit (int result) { @@ -7865,11 +7028,6 @@ ves_icall_System_Environment_Exit (int result) if (!mono_runtime_try_shutdown ()) mono_thread_exit (); -#ifndef ENABLE_NETCORE - /* Suspend all managed threads since the runtime is going away */ - mono_thread_suspend_all_other_threads (); -#endif - mono_runtime_quit_internal (); /* we may need to do some cleanup here... */ @@ -7904,14 +7062,6 @@ ves_icall_System_Environment_FailFast (MonoStringHandle message, MonoExceptionHa abort (); } -#ifndef ENABLE_NETCORE -MonoStringHandle -ves_icall_System_Environment_GetGacPath (MonoError *error) -{ - return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error); -} -#endif - #ifndef HOST_WIN32 static inline MonoStringHandle mono_icall_get_windows_folder_path (int folder, MonoError *error) @@ -7922,14 +7072,6 @@ mono_icall_get_windows_folder_path (int folder, MonoError *error) } #endif /* !HOST_WIN32 */ -#ifndef ENABLE_NETCORE -MonoStringHandle -ves_icall_System_Environment_GetWindowsFolderPath (int folder, MonoError *error) -{ - return mono_icall_get_windows_folder_path (folder, error); -} -#endif - static MonoArrayHandle mono_icall_get_logical_drives (MonoError *error) { @@ -7994,133 +7136,12 @@ leave: return result; } -#ifndef ENABLE_NETCORE -MonoArrayHandle -ves_icall_System_Environment_GetLogicalDrivesInternal (MonoError *error) -{ - return mono_icall_get_logical_drives (error); -} - -guint32 -ves_icall_System_IO_DriveInfo_GetDriveType (const gunichar2 *root_path_name, gint32 root_path_name_length, MonoError *error) -{ - return mono_w32file_get_drive_type (root_path_name, root_path_name_length, error); -} - -MonoStringHandle -ves_icall_System_IO_DriveInfo_GetDriveFormat (const gunichar2 *path, gint32 path_length, MonoError *error) -{ - gunichar2 volume_name [MAX_PATH + 1]; - - if (mono_w32file_get_file_system_type (path, volume_name, MAX_PATH + 1) == FALSE) - return NULL_HANDLE_STRING; - return mono_string_new_utf16_handle (mono_domain_get (), volume_name, g_utf16_len (volume_name), error); -} - -MonoStringHandle -ves_icall_System_Environment_InternalGetHome (MonoError *error) -{ - const gchar *home_dir = g_get_home_dir (); - if (home_dir != NULL) - return mono_string_new_handle (mono_domain_get (), home_dir, error); - else - return NULL_HANDLE_STRING; -} - -static const char * const encodings [] = { - (char *) 1, - "ascii", "us_ascii", "us", "ansi_x3.4_1968", - "ansi_x3.4_1986", "cp367", "csascii", "ibm367", - "iso_ir_6", "iso646_us", "iso_646.irv:1991", - (char *) 2, - "utf_7", "csunicode11utf7", "unicode_1_1_utf_7", - "unicode_2_0_utf_7", "x_unicode_1_1_utf_7", - "x_unicode_2_0_utf_7", - (char *) 3, - "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8", - "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8", - (char *) 4, - "utf_16", "UTF_16LE", "ucs_2", "unicode", - "iso_10646_ucs2", - (char *) 5, - "unicodefffe", "utf_16be", - (char *) 6, - "iso_8859_1", - (char *) 0 -}; - -/* - * Returns the internal codepage, if the value of "int_code_page" is - * 1 at entry, and we can not compute a suitable code page number, - * returns the code page as a string - */ -MonoStringHandle -ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page, MonoError *error) -{ - error_init (error); - const char *cset; - const char *p; - char *c; - char *codepage = NULL; - int code; - int want_name = *int_code_page; - int i; - - *int_code_page = -1; - - g_get_charset (&cset); - c = codepage = g_strdup (cset); - for (c = codepage; *c; c++){ - if (isascii (*c) && isalpha (*c)) - *c = tolower (*c); - if (*c == '-') - *c = '_'; - } - /* g_print ("charset: %s\n", cset); */ - - /* handle some common aliases */ - p = encodings [0]; - code = 0; - for (i = 0; p != 0; ){ - if ((gsize) p < 7){ - code = (gssize) p; - p = encodings [++i]; - continue; - } - if (strcmp (p, codepage) == 0){ - *int_code_page = code; - break; - } - p = encodings [++i]; - } - - if (strstr (codepage, "utf_8") != NULL) - *int_code_page |= 0x10000000; - g_free (codepage); - - if (want_name && *int_code_page == -1) - return mono_string_new_handle (mono_domain_get (), cset, error); - return NULL_HANDLE_STRING; -} -#endif - MonoBoolean ves_icall_System_Environment_get_HasShutdownStarted (void) { return mono_runtime_is_shutting_down () || mono_domain_is_unloading (mono_domain_get ()); } -#ifndef HOST_WIN32 - -#ifndef ENABLE_NETCORE -void -ves_icall_System_Environment_BroadcastSettingChange (MonoError *error) -{ -} -#endif - -#endif - gint32 ves_icall_System_Environment_get_TickCount (void) { @@ -8128,21 +7149,11 @@ ves_icall_System_Environment_get_TickCount (void) return (gint32) (mono_msec_boottime () & 0xffffffff); } -#if ENABLE_NETCORE gint64 ves_icall_System_Environment_get_TickCount64 (void) { return mono_msec_boottime (); } -#endif - -#ifndef ENABLE_NETCORE -gint32 -ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (MonoError *error) -{ - return 9; -} -#endif #ifndef DISABLE_REMOTING MonoBoolean @@ -8224,127 +7235,7 @@ ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (Mo mono_vtable_set_is_remote (vtable, enable); } - -#else /* DISABLE_REMOTING */ - -#ifndef ENABLE_NETCORE -void -ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error) -{ - g_assert_not_reached (); -} -#endif - -#endif - -#ifndef ENABLE_NETCORE -MonoObjectHandle -ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionTypeHandle type, MonoError *error) -{ - MonoDomain *domain = MONO_HANDLE_DOMAIN (type); - MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type)); - mono_class_init_checked (klass, error); - return_val_if_nok (error, NULL_HANDLE); - - if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || mono_class_is_abstract (klass)) { - mono_error_set_argument (error, "type", "Type cannot be instantiated"); - return NULL_HANDLE; - } - - if (m_class_get_rank (klass) >= 1) { - g_assert (m_class_get_rank (klass) == 1); - return MONO_HANDLE_CAST (MonoObject, mono_array_new_handle (domain, m_class_get_element_class (klass), 0, error)); - } else { - MonoVTable *vtable = mono_class_vtable_checked (domain, klass, error); - return_val_if_nok (error, NULL_HANDLE); - - /* Bypass remoting object creation check */ - return MONO_HANDLE_NEW (MonoObject, mono_object_new_alloc_specific_checked (vtable, error)); - } -} - -MonoStringHandle -ves_icall_System_IO_get_temp_path (MonoError *error) -{ - return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error); -} - -#if defined(ENABLE_MONODROID) || defined(ENABLE_MONOTOUCH) || defined(TARGET_WASM) - -// FIXME? Names should start "mono"? -G_EXTERN_C gpointer CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data); -G_EXTERN_C gint32 CloseZStream (gpointer stream); -G_EXTERN_C gint32 Flush (gpointer stream); -G_EXTERN_C gint32 ReadZStream (gpointer stream, gpointer buffer, gint32 length); -G_EXTERN_C gint32 WriteZStream (gpointer stream, gpointer buffer, gint32 length); - -gpointer -ves_icall_System_IO_Compression_DeflateStreamNative_CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data) -{ -#ifdef MONO_CROSS_COMPILE - return NULL; -#else - return CreateZStream (compress, gzip, feeder, data); #endif -} - -gint32 -ves_icall_System_IO_Compression_DeflateStreamNative_CloseZStream (gpointer stream) -{ -#ifdef MONO_CROSS_COMPILE - return 0; -#else - return CloseZStream (stream); -#endif -} - -gint32 -ves_icall_System_IO_Compression_DeflateStreamNative_Flush (gpointer stream) -{ -#ifdef MONO_CROSS_COMPILE - return 0; -#else - return Flush (stream); -#endif -} - -gint32 -ves_icall_System_IO_Compression_DeflateStreamNative_ReadZStream (gpointer stream, gpointer buffer, gint32 length) -{ -#ifdef MONO_CROSS_COMPILE - return 0; -#else - return ReadZStream (stream, buffer, length); -#endif -} - -gint32 -ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream (gpointer stream, gpointer buffer, gint32 length) -{ -#ifdef MONO_CROSS_COMPILE - return 0; -#else - return WriteZStream (stream, buffer, length); -#endif -} - -#endif - -#if defined(TARGET_WASM) -G_EXTERN_C void mono_timezone_get_local_name (MonoString **result); -void -ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name (MonoString **result) -{ - // MONO_CROSS_COMPILE returns undefined symbol "_mono_timezone_get_local_name" - // The icall offsets will be generated and linked at build time - // This is defined outside the runtime within the webassembly sdk -#ifndef MONO_CROSS_COMPILE - return mono_timezone_get_local_name (result); -#endif -} -#endif - -#endif /* ENABLE_NETCORE */ #ifndef PLATFORM_NO_DRIVEINFO MonoBoolean @@ -8378,153 +7269,6 @@ ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method, MonoError return mono_compile_method_checked (method, error); } -#ifndef ENABLE_NETCORE - -MonoStringHandle -ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (MonoError *error) -{ - gchar *path; - - const char *mono_cfg_dir = mono_get_config_dir (); - if (!mono_cfg_dir) - return mono_string_new_handle (mono_domain_get (), "", error); - - path = g_build_path (G_DIR_SEPARATOR_S, mono_cfg_dir, "mono", mono_get_runtime_info ()->framework_version, "machine.config", (const char*)NULL); - - mono_icall_make_platform_path (path); - - MonoStringHandle mcpath = mono_string_new_handle (mono_domain_get (), path, error); - g_free (path); - - mono_error_assert_ok (error); - - return mcpath; -} - -MonoStringHandle -ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_app_config (MonoError *error) -{ - const gchar *app_config; - MonoDomain *domain; - gchar *config_file_name, *config_file_path; - gsize len, config_file_path_length, config_ext_length; - gchar *module; - - domain = mono_domain_get (); - MonoStringHandle file = MONO_HANDLE_NEW (MonoString, domain->setup->configuration_file); - if (MONO_HANDLE_IS_NULL (file) || MONO_HANDLE_GETVAL (file, length) == 0) - return MONO_HANDLE_CAST (MonoString, mono_new_null ()); - - // Retrieve config file and remove the extension - config_file_name = mono_string_handle_to_utf8 (file, error); - return_val_if_nok (error, MONO_HANDLE_CAST (MonoString, NULL_HANDLE)); - - config_file_path = mono_portability_find_file (config_file_name, TRUE); - if (!config_file_path) - config_file_path = config_file_name; - - config_file_path_length = strlen (config_file_path); - config_ext_length = strlen (".config"); - if (config_file_path_length <= config_ext_length) { - if (config_file_name != config_file_path) - g_free (config_file_name); - return MONO_HANDLE_CAST (MonoString, NULL_HANDLE); - } - - len = config_file_path_length - config_ext_length; - module = (gchar *)g_malloc0 (len + 1); - memcpy (module, config_file_path, len); - // Get the config file from the module name - app_config = mono_config_string_for_assembly_file (module); - // Clean-up - g_free (module); - if (config_file_name != config_file_path) - g_free (config_file_name); - g_free (config_file_path); - - if (!app_config) - return MONO_HANDLE_CAST (MonoString, NULL_HANDLE); - - return mono_string_new_handle (mono_domain_get (), app_config, error); -} - -static MonoStringHandle -get_bundled_machine_config (MonoError *error) -{ - const gchar *machine_config; - - machine_config = mono_get_machine_config (); - - if (!machine_config) - return NULL_HANDLE_STRING; - - return mono_string_new_handle (mono_domain_get (), machine_config, error); -} - -MonoStringHandle -ves_icall_System_Environment_get_bundled_machine_config (MonoError *error) -{ - return get_bundled_machine_config (error); -} - -MonoStringHandle -ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error) -{ - return get_bundled_machine_config (error); -} - -MonoStringHandle -ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error) -{ - return get_bundled_machine_config (error); -} - -MonoStringHandle -ves_icall_System_Web_Util_ICalls_get_machine_install_dir (MonoError *error) -{ - const char *mono_cfg_dir = mono_get_config_dir (); - if (!mono_cfg_dir) - return mono_string_new_handle (mono_domain_get (), "", error); - - char *path = g_path_get_dirname (mono_cfg_dir); - - mono_icall_make_platform_path (path); - - MonoStringHandle ipath = mono_string_new_handle (mono_domain_get (), path, error); - g_free (path); - - return ipath; -} - -MonoBoolean -ves_icall_get_resources_ptr (MonoReflectionAssemblyHandle assembly, gpointer *result, gint32 *size, MonoError *error) -{ - MonoPEResourceDataEntry *entry; - MonoImage *image; - - if (MONO_HANDLE_IS_NULL (assembly) || !result || !size) - return FALSE; - - *result = NULL; - *size = 0; - MonoAssembly *assm = MONO_HANDLE_GETVAL (assembly, assembly); - image = assm->image; - entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL); - if (!entry) - return FALSE; - - *result = mono_image_rva_map (image, entry->rde_data_offset); - if (!(*result)) { - g_free (entry); - return FALSE; - } - *size = entry->rde_size; - g_free (entry); - return TRUE; -} - -#endif /* ENABLE_NETCORE */ - MonoBoolean ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void) { @@ -8553,14 +7297,6 @@ mono_icall_write_windows_debug_string (const gunichar2 *message) } #endif /* !HOST_WIN32 */ -#ifndef ENABLE_NETCORE -void -ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (const gunichar2 *message, MonoError *error) -{ - mono_icall_write_windows_debug_string (message); -} -#endif - /* Only used for value types */ MonoObjectHandle ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionTypeHandle ref_type, MonoError *error) @@ -8763,49 +7499,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethodHa prelink_method (MONO_HANDLE_GETVAL (method, method), error); } -void -ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error); - -void -ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error) -{ - g_assert_not_netcore (); - - error_init (error); - MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type)); - MonoMethod* m; - gpointer iter = NULL; - - mono_class_init_checked (klass, error); - return_if_nok (error); - - while ((m = mono_class_get_methods (klass, &iter))) { - prelink_method (m, error); - return_if_nok (error); - } -} - -#ifndef ENABLE_NETCORE -/* - * used by System.Runtime.InteropServices.RuntimeInformation.(OS|Process)Architecture; - * which use them in different ways for filling in an enum - */ -MonoStringHandle -ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetRuntimeArchitecture (MonoError *error) -{ - return mono_string_new_handle (mono_domain_get (), mono_config_get_cpu (), error); -} - -/* - * used by System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform - */ -MonoStringHandle -ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetOSName (MonoError *error) -{ - return mono_string_new_handle (mono_domain_get (), mono_config_get_os (), error); -} -#endif /* ENABLE_NETCORE */ - int ves_icall_Interop_Sys_DoubleToString(double value, char *format, char *buffer, int bufferLength) { @@ -9088,30 +7781,6 @@ mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds) } #endif /* !HOST_WIN32 */ -#ifndef ENABLE_NETCORE -gint32 -ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds) -{ - return mono_icall_wait_for_input_idle (handle, milliseconds); -} - -gint32 -ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void) -{ - return mono_process_current_pid (); -} - -MonoBoolean -ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void) -{ -#if HAVE_BTLS - return TRUE; -#else - return FALSE; -#endif -} -#endif /* ENABLE_NETCORE */ - #ifndef DISABLE_COM int @@ -9178,16 +7847,6 @@ ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_Wind #endif -#if !ENABLE_NETCORE - -void -ves_icall_System_IO_LogcatTextWriter_Log (const char *appname, gint32 level, const char *message) -{ - g_log (appname, (GLogLevelFlags)level, "%s", message); -} - -#endif - static const MonoIcallTableCallbacks *icall_table; static mono_mutex_t icall_mutex; static GHashTable *icall_hash = NULL; @@ -9769,13 +8428,11 @@ ves_icall_System_GC_GetAllocatedBytesForCurrentThread (void) return mono_gc_get_allocated_bytes_for_current_thread (); } -#ifdef ENABLE_NETCORE guint64 ves_icall_System_GC_GetTotalAllocatedBytes (MonoBoolean precise, MonoError* error) { return mono_gc_get_total_allocated_bytes (precise); } -#endif void ves_icall_System_GC_RecordPressure (gint64 value) @@ -9820,34 +8477,6 @@ ves_icall_System_Environment_get_ProcessorCount (void) return mono_cpu_count (); } -#if !defined(ENABLE_NETCORE) -#if defined(ENABLE_MONODROID) - -G_EXTERN_C gpointer CreateNLSocket (void); -G_EXTERN_C gint32 ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size); -G_EXTERN_C gpointer CloseNLSocket (gpointer sock); - -gpointer -ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CreateNLSocket (void) -{ - return CreateNLSocket (); -} - -gint32 -ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size) -{ - return ReadEvents (sock, buffer, count, size); -} - -gpointer -ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket (gpointer sock) -{ - return CloseNLSocket (sock); -} - -#endif -#endif - // Generate wrappers. #define ICALL_TYPE(id,name,first) /* nothing */ diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index 757324e..2f57765 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -260,10 +260,6 @@ mono_images_init (void) images_storage_hash = g_hash_table_new (g_str_hash, g_str_equal); -#ifndef ENABLE_NETCORE - mono_loaded_images_init (mono_get_global_loaded_images (), NULL); -#endif - debug_assembly_unload = g_hasenv ("MONO_DEBUG_ASSEMBLY_UNLOAD"); install_pe_loader (); @@ -281,10 +277,6 @@ mono_images_cleanup (void) { mono_os_mutex_destroy (&images_mutex); -#ifndef ENABLE_NETCORE - mono_loaded_images_cleanup (mono_get_global_loaded_images (), TRUE); -#endif - g_hash_table_destroy (images_storage_hash); mono_os_mutex_destroy (&images_storage_mutex); @@ -715,22 +707,6 @@ mono_image_check_for_module_cctor (MonoImage *image) image->checked_module_cctor = TRUE; } -#ifndef ENABLE_NETCORE -static void -load_modules (MonoImage *image) -{ - MonoTableInfo *t; - - if (image->modules) - return; - - t = &image->tables [MONO_TABLE_MODULEREF]; - image->modules = g_new0 (MonoImage *, t->rows); - image->modules_loaded = g_new0 (gboolean, t->rows); - image->module_count = t->rows; -} -#endif - /** * mono_image_load_module_checked: * @@ -747,81 +723,8 @@ mono_image_load_module_checked (MonoImage *image, int idx, MonoError *error) if (image->modules_loaded [idx - 1]) return image->modules [idx - 1]; -#ifdef ENABLE_NETCORE /* SRE still uses image->modules, but they are not loaded from files, so the rest of this function is dead code for netcore */ g_assert_not_reached (); -#else - MonoTableInfo *t; - MonoTableInfo *file_table; - int i; - char *base_dir; - gboolean refonly = image->ref_only; - GList *list_iter, *valid_modules = NULL; - MonoImageOpenStatus status; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Loading module %d of %s (%s)", idx, image->assembly ? image->assembly->aname.name : "some assembly", image->name); - - file_table = &image->tables [MONO_TABLE_FILE]; - for (i = 0; i < file_table->rows; i++) { - guint32 cols [MONO_FILE_SIZE]; - mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE); - if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA) - continue; - valid_modules = g_list_prepend (valid_modules, (char*)mono_metadata_string_heap (image, cols [MONO_FILE_NAME])); - } - - t = &image->tables [MONO_TABLE_MODULEREF]; - base_dir = g_path_get_dirname (image->name); - - { - char *module_ref; - const char *name; - guint32 cols [MONO_MODULEREF_SIZE]; - /* if there is no file table, we try to load the module... */ - int valid = file_table->rows == 0; - - mono_metadata_decode_row (t, idx - 1, cols, MONO_MODULEREF_SIZE); - name = mono_metadata_string_heap (image, cols [MONO_MODULEREF_NAME]); - for (list_iter = valid_modules; list_iter; list_iter = list_iter->next) { - /* be safe with string dups, but we could just compare string indexes */ - if (strcmp ((const char*)list_iter->data, name) == 0) { - valid = TRUE; - break; - } - } - if (valid) { - MonoAssemblyLoadContext *alc = mono_image_get_alc (image); - MonoLoadedImages *li = mono_image_get_loaded_images_for_modules (image); - module_ref = g_build_filename (base_dir, name, (const char*)NULL); - MonoImage *moduleImage = mono_image_open_a_lot_parameterized (li, alc, module_ref, &status, refonly, FALSE, NULL); - if (moduleImage) { - if (!assign_assembly_parent_for_netmodule (moduleImage, image, error)) { - mono_image_close (moduleImage); - g_free (module_ref); - g_free (base_dir); - g_list_free (valid_modules); - return NULL; - } - - image->modules [idx - 1] = moduleImage; - -#ifdef HOST_WIN32 - if (m_image_is_module_handle (image->modules [idx - 1])) - mono_image_fixup_vtable (image->modules [idx - 1]); -#endif - /* g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly); */ - } - g_free (module_ref); - } - } - - image->modules_loaded [idx - 1] = TRUE; - - g_free (base_dir); - g_list_free (valid_modules); - - return image->modules [idx - 1]; -#endif } /** @@ -1565,10 +1468,6 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status, mono_image_load_time_date_stamp (image); -#ifndef ENABLE_NETCORE - load_modules (image); -#endif - done: MONO_PROFILER_RAISE (image_loaded, (image)); if (status) @@ -1795,9 +1694,7 @@ do_mono_image_open (MonoAssemblyLoadContext *alc, const char *fname, MonoImageOp image->ref_count = 1; /* if MONO_SECURITY_MODE_CORE_CLR is set then determine if this image is platform code */ image->core_clr_platform_code = mono_security_core_clr_determine_platform_image (image); -#ifdef ENABLE_NETCORE image->alc = alc; -#endif return do_mono_image_load (image, status, care_about_cli, care_about_pecoff); } @@ -1907,20 +1804,8 @@ mono_image_loaded_by_guid_full (const char *guid, gboolean refonly) static MonoImage * mono_image_loaded_by_guid_internal (const char *guid, gboolean refonly) { -#ifndef ENABLE_NETCORE - GuidData data; - GHashTable *loaded_images = mono_loaded_images_get_hash (mono_get_global_loaded_images (), refonly); - data.res = NULL; - data.guid = guid; - - mono_images_lock (); - g_hash_table_foreach (loaded_images, find_by_guid, &data); - mono_images_unlock (); - return data.res; -#else /* TODO: Maybe implement this for netcore by searching only the default ALC of the current domain */ return NULL; -#endif } /** @@ -1967,13 +1852,11 @@ register_image (MonoLoadedImages *li, MonoImage *image, gboolean *problematic) { MonoImage *image2; char *name = image->name; -#ifdef ENABLE_NETCORE /* Since we register cultures by file name, we need to make this culture aware for satellite assemblies */ char *name_with_culture = mono_image_get_name_with_culture_if_needed (image); if (name_with_culture) name = name_with_culture; -#endif GHashTable *loaded_images = mono_loaded_images_get_hash (li, image->ref_only); mono_images_lock (); @@ -1984,9 +1867,7 @@ register_image (MonoLoadedImages *li, MonoImage *image, gboolean *problematic) mono_image_addref (image2); mono_images_unlock (); mono_image_close (image); -#ifdef ENABLE_NETCORE g_free (name_with_culture); -#endif return image2; } @@ -2001,9 +1882,7 @@ register_image (MonoLoadedImages *li, MonoImage *image, gboolean *problematic) if (problematic) *problematic = TRUE; } -#ifdef ENABLE_NETCORE g_free (name_with_culture); -#endif return image; } @@ -2041,9 +1920,7 @@ mono_image_open_from_data_internal (MonoAssemblyLoadContext *alc, char *data, gu image->ref_only = refonly; image->metadata_only = metadata_only; image->ref_count = 1; -#ifdef ENABLE_NETCORE image->alc = alc; -#endif image = do_mono_image_load (image, status, TRUE, TRUE); if (image == NULL) @@ -2057,11 +1934,8 @@ mono_image_open_from_data_alc (MonoAssemblyLoadContextGCHandle alc_gchandle, cha { MonoImage *result; MONO_ENTER_GC_UNSAFE; -#ifdef ENABLE_NETCORE MonoAssemblyLoadContext *alc = mono_alc_from_gchandle (alc_gchandle); -#else - MonoAssemblyLoadContext *alc = mono_domain_default_alc (mono_domain_get ()); -#endif + result = mono_image_open_from_data_internal (alc, data, data_len, need_copy, status, FALSE, FALSE, name, name); MONO_EXIT_GC_UNSAFE; return result; @@ -2152,9 +2026,7 @@ mono_image_open_from_module_handle (MonoAssemblyLoadContext *alc, HMODULE module image->name = fname; image->filename = g_strdup (image->name); image->ref_count = has_entry_point ? 0 : 1; -#ifdef ENABLE_NETCORE image->alc = alc; -#endif image = do_mono_image_load (image, status, TRUE, TRUE); if (image == NULL) @@ -2690,9 +2562,6 @@ mono_image_close_except_pools (MonoImage *image) if (image->mvar_gparam_cache) mono_conc_hashtable_destroy (image->mvar_gparam_cache); free_hash (image->wrapper_param_names); -#ifndef ENABLE_NETCORE - free_hash (image->pinvoke_scopes); -#endif free_hash (image->native_func_wrapper_cache); mono_conc_hashtable_destroy (image->typespec_cache); free_hash (image->weak_field_indexes); diff --git a/src/mono/mono/metadata/loaded-images-global.c b/src/mono/mono/metadata/loaded-images-global.c deleted file mode 100644 index 645b0cd..0000000 --- a/src/mono/mono/metadata/loaded-images-global.c +++ /dev/null @@ -1,65 +0,0 @@ -#include - -#include "mono/metadata/loaded-images-internals.h" -#include "mono/metadata/metadata-internals.h" - -#ifndef ENABLE_NETCORE -/* Global image hashes should not be in netcore Mono */ - -static MonoLoadedImages global_loaded_images; /* zero initalized is good enough */ - -MonoLoadedImages* -mono_get_global_loaded_images (void) -{ - return &global_loaded_images; -} - -// This is support for the mempool reference tracking feature in checked-build, -// but lives in loaded-images-global.c due to use of static variables of this -// file. - -/** - * mono_find_image_owner: - * - * Find the image, if any, which a given pointer is located in the memory of. - */ -MonoImage * -mono_find_image_owner (void *ptr) -{ - MonoLoadedImages *li = mono_get_global_loaded_images (); - mono_images_lock (); - - MonoImage *owner = NULL; - - // Iterate over both by-path image hashes - const int hash_candidates[] = {MONO_LOADED_IMAGES_HASH_PATH, MONO_LOADED_IMAGES_HASH_PATH_REFONLY}; - int hash_idx; - for (hash_idx = 0; !owner && hash_idx < G_N_ELEMENTS (hash_candidates); hash_idx++) - { - GHashTable *target = li->loaded_images_hashes [hash_candidates [hash_idx]]; - GHashTableIter iter; - MonoImage *image; - - // Iterate over images within a hash - g_hash_table_iter_init (&iter, target); - while (!owner && g_hash_table_iter_next(&iter, NULL, (gpointer *)&image)) - { - mono_image_lock (image); - if (mono_mempool_contains_addr (image->mempool, ptr)) - owner = image; - mono_image_unlock (image); - } - } - - mono_images_unlock (); - - return owner; -} - -MonoLoadedImages * -mono_alc_get_loaded_images (MonoAssemblyLoadContext *alc) -{ - return mono_get_global_loaded_images (); -} - -#endif /* ENABLE_NETCORE */ diff --git a/src/mono/mono/metadata/loaded-images-internals.h b/src/mono/mono/metadata/loaded-images-internals.h index 7eb2b28..c6cbd7a 100644 --- a/src/mono/mono/metadata/loaded-images-internals.h +++ b/src/mono/mono/metadata/loaded-images-internals.h @@ -50,11 +50,6 @@ mono_loaded_images_remove_image (MonoImage *image); MonoLoadedImages* mono_image_get_loaded_images_for_modules (MonoImage *image); -#ifndef ENABLE_NETCORE -MonoLoadedImages* -mono_get_global_loaded_images (void); -#endif - MonoImage * mono_find_image_owner (void *ptr); diff --git a/src/mono/mono/metadata/loaded-images-netcore.c b/src/mono/mono/metadata/loaded-images-netcore.c deleted file mode 100644 index 3d15afd..0000000 --- a/src/mono/mono/metadata/loaded-images-netcore.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "config.h" - -#include "mono/metadata/loaded-images-internals.h" - -#ifdef ENABLE_NETCORE -/* Should be compiling loaded-images-netcore.c only for netcore Mono */ - -// This is support for the mempool reference tracking feature in checked-build, -// but lives in loaded-images-netcore.c due to use of static variables of this -// file. - -/** - * mono_find_image_owner: - * - * Find the image, if any, which a given pointer is located in the memory of. - */ -MonoImage * -mono_find_image_owner (void *ptr) -{ - /* FIXME: this function is a bit annoying to implement without a global - * table of all the loaded images. We need to traverse all the domains - * and each ALC in each domain. */ - return NULL; -} - -MonoLoadedImages * -mono_alc_get_loaded_images (MonoAssemblyLoadContext *alc) -{ - g_assert (alc); - g_assert (alc->loaded_images); - return alc->loaded_images; -} - -#else - -MONO_EMPTY_SOURCE_FILE (loaded_images_netcore); - -#endif /* ENABLE_NETCORE */ diff --git a/src/mono/mono/metadata/loaded-images.c b/src/mono/mono/metadata/loaded-images.c index c0fa0d5..b370425 100644 --- a/src/mono/mono/metadata/loaded-images.c +++ b/src/mono/mono/metadata/loaded-images.c @@ -104,11 +104,11 @@ mono_loaded_images_remove_image (MonoImage *image) loaded_images_by_name = mono_loaded_images_get_by_name_hash (li, image->ref_only); name = image->name; -#ifdef ENABLE_NETCORE + char *name_with_culture = mono_image_get_name_with_culture_if_needed (image); if (name_with_culture) name = name_with_culture; -#endif + image2 = (MonoImage *)g_hash_table_lookup (loaded_images, name); if (image == image2) { /* This is not true if we are called from mono_image_open () */ @@ -118,9 +118,9 @@ mono_loaded_images_remove_image (MonoImage *image) g_hash_table_remove (loaded_images_by_name, (char *) image->assembly_name); proceed = TRUE; -#ifdef ENABLE_NETCORE + g_free (name_with_culture); -#endif + done: mono_images_unlock (); @@ -131,9 +131,28 @@ done: MonoLoadedImages* mono_image_get_loaded_images_for_modules (MonoImage *image) { -#ifndef ENABLE_NETCORE - return mono_get_global_loaded_images (); -#else g_assert_not_reached (); -#endif } + +/** + * mono_find_image_owner: + * + * Find the image, if any, which a given pointer is located in the memory of. + */ +MonoImage * +mono_find_image_owner (void *ptr) +{ + /* FIXME: this function is a bit annoying to implement without a global + * table of all the loaded images. We need to traverse all the domains + * and each ALC in each domain. */ + return NULL; +} + +MonoLoadedImages * +mono_alc_get_loaded_images (MonoAssemblyLoadContext *alc) +{ + g_assert (alc); + g_assert (alc->loaded_images); + return alc->loaded_images; +} + diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index e0d67f2..c58f4ed 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -17,7 +17,6 @@ #include #include -#ifdef ENABLE_NETCORE #if defined(TARGET_OSX) #define MONO_LOADER_LIBRARY_NAME "libcoreclr.dylib" #elif defined(TARGET_ANDROID) @@ -25,7 +24,6 @@ #else #define MONO_LOADER_LIBRARY_NAME "libcoreclr.so" #endif -#endif G_BEGIN_DECLS @@ -33,9 +31,7 @@ typedef struct _MonoLoadedImages MonoLoadedImages; typedef struct _MonoAssemblyLoadContext MonoAssemblyLoadContext; typedef struct _MonoMemoryManager MonoMemoryManager; typedef struct _MonoSingletonMemoryManager MonoSingletonMemoryManager; -#ifdef ENABLE_NETCORE typedef struct _MonoGenericMemoryManager MonoGenericMemoryManager; -#endif struct _MonoBundledSatelliteAssembly { const char *name; @@ -55,7 +51,6 @@ struct _MonoDllMap { }; #endif -#ifdef ENABLE_NETCORE struct _MonoAssemblyLoadContext { MonoDomain *domain; MonoLoadedImages *loaded_images; @@ -79,7 +74,6 @@ struct _MonoAssemblyLoadContext { // Maps malloc-ed char* pinvoke scope -> MonoDl* GHashTable *pinvoke_scopes; }; -#endif /* ENABLE_NETCORE */ struct _MonoMemoryManager { MonoDomain *domain; @@ -117,7 +111,6 @@ struct _MonoSingletonMemoryManager { MonoAssemblyLoadContext *alc; }; -#ifdef ENABLE_NETCORE struct _MonoGenericMemoryManager { MonoMemoryManager memory_manager; @@ -125,7 +118,6 @@ struct _MonoGenericMemoryManager { int n_alcs; MonoAssemblyLoadContext **alcs; }; -#endif void mono_global_loader_data_lock (void); @@ -150,7 +142,6 @@ mono_global_loader_cache_init (void); void mono_global_loader_cache_cleanup (void); -#ifdef ENABLE_NETCORE void mono_set_pinvoke_search_directories (int dir_count, char **dirs); @@ -186,16 +177,11 @@ mono_alc_invoke_resolve_using_resolve_satellite_nofail (MonoAssemblyLoadContext MonoAssemblyLoadContext * mono_alc_from_gchandle (MonoGCHandle alc_gchandle); -#endif /* ENABLE_NETCORE */ static inline MonoDomain * mono_alc_domain (MonoAssemblyLoadContext *alc) { -#ifdef ENABLE_NETCORE return alc->domain; -#else - return mono_domain_get (); -#endif } MonoLoadedImages * diff --git a/src/mono/mono/metadata/locales.h b/src/mono/mono/metadata/locales.h deleted file mode 100644 index 8746cf9..0000000 --- a/src/mono/mono/metadata/locales.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * \file - * Culture-sensitive handling - * - * Authors: - * Dick Porter (dick@ximian.com) - * - * (C) 2003 Ximian, Inc. - */ - -#ifndef _MONO_METADATA_LOCALES_H_ -#define _MONO_METADATA_LOCALES_H_ - -#include - -#include -#include - -#if !ENABLE_NETCORE - -/* This is a copy of System.Globalization.CompareOptions */ -typedef enum { - CompareOptions_None=0x00, - CompareOptions_IgnoreCase=0x01, - CompareOptions_IgnoreNonSpace=0x02, - CompareOptions_IgnoreSymbols=0x04, - CompareOptions_IgnoreKanaType=0x08, - CompareOptions_IgnoreWidth=0x10, - CompareOptions_StringSort=0x20000000, - CompareOptions_Ordinal=0x40000000 -} MonoCompareOptions; - -typedef struct NumberFormatEntryManaged NumberFormatEntryManaged; - -ICALL_EXPORT -gconstpointer -ves_icall_System_Globalization_CultureData_fill_number_data (gint32 number_index, NumberFormatEntryManaged *managed); - -ICALL_EXPORT -void ves_icall_System_Globalization_CultureInfo_construct_internal_locale (MonoCultureInfo *this_obj, MonoString *locale); - -ICALL_EXPORT -void ves_icall_System_Globalization_CompareInfo_construct_compareinfo (MonoCompareInfo *comp, MonoString *locale); - -ICALL_EXPORT gint32 -ves_icall_System_Globalization_CompareInfo_internal_compare (const gunichar2 *str1, gint32 len1, - const gunichar2 *str2, gint32 len2, gint32 options); - -ICALL_EXPORT -void ves_icall_System_Globalization_CompareInfo_free_internal_collator (MonoCompareInfo *this_obj); - -ICALL_EXPORT gint32 -ves_icall_System_Globalization_CompareInfo_internal_index (const gunichar2 *source, gint32 sindex, - gint32 count, const gunichar2 *value, gint32 value_length, MonoBoolean first); - -#endif /* !ENABLE_NETCORE */ - -#define MONO_LOCALE_INVARIANT (0x007F) - -#endif /* _MONO_METADATA_FILEIO_H_ */ diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c index b72a45c..ae8b2b7 100644 --- a/src/mono/mono/metadata/marshal-ilgen.c +++ b/src/mono/mono/metadata/marshal-ilgen.c @@ -35,7 +35,6 @@ #include "mono/metadata/cominterop.h" #include "mono/metadata/remoting.h" #include "mono/metadata/reflection-internals.h" -#include "mono/metadata/threadpool.h" #include "mono/metadata/handle.h" #include "mono/metadata/custom-attrs-internals.h" #include "mono/metadata/icall-internals.h" @@ -1645,13 +1644,11 @@ handle_enum: if (sig->ret->byref) { /* perform indirect load and return by value */ -#ifdef ENABLE_NETCORE int pos; mono_mb_emit_byte (mb, CEE_DUP); pos = mono_mb_emit_branch (mb, CEE_BRTRUE); mono_mb_emit_exception_full (mb, "Mono", "NullByRefReturnException", NULL); mono_mb_patch_branch (mb, pos); -#endif int ldind_op; MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); @@ -2061,7 +2058,6 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi if (need_gc_safe) gc_safe_transition_builder_add_locals (&gc_safe_transition_builder); -#ifdef ENABLE_NETCORE if (!func && !aot && !func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass)) { /* * On netcore, its possible to register pinvoke resolvers at runtime, so @@ -2094,7 +2090,6 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_stloc (mb, func_addr_local); } -#endif /* * cookie = mono_threads_enter_gc_safe_region_unbalanced (ref dummy); @@ -6513,11 +6508,7 @@ emit_create_string_hack_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *csig, { int i; -#ifdef ENABLE_NETCORE g_assert (!mono_method_signature_internal (res)->hasthis); -#else - mono_mb_emit_byte (mb, CEE_LDARG_0); -#endif for (i = 1; i <= csig->param_count; i++) mono_mb_emit_ldarg (mb, i); mono_mb_emit_managed_call (mb, res, NULL); diff --git a/src/mono/mono/metadata/marshal-windows.c b/src/mono/mono/metadata/marshal-windows.c index 1220048..eaefc8f 100644 --- a/src/mono/mono/metadata/marshal-windows.c +++ b/src/mono/mono/metadata/marshal-windows.c @@ -77,38 +77,6 @@ mono_marshal_realloc_co_task_mem (gpointer ptr, size_t size) return CoTaskMemRealloc (ptr, size); } -char* -ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (const gunichar2 *s, int length); - -char* -ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (const gunichar2 *s, int length) -{ - g_assert_not_netcore (); - - // FIXME pass mono_utf16_to_utf8 an allocator to avoid double alloc/copy. - - ERROR_DECL (error); - size_t len = 0; - char* ret = NULL; - char* tres = mono_utf16_to_utf8 (s, length, error); - if (!tres || !is_ok (error)) - goto exit; - - /* - * mono_utf16_to_utf8() returns a memory area at least as large as length, - * even if it contains NULL characters. The copy we allocate here has to be equally - * large. - */ - len = MAX (strlen (tres) + 1, length); - ret = (char*)mono_marshal_alloc_hglobal_error (len, error); - if (ret) - memcpy (ret, tres, len); -exit: - g_free (tres); - mono_error_set_pending_exception (error); - return ret; -} - gpointer mono_string_to_utf8str_impl (MonoStringHandle s, MonoError *error) { diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 3c3ea52..2fd585b 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -44,7 +44,6 @@ #include "mono/metadata/cominterop.h" #include "mono/metadata/remoting.h" #include "mono/metadata/reflection-internals.h" -#include "mono/metadata/threadpool.h" #include "mono/metadata/handle.h" #include "mono/metadata/object-internals.h" #include "mono/metadata/custom-attrs-internals.h" @@ -111,10 +110,8 @@ delegate_hash_table_remove (MonoDelegate *d); GENERATE_TRY_GET_CLASS_WITH_CACHE (stringbuilder, "System.Text", "StringBuilder"); static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); -#ifdef ENABLE_NETCORE 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") -#endif static gboolean type_is_blittable (MonoType *type); @@ -1230,75 +1227,8 @@ handle_enum: MonoAsyncResult * mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params) { -#ifdef ENABLE_NETCORE mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib, "System", "PlatformNotSupportedException")); return NULL; -#else - ERROR_DECL (error); - MonoMulticastDelegate *mcast_delegate; - MonoClass *klass; - MonoMethod *method; - - g_assert (delegate); - mcast_delegate = (MonoMulticastDelegate *) delegate; - if (mcast_delegate->delegates != NULL) { - mono_error_set_argument (error, NULL, "The delegate must have only one target"); - mono_error_set_pending_exception (error); - return NULL; - } - -#ifndef DISABLE_REMOTING - if (delegate->target && mono_object_is_transparent_proxy (delegate->target)) { - MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target; - if (!mono_class_is_contextbound (tp->remote_class->proxy_class) || tp->rp->context != (MonoObject *) mono_context_get ()) { - /* If the target is a proxy, make a direct call. Is proxy's work - // to make the call asynchronous. - */ - MonoMethodMessage *msg; - MonoDelegate *async_callback; - MonoObject *state; - MonoAsyncResult *ares; - MonoObject *exc; - MonoArray *out_args; - method = delegate->method; - - msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state, error); - if (mono_error_set_pending_exception (error)) - return NULL; - ares = mono_async_result_new (mono_domain_get (), NULL, state, NULL, NULL, error); - if (mono_error_set_pending_exception (error)) - return NULL; - MONO_OBJECT_SETREF_INTERNAL (ares, async_delegate, (MonoObject *)delegate); - MONO_OBJECT_SETREF_INTERNAL (ares, async_callback, (MonoObject *)async_callback); - MONO_OBJECT_SETREF_INTERNAL (msg, async_result, ares); - msg->call_type = CallType_BeginInvoke; - - exc = NULL; - mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, error); - if (!is_ok (error)) { - mono_error_set_pending_exception (error); - return NULL; - } - if (exc) - mono_set_pending_exception ((MonoException *) exc); - return ares; - } - } -#endif - - klass = delegate->object.vtable->klass; - - ERROR_DECL (begin_invoke_error); - method = mono_get_delegate_begin_invoke_checked (klass, begin_invoke_error); - mono_error_cleanup (begin_invoke_error); /* if we can't call BeginInvoke, fall back on Invoke */ - if (!method) - method = mono_get_delegate_invoke_internal (klass); - g_assert (method); - - MonoAsyncResult *result = mono_threadpool_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, error); - mono_error_set_pending_exception (error); - return result; -#endif } static char* @@ -1945,110 +1875,8 @@ mono_marshal_get_delegate_begin_invoke (MonoMethod *method) MonoObject * mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) { -#ifdef ENABLE_NETCORE mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib, "System", "PlatformNotSupportedException")); return NULL; -#else - ERROR_DECL (error); - MonoDomain *domain = mono_domain_get (); - MonoAsyncResult *ares; - MonoMethod *method = NULL; - MonoMethodSignature *sig; - MonoMethodMessage *msg; - MonoObject *res, *exc; - MonoArray *out_args; - MonoClass *klass; - - g_assert (delegate); - - if (!delegate->method_info) { - g_assert (delegate->method); - MonoReflectionMethod *rm = mono_method_get_object_checked (domain, delegate->method, NULL, error); - if (!is_ok (error)) { - mono_error_set_pending_exception (error); - return NULL; - } - MONO_OBJECT_SETREF_INTERNAL (delegate, method_info, rm); - } - - if (!delegate->method_info || !delegate->method_info->method) - g_assert_not_reached (); - - klass = delegate->object.vtable->klass; - - method = mono_get_delegate_end_invoke_checked (klass, error); - mono_error_assert_ok (error); - g_assert (method != NULL); - - sig = mono_signature_no_pinvoke (method); - - msg = mono_method_call_message_new (method, params, NULL, NULL, NULL, error); - if (mono_error_set_pending_exception (error)) - return NULL; - - ares = (MonoAsyncResult *)mono_array_get_internal (msg->args, gpointer, sig->param_count - 1); - if (ares == NULL) { - mono_error_set_remoting (error, "The async result object is null or of an unexpected type."); - mono_error_set_pending_exception (error); - return NULL; - } - - if (ares->async_delegate != (MonoObject*)delegate) { - mono_error_set_invalid_operation (error, - "%s", "The IAsyncResult object provided does not match this delegate."); - mono_error_set_pending_exception (error); - return NULL; - } - -#ifndef DISABLE_REMOTING - if (delegate->target && mono_object_is_transparent_proxy (delegate->target)) { - MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target; - msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error); - if (!is_ok (error)) { - mono_error_set_pending_exception (error); - return NULL; - } - mono_message_init (domain, msg, delegate->method_info, NULL, error); - if (mono_error_set_pending_exception (error)) - return NULL; - msg->call_type = CallType_EndInvoke; - MONO_OBJECT_SETREF_INTERNAL (msg, async_result, ares); - res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args, error); - if (!is_ok (error)) { - mono_error_set_pending_exception (error); - return NULL; - } - } else -#endif - { - res = mono_threadpool_end_invoke (ares, &out_args, &exc, error); - if (mono_error_set_pending_exception (error)) - return NULL; - } - - if (exc) { - if (((MonoException*)exc)->stack_trace) { - ERROR_DECL (inner_error); - char *strace = mono_string_to_utf8_checked_internal (((MonoException*)exc)->stack_trace, inner_error); - if (is_ok (inner_error)) { - char *tmp; - tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace); - g_free (strace); - MonoString *tmp_str = mono_string_new_checked (domain, tmp, inner_error); - g_free (tmp); - if (is_ok (inner_error)) - MONO_OBJECT_SETREF_INTERNAL (((MonoException*)exc), stack_trace, tmp_str); - }; - if (!is_ok (inner_error)) - mono_error_cleanup (inner_error); /* no stack trace, but at least throw the original exception */ - } - mono_set_pending_exception ((MonoException*)exc); - } - - mono_method_return_message_restore (method, params, out_args, error); - mono_error_set_pending_exception (error); - return res; -#endif } /** @@ -3357,7 +3185,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, csig->pinvoke = 0; res = NULL; -#ifdef ENABLE_NETCORE iter = NULL; while ((m = mono_class_get_methods (mono_defaults.string_class, &iter))) { /* @@ -3379,16 +3206,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, } } } -#else - iter = NULL; - while ((m = mono_class_get_methods (mono_defaults.string_class, &iter))) { - if (!strcmp ("CreateString", m->name) && - mono_metadata_signature_equal (csig, mono_method_signature_internal (m))) { - res = m; - break; - } - } -#endif + g_assert (res); WrapperInfo *info; @@ -3436,12 +3254,8 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, * In AOT mode and embedding scenarios, it is possible that the icall is not * registered in the runtime doing the AOT compilation. */ -#ifdef ENABLE_NETCORE /* Handled at runtime */ pinvoke_not_found = !pinvoke && !piinfo->addr && !aot; -#else - pinvoke_not_found = !piinfo->addr && !aot; -#endif if (pinvoke_not_found) { /* if there's no code but the error isn't set, just use a fairly generic exception. */ if (is_ok (emitted_error)) @@ -3496,7 +3310,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1); mono_method_get_marshal_info (method, mspecs); -#ifdef ENABLE_NETCORE if (mono_class_try_get_suppress_gc_transition_attribute_class ()) { MonoCustomAttrInfo *cinfo; ERROR_DECL (error); @@ -3518,7 +3331,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, if (cinfo && !cinfo->cached) mono_custom_attrs_free (cinfo); } -#endif MonoNativeWrapperFlags flags = aot ? EMIT_NATIVE_WRAPPER_AOT : (MonoNativeWrapperFlags)0; flags |= check_exceptions ? EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS : (MonoNativeWrapperFlags)0; @@ -5034,110 +4846,6 @@ copy_managed_common (MonoArrayHandle managed, gconstpointer native, gint32 start return element_size * length; } -void -ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArrayHandle src, gint32 start_index, - gpointer dest, gint32 length, gconstpointer managed_source_addr, MonoError *error); - -void -ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArrayHandle src, gint32 start_index, - gpointer dest, gint32 length, gconstpointer managed_source_addr, MonoError *error) -{ - g_assert_not_netcore (); - - if (length != 0) { - MonoGCHandle gchandle = 0; - gsize const bytes = copy_managed_common (src, dest, start_index, length, (gpointer*)&managed_source_addr, &gchandle, error); - if (bytes) - memmove (dest, managed_source_addr, bytes); // no references should be involved - mono_gchandle_free_internal (gchandle); - } -} - -void -ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gconstpointer src, gint32 start_index, - MonoArrayHandle dest, gint32 length, gpointer managed_dest_addr, MonoError *error); - -void -ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gconstpointer src, gint32 start_index, - MonoArrayHandle dest, gint32 length, gpointer managed_dest_addr, MonoError *error) -{ - g_assert_not_netcore (); - - if (length != 0) { - MonoGCHandle gchandle = 0; - gsize const bytes = copy_managed_common (dest, src, start_index, length, &managed_dest_addr, &gchandle, error); - if (bytes) - memmove (managed_dest_addr, src, bytes); // no references should be involved - mono_gchandle_free_internal (gchandle); - } -} - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (const char *ptr, MonoError *error); - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (const char *ptr, MonoError *error) -{ - g_assert_not_netcore (); - - if (!ptr) - return NULL_HANDLE_STRING; - return mono_string_new_handle (mono_domain_get (), ptr, error); -} - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (const char *ptr, gint32 len, MonoError *error); - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (const char *ptr, gint32 len, MonoError *error) -{ - g_assert_not_netcore (); - - if (!ptr) { - mono_error_set_argument_null (error, "ptr", ""); - return NULL_HANDLE_STRING; - } - return mono_string_new_utf8_len (mono_domain_get (), ptr, len, error); -} - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (const gunichar2 *ptr, MonoError *error); - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (const gunichar2 *ptr, MonoError *error) -{ - g_assert_not_netcore (); - - gsize len = 0; - const gunichar2 *t = ptr; - - if (!ptr) - return NULL_HANDLE_STRING; - - while (*t++) - len++; - - MonoStringHandle res = mono_string_new_utf16_handle (mono_domain_get (), ptr, len, error); - return_val_if_nok (error, NULL_HANDLE_STRING); - - return res; -} - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (const gunichar2 *ptr, gint32 len, MonoError *error); - -MonoStringHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (const gunichar2 *ptr, gint32 len, MonoError *error) -{ - g_assert_not_netcore (); - - if (!ptr) { - mono_error_set_argument_null (error, "ptr", ""); - return NULL_HANDLE_STRING; - } - return mono_string_new_utf16_handle (mono_domain_get (), ptr, len, error); -} - guint32 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void) { @@ -5190,7 +4898,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObjectHandl MONO_CHECK_ARG_NULL_HANDLE_NAMED (obj, "structure",); MONO_CHECK_ARG_NULL_NAMED (dst, "ptr",); -#ifdef ENABLE_NETCORE MonoClass *klass = mono_handle_class (obj); if (m_class_is_auto_layout (klass)) { mono_error_set_argument (error, "structure", "The specified structure must be blittable or have layout information."); @@ -5200,7 +4907,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObjectHandl mono_error_set_argument (error, "structure", "The specified object must not be an instance of a generic type."); return; } -#endif MonoMethod *method = mono_marshal_get_struct_to_ptr (mono_handle_class (obj)); @@ -5220,8 +4926,6 @@ ptr_to_structure (gconstpointer src, MonoObjectHandle dst, MonoError *error) mono_runtime_invoke_checked (method, NULL, pa, error); } -#ifdef ENABLE_NETCORE - void ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructureInternal (gconstpointer src, MonoObjectHandle dst, MonoBoolean allow_vtypes, MonoError *error) { @@ -5243,48 +4947,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructureInternal (gconstp ptr_to_structure (src, dst, error); } -#else - -void -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gconstpointer src, MonoObjectHandle dst, MonoError *error) -{ - MonoType *t; - - MONO_CHECK_ARG_NULL (src,); - MONO_CHECK_ARG_NULL_HANDLE (dst,); - - t = mono_type_get_underlying_type (m_class_get_byval_arg (mono_handle_class (dst))); - - if (t->type == MONO_TYPE_VALUETYPE) { - mono_error_set_argument (error, "dst", "Destination is a boxed value type."); - return; - } - - ptr_to_structure (src, dst, error); -} - -MonoObjectHandle -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gconstpointer src, MonoReflectionTypeHandle type, MonoError *error) -{ - if (src == NULL) - return NULL_HANDLE; - - MONO_CHECK_ARG_NULL_HANDLE (type, NULL_HANDLE); - - MonoClass *klass = mono_class_from_mono_type_handle (type); - if (!mono_class_init_checked (klass, error)) - return NULL_HANDLE; - - MonoObjectHandle res = mono_object_new_handle (mono_domain_get (), klass, error); - return_val_if_nok (error, NULL_HANDLE); - - ptr_to_structure (src, res, error); - return_val_if_nok (error, NULL_HANDLE); - - return res; -} -#endif // !NETCORE - int ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHandle ref_type, MonoStringHandle field_name, MonoError *error) { @@ -5294,20 +4956,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHan return 0; } if (MONO_HANDLE_IS_NULL (field_name)) { -#ifdef ENABLE_NETCORE mono_error_set_argument_null (error, NULL, ""); -#else - mono_error_set_argument_null (error, "fieldName", ""); -#endif return 0; } if (!m_class_is_runtime_type (MONO_HANDLE_GET_CLASS (ref_type))) { -#ifdef ENABLE_NETCORE mono_error_set_argument (error, "fieldName", ""); -#else - mono_error_set_argument (error, "type", ""); -#endif return 0; } @@ -5318,12 +4972,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHan MonoClass *klass = mono_class_from_mono_type_internal (type); if (!mono_class_init_checked (klass, error)) return 0; -#ifdef ENABLE_NETCORE + if (m_class_is_auto_layout (klass)) { mono_error_set_argument (error, NULL, ""); return 0; } -#endif + int match_index = -1; while (klass && match_index == -1) { MonoClassField* field; @@ -5358,56 +5012,13 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHan } #ifndef HOST_WIN32 - -char* -ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (const gunichar2 *utf16, int length); - -char* -ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (const gunichar2 *utf16, int length) -{ - g_assert_not_netcore (); - - ERROR_DECL (error); - - char * const utf8 = mono_utf16_to_utf8 (utf16, length, error); - - mono_error_set_pending_exception (error); - - return utf8; -} - void * mono_marshal_alloc_hglobal (size_t size) { return g_try_malloc (size); } - #endif /* !HOST_WIN32 */ -gunichar2* -ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (const gunichar2 *s, int length); - -gunichar2* -ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (const gunichar2 *s, int length) -{ - g_assert_not_netcore (); - - if (!s) - return NULL; - - ERROR_DECL (error); - - gsize const len = ((gsize)length + 1) * 2; - gunichar2 *res = (gunichar2*)mono_marshal_alloc_hglobal_error (len, error); - if (res) { - memcpy (res, s, length * 2); - res [length] = 0; - } - - mono_error_set_pending_exception (error); - return res; -} - void mono_struct_delete_old (MonoClass *klass, char *ptr) { @@ -5475,14 +5086,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoClass *klass = mono_class_from_mono_type_handle (type); if (!mono_class_init_checked (klass, error)) return; -#ifdef ENABLE_NETCORE + if (m_class_is_auto_layout (klass)) { mono_error_set_argument (error, "structureType", "The specified structure must be blittable or have layout information."); return; } -#endif - mono_struct_delete_old (klass, (char *)src); } @@ -5562,25 +5171,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size) return res; } -void* -ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMemSize (gsize size); - -void* -ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMemSize (gsize size) -{ - g_assert_not_netcore (); - - void *res = mono_marshal_alloc_co_task_mem (size); - - if (!res) { - ERROR_DECL (error); - mono_error_set_out_of_memory (error, ""); - mono_error_set_pending_exception (error); - } - - return res; -} - void ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr) { @@ -5610,15 +5200,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, return res; } -#ifndef ENABLE_NETCORE -gpointer -ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArrayHandle arrayobj, int index, MonoError *error) -{ - int esize = mono_array_element_size (mono_handle_class (arrayobj)); - return mono_array_addr_with_size_fast (MONO_HANDLE_RAW (arrayobj), esize, index); -} -#endif - MonoDelegateHandle ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionTypeHandle type, MonoError *error) { @@ -6005,9 +5586,7 @@ mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align, (mspec && mspec->native == MONO_NATIVE_STRUCT)) { *align = 16; return 16; - } -#ifdef ENABLE_NETCORE - else if (strcmp (m_class_get_name_space (klass), "System") == 0 && + } else if (strcmp (m_class_get_name_space (klass), "System") == 0 && strcmp (m_class_get_name (klass), "Decimal") == 0) { // Special case: Managed Decimal consists of 4 int32 fields, the alignment should be 8 on x64 to follow @@ -6015,7 +5594,6 @@ mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align, *align = MONO_ABI_ALIGNOF (gpointer); return mono_class_native_size (klass, NULL); } -#endif padded_size = mono_class_native_size (klass, align); if (padded_size == 0) padded_size = 1; @@ -6505,9 +6083,6 @@ get_marshal_cb (void) gboolean mono_method_has_unmanaged_callers_only_attribute (MonoMethod *method) { -#ifndef ENABLE_NETCORE - return FALSE; -#else ERROR_DECL (attr_error); MonoClass *attr_klass = NULL; attr_klass = mono_class_try_get_unmanaged_callers_only_attribute_class (); @@ -6524,5 +6099,4 @@ mono_method_has_unmanaged_callers_only_attribute (MonoMethod *method) if (!cinfo->cached) mono_custom_attrs_free (cinfo); return result; -#endif } diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 0e6bf24..e5a1349 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -169,11 +169,7 @@ struct _MonoAssemblyName { uint32_t hash_alg; uint32_t hash_len; uint32_t flags; -#ifdef ENABLE_NETCORE int32_t major, minor, build, revision, arch; -#else - uint16_t major, minor, build, revision, arch; -#endif //Add members for correct work with mono_stringify_assembly_name MonoBoolean without_version; MonoBoolean without_culture; @@ -466,12 +462,10 @@ struct _MonoImage { */ MonoAssembly *assembly; -#ifdef ENABLE_NETCORE /* * The AssemblyLoadContext that this image was loaded into. */ MonoAssemblyLoadContext *alc; -#endif /* * Indexed by method tokens and typedef tokens. @@ -574,11 +568,6 @@ struct _MonoImage { MonoConcurrentHashTable *var_gparam_cache; MonoConcurrentHashTable *mvar_gparam_cache; -#ifndef ENABLE_NETCORE - /* Maps malloc-ed char* pinvoke scope -> MonoDl* */ - GHashTable *pinvoke_scopes; -#endif - /* The loader used to load this image */ MonoImageLoader *loader; @@ -1320,11 +1309,7 @@ static inline MonoAssemblyLoadContext * mono_image_get_alc (MonoImage *image) { -#ifndef ENABLE_NETCORE - return NULL; -#else return image->alc; -#endif } static inline diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index a96d9bb..8790809 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -8016,11 +8016,7 @@ mono_loader_set_strict_assembly_name_check (gboolean enabled) gboolean mono_loader_get_strict_assembly_name_check (void) { -#if !defined(DISABLE_DESKTOP_LOADER) || defined(ENABLE_NETCORE) return check_assembly_names_strictly; -#else - return FALSE; -#endif } diff --git a/src/mono/mono/metadata/monitor.c b/src/mono/mono/metadata/monitor.c index 86a25e9..410f0d6 100644 --- a/src/mono/mono/metadata/monitor.c +++ b/src/mono/mono/metadata/monitor.c @@ -795,9 +795,7 @@ signal_monitor (gpointer mon_untyped) mono_coop_mutex_unlock (mon->entry_mutex); } -#ifdef ENABLE_NETCORE static gint64 thread_contentions; /* for Monitor.LockContentionCount, otherwise mono_perfcounters struct is used */ -#endif /* If allow_interruption==TRUE, the method will be interrupted if abort or suspend * is requested. In this case it returns -1. @@ -856,10 +854,8 @@ retry: #ifndef DISABLE_PERFCOUNTERS mono_atomic_inc_i32 (&mono_perfcounters->thread_contentions); #else -#ifdef ENABLE_NETCORE mono_atomic_inc_i64 (&thread_contentions); #endif -#endif /* If ms is 0 we don't block, but just fail straight away */ if (ms == 0) { @@ -1223,19 +1219,11 @@ mono_monitor_try_enter_loop_if_interrupted (MonoObject *obj, guint32 ms, return res; } -#ifdef ENABLE_NETCORE void ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObjectHandle obj, guint32 ms, MonoBoolean allow_interruption, MonoBoolean* lockTaken, MonoError* error) { mono_monitor_try_enter_loop_if_interrupted (MONO_HANDLE_RAW (obj), ms, allow_interruption, lockTaken, error); } -#else -void -ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObjectHandle obj, guint32 ms, MonoBoolean* lockTaken, MonoError* error) -{ - mono_monitor_try_enter_loop_if_interrupted (MONO_HANDLE_RAW (obj), ms, TRUE, lockTaken, error); -} -#endif /** * mono_monitor_enter_v4: @@ -1493,26 +1481,18 @@ mono_monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_in return success; } -#ifdef ENABLE_NETCORE MonoBoolean ves_icall_System_Threading_Monitor_Monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_interruption, MonoError* error) { return mono_monitor_wait (obj_handle, ms, allow_interruption, error); } -#else -MonoBoolean -ves_icall_System_Threading_Monitor_Monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoError* error) -{ - return mono_monitor_wait (obj_handle, ms, TRUE, error); -} -#endif + void ves_icall_System_Threading_Monitor_Monitor_Enter (MonoObjectHandle obj, MonoError* error) { mono_monitor_enter_internal (MONO_HANDLE_RAW (obj)); } -#ifdef ENABLE_NETCORE gint64 ves_icall_System_Threading_Monitor_Monitor_LockContentionCount (void) { @@ -1522,4 +1502,3 @@ ves_icall_System_Threading_Monitor_Monitor_LockContentionCount (void) return thread_contentions; #endif } -#endif diff --git a/src/mono/mono/metadata/monitor.h b/src/mono/mono/metadata/monitor.h index 6b95a3e..9fe9cc9 100644 --- a/src/mono/mono/metadata/monitor.h +++ b/src/mono/mono/metadata/monitor.h @@ -130,10 +130,8 @@ mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_offset); #define MONO_THREADS_SYNC_MEMBER_OFFSET(o) ((o)>>8) #define MONO_THREADS_SYNC_MEMBER_SIZE(o) ((o)&0xff) -#if ENABLE_NETCORE ICALL_EXPORT gint64 ves_icall_System_Threading_Monitor_Monitor_LockContentionCount (void); -#endif #endif /* _MONO_METADATA_MONITOR_H_ */ diff --git a/src/mono/mono/metadata/mono-mlist.c b/src/mono/mono/metadata/mono-mlist.c index f4389fd..0bd5a92 100644 --- a/src/mono/mono/metadata/mono-mlist.c +++ b/src/mono/mono/metadata/mono-mlist.c @@ -68,11 +68,7 @@ mono_mlist_alloc_checked (MonoObject *data, MonoError *error) error_init (error); MonoMList* res; if (!monolist_item_vtable) { -#ifdef ENABLE_NETCORE MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "Mono", "MonoListItem"); -#else - MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System", "MonoListItem"); -#endif monolist_item_vtable = mono_class_vtable_checked (mono_get_root_domain (), klass, error); mono_error_assert_ok (error); } diff --git a/src/mono/mono/metadata/mono-perfcounters.c b/src/mono/mono/metadata/mono-perfcounters.c index 411ffe6..316e1b3 100644 --- a/src/mono/mono/metadata/mono-perfcounters.c +++ b/src/mono/mono/metadata/mono-perfcounters.c @@ -1822,89 +1822,6 @@ mono_perfcounter_foreach (PerfCounterEnumCallback cb, gpointer data) #else -#ifndef ENABLE_NETCORE - -void* -mono_perfcounter_get_impl (const gunichar2 *category, gint32 category_length, - const gunichar2 *counter, gint32 counter_length, - const gunichar2 *instance, gint32 instance_length, - gint32 *type, MonoBoolean *custom, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoBoolean -mono_perfcounter_get_sample (void *impl, MonoBoolean only_value, MonoCounterSample *sample) -{ - g_assert_not_reached (); -} - -gint64 -mono_perfcounter_update_value (void *impl, MonoBoolean do_incr, gint64 value) -{ - g_assert_not_reached (); -} - -void -mono_perfcounter_free_data (void *impl) -{ - g_assert_not_reached (); -} - -/* Category icalls */ -MonoBoolean -mono_perfcounter_category_del (const gunichar2 *name, gint32 name_length, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoStringHandle -mono_perfcounter_category_help (const gunichar2 *category, gint32 category_length, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoBoolean -mono_perfcounter_category_exists (const gunichar2 *counter, gint32 counter_length, const gunichar2 *category, - gint32 category_length, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoBoolean -mono_perfcounter_create (const gunichar2 *category, gint32 category_length, const gunichar2 *help, - gint32 help_length, gint32 type, MonoArrayHandle items, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoBoolean -mono_perfcounter_instance_exists (const gunichar2 *instance, gint32 instance_length, - const gunichar2 *category, gint32 category_length, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoArrayHandle -mono_perfcounter_category_names (MonoError *error) -{ - g_assert_not_reached (); -} - -MonoArrayHandle -mono_perfcounter_counter_names (const gunichar2 *category, gint32 category_length, MonoError *error) -{ - g_assert_not_reached (); -} - -MonoArrayHandle -mono_perfcounter_instance_names (const gunichar2 *category, gint32 category_length, MonoError *error) -{ - g_assert_not_reached (); -} - -#endif /* ENABLE_NETCORE */ - void mono_perfcounter_foreach (PerfCounterEnumCallback cb, gpointer data) { diff --git a/src/mono/mono/metadata/mono-route.c b/src/mono/mono/metadata/mono-route.c index 2e0bf02..9182d59 100644 --- a/src/mono/mono/metadata/mono-route.c +++ b/src/mono/mono/metadata/mono-route.c @@ -9,166 +9,5 @@ #include "config.h" -#ifndef ENABLE_NETCORE -#if HOST_DARWIN || HOST_BSD - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if HOST_IOS || HOST_WATCHOS || HOST_TVOS -// The iOS SDK does not provide the net/route.h header but using the Darwin version works fine. -#include "../../support/ios/net/route.h" -#else -#include -#endif - -static in_addr_t -gateway_from_rtm (struct rt_msghdr *rtm); - -#include "object.h" -#include "icall-decl.h" - -MonoBoolean -ves_icall_System_Net_NetworkInformation_MacOsIPInterfaceProperties_ParseRouteInfo (MonoStringHandle iface_handle, MonoArrayHandleOut gw_addr_list_handle, MonoError *error) -{ - MonoString *iface = MONO_HANDLE_RAW (iface_handle); - MONO_HANDLE_ASSIGN_RAW (gw_addr_list_handle, NULL); - - size_t needed; - in_addr_t in; - int mib [6]; - int num_gws = 0, gwnum = 0; - unsigned int ifindex = 0; - char *buf = NULL; - char *next, *lim; - char *ifacename = NULL; - struct rt_msghdr *rtm; - MonoArray *gw_addr_list = NULL; - MonoStringHandle addr_string_handle = NULL_HANDLE_INIT; // FIXME probably overkill - MonoDomain *domain = mono_domain_get (); - MonoBoolean result = FALSE; - - ifacename = mono_string_to_utf8_checked_internal (iface, error); - goto_if_nok (error, fail); - - if ((ifindex = if_nametoindex (ifacename)) == 0) - goto fail; - - // MIB array defining data to read from sysctl - mib [0] = CTL_NET; // Networking - mib [1] = PF_ROUTE; // Routing messages - mib [2] = 0; // Protocol number (always zero) - mib [3] = AF_INET; // Address family (IPv4) - mib [4] = NET_RT_DUMP; // Dump routing table - mib [5] = 0; // - - // First sysctl call with oldp set to NULL to determine size of available data - if (sysctl(mib, G_N_ELEMENTS(mib), NULL, &needed, NULL, 0) < 0) - goto fail; - - // Allocate suffcient memory for available data based on the previous sysctl call - if ((buf = g_malloc (needed)) == NULL) - goto fail; - - // Second sysctl call to retrieve data into appropriately sized buffer - if (sysctl (mib, G_N_ELEMENTS (mib), buf, &needed, NULL, 0) < 0) - goto fail; - - lim = buf + needed; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; - if (rtm->rtm_version != RTM_VERSION - || rtm->rtm_index != ifindex - || (in = gateway_from_rtm (rtm)) == 0) - continue; - num_gws++; - } - - gw_addr_list = mono_array_new_checked (domain, mono_get_string_class (), num_gws, error); - goto_if_nok (error, leave); - - MONO_HANDLE_ASSIGN_RAW (gw_addr_list_handle, gw_addr_list); - - addr_string_handle = MONO_HANDLE_NEW (MonoString, NULL); // FIXME probably overkill - - for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; - if (rtm->rtm_version != RTM_VERSION - || rtm->rtm_index != ifindex - || (in = gateway_from_rtm (rtm)) == 0) - continue; - - MonoString *addr_string; - char addr [16], *ptr; - int len; - - ptr = (char *) ∈ - len = snprintf(addr, sizeof (addr), "%u.%u.%u.%u", - (unsigned char) ptr [0], - (unsigned char) ptr [1], - (unsigned char) ptr [2], - (unsigned char) ptr [3]); - - if (len >= sizeof (addr) || len < 0) - // snprintf output truncated - continue; - - addr_string = mono_string_new_checked (domain, addr, error); - goto_if_nok (error, leave); - MONO_HANDLE_ASSIGN_RAW (addr_string_handle, addr_string); // FIXME probably overkill - mono_array_setref_internal (gw_addr_list, gwnum, addr_string); - gwnum++; - } -leave: - result = is_ok (error); -fail: - g_free (ifacename); - g_free (buf); - return result; -} - -static in_addr_t -gateway_from_rtm(struct rt_msghdr *rtm) -{ - struct sockaddr *gw; - unsigned int l; - - struct sockaddr *addr = (struct sockaddr *)(rtm + 1); - l = roundup(addr->sa_len, sizeof(long)); \ - gw = (struct sockaddr *)((char *) addr + l); \ - - if (rtm->rtm_addrs & RTA_GATEWAY) { - if(gw->sa_family == AF_INET) { - struct sockaddr_in *sockin = (struct sockaddr_in *)gw; - return(sockin->sin_addr.s_addr); - } - } - - return 0; -} - -#else - -#include "object.h" -#include "icall-decl.h" - -MonoBoolean -ves_icall_System_Net_NetworkInformation_MacOsIPInterfaceProperties_ParseRouteInfo (MonoStringHandle iface_handle, MonoArrayHandleOut gw_addr_list_handle, MonoError *error) -{ - mono_error_set_not_implemented (error, ""); - return FALSE; -} - -#endif - -#endif - extern const char mono_route_empty_file_no_warning; const char mono_route_empty_file_no_warning = 0; diff --git a/src/mono/mono/metadata/mono-security.c b/src/mono/mono/metadata/mono-security.c deleted file mode 100644 index b360d82..0000000 --- a/src/mono/mono/metadata/mono-security.c +++ /dev/null @@ -1,675 +0,0 @@ -/** - * \file - * Security internal calls - * - * Author: - * Sebastien Pouliot - * - * Copyright 2004-2009 Novell, Inc (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "reflection-internals.h" -#include "icall-decl.h" - -#ifndef ENABLE_NETCORE - -#ifndef HOST_WIN32 -#ifdef HAVE_GRP_H -#include -#endif -#ifdef HAVE_PWD_H -#include -#endif -#include -#include -#include -#include -#include "icall-decl.h" - -/* Disclaimers */ - -#if defined(__GNUC__) - -#ifdef HAVE_GRP_H -#ifndef HAVE_GETGRGID_R - #warning Non-thread safe getgrgid being used! -#endif -#ifndef HAVE_GETGRNAM_R - #warning Non-thread safe getgrnam being used! -#endif -#endif - -#ifdef HAVE_PWD_H -#ifndef HAVE_GETPWNAM_R - #warning Non-thread safe getpwnam being used! -#endif -#ifndef HAVE_GETPWUID_R - #warning Non-thread safe getpwuid being used! -#endif -#endif -#endif /* defined(__GNUC__) */ -#endif /* !HOST_WIN32 */ - -/* internal functions - reuse driven */ - -/* ask a server to translate a SID into a textual representation */ -#ifndef HOST_WIN32 -#define MONO_SYSCONF_DEFAULT_SIZE ((size_t) 1024) - -/* - * Ensure we always get a valid (usable) value from sysconf. - * In case of error, we return the default value. - */ -static size_t mono_sysconf (int name) -{ -#ifdef HAVE_SYSCONF - size_t size = (size_t) sysconf (name); - /* default value */ - return (size == -1) ? MONO_SYSCONF_DEFAULT_SIZE : size; -#else - return MONO_SYSCONF_DEFAULT_SIZE; -#endif -} - -static gchar* -GetTokenName (uid_t uid) -{ - gchar *uname = NULL; - -#ifdef HAVE_PWD_H - -#ifdef HAVE_GETPWUID_R - struct passwd pwd; - size_t fbufsize; - gchar *fbuf; - gint32 retval; -#endif - struct passwd *p = NULL; - gboolean result; - -#ifdef HAVE_GETPWUID_R -#ifdef _SC_GETPW_R_SIZE_MAX - fbufsize = mono_sysconf (_SC_GETPW_R_SIZE_MAX); -#else - fbufsize = MONO_SYSCONF_DEFAULT_SIZE; -#endif - fbuf = (gchar *)g_malloc0 (fbufsize); - retval = getpwuid_r (uid, &pwd, fbuf, fbufsize, &p); - result = ((retval == 0) && (p == &pwd)); -#else - /* default to non thread-safe but posix compliant function */ - p = getpwuid (uid); - result = (p != NULL); -#endif - - if (result) { - uname = g_strdup (p->pw_name); - } - -#ifdef HAVE_GETPWUID_R - g_free (fbuf); -#endif - -#endif /* HAVE_PWD_H */ - - return uname; -} - -#ifdef HAVE_GRP_H - -static gboolean -IsMemberInList (uid_t user, struct group *g) -{ - gboolean result = FALSE; - gchar *utf8_username = GetTokenName (user); - - if (!utf8_username) - return FALSE; - - if (g) { - gchar **users = g->gr_mem; - - while (*users) { - gchar *u = *(users); - if (strcmp (utf8_username, u) == 0) { - result = TRUE; - break; - } - users++; - } - } - - g_free (utf8_username); - return result; -} - -#endif /* HAVE_GRP_H */ - -static gboolean -IsDefaultGroup (uid_t user, gid_t group) -{ - gboolean result = FALSE; - -#ifdef HAVE_PWD_H - -#ifdef HAVE_GETPWUID_R - struct passwd pwd; - size_t fbufsize; - gchar *fbuf; - gint32 retval; -#endif - struct passwd *p = NULL; - -#ifdef HAVE_GETPWUID_R -#ifdef _SC_GETPW_R_SIZE_MAX - fbufsize = mono_sysconf (_SC_GETPW_R_SIZE_MAX); -#else - fbufsize = MONO_SYSCONF_DEFAULT_SIZE; -#endif - - fbuf = (gchar *)g_malloc0 (fbufsize); - retval = getpwuid_r (user, &pwd, fbuf, fbufsize, &p); - result = ((retval == 0) && (p == &pwd)); -#else - /* default to non thread-safe but posix compliant function */ - p = getpwuid (user); - result = (p != NULL); -#endif - - if (result) { - result = (p->pw_gid == group); - } - -#ifdef HAVE_GETPWUID_R - g_free (fbuf); -#endif - -#endif /* HAVE_PWD_H */ - - return result; -} - -#ifdef HAVE_GRP_H - -static gboolean -IsMemberOf (gid_t user, struct group *g) -{ - if (!g) - return FALSE; - - /* is it the user default group */ - if (IsDefaultGroup (user, g->gr_gid)) - return TRUE; - - /* is the user in the group list */ - return IsMemberInList (user, g); -} - -#endif /* HAVE_GRP_H */ - -#endif /* !HOST_WIN32 */ - -/* ICALLS */ - -/* System.Security.Principal.WindowsIdentity */ - -#ifndef HOST_WIN32 -gpointer -mono_security_principal_windows_identity_get_current_token (MonoError *error) -{ - return GINT_TO_POINTER (geteuid ()); -} - -gpointer -ves_icall_System_Security_Principal_WindowsIdentity_GetCurrentToken (MonoError *error) -{ - return mono_security_principal_windows_identity_get_current_token (error); -} - -static gint32 -internal_get_token_name (gpointer token, gunichar2 ** uniname) -{ - gint32 size = 0; - - gchar *uname = GetTokenName ((uid_t) GPOINTER_TO_INT (token)); - - if (uname) { - size = strlen (uname); - *uniname = g_utf8_to_utf16 (uname, size, NULL, NULL, NULL); - g_free (uname); - } - - return size; -} - -MonoStringHandle -ves_icall_System_Security_Principal_WindowsIdentity_GetTokenName (gpointer token, MonoError *error) -{ - MonoStringHandle result; - gunichar2 *uniname = NULL; - gint32 size = 0; - - error_init (error); - - size = internal_get_token_name (token, &uniname); - - if (size > 0) { - result = mono_string_new_utf16_handle (mono_domain_get (), uniname, size, error); - } - else - result = mono_string_new_handle (mono_domain_get (), "", error); - - if (uniname) - g_free (uniname); - - return result; -} -#endif /* !HOST_WIN32 */ - -#ifndef HOST_WIN32 -gpointer -ves_icall_System_Security_Principal_WindowsIdentity_GetUserToken (MonoStringHandle username, MonoError *error) -{ - gpointer token = (gpointer)-2; - - error_init (error); -#if defined (HAVE_PWD_H) && !defined (HOST_WASM) - -#ifdef HAVE_GETPWNAM_R - struct passwd pwd; - size_t fbufsize; - gchar *fbuf; - gint32 retval; -#endif - struct passwd *p; - gchar *utf8_name; - gboolean result; - - utf8_name = mono_string_handle_to_utf8 (username, error); - return_val_if_nok (error, NULL); - -#ifdef HAVE_GETPWNAM_R -#ifdef _SC_GETPW_R_SIZE_MAX - fbufsize = mono_sysconf (_SC_GETPW_R_SIZE_MAX); -#else - fbufsize = MONO_SYSCONF_DEFAULT_SIZE; -#endif - - fbuf = (gchar *)g_malloc0 (fbufsize); - retval = getpwnam_r (utf8_name, &pwd, fbuf, fbufsize, &p); - result = ((retval == 0) && (p == &pwd)); -#else - /* default to non thread-safe but posix compliant function */ - p = getpwnam (utf8_name); - result = (p != NULL); -#endif - - if (result) { - token = GINT_TO_POINTER (p->pw_uid); - } - -#ifdef HAVE_GETPWNAM_R - g_free (fbuf); -#endif - g_free (utf8_name); - -#endif /* HAVE_PWD_H */ - - return token; -} -#endif /* HOST_WIN32 */ - -/* http://www.dotnet247.com/247reference/msgs/39/195403.aspx -// internal static string[] WindowsIdentity._GetRoles (IntPtr token) -*/ - -#ifndef HOST_WIN32 -MonoArrayHandle -ves_icall_System_Security_Principal_WindowsIdentity_GetRoles (gpointer token, MonoError *error) -{ - MonoDomain *domain = mono_domain_get (); - - /* POSIX-compliant systems should use IsMemberOfGroupId or IsMemberOfGroupName */ - g_warning ("WindowsIdentity._GetRoles should never be called on POSIX"); - - return mono_array_new_handle (domain, mono_get_string_class (), 0, error); -} -#endif /* !HOST_WIN32 */ - -/* System.Security.Principal.WindowsImpersonationContext */ - -#ifndef HOST_WIN32 -MonoBoolean -ves_icall_System_Security_Principal_WindowsImpersonationContext_CloseToken (gpointer token, MonoError *error) -{ - return TRUE; -} -#endif /* !HOST_WIN32 */ - -#ifndef HOST_WIN32 -gpointer -ves_icall_System_Security_Principal_WindowsImpersonationContext_DuplicateToken (gpointer token, MonoError *error) -{ - return token; -} -#endif /* !HOST_WIN32 */ - -#if HAVE_API_SUPPORT_WIN32_SECURITY -MonoBoolean -ves_icall_System_Security_Principal_WindowsImpersonationContext_SetCurrentToken (gpointer token, MonoError *error) -{ -#ifdef HOST_WIN32 - return (ImpersonateLoggedOnUser (token) != 0); -#else - uid_t itoken = (uid_t) GPOINTER_TO_INT (token); -#ifdef HAVE_SETRESUID - if (setresuid (-1, itoken, getuid ()) < 0) - return FALSE; -#endif - return geteuid () == itoken; -#endif -} - -MonoBoolean -ves_icall_System_Security_Principal_WindowsImpersonationContext_RevertToSelf (MonoError *error) -{ -#ifdef HOST_WIN32 - return (RevertToSelf () != 0); -#else -#ifdef HAVE_GETRESUID - uid_t ruid, euid; -#endif - uid_t suid = -1; - -#ifdef HAVE_GETRESUID - if (getresuid (&ruid, &euid, &suid) < 0) - return FALSE; -#endif -#ifdef HAVE_SETRESUID - if (setresuid (-1, suid, -1) < 0) - return FALSE; -#else - return TRUE; -#endif - return geteuid () == suid; -#endif -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SECURITY -MonoBoolean -ves_icall_System_Security_Principal_WindowsImpersonationContext_SetCurrentToken (gpointer token, MonoError *error) -{ - g_unsupported_api ("ImpersonateLoggedOnUser"); - mono_error_set_not_supported (error, G_UNSUPPORTED_API, "ImpersonateLoggedOnUser"); - SetLastError (ERROR_NOT_SUPPORTED); - return FALSE; -} - -MonoBoolean -ves_icall_System_Security_Principal_WindowsImpersonationContext_RevertToSelf (MonoError *error) -{ - g_unsupported_api ("RevertToSelf"); - mono_error_set_not_supported (error, G_UNSUPPORTED_API, "RevertToSelf"); - SetLastError (ERROR_NOT_SUPPORTED); - return FALSE; -} -#endif /* HAVE_API_SUPPORT_WIN32_SECURITY */ - -/* System.Security.Principal.WindowsPrincipal */ - -#ifndef HOST_WIN32 -MonoBoolean -ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupId (gpointer user, gpointer group, MonoError *error) -{ - gboolean result = FALSE; - -#ifdef HAVE_GRP_H - -#ifdef HAVE_GETGRGID_R - struct group grp; - size_t fbufsize; - gchar *fbuf; - gint32 retval; -#endif - struct group *g = NULL; - -#ifdef HAVE_GETGRGID_R -#ifdef _SC_GETGR_R_SIZE_MAX - fbufsize = mono_sysconf (_SC_GETGR_R_SIZE_MAX); -#else - fbufsize = MONO_SYSCONF_DEFAULT_SIZE; -#endif - fbuf = (gchar *)g_malloc0 (fbufsize); - retval = getgrgid_r ((gid_t) GPOINTER_TO_INT (group), &grp, fbuf, fbufsize, &g); - result = ((retval == 0) && (g == &grp)); -#else - /* default to non thread-safe but posix compliant function */ - g = getgrgid ((gid_t) GPOINTER_TO_INT (group)); - result = (g != NULL); -#endif - - if (result) - result = IsMemberOf ((uid_t) GPOINTER_TO_INT (user), g); - -#ifdef HAVE_GETGRGID_R - g_free (fbuf); -#endif - -#endif /* HAVE_GRP_H */ - - return result; -} - -MonoBoolean -ves_icall_System_Security_Principal_WindowsPrincipal_IsMemberOfGroupName (gpointer user, const gchar *utf8_groupname, MonoError *error) -{ - gboolean result = FALSE; - -#ifdef HAVE_GRP_H - - if (utf8_groupname) { - struct group *g = NULL; -#ifdef HAVE_GETGRNAM_R - struct group grp; - gchar *fbuf; - gint32 retval; -#ifdef _SC_GETGR_R_SIZE_MAX - size_t fbufsize = mono_sysconf (_SC_GETGR_R_SIZE_MAX); -#else - size_t fbufsize = MONO_SYSCONF_DEFAULT_SIZE; -#endif - fbuf = (gchar *)g_malloc0 (fbufsize); - retval = getgrnam_r (utf8_groupname, &grp, fbuf, fbufsize, &g); - result = ((retval == 0) && (g == &grp)); -#else - /* default to non thread-safe but posix compliant function */ - g = getgrnam (utf8_groupname); - result = (g != NULL); -#endif - if (result) - result = IsMemberOf ((uid_t) GPOINTER_TO_INT (user), g); - -#ifdef HAVE_GETGRNAM_R - g_free (fbuf); -#endif - } - -#endif /* HAVE_GRP_H */ - - return result; -} -#endif /* !HOST_WIN32 */ - -/* Mono.Security.Cryptography IO related internal calls */ - -#ifndef HOST_WIN32 -static gboolean -IsProtected (const gunichar2 *path, gint32 protection) -{ - gboolean result = FALSE; - gchar *utf8_name = mono_unicode_to_external (path); - if (utf8_name) { - struct stat st; - if (stat (utf8_name, &st) == 0) { - result = (((st.st_mode & 0777) & protection) == 0); - } - g_free (utf8_name); - } - return result; -} - - -static gboolean -Protect (const gunichar2 *path, gint32 file_mode, gint32 add_dir_mode) -{ - gboolean result = FALSE; - gchar *utf8_name = mono_unicode_to_external (path); - if (utf8_name) { - struct stat st; - if (stat (utf8_name, &st) == 0) { - int mode = file_mode; - if (st.st_mode & S_IFDIR) - mode |= add_dir_mode; -#ifdef HAVE_CHMOD - result = (chmod (utf8_name, mode) == 0); -#else - result = -1; // FIXME Huh? This must be TRUE or FALSE. -#endif - } - g_free (utf8_name); - } - return result; -} - -MonoBoolean -ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure (const gunichar2 *path) -{ - /* we assume some kind of security is applicable outside Windows */ - return TRUE; -} - -MonoBoolean -ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsMachineProtected (const gunichar2 *path) -{ - gboolean ret = FALSE; - - /* no one, but the owner, should have write access to the directory */ - ret = IsProtected (path, (S_IWGRP | S_IWOTH)); - return (MonoBoolean)ret; -} - -MonoBoolean -ves_icall_Mono_Security_Cryptography_KeyPairPersistence_IsUserProtected (const gunichar2 *path) -{ - gboolean ret = FALSE; - - /* no one, but the user, should have access to the directory */ - ret = IsProtected (path, (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH)); - return (MonoBoolean)ret; -} - -MonoBoolean -ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectMachine (const gunichar2 *path) -{ - gboolean ret = FALSE; - - /* read/write to owner, read to everyone else */ - ret = Protect (path, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), (S_IXUSR | S_IXGRP | S_IXOTH)); - return (MonoBoolean)ret; -} - -MonoBoolean -ves_icall_Mono_Security_Cryptography_KeyPairPersistence_ProtectUser (const gunichar2 *path) -{ - gboolean ret = FALSE; - - /* read/write to user, no access to everyone else */ - ret = Protect (path, (S_IRUSR | S_IWUSR), S_IXUSR); - return (MonoBoolean)ret; -} -#endif /* !HOST_WIN32 */ - -/* - * Returns TRUE if there is "something" where the Authenticode signature is - * normally located. Returns FALSE is data directory is empty. - * - * Note: Neither the structure nor the signature is verified by this function. - */ -MonoBoolean -ves_icall_System_Security_Policy_Evidence_IsAuthenticodePresent (MonoReflectionAssemblyHandle refass, MonoError *error) -{ - error_init (error); - if (MONO_HANDLE_IS_NULL (refass)) - return FALSE; - MonoAssembly *assembly = MONO_HANDLE_GETVAL (refass, assembly); - if (assembly && assembly->image) { - return (MonoBoolean)mono_image_has_authenticode_entry (assembly->image); - } - return FALSE; -} - - -/* System.Security.SecureString related internal calls */ - -static MonoImage *system_security_assembly; -static MonoMethod *mono_method_securestring_decrypt; -static MonoMethod *mono_method_securestring_encrypt; - -static void -mono_invoke_protected_memory_method (MonoArrayHandle data, MonoObjectHandle scope, - const char *method_name, MonoMethod **method, MonoError *error) -{ - if (!*method) { - MonoDomain *domain = mono_domain_get (); - MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain); - if (system_security_assembly == NULL) { - system_security_assembly = mono_image_loaded_internal (alc, "System.Security", FALSE); - if (!system_security_assembly) { - MonoAssemblyOpenRequest req; - mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, alc); - MonoAssembly *sa = mono_assembly_request_open ("System.Security.dll", &req, NULL); - g_assert (sa); - system_security_assembly = mono_assembly_get_image_internal (sa); - } - } - MonoClass *klass = mono_class_load_from_name (system_security_assembly, - "System.Security.Cryptography", "ProtectedMemory"); - *method = mono_class_get_method_from_name_checked (klass, method_name, 2, 0, error); - mono_error_assert_ok (error); - g_assert (*method); - } - void *params [ ] = { - MONO_HANDLE_RAW (data), - MONO_HANDLE_RAW (scope) // MemoryProtectionScope.SameProcess - }; - mono_runtime_invoke_handle_void (*method, NULL_HANDLE, params, error); -} - -void -ves_icall_System_Security_SecureString_DecryptInternal (MonoArrayHandle data, MonoObjectHandle scope, MonoError *error) -{ - mono_invoke_protected_memory_method (data, scope, "Unprotect", &mono_method_securestring_decrypt, error); -} -void -ves_icall_System_Security_SecureString_EncryptInternal (MonoArrayHandle data, MonoObjectHandle scope, MonoError *error) -{ - mono_invoke_protected_memory_method (data, scope, "Protect", &mono_method_securestring_encrypt, error); -} - -#else - -MONO_EMPTY_SOURCE_FILE (mono_security); - -#endif /* ENABLE_NETCORE */ diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index c69304c..e35240b 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -13,7 +13,6 @@ #include "mono/metadata/native-library.h" #include "mono/metadata/custom-attrs-internals.h" -#ifdef ENABLE_NETCORE static int pinvoke_search_directories_count; static char **pinvoke_search_directories; @@ -51,7 +50,6 @@ static GHashTable *native_library_module_blocklist; #ifndef NO_GLOBALIZATION_SHIM extern const void *GlobalizationResolveDllImport (const char *name); #endif -#endif // ENABLE_NETCORE #ifndef DISABLE_DLLMAP static MonoDllMap *global_dll_map; @@ -76,10 +74,8 @@ static char *bundled_dylibrary_directory; /* Class lazy loading functions */ GENERATE_GET_CLASS_WITH_CACHE (appdomain_unloaded_exception, "System", "AppDomainUnloadedException") GENERATE_TRY_GET_CLASS_WITH_CACHE (appdomain_unloaded_exception, "System", "AppDomainUnloadedException") -#ifdef ENABLE_NETCORE GENERATE_GET_CLASS_WITH_CACHE (native_library, "System.Runtime.InteropServices", "NativeLibrary"); static GENERATE_TRY_GET_CLASS_WITH_CACHE (dllimportsearchpath_attribute, "System.Runtime.InteropServices", "DefaultDllImportSearchPathsAttribute"); -#endif #ifndef DISABLE_DLLMAP /* @@ -296,7 +292,6 @@ mono_loader_register_module (const char *name, MonoDl *module) mono_global_loader_data_unlock (); } -#ifdef ENABLE_NETCORE static MonoDl * mono_loader_register_module_locking (const char *name, MonoDl *module) { @@ -323,7 +318,6 @@ exit: return result; } -#endif static void remove_cached_module (gpointer key, gpointer value, gpointer user_data) @@ -337,13 +331,11 @@ mono_global_loader_cache_init (void) if (!global_module_map) global_module_map = g_hash_table_new (g_str_hash, g_str_equal); -#ifdef ENABLE_NETCORE if (!native_library_module_map) native_library_module_map = g_hash_table_new (g_direct_hash, g_direct_equal); if (!native_library_module_blocklist) native_library_module_blocklist = g_hash_table_new (g_direct_hash, g_direct_equal); mono_coop_mutex_init (&native_library_module_lock); -#endif } void @@ -451,7 +443,6 @@ mono_lookup_pinvoke_call_internal (MonoMethod *method, MonoError *error) return result; } -#ifdef ENABLE_NETCORE void mono_set_pinvoke_search_directories (int dir_count, char **dirs) { @@ -960,347 +951,13 @@ default_resolve_dllimport (const char *dll, const char *func) } #endif // NO_GLOBALIZATION_SHIM -#else // ENABLE_NETCORE - -static MonoDl * -cached_module_load (const char *name, int flags, char **err) -{ - MonoDl *res; - - if (err) - *err = NULL; - - MONO_ENTER_GC_SAFE; - mono_global_loader_data_lock (); - MONO_EXIT_GC_SAFE; - - res = (MonoDl *)g_hash_table_lookup (global_module_map, name); - if (res) - goto exit; - - res = mono_dl_open (name, flags, err); - if (res) - g_hash_table_insert (global_module_map, g_strdup (name), res); - -exit: - MONO_ENTER_GC_SAFE; - mono_global_loader_data_unlock (); - MONO_EXIT_GC_SAFE; - - return res; -} - -/** - * legacy_probe_transform_path: - * - * Try transforming the library path given in \p new_scope in different ways - * depending on \p phase - * - * \returns \c TRUE if a transformation was applied and the transformed path - * components are written to the out arguments, or \c FALSE if a transformation - * did not apply. - */ -static gboolean -legacy_probe_transform_path (const char *new_scope, int phase, char **file_name_out, char **base_name_out, char **dir_name_out, gboolean *is_absolute_out) -{ - char *file_name = NULL, *base_name = NULL, *dir_name = NULL; - gboolean changed = FALSE; - gboolean is_absolute = is_absolute_path (new_scope); - switch (phase) { - case 0: - /* Try the original name */ - file_name = g_strdup (new_scope); - changed = TRUE; - break; - case 1: - /* Try trimming the .dll extension */ - if (strstr (new_scope, ".dll") == (new_scope + strlen (new_scope) - 4)) { - file_name = g_strdup (new_scope); - file_name [strlen (new_scope) - 4] = '\0'; - changed = TRUE; - } - break; - case 2: - if (is_absolute) { - dir_name = g_path_get_dirname (new_scope); - base_name = g_path_get_basename (new_scope); - if (strstr (base_name, "lib") != base_name) { - char *tmp = g_strdup_printf ("lib%s", base_name); - g_free (base_name); - base_name = tmp; - file_name = g_strdup_printf ("%s%s%s", dir_name, G_DIR_SEPARATOR_S, base_name); - changed = TRUE; - } - } else if (strstr (new_scope, "lib") != new_scope) { - file_name = g_strdup_printf ("lib%s", new_scope); - changed = TRUE; - } - break; - case 3: - if (!is_absolute && mono_dl_get_system_dir ()) { - dir_name = (char*)mono_dl_get_system_dir (); - file_name = g_path_get_basename (new_scope); - base_name = NULL; - changed = TRUE; - } - break; - default: -#ifndef TARGET_WIN32 - if (!g_ascii_strcasecmp ("user32.dll", new_scope) || - !g_ascii_strcasecmp ("kernel32.dll", new_scope) || - !g_ascii_strcasecmp ("user32", new_scope) || - !g_ascii_strcasecmp ("kernel", new_scope)) { - file_name = g_strdup ("libMonoSupportW.so"); - changed = TRUE; - } -#endif - break; - } - if (changed && is_absolute) { - if (!dir_name) - dir_name = g_path_get_dirname (file_name); - if (!base_name) - base_name = g_path_get_basename (file_name); - } - *file_name_out = file_name; - *base_name_out = base_name; - *dir_name_out = dir_name; - *is_absolute_out = is_absolute; - return changed; -} - -static MonoDl * -legacy_probe_for_module_in_directory (const char *mdirname, const char *file_name) -{ - void *iter = NULL; - char *full_name; - MonoDl* module = NULL; - - while ((full_name = mono_dl_build_path (mdirname, file_name, &iter)) && module == NULL) { - char *error_msg; - module = cached_module_load (full_name, MONO_DL_LAZY, &error_msg); - if (!module) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s': '%s'.", full_name, error_msg); - g_free (error_msg); - } - g_free (full_name); - } - g_free (full_name); - - return module; -} - -static MonoDl * -legacy_probe_for_module_relative_directories (MonoImage *image, const char *file_name) -{ - MonoDl* module = NULL; - - for (int j = 0; j < 3; ++j) { - char *mdirname = NULL; - - switch (j) { - case 0: - mdirname = g_path_get_dirname (image->filename); - break; - case 1: // @executable_path@/../lib - { - char buf [4096]; // FIXME: MAX_PATH - int binl; - binl = mono_dl_get_executable_path (buf, sizeof (buf)); - if (binl != -1) { - char *base, *newbase; - char *resolvedname; - buf [binl] = 0; - resolvedname = mono_path_resolve_symlinks (buf); - - base = g_path_get_dirname (resolvedname); - newbase = g_path_get_dirname(base); - - // On Android the executable for the application is going to be /system/bin/app_process{32,64} depending on - // the application's architecture. However, libraries for the different architectures live in different - // subdirectories of `/system`: `lib` for 32-bit apps and `lib64` for 64-bit ones. Thus appending `/lib` below - // will fail to load the DSO for a 64-bit app, even if it exists there, because it will have a different - // architecture. This is the cause of https://github.com/xamarin/xamarin-android/issues/2780 and the ifdef - // below is the fix. - mdirname = g_strdup_printf ( -#if defined(TARGET_ANDROID) && (defined(TARGET_ARM64) || defined(TARGET_AMD64)) - "%s/lib64", -#else - "%s/lib", -#endif - newbase); - g_free (resolvedname); - g_free (base); - g_free (newbase); - } - break; - } -#ifdef __MACH__ - case 2: // @executable_path@/../Libraries - { - char buf [4096]; // FIXME: MAX_PATH - int binl; - binl = mono_dl_get_executable_path (buf, sizeof (buf)); - if (binl != -1) { - char *base, *newbase; - char *resolvedname; - buf [binl] = 0; - resolvedname = mono_path_resolve_symlinks (buf); - - base = g_path_get_dirname (resolvedname); - newbase = g_path_get_dirname(base); - mdirname = g_strdup_printf ("%s/Libraries", newbase); - - g_free (resolvedname); - g_free (base); - g_free (newbase); - } - break; - } -#endif - } - - if (!mdirname) - continue; - - module = legacy_probe_for_module_in_directory (mdirname, file_name); - g_free (mdirname); - if (module) - break; - } - - return module; -} - -static MonoDl * -legacy_probe_for_module (MonoImage *image, const char *new_scope) -{ - char *full_name, *file_name; - char *error_msg = NULL; - int i; - MonoDl *module = NULL; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "DllImport attempting to load: '%s'.", new_scope); - - /* we allow a special name to dlopen from the running process namespace */ - if (strcmp (new_scope, "__Internal") == 0) { - if (!internal_module) - internal_module = mono_dl_open (NULL, MONO_DL_LAZY, &error_msg); - module = internal_module; - - if (!module) { - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", error_msg); - g_free (error_msg); - } - - return module; - } - - /* - * Try loading the module using a variety of names - */ - for (i = 0; i < 5; ++i) { - char *base_name = NULL, *dir_name = NULL; - gboolean is_absolute; - - gboolean changed = legacy_probe_transform_path (new_scope, i, &file_name, &base_name, &dir_name, &is_absolute); - if (!changed) - continue; - - if (!module && is_absolute) { - module = cached_module_load (file_name, MONO_DL_LAZY, &error_msg); - if (!module) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, - "DllImport error loading library '%s': '%s'.", - file_name, error_msg); - g_free (error_msg); - } - } - - if (!module && !is_absolute) { - module = legacy_probe_for_module_relative_directories (image, file_name); - } - - if (!module) { - void *iter = NULL; - char *file_or_base = is_absolute ? base_name : file_name; - while ((full_name = mono_dl_build_path (dir_name, file_or_base, &iter))) { - module = cached_module_load (full_name, MONO_DL_LAZY, &error_msg); - if (!module) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, - "DllImport error loading library '%s': '%s'.", - full_name, error_msg); - g_free (error_msg); - } - g_free (full_name); - if (module) - break; - } - } - - if (!module) { - module = cached_module_load (file_name, MONO_DL_LAZY, &error_msg); - if (!module) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, - "DllImport error loading library '%s': '%s'.", - file_name, error_msg); - g_free (error_msg); - } - } - - g_free (file_name); - if (is_absolute) { - g_free (base_name); - g_free (dir_name); - } - - if (module) - break; - } - - return module; -} - -static MonoDl * -legacy_lookup_native_library (MonoImage *image, const char *scope) -{ - MonoDl *module = NULL; - gboolean cached = FALSE; - - mono_image_lock (image); - if (!image->pinvoke_scopes) - image->pinvoke_scopes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - module = (MonoDl *)g_hash_table_lookup (image->pinvoke_scopes, scope); - mono_image_unlock (image); - if (module) - cached = TRUE; - - if (!module) - module = legacy_probe_for_module (image, scope); - - if (module && !cached) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, - "DllImport loaded library '%s'.", module->full_name); - mono_image_lock (image); - if (!g_hash_table_lookup (image->pinvoke_scopes, scope)) { - g_hash_table_insert (image->pinvoke_scopes, g_strdup (scope), module); - } - mono_image_unlock (image); - } - - return module; -} -#endif // ENABLE_NETCORE - gpointer lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_out) { MonoImage *image = m_class_get_image (method->klass); -#ifdef ENABLE_NETCORE MonoAssemblyLoadContext *alc = mono_image_get_alc (image); MonoCustomAttrInfo *cinfo; int flags; -#endif MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method; MonoTableInfo *tables = image->tables; MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP]; @@ -1372,7 +1029,6 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou } #endif -#ifdef ENABLE_NETCORE #ifndef NO_GLOBALIZATION_SHIM addr = default_resolve_dllimport (new_scope, new_import); if (addr) @@ -1408,9 +1064,6 @@ retry_with_libcoreclr: if (flags < 0) flags = 0; module = netcore_lookup_native_library (alc, image, new_scope, flags); -#else - module = legacy_lookup_native_library (image, new_scope); -#endif // ENABLE_NETCORE if (!module) { mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DLLIMPORT, @@ -1428,13 +1081,13 @@ retry_with_libcoreclr: addr = pinvoke_probe_for_symbol (module, piinfo, new_import, &error_msg); if (!addr) { -#if defined(ENABLE_NETCORE) && !defined(HOST_WIN32) +#ifndef HOST_WIN32 if (strcmp (new_scope, "__Internal") == 0) { g_free ((char *)new_scope); new_scope = g_strdup (MONO_LOADER_LIBRARY_NAME); goto retry_with_libcoreclr; } -#endif +#endif status_out->err_code = LOOKUP_PINVOKE_ERR_NO_SYM; status_out->err_arg = g_strdup (new_import); goto exit; @@ -1469,7 +1122,7 @@ pinvoke_probe_for_symbol (MonoDl *module, MonoMethodPInvoke *piinfo, const char mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Searching for '%s'.", import); -#if !defined(ENABLE_NETCORE) || defined(HOST_WIN32) // For netcore, name mangling is Windows-exclusive +#ifdef HOST_WIN32 // For netcore, name mangling is Windows-exclusive if (piinfo->piflags & PINVOKE_ATTRIBUTE_NO_MANGLE) error_msg = mono_dl_symbol (module, import, &addr); else { @@ -1562,7 +1215,6 @@ pinvoke_probe_for_symbol (MonoDl *module, MonoMethodPInvoke *piinfo, const char return addr; } -#ifdef ENABLE_NETCORE void ves_icall_System_Runtime_InteropServices_NativeLibrary_FreeLib (gpointer lib, MonoError *error) { @@ -1718,7 +1370,6 @@ leave: return handle; } -#endif #ifdef HAVE_ATEXIT static void diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index 08b2752..36ae4f1 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -278,9 +278,6 @@ mono_handle_array_get_bounds_dim (MonoArrayHandle arr, gint32 dim, MonoArrayBoun typedef struct { MonoObject obj; -#ifndef ENABLE_NETCORE - MonoObject *identity; -#endif } MonoMarshalByRefObject; TYPED_HANDLE_DECL (MonoMarshalByRefObject); @@ -288,19 +285,11 @@ TYPED_HANDLE_DECL (MonoMarshalByRefObject); /* This is a copy of System.AppDomain */ struct _MonoAppDomain { MonoMarshalByRefObject mbr; -#ifndef ENABLE_NETCORE - MonoDomain *data; -#endif }; /* Safely access System.AppDomain from native code */ TYPED_HANDLE_DECL (MonoAppDomain); -#ifndef ENABLE_NETCORE -/* Safely access System.AppDomainSetup from native code. (struct is in domain-internals.h) */ -TYPED_HANDLE_DECL (MonoAppDomainSetup); -#endif - typedef struct _MonoStringBuilder MonoStringBuilder; TYPED_HANDLE_DECL (MonoStringBuilder); @@ -358,11 +347,7 @@ struct _MonoException { MonoString *remote_stack_trace; gint32 remote_stack_index; /* Dynamic methods referenced by the stack trace */ -#ifdef ENABLE_NETCORE MonoArray *dynamic_methods; -#else - MonoObject *dynamic_methods; -#endif gint32 hresult; MonoString *source; MonoObject *serialization_manager; @@ -377,13 +362,6 @@ typedef struct { TYPED_HANDLE_DECL (MonoSystemException); -#ifndef ENABLE_NETCORE -typedef struct { - MonoSystemException base; - MonoString *param_name; -} MonoArgumentException; -#endif - typedef struct { MonoObject object; MonoObject *async_state; @@ -598,9 +576,6 @@ struct _MonoInternalThread { gsize debugger_thread; // FIXME switch to bool as soon as CI testing with corlib version bump works gpointer *static_data; struct _MonoThreadInfo *thread_info; -#ifndef ENABLE_NETCORE - MonoAppContext *current_appcontext; -#endif MonoThread *root_domain_thread; MonoObject *_serialized_principal; int _serialized_principal_version; @@ -628,13 +603,10 @@ struct _MonoInternalThread { gint32 self_suspended; // TRUE | FALSE gsize thread_state; -#ifdef ENABLE_NETCORE struct _MonoInternalThread *internal_thread; MonoObject *start_obj; MonoException *pending_exception; -#else - void* unused [3]; // same size as netcore -#endif + /* This is used only to check that we are in sync between the representation * of MonoInternalThread in native and InternalThread in managed * @@ -642,170 +614,11 @@ struct _MonoInternalThread { gpointer last; }; -#ifndef ENABLE_NETCORE -struct _MonoThread { - MonoObject obj; - MonoInternalThread *internal_thread; - MonoObject *start_obj; - MonoException *pending_exception; -}; -#endif - typedef struct { guint32 state; MonoObject *additional; } MonoStreamingContext; -#if !ENABLE_NETCORE -typedef struct { - MonoObject obj; - MonoBoolean readOnly; - MonoString *AMDesignator; - MonoString *PMDesignator; - MonoString *DateSeparator; - MonoString *TimeSeparator; - MonoString *ShortDatePattern; - MonoString *LongDatePattern; - MonoString *ShortTimePattern; - MonoString *LongTimePattern; - MonoString *MonthDayPattern; - MonoString *YearMonthPattern; - guint32 FirstDayOfWeek; - guint32 CalendarWeekRule; - MonoArray *AbbreviatedDayNames; - MonoArray *DayNames; - MonoArray *MonthNames; - MonoArray *GenitiveMonthNames; - MonoArray *AbbreviatedMonthNames; - MonoArray *GenitiveAbbreviatedMonthNames; - MonoArray *ShortDatePatterns; - MonoArray *LongDatePatterns; - MonoArray *ShortTimePatterns; - MonoArray *LongTimePatterns; - MonoArray *MonthDayPatterns; - MonoArray *YearMonthPatterns; - MonoArray *ShortestDayNames; -} MonoDateTimeFormatInfo; - -typedef struct -{ - MonoObject obj; - MonoArray *numberGroupSizes; - MonoArray *currencyGroupSizes; - MonoArray *percentGroupSizes; - MonoString *positiveSign; - MonoString *negativeSign; - MonoString *numberDecimalSeparator; - MonoString *numberGroupSeparator; - MonoString *currencyGroupSeparator; - MonoString *currencyDecimalSeparator; - MonoString *currencySymbol; - MonoString *ansiCurrencySymbol; /* unused */ - MonoString *naNSymbol; - MonoString *positiveInfinitySymbol; - MonoString *negativeInfinitySymbol; - MonoString *percentDecimalSeparator; - MonoString *percentGroupSeparator; - MonoString *percentSymbol; - MonoString *perMilleSymbol; - MonoString *nativeDigits; /* unused */ - gint32 dataItem; /* unused */ - guint32 numberDecimalDigits; - gint32 currencyDecimalDigits; - gint32 currencyPositivePattern; - gint32 currencyNegativePattern; - gint32 numberNegativePattern; - gint32 percentPositivePattern; - gint32 percentNegativePattern; - gint32 percentDecimalDigits; -} MonoNumberFormatInfo; - -typedef struct { - MonoObject obj; - gint32 lcid; - MonoString *icu_name; - gpointer ICU_collator; -} MonoCompareInfo; - -typedef struct { - MonoObject obj; - MonoString *NativeName; - MonoArray *ShortDatePatterns; - MonoArray *YearMonthPatterns; - MonoArray *LongDatePatterns; - MonoString *MonthDayPattern; - - MonoArray *EraNames; - MonoArray *AbbreviatedEraNames; - MonoArray *AbbreviatedEnglishEraNames; - MonoArray *DayNames; - MonoArray *AbbreviatedDayNames; - MonoArray *SuperShortDayNames; - MonoArray *MonthNames; - MonoArray *AbbreviatedMonthNames; - MonoArray *GenitiveMonthNames; - MonoArray *GenitiveAbbreviatedMonthNames; -} MonoCalendarData; - -TYPED_HANDLE_DECL (MonoCalendarData); - -typedef struct { - MonoObject obj; - MonoString *AMDesignator; - MonoString *PMDesignator; - MonoString *TimeSeparator; - MonoArray *LongTimePatterns; - MonoArray *ShortTimePatterns; - guint32 FirstDayOfWeek; - guint32 CalendarWeekRule; -} MonoCultureData; - -TYPED_HANDLE_DECL (MonoCultureData); - -typedef struct { - MonoObject obj; - MonoBoolean is_read_only; - gint32 lcid; - gint32 parent_lcid; - gint32 datetime_index; - gint32 number_index; - gint32 calendar_type; - MonoBoolean use_user_override; - MonoNumberFormatInfo *number_format; - MonoDateTimeFormatInfo *datetime_format; - MonoObject *textinfo; - MonoString *name; - MonoString *englishname; - MonoString *nativename; - MonoString *iso3lang; - MonoString *iso2lang; - MonoString *win3lang; - MonoString *territory; - MonoArray *native_calendar_names; - MonoCompareInfo *compareinfo; - const void* text_info_data; -} MonoCultureInfo; - -TYPED_HANDLE_DECL (MonoCultureInfo); - -typedef struct { - MonoObject obj; - gint32 geo_id; - MonoString *iso2name; - MonoString *iso3name; - MonoString *win3name; - MonoString *english_name; - MonoString *native_name; - MonoString *currency_symbol; - MonoString *iso_currency_symbol; - MonoString *currency_english_name; - MonoString *currency_native_name; -} MonoRegionInfo; - -TYPED_HANDLE_DECL (MonoRegionInfo); - -#endif /* !ENABLE_NETCORE */ - typedef struct { MonoObject object; guint32 intType; @@ -1058,9 +871,6 @@ TYPED_HANDLE_DECL (MonoReflectionProperty); /*This is System.EventInfo*/ struct _MonoReflectionEvent { MonoObject object; -#ifndef ENABLE_NETCORE - MonoObject *cached_add_event; -#endif }; /* Safely access System.Reflection.EventInfo from native code */ @@ -1527,7 +1337,6 @@ typedef struct { TYPED_HANDLE_DECL (MonoReflectionCustomAttr); -#if ENABLE_NETCORE typedef struct { MonoObject object; guint32 utype; @@ -1541,21 +1350,6 @@ typedef struct { MonoReflectionType *marshal_type_ref; MonoString *marshal_cookie; } MonoReflectionMarshalAsAttribute; -#else -typedef struct { - MonoObject object; - MonoString *marshal_cookie; - MonoString *marshal_type; - MonoReflectionType *marshal_type_ref; - MonoReflectionType *marshal_safe_array_user_defined_subtype; - guint32 utype; - guint32 array_subtype; - gint32 safe_array_subtype; - gint32 size_const; - gint32 IidParameterIndex; - gint16 size_param_index; -} MonoReflectionMarshalAsAttribute; -#endif /* Safely access System.Runtime.InteropServices.MarshalAsAttribute */ TYPED_HANDLE_DECL (MonoReflectionMarshalAsAttribute); @@ -1662,7 +1456,6 @@ typedef struct { MonoProperty *prop; } CattrNamedArg; -#ifdef ENABLE_NETCORE // Keep in sync with System.Runtime.Loader.AssemblyLoadContext.InternalState typedef enum { ALIVE = 0, @@ -1676,7 +1469,6 @@ typedef struct { } MonoManagedAssemblyLoadContext; TYPED_HANDLE_DECL (MonoManagedAssemblyLoadContext); -#endif /* All MonoInternalThread instances should be pinned, so it's safe to use the raw ptr. However * for uniformity, icall wrapping will make handles anyway. So this is the method for getting the payload. @@ -1934,13 +1726,11 @@ mono_runtime_unhandled_exception_policy_set (MonoRuntimeUnhandledExceptionPolicy void mono_unhandled_exception_checked (MonoObjectHandle exc, MonoError *error); -#ifdef ENABLE_NETCORE void mono_first_chance_exception_checked (MonoObjectHandle exc, MonoError *error); void mono_first_chance_exception_internal (MonoObject *exc_raw); -#endif MonoVTable * mono_class_try_get_vtable (MonoDomain *domain, MonoClass *klass); diff --git a/src/mono/mono/metadata/object-offsets.h b/src/mono/mono/metadata/object-offsets.h index ab8fb9e..dd19b9c 100644 --- a/src/mono/mono/metadata/object-offsets.h +++ b/src/mono/mono/metadata/object-offsets.h @@ -167,14 +167,6 @@ DECL_OFFSET(MonoJitTlsData, stack_restore_ctx) DECL_OFFSET(MonoGSharedVtMethodRuntimeInfo, locals_size) DECL_OFFSET(MonoGSharedVtMethodRuntimeInfo, entries) //XXX more to fix here -#if !defined(ENABLE_NETCORE) -DECL_OFFSET(MonoContinuation, stack_used_size) -DECL_OFFSET(MonoContinuation, saved_stack) -DECL_OFFSET(MonoContinuation, return_sp) -DECL_OFFSET(MonoContinuation, lmf) -DECL_OFFSET(MonoContinuation, return_ip) -#endif - DECL_OFFSET(MonoDelegateTrampInfo, method) DECL_OFFSET(MonoDelegateTrampInfo, invoke_impl) DECL_OFFSET(MonoDelegateTrampInfo, method_ptr) diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index b114775..d593c9a 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -1252,12 +1252,6 @@ field_is_special_static (MonoClass *fklass, MonoClassField *field) mono_custom_attrs_free (ainfo); return SPECIAL_STATIC_THREAD; } -#ifndef ENABLE_NETCORE - else if (strcmp (klass_name, "ContextStaticAttribute") == 0) { - mono_custom_attrs_free (ainfo); - return SPECIAL_STATIC_CONTEXT; - } -#endif } } mono_custom_attrs_free (ainfo); @@ -3412,11 +3406,7 @@ mono_field_set_value_internal (MonoObject *obj, MonoClassField *field, void *val return; dest = (char*)obj + field->offset; -#if ENABLE_NETCORE mono_copy_value (field->type, dest, value, value && field->type->type == MONO_TYPE_PTR); -#else - mono_copy_value (field->type, dest, value, FALSE); -#endif } /** @@ -3724,12 +3714,7 @@ mono_field_get_value_object_checked (MonoDomain *domain, MonoClassField *field, mono_field_get_value_internal (obj, field, v); } -#if ENABLE_NETCORE args [0] = ptr; -#else - /* MONO_TYPE_PTR is passed by value to runtime_invoke () */ - args [0] = ptr ? *ptr : NULL; -#endif args [1] = mono_type_get_object_checked (mono_domain_get (), type, error); goto_if_nok (error, return_null); @@ -5011,7 +4996,6 @@ mono_unhandled_exception (MonoObject *exc) MONO_EXTERNAL_ONLY_VOID (mono_unhandled_exception_internal (exc)); } -#ifdef ENABLE_NETCORE static MonoObjectHandle create_first_chance_exception_eventargs (MonoObjectHandle exc, MonoError *error) { @@ -5106,7 +5090,6 @@ mono_first_chance_exception_checked (MonoObjectHandle exc, MonoError *error) mono_runtime_delegate_try_invoke_handle (delegate_handle, args, error); } } -#endif /** * mono_unhandled_exception_checked: @@ -5133,55 +5116,19 @@ mono_unhandled_exception_checked (MonoObjectHandle exc, MonoError *error) * https://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(v=vs.110).aspx#Anchor_6 */ gboolean no_event = (klass == mono_defaults.threadabortexception_class); -#ifndef ENABLE_NETCORE - no_event = no_event || - (klass == mono_class_get_appdomain_unloaded_exception_class () && - mono_thread_info_current ()->runtime_thread); -#endif if (no_event) return; MONO_STATIC_POINTER_INIT (MonoClassField, field) -#ifndef ENABLE_NETCORE - field = mono_class_get_field_from_name_full (mono_defaults.appdomain_class, "UnhandledException", NULL); -#else static gboolean inited; if (!inited) { field = mono_class_get_field_from_name_full (mono_defaults.appcontext_class, "UnhandledException", NULL); inited = TRUE; } -#endif MONO_STATIC_POINTER_INIT_END (MonoClassField, field) -#ifndef ENABLE_NETCORE - g_assert (field); - - MonoDomain *root_domain; - MonoObjectHandle current_appdomain_delegate = MONO_HANDLE_NEW (MonoObject, NULL); - - root_domain = mono_get_root_domain (); - - MonoObjectHandle root_appdomain_delegate = MONO_HANDLE_NEW (MonoObject, mono_field_get_value_object_checked (root_domain, field, (MonoObject*) root_domain->domain, error)); /* FIXME use handles for mono_field_get_value_object_checked */ - return_if_nok (error); - if (current_domain != root_domain) { - MONO_HANDLE_ASSIGN (current_appdomain_delegate, MONO_HANDLE_NEW (MonoObject, mono_field_get_value_object_checked (current_domain, field, (MonoObject*) current_domain->domain, error))); /* FIXME use handles for mono_field_get_value_object_checked */ - return_if_nok (error); - } - - if (MONO_HANDLE_IS_NULL (current_appdomain_delegate) && MONO_HANDLE_IS_NULL (root_appdomain_delegate)) { - mono_print_unhandled_exception_internal (MONO_HANDLE_RAW (exc)); /* FIXME use handles for mono_print_unhandled_exception */ - } else { - /* unhandled exception callbacks must not be aborted */ - mono_threads_begin_abort_protected_block (); - if (!MONO_HANDLE_IS_NULL (root_appdomain_delegate)) - call_unhandled_exception_delegate (root_domain, root_appdomain_delegate, exc); - if (!MONO_HANDLE_IS_NULL (current_appdomain_delegate)) - call_unhandled_exception_delegate (current_domain, current_appdomain_delegate, exc); - mono_threads_end_abort_protected_block (); - } -#else if (!field) goto leave; @@ -5206,7 +5153,6 @@ mono_unhandled_exception_checked (MonoObjectHandle exc, MonoError *error) } leave: -#endif /* set exitcode only if we will abort the process */ if ((main_thread && mono_thread_internal_current () == main_thread->internal_thread) @@ -6708,7 +6654,6 @@ mono_array_new_specific_checked (MonoVTable *vtable, uintptr_t n, MonoError *err return mono_array_new_specific_internal (vtable, n, FALSE, error); } -#ifdef ENABLE_NETCORE MonoArrayHandle ves_icall_System_GC_AllocPinnedArray (MonoReflectionTypeHandle array_type, gint32 length, MonoError *error) { @@ -6726,7 +6671,6 @@ ves_icall_System_GC_AllocPinnedArray (MonoReflectionTypeHandle array_type, gint3 fail: return MONO_HANDLE_NEW (MonoArray, NULL); } -#endif MonoArrayHandle @@ -8316,59 +8260,6 @@ mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx) eh_callbacks.mono_raise_exception_with_ctx (ex, ctx); } -#ifndef ENABLE_NETCORE - -/** - * mono_wait_handle_new: - * \param domain Domain where the object will be created - * \param handle Handle for the wait handle - * \param error set on error. - * \returns A new \c MonoWaitHandle created in the given domain for the - * given handle. On failure returns NULL and sets \p error. - */ -MonoWaitHandle * -mono_wait_handle_new (MonoDomain *domain, HANDLE handle, MonoError *error) -{ - MONO_REQ_GC_UNSAFE_MODE; - - MonoWaitHandle *res; - gpointer params [1]; - static MonoMethod *handle_set; - - error_init (error); - res = (MonoWaitHandle *)mono_object_new_checked (domain, mono_defaults.manualresetevent_class, error); - return_val_if_nok (error, NULL); - - /* Even though this method is virtual, it's safe to invoke directly, since the object type matches. */ - if (!handle_set) - handle_set = mono_class_get_property_from_name_internal (mono_defaults.manualresetevent_class, "Handle")->set; - - params [0] = &handle; - - mono_runtime_invoke_checked (handle_set, res, params, error); - return res; -} - -HANDLE -mono_wait_handle_get_handle (MonoWaitHandle *handle) -{ - MONO_REQ_GC_UNSAFE_MODE; - - MonoSafeHandle *sh; - - MONO_STATIC_POINTER_INIT (MonoClassField, f_safe_handle) - - f_safe_handle = mono_class_get_field_from_name_full (mono_defaults.manualresetevent_class, "safeWaitHandle", NULL); - g_assert (f_safe_handle); - - MONO_STATIC_POINTER_INIT_END (MonoClassField, f_safe_handle) - - mono_field_get_value_internal ((MonoObject*)handle, f_safe_handle, &sh); - return sh->handle; -} - -#endif /* ENABLE_NETCORE */ - /* * Returns the MonoMethod to call to Capture the ExecutionContext. */ @@ -8422,128 +8313,6 @@ mono_runtime_capture_context (MonoDomain *domain, MonoError *error) #endif } -#ifndef ENABLE_NETCORE - -/** - * mono_async_result_new: - * \param domain domain where the object will be created. - * \param handle wait handle. - * \param state state to pass to AsyncResult - * \param data C closure data. - * \param error set on error. - * Creates a new MonoAsyncResult (\c AsyncResult C# class) in the given domain. - * If the handle is not null, the handle is initialized to a \c MonoWaitHandle. - * On failure returns NULL and sets \p error. - */ -MonoAsyncResult * -mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data, MonoError *error) -{ - MONO_REQ_GC_UNSAFE_MODE; - - error_init (error); - MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new_checked (domain, mono_class_get_asyncresult_class (), error); - return_val_if_nok (error, NULL); - MonoObject *context = mono_runtime_capture_context (domain, error); - return_val_if_nok (error, NULL); - /* we must capture the execution context from the original thread */ - if (context) { - MONO_OBJECT_SETREF_INTERNAL (res, execution_context, context); - /* note: result may be null if the flow is suppressed */ - } - - res->data = (void **)data; - MONO_OBJECT_SETREF_INTERNAL (res, object_data, object_data); - MONO_OBJECT_SETREF_INTERNAL (res, async_state, state); - MonoWaitHandle *wait_handle = mono_wait_handle_new (domain, handle, error); - return_val_if_nok (error, NULL); - if (handle != NULL) - MONO_OBJECT_SETREF_INTERNAL (res, handle, (MonoObject *) wait_handle); - - res->sync_completed = FALSE; - res->completed = FALSE; - - return res; -} - -static MonoObject* -mono_message_invoke (MonoThreadInfo* thread_info_current_var, - MonoObject* target, MonoMethodMessage* msg, - MonoObject** exc, MonoArray** out_args, MonoError* error); - -MonoObjectHandle -ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResultHandle aresh, MonoError* error) -{ - MONO_REQ_GC_UNSAFE_MODE; - - SETUP_ICALL_FUNCTION; - - MonoAsyncCall *ac; - MonoObjectHandle res = MONO_HANDLE_NEW (MonoObject, NULL); - MonoAsyncResult* ares = MONO_HANDLE_RAW (aresh); - - g_assert (ares); - g_assert (ares->async_delegate); - MONO_HANDLE_NEW (MonoObject, ares->async_delegate); - - ac = (MonoAsyncCall*) ares->object_data; - MONO_HANDLE_NEW (MonoAsyncCall, ac); - - if (!ac) { - MONO_HANDLE_ASSIGN_RAW (res, mono_runtime_delegate_invoke_checked (ares->async_delegate, (void**) &ares->async_state, error)); - return_val_if_nok (error, NULL_HANDLE); - } else { - gpointer wait_event = NULL; - - MONO_HANDLE_NEW (MonoMethodMessage, ac->msg); - - ac->msg->exc = NULL; - - MONO_HANDLE_ASSIGN_RAW (res, mono_message_invoke (mono_thread_info_current_var, - ares->async_delegate, - ac->msg, - &ac->msg->exc, - &ac->out_args, - error)); - - /* The exit side of the invoke must not be aborted as it would leave the runtime in an undefined state */ - mono_threads_begin_abort_protected_block (); - - if (!ac->msg->exc) { - MonoException *ex = mono_error_convert_to_exception (error); - MONO_OBJECT_SETREF_INTERNAL (ac->msg, exc, (MonoObject *)ex); - } else { - mono_error_cleanup (error); - } - - MONO_OBJECT_SETREF_INTERNAL (ac, res, MONO_HANDLE_RAW (res)); - - MonoObjectHandle handle = MONO_HANDLE_NEW (MonoObject, NULL); // Create handle outside of lock. - - mono_monitor_enter_internal ((MonoObject*) ares); - ares->completed = 1; - if (ares->handle) { - MONO_HANDLE_ASSIGN_RAW (handle, ares->handle); - wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle); - } - mono_monitor_exit_internal ((MonoObject*) ares); - - if (wait_event != NULL) - mono_w32event_set (wait_event); - - error_init (error); //the else branch would leave it in an undefined state - if (ac->cb_method) { - MONO_HANDLE_NEW (MonoDelegate, ac->cb_target); - mono_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, error); - } - - mono_threads_end_abort_protected_block (); - - return_val_if_nok (error, NULL_HANDLE); - } - return res; -} -#endif /* ENABLE_NETCORE */ - gboolean mono_message_init (MonoDomain *domain, MonoMethodMessage *this_obj, diff --git a/src/mono/mono/metadata/object.h b/src/mono/mono/metadata/object.h index f421c6c..c8c0744 100644 --- a/src/mono/mono/metadata/object.h +++ b/src/mono/mono/metadata/object.h @@ -22,11 +22,7 @@ typedef struct _MonoReflectionEvent MONO_RT_MANAGED_ATTR MonoReflectionEvent; typedef struct _MonoReflectionType MONO_RT_MANAGED_ATTR MonoReflectionType; typedef struct _MonoDelegate MONO_RT_MANAGED_ATTR MonoDelegate; typedef struct _MonoThreadsSync MonoThreadsSync; -#ifdef ENABLE_NETCORE typedef struct _MonoInternalThread MONO_RT_MANAGED_ATTR MonoThread; -#else -typedef struct _MonoThread MONO_RT_MANAGED_ATTR MonoThread; -#endif typedef struct _MonoDynamicAssembly MonoDynamicAssembly; typedef struct _MonoDynamicImage MonoDynamicImage; typedef struct _MonoReflectionMethodBody MONO_RT_MANAGED_ATTR MonoReflectionMethodBody; diff --git a/src/mono/mono/metadata/rand.c b/src/mono/mono/metadata/rand.c deleted file mode 100644 index 8ce627e..0000000 --- a/src/mono/mono/metadata/rand.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * \file - * System.Security.Cryptography.RNGCryptoServiceProvider support - * - * Authors: - * Mark Crichton (crichton@gimp.org) - * Patrik Torstensson (p@rxc.se) - * Sebastien Pouliot (sebastien@ximian.com) - * - * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) - * Copyright 2004-2009 Novell, Inc (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#include - -#include "object.h" -#include "object-internals.h" -#include "rand.h" -#include "utils/mono-rand.h" -#include "icall-decl.h" - -#ifndef ENABLE_NETCORE - -MonoBoolean -ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngOpen (MonoError *error) -{ - return (MonoBoolean) mono_rand_open (); -} - -gpointer -ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngInitialize (const guchar *seed, gssize seed_length, MonoError *error) -{ - return mono_rand_init (seed, seed_length); -} - -gpointer -ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngGetBytes (gpointer handle, guchar *array, gssize array_length, MonoError *error) -{ - g_assert (array || !array_length); - mono_rand_try_get_bytes (&handle, array, array_length, error); - return handle; -} - -void -ves_icall_System_Security_Cryptography_RNGCryptoServiceProvider_RngClose (gpointer handle, MonoError *error) -{ - mono_rand_close (handle); -} - -#else - -MONO_EMPTY_SOURCE_FILE (rand); - -#endif /* ENABLE_NETCORE */ diff --git a/src/mono/mono/metadata/rand.h b/src/mono/mono/metadata/rand.h deleted file mode 100644 index 9a2fa47..0000000 --- a/src/mono/mono/metadata/rand.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * \file - * System.Security.Cryptography.RNGCryptoServiceProvider support - * - * Author: - * Mark Crichton (crichton@gimp.org) - * Sebastien Pouliot (sebastien@ximian.com) - * - * (C) 2001 Ximian, Inc. - * Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#ifndef _MONO_METADATA_RAND_H_ -#define _MONO_METADATA_RAND_H_ - -#include -#include -#include "mono/utils/mono-compiler.h" -#include - -#endif diff --git a/src/mono/mono/metadata/reflection-internals.h b/src/mono/mono/metadata/reflection-internals.h index 797d1ca..cccfef0 100644 --- a/src/mono/mono/metadata/reflection-internals.h +++ b/src/mono/mono/metadata/reflection-internals.h @@ -22,11 +22,6 @@ TYPED_HANDLE_DECL (MonoReflectionTypeBuilder) MonoReflectionAssemblyHandle mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error); -#ifndef ENABLE_NETCORE -MonoReflectionAssemblyHandle -mono_domain_try_type_resolve_typebuilder (MonoDomain *domain, MonoReflectionTypeBuilderHandle typebuilder, MonoError *error); -#endif - MonoReflectionTypeBuilderHandle mono_class_get_ref_info (MonoClass *klass); diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 55a21a1..cc21a86 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -66,15 +66,9 @@ static GENERATE_GET_CLASS_WITH_CACHE (mono_event, "System.Reflection", "RuntimeE static GENERATE_GET_CLASS_WITH_CACHE (mono_property, "System.Reflection", "RuntimePropertyInfo"); static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, "System.Reflection", "RuntimeParameterInfo"); static GENERATE_GET_CLASS_WITH_CACHE (missing, "System.Reflection", "Missing"); -#ifdef ENABLE_NETCORE static GENERATE_GET_CLASS_WITH_CACHE (method_body, "System.Reflection", "RuntimeMethodBody"); static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, "System.Reflection", "RuntimeLocalVariableInfo"); static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, "System.Reflection", "RuntimeExceptionHandlingClause"); -#else -static GENERATE_GET_CLASS_WITH_CACHE (method_body, "System.Reflection", "MethodBody"); -static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, "System.Reflection", "LocalVariableInfo"); -static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, "System.Reflection", "ExceptionHandlingClause"); -#endif static GENERATE_GET_CLASS_WITH_CACHE (type_builder, "System.Reflection.Emit", "TypeBuilder"); static GENERATE_GET_CLASS_WITH_CACHE (dbnull, "System", "DBNull"); @@ -465,13 +459,8 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err g_assert (!type->has_cmods); /* void is very common */ -#ifdef ENABLE_NETCORE if (!type->byref && type->type == MONO_TYPE_VOID && domain->typeof_void) return (MonoReflectionType*)domain->typeof_void; -#else - if (type->type == MONO_TYPE_VOID && domain->typeof_void) - return (MonoReflectionType*)domain->typeof_void; -#endif /* * If the vtable of the given class was already created, we can use @@ -1930,11 +1919,7 @@ mono_reflection_parse_type_checked (char *name, MonoTypeNameParse *info, MonoErr if (ok) { mono_identifier_unescape_info (info); } else { -#if ENABLE_NETCORE mono_error_set_argument_format (error, "typeName@0", "failed parse: %s", name); -#else - mono_error_set_argument_format (error, "typeName", "failed parse: %s", name); -#endif } return (ok != 0); } @@ -2655,11 +2640,7 @@ reflection_bind_generic_method_parameters (MonoMethod *method, MonoArrayHandle t mono_error_assert_ok (error); if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) { -#if ENABLE_NETCORE mono_error_set_argument (error, NULL, "Invalid generic arguments"); -#else - mono_error_set_argument (error, "typeArguments", "Invalid generic arguments"); -#endif return NULL; } @@ -3134,11 +3115,7 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, Mono error_init (error); if (method == NULL) { -#ifdef ENABLE_NETCORE method = mono_class_get_method_from_name_checked (mono_class_get_type_builder_class (), "IsAssignableToInternal", 1, 0, error); -#else - method = mono_class_get_method_from_name_checked (mono_class_get_type_builder_class (), "IsAssignableTo", 1, 0, error); -#endif mono_error_assert_ok (error); g_assert (method); } diff --git a/src/mono/mono/metadata/runtime.c b/src/mono/mono/metadata/runtime.c index ecd0eb3..aea2636 100644 --- a/src/mono/mono/metadata/runtime.c +++ b/src/mono/mono/metadata/runtime.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -57,7 +56,6 @@ fire_process_exit_event (MonoDomain *domain, gpointer user_data) ERROR_DECL (error); MonoObject *exc; -#if ENABLE_NETCORE MONO_STATIC_POINTER_INIT (MonoMethod, procexit_method) procexit_method = mono_class_get_method_from_name_checked (mono_defaults.appcontext_class, "OnProcessExit", 0, 0, error); @@ -68,23 +66,6 @@ fire_process_exit_event (MonoDomain *domain, gpointer user_data) g_assert (procexit_method); mono_runtime_try_invoke (procexit_method, NULL, NULL, &exc, error); -#else - MonoClassField *field; - gpointer pa [2]; - MonoObject *delegate; - - field = mono_class_get_field_from_name_full (mono_defaults.appdomain_class, "ProcessExit", NULL); - g_assert (field); - - delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); - if (delegate == NULL) - return; - - pa [0] = domain->domain; - pa [1] = NULL; - mono_runtime_delegate_try_invoke (delegate, pa, &exc, error); - mono_error_cleanup (error); -#endif } static void diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index ad482f9..1e40e4c 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -1405,12 +1405,10 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb, M mono_domain_assemblies_lock (domain); domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly); -#ifdef ENABLE_NETCORE // TODO: potentially relax the locking here? mono_alc_assemblies_lock (alc); alc->loaded_assemblies = g_slist_append (alc->loaded_assemblies, assembly); mono_alc_assemblies_unlock (alc); -#endif mono_domain_assemblies_unlock (domain); register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly); @@ -4332,18 +4330,8 @@ ensure_complete_type (MonoClass *klass, MonoError *error) error_init (error); if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_has_ref_info (klass)) { -#ifndef ENABLE_NETCORE - MonoReflectionTypeBuilderHandle tb = mono_class_get_ref_info (klass); - - mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error); - goto_if_nok (error, exit); - - // Asserting here could break a lot of code - //g_assert (klass->wastypebuilder); -#else // TODO: make this work on netcore when working on SRE.TypeBuilder g_assert_not_reached (); -#endif } if (mono_class_is_ginst (klass)) { @@ -4441,15 +4429,8 @@ mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **h /* Already created */ result = klass; } else { -#ifndef ENABLE_NETCORE - mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error); - goto_if_nok (error, return_null); - result = type->data.klass; - g_assert (result); -#else // TODO: make this work on netcore when working on SRE.TypeBuilder g_assert_not_reached(); -#endif } *handle_class = mono_defaults.typehandle_class; @@ -4685,20 +4666,6 @@ ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilderHandle mb, return mono_image_create_method_token (MONO_HANDLE_GETVAL (mb, dynamic_image), MONO_HANDLE_CAST (MonoObject, method), opt_param_types, error); } -#ifndef ENABLE_NETCORE -void -ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilderHandle mb, HANDLE file, MonoError* error) -{ - mono_image_create_pefile (MONO_HANDLE_RAW (mb), file, error); -} - -void -ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilderHandle mb, MonoError* error) -{ - mono_image_build_metadata (MONO_HANDLE_RAW (mb), error); -} -#endif - void ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error) { diff --git a/src/mono/mono/metadata/support.c b/src/mono/mono/metadata/support.c deleted file mode 100644 index 104ef64..0000000 --- a/src/mono/mono/metadata/support.c +++ /dev/null @@ -1,11 +0,0 @@ - -#include "utils/mono-compiler.h" - -#if defined(ENABLE_MONOTOUCH) && !defined(ENABLE_NETCORE) -#include "../../support/zlib-helper.c" -#elif defined(ENABLE_MONODROID) && !defined(ENABLE_NETCORE) -#include "../../support/nl.c" -#include "../../support/zlib-helper.c" -#else -MONO_EMPTY_SOURCE_FILE(empty); -#endif diff --git a/src/mono/mono/metadata/sysmath.c b/src/mono/mono/metadata/sysmath.c index b845711..3fcfbf1 100644 --- a/src/mono/mono/metadata/sysmath.c +++ b/src/mono/mono/metadata/sysmath.c @@ -188,7 +188,6 @@ ves_icall_System_Math_Ceiling (gdouble v) return ceil (v); } -#if ENABLE_NETCORE gint32 ves_icall_System_Math_ILogB (gdouble x) { @@ -211,7 +210,6 @@ ves_icall_System_Math_FusedMultiplyAdd (gdouble x, gdouble y, gdouble z) { return fma (x, y, z); } -#endif float ves_icall_System_MathF_Acos (float x) @@ -351,7 +349,6 @@ ves_icall_System_MathF_ModF (float x, float *d) return modff (x, d); } -#if ENABLE_NETCORE gint32 ves_icall_System_MathF_ILogB (float x) { @@ -374,4 +371,3 @@ ves_icall_System_MathF_FusedMultiplyAdd (float x, float y, float z) { return fmaf (x, y, z); } -#endif diff --git a/src/mono/mono/metadata/threadpool-io-epoll.c b/src/mono/mono/metadata/threadpool-io-epoll.c deleted file mode 100644 index 9a32744..0000000 --- a/src/mono/mono/metadata/threadpool-io-epoll.c +++ /dev/null @@ -1,139 +0,0 @@ -/** - * \file - */ - -#if defined(HAVE_EPOLL) - -#include - -#if defined(HOST_WIN32) -/* We assume that epoll is not available on windows */ -#error -#endif - -#define EPOLL_NEVENTS 128 - -static gint epoll_fd; -static struct epoll_event *epoll_events; - -static gboolean -epoll_init (gint wakeup_pipe_fd) -{ - struct epoll_event event; - -#ifdef EPOOL_CLOEXEC - epoll_fd = epoll_create1 (EPOLL_CLOEXEC); -#else - epoll_fd = epoll_create (256); - fcntl (epoll_fd, F_SETFD, FD_CLOEXEC); -#endif - - if (epoll_fd == -1) { -#ifdef EPOOL_CLOEXEC - g_error ("epoll_init: epoll (EPOLL_CLOEXEC) failed, error (%d) %s\n", errno, g_strerror (errno)); -#else - g_error ("epoll_init: epoll (256) failed, error (%d) %s\n", errno, g_strerror (errno)); -#endif - return FALSE; - } - - event.events = EPOLLIN; - event.data.fd = wakeup_pipe_fd; - if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, event.data.fd, &event) == -1) { - g_error ("epoll_init: epoll_ctl () failed, error (%d) %s", errno, g_strerror (errno)); - close (epoll_fd); - return FALSE; - } - - epoll_events = g_new0 (struct epoll_event, EPOLL_NEVENTS); - - return TRUE; -} - -static gboolean -epoll_can_register_fd (int fd) -{ - return TRUE; -} - -static void -epoll_register_fd (gint fd, gint events, gboolean is_new) -{ - struct epoll_event event; - -#ifndef EPOLLONESHOT -/* it was only defined on android in May 2013 */ -#define EPOLLONESHOT 0x40000000 -#endif - - event.data.fd = fd; - event.events = EPOLLONESHOT; - if ((events & EVENT_IN) != 0) - event.events |= EPOLLIN; - if ((events & EVENT_OUT) != 0) - event.events |= EPOLLOUT; - - if (epoll_ctl (epoll_fd, is_new ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, event.data.fd, &event) == -1) - g_error ("epoll_register_fd: epoll_ctl(%s) failed, error (%d) %s", is_new ? "EPOLL_CTL_ADD" : "EPOLL_CTL_MOD", errno, g_strerror (errno)); -} - -static void -epoll_remove_fd (gint fd) -{ - if (epoll_ctl (epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) - g_error ("epoll_remove_fd: epoll_ctl (EPOLL_CTL_DEL) failed, error (%d) %s", errno, g_strerror (errno)); -} - -static gint -epoll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data) -{ - gint i, ready; - - memset (epoll_events, 0, sizeof (struct epoll_event) * EPOLL_NEVENTS); - - mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC); - - MONO_ENTER_GC_SAFE; - ready = epoll_wait (epoll_fd, epoll_events, EPOLL_NEVENTS, -1); - MONO_EXIT_GC_SAFE; - - mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NONE); - - if (ready == -1) { - switch (errno) { - case EINTR: - ready = 0; - break; - default: - g_error ("epoll_event_wait: epoll_wait () failed, error (%d) %s", errno, g_strerror (errno)); - break; - } - } - - if (ready == -1) - return -1; - - for (i = 0; i < ready; ++i) { - gint fd, events = 0; - - fd = epoll_events [i].data.fd; - if (epoll_events [i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) - events |= EVENT_IN; - if (epoll_events [i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) - events |= EVENT_OUT; - - callback (fd, events, user_data); - } - - return 0; -} - -static ThreadPoolIOBackend backend_epoll = { - epoll_init, - epoll_can_register_fd, - epoll_register_fd, - epoll_remove_fd, - epoll_event_wait, -}; - -#endif diff --git a/src/mono/mono/metadata/threadpool-io-kqueue.c b/src/mono/mono/metadata/threadpool-io-kqueue.c deleted file mode 100644 index 6dd8196..0000000 --- a/src/mono/mono/metadata/threadpool-io-kqueue.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * \file - */ - -#if defined(HAVE_KQUEUE) - -#include -#include -#include - -#if defined(HOST_WIN32) -/* We assume that kqueue is not available on windows */ -#error -#endif - -#define KQUEUE_NEVENTS 128 - -static gint kqueue_fd; -static struct kevent *kqueue_events; - -static gint -KQUEUE_INIT_FD (gint fd, gint events, gint flags) -{ - struct kevent event; - EV_SET (&event, fd, events, flags, 0, 0, 0); - return kevent (kqueue_fd, &event, 1, NULL, 0, NULL); -} - -static gboolean -kqueue_init (gint wakeup_pipe_fd) -{ - kqueue_fd = kqueue (); - if (kqueue_fd == -1) { - g_error ("kqueue_init: kqueue () failed, error (%d) %s", errno, g_strerror (errno)); - return FALSE; - } - - if (KQUEUE_INIT_FD (wakeup_pipe_fd, EVFILT_READ, EV_ADD | EV_ENABLE) == -1) { - g_error ("kqueue_init: kevent () failed, error (%d) %s", errno, g_strerror (errno)); - close (kqueue_fd); - return FALSE; - } - - kqueue_events = g_new0 (struct kevent, KQUEUE_NEVENTS); - - return TRUE; -} - -static gboolean -kqueue_can_register_fd (int fd) -{ - return TRUE; -} - -static void -kqueue_register_fd (gint fd, gint events, gboolean is_new) -{ - if (events & EVENT_IN) { - if (KQUEUE_INIT_FD (fd, EVFILT_READ, EV_ADD | EV_ENABLE) == -1) - g_error ("kqueue_register_fd: kevent(read,enable) failed, error (%d) %s", errno, g_strerror (errno)); - } else { - if (KQUEUE_INIT_FD (fd, EVFILT_READ, EV_ADD | EV_DISABLE) == -1) - g_error ("kqueue_register_fd: kevent(read,disable) failed, error (%d) %s", errno, g_strerror (errno)); - } - if (events & EVENT_OUT) { - if (KQUEUE_INIT_FD (fd, EVFILT_WRITE, EV_ADD | EV_ENABLE) == -1) - g_error ("kqueue_register_fd: kevent(write,enable) failed, error (%d) %s", errno, g_strerror (errno)); - } else { - if (KQUEUE_INIT_FD (fd, EVFILT_WRITE, EV_ADD | EV_DISABLE) == -1) - g_error ("kqueue_register_fd: kevent(write,disable) failed, error (%d) %s", errno, g_strerror (errno)); - } - return; -} - -static void -kqueue_remove_fd (gint fd) -{ - /* FIXME: a race between closing and adding operation in the Socket managed code trigger a ENOENT error */ - if (KQUEUE_INIT_FD (fd, EVFILT_READ, EV_DELETE) == -1) - g_error ("kqueue_register_fd: kevent(read,delete) failed, error (%d) %s", errno, g_strerror (errno)); - if (KQUEUE_INIT_FD (fd, EVFILT_WRITE, EV_DELETE) == -1) - g_error ("kqueue_register_fd: kevent(write,delete) failed, error (%d) %s", errno, g_strerror (errno)); -} - -static gint -kqueue_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data) -{ - gint i, ready; - - memset (kqueue_events, 0, sizeof (struct kevent) * KQUEUE_NEVENTS); - - mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC); - - MONO_ENTER_GC_SAFE; - ready = kevent (kqueue_fd, NULL, 0, kqueue_events, KQUEUE_NEVENTS, NULL); - MONO_EXIT_GC_SAFE; - - mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NONE); - - if (ready == -1) { - switch (errno) { - case EINTR: - ready = 0; - break; - default: - g_error ("kqueue_event_wait: kevent () failed, error (%d) %s", errno, g_strerror (errno)); - break; - } - } - - if (ready == -1) - return -1; - - for (i = 0; i < ready; ++i) { - gint fd, events = 0; - - fd = kqueue_events [i].ident; - if (kqueue_events [i].filter == EVFILT_READ || (kqueue_events [i].flags & EV_ERROR) != 0) - events |= EVENT_IN; - if (kqueue_events [i].filter == EVFILT_WRITE || (kqueue_events [i].flags & EV_ERROR) != 0) - events |= EVENT_OUT; - - callback (fd, events, user_data); - } - - return 0; -} - -static ThreadPoolIOBackend backend_kqueue = { - .init = kqueue_init, - .can_register_fd = kqueue_can_register_fd, - .register_fd = kqueue_register_fd, - .remove_fd = kqueue_remove_fd, - .event_wait = kqueue_event_wait, -}; - -#endif diff --git a/src/mono/mono/metadata/threadpool-io-poll.c b/src/mono/mono/metadata/threadpool-io-poll.c deleted file mode 100644 index ac57194..0000000 --- a/src/mono/mono/metadata/threadpool-io-poll.c +++ /dev/null @@ -1,228 +0,0 @@ -/** - * \file - */ - -#include "utils/mono-poll.h" - -static mono_pollfd *poll_fds; -static guint poll_fds_capacity; -static guint poll_fds_size; - -static void -POLL_INIT_FD (mono_pollfd *poll_fd, gint fd, gint events) -{ - poll_fd->fd = fd; - poll_fd->events = events; - poll_fd->revents = 0; -} - -static gboolean -poll_init (gint wakeup_pipe_fd) -{ - g_assert (wakeup_pipe_fd >= 0); - - poll_fds_size = 1; - poll_fds_capacity = 64; - - poll_fds = g_new0 (mono_pollfd, poll_fds_capacity); - - POLL_INIT_FD (&poll_fds [0], wakeup_pipe_fd, MONO_POLLIN); - - return TRUE; -} - -static gboolean -poll_can_register_fd (int fd) -{ - return mono_poll_can_add (poll_fds, poll_fds_size, fd); -} - -static void -poll_register_fd (gint fd, gint events, gboolean is_new) -{ - gint i; - gint poll_event; - - g_assert (fd >= 0); - g_assert (poll_fds_size <= poll_fds_capacity); - - g_assert ((events & ~(EVENT_IN | EVENT_OUT)) == 0); - - poll_event = 0; - if (events & EVENT_IN) - poll_event |= MONO_POLLIN; - if (events & EVENT_OUT) - poll_event |= MONO_POLLOUT; - - for (i = 0; i < poll_fds_size; ++i) { - if (poll_fds [i].fd == fd) { - g_assert (!is_new); - POLL_INIT_FD (&poll_fds [i], fd, poll_event); - return; - } - } - - g_assert (is_new); - - for (i = 0; i < poll_fds_size; ++i) { - if (poll_fds [i].fd == -1) { - POLL_INIT_FD (&poll_fds [i], fd, poll_event); - return; - } - } - - poll_fds_size += 1; - - if (poll_fds_size > poll_fds_capacity) { - poll_fds_capacity *= 2; - g_assert (poll_fds_size <= poll_fds_capacity); - - poll_fds = (mono_pollfd *)g_renew (mono_pollfd, poll_fds, poll_fds_capacity); - } - - POLL_INIT_FD (&poll_fds [poll_fds_size - 1], fd, poll_event); - -} - -static void -poll_remove_fd (gint fd) -{ - gint i; - - g_assert (fd >= 0); - - for (i = 0; i < poll_fds_size; ++i) { - if (poll_fds [i].fd == fd) { - POLL_INIT_FD (&poll_fds [i], -1, 0); - break; - } - } - - /* if we don't find the fd in poll_fds, - * it means we try to delete it twice */ - g_assert (i < poll_fds_size); - - /* if we find it again, it means we added - * it twice */ - for (; i < poll_fds_size; ++i) - g_assert (poll_fds [i].fd != fd); - - /* reduce the value of poll_fds_size so we - * do not keep it too big */ - while (poll_fds_size > 1 && poll_fds [poll_fds_size - 1].fd == -1) - poll_fds_size -= 1; -} - -static gint -poll_mark_bad_fds (mono_pollfd *fds, gint size) -{ - gint i, ready = 0; - - for (i = 0; i < size; i++) { - if (fds [i].fd == -1) - continue; - - switch (mono_poll (&fds [i], 1, 0)) { - case 1: - ready++; - break; - case -1: - if (errno == EBADF) - { - fds [i].revents |= MONO_POLLNVAL; - ready++; - } - break; - } - } - - return ready; -} - -static gint -poll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data) -{ - gint i, ready; - - for (i = 0; i < poll_fds_size; ++i) - poll_fds [i].revents = 0; - - mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC); - - MONO_ENTER_GC_SAFE; - ready = mono_poll (poll_fds, poll_fds_size, -1); - MONO_EXIT_GC_SAFE; - - mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NONE); - - if (ready == -1) { - /* - * Apart from EINTR, we only check EBADF, for the rest: - * EINVAL: mono_poll() 'protects' us from descriptor - * numbers above the limit if using select() by marking - * then as POLLERR. If a system poll() is being - * used, the number of descriptor we're passing will not - * be over sysconf(_SC_OPEN_MAX), as the error would have - * happened when opening. - * - * EFAULT: we own the memory pointed by pfds. - * ENOMEM: we're doomed anyway - * - */ - switch (errno) - { - case EINTR: - { - ready = 0; - break; - } - case EBADF: - { - ready = poll_mark_bad_fds (poll_fds, poll_fds_size); - break; - } - default: - g_error ("poll_event_wait: mono_poll () failed, error (%d) %s", errno, g_strerror (errno)); - break; - } - } - - if (ready == -1) - return -1; - if (ready == 0) - return 0; - - g_assert (ready > 0); - - for (i = 0; i < poll_fds_size; ++i) { - gint fd, events = 0; - - if (poll_fds [i].fd == -1) - continue; - if (poll_fds [i].revents == 0) - continue; - - fd = poll_fds [i].fd; - if (poll_fds [i].revents & (MONO_POLLIN | MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)) - events |= EVENT_IN; - if (poll_fds [i].revents & (MONO_POLLOUT | MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)) - events |= EVENT_OUT; - if (poll_fds [i].revents & (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)) - events |= EVENT_ERR; - - callback (fd, events, user_data); - - if (--ready == 0) - break; - } - - return 0; -} - -static ThreadPoolIOBackend backend_poll = { - poll_init, - poll_can_register_fd, - poll_register_fd, - poll_remove_fd, - poll_event_wait, -}; diff --git a/src/mono/mono/metadata/threadpool-io.c b/src/mono/mono/metadata/threadpool-io.c deleted file mode 100644 index fdfef2d..0000000 --- a/src/mono/mono/metadata/threadpool-io.c +++ /dev/null @@ -1,751 +0,0 @@ -/** - * \file - * Microsoft IO threadpool runtime support - * - * Author: - * Ludovic Henry (ludovic.henry@xamarin.com) - * - * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#include - -#ifndef ENABLE_NETCORE - -#include -#include - -#ifndef DISABLE_SOCKETS - -#if defined(HOST_WIN32) -#include -#include -#else -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - gboolean (*init) (gint wakeup_pipe_fd); - gboolean (*can_register_fd) (int fd); - void (*register_fd) (gint fd, gint events, gboolean is_new); - void (*remove_fd) (gint fd); - gint (*event_wait) (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data); -} ThreadPoolIOBackend; - -/* Keep in sync with System.IOOperation in mcs/class/System/System/IOSelector.cs */ -enum MonoIOOperation { - EVENT_IN = 1 << 0, - EVENT_OUT = 1 << 1, - EVENT_ERR = 1 << 2, /* not in managed */ -}; - -#include "threadpool-io-epoll.c" -#include "threadpool-io-kqueue.c" -#include "threadpool-io-poll.c" - -#define UPDATES_CAPACITY 128 - -/* Keep in sync with System.IOSelectorJob in mcs/class/System/System/IOSelector.cs */ -struct _MonoIOSelectorJob { - MonoObject object; - gint32 operation; - MonoObject *callback; - MonoObject *state; -}; - -typedef enum { - UPDATE_EMPTY = 0, - UPDATE_ADD, - UPDATE_REMOVE_SOCKET, - UPDATE_REMOVE_DOMAIN, -} ThreadPoolIOUpdateType; - -typedef struct { - gint fd; - MonoIOSelectorJob *job; -} ThreadPoolIOUpdate_Add; - -typedef struct { - gint fd; -} ThreadPoolIOUpdate_RemoveSocket; - -typedef struct { - MonoDomain *domain; -} ThreadPoolIOUpdate_RemoveDomain; - -typedef struct { - ThreadPoolIOUpdateType type; - union { - ThreadPoolIOUpdate_Add add; - ThreadPoolIOUpdate_RemoveSocket remove_socket; - ThreadPoolIOUpdate_RemoveDomain remove_domain; - } data; -} ThreadPoolIOUpdate; - -typedef struct { - ThreadPoolIOBackend backend; - - ThreadPoolIOUpdate updates [UPDATES_CAPACITY]; - gint updates_size; - MonoCoopMutex updates_lock; - MonoCoopCond updates_cond; - -#if !defined(HOST_WIN32) - gint wakeup_pipes [2]; -#else - SOCKET wakeup_pipes [2]; -#endif -} ThreadPoolIO; - -static mono_lazy_init_t io_status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; - -static gboolean io_selector_running = FALSE; - -static ThreadPoolIO* threadpool_io; - -static MonoIOSelectorJob* -get_job_for_event (MonoMList **list, gint32 event) -{ - MonoMList *current; - - g_assert (list); - - for (current = *list; current; current = mono_mlist_next (current)) { - MonoIOSelectorJob *job = (MonoIOSelectorJob*) mono_mlist_get_data (current); - if (job->operation == event) { - *list = mono_mlist_remove_item (*list, current); - mono_mlist_set_data (current, NULL); - return job; - } - } - - return NULL; -} - -static gint -get_operations_for_jobs (MonoMList *list) -{ - MonoMList *current; - gint operations = 0; - - for (current = list; current; current = mono_mlist_next (current)) - operations |= ((MonoIOSelectorJob*) mono_mlist_get_data (current))->operation; - - return operations; -} - -static void -selector_thread_wakeup (void) -{ - gchar msg = 'c'; - gint written; - - for (;;) { -#if !defined(HOST_WIN32) - written = write (threadpool_io->wakeup_pipes [1], &msg, 1); - if (written == 1) - break; - if (written == -1) { - g_warning ("selector_thread_wakeup: write () failed, error (%d) %s\n", errno, g_strerror (errno)); - break; - } -#else - written = send (threadpool_io->wakeup_pipes [1], &msg, 1, 0); - if (written == 1) - break; - if (written == SOCKET_ERROR) { - g_warning ("selector_thread_wakeup: write () failed, error (%d)\n", WSAGetLastError ()); - break; - } -#endif - } -} - -static void -selector_thread_wakeup_drain_pipes (void) -{ - gchar buffer [128]; - gint received; - - for (;;) { -#if !defined(HOST_WIN32) - received = read (threadpool_io->wakeup_pipes [0], buffer, sizeof (buffer)); - if (received == 0) - break; - if (received == -1) { -#ifdef ERESTART - /* - * some unices (like AIX) send ERESTART, which doesn't - * exist on some other OSes errno - */ - if (errno != EINTR && errno != EAGAIN && errno != ERESTART) -#else - if (errno != EINTR && errno != EAGAIN) -#endif - g_warning ("selector_thread_wakeup_drain_pipes: read () failed, error (%d) %s\n", errno, g_strerror (errno)); - break; - } -#else - received = recv (threadpool_io->wakeup_pipes [0], buffer, sizeof (buffer), 0); - if (received == 0) - break; - if (received == SOCKET_ERROR) { - if (WSAGetLastError () != WSAEINTR && WSAGetLastError () != WSAEWOULDBLOCK) - g_warning ("selector_thread_wakeup_drain_pipes: recv () failed, error (%d)\n", WSAGetLastError ()); - break; - } -#endif - } -} - -typedef struct { - MonoDomain *domain; - MonoGHashTable *states; -} FilterSockaresForDomainData; - -static void -filter_jobs_for_domain (gpointer key, gpointer value, gpointer user_data) -{ - FilterSockaresForDomainData *data; - MonoMList *list = (MonoMList *)value, *element; - MonoDomain *domain; - MonoGHashTable *states; - - g_assert (user_data); - data = (FilterSockaresForDomainData *)user_data; - domain = data->domain; - states = data->states; - - for (element = list; element; element = mono_mlist_next (element)) { - MonoIOSelectorJob *job = (MonoIOSelectorJob*) mono_mlist_get_data (element); - if (mono_object_domain (job) == domain) - mono_mlist_set_data (element, NULL); - } - - /* we skip all the first elements which are NULL */ - for (; list; list = mono_mlist_next (list)) { - if (mono_mlist_get_data (list)) - break; - } - - if (list) { - g_assert (mono_mlist_get_data (list)); - - /* we delete all the NULL elements after the first one */ - for (element = list; element;) { - MonoMList *next; - if (!(next = mono_mlist_next (element))) - break; - if (mono_mlist_get_data (next)) - element = next; - else - mono_mlist_set_next (element, mono_mlist_next (next)); - } - } - - mono_g_hash_table_replace (states, key, list); -} - -static void -wait_callback (gint fd, gint events, gpointer user_data) -{ - ERROR_DECL (error); - - if (mono_runtime_is_shutting_down ()) - return; - - if (fd == threadpool_io->wakeup_pipes [0]) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: wke"); - selector_thread_wakeup_drain_pipes (); - } else { - MonoGHashTable *states; - MonoMList *list = NULL; - gpointer k; - gboolean remove_fd = FALSE; - gint operations; - - g_assert (user_data); - states = (MonoGHashTable *)user_data; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: cal fd %3d, events = %2s | %2s | %3s", - fd, (events & EVENT_IN) ? "RD" : "..", (events & EVENT_OUT) ? "WR" : "..", (events & EVENT_ERR) ? "ERR" : "..."); - - if (!mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list)) - g_error ("wait_callback: fd %d not found in states table", fd); - - if (list && (events & EVENT_IN) != 0) { - MonoIOSelectorJob *job = get_job_for_event (&list, EVENT_IN); - if (job) { - mono_threadpool_enqueue_work_item (((MonoObject*) job)->vtable->domain, (MonoObject*) job, error); - mono_error_assert_ok (error); - } - - } - if (list && (events & EVENT_OUT) != 0) { - MonoIOSelectorJob *job = get_job_for_event (&list, EVENT_OUT); - if (job) { - mono_threadpool_enqueue_work_item (((MonoObject*) job)->vtable->domain, (MonoObject*) job, error); - mono_error_assert_ok (error); - } - } - - remove_fd = (events & EVENT_ERR) == EVENT_ERR; - if (!remove_fd) { - mono_g_hash_table_replace (states, GINT_TO_POINTER (fd), list); - - operations = get_operations_for_jobs (list); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: res fd %3d, events = %2s | %2s | %3s", - fd, (operations & EVENT_IN) ? "RD" : "..", (operations & EVENT_OUT) ? "WR" : "..", (operations & EVENT_ERR) ? "ERR" : "..."); - - threadpool_io->backend.register_fd (fd, operations, FALSE); - } else { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: err fd %d", fd); - - mono_g_hash_table_remove (states, GINT_TO_POINTER (fd)); - - threadpool_io->backend.remove_fd (fd); - } - } -} - -static void -selector_thread_interrupt (gpointer unused) -{ - selector_thread_wakeup (); -} - -static gsize WINAPI -selector_thread (gpointer data) -{ - MonoGHashTable *states; - - mono_thread_set_name_constant_ignore_error (mono_thread_internal_current (), "Thread Pool I/O Selector", MonoSetThreadNameFlag_Reset); - - ERROR_DECL (error); - - if (mono_runtime_is_shutting_down ()) { - io_selector_running = FALSE; - return 0; - } - - states = mono_g_hash_table_new_type_internal (g_direct_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREAD_POOL, NULL, "Thread Pool I/O State Table"); - - while (!mono_runtime_is_shutting_down ()) { - gint i, j; - gint res; - gboolean interrupted = FALSE; - - if (mono_thread_interruption_checkpoint_bool ()) - continue; - - mono_coop_mutex_lock (&threadpool_io->updates_lock); - - for (i = 0; i < threadpool_io->updates_size; ++i) { - ThreadPoolIOUpdate *update = &threadpool_io->updates [i]; - - switch (update->type) { - case UPDATE_EMPTY: - break; - case UPDATE_ADD: { - gint fd; - gint operations; - gpointer k; - gboolean exists; - MonoMList *list = NULL; - MonoIOSelectorJob *job; - - fd = update->data.add.fd; - g_assert (fd >= 0); - - job = update->data.add.job; - g_assert (job); - - exists = mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list); - list = mono_mlist_append_checked (list, (MonoObject*) job, error); - mono_error_assert_ok (error); - mono_g_hash_table_replace (states, GINT_TO_POINTER (fd), list); - - operations = get_operations_for_jobs (list); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: %3s fd %3d, operations = %2s | %2s | %3s", - exists ? "mod" : "add", fd, (operations & EVENT_IN) ? "RD" : "..", (operations & EVENT_OUT) ? "WR" : "..", (operations & EVENT_ERR) ? "ERR" : "..."); - - threadpool_io->backend.register_fd (fd, operations, !exists); - - break; - } - case UPDATE_REMOVE_SOCKET: { - gint fd; - gpointer k; - MonoMList *list = NULL; - - fd = update->data.remove_socket.fd; - g_assert (fd >= 0); - - if (mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list)) { - mono_g_hash_table_remove (states, GINT_TO_POINTER (fd)); - - for (j = i + 1; j < threadpool_io->updates_size; ++j) { - ThreadPoolIOUpdate *update = &threadpool_io->updates [j]; - if (update->type == UPDATE_ADD && update->data.add.fd == fd) - memset (update, 0, sizeof (ThreadPoolIOUpdate)); - } - - for (; list; list = mono_mlist_remove_item (list, list)) { - mono_threadpool_enqueue_work_item (mono_object_domain (mono_mlist_get_data (list)), mono_mlist_get_data (list), error); - mono_mlist_set_data (list, NULL); - mono_error_assert_ok (error); - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: del fd %3d", fd); - threadpool_io->backend.remove_fd (fd); - } - - break; - } - case UPDATE_REMOVE_DOMAIN: { - MonoDomain *domain; - - domain = update->data.remove_domain.domain; - g_assert (domain); - - FilterSockaresForDomainData user_data; - memset (&user_data, 0, sizeof (user_data)); - user_data.domain = domain; - user_data.states = states; - mono_g_hash_table_foreach (states, filter_jobs_for_domain, &user_data); - - for (j = i + 1; j < threadpool_io->updates_size; ++j) { - ThreadPoolIOUpdate *update = &threadpool_io->updates [j]; - if (update->type == UPDATE_ADD && mono_object_domain (update->data.add.job) == domain) - memset (update, 0, sizeof (ThreadPoolIOUpdate)); - } - - break; - } - default: - g_assert_not_reached (); - } - } - - mono_coop_cond_broadcast (&threadpool_io->updates_cond); - - if (threadpool_io->updates_size > 0) { - threadpool_io->updates_size = 0; - memset (&threadpool_io->updates, 0, UPDATES_CAPACITY * sizeof (ThreadPoolIOUpdate)); - } - - mono_coop_mutex_unlock (&threadpool_io->updates_lock); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_SELECTOR, "io threadpool: wai"); - - mono_thread_info_install_interrupt (selector_thread_interrupt, NULL, &interrupted); - if (interrupted) - continue; - - res = threadpool_io->backend.event_wait (wait_callback, states); - if (res == -1) - break; - - mono_thread_info_uninstall_interrupt (&interrupted); - } - - mono_g_hash_table_destroy (states); - - mono_coop_mutex_lock (&threadpool_io->updates_lock); - - io_selector_running = FALSE; - mono_coop_cond_broadcast (&threadpool_io->updates_cond); - - mono_coop_mutex_unlock (&threadpool_io->updates_lock); - - return 0; -} - -/* Locking: threadpool_io->updates_lock must be held */ -static ThreadPoolIOUpdate* -update_get_new (void) -{ - ThreadPoolIOUpdate *update = NULL; - g_assert (threadpool_io->updates_size <= UPDATES_CAPACITY); - - while (threadpool_io->updates_size == UPDATES_CAPACITY) { - /* we wait for updates to be applied in the selector_thread and we loop - * as long as none are available. if it happends too much, then we need - * to increase UPDATES_CAPACITY */ - mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); - } - - g_assert (threadpool_io->updates_size < UPDATES_CAPACITY); - - update = &threadpool_io->updates [threadpool_io->updates_size ++]; - - return update; -} - -static void -wakeup_pipes_init (void) -{ -#if !defined(HOST_WIN32) - if (pipe (threadpool_io->wakeup_pipes) == -1) - g_error ("wakeup_pipes_init: pipe () failed, error (%d) %s\n", errno, g_strerror (errno)); - if (fcntl (threadpool_io->wakeup_pipes [0], F_SETFL, O_NONBLOCK) == -1) - g_error ("wakeup_pipes_init: fcntl () failed, error (%d) %s\n", errno, g_strerror (errno)); -#else - struct sockaddr_in client; - struct sockaddr_in server; - SOCKET server_sock; - gulong arg; - gint size; - - server_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - g_assert (server_sock != INVALID_SOCKET); - threadpool_io->wakeup_pipes [1] = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - g_assert (threadpool_io->wakeup_pipes [1] != INVALID_SOCKET); - - server.sin_family = AF_INET; - server.sin_port = 0; - inet_pton (server.sin_family, "127.0.0.1", &server.sin_addr); - if (bind (server_sock, (SOCKADDR*) &server, sizeof (server)) == SOCKET_ERROR) { - closesocket (server_sock); - g_error ("wakeup_pipes_init: bind () failed, error (%d)\n", WSAGetLastError ()); - } - - size = sizeof (server); - if (getsockname (server_sock, (SOCKADDR*) &server, &size) == SOCKET_ERROR) { - closesocket (server_sock); - g_error ("wakeup_pipes_init: getsockname () failed, error (%d)\n", WSAGetLastError ()); - } - if (listen (server_sock, 1024) == SOCKET_ERROR) { - closesocket (server_sock); - g_error ("wakeup_pipes_init: listen () failed, error (%d)\n", WSAGetLastError ()); - } - if (connect ((SOCKET) threadpool_io->wakeup_pipes [1], (SOCKADDR*) &server, sizeof (server)) == SOCKET_ERROR) { - closesocket (server_sock); - g_error ("wakeup_pipes_init: connect () failed, error (%d)\n", WSAGetLastError ()); - } - - size = sizeof (client); - threadpool_io->wakeup_pipes [0] = accept (server_sock, (SOCKADDR *) &client, &size); - g_assert (threadpool_io->wakeup_pipes [0] != INVALID_SOCKET); - - arg = 1; - if (ioctlsocket (threadpool_io->wakeup_pipes [0], FIONBIO, &arg) == SOCKET_ERROR) { - closesocket (threadpool_io->wakeup_pipes [0]); - closesocket (server_sock); - g_error ("wakeup_pipes_init: ioctlsocket () failed, error (%d)\n", WSAGetLastError ()); - } - - closesocket (server_sock); -#endif -} - -static void -initialize (void) -{ - g_assert (!threadpool_io); - threadpool_io = g_new0 (ThreadPoolIO, 1); - g_assert (threadpool_io); - - mono_coop_mutex_init (&threadpool_io->updates_lock); - mono_coop_cond_init (&threadpool_io->updates_cond); - mono_gc_register_root ((char *)&threadpool_io->updates [0], sizeof (threadpool_io->updates), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_THREAD_POOL, NULL, "Thread Pool I/O Update List"); - - threadpool_io->updates_size = 0; - - threadpool_io->backend = backend_poll; - if (g_hasenv ("MONO_ENABLE_AIO")) { -#if defined(HAVE_EPOLL) - threadpool_io->backend = backend_epoll; -#elif defined(HAVE_KQUEUE) - threadpool_io->backend = backend_kqueue; -#endif - } - - wakeup_pipes_init (); - - if (!threadpool_io->backend.init (threadpool_io->wakeup_pipes [0])) - g_error ("initialize: backend->init () failed"); - - mono_coop_mutex_lock (&threadpool_io->updates_lock); - - io_selector_running = TRUE; - - ERROR_DECL (error); - if (!mono_thread_create_internal (mono_get_root_domain (), (gpointer)selector_thread, NULL, (MonoThreadCreateFlags)(MONO_THREAD_CREATE_FLAGS_THREADPOOL | MONO_THREAD_CREATE_FLAGS_SMALL_STACK), error)) - g_error ("initialize: mono_thread_create_internal () failed due to %s", mono_error_get_message (error)); - - mono_coop_mutex_unlock (&threadpool_io->updates_lock); -} - -static void -cleanup (void) -{ - // FIXME destroy everything -} - -void -mono_threadpool_io_cleanup (void) -{ - mono_lazy_cleanup (&io_status, cleanup); -} - -#ifndef ENABLE_NETCORE -void -ves_icall_System_IOSelector_Add (gpointer handle, MonoIOSelectorJobHandle job_handle, MonoError* error) -{ - MonoIOSelectorJob* const job = MONO_HANDLE_RAW (job_handle); - ThreadPoolIOUpdate *update; - - g_assert (handle); - - g_assert ((job->operation == EVENT_IN) ^ (job->operation == EVENT_OUT)); - g_assert (job->callback); - - if (mono_runtime_is_shutting_down ()) - return; - if (mono_domain_is_unloading (mono_object_domain (job))) - return; - - mono_lazy_initialize (&io_status, initialize); - - mono_coop_mutex_lock (&threadpool_io->updates_lock); - - if (!io_selector_running) { - mono_coop_mutex_unlock (&threadpool_io->updates_lock); - return; - } - - int const fd = GPOINTER_TO_INT (handle); - - if (!threadpool_io->backend.can_register_fd (fd)) { - mono_coop_mutex_unlock (&threadpool_io->updates_lock); - mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_IO_SELECTOR, "Could not register to wait for file descriptor %d", fd); - mono_error_set_not_supported (error, "Could not register to wait for file descriptor %d", fd); - return; - } - - update = update_get_new (); - update->type = UPDATE_ADD; - update->data.add.fd = fd; - update->data.add.job = job; - mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ - - selector_thread_wakeup (); - - mono_coop_mutex_unlock (&threadpool_io->updates_lock); -} -#endif - -void -ves_icall_System_IOSelector_Remove (gpointer handle) -{ - mono_threadpool_io_remove_socket (GPOINTER_TO_INT (handle)); -} - -void -mono_threadpool_io_remove_socket (int fd) -{ - ThreadPoolIOUpdate *update; - - if (!mono_lazy_is_initialized (&io_status)) - return; - - mono_coop_mutex_lock (&threadpool_io->updates_lock); - - if (!io_selector_running) { - mono_coop_mutex_unlock (&threadpool_io->updates_lock); - return; - } - - update = update_get_new (); - update->type = UPDATE_REMOVE_SOCKET; - update->data.remove_socket.fd = fd; - mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ - - selector_thread_wakeup (); - - mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); - - mono_coop_mutex_unlock (&threadpool_io->updates_lock); -} - -void -mono_threadpool_io_remove_domain_jobs (MonoDomain *domain) -{ - ThreadPoolIOUpdate *update; - - if (!mono_lazy_is_initialized (&io_status)) - return; - - mono_coop_mutex_lock (&threadpool_io->updates_lock); - - if (!io_selector_running) { - mono_coop_mutex_unlock (&threadpool_io->updates_lock); - return; - } - - update = update_get_new (); - update->type = UPDATE_REMOVE_DOMAIN; - update->data.remove_domain.domain = domain; - mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ - - selector_thread_wakeup (); - - mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); - - mono_coop_mutex_unlock (&threadpool_io->updates_lock); -} - -#else - -void -ves_icall_System_IOSelector_Add (gpointer handle, MonoIOSelectorJobHandle job_handle, MonoError* error) -{ - g_assert_not_reached (); -} - -void -ves_icall_System_IOSelector_Remove (gpointer handle) -{ - g_assert_not_reached (); -} - -void -mono_threadpool_io_cleanup (void) -{ - g_assert_not_reached (); -} - -void -mono_threadpool_io_remove_socket (int fd) -{ - g_assert_not_reached (); -} - -void -mono_threadpool_io_remove_domain_jobs (MonoDomain *domain) -{ - g_assert_not_reached (); -} - -#endif - -#endif /* !ENABLE_NETCORE */ - -MONO_EMPTY_SOURCE_FILE (threadpool_io); diff --git a/src/mono/mono/metadata/threadpool-io.h b/src/mono/mono/metadata/threadpool-io.h deleted file mode 100644 index 7a51863..0000000 --- a/src/mono/mono/metadata/threadpool-io.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * \file - */ - -#ifndef _MONO_METADATA_THREADPOOL_IO_H_ -#define _MONO_METADATA_THREADPOOL_IO_H_ - -#include -#include - -#ifndef ENABLE_NETCORE - -#include -#include - -typedef struct _MonoIOSelectorJob MonoIOSelectorJob; - -TYPED_HANDLE_DECL (MonoIOSelectorJob); - -ICALL_EXPORT -void -ves_icall_System_IOSelector_Remove (gpointer handle); - -void -mono_threadpool_io_remove_socket (int fd); -void -mono_threadpool_io_remove_domain_jobs (MonoDomain *domain); -void -mono_threadpool_io_cleanup (void); - -#endif /* ENABLE_NETCORE */ - -#endif /* _MONO_METADATA_THREADPOOL_IO_H_ */ diff --git a/src/mono/mono/metadata/threadpool-worker-default.c b/src/mono/mono/metadata/threadpool-worker-default.c deleted file mode 100644 index 27844ab..0000000 --- a/src/mono/mono/metadata/threadpool-worker-default.c +++ /dev/null @@ -1,1236 +0,0 @@ -/** - * \file - * native threadpool worker - * - * Author: - * Ludovic Henry (ludovic.henry@xamarin.com) - * - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#define _USE_MATH_DEFINES // needed by MSVC to define math constants -#include -#include -#include - -#ifndef ENABLE_NETCORE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // This header has defines to muck with names, so put it late. - -#define CPU_USAGE_LOW 80 -#define CPU_USAGE_HIGH 95 - -#define MONITOR_INTERVAL 500 // ms -#define MONITOR_MINIMAL_LIFETIME 60 * 1000 // ms - -#define WORKER_CREATION_MAX_PER_SEC 10 - -/* The exponent to apply to the gain. 1.0 means to use linear gain, - * higher values will enhance large moves and damp small ones. - * default: 2.0 */ -#define HILL_CLIMBING_GAIN_EXPONENT 2.0 - -/* The 'cost' of a thread. 0 means drive for increased throughput regardless - * of thread count, higher values bias more against higher thread counts. - * default: 0.15 */ -#define HILL_CLIMBING_BIAS 0.15 - -#define HILL_CLIMBING_WAVE_PERIOD 4 -#define HILL_CLIMBING_MAX_WAVE_MAGNITUDE 20 -#define HILL_CLIMBING_WAVE_MAGNITUDE_MULTIPLIER 1.0 -#define HILL_CLIMBING_WAVE_HISTORY_SIZE 8 -#define HILL_CLIMBING_TARGET_SIGNAL_TO_NOISE_RATIO 3.0 -#define HILL_CLIMBING_MAX_CHANGE_PER_SECOND 4 -#define HILL_CLIMBING_MAX_CHANGE_PER_SAMPLE 20 -#define HILL_CLIMBING_SAMPLE_INTERVAL_LOW 10 -#define HILL_CLIMBING_SAMPLE_INTERVAL_HIGH 200 -#define HILL_CLIMBING_ERROR_SMOOTHING_FACTOR 0.01 -#define HILL_CLIMBING_MAX_SAMPLE_ERROR_PERCENT 0.15 - -typedef enum { - TRANSITION_WARMUP, - TRANSITION_INITIALIZING, - TRANSITION_RANDOM_MOVE, - TRANSITION_CLIMBING_MOVE, - TRANSITION_CHANGE_POINT, - TRANSITION_STABILIZING, - TRANSITION_STARVATION, - TRANSITION_THREAD_TIMED_OUT, - TRANSITION_UNDEFINED, -} ThreadPoolHeuristicStateTransition; - -typedef struct { - gint32 wave_period; - gint32 samples_to_measure; - gdouble target_throughput_ratio; - gdouble target_signal_to_noise_ratio; - gdouble max_change_per_second; - gdouble max_change_per_sample; - gint32 max_thread_wave_magnitude; - gint32 sample_interval_low; - gdouble thread_magnitude_multiplier; - gint32 sample_interval_high; - gdouble throughput_error_smoothing_factor; - gdouble gain_exponent; - gdouble max_sample_error; - - gdouble current_control_setting; - gint64 total_samples; - gint16 last_thread_count; - gdouble elapsed_since_last_change; - gdouble completions_since_last_change; - - gdouble average_throughput_noise; - - gdouble *samples; - gdouble *thread_counts; - - guint32 current_sample_interval; - - gint32 accumulated_completion_count; - gdouble accumulated_sample_duration; -} ThreadPoolHillClimbing; - -typedef union { - struct { - gint16 max_working; /* determined by heuristic */ - gint16 starting; /* starting, but not yet in worker_thread */ - gint16 working; /* executing worker_thread */ - gint16 parked; /* parked */ - } _; - gint64 as_gint64; -} ThreadPoolWorkerCounter -#ifdef __GNUC__ -__attribute__((aligned(64))) -#endif -; - -typedef struct { - MonoRefCount ref; - - MonoThreadPoolWorkerCallback callback; - - ThreadPoolWorkerCounter counters; - - MonoCoopSem parked_threads_sem; - gint32 parked_threads_count; - - volatile gint32 work_items_count; - - guint32 worker_creation_current_second; - guint32 worker_creation_current_count; - MonoCoopMutex worker_creation_lock; - - gint32 heuristic_completions; - gint64 heuristic_sample_start; - gint64 heuristic_last_dequeue; // ms - gint64 heuristic_last_adjustment; // ms - gint64 heuristic_adjustment_interval; // ms - ThreadPoolHillClimbing heuristic_hill_climbing; - MonoCoopMutex heuristic_lock; - - gint32 limit_worker_min; - gint32 limit_worker_max; - - MonoCpuUsageState *cpu_usage_state; - gint32 cpu_usage; - - /* suspended by the debugger */ - gboolean suspended; - - gint32 monitor_status; -} ThreadPoolWorker; - -enum { - MONITOR_STATUS_REQUESTED, - MONITOR_STATUS_WAITING_FOR_REQUEST, - MONITOR_STATUS_NOT_RUNNING, -}; - -static ThreadPoolWorker worker; - -#define COUNTER_CHECK(counter) \ - do { \ - g_assert (counter._.max_working > 0); \ - g_assert (counter._.starting >= 0); \ - g_assert (counter._.working >= 0); \ - } while (0) - -#define COUNTER_ATOMIC(var,block) \ - do { \ - ThreadPoolWorkerCounter __old; \ - do { \ - __old = COUNTER_READ (); \ - (var) = __old; \ - { block; } \ - COUNTER_CHECK (var); \ - } while (mono_atomic_cas_i64 (&worker.counters.as_gint64, (var).as_gint64, __old.as_gint64) != __old.as_gint64); \ - } while (0) - -static ThreadPoolWorkerCounter -COUNTER_READ (void) -{ - ThreadPoolWorkerCounter counter; - counter.as_gint64 = mono_atomic_load_i64 (&worker.counters.as_gint64); - return counter; -} - -static gint16 -counter_num_active (ThreadPoolWorkerCounter counter) -{ - gint16 num_active = counter._.starting + counter._.working + counter._.parked; - g_assert (num_active >= 0); - return num_active; -} - -static guint32 -rand_next (guint32 min, guint32 max) -{ - ERROR_DECL (error); - -#ifdef HOST_WIN32 - guint32 val = (rand () % (max - min)) + min; -#else - guint32 val = (random () % (max - min)) + min; -#endif - - // FIXME handle error - mono_error_assert_ok (error); - return val; -} - -static void -destroy (gpointer data) -{ - mono_coop_sem_destroy (&worker.parked_threads_sem); - - mono_coop_mutex_destroy (&worker.worker_creation_lock); - - mono_coop_mutex_destroy (&worker.heuristic_lock); - - g_free (worker.cpu_usage_state); -} - -void -mono_threadpool_worker_init (MonoThreadPoolWorkerCallback callback) -{ - ThreadPoolHillClimbing *hc; - const char *threads_per_cpu_env; - gint threads_per_cpu; - gint threads_count; - - mono_refcount_init (&worker, destroy); - - worker.callback = callback; - - mono_coop_sem_init (&worker.parked_threads_sem, 0); - worker.parked_threads_count = 0; - - worker.worker_creation_current_second = -1; - mono_coop_mutex_init (&worker.worker_creation_lock); - - worker.heuristic_adjustment_interval = 10; - mono_coop_mutex_init (&worker.heuristic_lock); - - hc = &worker.heuristic_hill_climbing; - - hc->wave_period = HILL_CLIMBING_WAVE_PERIOD; - hc->max_thread_wave_magnitude = HILL_CLIMBING_MAX_WAVE_MAGNITUDE; - hc->thread_magnitude_multiplier = (gdouble) HILL_CLIMBING_WAVE_MAGNITUDE_MULTIPLIER; - hc->samples_to_measure = hc->wave_period * HILL_CLIMBING_WAVE_HISTORY_SIZE; - hc->target_throughput_ratio = (gdouble) HILL_CLIMBING_BIAS; - hc->target_signal_to_noise_ratio = (gdouble) HILL_CLIMBING_TARGET_SIGNAL_TO_NOISE_RATIO; - hc->max_change_per_second = (gdouble) HILL_CLIMBING_MAX_CHANGE_PER_SECOND; - hc->max_change_per_sample = (gdouble) HILL_CLIMBING_MAX_CHANGE_PER_SAMPLE; - hc->sample_interval_low = HILL_CLIMBING_SAMPLE_INTERVAL_LOW; - hc->sample_interval_high = HILL_CLIMBING_SAMPLE_INTERVAL_HIGH; - hc->throughput_error_smoothing_factor = (gdouble) HILL_CLIMBING_ERROR_SMOOTHING_FACTOR; - hc->gain_exponent = (gdouble) HILL_CLIMBING_GAIN_EXPONENT; - hc->max_sample_error = (gdouble) HILL_CLIMBING_MAX_SAMPLE_ERROR_PERCENT; - hc->current_control_setting = 0; - hc->total_samples = 0; - hc->last_thread_count = 0; - hc->average_throughput_noise = 0; - hc->elapsed_since_last_change = 0; - hc->accumulated_completion_count = 0; - hc->accumulated_sample_duration = 0; - hc->samples = g_new0 (gdouble, hc->samples_to_measure); - hc->thread_counts = g_new0 (gdouble, hc->samples_to_measure); - hc->current_sample_interval = rand_next (hc->sample_interval_low, hc->sample_interval_high); - - if (!(threads_per_cpu_env = g_getenv ("MONO_THREADS_PER_CPU"))) - threads_per_cpu = 1; - else - threads_per_cpu = CLAMP (atoi (threads_per_cpu_env), 1, 50); - - threads_count = mono_cpu_count () * threads_per_cpu; - - worker.limit_worker_min = threads_count; - -#if defined (HOST_ANDROID) || defined (HOST_IOS) - worker.limit_worker_max = CLAMP (threads_count * 100, MIN (threads_count, 200), MAX (threads_count, 200)); -#else - worker.limit_worker_max = threads_count * 100; -#endif - - worker.counters._.max_working = worker.limit_worker_min; - - worker.cpu_usage_state = g_new0 (MonoCpuUsageState, 1); - - worker.suspended = FALSE; - - worker.monitor_status = MONITOR_STATUS_NOT_RUNNING; -} - -void -mono_threadpool_worker_cleanup (void) -{ - mono_refcount_dec (&worker); -} - -static void -work_item_push (void) -{ - gint32 old, new_; - - do { - old = mono_atomic_load_i32 (&worker.work_items_count); - g_assert (old >= 0); - - new_ = old + 1; - } while (mono_atomic_cas_i32 (&worker.work_items_count, new_, old) != old); -} - -static gboolean -work_item_try_pop (void) -{ - gint32 old, new_; - - do { - old = mono_atomic_load_i32 (&worker.work_items_count); - g_assert (old >= 0); - - if (old == 0) - return FALSE; - - new_ = old - 1; - } while (mono_atomic_cas_i32 (&worker.work_items_count, new_, old) != old); - - return TRUE; -} - -static gint32 -work_item_count (void) -{ - return mono_atomic_load_i32 (&worker.work_items_count); -} - -static void worker_request (void); - -void -mono_threadpool_worker_request (void) -{ - if (!mono_refcount_tryinc (&worker)) - return; - - work_item_push (); - - worker_request (); - - mono_refcount_dec (&worker); -} - -/* return TRUE if timeout, FALSE otherwise (worker unpark or interrupt) */ -static gboolean -worker_park (void) -{ - gboolean timeout = FALSE; - gboolean interrupted = FALSE; - gint32 old, new_; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker parking", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - if (!mono_runtime_is_shutting_down ()) { - ThreadPoolWorkerCounter counter; - - COUNTER_ATOMIC (counter, { - counter._.working --; - counter._.parked ++; - }); - - do { - old = mono_atomic_load_i32 (&worker.parked_threads_count); - g_assert (old >= G_MININT32); - - new_ = old + 1; - } while (mono_atomic_cas_i32 (&worker.parked_threads_count, new_, old) != old); - - switch (mono_coop_sem_timedwait (&worker.parked_threads_sem, rand_next (5 * 1000, 60 * 1000), MONO_SEM_FLAGS_ALERTABLE)) { - case MONO_SEM_TIMEDWAIT_RET_SUCCESS: - break; - case MONO_SEM_TIMEDWAIT_RET_ALERTED: - interrupted = TRUE; - break; - case MONO_SEM_TIMEDWAIT_RET_TIMEDOUT: - timeout = TRUE; - break; - default: - g_assert_not_reached (); - } - - if (interrupted || timeout) { - /* If the semaphore was posted, then worker.parked_threads_count was decremented in worker_try_unpark */ - do { - old = mono_atomic_load_i32 (&worker.parked_threads_count); - g_assert (old > G_MININT32); - - new_ = old - 1; - } while (mono_atomic_cas_i32 (&worker.parked_threads_count, new_, old) != old); - } - - COUNTER_ATOMIC (counter, { - counter._.working ++; - counter._.parked --; - }); - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker unparking, timeout? %s interrupted? %s", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), timeout ? "yes" : "no", interrupted ? "yes" : "no"); - - return timeout; -} - -static gboolean -worker_try_unpark (void) -{ - gboolean res = TRUE; - gint32 old, new_; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try unpark worker", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - do { - old = mono_atomic_load_i32 (&worker.parked_threads_count); - g_assert (old > G_MININT32); - - if (old <= 0) { - res = FALSE; - break; - } - - new_ = old - 1; - } while (mono_atomic_cas_i32 (&worker.parked_threads_count, new_, old) != old); - - if (res) - mono_coop_sem_post (&worker.parked_threads_sem); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try unpark worker, success? %s", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), res ? "yes" : "no"); - - return res; -} - -static void hill_climbing_force_change (gint16 new_thread_count, ThreadPoolHeuristicStateTransition transition); - -static gsize WINAPI -worker_thread (gpointer unused) -{ - MonoInternalThread *thread; - ThreadPoolWorkerCounter counter; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker starting", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - if (!mono_refcount_tryinc (&worker)) - return 0; - - COUNTER_ATOMIC (counter, { - counter._.starting --; - counter._.working ++; - }); - - thread = mono_thread_internal_current (); - g_assert (thread); - - gboolean worker_timed_out = FALSE; - while (!mono_runtime_is_shutting_down ()) { - if (mono_thread_interruption_checkpoint_bool ()) - continue; - - // If a worker thread is in its native top, not running managed code, - // there is no point in raising thread abort, and no code will clear - // the abort request. As such, the subsequent timedwait, would - // not be interrupted at runtime shutdown, because an abort is already requested. - // Clear the abort request. - // This avoids a shutdown hang in tests thread6 and thread7. - if (thread->state & ThreadState_AbortRequested) - mono_thread_internal_reset_abort (thread); - - if (!work_item_try_pop ()) { - gboolean const timeout = worker_park (); - if (timeout) { - worker_timed_out = TRUE; - break; - } - - continue; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker executing", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - worker.callback (); - } - - COUNTER_ATOMIC (counter, { - counter._.working --; - }); - - if (worker_timed_out) { - gint16 decr_max_working; - COUNTER_ATOMIC (counter, { - decr_max_working = MAX (worker.limit_worker_min, MIN (counter_num_active (counter), counter._.max_working)); - counter._.max_working = decr_max_working; - }); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker timed out, starting = %d working = %d parked = %d, setting max_working to %d", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), - counter._.starting, counter._.working, counter._.parked, - decr_max_working); - hill_climbing_force_change (decr_max_working, TRANSITION_THREAD_TIMED_OUT); - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker finishing", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - mono_refcount_dec (&worker); - - return 0; -} - -static gboolean -worker_try_create (void) -{ - ERROR_DECL (error); - MonoInternalThread *thread; - gint64 current_ticks; - gint32 now = 0; - ThreadPoolWorkerCounter counter; - - if (mono_runtime_is_shutting_down ()) - return FALSE; - - mono_coop_mutex_lock (&worker.worker_creation_lock); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - current_ticks = mono_100ns_ticks (); - if (0 == current_ticks) { - g_warning ("failed to get 100ns ticks"); - } else { - now = current_ticks / (10 * 1000 * 1000); - if (worker.worker_creation_current_second != now) { - worker.worker_creation_current_second = now; - worker.worker_creation_current_count = 0; - } else { - g_assert (worker.worker_creation_current_count <= WORKER_CREATION_MAX_PER_SEC); - if (worker.worker_creation_current_count == WORKER_CREATION_MAX_PER_SEC) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, failed: maximum number of worker created per second reached, current count = %d", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), worker.worker_creation_current_count); - mono_coop_mutex_unlock (&worker.worker_creation_lock); - return FALSE; - } - } - } - - COUNTER_ATOMIC (counter, { - if (counter._.working >= counter._.max_working) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, failed: maximum number of working threads reached", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - mono_coop_mutex_unlock (&worker.worker_creation_lock); - return FALSE; - } - counter._.starting ++; - }); - - thread = mono_thread_create_internal (mono_get_root_domain (), (gpointer)worker_thread, NULL, MONO_THREAD_CREATE_FLAGS_THREADPOOL, error); - if (!thread) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, failed: could not create thread due to %s", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), mono_error_get_message (error)); - mono_error_cleanup (error); - - COUNTER_ATOMIC (counter, { - counter._.starting --; - }); - - mono_coop_mutex_unlock (&worker.worker_creation_lock); - - return FALSE; - } - -#ifndef DISABLE_PERFCOUNTERS - mono_atomic_inc_i32 (&mono_perfcounters->threadpool_threads); -#endif - - worker.worker_creation_current_count += 1; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, created %p, now = %d count = %d", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), (gpointer) thread->tid, now, worker.worker_creation_current_count); - - mono_coop_mutex_unlock (&worker.worker_creation_lock); - return TRUE; -} - -static void monitor_ensure_running (void); - -static void -worker_request (void) -{ - if (worker.suspended) - return; - - monitor_ensure_running (); - - if (worker_try_unpark ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, unparked", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - return; - } - - if (worker_try_create ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, created", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - return; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, failed", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); -} - -static gboolean -monitor_should_keep_running (void) -{ - static gint64 last_should_keep_running = -1; - - g_assert (worker.monitor_status == MONITOR_STATUS_WAITING_FOR_REQUEST || worker.monitor_status == MONITOR_STATUS_REQUESTED); - - if (mono_atomic_xchg_i32 (&worker.monitor_status, MONITOR_STATUS_WAITING_FOR_REQUEST) == MONITOR_STATUS_WAITING_FOR_REQUEST) { - gboolean should_keep_running = TRUE, force_should_keep_running = FALSE; - - if (mono_runtime_is_shutting_down ()) { - should_keep_running = FALSE; - } else { - if (work_item_count () == 0) - should_keep_running = FALSE; - - if (!should_keep_running) { - if (last_should_keep_running == -1 || mono_100ns_ticks () - last_should_keep_running < MONITOR_MINIMAL_LIFETIME * 1000 * 10) { - should_keep_running = force_should_keep_running = TRUE; - } - } - } - - if (should_keep_running) { - if (last_should_keep_running == -1 || !force_should_keep_running) - last_should_keep_running = mono_100ns_ticks (); - } else { - last_should_keep_running = -1; - if (mono_atomic_cas_i32 (&worker.monitor_status, MONITOR_STATUS_NOT_RUNNING, MONITOR_STATUS_WAITING_FOR_REQUEST) == MONITOR_STATUS_WAITING_FOR_REQUEST) - return FALSE; - } - } - - g_assert (worker.monitor_status == MONITOR_STATUS_WAITING_FOR_REQUEST || worker.monitor_status == MONITOR_STATUS_REQUESTED); - - return TRUE; -} - -static gboolean -monitor_sufficient_delay_since_last_dequeue (void) -{ - gint64 threshold; - - if (worker.cpu_usage < CPU_USAGE_LOW) { - threshold = MONITOR_INTERVAL; - } else { - threshold = COUNTER_READ ()._.max_working * MONITOR_INTERVAL * 2; - } - - return mono_msec_ticks () >= worker.heuristic_last_dequeue + threshold; -} - -static gsize WINAPI -monitor_thread (gpointer unused) -{ - MonoInternalThread *internal; - guint i; - - if (!mono_refcount_tryinc (&worker)) - return 0; - - internal = mono_thread_internal_current (); - g_assert (internal); - - mono_cpu_usage (worker.cpu_usage_state); - - // printf ("monitor_thread: start\n"); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, started", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - do { - ThreadPoolWorkerCounter counter; - gboolean limit_worker_max_reached; - gint32 interval_left = MONITOR_INTERVAL; - gint32 awake = 0; /* number of spurious awakes we tolerate before doing a round of rebalancing */ - - g_assert (worker.monitor_status != MONITOR_STATUS_NOT_RUNNING); - -#if 0 - // This is ifdef'd out because otherwise we flood the log every - // MONITOR_INTERVAL ms, which is pretty noisy. - if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL)) { - ThreadPoolWorkerCounter trace_counter = COUNTER_READ (); - gint32 work_items = work_item_count (); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "monitor_thread: work items = %d, starting = %d working = %d parked = %d max_working = %d\n", - work_items, trace_counter._.starting, trace_counter._.working, trace_counter._.parked, trace_counter._.max_working); - } -#endif - - do { - gint64 ts; - gboolean alerted = FALSE; - - if (mono_runtime_is_shutting_down ()) - break; - - ts = mono_msec_ticks (); - if (mono_thread_info_sleep (interval_left, &alerted) == 0) - break; - interval_left -= mono_msec_ticks () - ts; - - mono_thread_interruption_checkpoint_void (); - } while (interval_left > 0 && ++awake < 10); - - if (mono_runtime_is_shutting_down ()) - continue; - - if (worker.suspended) - continue; - - if (work_item_count () == 0) - continue; - - worker.cpu_usage = mono_cpu_usage (worker.cpu_usage_state); - - if (!monitor_sufficient_delay_since_last_dequeue ()) - continue; - - gboolean active_max_reached; - - COUNTER_ATOMIC (counter, { - limit_worker_max_reached = FALSE; - active_max_reached = FALSE; - if (counter._.max_working >= worker.limit_worker_max) { - limit_worker_max_reached = TRUE; - if (counter_num_active (counter) >= counter._.max_working) - active_max_reached = TRUE; - break; - } - counter._.max_working ++; - }); - - if (limit_worker_max_reached) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, limit_worker_max (%d) reached", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), - worker.limit_worker_max); - if (active_max_reached) - continue; - else - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, num_active (%d) < max_working, allowing active thread increase", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), - counter_num_active (counter)); - } - else - hill_climbing_force_change (counter._.max_working, TRANSITION_STARVATION); - - for (i = 0; i < 5; ++i) { - if (mono_runtime_is_shutting_down ()) - break; - - if (worker_try_unpark ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, unparked", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - break; - } - - if (worker_try_create ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, created", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - break; - } - } - } while (monitor_should_keep_running ()); - - // printf ("monitor_thread: stop\n"); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, finished", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()))); - - mono_refcount_dec (&worker); - return 0; -} - -static void -monitor_ensure_running (void) -{ - ERROR_DECL (error); - for (;;) { - switch (worker.monitor_status) { - case MONITOR_STATUS_REQUESTED: - // printf ("monitor_thread: requested\n"); - return; - case MONITOR_STATUS_WAITING_FOR_REQUEST: - // printf ("monitor_thread: waiting for request\n"); - mono_atomic_cas_i32 (&worker.monitor_status, MONITOR_STATUS_REQUESTED, MONITOR_STATUS_WAITING_FOR_REQUEST); - break; - case MONITOR_STATUS_NOT_RUNNING: - // printf ("monitor_thread: not running\n"); - if (mono_runtime_is_shutting_down ()) - return; - if (mono_atomic_cas_i32 (&worker.monitor_status, MONITOR_STATUS_REQUESTED, MONITOR_STATUS_NOT_RUNNING) == MONITOR_STATUS_NOT_RUNNING) { - // printf ("monitor_thread: creating\n"); - if (!mono_thread_create_internal (mono_get_root_domain (), (gpointer)monitor_thread, NULL, (MonoThreadCreateFlags)(MONO_THREAD_CREATE_FLAGS_THREADPOOL | MONO_THREAD_CREATE_FLAGS_SMALL_STACK), error)) { - // printf ("monitor_thread: creating failed\n"); - worker.monitor_status = MONITOR_STATUS_NOT_RUNNING; - mono_error_cleanup (error); - mono_refcount_dec (&worker); - } - return; - } - break; - default: g_assert_not_reached (); - } - } -} - -static void -hill_climbing_change_thread_count (gint16 new_thread_count, ThreadPoolHeuristicStateTransition transition) -{ - ThreadPoolHillClimbing *hc; - - hc = &worker.heuristic_hill_climbing; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] hill climbing, change max number of threads %d", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), new_thread_count); - - hc->last_thread_count = new_thread_count; - hc->current_sample_interval = rand_next (hc->sample_interval_low, hc->sample_interval_high); - hc->elapsed_since_last_change = 0; - hc->completions_since_last_change = 0; -} - -static void -hill_climbing_force_change (gint16 new_thread_count, ThreadPoolHeuristicStateTransition transition) -{ - ThreadPoolHillClimbing *hc; - - hc = &worker.heuristic_hill_climbing; - - if (new_thread_count != hc->last_thread_count) { - hc->current_control_setting += new_thread_count - hc->last_thread_count; - hill_climbing_change_thread_count (new_thread_count, transition); - } -} - -static double_complex -hill_climbing_get_wave_component (gdouble *samples, guint sample_count, gdouble period) -{ - ThreadPoolHillClimbing *hc; - gdouble w, cosine, sine, coeff, q0, q1, q2; - guint i; - - g_assert (sample_count >= period); - g_assert (period >= 2); - - hc = &worker.heuristic_hill_climbing; - - w = 2.0 * M_PI / period; - cosine = cos (w); - sine = sin (w); - coeff = 2.0 * cosine; - q0 = q1 = q2 = 0; - - for (i = 0; i < sample_count; ++i) { - q0 = coeff * q1 - q2 + samples [(hc->total_samples - sample_count + i) % hc->samples_to_measure]; - q2 = q1; - q1 = q0; - } - - return mono_double_complex_scalar_div (mono_double_complex_make (q1 - q2 * cosine, (q2 * sine)), ((gdouble)sample_count)); -} - -static gint16 -hill_climbing_update (gint16 current_thread_count, guint32 sample_duration, gint32 completions, gint64 *adjustment_interval) -{ - ThreadPoolHillClimbing *hc; - ThreadPoolHeuristicStateTransition transition; - gdouble throughput; - gdouble throughput_error_estimate; - gdouble confidence; - gdouble move; - gdouble gain; - gint sample_index; - gint sample_count; - gint new_thread_wave_magnitude; - gint new_thread_count; - double_complex thread_wave_component; - double_complex throughput_wave_component; - double_complex ratio; - - g_assert (adjustment_interval); - - hc = &worker.heuristic_hill_climbing; - - /* If someone changed the thread count without telling us, update our records accordingly. */ - if (current_thread_count != hc->last_thread_count) - hill_climbing_force_change (current_thread_count, TRANSITION_INITIALIZING); - - /* Update the cumulative stats for this thread count */ - hc->elapsed_since_last_change += sample_duration; - hc->completions_since_last_change += completions; - - /* Add in any data we've already collected about this sample */ - sample_duration += hc->accumulated_sample_duration; - completions += hc->accumulated_completion_count; - - /* We need to make sure we're collecting reasonably accurate data. Since we're just counting the end - * of each work item, we are goinng to be missing some data about what really happened during the - * sample interval. The count produced by each thread includes an initial work item that may have - * started well before the start of the interval, and each thread may have been running some new - * work item for some time before the end of the interval, which did not yet get counted. So - * our count is going to be off by +/- threadCount workitems. - * - * The exception is that the thread that reported to us last time definitely wasn't running any work - * at that time, and the thread that's reporting now definitely isn't running a work item now. So - * we really only need to consider threadCount-1 threads. - * - * Thus the percent error in our count is +/- (threadCount-1)/numCompletions. - * - * We cannot rely on the frequency-domain analysis we'll be doing later to filter out this error, because - * of the way it accumulates over time. If this sample is off by, say, 33% in the negative direction, - * then the next one likely will be too. The one after that will include the sum of the completions - * we missed in the previous samples, and so will be 33% positive. So every three samples we'll have - * two "low" samples and one "high" sample. This will appear as periodic variation right in the frequency - * range we're targeting, which will not be filtered by the frequency-domain translation. */ - if (hc->total_samples > 0 && ((current_thread_count - 1.0) / completions) >= hc->max_sample_error) { - /* Not accurate enough yet. Let's accumulate the data so - * far, and tell the ThreadPoolWorker to collect a little more. */ - hc->accumulated_sample_duration = sample_duration; - hc->accumulated_completion_count = completions; - *adjustment_interval = 10; - return current_thread_count; - } - - /* We've got enouugh data for our sample; reset our accumulators for next time. */ - hc->accumulated_sample_duration = 0; - hc->accumulated_completion_count = 0; - - /* Add the current thread count and throughput sample to our history. */ - throughput = ((gdouble) completions) / sample_duration; - - sample_index = hc->total_samples % hc->samples_to_measure; - hc->samples [sample_index] = throughput; - hc->thread_counts [sample_index] = current_thread_count; - hc->total_samples ++; - - /* Set up defaults for our metrics. */ - thread_wave_component = mono_double_complex_make(0, 0); - throughput_wave_component = mono_double_complex_make(0, 0); - throughput_error_estimate = 0; - ratio = mono_double_complex_make(0, 0); - confidence = 0; - - transition = TRANSITION_WARMUP; - - /* How many samples will we use? It must be at least the three wave periods we're looking for, and it must also - * be a whole multiple of the primary wave's period; otherwise the frequency we're looking for will fall between - * two frequency bands in the Fourier analysis, and we won't be able to measure it accurately. */ - sample_count = ((gint) MIN (hc->total_samples - 1, hc->samples_to_measure) / hc->wave_period) * hc->wave_period; - - if (sample_count > hc->wave_period) { - guint i; - gdouble average_throughput; - gdouble average_thread_count; - gdouble sample_sum = 0; - gdouble thread_sum = 0; - - /* Average the throughput and thread count samples, so we can scale the wave magnitudes later. */ - for (i = 0; i < sample_count; ++i) { - guint j = (hc->total_samples - sample_count + i) % hc->samples_to_measure; - sample_sum += hc->samples [j]; - thread_sum += hc->thread_counts [j]; - } - - average_throughput = sample_sum / sample_count; - average_thread_count = thread_sum / sample_count; - - if (average_throughput > 0 && average_thread_count > 0) { - gdouble noise_for_confidence, adjacent_period_1, adjacent_period_2; - - /* Calculate the periods of the adjacent frequency bands we'll be using to - * measure noise levels. We want the two adjacent Fourier frequency bands. */ - adjacent_period_1 = sample_count / (((gdouble) sample_count) / ((gdouble) hc->wave_period) + 1); - adjacent_period_2 = sample_count / (((gdouble) sample_count) / ((gdouble) hc->wave_period) - 1); - - /* Get the the three different frequency components of the throughput (scaled by average - * throughput). Our "error" estimate (the amount of noise that might be present in the - * frequency band we're really interested in) is the average of the adjacent bands. */ - throughput_wave_component = mono_double_complex_scalar_div (hill_climbing_get_wave_component (hc->samples, sample_count, hc->wave_period), average_throughput); - throughput_error_estimate = mono_cabs (mono_double_complex_scalar_div (hill_climbing_get_wave_component (hc->samples, sample_count, adjacent_period_1), average_throughput)); - - if (adjacent_period_2 <= sample_count) { - throughput_error_estimate = MAX (throughput_error_estimate, mono_cabs (mono_double_complex_scalar_div (hill_climbing_get_wave_component ( - hc->samples, sample_count, adjacent_period_2), average_throughput))); - } - - /* Do the same for the thread counts, so we have something to compare to. We don't - * measure thread count noise, because there is none; these are exact measurements. */ - thread_wave_component = mono_double_complex_scalar_div (hill_climbing_get_wave_component (hc->thread_counts, sample_count, hc->wave_period), average_thread_count); - - /* Update our moving average of the throughput noise. We'll use this - * later as feedback to determine the new size of the thread wave. */ - if (hc->average_throughput_noise == 0) { - hc->average_throughput_noise = throughput_error_estimate; - } else { - hc->average_throughput_noise = (hc->throughput_error_smoothing_factor * throughput_error_estimate) - + ((1.0 + hc->throughput_error_smoothing_factor) * hc->average_throughput_noise); - } - - if (mono_cabs (thread_wave_component) > 0) { - /* Adjust the throughput wave so it's centered around the target wave, - * and then calculate the adjusted throughput/thread ratio. */ - ratio = mono_double_complex_div (mono_double_complex_sub (throughput_wave_component, mono_double_complex_scalar_mul(thread_wave_component, hc->target_throughput_ratio)), thread_wave_component); - transition = TRANSITION_CLIMBING_MOVE; - } else { - ratio = mono_double_complex_make (0, 0); - transition = TRANSITION_STABILIZING; - } - - noise_for_confidence = MAX (hc->average_throughput_noise, throughput_error_estimate); - if (noise_for_confidence > 0) { - confidence = mono_cabs (thread_wave_component) / noise_for_confidence / hc->target_signal_to_noise_ratio; - } else { - /* there is no noise! */ - confidence = 1.0; - } - } - } - - /* We use just the real part of the complex ratio we just calculated. If the throughput signal - * is exactly in phase with the thread signal, this will be the same as taking the magnitude of - * the complex move and moving that far up. If they're 180 degrees out of phase, we'll move - * backward (because this indicates that our changes are having the opposite of the intended effect). - * If they're 90 degrees out of phase, we won't move at all, because we can't tell wether we're - * having a negative or positive effect on throughput. */ - move = mono_creal (ratio); - move = CLAMP (move, -1.0, 1.0); - - /* Apply our confidence multiplier. */ - move *= CLAMP (confidence, -1.0, 1.0); - - /* Now apply non-linear gain, such that values around zero are attenuated, while higher values - * are enhanced. This allows us to move quickly if we're far away from the target, but more slowly - * if we're getting close, giving us rapid ramp-up without wild oscillations around the target. */ - gain = hc->max_change_per_second * sample_duration; - move = pow (fabs (move), hc->gain_exponent) * (move >= 0.0 ? 1 : -1) * gain; - move = MIN (move, hc->max_change_per_sample); - - /* If the result was positive, and CPU is > 95%, refuse the move. */ - if (move > 0.0 && worker.cpu_usage > CPU_USAGE_HIGH) - move = 0.0; - - /* Apply the move to our control setting. */ - hc->current_control_setting += move; - - /* Calculate the new thread wave magnitude, which is based on the moving average we've been keeping of the - * throughput error. This average starts at zero, so we'll start with a nice safe little wave at first. */ - new_thread_wave_magnitude = (gint)(0.5 + (hc->current_control_setting * hc->average_throughput_noise - * hc->target_signal_to_noise_ratio * hc->thread_magnitude_multiplier * 2.0)); - new_thread_wave_magnitude = CLAMP (new_thread_wave_magnitude, 1, hc->max_thread_wave_magnitude); - - /* Make sure our control setting is within the ThreadPoolWorker's limits. */ - hc->current_control_setting = CLAMP (hc->current_control_setting, worker.limit_worker_min, worker.limit_worker_max - new_thread_wave_magnitude); - - /* Calculate the new thread count (control setting + square wave). */ - new_thread_count = (gint)(hc->current_control_setting + new_thread_wave_magnitude * ((hc->total_samples / (hc->wave_period / 2)) % 2)); - - /* Make sure the new thread count doesn't exceed the ThreadPoolWorker's limits. */ - new_thread_count = CLAMP (new_thread_count, worker.limit_worker_min, worker.limit_worker_max); - - if (new_thread_count != current_thread_count) - hill_climbing_change_thread_count (new_thread_count, transition); - - if (mono_creal (ratio) < 0.0 && new_thread_count == worker.limit_worker_min) - *adjustment_interval = (gint)(0.5 + hc->current_sample_interval * (10.0 * MAX (-1.0 * mono_creal (ratio), 1.0))); - else - *adjustment_interval = hc->current_sample_interval; - - return new_thread_count; -} - -static gboolean -heuristic_should_adjust (void) -{ - if (worker.heuristic_last_dequeue > worker.heuristic_last_adjustment + worker.heuristic_adjustment_interval) { - ThreadPoolWorkerCounter const counter = COUNTER_READ (); - if (counter._.working <= counter._.max_working) - return TRUE; - } - - return FALSE; -} - -static void -heuristic_adjust (void) -{ - if (mono_coop_mutex_trylock (&worker.heuristic_lock) == 0) { - gint32 completions = mono_atomic_xchg_i32 (&worker.heuristic_completions, 0); - gint64 sample_end = mono_msec_ticks (); - gint64 sample_duration = sample_end - worker.heuristic_sample_start; - - if (sample_duration >= worker.heuristic_adjustment_interval / 2) { - - ThreadPoolWorkerCounter counter = COUNTER_READ (); - gint16 const new_thread_count = hill_climbing_update (counter._.max_working, sample_duration, completions, &worker.heuristic_adjustment_interval); - - COUNTER_ATOMIC (counter, { - counter._.max_working = new_thread_count; - }); - - /* FIXME: this can never be true. we only leave COUNTER_ATOMIC() if the assignment and CAS succeeded */ - if (new_thread_count > counter._.max_working) - worker_request (); - - worker.heuristic_sample_start = sample_end; - worker.heuristic_last_adjustment = mono_msec_ticks (); - } - - mono_coop_mutex_unlock (&worker.heuristic_lock); - } -} - -static void -heuristic_notify_work_completed (void) -{ - mono_atomic_inc_i32 (&worker.heuristic_completions); - worker.heuristic_last_dequeue = mono_msec_ticks (); - - if (heuristic_should_adjust ()) - heuristic_adjust (); -} - -gboolean -mono_threadpool_worker_notify_completed (void) -{ - heuristic_notify_work_completed (); - - ThreadPoolWorkerCounter const counter = COUNTER_READ (); - return counter._.working <= counter._.max_working; -} - -gint32 -mono_threadpool_worker_get_min (void) -{ - gint32 ret; - - if (!mono_refcount_tryinc (&worker)) - return 0; - - ret = worker.limit_worker_min; - - mono_refcount_dec (&worker); - return ret; -} - -gboolean -mono_threadpool_worker_set_min (gint32 value) -{ - if (value <= 0 || value > worker.limit_worker_max) - return FALSE; - - if (!mono_refcount_tryinc (&worker)) - return FALSE; - - worker.limit_worker_min = value; - - mono_refcount_dec (&worker); - return TRUE; -} - -gint32 -mono_threadpool_worker_get_max (void) -{ - gint32 ret; - - if (!mono_refcount_tryinc (&worker)) - return 0; - - ret = worker.limit_worker_max; - - mono_refcount_dec (&worker); - return ret; -} - -gboolean -mono_threadpool_worker_set_max (gint32 value) -{ - gint32 cpu_count; - - cpu_count = mono_cpu_count (); - if (value < worker.limit_worker_min || value < cpu_count) - return FALSE; - - if (!mono_refcount_tryinc (&worker)) - return FALSE; - - worker.limit_worker_max = value; - - mono_refcount_dec (&worker); - return TRUE; -} - -void -mono_threadpool_worker_set_suspended (gboolean suspended) -{ - if (!mono_refcount_tryinc (&worker)) - return; - - worker.suspended = suspended; - if (!suspended) - worker_request (); - - mono_refcount_dec (&worker); -} - -#endif /* ENABLE_NETCORE */ diff --git a/src/mono/mono/metadata/threadpool-worker-wasm.c b/src/mono/mono/metadata/threadpool-worker-wasm.c deleted file mode 100644 index 3cd3485..0000000 --- a/src/mono/mono/metadata/threadpool-worker-wasm.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file - * native threadpool worker - * - * Author: - * Ludovic Henry (ludovic.henry@xamarin.com) - * - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include -#define _USE_MATH_DEFINES // needed by MSVC to define math constants -#include -#include -#include - -#ifndef ENABLE_NETCORE - -#include -#include - -static MonoThreadPoolWorkerCallback tp_cb; -static gboolean cb_scheduled; - -void -mono_threadpool_worker_init (MonoThreadPoolWorkerCallback callback) -{ - tp_cb = callback; -} - -void -mono_threadpool_worker_cleanup (void) -{ -} - -gint32 -mono_threadpool_worker_get_min (void) -{ - return 1; -} - -gboolean -mono_threadpool_worker_set_min (gint32 value) -{ - return value == 1; -} - -gint32 -mono_threadpool_worker_get_max (void) -{ - return 1; -} - -gboolean -mono_threadpool_worker_set_max (gint32 value) -{ - return value == 1; -} - -static void -fire_tp_callback (void) -{ - cb_scheduled = FALSE; - tp_cb (); -} - -void -mono_threadpool_worker_request (void) -{ - if (!cb_scheduled) - mono_threads_schedule_background_job (fire_tp_callback); - cb_scheduled = TRUE; -} - -gboolean -mono_threadpool_worker_notify_completed (void) -{ - return FALSE; -} - -#endif diff --git a/src/mono/mono/metadata/threadpool-worker.h b/src/mono/mono/metadata/threadpool-worker.h deleted file mode 100644 index 0b37d24..0000000 --- a/src/mono/mono/metadata/threadpool-worker.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * \file - */ - -#ifndef _MONO_METADATA_THREADPOOL_WORKER_H -#define _MONO_METADATA_THREADPOOL_WORKER_H - -#include -#include - -#ifndef ENABLE_NETCORE - -typedef void (*MonoThreadPoolWorkerCallback)(void); - -void -mono_threadpool_worker_init (MonoThreadPoolWorkerCallback callback); - -void -mono_threadpool_worker_cleanup (void); - -void -mono_threadpool_worker_request (void); - -gboolean -mono_threadpool_worker_notify_completed (void); - -gint32 -mono_threadpool_worker_get_min (void); -gboolean -mono_threadpool_worker_set_min (gint32 value); - -gint32 -mono_threadpool_worker_get_max (void); -gboolean -mono_threadpool_worker_set_max (gint32 value); - -void -mono_threadpool_worker_set_suspended (gboolean suspended); - -#endif /* ENABLE_NETCORE */ - -#endif /* _MONO_METADATA_THREADPOOL_WORKER_H */ diff --git a/src/mono/mono/metadata/threadpool.c b/src/mono/mono/metadata/threadpool.c deleted file mode 100644 index ecbe81a..0000000 --- a/src/mono/mono/metadata/threadpool.c +++ /dev/null @@ -1,828 +0,0 @@ -/** - * \file - * Microsoft threadpool runtime support - * - * Author: - * Ludovic Henry (ludovic.henry@xamarin.com) - * - * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -// Files: -// - src/vm/comthreadpool.cpp -// - src/vm/win32threadpoolcpp -// - src/vm/threadpoolrequest.cpp -// - src/vm/hillclimbing.cpp -// -// Ported from C++ to C and adjusted to Mono runtime - -#include -#include - -#ifndef ENABLE_NETCORE - -#include -#define _USE_MATH_DEFINES // needed by MSVC to define math constants -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "monitor.h" -#include "icall-decl.h" - -// consistency with coreclr https://github.com/dotnet/coreclr/blob/643b09f966e68e06d5f0930755985a01a2a2b096/src/vm/win32threadpool.h#L111 -#define MAX_POSSIBLE_THREADS 0x7fff - -typedef struct { - MonoDomain *domain; - /* Number of outstanding jobs */ - gint32 outstanding_request; - /* Number of currently executing jobs */ - gint32 threadpool_jobs; - /* Signalled when threadpool_jobs + outstanding_request is 0 */ - /* Protected by threadpool.domains_lock */ - MonoCoopCond cleanup_cond; -} ThreadPoolDomain; - -typedef union { - struct { - gint16 starting; /* starting, but not yet in worker_callback */ - gint16 working; /* executing worker_callback */ - } _; - gint32 as_gint32; -} ThreadPoolCounter; - -typedef struct { - MonoRefCount ref; - - GPtrArray *domains; // ThreadPoolDomain* [] - MonoCoopMutex domains_lock; - - ThreadPoolCounter counters; - - gint32 limit_io_min; - gint32 limit_io_max; -} ThreadPool; - -static mono_lazy_init_t status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; - -static ThreadPool threadpool; - -#define COUNTER_ATOMIC(var,block) \ - do { \ - ThreadPoolCounter __old; \ - do { \ - (var) = __old = COUNTER_READ (); \ - { block; } \ - if (!(counter._.starting >= 0)) \ - g_error ("%s: counter._.starting = %d, but should be >= 0", __func__, counter._.starting); \ - if (!(counter._.working >= 0)) \ - g_error ("%s: counter._.working = %d, but should be >= 0", __func__, counter._.working); \ - } while (mono_atomic_cas_i32 (&threadpool.counters.as_gint32, (var).as_gint32, __old.as_gint32) != __old.as_gint32); \ - } while (0) - -static ThreadPoolCounter -COUNTER_READ (void) -{ - ThreadPoolCounter counter; - counter.as_gint32 = mono_atomic_load_i32 (&threadpool.counters.as_gint32); - return counter; -} - -static void -domains_lock (void) -{ - mono_coop_mutex_lock (&threadpool.domains_lock); -} - -static void -domains_unlock (void) -{ - mono_coop_mutex_unlock (&threadpool.domains_lock); -} - -static void -destroy (gpointer unused) -{ - g_ptr_array_free (threadpool.domains, TRUE); - mono_coop_mutex_destroy (&threadpool.domains_lock); -} - -static void -worker_callback (void); - -static void -initialize (void) -{ - g_assert (sizeof (ThreadPoolCounter) == sizeof (gint32)); - - mono_refcount_init (&threadpool, destroy); - - threadpool.domains = g_ptr_array_new (); - mono_coop_mutex_init (&threadpool.domains_lock); - - threadpool.limit_io_min = mono_cpu_count (); - threadpool.limit_io_max = CLAMP (threadpool.limit_io_min * 100, MIN (threadpool.limit_io_min, 200), MAX (threadpool.limit_io_min, 200)); - - mono_threadpool_worker_init (worker_callback); -} - -static void -cleanup (void) -{ - mono_threadpool_worker_cleanup (); - - mono_refcount_dec (&threadpool); -} - -gboolean -mono_threadpool_enqueue_work_item (MonoDomain *domain, MonoObject *work_item, MonoError *error) -{ - MonoDomain *current_domain; - MonoBoolean f; - gpointer args [2]; - - error_init (error); - g_assert (work_item); - - MONO_STATIC_POINTER_INIT (MonoClass, threadpool_class) - - threadpool_class = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "ThreadPool"); - - MONO_STATIC_POINTER_INIT_END (MonoClass, threadpool_class) - - MONO_STATIC_POINTER_INIT (MonoMethod, unsafe_queue_custom_work_item_method) - - unsafe_queue_custom_work_item_method = mono_class_get_method_from_name_checked (threadpool_class, "UnsafeQueueCustomWorkItem", 2, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, unsafe_queue_custom_work_item_method) - - g_assert (unsafe_queue_custom_work_item_method); - - f = FALSE; - - args [0] = (gpointer) work_item; - args [1] = (gpointer) &f; - - current_domain = mono_domain_get (); - if (current_domain == domain) { - mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, error); - } else { - mono_thread_push_appdomain_ref (domain); - if (mono_domain_set_fast (domain, FALSE)) { - mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, error); - mono_domain_set_fast (current_domain, TRUE); - } else { - // mono_domain_set_fast failing still leads to success. - } - mono_thread_pop_appdomain_ref (); - } - return is_ok (error); -} - -/* LOCKING: domains_lock must be held. */ -static ThreadPoolDomain * -tpdomain_create (MonoDomain *domain) -{ - ThreadPoolDomain *tpdomain; - - tpdomain = g_new0 (ThreadPoolDomain, 1); - tpdomain->domain = domain; - mono_coop_cond_init (&tpdomain->cleanup_cond); - - g_ptr_array_add (threadpool.domains, tpdomain); - - return tpdomain; -} - -/* LOCKING: domains_lock must be held. */ -static gboolean -tpdomain_remove (ThreadPoolDomain *tpdomain) -{ - g_assert (tpdomain); - return g_ptr_array_remove (threadpool.domains, tpdomain); -} - -/* LOCKING: domains_lock must be held */ -static ThreadPoolDomain * -tpdomain_get (MonoDomain *domain) -{ - gint i; - - g_assert (domain); - - for (i = 0; i < threadpool.domains->len; ++i) { - ThreadPoolDomain *tpdomain; - - tpdomain = (ThreadPoolDomain *)g_ptr_array_index (threadpool.domains, i); - if (tpdomain->domain == domain) - return tpdomain; - } - - return NULL; -} - -static void -tpdomain_free (ThreadPoolDomain *tpdomain) -{ - g_free (tpdomain); -} - -/* LOCKING: domains_lock must be held */ -static ThreadPoolDomain * -tpdomain_get_next (ThreadPoolDomain *current) -{ - ThreadPoolDomain *tpdomain = NULL; - gint len; - - len = threadpool.domains->len; - if (len > 0) { - gint i, current_idx = -1; - if (current) { - for (i = 0; i < len; ++i) { - if (current == g_ptr_array_index (threadpool.domains, i)) { - current_idx = i; - break; - } - } - } - for (i = current_idx + 1; i < len + current_idx + 1; ++i) { - ThreadPoolDomain *tmp = (ThreadPoolDomain *)g_ptr_array_index (threadpool.domains, i % len); - if (tmp->outstanding_request > 0) { - tpdomain = tmp; - break; - } - } - } - - return tpdomain; -} - -static MonoObject* -try_invoke_perform_wait_callback (MonoObject** exc, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - error_init (error); - MonoObject * const res = mono_runtime_try_invoke (mono_defaults.threadpool_perform_wait_callback_method, NULL, NULL, exc, error); - HANDLE_FUNCTION_RETURN_VAL (res); -} - -static void -mono_threadpool_set_thread_name (MonoInternalThread *thread) -{ - mono_thread_set_name_constant_ignore_error ( - thread, - "Thread Pool Worker", - MonoSetThreadNameFlag_Reset | MonoSetThreadNameFlag_RepeatedlyButOptimized); -} - -static void -worker_callback (void) -{ - ThreadPoolDomain *tpdomain, *previous_tpdomain; - ThreadPoolCounter counter; - MonoInternalThread *thread; - - if (!mono_refcount_tryinc (&threadpool)) - return; - - thread = mono_thread_internal_current (); - - COUNTER_ATOMIC (counter, { - if (!(counter._.working < 32767 /* G_MAXINT16 */)) - g_error ("%s: counter._.working = %d, but should be < 32767", __func__, counter._.working); - - counter._.starting --; - counter._.working ++; - }); - - if (mono_runtime_is_shutting_down ()) { - COUNTER_ATOMIC (counter, { - counter._.working --; - }); - - mono_refcount_dec (&threadpool); - return; - } - - /* - * This is needed so there is always an lmf frame in the runtime invoke call below, - * so ThreadAbortExceptions are caught even if the thread is in native code. - */ - mono_defaults.threadpool_perform_wait_callback_method->save_lmf = TRUE; - - /* Set the name if this is the first call to worker_callback on this thread */ - mono_threadpool_set_thread_name (thread); - - domains_lock (); - - previous_tpdomain = NULL; - - while (!mono_runtime_is_shutting_down ()) { - gboolean retire = FALSE; - - if (thread->state & (ThreadState_AbortRequested | ThreadState_SuspendRequested)) { - domains_unlock (); - if (mono_thread_interruption_checkpoint_bool ()) { - domains_lock (); - continue; - } - domains_lock (); - } - - tpdomain = tpdomain_get_next (previous_tpdomain); - if (!tpdomain) - break; - - tpdomain->outstanding_request --; - g_assert (tpdomain->outstanding_request >= 0); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker running in domain %p (outstanding requests %d)", - GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ())), tpdomain->domain, tpdomain->outstanding_request); - - g_assert (tpdomain->threadpool_jobs >= 0); - tpdomain->threadpool_jobs ++; - - domains_unlock (); - - mono_threadpool_set_thread_name (thread); - - mono_thread_clear_and_set_state (thread, - (MonoThreadState)~ThreadState_Background, - ThreadState_Background); - - mono_thread_push_appdomain_ref (tpdomain->domain); - if (mono_domain_set_fast (tpdomain->domain, FALSE)) { - MonoObject *exc = NULL, *res; - - ERROR_DECL (error); - - res = try_invoke_perform_wait_callback (&exc, error); - if (exc || !is_ok(error)) { - if (exc == NULL) - exc = (MonoObject *) mono_error_convert_to_exception (error); - else - mono_error_cleanup (error); - mono_thread_internal_unhandled_exception (exc); - } else if (res && *(MonoBoolean*) mono_object_unbox_internal (res) == FALSE) { - retire = TRUE; - } - - mono_domain_set_fast (mono_get_root_domain (), TRUE); - } - mono_thread_pop_appdomain_ref (); - - /* Reset name after every callback */ - mono_threadpool_set_thread_name (thread); - - domains_lock (); - - tpdomain->threadpool_jobs --; - g_assert (tpdomain->threadpool_jobs >= 0); - - if (tpdomain->outstanding_request + tpdomain->threadpool_jobs == 0 && mono_domain_is_unloading (tpdomain->domain)) { - gboolean removed; - - removed = tpdomain_remove (tpdomain); - g_assert (removed); - - mono_coop_cond_signal (&tpdomain->cleanup_cond); - tpdomain = NULL; - } - - if (retire) - break; - - previous_tpdomain = tpdomain; - } - - domains_unlock (); - - COUNTER_ATOMIC (counter, { - counter._.working --; - }); - - mono_refcount_dec (&threadpool); -} - -void -mono_threadpool_cleanup (void) -{ -#ifndef DISABLE_SOCKETS - mono_threadpool_io_cleanup (); -#endif - mono_lazy_cleanup (&status, cleanup); -} - -MonoAsyncResult * -mono_threadpool_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params, MonoError *error) -{ - MonoMethodMessage *message; - MonoAsyncResult *async_result; - MonoAsyncCall *async_call; - MonoDelegate *async_callback = NULL; - MonoObject *state = NULL; - - MONO_STATIC_POINTER_INIT (MonoClass, async_call_klass) - - async_call_klass = mono_class_load_from_name (mono_defaults.corlib, "System", "MonoAsyncCall"); - - MONO_STATIC_POINTER_INIT_END (MonoClass, async_call_klass) - - error_init (error); - - message = mono_method_call_message_new (method, params, mono_get_delegate_invoke_internal (method->klass), (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL, error); - return_val_if_nok (error, NULL); - - async_call = (MonoAsyncCall*) mono_object_new_checked (domain, async_call_klass, error); - return_val_if_nok (error, NULL); - - MONO_OBJECT_SETREF_INTERNAL (async_call, msg, message); - MONO_OBJECT_SETREF_INTERNAL (async_call, state, state); - - if (async_callback) { - MONO_OBJECT_SETREF_INTERNAL (async_call, cb_method, mono_get_delegate_invoke_internal (((MonoObject*) async_callback)->vtable->klass)); - MONO_OBJECT_SETREF_INTERNAL (async_call, cb_target, async_callback); - } - - async_result = mono_async_result_new (domain, NULL, async_call->state, NULL, (MonoObject*) async_call, error); - return_val_if_nok (error, NULL); - MONO_OBJECT_SETREF_INTERNAL (async_result, async_delegate, target); - - mono_threadpool_enqueue_work_item (domain, (MonoObject*) async_result, error); - return_val_if_nok (error, NULL); - - return async_result; -} - -MonoObject * -mono_threadpool_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, MonoObject **exc, MonoError *error) -{ - MonoAsyncCall *ac; - - error_init (error); - g_assert (exc); - g_assert (out_args); - - *exc = NULL; - *out_args = NULL; - - /* check if already finished */ - mono_monitor_enter_internal ((MonoObject*) ares); - - if (ares->endinvoke_called) { - mono_error_set_invalid_operation(error, "Delegate EndInvoke method called more than once"); - mono_monitor_exit_internal ((MonoObject*) ares); - return NULL; - } - - ares->endinvoke_called = 1; - - /* wait until we are really finished */ - if (ares->completed) { - mono_monitor_exit_internal ((MonoObject *) ares); - } else { - gpointer wait_event; - if (ares->handle) { - wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle); - } else { - wait_event = mono_w32event_create (TRUE, FALSE); - g_assert(wait_event); - MonoWaitHandle *wait_handle = mono_wait_handle_new (mono_object_domain (ares), wait_event, error); - if (!is_ok (error)) { - mono_w32event_close (wait_event); - return NULL; - } - MONO_OBJECT_SETREF_INTERNAL (ares, handle, (MonoObject*) wait_handle); - } - mono_monitor_exit_internal ((MonoObject*) ares); - mono_w32handle_wait_one (wait_event, MONO_INFINITE_WAIT, TRUE); - } - - ac = (MonoAsyncCall*) ares->object_data; - g_assert (ac); - - *exc = ac->msg->exc; /* FIXME: GC add write barrier */ - *out_args = ac->out_args; - return ac->res; -} - -gboolean -mono_threadpool_remove_domain_jobs (MonoDomain *domain, int timeout) -{ - gint64 end = 0; - ThreadPoolDomain *tpdomain; - gboolean ret; - - g_assert (domain); - g_assert (timeout >= -1); - - g_assert (mono_domain_is_unloading (domain)); - - if (timeout != -1) - end = mono_msec_ticks () + timeout; - -#ifndef DISABLE_SOCKETS - mono_threadpool_io_remove_domain_jobs (domain); - if (timeout != -1) { - if (mono_msec_ticks () > end) - return FALSE; - } -#endif - - /* - * Wait for all threads which execute jobs in the domain to exit. - * The is_unloading () check in worker_request () ensures that - * no new jobs are added after we enter the lock below. - */ - - if (!mono_lazy_is_initialized (&status)) - return TRUE; - - mono_refcount_inc (&threadpool); - - domains_lock (); - - tpdomain = tpdomain_get (domain); - if (!tpdomain) { - domains_unlock (); - mono_refcount_dec (&threadpool); - return TRUE; - } - - ret = TRUE; - - while (tpdomain->outstanding_request + tpdomain->threadpool_jobs > 0) { - if (timeout == -1) { - mono_coop_cond_wait (&tpdomain->cleanup_cond, &threadpool.domains_lock); - } else { - gint64 now; - gint res; - - now = mono_msec_ticks(); - if (now > end) { - ret = FALSE; - break; - } - - res = mono_coop_cond_timedwait (&tpdomain->cleanup_cond, &threadpool.domains_lock, end - now); - if (res != 0) { - ret = FALSE; - break; - } - } - } - - /* Remove from the list the worker threads look at */ - tpdomain_remove (tpdomain); - - domains_unlock (); - - mono_coop_cond_destroy (&tpdomain->cleanup_cond); - tpdomain_free (tpdomain); - - mono_refcount_dec (&threadpool); - - return ret; -} - -void -mono_threadpool_suspend (void) -{ - if (mono_lazy_is_initialized (&status)) - mono_threadpool_worker_set_suspended (TRUE); -} - -void -mono_threadpool_resume (void) -{ - if (mono_lazy_is_initialized (&status)) - mono_threadpool_worker_set_suspended (FALSE); -} - -void -ves_icall_System_Threading_ThreadPool_GetAvailableThreadsNative (gint32 *worker_threads, gint32 *completion_port_threads, MonoError *error) -{ - ThreadPoolCounter counter; - - if (!worker_threads || !completion_port_threads) - return; - - if (!mono_lazy_initialize (&status, initialize) || !mono_refcount_tryinc (&threadpool)) { - *worker_threads = 0; - *completion_port_threads = 0; - return; - } - - counter = COUNTER_READ (); - - *worker_threads = MAX (0, mono_threadpool_worker_get_max () - counter._.working); - *completion_port_threads = threadpool.limit_io_max; - - mono_refcount_dec (&threadpool); -} - -void -ves_icall_System_Threading_ThreadPool_GetMinThreadsNative (gint32 *worker_threads, gint32 *completion_port_threads, MonoError *error) -{ - if (!worker_threads || !completion_port_threads) - return; - - if (!mono_lazy_initialize (&status, initialize) || !mono_refcount_tryinc (&threadpool)) { - *worker_threads = 0; - *completion_port_threads = 0; - return; - } - - *worker_threads = mono_threadpool_worker_get_min (); - *completion_port_threads = threadpool.limit_io_min; - - mono_refcount_dec (&threadpool); -} - -void -ves_icall_System_Threading_ThreadPool_GetMaxThreadsNative (gint32 *worker_threads, gint32 *completion_port_threads, MonoError *error) -{ - if (!worker_threads || !completion_port_threads) - return; - - if (!mono_lazy_initialize (&status, initialize) || !mono_refcount_tryinc (&threadpool)) { - *worker_threads = 0; - *completion_port_threads = 0; - return; - } - - *worker_threads = mono_threadpool_worker_get_max (); - *completion_port_threads = threadpool.limit_io_max; - - mono_refcount_dec (&threadpool); -} - -MonoBoolean -ves_icall_System_Threading_ThreadPool_SetMinThreadsNative (gint32 worker_threads, gint32 completion_port_threads, MonoError *error) -{ - if (!mono_lazy_initialize (&status, initialize) || !mono_refcount_tryinc (&threadpool)) - return FALSE; - - if (completion_port_threads <= 0 || completion_port_threads > threadpool.limit_io_max) - return FALSE; - - if (!mono_threadpool_worker_set_min (worker_threads)) { - mono_refcount_dec (&threadpool); - return FALSE; - } - - threadpool.limit_io_min = completion_port_threads; - - mono_refcount_dec (&threadpool); - return TRUE; -} - -MonoBoolean -ves_icall_System_Threading_ThreadPool_SetMaxThreadsNative (gint32 worker_threads, gint32 completion_port_threads, MonoError *error) -{ - if (!mono_lazy_initialize (&status, initialize) || !mono_refcount_tryinc (&threadpool)) - return FALSE; - - worker_threads = MIN (worker_threads, MAX_POSSIBLE_THREADS); - completion_port_threads = MIN (completion_port_threads, MAX_POSSIBLE_THREADS); - - gint cpu_count = mono_cpu_count (); - - if (completion_port_threads < threadpool.limit_io_min || completion_port_threads < cpu_count) - return FALSE; - - if (!mono_threadpool_worker_set_max (worker_threads)) { - mono_refcount_dec (&threadpool); - return FALSE; - } - - threadpool.limit_io_max = completion_port_threads; - - mono_refcount_dec (&threadpool); - return TRUE; -} - -void -ves_icall_System_Threading_ThreadPool_InitializeVMTp (MonoBoolean *enable_worker_tracking, MonoError *error) -{ - if (enable_worker_tracking) { - // TODO implement some kind of switch to have the possibily to use it - *enable_worker_tracking = FALSE; - } - - mono_lazy_initialize (&status, initialize); -} - -MonoBoolean -ves_icall_System_Threading_ThreadPool_NotifyWorkItemComplete (MonoError *error) -{ - if (mono_domain_is_unloading (mono_domain_get ()) || mono_runtime_is_shutting_down ()) - return FALSE; - - return mono_threadpool_worker_notify_completed (); -} - -void -ves_icall_System_Threading_ThreadPool_NotifyWorkItemProgressNative (MonoError *error) -{ - mono_threadpool_worker_notify_completed (); -} - -void -ves_icall_System_Threading_ThreadPool_NotifyWorkItemQueued (MonoError *error) -// FIXME Move to managed. -{ -#ifndef DISABLE_PERFCOUNTERS - mono_atomic_inc_i64 (&mono_perfcounters->threadpool_workitems); -#endif -} - -void -ves_icall_System_Threading_ThreadPool_ReportThreadStatus (MonoBoolean is_working, MonoError *error) -{ - // TODO - mono_error_set_not_implemented (error, ""); -} - -MonoBoolean -ves_icall_System_Threading_ThreadPool_RequestWorkerThread (MonoError *error) -{ - MonoDomain *domain; - ThreadPoolDomain *tpdomain; - ThreadPoolCounter counter; - - domain = mono_domain_get (); - if (mono_domain_is_unloading (domain)) - return FALSE; - - if (!mono_lazy_initialize (&status, initialize) || !mono_refcount_tryinc (&threadpool)) { - /* threadpool has been destroyed, we are shutting down */ - return FALSE; - } - - domains_lock (); - - tpdomain = tpdomain_get (domain); - if (!tpdomain) { - /* synchronize with mono_threadpool_remove_domain_jobs */ - if (mono_domain_is_unloading (domain)) { - domains_unlock (); - mono_refcount_dec (&threadpool); - return FALSE; - } - - tpdomain = tpdomain_create (domain); - } - - g_assert (tpdomain); - - tpdomain->outstanding_request ++; - g_assert (tpdomain->outstanding_request >= 1); - - domains_unlock (); - - COUNTER_ATOMIC (counter, { - if (counter._.starting == 16) { - mono_refcount_dec (&threadpool); - return TRUE; - } - - counter._.starting ++; - }); - - mono_threadpool_worker_request (); - - mono_refcount_dec (&threadpool); - return TRUE; -} - -#endif /* !ENABLE_NETCORE */ - -MONO_EMPTY_SOURCE_FILE (threadpool); diff --git a/src/mono/mono/metadata/threadpool.h b/src/mono/mono/metadata/threadpool.h deleted file mode 100644 index e2ff2b8..0000000 --- a/src/mono/mono/metadata/threadpool.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * \file - */ - -#ifndef _MONO_METADATA_THREADPOOL_H_ -#define _MONO_METADATA_THREADPOOL_H_ - -#include -#include - -#include -#include -#include - -void -mono_threadpool_cleanup (void); - -MonoAsyncResult * -mono_threadpool_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params, MonoError *error); -MonoObject * -mono_threadpool_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, MonoObject **exc, MonoError *error); - -gboolean -mono_threadpool_remove_domain_jobs (MonoDomain *domain, int timeout); - -void -mono_threadpool_suspend (void); -void -mono_threadpool_resume (void); - -/* Internals */ - -gboolean -mono_threadpool_enqueue_work_item (MonoDomain *domain, MonoObject *work_item, MonoError *error); - -#endif // _MONO_METADATA_THREADPOOL_H_ diff --git a/src/mono/mono/metadata/threads-types.h b/src/mono/mono/metadata/threads-types.h index 97c1fb2..7a1d870 100644 --- a/src/mono/mono/metadata/threads-types.h +++ b/src/mono/mono/metadata/threads-types.h @@ -161,11 +161,6 @@ gint64 ves_icall_System_Threading_Interlocked_Exchange_Long(gint64 *location, gi ICALL_EXPORT void ves_icall_System_Threading_Interlocked_Exchange_Object (MonoObject *volatile*location, MonoObject *volatile*value, MonoObject *volatile*res); -#ifndef ENABLE_NETCORE -ICALL_EXPORT -gpointer ves_icall_System_Threading_Interlocked_Exchange_IntPtr(gpointer *location, gpointer value); -#endif - ICALL_EXPORT gfloat ves_icall_System_Threading_Interlocked_Exchange_Single(gfloat *location, gfloat value); @@ -184,11 +179,6 @@ gint64 ves_icall_System_Threading_Interlocked_CompareExchange_Long(gint64 *locat ICALL_EXPORT void ves_icall_System_Threading_Interlocked_CompareExchange_Object (MonoObject *volatile*location, MonoObject *volatile*value, MonoObject *volatile*comparand, MonoObject *volatile*res); -#ifndef ENABLE_NETCORE -ICALL_EXPORT -gpointer ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr(gpointer *location, gpointer value, gpointer comparand); -#endif - ICALL_EXPORT gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single(gfloat *location, gfloat value, gfloat comparand); @@ -363,9 +353,6 @@ mono_thread_set_name (MonoInternalThread *thread, MONO_THREAD_NAME_WINDOWS_CONSTANT (name), \ (flags) | MonoSetThreadNameFlag_Constant, NULL) -#ifndef ENABLE_NETCORE -void mono_thread_suspend_all_other_threads (void); -#endif gboolean mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout); void mono_thread_push_appdomain_ref (MonoDomain *domain); diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index be3416c..257d925 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -543,16 +543,6 @@ unlock_thread_handle (MonoInternalThreadHandle thread) } static gboolean -is_appdomainunloaded_exception (MonoClass *klass) -{ -#ifdef ENABLE_NETCORE - return FALSE; -#else - return klass == mono_class_get_appdomain_unloaded_exception_class (); -#endif -} - -static gboolean is_threadabort_exception (MonoClass *klass) { return klass == mono_defaults.threadabortexception_class; @@ -643,41 +633,11 @@ get_current_thread_ptr_for_domain (MonoDomain *domain, MonoInternalThread *threa return (MonoThread **)get_thread_static_data (thread, offset); } -static void -set_current_thread_for_domain (MonoDomain *domain, MonoInternalThread *thread, MonoThread *current) -{ -#ifndef ENABLE_NETCORE - MonoThread **current_thread_ptr = get_current_thread_ptr_for_domain (domain, thread); - - g_assert (current->obj.vtable->domain == domain); - - g_assert (!*current_thread_ptr); - *current_thread_ptr = current; -#endif -} - static MonoThread* create_thread_object (MonoDomain *domain, MonoInternalThread *internal) { -#ifdef ENABLE_NETCORE MONO_OBJECT_SETREF_INTERNAL (internal, internal_thread, internal); return internal; -#else - MonoThread *thread; - MonoVTable *vtable; - ERROR_DECL (error); - - vtable = mono_class_vtable_checked (domain, mono_defaults.thread_class, error); - mono_error_assert_ok (error); - - thread = (MonoThread*)mono_object_new_mature (vtable, error); - /* only possible failure mode is OOM, from which we don't expect to recover. */ - mono_error_assert_ok (error); - - MONO_OBJECT_SETREF_INTERNAL (thread, internal_thread, internal); - - return thread; -#endif } static void @@ -934,11 +894,6 @@ mono_thread_attach_internal (MonoThread *thread, gboolean force_attach, gboolean else MONO_OBJECT_SETREF_INTERNAL (internal, root_domain_thread, thread); - if (domain != root_domain) - set_current_thread_for_domain (root_domain, internal, internal->root_domain_thread); - - set_current_thread_for_domain (domain, internal, thread); - #ifdef MONO_METADATA_UPDATE /* Roll up to the latest published metadata generation */ mono_metadata_update_thread_expose_published (); @@ -1005,9 +960,6 @@ mono_thread_detach_internal (MonoInternalThread *thread) thread->abort_state_handle = 0; thread->abort_exc = NULL; -#ifndef ENABLE_NETCORE - thread->current_appcontext = NULL; -#endif LOCK_THREAD (thread); @@ -1250,7 +1202,6 @@ start_wrapper_internal (StartInfo *start_info, gsize *stack_ptr) if (start_func) { start_func (start_func_arg); } else { -#ifdef ENABLE_NETCORE /* Call a callback in the RuntimeThread class */ g_assert (start_delegate == NULL); @@ -1263,15 +1214,6 @@ start_wrapper_internal (StartInfo *start_info, gsize *stack_ptr) MONO_STATIC_POINTER_INIT_END (MonoMethod, cb) mono_runtime_invoke_checked (cb, internal, NULL, error); -#else - void *args [1]; - - g_assert (start_delegate != NULL); - - /* we may want to handle the exception here. See comment below on unhandled exceptions */ - args [0] = (gpointer) start_delegate_arg; - mono_runtime_delegate_invoke_checked (start_delegate, args, error); -#endif if (!is_ok (error)) { MonoException *ex = mono_error_convert_to_exception (error); @@ -1406,12 +1348,6 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, MonoObject *sta mono_g_hash_table_insert_internal (threads_starting_up, thread, thread); mono_threads_unlock (); -#ifndef ENABLE_NETCORE - internal->threadpool_thread = flags & MONO_THREAD_CREATE_FLAGS_THREADPOOL; - if (internal->threadpool_thread) - mono_thread_set_state (internal, ThreadState_Background); -#endif - internal->debugger_thread = flags & MONO_THREAD_CREATE_FLAGS_DEBUGGER; start_info = g_new0 (StartInfo, 1); @@ -1436,11 +1372,8 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, MonoObject *sta mono_g_hash_table_remove (threads_starting_up, thread); mono_threads_unlock (); -#ifdef ENABLE_NETCORE throw_thread_start_exception (mono_w32error_get_last(), error); -#else - mono_error_set_execution_engine (error, "Couldn't create thread. Error 0x%x", mono_w32error_get_last()); -#endif + /* ref is not going to be decremented in start_wrapper_internal */ mono_atomic_dec_i32 (&start_info->ref); ret = FALSE; @@ -1824,14 +1757,6 @@ mono_thread_construct_internal (MonoThreadObjectHandle this_obj_handle) mono_gchandle_free_internal (thread_gchandle); } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThreadObjectHandle this_obj_handle, MonoError *error) -{ - mono_thread_construct_internal (this_obj_handle); -} -#endif - void ves_icall_System_Threading_Thread_GetCurrentThread (MonoThread *volatile* thread) { @@ -1856,58 +1781,6 @@ mono_error_set_exception_thread_not_started_or_dead (MonoError *error) mono_error_set_exception_thread_state (error, "Thread has not been started, or is dead."); } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_Threading_Thread_Thread_internal (MonoThreadObjectHandle thread_handle, MonoObjectHandle start_handle, MonoError *error) -{ - MonoInternalThread *internal; - gboolean res; - MonoThread *this_obj = MONO_HANDLE_RAW (thread_handle); - MonoObject *start = MONO_HANDLE_RAW (start_handle); - -#ifdef DISABLE_THREADS - mono_error_set_platform_not_supported (error, "Cannot start threads on this runtime."); - return FALSE; -#endif - - THREAD_DEBUG (g_message("%s: Trying to start a new thread: this (%p) start (%p)", __func__, this_obj, start)); - - internal = thread_handle_to_internal_ptr (thread_handle); - - if (!internal) { - mono_thread_construct_internal (thread_handle); - internal = thread_handle_to_internal_ptr (thread_handle); - g_assert (internal); - } - - LOCK_THREAD (internal); - - if ((internal->state & ThreadState_Unstarted) == 0) { - UNLOCK_THREAD (internal); - mono_error_set_exception_thread_state (error, "Thread has already been started."); - return FALSE; - } - - if ((internal->state & ThreadState_Aborted) != 0) { - UNLOCK_THREAD (internal); - return TRUE; - } - - res = create_thread (this_obj, internal, start, NULL, NULL, MONO_THREAD_CREATE_FLAGS_NONE, error); - if (!res) { - UNLOCK_THREAD (internal); - return FALSE; - } - - internal->state &= ~ThreadState_Unstarted; - - THREAD_DEBUG (g_message ("%s: Started thread ID %" G_GSIZE_FORMAT " (handle %p)", __func__, (gsize)internal->tid, internal)); - - UNLOCK_THREAD (internal); - return TRUE; -} -#endif - static void mono_thread_name_cleanup (MonoThreadName* name) @@ -1996,32 +1869,11 @@ mono_sleep_internal (gint32 ms, MonoBoolean allow_interruption, MonoError *error } } -#ifdef ENABLE_NETCORE void ves_icall_System_Threading_Thread_Sleep_internal (gint32 ms, MonoBoolean allow_interruption, MonoError *error) { mono_sleep_internal (ms, allow_interruption, error); } -#else -void -ves_icall_System_Threading_Thread_Sleep_internal (gint32 ms, MonoError *error) -{ - mono_sleep_internal (ms, TRUE, error); -} - -void -ves_icall_System_Threading_Thread_SpinWait_nop (MonoError *error) -{ -} -#endif - -#ifndef ENABLE_NETCORE -gint32 -ves_icall_System_Threading_Thread_GetDomainID (MonoError *error) -{ - return mono_domain_get()->domain_id; -} -#endif /** * mono_thread_get_name_utf8: @@ -2071,30 +1923,6 @@ mono_thread_get_managed_id (MonoThread *thread) return id; } -#ifndef ENABLE_NETCORE -MonoStringHandle -ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThreadHandle thread_handle, MonoError *error) -{ - // InternalThreads are always pinned, so shallowly coop-handleize. - MonoInternalThread * const this_obj = mono_internal_thread_handle_ptr (thread_handle); - - MonoStringHandle str = NULL_HANDLE_STRING; - - // This is a little racy, ok. - - if (this_obj->name.chars) { - LOCK_THREAD (this_obj); - - if (this_obj->name.chars) - str = mono_string_new_utf8_len (mono_domain_get (), this_obj->name.chars, this_obj->name.length, error); - - UNLOCK_THREAD (this_obj); - } - - return str; -} -#endif - // Unusal function: // - MonoError is optional -- failure is usually not interesting, except the documented failure mode for managed callers. // - name16 only used on Windows. @@ -2172,44 +2000,17 @@ ves_icall_System_Threading_Thread_SetName_icall (MonoInternalThreadHandle thread char* name8 = name16 ? g_utf16_to_utf8 (name16, name16_length, NULL, &name8_length, NULL) : NULL; -#ifdef ENABLE_NETCORE // The managed thread implementation prevents the Name property from being set multiple times on normal threads. On thread // pool threads, for compatibility the thread's name should be changeable and this function may be called to force-reset the // thread's name if user code had changed it. So for the flags, MonoSetThreadNameFlag_Reset is passed instead of // MonoSetThreadNameFlag_Permanent for all threads, relying on the managed side to prevent multiple changes where // appropriate. MonoSetThreadNameFlags flags = MonoSetThreadNameFlag_Reset; -#else - MonoSetThreadNameFlags flags = MonoSetThreadNameFlag_Permanent; -#endif mono_thread_set_name (mono_internal_thread_handle_ptr (thread_handle), name8, (gint32)name8_length, name16, flags, error); } -#ifndef ENABLE_NETCORE -/* - * ves_icall_System_Threading_Thread_GetPriority_internal: - * @param this_obj: The MonoInternalThread on which to operate. - * - * Gets the priority of the given thread. - * @return: The priority of the given thread. - */ -int -ves_icall_System_Threading_Thread_GetPriority (MonoThreadObjectHandle this_obj, MonoError *error) -{ - gint32 priority; - - MonoInternalThread *internal = thread_handle_to_internal_ptr (this_obj); - - LOCK_THREAD (internal); - priority = internal->priority; - UNLOCK_THREAD (internal); - - return priority; -} -#endif - /* * ves_icall_System_Threading_Thread_SetPriority_internal: * @param this_obj: The MonoInternalThread on which to operate. @@ -2269,42 +2070,13 @@ exit: HANDLE_FUNCTION_RETURN_REF (MonoArray, dest.handle) } -#ifndef ENABLE_NETCORE -MonoArrayHandle -ves_icall_System_Threading_Thread_ByteArrayToRootDomain (MonoArrayHandle arr, MonoError *error) -{ - return byte_array_to_domain (arr, mono_get_root_domain (), error); -} - -MonoArrayHandle -ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (MonoArrayHandle arr, MonoError *error) -{ - return byte_array_to_domain (arr, mono_domain_get (), error); -} -#endif - /** * mono_thread_current: */ MonoThread * mono_thread_current (void) { -#ifdef ENABLE_NETCORE return mono_thread_internal_current (); -#else - MonoDomain *domain = mono_domain_get (); - MonoInternalThread *internal = mono_thread_internal_current (); - MonoThread **current_thread_ptr; - - g_assert (internal); - current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal); - - if (!*current_thread_ptr) { - g_assert (domain != mono_get_root_domain ()); - *current_thread_ptr = create_thread_object (domain, internal); - } - return *current_thread_ptr; -#endif } static MonoThreadObjectHandle @@ -2317,21 +2089,7 @@ mono_thread_current_handle (void) static MonoThread * mono_thread_current_for_thread (MonoInternalThread *internal) { -#ifdef ENABLE_NETCORE return mono_thread_internal_current (); -#else - MonoDomain *domain = mono_domain_get (); - MonoThread **current_thread_ptr; - - g_assert (internal); - current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal); - - if (!*current_thread_ptr) { - g_assert (domain != mono_get_root_domain ()); - *current_thread_ptr = create_thread_object (domain, internal); - } - return *current_thread_ptr; -#endif } MonoInternalThread* @@ -2618,13 +2376,6 @@ ves_icall_System_Threading_Interlocked_Exchange_Object (MonoObject *volatile*loc mono_gc_wbarrier_generic_nostore_internal ((gpointer)location); // FIXME volatile } -#ifndef ENABLE_NETCORE -gpointer ves_icall_System_Threading_Interlocked_Exchange_IntPtr (gpointer *location, gpointer value) -{ - return mono_atomic_xchg_ptr(location, value); -} -#endif - gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location, gfloat value) { IntFloatUnion val, ret; @@ -2689,13 +2440,6 @@ ves_icall_System_Threading_Interlocked_CompareExchange_Object (MonoObject *volat mono_gc_wbarrier_generic_nostore_internal ((gpointer)location); // FIXME volatile } -#ifndef ENABLE_NETCORE -gpointer ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr(gpointer *location, gpointer value, gpointer comparand) -{ - return mono_atomic_cas_ptr(location, value, comparand); -} -#endif - gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *location, gfloat value, gfloat comparand) { IntFloatUnion val, ret, cmp; @@ -2927,26 +2671,6 @@ request_thread_abort (MonoInternalThread *thread, MonoObjectHandle *state, gbool return TRUE; } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Threading_Thread_Abort (MonoInternalThreadHandle thread_handle, MonoObjectHandle state, MonoError *error) -{ - // InternalThreads are always pinned, so shallowly coop-handleize. - MonoInternalThread * const thread = mono_internal_thread_handle_ptr (thread_handle); - gboolean is_self = thread == mono_thread_internal_current (); - - /* For self aborts we always process the abort */ - if (!request_thread_abort (thread, &state, FALSE) && !is_self) - return; - - if (is_self) { - self_abort_internal (error); - } else { - async_abort_internal (thread, TRUE); - } -} -#endif - /** * mono_thread_internal_abort: * Request thread \p thread to be aborted. @@ -2963,38 +2687,6 @@ mono_thread_internal_abort (MonoInternalThread *thread, gboolean appdomain_unloa return async_abort_internal (thread, TRUE); } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Threading_Thread_ResetAbort (MonoThreadObjectHandle this_obj, MonoError *error) -{ - MonoInternalThread *thread = mono_thread_internal_current (); - gboolean was_aborting, is_domain_abort; - - LOCK_THREAD (thread); - was_aborting = thread->state & ThreadState_AbortRequested; - is_domain_abort = thread->flags & MONO_THREAD_FLAG_APPDOMAIN_ABORT; - - if (was_aborting && !is_domain_abort) - thread->state &= ~ThreadState_AbortRequested; - UNLOCK_THREAD (thread); - - if (!was_aborting) { - mono_error_set_exception_thread_state (error, "Unable to reset abort because no abort was requested"); - return; - } else if (is_domain_abort) { - /* Silently ignore abort resets in unloading appdomains */ - return; - } - - mono_get_eh_callbacks ()->mono_clear_abort_threshold (); - thread->abort_exc = NULL; - mono_gchandle_free_internal (thread->abort_state_handle); - /* This is actually not necessary - the handle - only counts if the exception is set */ - thread->abort_state_handle = 0; -} -#endif - void mono_thread_internal_reset_abort (MonoInternalThread *thread) { @@ -3014,48 +2706,6 @@ mono_thread_internal_reset_abort (MonoInternalThread *thread) UNLOCK_THREAD (thread); } -#ifndef ENABLE_NETCORE -MonoObjectHandle -ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThreadObjectHandle this_obj, MonoError *error) -{ - MonoInternalThread *thread = thread_handle_to_internal_ptr (this_obj); - - if (!thread->abort_state_handle) - return NULL_HANDLE; // No state. No error. - - // Convert gc handle to coop handle. - MonoObjectHandle state = mono_gchandle_get_target_handle (thread->abort_state_handle); - g_assert (MONO_HANDLE_BOOL (state)); - - MonoDomain *domain = mono_domain_get (); - if (MONO_HANDLE_DOMAIN (state) == domain) - return state; // No need to cross domain, return state directly. - - // Attempt move state cross-domain. - MonoObjectHandle deserialized = mono_object_xdomain_representation (state, domain, error); - - // If deserialized is null, there must be an error, and vice versa. - g_assert (is_ok (error) == MONO_HANDLE_BOOL (deserialized)); - - if (MONO_HANDLE_BOOL (deserialized)) - return deserialized; // Cross-domain serialization succeeded. Return it. - - // Wrap error in InvalidOperationException. - ERROR_DECL (error_creating_exception); - MonoExceptionHandle invalid_op_exc = mono_exception_new_invalid_operation ( - "Thread.ExceptionState cannot access an ExceptionState from a different AppDomain", error_creating_exception); - mono_error_assert_ok (error_creating_exception); - g_assert (!is_ok (error) && 1); - MONO_HANDLE_SET (invalid_op_exc, inner_ex, mono_error_convert_to_exception_handle (error)); - error_init_reuse (error); - mono_error_set_exception_handle (error, invalid_op_exc); - g_assert (!is_ok (error) && 2); - - // There is state, but we failed to return it. - return NULL_HANDLE; -} -#endif - static gboolean mono_thread_suspend (MonoInternalThread *thread) { @@ -3089,16 +2739,6 @@ mono_thread_suspend (MonoInternalThread *thread) return TRUE; } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Threading_Thread_Suspend (MonoThreadObjectHandle this_obj, MonoError *error) -{ - if (!mono_thread_suspend (thread_handle_to_internal_ptr (this_obj))) - mono_error_set_exception_thread_not_started_or_dead (error); - -} -#endif - /* LOCKING: LOCK_THREAD(thread) must be held */ static gboolean mono_thread_resume (MonoInternalThread *thread) @@ -3142,28 +2782,6 @@ mono_thread_resume (MonoInternalThread *thread) return TRUE; } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Threading_Thread_Resume (MonoThreadObjectHandle thread_handle, MonoError *error) -{ - // Internal threads are pinned so shallow coop/handle. - MonoInternalThread * const internal_thread = thread_handle_to_internal_ptr (thread_handle); - gboolean exception = FALSE; - - if (!internal_thread) { - exception = TRUE; - } else { - LOCK_THREAD (internal_thread); - if (!mono_thread_resume (internal_thread)) - exception = TRUE; - UNLOCK_THREAD (internal_thread); - } - - if (exception) - mono_error_set_exception_thread_not_started_or_dead (error); -} -#endif - gboolean mono_threads_is_critical_method (MonoMethod *method) { @@ -3499,14 +3117,6 @@ mono_threads_register_app_context (MonoAppContextHandle ctx, MonoError *error) MONO_PROFILER_RAISE (context_loaded, (MONO_HANDLE_RAW (ctx))); } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext (MonoAppContextHandle ctx, MonoError *error) -{ - mono_threads_register_app_context (ctx, error); -} -#endif - void mono_threads_release_app_context (MonoAppContext* ctx, MonoError *error) { @@ -3521,14 +3131,6 @@ mono_threads_release_app_context (MonoAppContext* ctx, MonoError *error) MONO_PROFILER_RAISE (context_unloaded, (ctx)); } -#ifndef ENABLE_NETCORE -void -ves_icall_System_Runtime_Remoting_Contexts_Context_ReleaseContext (MonoAppContextHandle ctx, MonoError *error) -{ - mono_threads_release_app_context (MONO_HANDLE_RAW (ctx), error); /* FIXME use handles in mono_threads_release_app_context */ -} -#endif - void mono_thread_init (MonoThreadStartCB start_cb, MonoThreadAttachCB attach_cb) { @@ -3948,35 +3550,6 @@ mono_thread_manage_internal (void) mono_thread_execute_interruption_void (); } -#ifndef ENABLE_NETCORE - /* - * Under netcore, we don't abort any threads, just exit. - * This is not a problem since we don't do runtime cleanup either. - */ - /* - * Remove everything but the finalizer thread and self. - * Also abort all the background threads - * */ - do { - THREAD_DEBUG (g_message ("%s: abort phase", __func__)); - - mono_threads_lock (); - - wait->num = 0; - /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/ - memset (wait->threads, 0, sizeof (wait->threads)); - mono_g_hash_table_foreach (threads, abort_threads, wait); - - mono_threads_unlock (); - - THREAD_DEBUG (g_message ("%s: wait->num is now %d", __func__, wait->num)); - if (wait->num > 0) { - /* Something to wait for */ - wait_for_tids (wait, MONO_INFINITE_WAIT, FALSE); - } - } while (wait->num > 0); -#endif - /* * give the subthreads a chance to really quit (this is mainly needed * to get correct user and system times from getrusage/wait/time(1)). @@ -3985,140 +3558,6 @@ mono_thread_manage_internal (void) mono_thread_info_yield (); } -#ifndef ENABLE_NETCORE -static void -collect_threads_for_suspend (gpointer key, gpointer value, gpointer user_data) -{ - MonoInternalThread *thread = (MonoInternalThread*)value; - struct wait_data *wait = (struct wait_data*)user_data; - - /* - * We try to exclude threads early, to avoid running into the MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS - * limitation. - * This needs no locking. - */ - if ((thread->state & ThreadState_Suspended) != 0 || - (thread->state & ThreadState_Stopped) != 0) - return; - - if (wait->numhandles [wait->num] = mono_threads_open_thread_handle (thread->handle); - wait->threads [wait->num] = thread; - wait->num++; - } -} - -/* - * mono_thread_suspend_all_other_threads: - * - * Suspend all managed threads except the finalizer thread and this thread. It is - * not possible to resume them later. - */ -void mono_thread_suspend_all_other_threads (void) -{ - struct wait_data wait_data; - struct wait_data *wait = &wait_data; - int i; - MonoNativeThreadId self = mono_native_thread_id_get (); - guint32 eventidx = 0; - gboolean starting, finished; - - memset (wait, 0, sizeof (struct wait_data)); - /* - * The other threads could be in an arbitrary state at this point, i.e. - * they could be starting up, shutting down etc. This means that there could be - * threads which are not even in the threads hash table yet. - */ - - /* - * First we set a barrier which will be checked by all threads before they - * are added to the threads hash table, and they will exit if the flag is set. - * This ensures that no threads could be added to the hash later. - * We will use shutting_down as the barrier for now. - */ - g_assert (shutting_down); - - /* - * We make multiple calls to WaitForMultipleObjects since: - * - we can only wait for MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS threads - * - some threads could exit without becoming suspended - */ - finished = FALSE; - while (!finished) { - /* - * Make a copy of the hashtable since we can't do anything with - * threads while threads_mutex is held. - */ - wait->num = 0; - /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/ - memset (wait->threads, 0, sizeof (wait->threads)); - mono_threads_lock (); - mono_g_hash_table_foreach (threads, collect_threads_for_suspend, wait); - mono_threads_unlock (); - - eventidx = 0; - /* Get the suspended events that we'll be waiting for */ - for (i = 0; i < wait->num; ++i) { - MonoInternalThread *thread = wait->threads [i]; - - if (mono_native_thread_id_equals (thread_get_tid (thread), self) - || mono_gc_is_finalizer_internal_thread (thread) - || (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE) - ) { - mono_threads_close_thread_handle (wait->handles [i]); - wait->threads [i] = NULL; - continue; - } - - LOCK_THREAD (thread); - - if (thread->state & (ThreadState_Suspended | ThreadState_Stopped)) { - UNLOCK_THREAD (thread); - mono_threads_close_thread_handle (wait->handles [i]); - wait->threads [i] = NULL; - continue; - } - - ++eventidx; - - /* Convert abort requests into suspend requests */ - if ((thread->state & ThreadState_AbortRequested) != 0) - thread->state &= ~ThreadState_AbortRequested; - - thread->state |= ThreadState_SuspendRequested; - MONO_ENTER_GC_SAFE; - mono_os_event_reset (thread->suspended); - MONO_EXIT_GC_SAFE; - - /* Signal the thread to suspend + calls UNLOCK_THREAD (thread) */ - async_suspend_internal (thread, TRUE); - - mono_threads_close_thread_handle (wait->handles [i]); - wait->threads [i] = NULL; - } - if (eventidx <= 0) { - /* - * If there are threads which are starting up, we wait until they - * are suspended when they try to register in the threads hash. - * This is guaranteed to finish, since the threads which can create new - * threads get suspended after a while. - * FIXME: The finalizer thread can still create new threads. - */ - mono_threads_lock (); - if (threads_starting_up) - starting = mono_g_hash_table_size (threads_starting_up) > 0; - else - starting = FALSE; - mono_threads_unlock (); - if (starting) - mono_thread_info_sleep (100, NULL); - else - finished = TRUE; - } - } -} -#endif - typedef struct { MonoInternalThread *thread; MonoStackFrameInfo *frames; @@ -4344,123 +3783,6 @@ mono_threads_perform_thread_dump (void) thread_dump_requested = FALSE; } -#ifndef ENABLE_NETCORE -/* Obtain the thread dump of all threads */ -void -ves_icall_System_Threading_Thread_GetStackTraces (MonoArrayHandleOut out_threads_handle, MonoArrayHandleOut out_stack_frames_handle, MonoError *error) -{ - MONO_HANDLE_ASSIGN_RAW (out_threads_handle, NULL); - MONO_HANDLE_ASSIGN_RAW (out_stack_frames_handle, NULL); - - MonoGCHandle handle = 0; - - MonoStackFrameHandle stack_frame_handle = MONO_HANDLE_NEW (MonoStackFrame, NULL); - MonoReflectionMethodHandle reflection_method_handle = MONO_HANDLE_NEW (MonoReflectionMethod, NULL); - MonoStringHandle filename_handle = MONO_HANDLE_NEW (MonoString, NULL); - MonoArrayHandle thread_frames_handle = MONO_HANDLE_NEW (MonoArray, NULL); - - ThreadDumpUserData ud; - MonoGCHandle thread_array [128]; - MonoDomain *domain = mono_domain_get (); - MonoDebugSourceLocation *location; - int tindex, nthreads; - - MonoArray* out_threads = NULL; - MonoArray* out_stack_frames = NULL; - - MONO_HANDLE_ASSIGN_RAW (out_threads_handle, NULL); - MONO_HANDLE_ASSIGN_RAW (out_stack_frames_handle, NULL); - - /* Make a copy of the threads hash to avoid doing work inside threads_lock () */ - nthreads = collect_threads (thread_array, 128); - - memset (&ud, 0, sizeof (ud)); - ud.frames = g_new0 (MonoStackFrameInfo, 256); - ud.max_frames = 256; - - out_threads = mono_array_new_checked (domain, mono_defaults.thread_class, nthreads, error); - goto_if_nok (error, leave); - MONO_HANDLE_ASSIGN_RAW (out_threads_handle, out_threads); - out_stack_frames = mono_array_new_checked (domain, mono_defaults.array_class, nthreads, error); - goto_if_nok (error, leave); - MONO_HANDLE_ASSIGN_RAW (out_stack_frames_handle, out_stack_frames); - - for (tindex = 0; tindex < nthreads; ++tindex) { - - mono_gchandle_free_internal (handle); - handle = thread_array [tindex]; - MonoInternalThread *thread = (MonoInternalThread *) mono_gchandle_get_target_internal (handle); - - MonoArray *thread_frames; - int i; - - ud.thread = thread; - ud.nframes = 0; - - /* Collect frames for the thread */ - if (thread == mono_thread_internal_current ()) { - get_thread_dump (mono_thread_info_current (), &ud); - } else { - mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), FALSE, get_thread_dump, &ud); - } - - mono_array_setref_fast (out_threads, tindex, mono_thread_current_for_thread (thread)); - - thread_frames = mono_array_new_checked (domain, mono_defaults.stack_frame_class, ud.nframes, error); - MONO_HANDLE_ASSIGN_RAW (thread_frames_handle, thread_frames); - goto_if_nok (error, leave); - mono_array_setref_fast (out_stack_frames, tindex, thread_frames); - - for (i = 0; i < ud.nframes; ++i) { - MonoStackFrameInfo *frame = &ud.frames [i]; - MonoMethod *method = NULL; - MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, error); - MONO_HANDLE_ASSIGN_RAW (stack_frame_handle, sf); - goto_if_nok (error, leave); - - sf->native_offset = frame->native_offset; - - if (frame->type == FRAME_TYPE_MANAGED) - method = mono_jit_info_get_method (frame->ji); - - if (method) { - sf->method_address = (gsize) frame->ji->code_start; - - MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, error); - MONO_HANDLE_ASSIGN_RAW (reflection_method_handle, rm); - goto_if_nok (error, leave); - MONO_OBJECT_SETREF_INTERNAL (sf, method, rm); - - location = mono_debug_lookup_source_location (method, frame->native_offset, domain); - if (location) { - sf->il_offset = location->il_offset; - - if (location->source_file) { - MonoString *filename = mono_string_new_checked (domain, location->source_file, error); - MONO_HANDLE_ASSIGN_RAW (filename_handle, filename); - goto_if_nok (error, leave); - MONO_OBJECT_SETREF_INTERNAL (sf, filename, filename); - sf->line = location->row; - sf->column = location->column; - } - mono_debug_free_source_location (location); - } else { - sf->il_offset = -1; - } - } - mono_array_setref_internal (thread_frames, i, sf); - } - - mono_gchandle_free_internal (handle); - handle = 0; - } - -leave: - mono_gchandle_free_internal (handle); - g_free (ud.frames); -} -#endif - /** * mono_threads_request_thread_dump: * @@ -5053,11 +4375,7 @@ mono_get_special_static_data_for_thread (MonoInternalThread *thread, guint32 off if (static_type == SPECIAL_STATIC_OFFSET_TYPE_THREAD) { return get_thread_static_data (thread, offset); } else { -#ifndef ENABLE_NETCORE - return get_context_static_data (thread->current_appcontext, offset); -#else g_assert_not_reached (); -#endif } } @@ -6233,8 +5551,7 @@ mono_thread_internal_unhandled_exception (MonoObject* exc) MonoClass *klass = exc->vtable->klass; if (is_threadabort_exception (klass)) { mono_thread_internal_reset_abort (mono_thread_internal_current ()); - } else if (!is_appdomainunloaded_exception (klass) - && mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT) { + } else if (mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT) { mono_unhandled_exception_internal (exc); if (mono_environment_exitcode_get () == 1) { mono_environment_exitcode_set (255); @@ -6948,7 +6265,6 @@ mono_threads_summarize (MonoContext *ctx, gchar **out, MonoStackHash *hashes, gb #endif -#ifdef ENABLE_NETCORE void ves_icall_System_Threading_Thread_StartInternal (MonoThreadObjectHandle thread_handle, MonoError *error) { @@ -7037,4 +6353,3 @@ ves_icall_System_Threading_LowLevelLifoSemaphore_ReleaseInternal (gpointer sem_p LifoSemaphore *sem = (LifoSemaphore *)sem_ptr; mono_lifo_semaphore_release (sem, count); } -#endif diff --git a/src/mono/mono/metadata/w32event-unix.c b/src/mono/mono/metadata/w32event-unix.c index abc9bf9..e55051b 100644 --- a/src/mono/mono/metadata/w32event-unix.c +++ b/src/mono/mono/metadata/w32event-unix.c @@ -378,20 +378,6 @@ ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle) mono_w32handle_close (handle); } -#ifndef ENABLE_NETCORE -gpointer -ves_icall_System_Threading_Events_OpenEvent_icall (const gunichar2 *name, gint32 name_length, - gint32 rights, gint32 *win32error, MonoError *error) -{ - *win32error = ERROR_SUCCESS; - char *utf8_name = mono_utf16_to_utf8 (name, name_length, error); - return_val_if_nok (error, NULL); - gpointer handle = mono_w32event_open (utf8_name, rights, win32error); - g_free (utf8_name); - return handle; -} -#endif - gpointer mono_w32event_open (const gchar *utf8_name, gint32 rights G_GNUC_UNUSED, gint32 *win32error) { diff --git a/src/mono/mono/metadata/w32file-unix.c b/src/mono/mono/metadata/w32file-unix.c index 2105d20..0d84285 100644 --- a/src/mono/mono/metadata/w32file-unix.c +++ b/src/mono/mono/metadata/w32file-unix.c @@ -4726,40 +4726,6 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name) } #endif -#ifndef ENABLE_NETCORE -guint32 -mono_w32file_get_drive_type (const gunichar2 *root_path_name, gint32 root_path_name_length, MonoError *error) -{ - // FIXME Check for embedded nuls here or in managed. - - gchar *utf8_root_path_name; - guint32 drive_type; - - if (root_path_name == NULL) { - utf8_root_path_name = g_strdup (g_get_current_dir()); - if (utf8_root_path_name == NULL) { - return(DRIVE_NO_ROOT_DIR); - } - } - else { - utf8_root_path_name = mono_unicode_to_external_checked (root_path_name, error); - if (utf8_root_path_name == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: unicode conversion returned NULL; %s", __func__, mono_error_get_message (error)); - return(DRIVE_NO_ROOT_DIR); - } - - /* strip trailing slash for compare below */ - if (g_str_has_suffix(utf8_root_path_name, "/") && utf8_root_path_name [1] != 0) { - utf8_root_path_name[strlen(utf8_root_path_name) - 1] = 0; - } - } - drive_type = GetDriveTypeFromPath (utf8_root_path_name); - g_free (utf8_root_path_name); - - return (drive_type); -} -#endif - #if defined (HOST_DARWIN) || defined (__linux__) || defined(HOST_BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__) || defined(_AIX) static gchar* get_fstypename (gchar *utfpath) diff --git a/src/mono/mono/metadata/w32file.c b/src/mono/mono/metadata/w32file.c deleted file mode 100644 index bee7f71..0000000 --- a/src/mono/mono/metadata/w32file.c +++ /dev/null @@ -1,920 +0,0 @@ -/** - * \file - * File IO internal calls - * - * Author: - * Dick Porter (dick@ximian.com) - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) - * Copyright 2004-2009 Novell, Inc (http://www.novell.com) - * Copyright 2012 Xamarin Inc (http://www.xamarin.com) - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include - -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "icall-decl.h" - -#undef DEBUG - -/* conversion functions */ - -static guint32 convert_mode(MonoFileMode mono_mode) -{ - guint32 mode; - - switch(mono_mode) { - case FileMode_CreateNew: - mode=CREATE_NEW; - break; - case FileMode_Create: - mode=CREATE_ALWAYS; - break; - case FileMode_Open: - mode=OPEN_EXISTING; - break; - case FileMode_OpenOrCreate: - mode=OPEN_ALWAYS; - break; - case FileMode_Truncate: - mode=TRUNCATE_EXISTING; - break; - case FileMode_Append: - mode=OPEN_ALWAYS; - break; - default: - g_warning("System.IO.FileMode has unknown value 0x%x", - mono_mode); - /* Safe fallback */ - mode=OPEN_EXISTING; - } - - return(mode); -} - -static guint32 convert_access(MonoFileAccess mono_access) -{ - guint32 access; - - switch(mono_access) { - case FileAccess_Read: - access=GENERIC_READ; - break; - case FileAccess_Write: - access=GENERIC_WRITE; - break; - case FileAccess_ReadWrite: - access=GENERIC_READ|GENERIC_WRITE; - break; - default: - g_warning("System.IO.FileAccess has unknown value 0x%x", - mono_access); - /* Safe fallback */ - access=GENERIC_READ; - } - - return(access); -} - -static guint32 convert_share(MonoFileShare mono_share) -{ - guint32 share = 0; - - if (mono_share & FileShare_Read) { - share |= FILE_SHARE_READ; - } - if (mono_share & FileShare_Write) { - share |= FILE_SHARE_WRITE; - } - if (mono_share & FileShare_Delete) { - share |= FILE_SHARE_DELETE; - } - - if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) { - g_warning("System.IO.FileShare has unknown value 0x%x", - mono_share); - /* Safe fallback */ - share=0; - } - - return(share); -} - -#if 0 -static guint32 convert_stdhandle(guint32 fd) -{ - guint32 stdhandle; - - switch(fd) { - case 0: - stdhandle=STD_INPUT_HANDLE; - break; - case 1: - stdhandle=STD_OUTPUT_HANDLE; - break; - case 2: - stdhandle=STD_ERROR_HANDLE; - break; - default: - g_warning("unknown standard file descriptor %d", fd); - stdhandle=STD_INPUT_HANDLE; - } - - return(stdhandle); -} -#endif - -static guint32 convert_seekorigin(MonoSeekOrigin origin) -{ - guint32 w32origin; - - switch(origin) { - case SeekOrigin_Begin: - w32origin=FILE_BEGIN; - break; - case SeekOrigin_Current: - w32origin=FILE_CURRENT; - break; - case SeekOrigin_End: - w32origin=FILE_END; - break; - default: - g_warning("System.IO.SeekOrigin has unknown value 0x%x", - origin); - /* Safe fallback */ - w32origin=FILE_CURRENT; - } - - return(w32origin); -} - -/* Managed file attributes have nearly but not quite the same values - * as the w32 equivalents. - */ -static guint32 convert_attrs(MonoFileAttributes attrs) -{ - if(attrs & FileAttributes_Encrypted) { - attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED); - } - - return(attrs); -} - -/* System.IO.MonoIO internal calls */ - -#if !ENABLE_NETCORE - -MonoBoolean -ves_icall_System_IO_MonoIO_CreateDirectory (const gunichar2 *path, gint32 *error) -{ - gboolean ret; - - *error=ERROR_SUCCESS; - - ret=mono_w32file_create_directory (path); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_RemoveDirectory (const gunichar2 *path, gint32 *error) -{ - gboolean ret; - - *error=ERROR_SUCCESS; - - ret=mono_w32file_remove_directory (path); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -HANDLE -ves_icall_System_IO_MonoIO_FindFirstFile (const gunichar2 *path_with_pattern, MonoStringHandleOut file_name, gint32 *file_attr, gint32 *ioerror, MonoError *error) -{ - HANDLE hnd; - WIN32_FIND_DATA data; - - hnd = mono_w32file_find_first (path_with_pattern, &data); - - if (hnd == INVALID_HANDLE_VALUE) { - MONO_HANDLE_ASSIGN (file_name, NULL_HANDLE_STRING); - *file_attr = 0; - *ioerror = mono_w32error_get_last (); - return hnd; - } - - int len = 0; - while (data.cFileName [len]) len++; - MONO_HANDLE_ASSIGN (file_name, mono_string_new_utf16_handle (mono_domain_get (), data.cFileName, len, error)); - return_val_if_nok (error, INVALID_HANDLE_VALUE); - - *file_attr = data.dwFileAttributes; - *ioerror = ERROR_SUCCESS; - - return hnd; -} - -MonoBoolean -ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoStringHandleOut file_name, gint32 *file_attr, gint32 *ioerror, MonoError *error) -{ - MonoBoolean res; - WIN32_FIND_DATA data; - - res = mono_w32file_find_next (hnd, &data); - - if (res == FALSE) { - MONO_HANDLE_ASSIGN (file_name, NULL_HANDLE_STRING); - *file_attr = 0; - *ioerror = mono_w32error_get_last (); - return res; - } - - int len = 0; - while (data.cFileName [len]) len++; - MONO_HANDLE_ASSIGN (file_name, mono_string_new_utf16_handle (mono_domain_get (), data.cFileName, len, error)); - return_val_if_nok (error, FALSE); - - *file_attr = data.dwFileAttributes; - *ioerror = ERROR_SUCCESS; - - return res; -} - -MonoBoolean -ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd) -{ - return mono_w32file_find_close (hnd); -} - -MonoStringHandle -ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error, MonoError *error) -{ - MonoStringHandle result; - gunichar2 *buf; - int len, res_len; - - len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/ - buf = g_new (gunichar2, len); - - *io_error = ERROR_SUCCESS; - result = MONO_HANDLE_NEW (MonoString, NULL); - - res_len = mono_w32file_get_cwd (len, buf); - if (res_len > len) { /*buf is too small.*/ - int old_res_len = res_len; - g_free (buf); - buf = g_new (gunichar2, res_len); - res_len = mono_w32file_get_cwd (res_len, buf) == old_res_len; - } - - if (res_len) { - len = 0; - while (buf [len]) - ++ len; - - MONO_HANDLE_ASSIGN (result, mono_string_new_utf16_handle (mono_domain_get (), buf, len, error)); - } else { - *io_error=mono_w32error_get_last (); - } - - g_free (buf); - return_val_if_nok (error, NULL_HANDLE_STRING); - return result; -} - -MonoBoolean -ves_icall_System_IO_MonoIO_SetCurrentDirectory (const gunichar2 *path, - gint32 *error) -{ - gboolean ret; - - *error=ERROR_SUCCESS; - - ret=mono_w32file_set_cwd (path); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_MoveFile (const gunichar2 *path, const gunichar2 *dest, gint32 *error) -{ - *error=ERROR_SUCCESS; - return mono_w32file_move (path, dest, error); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_ReplaceFile (const gunichar2 *source_file_name, const gunichar2 *destination_file_name, - const gunichar2 *destination_backup_file_name, MonoBoolean ignore_metadata_errors, - gint32 *error) -{ - guint32 replace_flags = REPLACEFILE_WRITE_THROUGH; - - *error = ERROR_SUCCESS; - if (ignore_metadata_errors) - replace_flags |= REPLACEFILE_IGNORE_MERGE_ERRORS; - - /* FIXME: source and destination file names must not be NULL, but apparently they might be! */ - return mono_w32file_replace (destination_file_name, source_file_name, - destination_backup_file_name, replace_flags, error); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_CopyFile (const gunichar2 *path, const gunichar2 *dest, - MonoBoolean overwrite, gint32 *error) -{ - *error=ERROR_SUCCESS; - return mono_w32file_copy (path, dest, overwrite, error); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_DeleteFile (const gunichar2 *path, gint32 *error) -{ - gboolean ret; - - *error=ERROR_SUCCESS; - - ret=mono_w32file_delete (path); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -gint32 -ves_icall_System_IO_MonoIO_GetFileAttributes (const gunichar2 *path, gint32 *error) -{ - gint32 ret; - *error=ERROR_SUCCESS; - - ret = mono_w32file_get_attributes (path); - - /* - * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32 - * headers is wrong, hence this temporary workaround. - * See - * http://cygwin.com/ml/cygwin/2003-09/msg01771.html - */ - if (ret==-1) { - /* if(ret==INVALID_FILE_ATTRIBUTES) { */ - *error=mono_w32error_get_last (); - } - return(ret); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_SetFileAttributes (const gunichar2 *path, gint32 attrs, - gint32 *error) -{ - gboolean ret; - *error=ERROR_SUCCESS; - - ret=mono_w32file_set_attributes (path, - convert_attrs ((MonoFileAttributes)attrs)); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - return(ret); -} - -gint32 -ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error) -{ - gboolean ret; - - *error=ERROR_SUCCESS; - - ret=mono_w32file_get_type (handle); - if(ret==FILE_TYPE_UNKNOWN) { - /* Not necessarily an error, but the caller will have - * to decide based on the error value. - */ - *error=mono_w32error_get_last (); - } - - return(ret); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_GetFileStat (const gunichar2 *path, MonoIOStat *stat, gint32 *error) -{ - gboolean result; - - *error=ERROR_SUCCESS; - - result = mono_w32file_get_attributes_ex (path, stat); - - if (!result) { - *error=mono_w32error_get_last (); - memset (stat, 0, sizeof (MonoIOStat)); - } - - return result; -} - -HANDLE -ves_icall_System_IO_MonoIO_Open (const gunichar2 *filename, gint32 mode, - gint32 access_mode, gint32 share, gint32 options, - gint32 *error) -{ - HANDLE ret; - int attributes, attrs; - - *error=ERROR_SUCCESS; - - if (options != 0){ - if (options & FileOptions_Encrypted) - attributes = FILE_ATTRIBUTE_ENCRYPTED; - else - attributes = FILE_ATTRIBUTE_NORMAL; - if (options & FileOptions_DeleteOnClose) - attributes |= FILE_FLAG_DELETE_ON_CLOSE; - if (options & FileOptions_SequentialScan) - attributes |= FILE_FLAG_SEQUENTIAL_SCAN; - if (options & FileOptions_RandomAccess) - attributes |= FILE_FLAG_RANDOM_ACCESS; - - if (options & FileOptions_Temporary) - attributes |= FILE_ATTRIBUTE_TEMPORARY; - - if (options & FileOptions_WriteThrough) - attributes |= FILE_FLAG_WRITE_THROUGH; - } else - attributes = FILE_ATTRIBUTE_NORMAL; - - /* If we're opening a directory we need to set the extra flag - */ - attrs = mono_w32file_get_attributes (filename); - if (attrs != INVALID_FILE_ATTRIBUTES) { - if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - attributes |= FILE_FLAG_BACKUP_SEMANTICS; - } - } - - ret=mono_w32file_create (filename, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes); - if(ret==INVALID_HANDLE_VALUE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error) -{ - gboolean ret; - *error=ERROR_SUCCESS; - - ret=mono_w32file_close (handle); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - return(ret); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_Cancel (HANDLE handle, gint32 *error) -{ - gboolean ret; - *error=ERROR_SUCCESS; - - ret = mono_w32file_cancel (handle); - if (ret == FALSE) - *error = mono_w32error_get_last (); - - return ret; -} - -gint32 -ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArrayHandle dest, - gint32 dest_offset, gint32 count, - gint32 *io_error, - MonoError *error) -{ - void *buffer; - gboolean result; - guint32 n; - - *io_error=ERROR_SUCCESS; - - MONO_CHECK_ARG_NULL_HANDLE (dest, 0); - - if (dest_offset > mono_array_handle_length (dest) - count) { - mono_error_set_argument (error, "array", "array too small. numBytes/offset wrong."); - return 0; - } - - MonoGCHandle buffer_handle = NULL; - buffer = MONO_ARRAY_HANDLE_PIN (dest, guchar, dest_offset, &buffer_handle); - result = mono_w32file_read (handle, buffer, count, &n, io_error); - mono_gchandle_free_internal (buffer_handle); - - if (!result) - return -1; - - return (gint32)n; -} - -gint32 -ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArrayHandle src, - gint32 src_offset, gint32 count, - gint32 *io_error, - MonoError *error) -{ - void *buffer; - gboolean result; - guint32 n; - - *io_error=ERROR_SUCCESS; - - MONO_CHECK_ARG_NULL_HANDLE (src, 0); - - if (src_offset > mono_array_handle_length (src) - count) { - mono_error_set_argument (error, "array", "array too small. numBytes/offset wrong."); - return 0; - } - - MonoGCHandle src_handle = NULL; - buffer = MONO_ARRAY_HANDLE_PIN (src, guchar, src_offset, &src_handle); - result = mono_w32file_write (handle, buffer, count, &n, io_error); - mono_gchandle_free_internal (src_handle); - - if (!result) - return -1; - - return (gint32)n; -} - -gint64 -ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin, - gint32 *error) -{ - gint32 offset_hi; - - *error=ERROR_SUCCESS; - - offset_hi = offset >> 32; - offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi, - convert_seekorigin ((MonoSeekOrigin)origin)); - - if(offset==INVALID_SET_FILE_POINTER) { - *error=mono_w32error_get_last (); - } - - return offset | ((gint64)offset_hi << 32); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error) -{ - gboolean ret; - - *error=ERROR_SUCCESS; - - ret=mono_w32file_flush (handle); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -gint64 -ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error) -{ - *error=ERROR_SUCCESS; - return mono_w32file_get_file_size (handle, error); -} - -/* FIXME make gc suspendable */ -MonoBoolean -ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length, - gint32 *error) -{ - gint64 offset, offset_set; - gint32 offset_hi; - gint32 length_hi; - gboolean result; - - *error=ERROR_SUCCESS; - - /* save file pointer */ - - offset_hi = 0; - offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT); - if(offset==INVALID_SET_FILE_POINTER) { - *error=mono_w32error_get_last (); - return(FALSE); - } - - /* extend or truncate */ - - length_hi = length >> 32; - offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi, - FILE_BEGIN); - if(offset_set==INVALID_SET_FILE_POINTER) { - *error=mono_w32error_get_last (); - return(FALSE); - } - - result = mono_w32file_truncate (handle); - if(result==FALSE) { - *error=mono_w32error_get_last (); - return(FALSE); - } - - /* restore file pointer */ - - offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi, - FILE_BEGIN); - if(offset_set==INVALID_SET_FILE_POINTER) { - *error=mono_w32error_get_last (); - return(FALSE); - } - - return result; -} - -MonoBoolean -ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time, - gint64 last_access_time, - gint64 last_write_time, gint32 *error) -{ - gboolean ret; - const FILETIME *creation_filetime; - const FILETIME *access_filetime; - const FILETIME *write_filetime; - - *error=ERROR_SUCCESS; - - if (creation_time < 0) - creation_filetime = NULL; - else - creation_filetime = (FILETIME *)&creation_time; - - if (last_access_time < 0) - access_filetime = NULL; - else - access_filetime = (FILETIME *)&last_access_time; - - if (last_write_time < 0) - write_filetime = NULL; - else - write_filetime = (FILETIME *)&last_write_time; - - ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime); - if(ret==FALSE) { - *error=mono_w32error_get_last (); - } - - return(ret); -} - -HANDLE -ves_icall_System_IO_MonoIO_get_ConsoleOutput (void) -{ - return mono_w32file_get_console_output (); -} - -HANDLE -ves_icall_System_IO_MonoIO_get_ConsoleInput (void) -{ - return mono_w32file_get_console_input (); -} - -HANDLE -ves_icall_System_IO_MonoIO_get_ConsoleError (void) -{ - return mono_w32file_get_console_error (); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error) -{ - *error = ERROR_SUCCESS; - - gboolean ret; - - ret=mono_w32file_create_pipe (read_handle, write_handle, 0); - - if(ret==FALSE) { - *error = mono_w32error_get_last (); - /* FIXME: throw an exception? */ - return(FALSE); - } - - return(TRUE); -} - -MonoBoolean -ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle, - HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error) -{ -#ifndef HOST_WIN32 - MonoW32Handle *source_handle_data; - - if (!mono_w32handle_lookup_and_ref (source_handle, &source_handle_data)) { - *error = ERROR_INVALID_HANDLE; - return FALSE; - } - - *target_handle = mono_w32handle_duplicate (source_handle_data); - - mono_w32handle_unref ((MonoW32Handle*)source_handle); -#else - gboolean ret; - - MONO_ENTER_GC_SAFE; - ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options); - MONO_EXIT_GC_SAFE; - - if (!ret) { - *error = mono_w32error_get_last (); - /* FIXME: throw an exception? */ - return(FALSE); - } -#endif - - return(TRUE); -} - -#ifndef HOST_WIN32 -gunichar2 -ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void) -{ - return (gunichar2) '/'; /* forward slash */ -} - -gunichar2 -ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void) -{ - return (gunichar2) '/'; /* forward slash */ -} - -gunichar2 -ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void) -{ -#if TARGET_WASM - return (gunichar2) '\\'; /* backslash issue https://github.com/mono/mono/issues/18933 */ -#else - if (IS_PORTABILITY_SET) - return (gunichar2) '\\'; /* backslash */ - else - return (gunichar2) '/'; /* forward slash */ -#endif -} - -gunichar2 -ves_icall_System_IO_MonoIO_get_PathSeparator (void) -{ - return (gunichar2) ':'; /* colon */ -} -#endif /* !HOST_WIN32 */ - -static const gunichar2 -invalid_path_chars [] = { -#if defined (TARGET_WIN32) - 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */ - 0x003c, /* less than */ - 0x003e, /* greater than */ - 0x007c, /* pipe */ - 0x0008, - 0x0010, - 0x0011, - 0x0012, - 0x0014, - 0x0015, - 0x0016, - 0x0017, - 0x0018, - 0x0019, -#endif - 0x0000 /* null */ -}; - -MonoArrayHandle -ves_icall_System_IO_MonoIO_get_InvalidPathChars (MonoError *error) -{ - MonoArrayHandle chars = MONO_HANDLE_NEW (MonoArray, NULL); - MonoDomain *domain; - int i, n; - - domain = mono_domain_get (); - n = sizeof (invalid_path_chars) / sizeof (gunichar2); - MONO_HANDLE_ASSIGN (chars, mono_array_new_handle (domain, mono_defaults.char_class, n, error)); - return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, mono_new_null ())); - - for (i = 0; i < n; ++ i) - MONO_HANDLE_ARRAY_SETVAL (chars, gunichar2, i, invalid_path_chars [i]); - - return chars; -} - -void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position, - gint64 length, gint32 *error) -{ - *error=ERROR_SUCCESS; - mono_w32file_lock (handle, position, length, error); -} - -void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position, - gint64 length, gint32 *error) -{ - *error=ERROR_SUCCESS; - mono_w32file_unlock (handle, position, length, error); -} - - -#ifndef HOST_WIN32 -void mono_w32handle_dump (void); - -void ves_icall_System_IO_MonoIO_DumpHandles (void) -{ - mono_w32handle_dump (); -} -#endif /* !HOST_WIN32 */ - -#endif /* !ENABLE_NETCORE */ - -//Support for io-layer free mmap'd files. - -#if defined (TARGET_IOS) || defined (TARGET_ANDROID) - -gint64 -mono_filesize_from_path (MonoString *string) -{ - ERROR_DECL (error); - struct stat buf; - gint64 res; - char *path = mono_string_to_utf8_checked_internal (string, error); - mono_error_raise_exception_deprecated (error); /* OK to throw, external only without a good alternative */ - - gint stat_res; - MONO_ENTER_GC_SAFE; - stat_res = stat (path, &buf); - MONO_EXIT_GC_SAFE; - if (stat_res == -1) - res = -1; - else - res = (gint64)buf.st_size; - - g_free (path); - - return res; -} - -gint64 -mono_filesize_from_fd (int fd) -{ - struct stat buf; - int res; - - MONO_ENTER_GC_SAFE; - res = fstat (fd, &buf); - MONO_EXIT_GC_SAFE; - - if (res == -1) - return (gint64)-1; - - return (gint64)buf.st_size; -} - -#else - -MONO_EMPTY_SOURCE_FILE (w32file); - -#endif diff --git a/src/mono/mono/metadata/w32file.h b/src/mono/mono/metadata/w32file.h index e40eac1..c69554f 100644 --- a/src/mono/mono/metadata/w32file.h +++ b/src/mono/mono/metadata/w32file.h @@ -113,143 +113,6 @@ typedef struct _MonoFSAsyncResult { */ /* System.IO.MonoIO */ -#if !ENABLE_NETCORE - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_CreateDirectory (const gunichar2 *path, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_RemoveDirectory (const gunichar2 *path, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_FindCloseFile (gpointer hnd); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_SetCurrentDirectory (const gunichar2 *path, - gint32 *error); -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_MoveFile (const gunichar2 *path, const gunichar2 *dest, - gint32 *error); -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_CopyFile (const gunichar2 *path, const gunichar2 *dest, - MonoBoolean overwrite, gint32 *error); -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_DeleteFile (const gunichar2 *path, gint32 *error); - -ICALL_EXPORT -gint32 -ves_icall_System_IO_MonoIO_GetFileAttributes (const gunichar2 *path, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_SetFileAttributes (const gunichar2 *path, gint32 attrs, - gint32 *error); -ICALL_EXPORT -gint32 -ves_icall_System_IO_MonoIO_GetFileType (gpointer handle, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_GetFileStat (const gunichar2 *path, MonoIOStat *stat, - gint32 *error); -ICALL_EXPORT -gpointer -ves_icall_System_IO_MonoIO_Open (const gunichar2 *filename, gint32 mode, - gint32 access_mode, gint32 share, gint32 options, - gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_Cancel (gpointer handle, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_Close (gpointer handle, gint32 *error); - -ICALL_EXPORT -gint64 -ves_icall_System_IO_MonoIO_Seek (gpointer handle, gint64 offset, gint32 origin, - gint32 *error); -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_Flush (gpointer handle, gint32 *error); - -ICALL_EXPORT -gint64 -ves_icall_System_IO_MonoIO_GetLength (gpointer handle, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_SetLength (gpointer handle, gint64 length, - gint32 *error); -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_SetFileTime (gpointer handle, gint64 creation_time, - gint64 last_access_time, - gint64 last_write_time, gint32 *error); -ICALL_EXPORT -gpointer -ves_icall_System_IO_MonoIO_get_ConsoleOutput (void); - -ICALL_EXPORT -gpointer -ves_icall_System_IO_MonoIO_get_ConsoleInput (void); - -ICALL_EXPORT -gpointer -ves_icall_System_IO_MonoIO_get_ConsoleError (void); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_CreatePipe (gpointer *read_handle, gpointer *write_handle, gint32 *error); - -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_DuplicateHandle (gpointer source_process_handle, gpointer source_handle, - gpointer target_process_handle, gpointer *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error); - -ICALL_EXPORT -gunichar2 -ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void); - -ICALL_EXPORT -gunichar2 -ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void); - -ICALL_EXPORT -gunichar2 -ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void); - -ICALL_EXPORT -gunichar2 -ves_icall_System_IO_MonoIO_get_PathSeparator (void); - -ICALL_EXPORT -void ves_icall_System_IO_MonoIO_Lock (gpointer handle, gint64 position, - gint64 length, gint32 *error); - -ICALL_EXPORT -void ves_icall_System_IO_MonoIO_Unlock (gpointer handle, gint64 position, - gint64 length, gint32 *error); -ICALL_EXPORT -MonoBoolean -ves_icall_System_IO_MonoIO_ReplaceFile (const gunichar2 *source_file_name, const gunichar2 *destination_file_name, - const gunichar2 *destination_backup_file_name, MonoBoolean ignore_metadata_errors, - gint32 *error); - -ICALL_EXPORT -void -ves_icall_System_IO_MonoIO_DumpHandles (void); - -#endif /* !ENABLE_NETCORE */ - #if defined (TARGET_IOS) || defined (TARGET_ANDROID) MONO_API MONO_RT_EXTERNAL_ONLY gint64 diff --git a/src/mono/mono/metadata/w32process-unix.c b/src/mono/mono/metadata/w32process-unix.c index 663cc6f..884191f 100644 --- a/src/mono/mono/metadata/w32process-unix.c +++ b/src/mono/mono/metadata/w32process-unix.c @@ -91,3414 +91,6 @@ #include "object-internals.h" #include "icall-decl.h" -#if !defined(ENABLE_NETCORE) && !defined(DISABLE_PROCESSES) - -#ifndef MAXPATHLEN -#define MAXPATHLEN 242 -#endif - -#define STILL_ACTIVE ((int) 0x00000103) - -#define LOGDEBUG(...) -/* define LOGDEBUG(...) g_message(__VA_ARGS__) */ - -/* The process' environment strings */ -#if defined (HAVE_FORK) && defined (HAVE_EXECVE) -#if defined(__APPLE__) -#if defined (TARGET_OSX) -/* Apple defines this in crt_externs.h but doesn't provide that header for - * arm-apple-darwin9. We'll manually define the symbol on Apple as it does - * in fact exist on all implementations (so far) - */ -G_BEGIN_DECLS -gchar ***_NSGetEnviron(void); -G_END_DECLS -#define environ (*_NSGetEnviron()) -#else -static char *mono_environ[1] = { NULL }; -#define environ mono_environ -#endif /* defined (TARGET_OSX) */ -#else -G_BEGIN_DECLS -extern char **environ; -G_END_DECLS -#endif -#endif - -typedef enum { - STARTF_USESHOWWINDOW=0x001, - STARTF_USESIZE=0x002, - STARTF_USEPOSITION=0x004, - STARTF_USECOUNTCHARS=0x008, - STARTF_USEFILLATTRIBUTE=0x010, - STARTF_RUNFULLSCREEN=0x020, - STARTF_FORCEONFEEDBACK=0x040, - STARTF_FORCEOFFFEEDBACK=0x080, - STARTF_USESTDHANDLES=0x100 -} StartupFlags; - -typedef struct { - gpointer input; - gpointer output; - gpointer error; -} StartupHandles; - -typedef struct { -#if G_BYTE_ORDER == G_BIG_ENDIAN - guint32 highDateTime; - guint32 lowDateTime; -#else - guint32 lowDateTime; - guint32 highDateTime; -#endif -} ProcessTime; - -/* - * Process describes processes we create. - * It contains a semaphore that can be waited on in order to wait - * for process termination. - */ -typedef struct _Process { - pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */ - MonoCoopSem exit_sem; /* this semaphore will be released when the process exits */ - int status; /* the exit status */ - gint32 handle_count; /* the number of handles to this process instance */ - /* we keep a ref to the creating _WapiHandle_process handle until - * the process has exited, so that the information there isn't lost. - */ - gpointer handle; - gboolean signalled; - struct _Process *next; -} Process; - -/* MonoW32HandleProcess is a structure containing all the required information for process handling. */ -typedef struct { - pid_t pid; - gboolean child; - guint32 exitstatus; - gpointer main_thread; - guint64 create_time; - guint64 exit_time; - char *pname; - size_t min_working_set; - size_t max_working_set; - gboolean exited; - Process *process; -} MonoW32HandleProcess; - -/* - * VS_VERSIONINFO: - * - * 2 bytes: Length in bytes (this block, and all child blocks. does _not_ include alignment padding between blocks) - * 2 bytes: Length in bytes of VS_FIXEDFILEINFO struct - * 2 bytes: Type (contains 1 if version resource contains text data and 0 if version resource contains binary data) - * Variable length unicode string (null terminated): Key (currently "VS_VERSION_INFO") - * Variable length padding to align VS_FIXEDFILEINFO on a 32-bit boundary - * VS_FIXEDFILEINFO struct - * Variable length padding to align Child struct on a 32-bit boundary - * Child struct (zero or one StringFileInfo structs, zero or one VarFileInfo structs) - */ - -/* - * StringFileInfo: - * - * 2 bytes: Length in bytes (includes this block, as well as all Child blocks) - * 2 bytes: Value length (always zero) - * 2 bytes: Type (contains 1 if version resource contains text data and 0 if version resource contains binary data) - * Variable length unicode string: Key (currently "StringFileInfo") - * Variable length padding to align Child struct on a 32-bit boundary - * Child structs ( one or more StringTable structs. Each StringTable struct's Key member indicates the appropriate language and code page for displaying the text in that StringTable struct.) - */ - -/* - * StringTable: - * - * 2 bytes: Length in bytes (includes this block as well as all Child blocks, but excludes any padding between String blocks) - * 2 bytes: Value length (always zero) - * 2 bytes: Type (contains 1 if version resource contains text data and 0 if version resource contains binary data) - * Variable length unicode string: Key. An 8-digit hex number stored as a unicode string. The four most significant digits represent the language identifier. The four least significant digits represent the code page for which the data is formatted. - * Variable length padding to align Child struct on a 32-bit boundary - * Child structs (an array of one or more String structs (each aligned on a 32-bit boundary) - */ - -/* - * String: - * - * 2 bytes: Length in bytes (of this block) - * 2 bytes: Value length (the length in words of the Value member) - * 2 bytes: Type (contains 1 if version resource contains text data and 0 if version resource contains binary data) - * Variable length unicode string: Key. arbitrary string, identifies data. - * Variable length padding to align Value on a 32-bit boundary - * Value: Variable length unicode string, holding data. - */ - -/* - * VarFileInfo: - * - * 2 bytes: Length in bytes (includes this block, as well as all Child blocks) - * 2 bytes: Value length (always zero) - * 2 bytes: Type (contains 1 if version resource contains text data and 0 if version resource contains binary data) - * Variable length unicode string: Key (currently "VarFileInfo") - * Variable length padding to align Child struct on a 32-bit boundary - * Child structs (a Var struct) - */ - -/* - * Var: - * - * 2 bytes: Length in bytes of this block - * 2 bytes: Value length in bytes of the Value - * 2 bytes: Type (contains 1 if version resource contains text data and 0 if version resource contains binary data) - * Variable length unicode string: Key ("Translation") - * Variable length padding to align Value on a 32-bit boundary - * Value: an array of one or more 4 byte values that are language and code page identifier pairs, low-order word containing a language identifier, and the high-order word containing a code page number. Either word can be zero, indicating that the file is language or code page independent. - */ - -#if G_BYTE_ORDER == G_BIG_ENDIAN -#define VS_FFI_SIGNATURE 0xbd04effe -#define VS_FFI_STRUCVERSION 0x00000100 -#else -#define VS_FFI_SIGNATURE 0xfeef04bd -#define VS_FFI_STRUCVERSION 0x00010000 -#endif - -#define VOS_UNKNOWN 0x00000000 -#define VOS_DOS 0x00010000 -#define VOS_OS216 0x00020000 -#define VOS_OS232 0x00030000 -#define VOS_NT 0x00040000 -#define VOS__BASE 0x00000000 -#define VOS__WINDOWS16 0x00000001 -#define VOS__PM16 0x00000002 -#define VOS__PM32 0x00000003 -#define VOS__WINDOWS32 0x00000004 -/* Should "embrace and extend" here with some entries for linux etc */ - -#define VOS_DOS_WINDOWS16 0x00010001 -#define VOS_DOS_WINDOWS32 0x00010004 -#define VOS_OS216_PM16 0x00020002 -#define VOS_OS232_PM32 0x00030003 -#define VOS_NT_WINDOWS32 0x00040004 - -#define VFT_UNKNOWN 0x0000 -#define VFT_APP 0x0001 -#define VFT_DLL 0x0002 -#define VFT_DRV 0x0003 -#define VFT_FONT 0x0004 -#define VFT_VXD 0x0005 -#define VFT_STATIC_LIB 0x0007 - -#define VFT2_UNKNOWN 0x0000 -#define VFT2_DRV_PRINTER 0x0001 -#define VFT2_DRV_KEYBOARD 0x0002 -#define VFT2_DRV_LANGUAGE 0x0003 -#define VFT2_DRV_DISPLAY 0x0004 -#define VFT2_DRV_MOUSE 0x0005 -#define VFT2_DRV_NETWORK 0x0006 -#define VFT2_DRV_SYSTEM 0x0007 -#define VFT2_DRV_INSTALLABLE 0x0008 -#define VFT2_DRV_SOUND 0x0009 -#define VFT2_DRV_COMM 0x000a -#define VFT2_DRV_INPUTMETHOD 0x000b -#define VFT2_FONT_RASTER 0x0001 -#define VFT2_FONT_VECTOR 0x0002 -#define VFT2_FONT_TRUETYPE 0x0003 - -#define MAKELANGID(primary,secondary) ((guint16)((secondary << 10) | (primary))) - -#define ALIGN32(ptr) ptr = (gpointer)((char *)ptr + 3); ptr = (gpointer)((char *)ptr - ((gsize)ptr & 3)); - -#if HAVE_SIGACTION -static mono_lazy_init_t process_sig_chld_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED; -#endif - -static gchar *cli_launcher; - -static Process *processes; -static MonoCoopMutex processes_mutex; - -static pid_t current_pid; -static gpointer current_process; - -static const gunichar2 utf16_space [2] = { 0x20, 0 }; -static const gunichar2 utf16_quote [2] = { 0x22, 0 }; - -static MonoBoolean -mono_get_exit_code_process (gpointer handle, gint32 *exitcode); - -/* Check if a pid is valid - i.e. if a process exists with this pid. */ -static gboolean -process_is_alive (pid_t pid) -{ -#if defined(HOST_WATCHOS) - return TRUE; // TODO: Rewrite using sysctl -#elif defined(HOST_DARWIN) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(_AIX) - if (pid == 0) - return FALSE; - if (kill (pid, 0) == 0) - return TRUE; - if (errno == EPERM) - return TRUE; - return FALSE; -#elif defined(__HAIKU__) - team_info teamInfo; - if (get_team_info ((team_id)pid, &teamInfo) == B_OK) - return TRUE; - return FALSE; -#else - gchar *dir = g_strdup_printf ("/proc/%d", pid); - gboolean result = access (dir, F_OK) == 0; - g_free (dir); - return result; -#endif -} - -static void -process_details (MonoW32Handle *handle_data) -{ - MonoW32HandleProcess *process_handle = (MonoW32HandleProcess *) handle_data->specific; - g_print ("pid: %d, exited: %s, exitstatus: %d", - process_handle->pid, process_handle->exited ? "true" : "false", process_handle->exitstatus); -} - -static const gchar* -process_typename (void) -{ - return "Process"; -} - -static gsize -process_typesize (void) -{ - return sizeof (MonoW32HandleProcess); -} - -static MonoW32HandleWaitRet -process_wait (MonoW32Handle *handle_data, guint32 timeout, gboolean *alerted) -{ - MonoW32HandleProcess *process_handle; - pid_t pid G_GNUC_UNUSED, ret; - int status; - gint64 start, now; - Process *process; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT ")", __func__, handle_data, timeout); - - if (alerted) - *alerted = FALSE; - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - if (process_handle->exited) { - /* We've already done this one */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): Process already exited", __func__, handle_data, timeout); - return MONO_W32HANDLE_WAIT_RET_SUCCESS_0; - } - - pid = process_handle->pid; - - if (pid == mono_process_current_pid ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): waiting on current process", __func__, handle_data, timeout); - return MONO_W32HANDLE_WAIT_RET_TIMEOUT; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): PID: %d", __func__, handle_data, timeout, pid); - - if (!process_handle->child) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): waiting on non-child process", __func__, handle_data, timeout); - - if (!process_is_alive (pid)) { - /* assume the process has exited */ - process_handle->exited = TRUE; - process_handle->exitstatus = -1; - mono_w32handle_set_signal_state (handle_data, TRUE, TRUE); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): non-child process is not alive anymore (2)", __func__, handle_data, timeout); - return MONO_W32HANDLE_WAIT_RET_SUCCESS_0; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): non-child process wait failed, error : %s (%d))", __func__, handle_data, timeout, g_strerror (errno), errno); - return MONO_W32HANDLE_WAIT_RET_FAILED; - } - - /* We don't need to lock processes here, the entry - * has a handle_count > 0 which means it will not be freed. */ - process = process_handle->process; - g_assert (process); - - start = mono_msec_ticks (); - now = start; - - while (1) { - if (timeout != MONO_INFINITE_WAIT) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): waiting on semaphore for %" G_GINT64_FORMAT " ms...", - __func__, handle_data, timeout, timeout - (now - start)); - ret = mono_coop_sem_timedwait (&process->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE); - } else { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): waiting on semaphore forever...", - __func__, handle_data, timeout); - ret = mono_coop_sem_wait (&process->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE); - } - - if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) { - /* Success, process has exited */ - mono_coop_sem_post (&process->exit_sem); - break; - } - - if (ret == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): wait timeout (timeout = 0)", __func__, handle_data, timeout); - return MONO_W32HANDLE_WAIT_RET_TIMEOUT; - } - - now = mono_msec_ticks (); - if (now - start >= timeout) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): wait timeout", __func__, handle_data, timeout); - return MONO_W32HANDLE_WAIT_RET_TIMEOUT; - } - - if (alerted && ret == MONO_SEM_TIMEDWAIT_RET_ALERTED) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): wait alerted", __func__, handle_data, timeout); - *alerted = TRUE; - return MONO_W32HANDLE_WAIT_RET_ALERTED; - } - } - - /* Process must have exited */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): Waited successfully", __func__, handle_data, timeout); - - status = process->status; - if (WIFSIGNALED (status)) - process_handle->exitstatus = 128 + WTERMSIG (status); - else - process_handle->exitstatus = WEXITSTATUS (status); - - process_handle->exit_time = mono_100ns_datetime (); - - process_handle->exited = TRUE; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s (%p, %" G_GUINT32_FORMAT "): Setting pid %d signalled, exit status %d", - __func__, handle_data, timeout, process_handle->pid, process_handle->exitstatus); - - mono_w32handle_set_signal_state (handle_data, TRUE, TRUE); - - return MONO_W32HANDLE_WAIT_RET_SUCCESS_0; -} - -static void -processes_cleanup (void) -{ - static gint32 cleaning_up; - Process *process; - Process *prev = NULL; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s", __func__); - - /* Ensure we're not in here in multiple threads at once, nor recursive. */ - if (mono_atomic_cas_i32 (&cleaning_up, 1, 0) != 0) - return; - - /* - * This needs to be done outside the lock but atomically, hence the CAS above. - */ - for (process = processes; process; process = process->next) { - if (process->signalled && process->handle) { - /* This process has exited and we need to remove the artifical ref - * on the handle */ - mono_w32handle_close (process->handle); - process->handle = NULL; - } - } - - mono_coop_mutex_lock (&processes_mutex); - - for (process = processes; process;) { - Process *next = process->next; - if (process->handle_count == 0 && process->signalled) { - /* - * Unlink the entry. - */ - if (process == processes) - processes = process->next; - else - prev->next = process->next; - - mono_coop_sem_destroy (&process->exit_sem); - g_free (process); - } else { - prev = process; - } - process = next; - } - - mono_coop_mutex_unlock (&processes_mutex); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s done", __func__); - - mono_atomic_xchg_i32 (&cleaning_up, 0); -} - -static void -process_close (gpointer data) -{ - MonoW32HandleProcess *process_handle; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s", __func__); - - process_handle = (MonoW32HandleProcess *) data; - g_free (process_handle->pname); - process_handle->pname = NULL; - if (process_handle->process) - mono_atomic_dec_i32 (&process_handle->process->handle_count); - processes_cleanup (); -} - -static const MonoW32HandleOps process_ops = { - process_close, /* close_shared */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - process_wait, /* special_wait */ - NULL, /* prewait */ - process_details, /* details */ - process_typename, /* typename */ - process_typesize, /* typesize */ -}; - -static void -process_set_defaults (MonoW32HandleProcess *process_handle) -{ - /* These seem to be the defaults on w2k */ - process_handle->min_working_set = 204800; - process_handle->max_working_set = 1413120; - - process_handle->create_time = mono_100ns_datetime (); -} - -static void -process_set_name (MonoW32HandleProcess *process_handle) -{ - char *progname, *utf8_progname, *slash; - - progname = g_get_prgname (); - utf8_progname = mono_utf8_from_external (progname); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: using [%s] as prog name", __func__, progname); - - if (utf8_progname) { - slash = strrchr (utf8_progname, '/'); - if (slash) - process_handle->pname = g_strdup (slash+1); - else - process_handle->pname = g_strdup (utf8_progname); - g_free (utf8_progname); - } -} - -static mono_once_t init_state = MONO_ONCE_INIT; - -void -mono_w32process_init (void) -{ - MonoW32HandleProcess process_handle; - - mono_w32handle_register_ops (MONO_W32TYPE_PROCESS, &process_ops); - - mono_w32handle_register_capabilities (MONO_W32TYPE_PROCESS, - (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT)); - - current_pid = getpid (); - - memset (&process_handle, 0, sizeof (process_handle)); - process_handle.pid = current_pid; - process_set_defaults (&process_handle); - process_set_name (&process_handle); - - current_process = mono_w32handle_new (MONO_W32TYPE_PROCESS, &process_handle); - g_assert (current_process != INVALID_HANDLE_VALUE); - - mono_coop_mutex_init (&processes_mutex); - mono_once (&init_state, &mono_w32process_platform_init_once); -} - -void -mono_w32process_cleanup (void) -{ - g_free (cli_launcher); -} - -static int -len16 (const gunichar2 *str) -{ - int len = 0; - - while (*str++ != 0) - len++; - - return len; -} - -static gunichar2 * -utf16_concat (const gunichar2 *first, ...) -{ - va_list args; - int total = 0, i; - const gunichar2 *s; - const gunichar2 *p; - gunichar2 *ret; - - va_start (args, first); - total += len16 (first); - for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg(args, gunichar2 *)) - total += len16 (s); - va_end (args); - - ret = g_new (gunichar2, total + 1); - if (ret == NULL) - return NULL; - - ret [total] = 0; - i = 0; - for (s = first; *s != 0; s++) - ret [i++] = *s; - va_start (args, first); - for (s = va_arg (args, gunichar2 *); s != NULL; s = va_arg (args, gunichar2 *)){ - for (p = s; *p != 0; p++) - ret [i++] = *p; - } - va_end (args); - - return ret; -} - -guint32 -mono_w32process_get_pid (gpointer handle) -{ - MonoW32Handle *handle_data; - guint32 ret; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return 0; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return 0; - } - - ret = ((MonoW32HandleProcess*) handle_data->specific)->pid; - - mono_w32handle_unref (handle_data); - - return ret; -} - -typedef struct { - guint32 pid; - gpointer handle; -} GetProcessForeachData; - -static gboolean -get_process_foreach_callback (MonoW32Handle *handle_data, gpointer user_data) -{ - GetProcessForeachData *foreach_data; - MonoW32HandleProcess *process_handle; - pid_t pid; - - if (handle_data->type != MONO_W32TYPE_PROCESS) - return FALSE; - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: looking at process %d", __func__, process_handle->pid); - - pid = process_handle->pid; - if (pid == 0) - return FALSE; - - foreach_data = (GetProcessForeachData*) user_data; - - /* It's possible to have more than one process handle with the - * same pid, but only the one running process can be - * unsignalled. */ - if (foreach_data->pid != pid) - return FALSE; - if (mono_w32handle_issignalled (handle_data)) - return FALSE; - - foreach_data->handle = mono_w32handle_duplicate (handle_data); - return TRUE; -} - -HANDLE -ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid, MonoError *error) -{ - GetProcessForeachData foreach_data; - gpointer handle; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: looking for process %d", __func__, pid); - - memset (&foreach_data, 0, sizeof (foreach_data)); - foreach_data.pid = pid; - mono_w32handle_foreach (get_process_foreach_callback, &foreach_data); - handle = foreach_data.handle; - if (handle) { - /* get_process_foreach_callback already added a ref */ - return handle; - } - - if (process_is_alive (pid)) { - /* non-child process */ - MonoW32HandleProcess process_handle; - - memset (&process_handle, 0, sizeof (process_handle)); - process_handle.pid = pid; - process_handle.pname = mono_w32process_get_name (pid); - - handle = mono_w32handle_new (MONO_W32TYPE_PROCESS, &process_handle); - if (handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating process handle", __func__); - - mono_w32error_set_last (ERROR_OUTOFMEMORY); - return NULL; - } - - return handle; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't find pid %d", __func__, pid); - - mono_w32error_set_last (ERROR_PROC_NOT_FOUND); - return NULL; -} - -HANDLE -ves_icall_System_Diagnostics_Process_MainWindowHandle_internal (guint32 pid, MonoError *error) -{ - /*TODO: Implement for unix*/ - return NULL; -} - -static gboolean -match_procname_to_modulename (char *procname, char *modulename) -{ - char* lastsep = NULL; - char* lastsep2 = NULL; - char* pname = NULL; - char* mname = NULL; - gboolean result = FALSE; - - if (procname == NULL || modulename == NULL) - return (FALSE); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename); - pname = mono_path_resolve_symlinks (procname); - mname = mono_path_resolve_symlinks (modulename); - - if (!strcmp (pname, mname)) - result = TRUE; - - if (!result) { - lastsep = strrchr (mname, '/'); - if (lastsep) - if (!strcmp (lastsep+1, pname)) - result = TRUE; - if (!result) { - lastsep2 = strrchr (pname, '/'); - if (lastsep2){ - if (lastsep) { - if (!strcmp (lastsep+1, lastsep2+1)) - result = TRUE; - } else { - if (!strcmp (mname, lastsep2+1)) - result = TRUE; - } - } - } - } - - g_free (pname); - g_free (mname); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: result is %" G_GINT32_FORMAT, __func__, result); - return result; -} - -gboolean -mono_w32process_try_get_modules (gpointer handle, gpointer *modules, guint32 size, guint32 *needed) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - GSList *mods = NULL, *mods_iter; - MonoW32ProcessModule *module; - guint32 count, avail = size / sizeof(gpointer); - int i; - pid_t pid; - char *pname = NULL; - - /* Store modules in an array of pointers (main module as - * modules[0]), using the load address for each module as a - * token. (Use 'NULL' as an alternative for the main module - * so that the simple implementation can just return one item - * for now.) Get the info from /proc//maps on linux, - * /proc//map on FreeBSD, other systems will have to - * implement /dev/kmem reading or whatever other horrid - * technique is needed. - */ - if (size < sizeof(gpointer)) - return FALSE; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - pid = process_handle->pid; - pname = g_strdup (process_handle->pname); - - if (!pname) { - modules[0] = NULL; - *needed = sizeof(gpointer); - mono_w32handle_unref (handle_data); - return TRUE; - } - - mods = mono_w32process_get_modules (pid); - if (!mods) { - modules[0] = NULL; - *needed = sizeof(gpointer); - g_free (pname); - mono_w32handle_unref (handle_data); - return TRUE; - } - - count = 0; - - /* - * Use the NULL shortcut, as the first line in - * /proc//maps isn't the executable, and we need - * that first in the returned list. Check the module name - * to see if it ends with the proc name and substitute - * the first entry with it. FIXME if this turns out to - * be a problem. - */ - modules[0] = NULL; - mods_iter = mods; - for (i = 0; mods_iter; i++) { - if (i < avail - 1) { - module = (MonoW32ProcessModule *)mods_iter->data; - if (modules[0] != NULL) - modules[i] = module->address_start; - else if (match_procname_to_modulename (pname, module->filename)) - modules[0] = module->address_start; - else - modules[i + 1] = module->address_start; - } - mono_w32process_module_free ((MonoW32ProcessModule *)mods_iter->data); - mods_iter = g_slist_next (mods_iter); - count++; - } - - /* count + 1 to leave slot 0 for the main module */ - *needed = sizeof(gpointer) * (count + 1); - - g_slist_free (mods); - g_free (pname); - mono_w32handle_unref (handle_data); - return TRUE; -} - -gboolean -mono_w32process_module_get_filename (gpointer handle, gpointer module, gunichar2 **str, guint32 *len) -{ - gint pid; - gsize bytes = 0; - gchar *path; - gunichar2 *proc_path; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Getting module file name, process handle %p module %p " G_GUINT32_FORMAT, - __func__, handle, module); - - if (str == NULL || len == NULL) - return FALSE; - - *str = NULL; - *len = 0; - - pid = mono_w32process_get_pid (handle); - if (pid == 0) - return FALSE; - - path = mono_w32process_get_path (pid); - if (path == NULL) - return FALSE; - - proc_path = mono_unicode_from_external (path, &bytes); - - if (proc_path == NULL) { - g_free (path); - return FALSE; - } - - *str = mono_unicode_from_external (path, &bytes); - *len = bytes / sizeof (gunichar2); - - g_free (path); - return TRUE; -} - -gboolean -mono_w32process_module_get_name (gpointer handle, gpointer module, gunichar2 **str, guint32 *len) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - pid_t pid; - gunichar2 *procname; - char *procname_ext = NULL; - gsize bytes = 0; - GSList *mods = NULL, *mods_iter; - MonoW32ProcessModule *found_module; - char *pname = NULL; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Getting module base name, process handle %p module %p " G_GUINT32_FORMAT, - __func__, handle, module); - - if (str == NULL || len == NULL) - return FALSE; - - *str = NULL; - *len = 0; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - pid = process_handle->pid; - pname = g_strdup (process_handle->pname); - - mods = mono_w32process_get_modules (pid); - if (!mods && module != NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't get modules %p", __func__, handle); - g_free (pname); - mono_w32handle_unref (handle_data); - return FALSE; - } - - /* If module != NULL compare the address. - * If module == NULL we are looking for the main module. - * The best we can do for now check it the module name end with the process name. - */ - for (mods_iter = mods; mods_iter; mods_iter = g_slist_next (mods_iter)) { - found_module = (MonoW32ProcessModule *)mods_iter->data; - if (procname_ext == NULL && - ((module == NULL && match_procname_to_modulename (pname, found_module->filename)) || - (module != NULL && found_module->address_start == module))) { - procname_ext = g_path_get_basename (found_module->filename); - } - - mono_w32process_module_free (found_module); - } - - if (procname_ext == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't find procname_ext from procmods %p", __func__, handle); - /* If it's *still* null, we might have hit the - * case where reading /proc/$pid/maps gives an - * empty file for this user. - */ - procname_ext = mono_w32process_get_name (pid); - if (!procname_ext) - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't find procname_ext from proc_get_name %p pid %d", __func__, handle, pid); - } - - g_slist_free (mods); - g_free (pname); - - if (procname_ext) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Process name is [%s]", __func__, - procname_ext); - - procname = mono_unicode_from_external (procname_ext, &bytes); - if (procname == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't get procname %p", __func__, handle); - g_free (procname_ext); - mono_w32handle_unref (handle_data); - return FALSE; - } - - *str = procname; - *len = bytes / sizeof (gunichar2); - - g_free (procname_ext); - mono_w32handle_unref (handle_data); - return TRUE; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't find procname_ext %p", __func__, handle); - mono_w32handle_unref (handle_data); - return FALSE; -} - -gboolean -mono_w32process_module_get_information (gpointer handle, gpointer module, gpointer modinfo, guint32 size) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - pid_t pid; - GSList *mods = NULL, *mods_iter; - MonoW32ProcessModule *found_module; - gboolean ret = FALSE; - char *pname = NULL; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Getting module info, process handle %p module %p", - __func__, handle, module); - - if (modinfo == NULL || size < sizeof (MODULEINFO)) - return FALSE; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - pid = process_handle->pid; - pname = g_strdup (process_handle->pname); - - mods = mono_w32process_get_modules (pid); - if (!mods) { - g_free (pname); - mono_w32handle_unref (handle_data); - return FALSE; - } - - /* If module != NULL compare the address. - * If module == NULL we are looking for the main module. - * The best we can do for now check it the module name end with the process name. - */ - for (mods_iter = mods; mods_iter; mods_iter = g_slist_next (mods_iter)) { - found_module = (MonoW32ProcessModule *)mods_iter->data; - if (ret == FALSE && - ((module == NULL && match_procname_to_modulename (pname, found_module->filename)) || - (module != NULL && found_module->address_start == module))) { - ((MODULEINFO *)modinfo)->lpBaseOfDll = found_module->address_start; - ((MODULEINFO *)modinfo)->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start); - ((MODULEINFO *)modinfo)->EntryPoint = found_module->address_offset; - ret = TRUE; - } - - mono_w32process_module_free (found_module); - } - - g_slist_free (mods); - g_free (pname); - mono_w32handle_unref (handle_data); - return ret; -} - -#if HAVE_SIGACTION - -MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context)) -{ - /* - * Don't want to do any complicated processing here so just wake up the finalizer thread which will call - * mono_w32process_signal_finished (). - */ - int old_errno = errno; - - mono_gc_finalize_notify (); - - mono_set_errno (old_errno); -} - -static void -process_add_sigchld_handler (void) -{ - struct sigaction sa; - - sa.sa_sigaction = mono_sigchld_signal_handler; - sigemptyset (&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO | SA_RESTART; - g_assert (sigaction (SIGCHLD, &sa, NULL) != -1); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "Added SIGCHLD handler"); -} - -#endif - -/* - * mono_w32process_signal_finished: - * - * Signal the exit semaphore for processes which have finished. - */ -void -mono_w32process_signal_finished (void) -{ - mono_coop_mutex_lock (&processes_mutex); - - for (Process* process = processes; process; process = process->next) { - int status = -1; - int pid; - - do { - pid = waitpid (process->pid, &status, WNOHANG); - } while (pid == -1 && errno == EINTR); - - // possible values of 'pid': - // process->pid : the status changed for this child - // 0 : status unchanged for this PID - // ECHILD : process has been reaped elsewhere (or never existed) - // EINVAL : invalid PID or other argument - - // Therefore, we ignore status unchanged (nothing to do) and error - // events (process is cleaned up later). - if (pid <= 0) - continue; - if (process->signalled) - continue; - - process->signalled = TRUE; - process->status = status; - mono_coop_sem_post (&process->exit_sem); - } - - mono_coop_mutex_unlock (&processes_mutex); -} - -#if defined (HAVE_FORK) && defined (HAVE_EXECVE) -static void -switch_dir_separators (char *path) -{ - size_t i, pathLength = strlen (path); - - /* Turn all the slashes round the right way, except for \' */ - /* There are probably other characters that need to be excluded as well. */ - for (i = 0; i < pathLength; i++) { - if (path[i] == '\\' && i < pathLength - 1 && path[i + 1] != '\'') - path[i] = '/'; - } -} - -static gboolean -is_readable_or_executable (const char *prog) -{ - struct stat buf; - int a = access (prog, R_OK); - int b = access (prog, X_OK); - if (a != 0 && b != 0) - return FALSE; - if (stat (prog, &buf)) - return FALSE; - if (S_ISREG (buf.st_mode)) - return TRUE; - return FALSE; -} - -static gboolean -is_executable (const char *prog) -{ - struct stat buf; - if (access (prog, X_OK) != 0) - return FALSE; - if (stat (prog, &buf)) - return FALSE; - if (S_ISREG (buf.st_mode)) - return TRUE; - return FALSE; -} - -static gboolean -is_managed_binary (const char *filename) -{ - int original_errno = errno; -#if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE) - int file = open (filename, O_RDONLY | O_LARGEFILE); -#else - int file = open (filename, O_RDONLY); -#endif - off_t new_offset; - unsigned char buffer[8]; - off_t file_size, optional_header_offset; - off_t pe_header_offset, clr_header_offset; - gboolean managed = FALSE; - int num_read; - guint32 first_word, second_word, magic_number; - - /* If we are unable to open the file, then we definitely - * can't say that it is managed. The child mono process - * probably wouldn't be able to open it anyway. - */ - if (file < 0) { - mono_set_errno (original_errno); - return FALSE; - } - - /* Retrieve the length of the file for future sanity checks. */ - file_size = lseek (file, 0, SEEK_END); - lseek (file, 0, SEEK_SET); - - /* We know we need to read a header field at offset 60. */ - if (file_size < 64) - goto leave; - - num_read = read (file, buffer, 2); - - if ((num_read != 2) || (buffer[0] != 'M') || (buffer[1] != 'Z')) - goto leave; - - new_offset = lseek (file, 60, SEEK_SET); - - if (new_offset != 60) - goto leave; - - num_read = read (file, buffer, 4); - - if (num_read != 4) - goto leave; - pe_header_offset = buffer[0] - | (buffer[1] << 8) - | (buffer[2] << 16) - | (buffer[3] << 24); - - if (pe_header_offset + 24 > file_size) - goto leave; - - new_offset = lseek (file, pe_header_offset, SEEK_SET); - - if (new_offset != pe_header_offset) - goto leave; - - num_read = read (file, buffer, 4); - - if ((num_read != 4) || (buffer[0] != 'P') || (buffer[1] != 'E') || (buffer[2] != 0) || (buffer[3] != 0)) - goto leave; - - /* - * Verify that the header we want in the optional header data - * is present in this binary. - */ - new_offset = lseek (file, pe_header_offset + 20, SEEK_SET); - - if (new_offset != pe_header_offset + 20) - goto leave; - - num_read = read (file, buffer, 2); - - if ((num_read != 2) || ((buffer[0] | (buffer[1] << 8)) < 216)) - goto leave; - - optional_header_offset = pe_header_offset + 24; - - /* Read the PE magic number */ - new_offset = lseek (file, optional_header_offset, SEEK_SET); - - if (new_offset != optional_header_offset) - goto leave; - - num_read = read (file, buffer, 2); - - if (num_read != 2) - goto leave; - - magic_number = (buffer[0] | (buffer[1] << 8)); - - if (magic_number == 0x10B) // PE32 - clr_header_offset = 208; - else if (magic_number == 0x20B) // PE32+ - clr_header_offset = 224; - else - goto leave; - - /* Read the CLR header address and size fields. These will be - * zero if the binary is not managed. - */ - new_offset = lseek (file, optional_header_offset + clr_header_offset, SEEK_SET); - - if (new_offset != optional_header_offset + clr_header_offset) - goto leave; - - num_read = read (file, buffer, 8); - - /* We are not concerned with endianness, only with - * whether it is zero or not. - */ - first_word = *(guint32 *)&buffer[0]; - second_word = *(guint32 *)&buffer[4]; - - if ((num_read != 8) || (first_word == 0) || (second_word == 0)) - goto leave; - - managed = TRUE; - -leave: - close (file); - mono_set_errno (original_errno); - return managed; -} - -/** - * Gets the biggest numbered file descriptor for the current process; failing - * that, the system's file descriptor limit. This is called by the fork child - * in close_my_fds. - */ -static guint32 -max_fd_count (void) -{ -#if defined (_AIX) - struct procentry64 pe; - pid_t p; - p = getpid (); - if (getprocs64 (&pe, sizeof (pe), NULL, 0, &p, 1) != -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, - "%s: maximum returned fd in child is %u", - __func__, pe.pi_maxofile); - return pe.pi_maxofile; // biggest + 1 - } -#endif - // fallback to user/system limit if unsupported/error - return eg_getdtablesize (); -} - -/** - * Closes all of the process' opened file descriptors, applying a strategy - * appropriate for the target system. This is called by the fork child in - * process_create. - */ -static void -close_my_fds (void) -{ -// TODO: Other platforms. -// * On macOS, use proc_pidinfo + PROC_PIDLISTFDS? See: -// http://blog.palominolabs.com/2012/06/19/getting-the-files-being-used-by-a-process-on-mac-os-x/ -// (I have no idea how this plays out on i/watch/tvOS.) -// * On the other BSDs, there's likely a sysctl for this. -// * On Solaris, there exists posix_spawn_file_actions_addclosefrom_np, -// but that assumes we're using posix_spawn; we aren't, as we do some -// complex stuff between fork and exec. There's likely a way to get -// the FD list/count though (maybe look at addclosefrom source in -// illumos?) or just walk /proc/pid/fd like Linux? -#if defined (__linux__) - /* Walk the file descriptors in /proc/self/fd/. Linux has no other API, - * as far as I'm aware. Opening a directory won't create an FD. */ - struct dirent *dp; - DIR *d; - int fd; - d = opendir ("/proc/self/fd/"); - if (d) { - while ((dp = readdir (d)) != NULL) { - if (dp->d_name [0] == '.') - continue; - fd = atoi (dp->d_name); - if (fd > 2) - close (fd); - } - closedir (d); - return; - } else { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, - "%s: opening fd dir failed, using fallback", - __func__); - } -#elif defined (__FreeBSD__) - /* FreeBSD lets us get a list of FDs. There's a MIB to access them - * directly, but it uses a lot of nasty variable length structures. The - * system library libutil provides a nicer way to get a fixed length - * version instead. */ - struct kinfo_file *kif; - int count, i; - /* this is malloced but we won't need to free once we exec/exit */ - kif = kinfo_getfile (getpid (), &count); - if (kif) { - for (i = 0; i < count; i++) { - /* negative FDs look to be used by the OS */ - if (kif [i].kf_fd > 2) /* no neg + no stdio */ - close (kif [i].kf_fd); - } - return; - } else { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, - "%s: kinfo_getfile failed, using fallback", - __func__); - } -#elif defined (_AIX) - struct procentry64 pe; - /* this array struct is 1 MB, we're NOT putting it on the stack. - * likewise no need to free; getprocs will fail if we use the smalller - * versions if we have a lot of FDs (is it worth it?) - */ - struct fdsinfo_100K *fds; - pid_t p; - p = getpid (); - fds = (struct fdsinfo_100K *) g_malloc0 (sizeof (struct fdsinfo_100K)); - if (!fds) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, - "%s: fdsinfo alloc failed, using fallback", - __func__); - goto fallback; - } - - if (getprocs64 (&pe, sizeof (pe), fds, sizeof (struct fdsinfo_100K), &p, 1) != -1) { - for (int i = 3; i < pe.pi_maxofile; i++) { - if (fds->pi_ufd [i].fp != 0) - close (fds->pi_ufd [i].fp); - } - return; - } else { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, - "%s: getprocs64 failed, using fallback", - __func__); - } -fallback: -#endif - /* Fallback: Close FDs blindly, according to an FD limit */ - for (guint32 i = max_fd_count () - 1; i > 2; i--) - close (i); -} -#endif - -static gboolean -process_create (const gunichar2 *appname, const gunichar2 *cmdline, - const gunichar2 *cwd, StartupHandles *startup_handles, MonoW32ProcessInfo *process_info) -{ -#if defined (HAVE_FORK) && defined (HAVE_EXECVE) - char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL; - char *dir = NULL, **env_strings = NULL, **argv = NULL; - guint32 i; - gboolean ret = FALSE; - gpointer handle = NULL; - GError *gerr = NULL; - int in_fd, out_fd, err_fd; - pid_t pid = 0; - int startup_pipe [2] = {-1, -1}; - int dummy; - Process *process; - ERROR_DECL (error); - -#if HAVE_SIGACTION - mono_lazy_initialize (&process_sig_chld_once, process_add_sigchld_handler); -#endif - - /* appname and cmdline specify the executable and its args: - * - * If appname is not NULL, it is the name of the executable. - * Otherwise the executable is the first token in cmdline. - * - * Executable searching: - * - * If appname is not NULL, it can specify the full path and - * file name, or else a partial name and the current directory - * will be used. There is no additional searching. - * - * If appname is NULL, the first whitespace-delimited token in - * cmdline is used. If the name does not contain a full - * directory path, the search sequence is: - * - * 1) The directory containing the current process - * 2) The current working directory - * 3) The windows system directory (Ignored) - * 4) The windows directory (Ignored) - * 5) $PATH - * - * Just to make things more interesting, tokens can contain - * white space if they are surrounded by quotation marks. - */ - if (appname != NULL) { - cmd = mono_unicode_to_external_checked (appname, error); - if (cmd == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unicode conversion returned NULL; %s", - __func__, mono_error_get_message (error)); - - mono_error_cleanup (error); - mono_w32error_set_last (ERROR_PATH_NOT_FOUND); - goto free_strings; - } - - switch_dir_separators(cmd); - } - - if (cmdline != NULL) { - args = mono_unicode_to_external_checked (cmdline, error); - if (args == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unicode conversion returned NULL; %s", __func__, mono_error_get_message (error)); - - mono_error_cleanup (error); - mono_w32error_set_last (ERROR_PATH_NOT_FOUND); - goto free_strings; - } - } - - if (cwd != NULL) { - dir = mono_unicode_to_external_checked (cwd, error); - if (dir == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unicode conversion returned NULL; %s", __func__, mono_error_get_message (error)); - - mono_error_cleanup (error); - mono_w32error_set_last (ERROR_PATH_NOT_FOUND); - goto free_strings; - } - - /* Turn all the slashes round the right way */ - switch_dir_separators(dir); - } - - - /* We can't put off locating the executable any longer :-( */ - if (cmd != NULL) { - char *unquoted; - if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) { - /* Strip off the drive letter. I can't - * believe that CP/M holdover is still - * visible... - */ - g_memmove (cmd, cmd+2, strlen (cmd)-2); - cmd[strlen (cmd)-2] = '\0'; - } - - unquoted = g_shell_unquote (cmd, NULL); - if (unquoted[0] == '/') { - /* Assume full path given */ - prog = g_strdup (unquoted); - - /* Executable existing ? */ - if (!is_readable_or_executable (prog)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Couldn't find executable %s", - __func__, prog); - g_free (unquoted); - mono_w32error_set_last (ERROR_FILE_NOT_FOUND); - goto free_strings; - } - } else { - /* Search for file named by cmd in the current - * directory - */ - char *curdir = g_get_current_dir (); - - prog = g_strdup_printf ("%s/%s", curdir, unquoted); - g_free (curdir); - - /* And make sure it's readable */ - if (!is_readable_or_executable (prog)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Couldn't find executable %s", - __func__, prog); - g_free (unquoted); - mono_w32error_set_last (ERROR_FILE_NOT_FOUND); - goto free_strings; - } - } - g_free (unquoted); - - args_after_prog = args; - } else { - char *token = NULL; - char quote; - - /* Dig out the first token from args, taking quotation - * marks into account - */ - - /* First, strip off all leading whitespace */ - args = g_strchug (args); - - /* args_after_prog points to the contents of args - * after token has been set (otherwise argv[0] is - * duplicated) - */ - args_after_prog = args; - - /* Assume the opening quote will always be the first - * character - */ - if (args[0] == '\"' || args [0] == '\'') { - quote = args [0]; - for (i = 1; args[i] != '\0' && args[i] != quote; i++); - if (args [i + 1] == '\0' || g_ascii_isspace (args[i+1])) { - /* We found the first token */ - token = g_strndup (args+1, i-1); - args_after_prog = g_strchug (args + i + 1); - } else { - /* Quotation mark appeared in the - * middle of the token. Just give the - * whole first token, quotes and all, - * to exec. - */ - } - } - - if (token == NULL) { - /* No quote mark, or malformed */ - for (i = 0; args[i] != '\0'; i++) { - if (g_ascii_isspace (args[i])) { - token = g_strndup (args, i); - args_after_prog = args + i + 1; - break; - } - } - } - - if (token == NULL && args[0] != '\0') { - /* Must be just one token in the string */ - token = g_strdup (args); - args_after_prog = NULL; - } - - if (token == NULL) { - /* Give up */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Couldn't find what to exec", __func__); - - mono_w32error_set_last (ERROR_PATH_NOT_FOUND); - goto free_strings; - } - - /* Turn all the slashes round the right way. Only for - * the prg. name - */ - switch_dir_separators(token); - - if (g_ascii_isalpha (token[0]) && (token[1] == ':')) { - /* Strip off the drive letter. I can't - * believe that CP/M holdover is still - * visible... - */ - g_memmove (token, token+2, strlen (token)-2); - token[strlen (token)-2] = '\0'; - } - - if (token[0] == '/') { - /* Assume full path given */ - prog = g_strdup (token); - - /* Executable existing ? */ - if (!is_readable_or_executable (prog)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Couldn't find executable %s", - __func__, token); - g_free (token); - mono_w32error_set_last (ERROR_FILE_NOT_FOUND); - goto free_strings; - } - } else { - char *curdir = g_get_current_dir (); - - /* FIXME: Need to record the directory - * containing the current process, and check - * that for the new executable as the first - * place to look - */ - - prog = g_strdup_printf ("%s/%s", curdir, token); - g_free (curdir); - - /* I assume X_OK is the criterion to use, - * rather than F_OK - * - * X_OK is too strict *if* the target is a CLR binary - */ - if (!is_readable_or_executable (prog)) { - g_free (prog); - prog = g_find_program_in_path (token); - if (prog == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Couldn't find executable %s", __func__, token); - - g_free (token); - mono_w32error_set_last (ERROR_FILE_NOT_FOUND); - goto free_strings; - } - } - } - - g_free (token); - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Exec prog [%s] args [%s]", - __func__, prog, args_after_prog); - - /* Check for CLR binaries; if found, we will try to invoke - * them using the same mono binary that started us. - */ - if (is_managed_binary (prog)) { - gunichar2 *newapp, *newcmd; - gsize bytes_ignored; - - newapp = mono_unicode_from_external (cli_launcher ? cli_launcher : "mono", &bytes_ignored); - if (newapp) { - if (appname) - newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space, appname, utf16_space, cmdline, (const gunichar2 *)NULL); - else - newcmd = utf16_concat (utf16_quote, newapp, utf16_quote, utf16_space, cmdline, (const gunichar2 *)NULL); - - g_free (newapp); - - if (newcmd) { - ret = process_create (NULL, newcmd, cwd, startup_handles, process_info); - - g_free (newcmd); - - goto free_strings; - } - } - } else { - if (!is_executable (prog)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Executable permisson not set on %s", __func__, prog); - mono_w32error_set_last (ERROR_ACCESS_DENIED); - goto free_strings; - } - } - - if (args_after_prog != NULL && *args_after_prog) { - char *qprog; - - qprog = g_shell_quote (prog); - full_prog = g_strconcat (qprog, " ", args_after_prog, (const char*)NULL); - g_free (qprog); - } else { - full_prog = g_shell_quote (prog); - } - - ret = g_shell_parse_argv (full_prog, NULL, &argv, &gerr); - if (ret == FALSE) { - g_message ("process_create: %s\n", gerr->message); - g_error_free (gerr); - gerr = NULL; - goto free_strings; - } - - if (startup_handles) { - in_fd = GPOINTER_TO_UINT (startup_handles->input); - out_fd = GPOINTER_TO_UINT (startup_handles->output); - err_fd = GPOINTER_TO_UINT (startup_handles->error); - } else { - in_fd = GPOINTER_TO_UINT (mono_w32file_get_console_input ()); - out_fd = GPOINTER_TO_UINT (mono_w32file_get_console_output ()); - err_fd = GPOINTER_TO_UINT (mono_w32file_get_console_error ()); - } - - /* - * process->env_variables is a an array of MonoString* - * - * If new_environ is not NULL it specifies the entire set of - * environment variables in the new process. Otherwise the - * new process inherits the same environment. - */ - if (process_info->env_variables) { - MonoArrayHandle array = MONO_HANDLE_NEW (MonoArray, process_info->env_variables); - MonoStringHandle var = MONO_HANDLE_NEW (MonoString, NULL); - gsize const array_length = mono_array_handle_length (array); - - /* +2: one for the process handle value, and the last one is NULL */ - // What "process handle value"? - env_strings = g_new0 (gchar*, array_length + 2); - - /* Copy each environ string into 'strings' turning it into utf8 (or the requested encoding) at the same time */ - for (gsize i = 0; i < array_length; ++i) { - MONO_HANDLE_ARRAY_GETREF (var, array, i); - MonoGCHandle gchandle = NULL; - env_strings [i] = mono_unicode_to_external (mono_string_handle_pin_chars (var, &gchandle)); - mono_gchandle_free_internal (gchandle); - } - } else { - gsize env_count = 0; - for (i = 0; environ[i] != NULL; i++) - env_count++; - - /* +2: one for the process handle value, and the last one is NULL */ - // What "process handle value"? - env_strings = g_new0 (gchar*, env_count + 2); - - /* Copy each environ string into 'strings' turning it into utf8 (or the requested encoding) at the same time */ - for (i = 0; i < env_count; i++) - env_strings [i] = g_strdup (environ[i]); - } - - /* Create a pipe to make sure the child doesn't exit before - * we can add the process to the linked list of processes */ - if (pipe (startup_pipe) == -1) { - /* Could not create the pipe to synchroniz process startup. We'll just not synchronize. - * This is just for a very hard to hit race condition in the first place */ - startup_pipe [0] = startup_pipe [1] = -1; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__); - } - - switch (pid = fork ()) { - case -1: /* Error */ { - mono_w32error_set_last (ERROR_OUTOFMEMORY); - ret = FALSE; - break; - } - case 0: /* Child */ { - if (startup_pipe [0] != -1) { - /* Wait until the parent has updated it's internal data */ - ssize_t _i G_GNUC_UNUSED = read (startup_pipe [0], &dummy, 1); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: child: parent has completed its setup", __func__); - close (startup_pipe [0]); - close (startup_pipe [1]); - } - - /* should we detach from the process group? */ - - /* Connect stdin, stdout and stderr */ - dup2 (in_fd, 0); - dup2 (out_fd, 1); - dup2 (err_fd, 2); - - /* Close this child's file handles. */ - close_my_fds (); - -#ifdef DEBUG_ENABLED - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: exec()ing [%s] in dir [%s]", __func__, cmd, - dir == NULL?".":dir); - for (i = 0; argv[i] != NULL; i++) - g_message ("arg %" G_GUINT32_FORMAT ": [%s]", i, argv[i]); - - for (i = 0; env_strings[i] != NULL; i++) - g_message ("env %" G_GUINT32_FORMAT ": [%s]", i, env_strings[i]); -#endif - - /* set cwd */ - if (dir != NULL && chdir (dir) == -1) { - /* set error */ - _exit (-1); - } - - /* exec */ - execve (argv[0], argv, env_strings); - - /* set error */ - _exit (-1); - - break; - } - default: /* Parent */ { - MonoW32Handle *handle_data; - MonoW32HandleProcess process_handle; - - memset (&process_handle, 0, sizeof (process_handle)); - process_handle.pid = pid; - process_handle.child = TRUE; - process_handle.pname = g_strdup (prog); - process_set_defaults (&process_handle); - - /* Add our process into the linked list of processes */ - process = (Process *) g_malloc0 (sizeof (Process)); - process->pid = pid; - process->handle_count = 1; - mono_coop_sem_init (&process->exit_sem, 0); - - process_handle.process = process; - - handle = mono_w32handle_new (MONO_W32TYPE_PROCESS, &process_handle); - if (handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating process handle", __func__); - - mono_coop_sem_destroy (&process->exit_sem); - g_free (process); - - mono_w32error_set_last (ERROR_OUTOFMEMORY); - ret = FALSE; - break; - } - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) - g_error ("%s: unknown handle %p", __func__, handle); - - if (handle_data->type != MONO_W32TYPE_PROCESS) - g_error ("%s: unknown process handle %p", __func__, handle); - - /* Keep the process handle artificially alive until the process - * exits so that the information in the handle isn't lost. */ - process->handle = mono_w32handle_duplicate (handle_data); - - mono_coop_mutex_lock (&processes_mutex); - process->next = processes; - mono_memory_barrier (); - processes = process; - mono_coop_mutex_unlock (&processes_mutex); - - if (process_info != NULL) { - process_info->process_handle = handle; - process_info->pid = pid; - } - - mono_w32handle_unref (handle_data); - - break; - } - } - - if (startup_pipe [1] != -1) { - /* Write 1 byte, doesn't matter what */ - ssize_t _i G_GNUC_UNUSED = write (startup_pipe [1], startup_pipe, 1); - close (startup_pipe [0]); - close (startup_pipe [1]); - } - -free_strings: - g_free (cmd); - g_free (full_prog); - g_free (prog); - g_free (args); - g_free (dir); - g_strfreev (env_strings); - g_strfreev (argv); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: returning handle %p for pid %d", __func__, handle, pid); - - /* Check if something needs to be cleaned up. */ - processes_cleanup (); - - return ret; -#else - mono_w32error_set_last (ERROR_NOT_SUPPORTED); - return FALSE; -#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE) -} - -MonoBoolean -ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfoHandle proc_start_info, MonoW32ProcessInfo *process_info, MonoError *error) -{ - MonoCreateProcessCoop coop; - mono_createprocess_coop_init (&coop, proc_start_info, process_info); - - gboolean ret; - gboolean handler_needswait = FALSE; - - if (!coop.filename) { - /* w2k returns TRUE for this, for some reason. */ - ret = TRUE; - goto done; - } - - const gunichar2 *lpFile; - lpFile = coop.filename; - const gunichar2 *lpParameters; - lpParameters = coop.arguments; - const gunichar2 *lpDirectory; - lpDirectory = coop.length.working_directory ? coop.working_directory : NULL; - - /* Put both executable and parameters into the second argument - * to process_create (), so it searches $PATH. The conversion - * into and back out of utf8 is because there is no - * g_strdup_printf () equivalent for gunichar2 :-( - */ - gunichar2 *args; - args = utf16_concat (utf16_quote, lpFile, utf16_quote, lpParameters ? utf16_space : NULL, lpParameters, (const gunichar2 *)NULL); - if (args == NULL) { - mono_w32error_set_last (ERROR_INVALID_DATA); - ret = FALSE; - goto done; - } - ret = process_create (NULL, args, lpDirectory, NULL, process_info); - g_free (args); - - if (!ret && mono_w32error_get_last () == ERROR_OUTOFMEMORY) - goto done; - - if (!ret) { - -#if defined(TARGET_IOS) || defined(TARGET_ANDROID) - // don't try the "open" handlers on iOS/Android, they don't exist there anyway - goto done; -#endif - - static char *handler; - static gunichar2 *handler_utf16; - - if (handler_utf16 == (gunichar2 *)-1) { - ret = FALSE; - goto done; - } - -#ifdef HOST_DARWIN - handler = g_strdup ("/usr/bin/open"); - handler_needswait = TRUE; -#else - /* - * On Linux, try: xdg-open, the FreeDesktop standard way of doing it, - * if that fails, try to use gnome-open, then kfmclient - */ - MONO_ENTER_GC_SAFE; - handler = g_find_program_in_path ("xdg-open"); - if (handler != NULL) - handler_needswait = TRUE; - else { - handler = g_find_program_in_path ("gnome-open"); - if (handler == NULL){ - handler = g_find_program_in_path ("kfmclient"); - if (handler == NULL){ - handler_utf16 = (gunichar2 *) -1; - ret = FALSE; - } else { - /* kfmclient needs exec argument */ - char *old = handler; - handler = g_strconcat (old, " exec", - (const char*)NULL); - g_free (old); - } - } - } - MONO_EXIT_GC_SAFE; - if (ret == FALSE){ - goto done; - } -#endif - handler_utf16 = g_utf8_to_utf16 (handler, -1, NULL, NULL, NULL); - g_free (handler); - - /* Put quotes around the filename, in case it's a url - * that contains #'s (process_create() calls - * g_shell_parse_argv(), which deliberately throws - * away anything after an unquoted #). Fixes bug - * 371567. - */ - args = utf16_concat (handler_utf16, utf16_space, utf16_quote, lpFile, utf16_quote, - lpParameters ? utf16_space : NULL, lpParameters, (const gunichar2 *)NULL); - if (args == NULL) { - mono_w32error_set_last (ERROR_INVALID_DATA); - ret = FALSE; - goto done; - } - ret = process_create (NULL, args, lpDirectory, NULL, process_info); - g_free (args); - if (!ret) { - if (mono_w32error_get_last () != ERROR_OUTOFMEMORY) - mono_w32error_set_last (ERROR_INVALID_DATA); - ret = FALSE; - goto done; - } - - if (handler_needswait) { - gint32 exitcode; - MonoW32HandleWaitRet waitret; - waitret = process_wait ((MonoW32Handle*)process_info->process_handle, MONO_INFINITE_WAIT, NULL); - (void)waitret; - mono_get_exit_code_process (process_info->process_handle, &exitcode); - if (exitcode != 0) - ret = FALSE; - } - /* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */ - mono_w32handle_close (process_info->process_handle); - process_info->process_handle = INVALID_HANDLE_VALUE; - } - -done: - if (ret == FALSE) { - process_info->pid = -mono_w32error_get_last (); - } else { -#if !defined(MONO_CROSS_COMPILE) - process_info->pid = mono_w32process_get_pid (process_info->process_handle); -#else - process_info->pid = 0; -#endif - } - - mono_createprocess_coop_cleanup (&coop); - - return ret; -} - -/* Only used when UseShellExecute is false */ -static gboolean -process_get_complete_path (const gunichar2 *appname, gchar **completed) -{ - char *found = NULL; - gboolean result = FALSE; - - char *utf8app = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL); - - if (g_path_is_absolute (utf8app)) { - *completed = g_shell_quote (utf8app); - result = TRUE; - goto exit; - } - - if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) { - *completed = g_shell_quote (utf8app); - result = TRUE; - goto exit; - } - - found = g_find_program_in_path (utf8app); - if (found == NULL) { - *completed = NULL; - result = FALSE; - goto exit; - } - - *completed = g_shell_quote (found); - result = TRUE; -exit: - g_free (found); - g_free (utf8app); - return result; -} - -static gboolean -process_get_shell_arguments (MonoCreateProcessCoop *coop, gunichar2 **shell_path) -{ - gchar *complete_path = NULL; - - *shell_path = NULL; - - if (process_get_complete_path (coop->filename, &complete_path)) { - *shell_path = g_utf8_to_utf16 (complete_path, -1, NULL, NULL, NULL); - g_free (complete_path); - } - - return *shell_path != NULL; -} - -MonoBoolean -ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStartInfoHandle proc_start_info, - HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoW32ProcessInfo *process_info, MonoError *error) -{ - MonoCreateProcessCoop coop; - mono_createprocess_coop_init (&coop, proc_start_info, process_info); - - gboolean ret; - StartupHandles startup_handles; - gunichar2 *shell_path = NULL; - - memset (&startup_handles, 0, sizeof (startup_handles)); - startup_handles.input = stdin_handle; - startup_handles.output = stdout_handle; - startup_handles.error = stderr_handle; - - if (!process_get_shell_arguments (&coop, &shell_path)) { - process_info->pid = -ERROR_FILE_NOT_FOUND; - ret = FALSE; - goto exit; - } - - gunichar2 *args; - args = coop.length.arguments ? coop.arguments : NULL; - - /* The default dir name is "". Turn that into NULL to mean "current directory" */ - gunichar2 *dir; - dir = coop.length.working_directory ? coop.working_directory : NULL; - - ret = process_create (shell_path, args, dir, &startup_handles, process_info); - - if (!ret) - process_info->pid = -mono_w32error_get_last (); - -exit: - g_free (shell_path); - mono_createprocess_coop_cleanup (&coop); - return ret; -} - -/* Returns an array of pids */ -MonoArrayHandle -ves_icall_System_Diagnostics_Process_GetProcesses_internal (MonoError *error) -{ - int count = 0; - guint32 *raw = 0; - gpointer *pidarray = 0; - MonoArrayHandle procs = NULL_HANDLE_ARRAY; - - // FIXME mono_process_list should probably return array of int - // as all of the users of the elements truncate to that. - - MONO_ENTER_GC_SAFE; - pidarray = mono_process_list (&count); - MONO_EXIT_GC_SAFE; - if (!pidarray) { - mono_error_set_not_supported (error, "This system does not support EnumProcesses"); - goto exit; - } - procs = mono_array_new_handle (mono_domain_get (), mono_get_int32_class (), count, error); - if (!is_ok (error)) { - procs = NULL_HANDLE_ARRAY; - goto exit; - } - - MONO_ENTER_NO_SAFEPOINTS; - - raw = mono_array_addr_internal (MONO_HANDLE_RAW (procs), guint32, 0); - if (sizeof (guint32) == sizeof (gpointer)) { - memcpy (raw, pidarray, count * sizeof (gint32)); - } else { - for (int i = 0; i < count; ++i) - raw [i] = GPOINTER_TO_UINT (pidarray [i]); - } - - MONO_EXIT_NO_SAFEPOINTS; - -exit: - g_free (pidarray); - return procs; -} - -void -mono_w32process_set_cli_launcher (gchar *path) -{ - g_free (cli_launcher); - cli_launcher = g_strdup (path); -} - -gpointer -ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void) -{ - return current_process; -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode) -{ - return mono_get_exit_code_process (handle, exitcode); -} - -static MonoBoolean -mono_get_exit_code_process (gpointer handle, gint32 *exitcode) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - - if (!exitcode) - return FALSE; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - if (process_handle->pid == current_pid) { - *exitcode = STILL_ACTIVE; - mono_w32handle_unref (handle_data); - return TRUE; - } - - /* A process handle is only signalled if the process has exited - * and has been waited for. Make sure any process exit has been - * noticed before checking if the process is signalled. - * Fixes bug 325463. */ - mono_w32handle_wait_one (handle, 0, TRUE); - - *exitcode = mono_w32handle_issignalled (handle_data) ? process_handle->exitstatus : STILL_ACTIVE; - - mono_w32handle_unref (handle_data); - - return TRUE; -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle) -{ - return mono_w32handle_close (handle); -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode) -{ -#ifdef HAVE_KILL - MonoW32Handle *handle_data; - int ret; - pid_t pid; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - pid = ((MonoW32HandleProcess*) handle_data->specific)->pid; - - ret = kill (pid, exitcode == -1 ? SIGKILL : SIGTERM); - if (ret == 0) { - mono_w32handle_unref (handle_data); - return TRUE; - } - - switch (errno) { - case EINVAL: mono_w32error_set_last (ERROR_INVALID_PARAMETER); break; - case EPERM: mono_w32error_set_last (ERROR_ACCESS_DENIED); break; - case ESRCH: mono_w32error_set_last (ERROR_PROC_NOT_FOUND); break; - default: mono_w32error_set_last (ERROR_GEN_FAILURE); break; - } - - mono_w32handle_unref (handle_data); - return FALSE; -#else - g_error ("kill() is not supported by this platform"); -#endif -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - - if (!min || !max) - return FALSE; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - if (!process_handle->child) { - mono_w32handle_unref (handle_data); - return FALSE; - } - - *min = process_handle->min_working_set; - *max = process_handle->max_working_set; - - mono_w32handle_unref (handle_data); - return TRUE; -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - if (!process_handle->child) { - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle->min_working_set = min; - process_handle->max_working_set = max; - - mono_w32handle_unref (handle_data); - return TRUE; -} - -gint32 -ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle) -{ -#ifdef HAVE_GETPRIORITY - MonoW32Handle *handle_data; - gint res; - gint32 ret; - pid_t pid; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return 0; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return 0; - } - - pid = ((MonoW32HandleProcess*) handle_data->specific)->pid; - - mono_set_errno (0); - res = getpriority (PRIO_PROCESS, pid); - if (res == -1 && errno != 0) { - switch (errno) { - case EPERM: - case EACCES: - mono_w32error_set_last (ERROR_ACCESS_DENIED); - break; - case ESRCH: - mono_w32error_set_last (ERROR_PROC_NOT_FOUND); - break; - default: - mono_w32error_set_last (ERROR_GEN_FAILURE); - } - - mono_w32handle_unref (handle_data); - return 0; - } - - if (res == 0) - ret = MONO_W32PROCESS_PRIORITY_CLASS_NORMAL; - else if (res < -15) - ret = MONO_W32PROCESS_PRIORITY_CLASS_REALTIME; - else if (res < -10) - ret = MONO_W32PROCESS_PRIORITY_CLASS_HIGH; - else if (res < 0) - ret = MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; - else if (res > 10) - ret = MONO_W32PROCESS_PRIORITY_CLASS_IDLE; - else if (res > 0) - ret = MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL; - else - ret = MONO_W32PROCESS_PRIORITY_CLASS_NORMAL; - - mono_w32handle_unref (handle_data); - return ret; -#else - mono_w32error_set_last (ERROR_NOT_SUPPORTED); - return 0; -#endif -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass) -{ -#ifdef HAVE_SETPRIORITY - MonoW32Handle *handle_data; - int ret; - int prio; - pid_t pid; - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - pid = ((MonoW32HandleProcess*) handle_data->specific)->pid; - - switch (priorityClass) { - case MONO_W32PROCESS_PRIORITY_CLASS_IDLE: - prio = 19; - break; - case MONO_W32PROCESS_PRIORITY_CLASS_BELOW_NORMAL: - prio = 10; - break; - case MONO_W32PROCESS_PRIORITY_CLASS_NORMAL: - prio = 0; - break; - case MONO_W32PROCESS_PRIORITY_CLASS_ABOVE_NORMAL: - prio = -5; - break; - case MONO_W32PROCESS_PRIORITY_CLASS_HIGH: - prio = -11; - break; - case MONO_W32PROCESS_PRIORITY_CLASS_REALTIME: - prio = -20; - break; - default: - mono_w32error_set_last (ERROR_INVALID_PARAMETER); - mono_w32handle_unref (handle_data); - return FALSE; - } - - ret = setpriority (PRIO_PROCESS, pid, prio); - if (ret == -1) { - switch (errno) { - case EPERM: - case EACCES: - mono_w32error_set_last (ERROR_ACCESS_DENIED); - break; - case ESRCH: - mono_w32error_set_last (ERROR_PROC_NOT_FOUND); - break; - default: - mono_w32error_set_last (ERROR_GEN_FAILURE); - } - } - - mono_w32handle_unref (handle_data); - return ret == 0; -#else - mono_w32error_set_last (ERROR_NOT_SUPPORTED); - return FALSE; -#endif -} - -static void -ticks_to_processtime (guint64 ticks, ProcessTime *processtime) -{ - processtime->lowDateTime = ticks & 0xFFFFFFFF; - processtime->highDateTime = ticks >> 32; -} - -MonoBoolean -ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creation_time, gint64 *exit_time, gint64 *kernel_time, gint64 *user_time) -{ - MonoW32Handle *handle_data; - MonoW32HandleProcess *process_handle; - ProcessTime *creation_processtime, *exit_processtime, *kernel_processtime, *user_processtime; - - if (!creation_time || !exit_time || !kernel_time || !user_time) { - /* Not sure if w32 allows NULLs here or not */ - return FALSE; - } - - creation_processtime = (ProcessTime*) creation_time; - exit_processtime = (ProcessTime*) exit_time; - kernel_processtime = (ProcessTime*) kernel_time; - user_processtime = (ProcessTime*) user_time; - - memset (creation_processtime, 0, sizeof (ProcessTime)); - memset (exit_processtime, 0, sizeof (ProcessTime)); - memset (kernel_processtime, 0, sizeof (ProcessTime)); - memset (user_processtime, 0, sizeof (ProcessTime)); - - if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return FALSE; - } - - if (handle_data->type != MONO_W32TYPE_PROCESS) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: unknown process handle %p", __func__, handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - mono_w32handle_unref (handle_data); - return FALSE; - } - - process_handle = (MonoW32HandleProcess*) handle_data->specific; - - if (!process_handle->child) { - gint64 start_ticks, user_ticks, kernel_ticks; - - mono_process_get_times (GINT_TO_POINTER (process_handle->pid), - &start_ticks, &user_ticks, &kernel_ticks); - - ticks_to_processtime (start_ticks, creation_processtime); - ticks_to_processtime (kernel_ticks, kernel_processtime); - ticks_to_processtime (user_ticks, user_processtime); - - mono_w32handle_unref (handle_data); - return TRUE; - } - - ticks_to_processtime (process_handle->create_time, creation_processtime); - - /* A process handle is only signalled if the process has - * exited, otherwise exit_processtime isn't set */ - if (mono_w32handle_issignalled (handle_data)) - ticks_to_processtime (process_handle->exit_time, exit_processtime); - -#ifdef HAVE_GETRUSAGE - if (process_handle->pid == getpid ()) { - struct rusage time_data; - if (getrusage (RUSAGE_SELF, &time_data) == 0) { - ticks_to_processtime ((guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10, user_processtime); - ticks_to_processtime ((guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10, kernel_processtime); - } - } -#endif - - mono_w32handle_unref (handle_data); - return TRUE; -} - -static IMAGE_SECTION_HEADER * -get_enclosing_section_header (guint32 rva, IMAGE_NT_HEADERS32 *nt_headers) -{ - IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION32 (nt_headers); - guint32 i; - - for (i = 0; i < GUINT16_FROM_LE (nt_headers->FileHeader.NumberOfSections); i++, section++) { - guint32 size = GUINT32_FROM_LE (section->Misc.VirtualSize); - if (size == 0) { - size = GUINT32_FROM_LE (section->SizeOfRawData); - } - - if ((rva >= GUINT32_FROM_LE (section->VirtualAddress)) && - (rva < (GUINT32_FROM_LE (section->VirtualAddress) + size))) { - return(section); - } - } - - return(NULL); -} - -/* This works for both 32bit and 64bit files, as the differences are - * all after the section header block - */ -static gpointer -get_ptr_from_rva (guint32 rva, IMAGE_NT_HEADERS32 *ntheaders, gpointer file_map) -{ - IMAGE_SECTION_HEADER *section_header; - guint32 delta; - - section_header = get_enclosing_section_header (rva, ntheaders); - if (section_header == NULL) { - return(NULL); - } - - delta = (guint32)(GUINT32_FROM_LE (section_header->VirtualAddress) - - GUINT32_FROM_LE (section_header->PointerToRawData)); - - return((guint8 *)file_map + rva - delta); -} - -static gpointer -scan_resource_dir (IMAGE_RESOURCE_DIRECTORY *root, IMAGE_NT_HEADERS32 *nt_headers, gpointer file_map, - IMAGE_RESOURCE_DIRECTORY_ENTRY *entry, int level, guint32 res_id, guint32 lang_id, gsize *size) -{ - IMAGE_RESOURCE_DIRECTORY_ENTRY swapped_entry; - gboolean is_string, is_dir; - guint32 name_offset, dir_offset, data_offset; - - swapped_entry.Name = GUINT32_FROM_LE (entry->Name); - swapped_entry.OffsetToData = GUINT32_FROM_LE (entry->OffsetToData); - - is_string = swapped_entry.NameIsString; - is_dir = swapped_entry.DataIsDirectory; - name_offset = swapped_entry.NameOffset; - dir_offset = swapped_entry.OffsetToDirectory; - data_offset = swapped_entry.OffsetToData; - - if (level == 0) { - /* Normally holds a directory entry for each type of - * resource - */ - if ((is_string == FALSE && - name_offset != res_id) || - (is_string == TRUE)) { - return(NULL); - } - } else if (level == 1) { - /* Normally holds a directory entry for each resource - * item - */ - } else if (level == 2) { - /* Normally holds a directory entry for each language - */ - if ((is_string == FALSE && - name_offset != lang_id && - lang_id != 0) || - (is_string == TRUE)) { - return(NULL); - } - } else { - g_assert_not_reached (); - } - - if (is_dir == TRUE) { - IMAGE_RESOURCE_DIRECTORY *res_dir = (IMAGE_RESOURCE_DIRECTORY *)((guint8 *)root + dir_offset); - IMAGE_RESOURCE_DIRECTORY_ENTRY *sub_entries = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(res_dir + 1); - guint32 entries, i; - - entries = GUINT16_FROM_LE (res_dir->NumberOfNamedEntries) + GUINT16_FROM_LE (res_dir->NumberOfIdEntries); - - for (i = 0; i < entries; i++) { - IMAGE_RESOURCE_DIRECTORY_ENTRY *sub_entry = &sub_entries[i]; - gpointer ret; - - ret = scan_resource_dir (root, nt_headers, file_map, - sub_entry, level + 1, res_id, - lang_id, size); - if (ret != NULL) { - return(ret); - } - } - - return(NULL); - } else { - IMAGE_RESOURCE_DATA_ENTRY *data_entry = (IMAGE_RESOURCE_DATA_ENTRY *)((guint8 *)root + data_offset); - *size = GUINT32_FROM_LE (data_entry->Size); - - return(get_ptr_from_rva (GUINT32_FROM_LE (data_entry->OffsetToData), nt_headers, file_map)); - } -} - -static gpointer -find_pe_file_resources32 (gpointer file_map, guint32 map_size, guint32 res_id, guint32 lang_id, gsize *size) -{ - IMAGE_DOS_HEADER *dos_header; - IMAGE_NT_HEADERS32 *nt_headers; - IMAGE_RESOURCE_DIRECTORY *resource_dir; - IMAGE_RESOURCE_DIRECTORY_ENTRY *resource_dir_entry; - guint32 resource_rva, entries, i; - gpointer ret = NULL; - - dos_header = (IMAGE_DOS_HEADER *)file_map; - if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Bad dos signature 0x%x", __func__, dos_header->e_magic); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - if (map_size < sizeof(IMAGE_NT_HEADERS32) + GUINT32_FROM_LE (dos_header->e_lfanew)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: File is too small: %" G_GUINT32_FORMAT, __func__, map_size); - - mono_w32error_set_last (ERROR_BAD_LENGTH); - return(NULL); - } - - nt_headers = (IMAGE_NT_HEADERS32 *)((guint8 *)file_map + GUINT32_FROM_LE (dos_header->e_lfanew)); - if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Bad NT signature 0x%x", __func__, nt_headers->Signature); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - if (nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - /* Do 64-bit stuff */ - resource_rva = GUINT32_FROM_LE (((IMAGE_NT_HEADERS64 *)nt_headers)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); - } else { - resource_rva = GUINT32_FROM_LE (nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); - } - - if (resource_rva == 0) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: No resources in file!", __func__); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - resource_dir = (IMAGE_RESOURCE_DIRECTORY *)get_ptr_from_rva (resource_rva, (IMAGE_NT_HEADERS32 *)nt_headers, file_map); - if (resource_dir == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't find resource directory", __func__); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - entries = GUINT16_FROM_LE (resource_dir->NumberOfNamedEntries) + GUINT16_FROM_LE (resource_dir->NumberOfIdEntries); - resource_dir_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resource_dir + 1); - - for (i = 0; i < entries; i++) { - IMAGE_RESOURCE_DIRECTORY_ENTRY *direntry = &resource_dir_entry[i]; - ret = scan_resource_dir (resource_dir, - (IMAGE_NT_HEADERS32 *)nt_headers, - file_map, direntry, 0, res_id, - lang_id, size); - if (ret != NULL) { - return(ret); - } - } - - return(NULL); -} - -static gpointer -find_pe_file_resources64 (gpointer file_map, guint32 map_size, guint32 res_id, guint32 lang_id, gsize *size) -{ - IMAGE_DOS_HEADER *dos_header; - IMAGE_NT_HEADERS64 *nt_headers; - IMAGE_RESOURCE_DIRECTORY *resource_dir; - IMAGE_RESOURCE_DIRECTORY_ENTRY *resource_dir_entry; - guint32 resource_rva, entries, i; - gpointer ret = NULL; - - dos_header = (IMAGE_DOS_HEADER *)file_map; - if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Bad dos signature 0x%x", __func__, dos_header->e_magic); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - if (map_size < sizeof(IMAGE_NT_HEADERS64) + GUINT32_FROM_LE (dos_header->e_lfanew)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: File is too small: %" G_GUINT32_FORMAT, __func__, map_size); - - mono_w32error_set_last (ERROR_BAD_LENGTH); - return(NULL); - } - - nt_headers = (IMAGE_NT_HEADERS64 *)((guint8 *)file_map + GUINT32_FROM_LE (dos_header->e_lfanew)); - if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Bad NT signature 0x%x", __func__, - nt_headers->Signature); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - if (nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { - /* Do 64-bit stuff */ - resource_rva = GUINT32_FROM_LE (((IMAGE_NT_HEADERS64 *)nt_headers)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); - } else { - resource_rva = GUINT32_FROM_LE (nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); - } - - if (resource_rva == 0) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: No resources in file!", __func__); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - resource_dir = (IMAGE_RESOURCE_DIRECTORY *)get_ptr_from_rva (resource_rva, (IMAGE_NT_HEADERS32 *)nt_headers, file_map); - if (resource_dir == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Can't find resource directory", __func__); - - mono_w32error_set_last (ERROR_INVALID_DATA); - return(NULL); - } - - entries = GUINT16_FROM_LE (resource_dir->NumberOfNamedEntries) + GUINT16_FROM_LE (resource_dir->NumberOfIdEntries); - resource_dir_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resource_dir + 1); - - for (i = 0; i < entries; i++) { - IMAGE_RESOURCE_DIRECTORY_ENTRY *direntry = &resource_dir_entry[i]; - ret = scan_resource_dir (resource_dir, - (IMAGE_NT_HEADERS32 *)nt_headers, - file_map, direntry, 0, res_id, - lang_id, size); - if (ret != NULL) { - return(ret); - } - } - - return(NULL); -} - -static gpointer -find_pe_file_resources (gpointer file_map, guint32 map_size, guint32 res_id, guint32 lang_id, gsize *size) -{ - /* Figure this out when we support 64bit PE files */ - if (1) { - return find_pe_file_resources32 (file_map, map_size, res_id, - lang_id, size); - } else { - return find_pe_file_resources64 (file_map, map_size, res_id, - lang_id, size); - } -} - -static guint32 -unicode_chars (const gunichar2 *str) -{ - guint32 len = 0; - - do { - if (str[len] == '\0') { - return(len); - } - len++; - } while(1); -} - -static gboolean -unicode_compare (const gunichar2 *str1, const gunichar2 *str2) -{ - while (*str1 && *str2) { - if (*str1 != *str2) { - return(FALSE); - } - ++str1; - ++str2; - } - - return(*str1 == *str2); -} - -/* compare a little-endian null-terminated utf16 string and a normal string. - * Can be used only for ascii or latin1 chars. - */ -static gboolean -unicode_string_equals (const gunichar2 *str1, const gchar *str2) -{ - while (*str1 && *str2) { - if (GUINT16_TO_LE (*str1) != *str2) { - return(FALSE); - } - ++str1; - ++str2; - } - - return(*str1 == *str2); -} - -typedef struct { - guint16 data_len; - guint16 value_len; - guint16 type; - gunichar2 *key; -} version_data; - -/* Returns a pointer to the value data, because there's no way to know - * how big that data is (value_len is set to zero for most blocks :-( ) - */ -static gconstpointer -get_versioninfo_block (gconstpointer data, version_data *block) -{ - block->data_len = GUINT16_FROM_LE (*((guint16 *)data)); - data = (char *)data + sizeof(guint16); - block->value_len = GUINT16_FROM_LE (*((guint16 *)data)); - data = (char *)data + sizeof(guint16); - - /* No idea what the type is supposed to indicate */ - block->type = GUINT16_FROM_LE (*((guint16 *)data)); - data = (char *)data + sizeof(guint16); - block->key = ((gunichar2 *)data); - - /* Skip over the key (including the terminator) */ - data = ((gunichar2 *)data) + (unicode_chars (block->key) + 1); - - /* align on a 32-bit boundary */ - ALIGN32 (data); - - return(data); -} - -static gconstpointer -get_fixedfileinfo_block (gconstpointer data, version_data *block) -{ - gconstpointer data_ptr; - VS_FIXEDFILEINFO *ffi; - - data_ptr = get_versioninfo_block (data, block); - - if (block->value_len != sizeof(VS_FIXEDFILEINFO)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: FIXEDFILEINFO size mismatch", __func__); - return(NULL); - } - - if (!unicode_string_equals (block->key, "VS_VERSION_INFO")) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: VS_VERSION_INFO mismatch", __func__); - - return(NULL); - } - - ffi = ((VS_FIXEDFILEINFO *)data_ptr); - if ((ffi->dwSignature != VS_FFI_SIGNATURE) || - (ffi->dwStrucVersion != VS_FFI_STRUCVERSION)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: FIXEDFILEINFO bad signature", __func__); - - return(NULL); - } - - return(data_ptr); -} - -static gconstpointer -get_varfileinfo_block (gconstpointer data_ptr, version_data *block) -{ - /* data is pointing at a Var block - */ - data_ptr = get_versioninfo_block (data_ptr, block); - - return(data_ptr); -} - -static gconstpointer -get_string_block (gconstpointer data_ptr, const gunichar2 *string_key, gpointer *string_value, - guint32 *string_value_len, version_data *block) -{ - guint16 data_len = block->data_len; - guint16 string_len = 28; /* Length of the StringTable block */ - char *orig_data_ptr = (char *)data_ptr - 28; - - /* data_ptr is pointing at an array of one or more String blocks - * with total length (not including alignment padding) of - * data_len - */ - while (((char *)data_ptr - (char *)orig_data_ptr) < data_len) { - /* align on a 32-bit boundary */ - ALIGN32 (data_ptr); - - data_ptr = get_versioninfo_block (data_ptr, block); - if (block->data_len == 0) { - /* We must have hit padding, so give up - * processing now - */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Hit 0-length block, giving up", __func__); - - return(NULL); - } - - string_len = string_len + block->data_len; - - if (string_key != NULL && - string_value != NULL && - string_value_len != NULL && - unicode_compare (string_key, block->key) == TRUE) { - *string_value = (gpointer)data_ptr; - *string_value_len = block->value_len; - } - - /* Skip over the value */ - data_ptr = ((gunichar2 *)data_ptr) + block->value_len; - } - - return(data_ptr); -} - -/* Returns a pointer to the byte following the Stringtable block, or - * NULL if the data read hits padding. We can't recover from this - * because the data length does not include padding bytes, so it's not - * possible to just return the start position + length - * - * If lang == NULL it means we're just stepping through this block - */ -static gconstpointer -get_stringtable_block (gconstpointer data_ptr, gchar *lang, const gunichar2 *string_key, gpointer *string_value, - guint32 *string_value_len, version_data *block) -{ - guint16 data_len = block->data_len; - guint16 string_len = 36; /* length of the StringFileInfo block */ - gchar *found_lang; - gchar *lowercase_lang; - - /* data_ptr is pointing at an array of StringTable blocks, - * with total length (not including alignment padding) of - * data_len - */ - - while(string_len < data_len) { - /* align on a 32-bit boundary */ - ALIGN32 (data_ptr); - - data_ptr = get_versioninfo_block (data_ptr, block); - if (block->data_len == 0) { - /* We must have hit padding, so give up - * processing now - */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Hit 0-length block, giving up", __func__); - return(NULL); - } - - string_len = string_len + block->data_len; - - found_lang = g_utf16_to_utf8 (block->key, 8, NULL, NULL, NULL); - if (found_lang == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Didn't find a valid language key, giving up", __func__); - return(NULL); - } - - lowercase_lang = g_utf8_strdown (found_lang, -1); - g_free (found_lang); - found_lang = lowercase_lang; - lowercase_lang = NULL; - - if (lang != NULL && !strcmp (found_lang, lang)) { - /* Got the one we're interested in */ - data_ptr = get_string_block (data_ptr, string_key, - string_value, - string_value_len, block); - } else { - data_ptr = get_string_block (data_ptr, NULL, NULL, - NULL, block); - } - - g_free (found_lang); - - if (data_ptr == NULL) { - /* Child block hit padding */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Child block hit 0-length block, giving up", __func__); - return(NULL); - } - } - - return(data_ptr); -} - -#if G_BYTE_ORDER == G_BIG_ENDIAN -static gconstpointer -big_up_string_block (gconstpointer data_ptr, version_data *block) -{ - guint16 data_len = block->data_len; - guint16 string_len = 28; /* Length of the StringTable block */ - gchar *big_value; - char *orig_data_ptr = (char *)data_ptr - 28; - - /* data_ptr is pointing at an array of one or more String - * blocks with total length (not including alignment padding) - * of data_len - */ - while (((char *)data_ptr - (char *)orig_data_ptr) < data_len) { - /* align on a 32-bit boundary */ - ALIGN32 (data_ptr); - - data_ptr = get_versioninfo_block (data_ptr, block); - if (block->data_len == 0) { - /* We must have hit padding, so give up - * processing now - */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Hit 0-length block, giving up", __func__); - return(NULL); - } - - string_len = string_len + block->data_len; - - big_value = g_convert ((gchar *)block->key, - unicode_chars (block->key) * 2, - "UTF-16BE", "UTF-16LE", NULL, NULL, - NULL); - if (big_value == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Didn't find a valid string, giving up", __func__); - return(NULL); - } - - /* The swapped string should be exactly the same - * length as the original little-endian one, but only - * copy the number of original chars just to be on the - * safe side - */ - memcpy (block->key, big_value, unicode_chars (block->key) * 2); - g_free (big_value); - - big_value = g_convert ((gchar *)data_ptr, - unicode_chars ((const gunichar2*)data_ptr) * 2, - "UTF-16BE", "UTF-16LE", NULL, NULL, - NULL); - if (big_value == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Didn't find a valid data string, giving up", __func__); - return(NULL); - } - memcpy ((gpointer)data_ptr, big_value, - unicode_chars ((const gunichar2*)data_ptr) * sizeof(gunichar2)); - g_free (big_value); - - data_ptr = ((gunichar2 *)data_ptr) + block->value_len; - } - - return(data_ptr); -} - -/* Returns a pointer to the byte following the Stringtable block, or - * NULL if the data read hits padding. We can't recover from this - * because the data length does not include padding bytes, so it's not - * possible to just return the start position + length - */ -static gconstpointer -big_up_stringtable_block (gconstpointer data_ptr, version_data *block) -{ - guint16 data_len = block->data_len; - guint16 string_len = 36; /* length of the StringFileInfo block */ - gchar *big_value; - - /* data_ptr is pointing at an array of StringTable blocks, - * with total length (not including alignment padding) of - * data_len - */ - - while(string_len < data_len) { - /* align on a 32-bit boundary */ - ALIGN32 (data_ptr); - - data_ptr = get_versioninfo_block (data_ptr, block); - if (block->data_len == 0) { - /* We must have hit padding, so give up - * processing now - */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Hit 0-length block, giving up", __func__); - return(NULL); - } - - string_len = string_len + block->data_len; - - big_value = g_convert ((gchar *)block->key, 16, "UTF-16BE", - "UTF-16LE", NULL, NULL, NULL); - if (big_value == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Didn't find a valid string, giving up", __func__); - return(NULL); - } - - memcpy (block->key, big_value, 16); - g_free (big_value); - - data_ptr = big_up_string_block (data_ptr, block); - - if (data_ptr == NULL) { - /* Child block hit padding */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Child block hit 0-length block, giving up", __func__); - return(NULL); - } - } - - return(data_ptr); -} - -/* Follows the data structures and turns all UTF-16 strings from the - * LE found in the resource section into UTF-16BE - */ -static void -big_up (gconstpointer datablock, guint32 size) -{ - gconstpointer data_ptr; - gint32 data_len; /* signed to guard against underflow */ - version_data block; - - data_ptr = get_fixedfileinfo_block (datablock, &block); - if (data_ptr != NULL) { - VS_FIXEDFILEINFO *ffi = (VS_FIXEDFILEINFO *)data_ptr; - - /* Byteswap all the fields */ - ffi->dwFileVersionMS = GUINT32_SWAP_LE_BE (ffi->dwFileVersionMS); - ffi->dwFileVersionLS = GUINT32_SWAP_LE_BE (ffi->dwFileVersionLS); - ffi->dwProductVersionMS = GUINT32_SWAP_LE_BE (ffi->dwProductVersionMS); - ffi->dwProductVersionLS = GUINT32_SWAP_LE_BE (ffi->dwProductVersionLS); - ffi->dwFileFlagsMask = GUINT32_SWAP_LE_BE (ffi->dwFileFlagsMask); - ffi->dwFileFlags = GUINT32_SWAP_LE_BE (ffi->dwFileFlags); - ffi->dwFileOS = GUINT32_SWAP_LE_BE (ffi->dwFileOS); - ffi->dwFileType = GUINT32_SWAP_LE_BE (ffi->dwFileType); - ffi->dwFileSubtype = GUINT32_SWAP_LE_BE (ffi->dwFileSubtype); - ffi->dwFileDateMS = GUINT32_SWAP_LE_BE (ffi->dwFileDateMS); - ffi->dwFileDateLS = GUINT32_SWAP_LE_BE (ffi->dwFileDateLS); - - /* The FFI and header occupies the first 92 bytes - */ - data_ptr = (char *)data_ptr + sizeof(VS_FIXEDFILEINFO); - data_len = block.data_len - 92; - - /* There now follow zero or one StringFileInfo blocks - * and zero or one VarFileInfo blocks - */ - while (data_len > 0) { - /* align on a 32-bit boundary */ - ALIGN32 (data_ptr); - - data_ptr = get_versioninfo_block (data_ptr, &block); - if (block.data_len == 0) { - /* We must have hit padding, so give - * up processing now - */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Hit 0-length block, giving up", __func__); - return; - } - - data_len = data_len - block.data_len; - - if (unicode_string_equals (block.key, "VarFileInfo")) { - data_ptr = get_varfileinfo_block (data_ptr, - &block); - data_ptr = ((guchar *)data_ptr) + block.value_len; - } else if (unicode_string_equals (block.key, - "StringFileInfo")) { - data_ptr = big_up_stringtable_block (data_ptr, - &block); - } else { - /* Bogus data */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Not a valid VERSIONINFO child block", __func__); - return; - } - - if (data_ptr == NULL) { - /* Child block hit padding */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Child block hit 0-length block, giving up", __func__); - return; - } - } - } -} -#endif - -gboolean -mono_w32process_get_fileversion_info (const gunichar2 *filename, gpointer *data) -{ - gpointer file_map; - gpointer versioninfo; - void *map_handle; - gint32 map_size; - gsize datasize; - - g_assert (data); - *data = NULL; - - file_map = mono_pe_file_map (filename, &map_size, &map_handle); - if (!file_map) - return FALSE; - - versioninfo = find_pe_file_resources (file_map, map_size, RT_VERSION, 0, &datasize); - if (!versioninfo) { - mono_pe_file_unmap (file_map, map_handle); - return FALSE; - } - - *data = g_malloc0 (datasize); - - /* This could probably process the data so that mono_w32process_ver_query_value() doesn't have to follow the - * data blocks every time. But hey, these functions aren't likely to appear in many profiles. */ - memcpy (*data, versioninfo, datasize); - -#if G_BYTE_ORDER == G_BIG_ENDIAN - big_up (*data, datasize); -#endif - - mono_pe_file_unmap (file_map, map_handle); - - return TRUE; -} - -gboolean -mono_w32process_ver_query_value (gconstpointer datablock, const gunichar2 *subblock, gpointer *buffer, guint32 *len) -{ - gchar *subblock_utf8, *lang_utf8 = NULL; - gboolean ret = FALSE; - version_data block; - gconstpointer data_ptr; - gint32 data_len; /* signed to guard against underflow */ - gboolean want_var = FALSE; - gboolean want_string = FALSE; - gunichar2 lang[8]; - const gunichar2 *string_key = NULL; - gpointer string_value = NULL; - guint32 string_value_len = 0; - gchar *lowercase_lang; - - subblock_utf8 = g_utf16_to_utf8 (subblock, -1, NULL, NULL, NULL); - if (subblock_utf8 == NULL) { - return(FALSE); - } - - if (!strcmp (subblock_utf8, "\\VarFileInfo\\Translation")) { - want_var = TRUE; - } else if (!strncmp (subblock_utf8, "\\StringFileInfo\\", 16)) { - want_string = TRUE; - memcpy (lang, subblock + 16, 8 * sizeof(gunichar2)); - lang_utf8 = g_utf16_to_utf8 (lang, 8, NULL, NULL, NULL); - lowercase_lang = g_utf8_strdown (lang_utf8, -1); - g_free (lang_utf8); - lang_utf8 = lowercase_lang; - lowercase_lang = NULL; - string_key = subblock + 25; - } - - if (!strcmp (subblock_utf8, "\\")) { - data_ptr = get_fixedfileinfo_block (datablock, &block); - if (data_ptr != NULL) { - *buffer = (gpointer)data_ptr; - *len = block.value_len; - - ret = TRUE; - } - } else if (want_var || want_string) { - data_ptr = get_fixedfileinfo_block (datablock, &block); - if (data_ptr != NULL) { - /* The FFI and header occupies the first 92 - * bytes - */ - data_ptr = (char *)data_ptr + sizeof(VS_FIXEDFILEINFO); - data_len = block.data_len - 92; - - /* There now follow zero or one StringFileInfo - * blocks and zero or one VarFileInfo blocks - */ - while (data_len > 0) { - /* align on a 32-bit boundary */ - ALIGN32 (data_ptr); - - data_ptr = get_versioninfo_block (data_ptr, - &block); - if (block.data_len == 0) { - /* We must have hit padding, - * so give up processing now - */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Hit 0-length block, giving up", __func__); - goto done; - } - - data_len = data_len - block.data_len; - - if (unicode_string_equals (block.key, "VarFileInfo")) { - data_ptr = get_varfileinfo_block (data_ptr, &block); - if (want_var) { - *buffer = (gpointer)data_ptr; - *len = block.value_len; - ret = TRUE; - goto done; - } else { - /* Skip over the Var block */ - data_ptr = ((guchar *)data_ptr) + block.value_len; - } - } else if (unicode_string_equals (block.key, "StringFileInfo")) { - data_ptr = get_stringtable_block (data_ptr, lang_utf8, string_key, &string_value, &string_value_len, &block); - if (want_string && - string_value != NULL && - string_value_len != 0) { - *buffer = string_value; - *len = unicode_chars ((const gunichar2 *)string_value) + 1; /* Include trailing null */ - ret = TRUE; - goto done; - } - } else { - /* Bogus data */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Not a valid VERSIONINFO child block", __func__); - goto done; - } - - if (data_ptr == NULL) { - /* Child block hit padding */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_PROCESS, "%s: Child block hit 0-length block, giving up", __func__); - goto done; - } - } - } - } - - done: - if (lang_utf8) { - g_free (lang_utf8); - } - - g_free (subblock_utf8); - return(ret); -} - -#else /* ENABLE_NETCORE && DISABLE_PROCESSES */ - void mono_w32process_init (void) { @@ -3542,5 +134,3 @@ mono_w32process_ver_query_value (gconstpointer datablock, const gunichar2 *subbl { return FALSE; } - -#endif /* ENABLE_NETCORE && DISABLE_PROCESSES */ diff --git a/src/mono/mono/metadata/w32process-win32.c b/src/mono/mono/metadata/w32process-win32.c index f2e877e..cb3b2a8 100644 --- a/src/mono/mono/metadata/w32process-win32.c +++ b/src/mono/mono/metadata/w32process-win32.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mono/mono/metadata/w32process.c b/src/mono/mono/metadata/w32process.c index 08f9386..3755bcd 100644 --- a/src/mono/mono/metadata/w32process.c +++ b/src/mono/mono/metadata/w32process.c @@ -312,20 +312,6 @@ mono_w32process_get_fileversion (MonoObjectHandle filever, MonoStringHandle str, } #endif -#ifndef ENABLE_NETCORE -void -ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObjectHandle this_obj, - const gunichar2 *filename, int filename_length, MonoError *error) -{ - MonoStringHandle str = MONO_HANDLE_CAST (MonoString, mono_new_null ()); - - mono_w32process_get_fileversion (this_obj, str, filename, error); - return_if_nok (error); - - process_set_field_utf16 (this_obj, str, "filename", filename, filename_length, error); -} -#endif - static GPtrArray* get_domain_assemblies (MonoDomain *domain) { @@ -451,105 +437,6 @@ exit: HANDLE_FUNCTION_RETURN (); } -#ifndef ENABLE_NETCORE -/* Returns an array of System.Diagnostics.ProcessModule */ -MonoArrayHandle -ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObjectHandle this_obj, HANDLE process, MonoError *error) -{ - MonoArrayHandle temp_arr = NULL_HANDLE_ARRAY; - MonoArrayHandle arr = NULL_HANDLE_ARRAY; - HMODULE mods [1024]; - gunichar2 *filename = NULL; - gunichar2 *modname = NULL; - guint32 filename_len = 0; - guint32 modname_len = 0; - guint32 needed = 0; - guint32 count = 0; - guint32 module_count = 0; - guint32 assembly_count = 0; - guint32 i = 0; - guint32 num_added = 0; - GPtrArray *assemblies = NULL; - MonoClass *process_module_class; - - process_module_class = get_process_module_class (m_class_get_image (mono_handle_class (this_obj))); - - // Coop handles are created here, once, in order to cut down on - // handle creation and ease use of loops that would - // otherwise create handles. - MonoObjectHandle module = mono_new_null (); - MonoObjectHandle filever = mono_new_null (); - MonoStringHandle str = MONO_HANDLE_CAST (MonoString, mono_new_null ()); - - if (mono_w32process_get_pid (process) == mono_process_current_pid ()) { - assemblies = get_domain_assemblies (mono_domain_get ()); - assembly_count = assemblies->len; - } - - if (mono_w32process_try_get_modules (process, (gpointer *)mods, sizeof (mods), &needed)) - module_count += needed / sizeof (HMODULE); - - count = module_count + assembly_count; - temp_arr = mono_array_new_handle (mono_domain_get (), process_module_class, count, error); - return_val_if_nok (error, NULL_HANDLE_ARRAY); - - for (i = 0; i < module_count; i++) { - if (mono_w32process_module_get_name (process, mods [i], &modname, &modname_len) && mono_w32process_module_get_filename (process, mods [i], &filename, &filename_len)) { - process_add_module (module, filever, str, process, mods [i], filename, modname, process_module_class, error); - if (is_ok (error)) - MONO_HANDLE_ARRAY_SETREF (temp_arr, num_added++, module); - } - g_free (modname); - g_free (filename); - if (!is_ok (error)) - return NULL_HANDLE_ARRAY; - } - - if (assemblies) { - for (i = 0; i < assembly_count; i++) { - MonoAssembly *ass = (MonoAssembly *)g_ptr_array_index (assemblies, i); - process_get_module (module, filever, str, ass, process_module_class, error); - return_val_if_nok (error, NULL_HANDLE_ARRAY); - MONO_HANDLE_ARRAY_SETREF (temp_arr, num_added++, module); - } - g_ptr_array_free (assemblies, TRUE); - } - - if (count == num_added) - return temp_arr; - - /* shorter version of the array */ - arr = mono_array_new_handle (mono_domain_get (), process_module_class, num_added, error); - return_val_if_nok (error, NULL_HANDLE_ARRAY); - - for (i = 0; i < num_added; i++) { - MONO_HANDLE_ARRAY_GETREF (module, temp_arr, i); - MONO_HANDLE_ARRAY_SETREF (arr, i, module); - } - - return arr; -} - -MonoStringHandle -ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process, MonoError *error) -{ - gunichar2 *name = NULL; - HMODULE mod = 0; - guint32 needed = 0; - guint32 len = 0; - - if (!mono_w32process_try_get_modules (process, (gpointer *)&mod, sizeof (mod), &needed)) - return NULL_HANDLE_STRING; - - if (!mono_w32process_module_get_name (process, mod, &name, &len)) - return NULL_HANDLE_STRING; - - MonoStringHandle res = mono_string_new_utf16_handle (mono_domain_get (), name, len, error); - g_free (name); - return res; -} -#endif /* ENABLE_NETCORE */ - gint64 ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, MonoProcessError *error) { diff --git a/src/mono/mono/metadata/w32socket-unix.c b/src/mono/mono/metadata/w32socket-unix.c index 3c0e13a..2c19b03 100644 --- a/src/mono/mono/metadata/w32socket-unix.c +++ b/src/mono/mono/metadata/w32socket-unix.c @@ -1557,23 +1557,6 @@ mono_w32socket_convert_error (gint error) } } -#ifndef ENABLE_NETCORE -MonoBoolean -ves_icall_System_Net_Sockets_Socket_SupportPortReuse_icall (MonoProtocolType proto) -{ -#if defined (SO_REUSEPORT) - return TRUE; -#else -#ifdef __linux__ - /* Linux always supports double binding for UDP, even on older kernels. */ - if (proto == ProtocolType_Udp) - return TRUE; -#endif - return FALSE; -#endif -} -#endif - gboolean mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle) { diff --git a/src/mono/mono/metadata/w32socket.c b/src/mono/mono/metadata/w32socket.c deleted file mode 100644 index db3edc8..0000000 --- a/src/mono/mono/metadata/w32socket.c +++ /dev/null @@ -1,2646 +0,0 @@ -/** - * \file - * Socket IO internal calls - * - * Authors: - * Dick Porter (dick@ximian.com) - * Gonzalo Paniagua Javier (gonzalo@ximian.com) - * - * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) - * Copyright 2004-2009 Novell, Inc (http://www.novell.com) - * - * This file has been re-licensed under the MIT License: - * http://opensource.org/licenses/MIT - * Licensed under the MIT license. See LICENSE file in the project root for full license information. - */ - -#include - -#include - -#if !defined(DISABLE_SOCKETS) && !defined(ENABLE_NETCORE) - -#if defined(__APPLE__) || defined(__FreeBSD__) -#define __APPLE_USE_RFC_3542 -#endif - -#include -#include -#include -#ifdef HOST_WIN32 -#include -#else -#include -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#include -#include -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_NETINET_TCP_H -#include -#endif -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* FIXME change this code to not mess so much with the internals */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif - -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_SYS_FILIO_H -#include /* defines FIONBIO and FIONREAD */ -#endif -#ifdef HAVE_SYS_SOCKIO_H -#include /* defines SIOCATMARK */ -#endif -#ifdef HAVE_SYS_UN_H -#include -#endif - -#ifdef HAVE_GETIFADDRS -// must be included before -#include -#elif defined(HAVE_QP2GETIFADDRS) -/* Bizarrely, IBM i implements this, but AIX doesn't, so on i, it has a different name... */ -#include -#include -/* Defines to just reuse ifaddrs code */ -#define ifaddrs ifaddrs_pase -#define freeifaddrs Qp2freeifaddrs -#define getifaddrs Qp2getifaddrs -#endif - -#include "icall-decl.h" - -#define LOGDEBUG(...) -/* define LOGDEBUG(...) g_message(__VA_ARGS__) */ - -static gboolean -addrinfo_to_IPHostEntry_handles (MonoAddressInfo *info, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gboolean add_local_ips, MonoError *error); - -static MonoObjectHandle -create_object_handle_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error); - -static struct sockaddr* -create_sockaddr_from_handle (MonoObjectHandle saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error); - -#ifdef HOST_WIN32 - -static SOCKET -mono_w32socket_socket (int domain, int type, int protocol) -{ - SOCKET ret; - MONO_ENTER_GC_SAFE; - ret = WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = bind (sock, addr, addrlen); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = getpeername (sock, name, namelen); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = getsockname (sock, name, namelen); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = getsockopt (sock, level, optname, (char*)optval, optlen); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, gconstpointer optval, socklen_t optlen) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = setsockopt (sock, level, optname, (const char*)optval, optlen); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_listen (SOCKET sock, gint backlog) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = listen (sock, backlog); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_shutdown (SOCKET sock, gint how) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = shutdown (sock, how); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gint -mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, DWORD *written) -{ - gint ret; - MONO_ENTER_GC_SAFE; - ret = WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL); - MONO_EXIT_GC_SAFE; - return ret; -} - -static gboolean -mono_w32socket_close (SOCKET sock) -{ - gboolean ret; - MONO_ENTER_GC_SAFE; - ret = closesocket (sock); - MONO_EXIT_GC_SAFE; - return ret; -} - -#endif /* HOST_WIN32 */ - -static gint32 -convert_family (MonoAddressFamily mono_family) -{ - switch (mono_family) { - case AddressFamily_Unknown: - case AddressFamily_ImpLink: - case AddressFamily_Pup: - case AddressFamily_Chaos: - case AddressFamily_Iso: - case AddressFamily_Ecma: - case AddressFamily_DataKit: - case AddressFamily_Ccitt: - case AddressFamily_DataLink: - case AddressFamily_Lat: - case AddressFamily_HyperChannel: - case AddressFamily_NetBios: - case AddressFamily_VoiceView: - case AddressFamily_FireFox: - case AddressFamily_Banyan: - case AddressFamily_Atm: - case AddressFamily_Cluster: - case AddressFamily_Ieee12844: - case AddressFamily_NetworkDesigners: - g_warning ("System.Net.Sockets.AddressFamily has unsupported value 0x%x", mono_family); - return -1; - case AddressFamily_Unspecified: - return AF_UNSPEC; - case AddressFamily_Unix: - return AF_UNIX; - case AddressFamily_InterNetwork: - return AF_INET; - case AddressFamily_AppleTalk: -#ifdef AF_APPLETALK - return AF_APPLETALK; -#else - return -1; -#endif - case AddressFamily_InterNetworkV6: -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - return AF_INET6; -#else - return -1; -#endif - case AddressFamily_DecNet: -#ifdef AF_DECnet - return AF_DECnet; -#else - return -1; -#endif - case AddressFamily_Ipx: -#ifdef AF_IPX - return AF_IPX; -#else - return -1; -#endif - case AddressFamily_Sna: -#ifdef AF_SNA - return AF_SNA; -#else - return -1; -#endif - case AddressFamily_Irda: -#ifdef AF_IRDA - return AF_IRDA; -#else - return -1; -#endif - default: - g_warning ("System.Net.Sockets.AddressFamily has unknown value 0x%x", mono_family); - return -1; - } -} - -static MonoAddressFamily -convert_to_mono_family (guint16 af_family) -{ - switch (af_family) { - case AF_UNSPEC: - return AddressFamily_Unspecified; - case AF_UNIX: - return AddressFamily_Unix; - case AF_INET: - return AddressFamily_InterNetwork; -#ifdef AF_IPX - case AF_IPX: - return AddressFamily_Ipx; -#endif -#ifdef AF_SNA - case AF_SNA: - return AddressFamily_Sna; -#endif -#ifdef AF_DECnet - case AF_DECnet: - return AddressFamily_DecNet; -#endif -#ifdef AF_APPLETALK - case AF_APPLETALK: - return AddressFamily_AppleTalk; -#endif -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - case AF_INET6: - return AddressFamily_InterNetworkV6; -#endif -#ifdef AF_IRDA - case AF_IRDA: - return AddressFamily_Irda; -#endif - default: - g_warning ("unknown address family 0x%x", af_family); - return AddressFamily_Unknown; - } -} - -static gint32 -convert_type (MonoSocketType mono_type) -{ - switch (mono_type) { - case SocketType_Stream: - return SOCK_STREAM; - case SocketType_Dgram: - return SOCK_DGRAM; - case SocketType_Raw: - return SOCK_RAW; - case SocketType_Rdm: -#ifdef SOCK_RDM - return SOCK_RDM; -#else - return -1; -#endif - case SocketType_Seqpacket: -#ifdef SOCK_SEQPACKET - return SOCK_SEQPACKET; -#else - return -1; -#endif - case SocketType_Unknown: - g_warning ("System.Net.Sockets.SocketType has unsupported value 0x%x", mono_type); - return -1; - default: - g_warning ("System.Net.Sockets.SocketType has unknown value 0x%x", mono_type); - return -1; - } -} - -static gint32 -convert_proto (MonoProtocolType mono_proto) -{ - switch (mono_proto) { - case ProtocolType_IP: - case ProtocolType_IPv6: - case ProtocolType_Icmp: - case ProtocolType_Igmp: - case ProtocolType_Ggp: - case ProtocolType_Tcp: - case ProtocolType_Pup: - case ProtocolType_Udp: - case ProtocolType_Idp: - /* These protocols are known (on my system at least) */ - return mono_proto; - case ProtocolType_ND: - case ProtocolType_Raw: - case ProtocolType_Ipx: - case ProtocolType_Spx: - case ProtocolType_SpxII: - case ProtocolType_Unknown: - /* These protocols arent */ - g_warning ("System.Net.Sockets.ProtocolType has unsupported value 0x%x", mono_proto); - return -1; - default: - return -1; - } -} - -/* Convert MonoSocketFlags */ -static gint32 -convert_socketflags (gint32 sflags) -{ - gint32 flags = 0; - - if (!sflags) - /* SocketFlags.None */ - return 0; - - if (sflags & ~(SocketFlags_OutOfBand | SocketFlags_MaxIOVectorLength | SocketFlags_Peek | - SocketFlags_DontRoute | SocketFlags_Partial)) - /* Contains invalid flag values */ - return -1; - -#ifdef MSG_OOB - if (sflags & SocketFlags_OutOfBand) - flags |= MSG_OOB; -#endif - if (sflags & SocketFlags_Peek) - flags |= MSG_PEEK; - if (sflags & SocketFlags_DontRoute) - flags |= MSG_DONTROUTE; - - /* Ignore Partial - see bug 349688. Don't return -1, because - * according to the comment in that bug ms runtime doesn't for - * UDP sockets (this means we will silently ignore it for TCP - * too) - */ -#ifdef MSG_MORE - if (sflags & SocketFlags_Partial) - flags |= MSG_MORE; -#endif -#if 0 - /* Don't do anything for MaxIOVectorLength */ - if (sflags & SocketFlags_MaxIOVectorLength) - return -1; -#endif - return flags; -} - -/* - * Returns: - * 0 on success (mapped mono_level and mono_name to system_level and system_name - * -1 on error - * -2 on non-fatal error (ie, must ignore) - */ -static gint32 -convert_sockopt_level_and_name (MonoSocketOptionLevel mono_level, MonoSocketOptionName mono_name, int *system_level, int *system_name) -{ - switch (mono_level) { - case SocketOptionLevel_Socket: - *system_level = SOL_SOCKET; - - switch (mono_name) { - case SocketOptionName_DontLinger: - /* This is SO_LINGER, because the setsockopt - * internal call maps DontLinger to SO_LINGER - * with l_onoff=0 - */ - *system_name = SO_LINGER; - break; -#ifdef SO_DEBUG - case SocketOptionName_Debug: - *system_name = SO_DEBUG; - break; -#endif -#ifdef SO_ACCEPTCONN - case SocketOptionName_AcceptConnection: - *system_name = SO_ACCEPTCONN; - break; -#endif - case SocketOptionName_ReuseAddress: - *system_name = SO_REUSEADDR; - break; - case SocketOptionName_KeepAlive: - *system_name = SO_KEEPALIVE; - break; -#ifdef SO_DONTROUTE - case SocketOptionName_DontRoute: - *system_name = SO_DONTROUTE; - break; -#endif - case SocketOptionName_Broadcast: - *system_name = SO_BROADCAST; - break; - case SocketOptionName_Linger: - *system_name = SO_LINGER; - break; -#ifdef SO_OOBINLINE - case SocketOptionName_OutOfBandInline: - *system_name = SO_OOBINLINE; - break; -#endif - case SocketOptionName_SendBuffer: - *system_name = SO_SNDBUF; - break; - case SocketOptionName_ReceiveBuffer: - *system_name = SO_RCVBUF; - break; - case SocketOptionName_SendLowWater: - *system_name = SO_SNDLOWAT; - break; - case SocketOptionName_ReceiveLowWater: - *system_name = SO_RCVLOWAT; - break; - case SocketOptionName_SendTimeout: - *system_name = SO_SNDTIMEO; - break; - case SocketOptionName_ReceiveTimeout: - *system_name = SO_RCVTIMEO; - break; - case SocketOptionName_Error: - *system_name = SO_ERROR; - break; - case SocketOptionName_Type: - *system_name = SO_TYPE; - break; -#ifdef SO_PEERCRED - case SocketOptionName_PeerCred: - *system_name = SO_PEERCRED; - break; -#endif - case SocketOptionName_ExclusiveAddressUse: -#ifdef SO_EXCLUSIVEADDRUSE - *system_name = SO_EXCLUSIVEADDRUSE; - break; -#endif - case SocketOptionName_UseLoopback: -#ifdef SO_USELOOPBACK - *system_name = SO_USELOOPBACK; - break; -#endif - case SocketOptionName_MaxConnections: -#ifdef SO_MAXCONN - *system_name = SO_MAXCONN; - break; -#elif defined(SOMAXCONN) - *system_name = SOMAXCONN; - break; -#endif - default: - g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at Socket level", mono_name); - return -1; - } - break; - - case SocketOptionLevel_IP: - *system_level = mono_networking_get_ip_protocol (); - - switch (mono_name) { -#ifdef IP_OPTIONS - case SocketOptionName_IPOptions: - *system_name = IP_OPTIONS; - break; -#endif -#ifdef IP_HDRINCL - case SocketOptionName_HeaderIncluded: - *system_name = IP_HDRINCL; - break; -#endif -#ifdef IP_TOS - case SocketOptionName_TypeOfService: - *system_name = IP_TOS; - break; -#endif -#ifdef IP_TTL - case SocketOptionName_IpTimeToLive: - *system_name = IP_TTL; - break; -#endif - case SocketOptionName_MulticastInterface: - *system_name = IP_MULTICAST_IF; - break; - case SocketOptionName_MulticastTimeToLive: - *system_name = IP_MULTICAST_TTL; - break; - case SocketOptionName_MulticastLoopback: - *system_name = IP_MULTICAST_LOOP; - break; - case SocketOptionName_AddMembership: - *system_name = IP_ADD_MEMBERSHIP; - break; - case SocketOptionName_DropMembership: - *system_name = IP_DROP_MEMBERSHIP; - break; -#ifdef HAVE_IP_PKTINFO - case SocketOptionName_PacketInformation: - *system_name = IP_PKTINFO; - break; -#endif /* HAVE_IP_PKTINFO */ - - case SocketOptionName_DontFragment: -#ifdef HAVE_IP_DONTFRAGMENT - *system_name = IP_DONTFRAGMENT; - break; -#elif defined HAVE_IP_MTU_DISCOVER - /* Not quite the same */ - *system_name = IP_MTU_DISCOVER; - break; -#else - /* If the flag is not available on this system, we can ignore this error */ - return -2; -#endif /* HAVE_IP_DONTFRAGMENT */ - case SocketOptionName_AddSourceMembership: - case SocketOptionName_DropSourceMembership: - case SocketOptionName_BlockSource: - case SocketOptionName_UnblockSource: - /* Can't figure out how to map these, so fall - * through - */ - default: - g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IP level", mono_name); - return -1; - } - break; - - case SocketOptionLevel_IPv6: - *system_level = mono_networking_get_ipv6_protocol (); - - switch (mono_name) { - case SocketOptionName_IpTimeToLive: - case SocketOptionName_HopLimit: - *system_name = IPV6_UNICAST_HOPS; - break; - case SocketOptionName_MulticastInterface: - *system_name = IPV6_MULTICAST_IF; - break; - case SocketOptionName_MulticastTimeToLive: - *system_name = IPV6_MULTICAST_HOPS; - break; - case SocketOptionName_MulticastLoopback: - *system_name = IPV6_MULTICAST_LOOP; - break; - case SocketOptionName_AddMembership: - *system_name = IPV6_JOIN_GROUP; - break; - case SocketOptionName_DropMembership: - *system_name = IPV6_LEAVE_GROUP; - break; - case SocketOptionName_IPv6Only: -#ifdef IPV6_V6ONLY - *system_name = IPV6_V6ONLY; -#else - return -1; -#endif - break; - case SocketOptionName_PacketInformation: -#ifdef HAVE_IPV6_PKTINFO - *system_name = IPV6_PKTINFO; -#endif - break; - case SocketOptionName_HeaderIncluded: - case SocketOptionName_IPOptions: - case SocketOptionName_TypeOfService: - case SocketOptionName_DontFragment: - case SocketOptionName_AddSourceMembership: - case SocketOptionName_DropSourceMembership: - case SocketOptionName_BlockSource: - case SocketOptionName_UnblockSource: - /* Can't figure out how to map these, so fall - * through - */ - default: - g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at IPv6 level", mono_name); - return -1; - } - break; /* SocketOptionLevel_IPv6 */ - - case SocketOptionLevel_Tcp: - *system_level = mono_networking_get_tcp_protocol (); - - switch (mono_name) { - case SocketOptionName_NoDelay: - *system_name = TCP_NODELAY; - break; -#if 0 - /* The documentation is - * very vague here: rfc-1222 is titled - * 'Advancing the NSFNET Routing Architecture' - * and doesn't mention either of the words - * "expedite" or "urgent". - */ - case SocketOptionName_BsdUrgent: - case SocketOptionName_Expedited: -#endif - default: - g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at TCP level", mono_name); - return -1; - } - break; - - case SocketOptionLevel_Udp: - g_warning ("System.Net.Sockets.SocketOptionLevel has unsupported value 0x%x", mono_level); - - switch(mono_name) { - case SocketOptionName_NoChecksum: - case SocketOptionName_ChecksumCoverage: - default: - g_warning ("System.Net.Sockets.SocketOptionName 0x%x is not supported at UDP level", mono_name); - return -1; - } - return -1; - break; - - default: - g_warning ("System.Net.Sockets.SocketOptionLevel has unknown value 0x%x", mono_level); - return -1; - } - - return 0; -} - -static MonoImage* -get_socket_assembly (void) -{ - MonoDomain *domain = mono_domain_get (); - - if (domain->socket_assembly == NULL) { - MonoImage *socket_assembly; - MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain); - - socket_assembly = mono_image_loaded_internal (alc, "System", FALSE); - if (!socket_assembly) { - MonoAssemblyOpenRequest req; - mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, alc); - MonoAssembly *sa = mono_assembly_request_open ("System.dll", &req, NULL); - - if (!sa) { - g_assert_not_reached (); - } else { - socket_assembly = mono_assembly_get_image_internal (sa); - } - } - mono_atomic_store_release (&domain->socket_assembly, socket_assembly); - } - - return domain->socket_assembly; -} - -gpointer -ves_icall_System_Net_Sockets_Socket_Socket_icall (gint32 family, gint32 type, gint32 proto, gint32 *werror, MonoError *error) -{ - SOCKET sock; - gint32 sock_family; - gint32 sock_proto; - gint32 sock_type; - - error_init (error); - *werror = 0; - - sock_family = convert_family ((MonoAddressFamily)family); - if (sock_family == -1) { - *werror = WSAEAFNOSUPPORT; - return NULL; - } - - sock_proto = convert_proto ((MonoProtocolType)proto); - if (sock_proto == -1) { - *werror = WSAEPROTONOSUPPORT; - return NULL; - } - - sock_type = convert_type ((MonoSocketType)type); - if (sock_type == -1) { - *werror = WSAESOCKTNOSUPPORT; - return NULL; - } - - sock = mono_w32socket_socket (sock_family, sock_type, sock_proto); - - if (sock == INVALID_SOCKET) { - *werror = mono_w32socket_get_last_error (); - return NULL; - } - - return GUINT_TO_POINTER (sock); -} - -/* FIXME: the SOCKET parameter (here and in other functions in this - * file) is really an IntPtr which needs to be converted to a guint32. - */ -void -ves_icall_System_Net_Sockets_Socket_Close_icall (gsize sock, gint32 *werror) -{ - LOGDEBUG (g_message ("%s: closing 0x%x", __func__, sock)); - - *werror = 0; - - /* Clear any pending work item from this socket if the underlying - * polling system does not notify when the socket is closed */ - mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock)); - - mono_w32socket_close ((SOCKET) sock); -} - -gint32 -ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_icall (void) -{ - LOGDEBUG (g_message("%s: returning %d", __func__, mono_w32socket_get_last_error ())); - - return mono_w32socket_get_last_error (); -} - -gint32 -ves_icall_System_Net_Sockets_Socket_Available_icall (gsize sock, gint32 *werror) -{ - int ret; - guint64 amount; - - *werror = 0; - - /* FIXME: this might require amount to be unsigned long. */ - ret = mono_w32socket_get_available (sock, &amount); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return 0; - } - - return amount; -} - -void -ves_icall_System_Net_Sockets_Socket_Blocking_icall (gsize sock, MonoBoolean block, gint32 *werror) -{ - int ret; - - *werror = 0; - - ret = mono_w32socket_set_blocking (sock, block); - if (ret == SOCKET_ERROR) - *werror = mono_w32socket_get_last_error (); -} - -gpointer -ves_icall_System_Net_Sockets_Socket_Accept_icall (gsize sock, gint32 *werror, MonoBoolean blocking) -{ - SOCKET newsock; - - *werror = 0; - - newsock = mono_w32socket_accept (sock, NULL, 0, blocking); - if (newsock == INVALID_SOCKET) { - *werror = mono_w32socket_get_last_error (); - return NULL; - } - - return GUINT_TO_POINTER (newsock); -} - -void -ves_icall_System_Net_Sockets_Socket_Listen_icall (gsize sock, guint32 backlog, gint32 *werror) -{ - int ret; - - *werror = 0; - - ret = mono_w32socket_listen (sock, backlog); - if (ret == SOCKET_ERROR) - *werror = mono_w32socket_get_last_error (); -} - -#ifdef HAVE_STRUCT_SOCKADDR_IN6 -// Check whether it's ::ffff::0:0. -static gboolean -is_ipv4_mapped_any (const struct in6_addr *addr) -{ - int i; - - for (i = 0; i < 10; i++) { - if (addr->s6_addr [i]) - return FALSE; - } - if ((addr->s6_addr [10] != 0xff) || (addr->s6_addr [11] != 0xff)) - return FALSE; - for (i = 12; i < 16; i++) { - if (addr->s6_addr [i]) - return FALSE; - } - return TRUE; -} -#endif - -static MonoObjectHandle -create_object_handle_from_sockaddr (struct sockaddr *saddr, int sa_size, gint32 *werror, MonoError *error) -{ - MonoDomain *domain = mono_domain_get (); - MonoAddressFamily family; - - error_init (error); - - /* Build a System.Net.SocketAddress object instance */ - if (!domain->sockaddr_class) - domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress"); - MonoObjectHandle sockaddr_obj = mono_object_new_handle (domain, domain->sockaddr_class, error); - return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL)); - - /* Locate the SocketAddress data buffer in the object */ - if (!domain->sockaddr_data_field) { - domain->sockaddr_data_field = mono_class_get_field_from_name_full (domain->sockaddr_class, "m_Buffer", NULL); - g_assert (domain->sockaddr_data_field); - } - - /* Locate the SocketAddress data buffer length in the object */ - if (!domain->sockaddr_data_length_field) { - domain->sockaddr_data_length_field = mono_class_get_field_from_name_full (domain->sockaddr_class, "m_Size", NULL); - g_assert (domain->sockaddr_data_length_field); - } - - /* May be the +2 here is too conservative, as sa_len returns - * the length of the entire sockaddr_in/in6, including - * sizeof (unsigned short) of the family */ - /* We can't really avoid the +2 as all code below depends on this size - INCLUDING unix domain sockets.*/ - MonoArrayHandle data = mono_array_new_handle (domain, mono_get_byte_class (), sa_size + 2, error); - return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL)); - - /* The data buffer is laid out as follows: - * bytes 0 and 1 are the address family - * bytes 2 and 3 are the port info - * the rest is the address info - */ - - family = convert_to_mono_family (saddr->sa_family); - if (family == AddressFamily_Unknown) { - *werror = WSAEAFNOSUPPORT; - return MONO_HANDLE_NEW (MonoObject, NULL); - } - - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 0, family & 0x0FF); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 1, (family >> 8) & 0x0FF); - - if (saddr->sa_family == AF_INET) { - struct sockaddr_in *sa_in = (struct sockaddr_in *)saddr; - guint16 port = ntohs (sa_in->sin_port); - guint32 address = ntohl (sa_in->sin_addr.s_addr); - int buffer_size = 8; - - if (sa_size < buffer_size) { - mono_error_set_generic_error (error, "System", "SystemException", ""); - return MONO_HANDLE_NEW (MonoObject, NULL); - } - - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 2, (port>>8) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 3, (port) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 4, (address>>24) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 5, (address>>16) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 6, (address>>8) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 7, (address) & 0xff); - - mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_field, MONO_HANDLE_RAW (data)); /* FIXME: use handles for mono_field_set_value */ - mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_length_field, &buffer_size); /* FIXME: use handles for mono_field_set_value */ - - return sockaddr_obj; - } -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - else if (saddr->sa_family == AF_INET6) { - struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)saddr; - int i; - int buffer_size = 28; - - guint16 port = ntohs (sa_in->sin6_port); - - if (sa_size < buffer_size) { - mono_error_set_generic_error (error, "System", "SystemException", ""); - return MONO_HANDLE_NEW (MonoObject, NULL); - } - - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 2, (port>>8) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 3, (port) & 0xff); - - if (is_ipv4_mapped_any (&sa_in->sin6_addr)) { - // Map ::ffff:0:0 to :: (bug #5502) - for (i = 0; i < 16; i++) - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 8 + i, 0); - } else { - for (i = 0; i < 16; i++) { - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 8 + i, - sa_in->sin6_addr.s6_addr [i]); - } - } - - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 24, sa_in->sin6_scope_id & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 25, - (sa_in->sin6_scope_id >> 8) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 26, - (sa_in->sin6_scope_id >> 16) & 0xff); - MONO_HANDLE_ARRAY_SETVAL (data, guint8, 27, - (sa_in->sin6_scope_id >> 24) & 0xff); - - mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_field, MONO_HANDLE_RAW (data)); /* FIXME: use handles for mono_field_set_value */ - mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_length_field, &buffer_size); /* FIXME: use handles for mono_field_set_value */ - - return sockaddr_obj; - } -#endif -#ifdef HAVE_SYS_UN_H - else if (saddr->sa_family == AF_UNIX) { - int i; - int buffer_size = sa_size + 2; - - for (i = 0; i < sa_size; i++) - MONO_HANDLE_ARRAY_SETVAL (data, guint8, i + 2, saddr->sa_data [i]); - - mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_field, MONO_HANDLE_RAW (data)); /* FIXME: use handles for mono_field_set_value */ - mono_field_set_value_internal (MONO_HANDLE_RAW (sockaddr_obj), domain->sockaddr_data_length_field, &buffer_size); /* FIXME: use handles for mono_field_set_value */ - - return sockaddr_obj; - } -#endif - else { - *werror = WSAEAFNOSUPPORT; - return MONO_HANDLE_NEW (MonoObject, NULL); - } -} - -static int -get_sockaddr_size (int family) -{ - int size; - - size = 0; - if (family == AF_INET) { - size = sizeof (struct sockaddr_in); - } -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - else if (family == AF_INET6) { - size = sizeof (struct sockaddr_in6); - } -#endif -#ifdef HAVE_SYS_UN_H - else if (family == AF_UNIX) { - size = sizeof (struct sockaddr_un); - } -#endif - return size; -} - -static MonoObjectHandle -mono_w32socket_getname (gsize sock, gint32 af, gboolean local, gint32 *werror, MonoError *error) -{ - gpointer sa = NULL; - socklen_t salen = 0; - int ret; - MonoObjectHandle result = NULL_HANDLE; - - *werror = 0; - - salen = get_sockaddr_size (convert_family ((MonoAddressFamily)af)); - if (salen == 0) { - *werror = WSAEAFNOSUPPORT; - goto exit; - } - if (salen <= 128) { - sa = g_alloca (salen); - memset (sa, 0, salen); - } else { - sa = g_malloc0 (salen); - } - - /* Note: linux returns just 2 for AF_UNIX. Always. */ - ret = (local ? mono_w32socket_getsockname : mono_w32socket_getpeername) (sock, (struct sockaddr *)sa, &salen); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - goto exit; - } - - LOGDEBUG (g_message("%s: %s to %s port %d", __func__, local ? "bound" : "connected", inet_ntoa (((struct sockaddr_in *)&sa)->sin_addr), ntohs (((struct sockaddr_in *)&sa)->sin_port))); - - result = create_object_handle_from_sockaddr ((struct sockaddr *)sa, salen, werror, error); -exit: - if (salen > 128) - g_free (sa); - return result; -} - -MonoObjectHandle -ves_icall_System_Net_Sockets_Socket_LocalEndPoint_icall (gsize sock, gint32 af, gint32 *werror, MonoError *error) -{ - return mono_w32socket_getname (sock, af, TRUE, werror, error); -} - -MonoObjectHandle -ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_icall (gsize sock, gint32 af, gint32 *werror, MonoError *error) -{ - return mono_w32socket_getname (sock, af, FALSE, werror, error); -} - -static struct sockaddr* -create_sockaddr_from_handle (MonoObjectHandle saddr_obj, socklen_t *sa_size, gint32 *werror, MonoError *error) -{ - MonoDomain *domain = mono_domain_get (); - gint32 family; - int len; - - error_init (error); - - if (!domain->sockaddr_class) - domain->sockaddr_class = mono_class_load_from_name (get_socket_assembly (), "System.Net", "SocketAddress"); - - /* Locate the SocketAddress data buffer in the object */ - if (!domain->sockaddr_data_field) { - domain->sockaddr_data_field = mono_class_get_field_from_name_full (domain->sockaddr_class, "m_Buffer", NULL); - g_assert (domain->sockaddr_data_field); - } - - /* Locate the SocketAddress data buffer length in the object */ - if (!domain->sockaddr_data_length_field) { - domain->sockaddr_data_length_field = mono_class_get_field_from_name_full (domain->sockaddr_class, "m_Size", NULL); - g_assert (domain->sockaddr_data_length_field); - } - - MonoArrayHandle data = MONO_HANDLE_NEW_GET_FIELD (saddr_obj, MonoArray, domain->sockaddr_data_field); - - /* The data buffer is laid out as follows: - * byte 0 is the address family low byte - * byte 1 is the address family high byte - * INET: - * bytes 2 and 3 are the port info - * the rest is the address info - * UNIX: - * the rest is the file name - */ - len = MONO_HANDLE_GET_FIELD_VAL (saddr_obj, int, domain->sockaddr_data_length_field); - g_assert (len >= 2); - - MonoGCHandle gchandle; - guint8 *buf = MONO_ARRAY_HANDLE_PIN (data, guint8, 0, &gchandle); - family = convert_family ((MonoAddressFamily)(buf[0] + (buf[1] << 8))); - if (family == AF_INET) { - struct sockaddr_in *sa; - guint16 port; - guint32 address; - - if (len < 8) { - mono_error_set_generic_error (error, "System", "SystemException", ""); - mono_gchandle_free_internal (gchandle); - return NULL; - } - - sa = g_new0 (struct sockaddr_in, 1); - port = (buf[2] << 8) + buf[3]; - address = (buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7]; - - sa->sin_family = family; - sa->sin_addr.s_addr = htonl (address); - sa->sin_port = htons (port); - - *sa_size = sizeof (struct sockaddr_in); - mono_gchandle_free_internal (gchandle); - return (struct sockaddr *)sa; - } -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - else if (family == AF_INET6) { - struct sockaddr_in6 *sa; - int i; - guint16 port; - guint32 scopeid; - - if (len < 28) { - mono_error_set_generic_error (error, "System", "SystemException", ""); - mono_gchandle_free_internal (gchandle); - return NULL; - } - - sa = g_new0 (struct sockaddr_in6, 1); - port = buf[3] + (buf[2] << 8); - scopeid = buf[24] + (buf[25] << 8) + (buf[26] << 16) + (buf[27] << 24); - - sa->sin6_family = family; - sa->sin6_port = htons (port); - sa->sin6_scope_id = scopeid; - - for (i = 0; i < 16; i++) - sa->sin6_addr.s6_addr [i] = buf[8 + i]; - - *sa_size = sizeof (struct sockaddr_in6); - mono_gchandle_free_internal (gchandle); - return (struct sockaddr *)sa; - } -#endif -#ifdef HAVE_SYS_UN_H - else if (family == AF_UNIX) { - struct sockaddr_un *sock_un; - int i; - - /* Need a byte for the '\0' terminator/prefix, and the first - * two bytes hold the SocketAddress family - */ - if (len - 2 >= sizeof (sock_un->sun_path)) { - mono_error_set_argument_out_of_range (error, "SocketAddress.Size", "MonoArgumentException:SocketAddress.Size"); - mono_gchandle_free_internal (gchandle); - return NULL; - } - - sock_un = g_new0 (struct sockaddr_un, 1); - - sock_un->sun_family = family; - for (i = 0; i < len - 2; i++) - sock_un->sun_path [i] = buf[i + 2]; - - *sa_size = len; - mono_gchandle_free_internal (gchandle); - return (struct sockaddr *)sock_un; - } -#endif - else { - *werror = WSAEAFNOSUPPORT; - mono_gchandle_free_internal (gchandle); - return 0; - } -} - -void -ves_icall_System_Net_Sockets_Socket_Bind_icall (gsize sock, MonoObjectHandle sockaddr, gint32 *werror, MonoError *error) -{ - struct sockaddr *sa; - socklen_t sa_size; - int ret; - - error_init (error); - *werror = 0; - - sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error); - if (*werror != 0) - return; - return_if_nok (error); - - LOGDEBUG (g_message("%s: binding to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port))); - - ret = mono_w32socket_bind (sock, sa, sa_size); - - if (ret == SOCKET_ERROR) - *werror = mono_w32socket_get_last_error (); - - g_free (sa); -} - -enum { - SelectModeRead, - SelectModeWrite, - SelectModeError -}; - -MonoBoolean -ves_icall_System_Net_Sockets_Socket_Poll_icall (gsize sock, gint mode, gint timeout, gint32 *werror) -{ - MonoInternalThread *thread = mono_thread_internal_current (); - mono_pollfd *pfds; - int ret; - time_t start; - gint rtimeout; - - *werror = 0; - - pfds = g_new0 (mono_pollfd, 1); - pfds->fd = GPOINTER_TO_INT (sock); - - switch (mode) { - case SelectModeRead: - pfds->events = MONO_POLLIN; - break; - case SelectModeWrite: - pfds->events = MONO_POLLOUT; - break; - default: - pfds->events = MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL; - break; - } - - timeout = (timeout >= 0) ? (timeout / 1000) : -1; - rtimeout = timeout; - start = time (NULL); - - do { - MONO_ENTER_GC_SAFE; - - ret = mono_poll (pfds, 1, timeout); - - MONO_EXIT_GC_SAFE; - - if (timeout > 0 && ret < 0) { - int err = errno; - int sec = time (NULL) - start; - - timeout = rtimeout - sec * 1000; - if (timeout < 0) { - timeout = 0; - } - - mono_set_errno (err); - } - - if (ret == -1 && errno == EINTR) { - if (mono_thread_test_state (thread, ThreadState_AbortRequested)) { - g_free (pfds); - return FALSE; - } - - /* Suspend requested? */ - mono_thread_interruption_checkpoint_void (); - - mono_set_errno (EINTR); - } - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - *werror = mono_w32socket_convert_error (errno); - g_free (pfds); - return FALSE; - } - - g_free (pfds); - return ret != 0; -} - -void -ves_icall_System_Net_Sockets_Socket_Connect_icall (gsize sock, MonoObjectHandle sockaddr, gint32 *werror, MonoBoolean blocking, MonoError *error) -{ - struct sockaddr *sa; - socklen_t sa_size; - int ret; - - error_init (error); - *werror = 0; - - sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error); - if (*werror != 0) - return; - return_if_nok (error); - - LOGDEBUG (g_message("%s: connecting to %s port %d", __func__, inet_ntoa (((struct sockaddr_in *)sa)->sin_addr), ntohs (((struct sockaddr_in *)sa)->sin_port))); - - ret = mono_w32socket_connect (sock, sa, sa_size, blocking); - if (ret == SOCKET_ERROR) - *werror = mono_w32socket_get_last_error (); - - g_free (sa); -} - -void -ves_icall_System_Net_Sockets_Socket_Disconnect_icall (gsize sock, MonoBoolean reuse, gint32 *werror) -{ - LOGDEBUG (g_message("%s: disconnecting from socket %p (reuse %d)", __func__, sock, reuse)); - - *werror = mono_w32socket_disconnect (sock, reuse); -} - -MonoBoolean -ves_icall_System_Net_Sockets_Socket_Duplicate_icall (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle, gint32 *werror) -{ - *werror = 0; - if (!mono_w32socket_duplicate (handle, targetProcessId, duplicate_handle)) { - *werror = mono_w32error_get_last (); - return FALSE; - } - - return TRUE; -} - -gint32 -ves_icall_System_Net_Sockets_Socket_Receive_icall (gsize sock, gchar *buffer, gint32 count, gint32 flags, gint32 *werror, MonoBoolean blocking) -{ - int ret; - int recvflags = 0; - - *werror = 0; - - recvflags = convert_socketflags (flags); - if (recvflags == -1) { - *werror = WSAEOPNOTSUPP; - return 0; - } - - ret = mono_w32socket_recv (sock, buffer, count, recvflags, blocking); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return 0; - } - - return ret; -} - -gint32 -ves_icall_System_Net_Sockets_Socket_Receive_array_icall (gsize sock, WSABUF *buffers, gint32 count, gint32 flags, gint32 *werror, MonoBoolean blocking) -{ - int ret; - guint32 recv; - guint32 recvflags = 0; - - *werror = 0; - - recvflags = convert_socketflags (flags); - if (recvflags == -1) { - *werror = WSAEOPNOTSUPP; - return 0; - } - - ret = mono_w32socket_recvbuffers (sock, buffers, count, &recv, &recvflags, NULL, NULL, blocking); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return 0; - } - - return recv; -} - -gint32 -ves_icall_System_Net_Sockets_Socket_ReceiveFrom_icall (gsize sock, gchar *buffer, gint32 count, gint32 flags, MonoObjectHandleInOut sockaddr, gint32 *werror, MonoBoolean blocking, MonoError *error) -{ - int ret; - int recvflags = 0; - struct sockaddr *sa; - socklen_t sa_size; - - error_init (error); - *werror = 0; - - sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error); - if (*werror != 0) - return 0; - if (!is_ok (error)) - return 0; - - recvflags = convert_socketflags (flags); - if (recvflags == -1) { - *werror = WSAEOPNOTSUPP; - return 0; - } - - ret = mono_w32socket_recvfrom (sock, buffer, count, recvflags, sa, &sa_size, blocking); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - g_free(sa); - return 0; - } - - /* If we didn't get a socket size, then we're probably a - * connected connection-oriented socket and the stack hasn't - * returned the remote address. All we can do is return null. - */ - if (sa_size) { - MONO_HANDLE_ASSIGN (sockaddr, create_object_handle_from_sockaddr (sa, sa_size, werror, error)); - if (!is_ok (error)) { - g_free (sa); - return 0; - } - } else { - MONO_HANDLE_ASSIGN (sockaddr, MONO_HANDLE_NEW (MonoObject, NULL)); - } - - g_free (sa); - - return ret; -} - -gint32 -ves_icall_System_Net_Sockets_Socket_Send_icall (gsize sock, gchar *buffer, gint32 count, gint32 flags, gint32 *werror, MonoBoolean blocking) -{ - int ret; - int sendflags = 0; - - *werror = 0; - - LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count)); - - sendflags = convert_socketflags (flags); - if (sendflags == -1) { - *werror = WSAEOPNOTSUPP; - return 0; - } - - ret = mono_w32socket_send (sock, buffer, count, sendflags, blocking); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return 0; - } - - return ret; -} - -gint32 -ves_icall_System_Net_Sockets_Socket_Send_array_icall (gsize sock, WSABUF *buffers, gint32 count, gint32 flags, gint32 *werror, MonoBoolean blocking) -{ - int ret; - guint32 sent; - guint32 sendflags = 0; - - *werror = 0; - - sendflags = convert_socketflags (flags); - if (sendflags == -1) { - *werror = WSAEOPNOTSUPP; - return 0; - } - - ret = mono_w32socket_sendbuffers (sock, buffers, count, &sent, sendflags, NULL, NULL, blocking); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return 0; - } - - return sent; -} - -gint32 -ves_icall_System_Net_Sockets_Socket_SendTo_icall (gsize sock, gchar *buffer, gint32 count, gint32 flags, MonoObjectHandle sockaddr, gint32 *werror, MonoBoolean blocking, MonoError *error) -{ - int ret; - int sendflags = 0; - struct sockaddr *sa; - socklen_t sa_size; - - *werror = 0; - - sa = create_sockaddr_from_handle (sockaddr, &sa_size, werror, error); - if (*werror != 0 || !is_ok (error)) - return 0; - - LOGDEBUG (g_message("%s: Sending %d bytes", __func__, count)); - - sendflags = convert_socketflags (flags); - if (sendflags == -1) { - *werror = WSAEOPNOTSUPP; - g_free (sa); - return 0; - } - - ret = mono_w32socket_sendto (sock, buffer, count, sendflags, sa, sa_size, blocking); - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - g_free(sa); - return 0; - } - - g_free(sa); - return ret; -} - -static SOCKET -Socket_to_SOCKET (MonoObjectHandle sockobj) -{ - MonoClassField *field; - - field = mono_class_get_field_from_name_full (mono_handle_class (sockobj), "m_Handle", NULL); - MonoSafeHandleHandle safe_handle = MONO_HANDLE_NEW_GET_FIELD(sockobj, MonoSafeHandle, field); - - if (MONO_HANDLE_IS_NULL (safe_handle)) - return -1; - - return (SOCKET)(gsize)MONO_HANDLE_GETVAL (safe_handle, handle); -} - -#define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL) - -static gboolean -collect_pollfds_from_array (MonoArrayHandle sockets, int i, int nfds, mono_pollfd *pfds, int *idx, int *mode) -{ - HANDLE_FUNCTION_ENTER (); - gboolean result = TRUE; - MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, NULL); - MONO_HANDLE_ARRAY_GETREF (obj, sockets, i); - if (MONO_HANDLE_IS_NULL (obj)) { - (*mode)++; - goto leave; - } - - if (*idx >= nfds) { - result = FALSE; - goto leave; - } - - pfds [*idx].fd = Socket_to_SOCKET (obj); - pfds [*idx].events = (*mode == 0) ? MONO_POLLIN : (*mode == 1) ? MONO_POLLOUT : POLL_ERRORS; - (*idx)++; -leave: - HANDLE_FUNCTION_RETURN_VAL (result); -} - -static void -set_socks_array_from_pollfds (MonoArrayHandle sockets, int i, mono_pollfd *pfds, int *ret, int *mode, MonoArrayHandle socks, int *idx) -{ - HANDLE_FUNCTION_ENTER (); - mono_pollfd *pfd; - - MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, NULL); - MONO_HANDLE_ARRAY_GETREF (obj, sockets, i); - if (MONO_HANDLE_IS_NULL (obj)) { - (*mode)++; - (*idx)++; - goto leave; - } - - pfd = &pfds [i - *mode]; - if (pfd->revents == 0) - goto leave; - - (*ret)--; - if (((*mode == 0 && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0)) || - ((*mode == 1 && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0)) || - ((pfd->revents & POLL_ERRORS) != 0)) { - MONO_HANDLE_ARRAY_SETREF (socks, *idx, obj); - (*idx)++; - } -leave: - HANDLE_FUNCTION_RETURN (); -} - -void -ves_icall_System_Net_Sockets_Socket_Select_icall (MonoArrayHandleOut sockets, gint32 timeout, gint32 *werror, MonoError *error) -{ - MonoInternalThread *thread = mono_thread_internal_current (); - mono_pollfd *pfds; - int nfds, idx; - int ret; - int i, count; - int mode; - MonoClass *sock_arr_class; - time_t start; - uintptr_t socks_size; - gint32 rtimeout; - - error_init (error); - *werror = 0; - - /* *sockets -> READ, null, WRITE, null, ERROR, null */ - count = mono_array_handle_length (sockets); - nfds = count - 3; /* NULL separators */ - pfds = g_new0 (mono_pollfd, nfds); - mode = idx = 0; - for (i = 0; i < count; i++) { - if (!collect_pollfds_from_array (sockets, i, nfds, pfds, &idx, &mode)) { - /* The socket array was bogus */ - g_free (pfds); - *werror = WSAEFAULT; - return; - } - } - - timeout = (timeout >= 0) ? (timeout / 1000) : -1; - rtimeout = timeout; - start = time (NULL); - do { - MONO_ENTER_GC_SAFE; - - ret = mono_poll (pfds, nfds, timeout); - - MONO_EXIT_GC_SAFE; - - if (timeout > 0 && ret < 0) { - int err = errno; - int sec = time (NULL) - start; - - timeout = rtimeout - sec * 1000; - if (timeout < 0) - timeout = 0; - mono_set_errno (err); - } - - if (ret == -1 && errno == EINTR) { - if (mono_thread_test_state (thread, ThreadState_AbortRequested)) { - g_free (pfds); - MONO_HANDLE_ASSIGN (sockets, MONO_HANDLE_NEW (MonoObject, NULL)); - return; - } - - /* Suspend requested? */ - mono_thread_interruption_checkpoint_void (); - - mono_set_errno (EINTR); - } - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - *werror = mono_w32socket_convert_error (errno); - g_free (pfds); - return; - } - - if (ret == 0) { - g_free (pfds); - MONO_HANDLE_ASSIGN (sockets, MONO_HANDLE_NEW (MonoObject, NULL)); - return; - } - - sock_arr_class = mono_handle_class (sockets); - socks_size = ((uintptr_t)ret) + 3; /* space for the NULL delimiters */ - MonoArrayHandle socks = MONO_HANDLE_NEW (MonoArray, mono_array_new_full_checked (mono_domain_get (), sock_arr_class, &socks_size, NULL, error)); - if (!is_ok (error)) { - g_free (pfds); - return; - } - - mode = idx = 0; - for (i = 0; i < count && ret > 0; i++) { - set_socks_array_from_pollfds (sockets, i, pfds, &ret, &mode, socks, &idx); - } - - MONO_HANDLE_ASSIGN (sockets, socks); - g_free (pfds); -} - -static MonoObjectHandle -int_to_object_handle (MonoDomain *domain, int val, MonoError *error) -{ - return MONO_HANDLE_NEW (MonoObject, mono_value_box_checked (domain, mono_get_int32_class (), &val, error)); -} - -void -ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_icall (gsize sock, gint32 level, gint32 name, MonoObjectHandleOut obj_val, gint32 *werror, MonoError *error) -{ - int system_level = 0; - int system_name = 0; - int ret; - int val = 0; - socklen_t valsize = sizeof (val); - struct linger linger; - socklen_t lingersize = sizeof (linger); - int time_ms = 0; - socklen_t time_ms_size = sizeof (time_ms); -#ifdef SO_PEERCRED -# if defined(__OpenBSD__) - struct sockpeercred cred; -# else - struct ucred cred; -# endif - socklen_t credsize = sizeof (cred); -#endif - MonoDomain *domain = mono_domain_get (); - MonoClass *obj_class; - MonoClassField *field; - - error_init (error); - *werror = 0; - -#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) - if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) { - system_level = SOL_SOCKET; - system_name = SO_REUSEADDR; - ret = 0; - } else -#endif - { - ret = convert_sockopt_level_and_name ((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level, &system_name); - } - - if (ret == -1) { - *werror = WSAENOPROTOOPT; - return; - } - if (ret == -2) { - MONO_HANDLE_ASSIGN (obj_val, int_to_object_handle (domain, 0, error)); - return; - } - - /* No need to deal with MulticastOption names here, because - * you cant getsockopt AddMembership or DropMembership (the - * int getsockopt will error, causing an exception) - */ - switch (name) { - case SocketOptionName_Linger: - case SocketOptionName_DontLinger: - ret = mono_w32socket_getsockopt (sock, system_level, system_name, &linger, &lingersize); - break; - - case SocketOptionName_SendTimeout: - case SocketOptionName_ReceiveTimeout: - ret = mono_w32socket_getsockopt (sock, system_level, system_name, &time_ms, &time_ms_size); - break; - -#ifdef SO_PEERCRED - case SocketOptionName_PeerCred: - ret = mono_w32socket_getsockopt (sock, system_level, system_name, &cred, &credsize); - break; -#endif - - default: - ret = mono_w32socket_getsockopt (sock, system_level, system_name, &val, &valsize); - } - - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return; - } - - switch (name) { - case SocketOptionName_Linger: { - /* build a System.Net.Sockets.LingerOption */ - obj_class = mono_class_load_from_name (get_socket_assembly (), - "System.Net.Sockets", - "LingerOption"); - MonoObjectHandle obj = mono_object_new_handle (domain, obj_class, error); - return_if_nok (error); - - /* Locate and set the fields "bool enabled" and "int - * lingerTime" - */ - field = mono_class_get_field_from_name_full (obj_class, "enabled", NULL); - MONO_HANDLE_SET_FIELD_VAL (obj, guint8, field, linger.l_onoff); - - field = mono_class_get_field_from_name_full (obj_class, "lingerTime", NULL); - MONO_HANDLE_SET_FIELD_VAL (obj, guint32, field, linger.l_linger); - - MONO_HANDLE_ASSIGN (obj_val, obj); - break; - } - case SocketOptionName_DontLinger: { - /* construct a bool int in val - true if linger is off */ - MonoObjectHandle obj = int_to_object_handle (domain, !linger.l_onoff, error); - return_if_nok (error); - - MONO_HANDLE_ASSIGN (obj_val, obj); - break; - } - case SocketOptionName_SendTimeout: - case SocketOptionName_ReceiveTimeout: { - MonoObjectHandle obj = int_to_object_handle (domain, time_ms, error); - return_if_nok (error); - - MONO_HANDLE_ASSIGN (obj_val, obj); - break; - } - -#ifdef SO_PEERCRED - case SocketOptionName_PeerCred: { - /* - * build a Mono.Posix.PeerCred+PeerCredData if - * possible - */ - static MonoImage *mono_posix_image = NULL; - - if (mono_posix_image == NULL) { - MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain); - mono_posix_image = mono_image_loaded_internal (alc, "Mono.Posix", FALSE); - if (!mono_posix_image) { - MonoAssemblyOpenRequest req; - mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, alc); - MonoAssembly *sa = mono_assembly_request_open ("Mono.Posix.dll", &req, NULL); - if (!sa) { - *werror = WSAENOPROTOOPT; - return; - } else { - mono_posix_image = mono_assembly_get_image_internal (sa); - } - } - } - - obj_class = mono_class_load_from_name (mono_posix_image, - "Mono.Posix", - "PeerCredData"); - MonoPeerCredDataHandle cred_data = MONO_HANDLE_CAST (MonoPeerCredData, mono_object_new_handle (domain, obj_class, error)); - return_if_nok (error); - - MONO_HANDLE_SETVAL (cred_data, pid, gint, cred.pid); - MONO_HANDLE_SETVAL (cred_data, uid, gint, cred.uid); - MONO_HANDLE_SETVAL (cred_data, gid, gint, cred.gid); - - MONO_HANDLE_ASSIGN (obj_val, cred_data); - break; - } -#endif - - default: { -#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) - if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) - val = val ? 0 : 1; -#endif - MonoObjectHandle obj = int_to_object_handle (domain, val, error); - return_if_nok (error); - - MONO_HANDLE_ASSIGN (obj_val, obj); - } - } -} -void -ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_icall (gsize sock, gint32 level, gint32 name, MonoArrayHandle byte_val, gint32 *werror, MonoError *error) -{ - int system_level = 0; - int system_name = 0; - int ret; - socklen_t valsize; - - error_init (error); - *werror = 0; - - ret = convert_sockopt_level_and_name((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level, - &system_name); - if (ret == -1) { - *werror = WSAENOPROTOOPT; - return; - } - if (ret == -2) - return; - - valsize = mono_array_handle_length (byte_val); - - MonoGCHandle gchandle; - guchar *buf = MONO_ARRAY_HANDLE_PIN (byte_val, guchar, 0, &gchandle); - - ret = mono_w32socket_getsockopt (sock, system_level, system_name, buf, &valsize); - - mono_gchandle_free_internal (gchandle); - - if (ret == SOCKET_ERROR) - *werror = mono_w32socket_get_last_error (); -} - -#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ) -static struct in_addr -ipaddress_handle_to_struct_in_addr (MonoObjectHandle ipaddr) -{ - struct in_addr inaddr; - MonoClassField *field; - - field = mono_class_get_field_from_name_full (mono_handle_class (ipaddr), "_addressOrScopeId", NULL); - g_assert (field); - - /* No idea why .net uses a 64bit type to hold a 32bit value... - * - * Internal value of IPAddess is in little-endian order - */ - inaddr.s_addr = GUINT_FROM_LE ((guint32)MONO_HANDLE_GET_FIELD_VAL (ipaddr, guint32, field)); - - return inaddr; -} - -#ifdef HAVE_STRUCT_SOCKADDR_IN6 -static struct in6_addr -ipaddress_handle_to_struct_in6_addr (MonoObjectHandle ipaddr) -{ - struct in6_addr in6addr; - MonoClassField *field; - int i; - - field = mono_class_get_field_from_name_full (mono_handle_class (ipaddr), "_numbers", NULL); - g_assert (field); - MonoArrayHandle data = MONO_HANDLE_NEW_GET_FIELD (ipaddr, MonoArray, field); - - for (i = 0; i < 8; i++) { - guint16 v; - MONO_HANDLE_ARRAY_GETVAL (v, data, guint16, i); - const guint16 s = GUINT16_TO_BE (v); - -/* Solaris/MacOS have only the 8 bit version. */ -#ifndef s6_addr16 - in6addr.s6_addr[2 * i + 1] = (s >> 8) & 0xff; - in6addr.s6_addr[2 * i] = s & 0xff; -#else - in6addr.s6_addr16[i] = s; -#endif - } - return in6addr; -} -#endif -#endif - -#ifdef HAVE_STRUCT_SOCKADDR_IN6 -#if defined(__APPLE__) || defined(__FreeBSD__) -static int -get_local_interface_id (int family) -{ -#if !(defined(HAVE_GETIFADDRS) || defined(HAVE_QP2GETIFADDRS)) || !defined(HAVE_IF_NAMETOINDEX) - return 0; -#else - struct ifaddrs *ifap = NULL, *ptr; - int idx = 0; - - if (getifaddrs (&ifap)) - return 0; - - for (ptr = ifap; ptr; ptr = ptr->ifa_next) { - if (!ptr->ifa_addr || !ptr->ifa_name) - continue; - if (ptr->ifa_addr->sa_family != family) - continue; - if ((ptr->ifa_flags & IFF_LOOPBACK) != 0) - continue; - if ((ptr->ifa_flags & IFF_MULTICAST) == 0) - continue; - - idx = if_nametoindex (ptr->ifa_name); - break; - } - - freeifaddrs (ifap); - return idx; -#endif -} -#endif /* defined(__APPLE__) || defined(__FreeBSD__) */ -#endif /* HAVE_STRUCT_SOCKADDR_IN6 */ - -void -ves_icall_System_Net_Sockets_Socket_SetSocketOption_icall (gsize sock, gint32 level, gint32 name, MonoObjectHandle obj_val, MonoArrayHandle byte_val, gint32 int_val, gint32 *werror, MonoError *error) -{ - struct linger linger; - int system_level = 0; - int system_name = 0; - int ret; - int sol_ip; - int sol_ipv6; - - error_init (error); - *werror = 0; - - sol_ipv6 = mono_networking_get_ipv6_protocol (); - sol_ip = mono_networking_get_ip_protocol (); - - ret = convert_sockopt_level_and_name ((MonoSocketOptionLevel)level, (MonoSocketOptionName)name, &system_level, - &system_name); - -#if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) - if (level == SocketOptionLevel_Socket && name == SocketOptionName_ExclusiveAddressUse) { - system_name = SO_REUSEADDR; - int_val = int_val ? 0 : 1; - ret = 0; - } -#endif - - if (ret == -1) { - *werror = WSAENOPROTOOPT; - return; - } - if (ret == -2) - return; - - /* Only one of obj_val, byte_val or int_val has data */ - if (!MONO_HANDLE_IS_NULL (obj_val)) { - MonoClass *obj_class = mono_handle_class (obj_val); - MonoClassField *field; - int valsize; - - switch (name) { - case SocketOptionName_Linger: - /* Dig out "bool enabled" and "int lingerTime" - * fields - */ - field = mono_class_get_field_from_name_full (obj_class, "enabled", NULL); - linger.l_onoff = MONO_HANDLE_GET_FIELD_VAL (obj_val, guint8, field); - field = mono_class_get_field_from_name_full (obj_class, "lingerTime", NULL); - linger.l_linger = MONO_HANDLE_GET_FIELD_VAL (obj_val, guint32, field); - - valsize = sizeof (linger); - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, valsize); - break; - case SocketOptionName_AddMembership: - case SocketOptionName_DropMembership: -#if defined(HAVE_STRUCT_IP_MREQN) || defined(HAVE_STRUCT_IP_MREQ) - { - MonoObjectHandle address = MONO_HANDLE_NEW (MonoObject, NULL); -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - if (system_level == sol_ipv6) { - struct ipv6_mreq mreq6; - - /* - * Get group address - */ - field = mono_class_get_field_from_name_full (obj_class, "m_Group", NULL); - g_assert (field); - MONO_HANDLE_ASSIGN (address, MONO_HANDLE_NEW_GET_FIELD (obj_val, MonoObject, field)); - - if (!MONO_HANDLE_IS_NULL (address)) - mreq6.ipv6mr_multiaddr = ipaddress_handle_to_struct_in6_addr (address); - - field = mono_class_get_field_from_name_full (obj_class, "m_Interface", NULL); - mreq6.ipv6mr_interface = MONO_HANDLE_GET_FIELD_VAL (obj_val, guint64, field); - -#if defined(__APPLE__) || defined(__FreeBSD__) - /* - * Bug #5504: - * - * Mac OS Lion doesn't allow ipv6mr_interface = 0. - * - * Tests on Windows and Linux show that the multicast group is only - * joined on one NIC when interface = 0, so we simply use the interface - * id from the first non-loopback interface (this is also what - * Dns.GetHostName (string.Empty) would return). - */ - if (!mreq6.ipv6mr_interface) - mreq6.ipv6mr_interface = get_local_interface_id (AF_INET6); -#endif - - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq6, sizeof (mreq6)); - - break; // Don't check sol_ip - } -#endif - if (system_level == sol_ip) { -#ifdef HAVE_STRUCT_IP_MREQN - struct ip_mreqn mreq = {{0}}; -#else - struct ip_mreq mreq = {{0}}; -#endif /* HAVE_STRUCT_IP_MREQN */ - - /* - * pain! MulticastOption holds two IPAddress - * members, so I have to dig the value out of - * those :-( - */ - field = mono_class_get_field_from_name_full (obj_class, "group", NULL); - MONO_HANDLE_ASSIGN (address, MONO_HANDLE_NEW_GET_FIELD (obj_val, MonoObject, field)); - - /* address might not be defined and if so, set the address to ADDR_ANY. - */ - if (!MONO_HANDLE_IS_NULL (address)) - mreq.imr_multiaddr = ipaddress_handle_to_struct_in_addr (address); - - field = mono_class_get_field_from_name_full (obj_class, "localAddress", NULL); - MONO_HANDLE_ASSIGN (address, MONO_HANDLE_NEW_GET_FIELD (obj_val, MonoObject, field)); - -#ifdef HAVE_STRUCT_IP_MREQN - if (!MONO_HANDLE_IS_NULL (address)) - mreq.imr_address = ipaddress_handle_to_struct_in_addr (address); - - field = mono_class_get_field_from_name_full (obj_class, "ifIndex", NULL); - mreq.imr_ifindex = MONO_HANDLE_GET_FIELD_VAL (obj_val, gint32, field); -#else - if (!MONO_HANDLE_IS_NULL (address)) - mreq.imr_interface = ipaddress_handle_to_struct_in_addr (address); -#endif /* HAVE_STRUCT_IP_MREQN */ - - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq, sizeof (mreq)); - } - break; - } -#endif /* HAVE_STRUCT_IP_MREQN || HAVE_STRUCT_IP_MREQ */ - default: - /* Cause an exception to be thrown */ - *werror = WSAEINVAL; - return; - } - } else if (!MONO_HANDLE_IS_NULL (byte_val)) { - int valsize = mono_array_handle_length (byte_val); - MonoGCHandle gchandle; - guchar *buf = MONO_ARRAY_HANDLE_PIN (byte_val, guchar, 0, &gchandle); - - switch(name) { - case SocketOptionName_DontLinger: - if (valsize == 1) { - linger.l_onoff = (*buf) ? 0 : 1; - linger.l_linger = 0; - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, sizeof (linger)); - } else { - *werror = WSAEINVAL; - } - break; - default: - ret = mono_w32socket_setsockopt (sock, system_level, system_name, buf, valsize); - break; - } - mono_gchandle_free_internal (gchandle); - } else { - /* ReceiveTimeout/SendTimeout get here */ - switch (name) { - case SocketOptionName_DontLinger: - linger.l_onoff = !int_val; - linger.l_linger = 0; - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &linger, sizeof (linger)); - break; - case SocketOptionName_MulticastInterface: -#ifndef HOST_WIN32 -#ifdef HAVE_STRUCT_IP_MREQN - int_val = GUINT32_FROM_BE (int_val); - if ((int_val & 0xff000000) == 0) { - /* int_val is interface index */ - struct ip_mreqn mreq = {{0}}; - mreq.imr_ifindex = int_val; - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &mreq, sizeof (mreq)); - break; - } - int_val = GUINT32_TO_BE (int_val); -#endif /* HAVE_STRUCT_IP_MREQN */ -#endif /* HOST_WIN32 */ - /* int_val is in_addr */ - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &int_val, sizeof (int_val)); - break; - case SocketOptionName_DontFragment: -#ifdef HAVE_IP_MTU_DISCOVER - /* Fiddle with the value slightly if we're - * turning DF on - */ - if (int_val == 1) - int_val = IP_PMTUDISC_DO; - /* Fall through */ -#endif - - default: - ret = mono_w32socket_setsockopt (sock, system_level, system_name, &int_val, sizeof (int_val)); - } - } - - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - -#ifdef HAVE_IP_MTU_DISCOVER - if (system_name == IP_MTU_DISCOVER) { - switch (system_level) { - case IP_PMTUDISC_DONT: - case IP_PMTUDISC_WANT: - case IP_PMTUDISC_DO: -#ifdef IP_PMTUDISC_PROBE - case IP_PMTUDISC_PROBE: -#endif -#ifdef IP_PMTUDISC_INTERFACE - case IP_PMTUDISC_INTERFACE: -#endif -#ifdef IP_PMTUDISC_OMIT - case IP_PMTUDISC_OMIT: -#endif - /* - * This happens if HAVE_IP_MTU_DISCOVER is set but the OS - * doesn't actually understand it. The only OS that this is - * known to happen on currently is Windows Subsystem for Linux - * (newer versions have been fixed to recognize it). Just - * pretend everything is fine. - */ - ret = 0; - *werror = 0; - break; - default: - break; - } - } -#endif - } -} - -void -ves_icall_System_Net_Sockets_Socket_Shutdown_icall (gsize sock, gint32 how, gint32 *werror) -{ - int ret; - - *werror = 0; - - /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */ - ret = mono_w32socket_shutdown (sock, how); - if (ret == SOCKET_ERROR) - *werror = mono_w32socket_get_last_error (); -} - -gint -ves_icall_System_Net_Sockets_Socket_IOControl_icall (gsize sock, gint32 code, MonoArrayHandle input, MonoArrayHandle output, gint32 *werror, MonoError *error) -{ -#ifdef HOST_WIN32 - DWORD output_bytes = 0; -#else - glong output_bytes = 0; -#endif - gchar *i_buffer, *o_buffer; - gint i_len, o_len; - MonoGCHandle i_gchandle = 0; - MonoGCHandle o_gchandle = 0; - gint ret; - - error_init (error); - *werror = 0; - - if ((guint32)code == FIONBIO) - /* Invalid command. Must use Socket.Blocking */ - return -1; - - if (MONO_HANDLE_IS_NULL (input)) { - i_buffer = NULL; - i_len = 0; - i_gchandle = 0; - } else { - i_len = mono_array_handle_length (input); - i_buffer = MONO_ARRAY_HANDLE_PIN (input, gchar, 0, &i_gchandle); - } - - if (MONO_HANDLE_IS_NULL (output)) { - o_buffer = NULL; - o_len = 0; - o_gchandle = 0; - } else { - o_len = mono_array_handle_length (output); - o_buffer = MONO_ARRAY_HANDLE_PIN (output, gchar, 0, &o_gchandle); - } - - ret = mono_w32socket_ioctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes); - - mono_gchandle_free_internal (i_gchandle); - mono_gchandle_free_internal (o_gchandle); - - if (ret == SOCKET_ERROR) { - *werror = mono_w32socket_get_last_error (); - return -1; - } - - return (gint)output_bytes; -} - -static gboolean -addrinfo_add_string (MonoDomain *domain, const char *s, MonoArrayHandle arr, int index, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - error_init (error); - MonoStringHandle str = mono_string_new_handle (domain, s, error); - goto_if_nok (error, leave); - MONO_HANDLE_ARRAY_SETREF (arr, index, str); -leave: - HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); - -} - -static int -addrinfo_add_local_ips (MonoDomain *domain, MonoArrayHandleOut h_addr_list, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - struct in_addr *local_in = NULL; - int nlocal_in = 0; - struct in6_addr *local_in6 = NULL; - int nlocal_in6 = 0; - int addr_index = 0; - - error_init (error); - local_in = (struct in_addr *) mono_get_local_interfaces (AF_INET, &nlocal_in); - local_in6 = (struct in6_addr *) mono_get_local_interfaces (AF_INET6, &nlocal_in6); - if (nlocal_in || nlocal_in6) { - char addr [INET6_ADDRSTRLEN]; - MONO_HANDLE_ASSIGN (h_addr_list, mono_array_new_handle (domain, mono_get_string_class (), nlocal_in + nlocal_in6, error)); - goto_if_nok (error, leave); - - if (nlocal_in) { - int i; - - for (i = 0; i < nlocal_in; i++) { - MonoAddress maddr; - mono_address_init (&maddr, AF_INET, &local_in [i]); - if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) { - if (!addrinfo_add_string (domain, addr, h_addr_list, addr_index, error)) - goto leave; - addr_index++; - } - } - } -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - if (nlocal_in6) { - int i; - - for (i = 0; i < nlocal_in6; i++) { - MonoAddress maddr; - mono_address_init (&maddr, AF_INET6, &local_in6 [i]); - if (mono_networking_addr_to_str (&maddr, addr, sizeof (addr))) { - if (!addrinfo_add_string (domain, addr, h_addr_list, addr_index, error)) - goto leave; - addr_index++; - } - } - } -#endif - } - -leave: - g_free (local_in); - g_free (local_in6); - HANDLE_FUNCTION_RETURN_VAL (addr_index); -} - -static gboolean -addrinfo_to_IPHostEntry_handles (MonoAddressInfo *info, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gboolean add_local_ips, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - MonoAddressEntry *ai = NULL; - MonoDomain *domain = mono_domain_get (); - - error_init (error); - MONO_HANDLE_ASSIGN (h_aliases, mono_array_new_handle (domain, mono_get_string_class (), 0, error)); - goto_if_nok (error, leave); - if (add_local_ips) { - int addr_index = addrinfo_add_local_ips (domain, h_addr_list, error); - goto_if_nok (error, leave); - if (addr_index > 0) - goto leave; - } - - gint32 count; - count = 0; - for (ai = info->entries; ai != NULL; ai = ai->next) { - if (ai->family != AF_INET && ai->family != AF_INET6) - continue; - count++; - } - - int addr_index; - addr_index = 0; - MONO_HANDLE_ASSIGN (h_addr_list, mono_array_new_handle (domain, mono_get_string_class (), count, error)); - goto_if_nok (error, leave); - - gboolean name_assigned; - name_assigned = FALSE; - for (ai = info->entries; ai != NULL; ai = ai->next) { - MonoAddress maddr; - char buffer [INET6_ADDRSTRLEN]; /* Max. size for IPv6 */ - - if ((ai->family != PF_INET) && (ai->family != PF_INET6)) - continue; - - mono_address_init (&maddr, ai->family, &ai->address); - const char *addr = NULL; - if (mono_networking_addr_to_str (&maddr, buffer, sizeof (buffer))) - addr = buffer; - else - addr = ""; - if (!addrinfo_add_string (domain, addr, h_addr_list, addr_index, error)) - goto leave; - - if (!name_assigned) { - name_assigned = TRUE; - const char *name = ai->canonical_name != NULL ? ai->canonical_name : buffer; - MONO_HANDLE_ASSIGN (h_name, mono_string_new_handle (domain, name, error)); - goto_if_nok (error, leave); - } - - addr_index++; - } - -leave: - if (info) - mono_free_address_info (info); - - HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); -} - -MonoBoolean -ves_icall_System_Net_Dns_GetHostByName (MonoStringHandle host, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gint32 hint, MonoError *error) -{ - gboolean add_local_ips = FALSE, add_info_ok = TRUE; - gchar this_hostname [256]; - MonoAddressInfo *info = NULL; - - error_init (error); - - char *hostname = mono_string_handle_to_utf8 (host, error); - return_val_if_nok (error, FALSE); - - if (*hostname == '\0') { - add_local_ips = TRUE; - MONO_HANDLE_ASSIGN (h_name, host); - } - - if (!add_local_ips && gethostname (this_hostname, sizeof (this_hostname)) != -1) { - if (!strcmp (hostname, this_hostname)) { - add_local_ips = TRUE; - MONO_HANDLE_ASSIGN (h_name, host); - } - } - -#ifdef HOST_WIN32 - // Win32 APIs already returns local interface addresses for empty hostname ("") - // so we never want to add them manually. - add_local_ips = FALSE; - if (mono_get_address_info(hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info)) - add_info_ok = FALSE; -#else - if (*hostname && mono_get_address_info (hostname, 0, MONO_HINT_CANONICAL_NAME | hint, &info)) - add_info_ok = FALSE; -#endif - - g_free(hostname); - - if (add_info_ok) { - MonoBoolean result = addrinfo_to_IPHostEntry_handles (info, h_name, h_aliases, h_addr_list, add_local_ips, error); - return result; - } - return FALSE; -} - -MonoBoolean -ves_icall_System_Net_Dns_GetHostByAddr (MonoStringHandle addr, MonoStringHandleOut h_name, MonoArrayHandleOut h_aliases, MonoArrayHandleOut h_addr_list, gint32 hint, MonoError *error) -{ - char *address; - struct sockaddr_in saddr; -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - struct sockaddr_in6 saddr6; -#endif - MonoAddressInfo *info = NULL; - gint32 family; - gchar hostname [NI_MAXHOST] = { 0 }; - gboolean ret; - - error_init (error); - - address = mono_string_handle_to_utf8 (addr, error); - return_val_if_nok (error, FALSE); - - if (inet_pton (AF_INET, address, &saddr.sin_addr ) == 1) { - family = AF_INET; - saddr.sin_family = AF_INET; - } -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - else if (inet_pton (AF_INET6, address, &saddr6.sin6_addr) == 1) { - family = AF_INET6; - saddr6.sin6_family = AF_INET6; - } -#endif - else { - g_free (address); - return FALSE; - } - - g_free (address); - - switch (family) { - case AF_INET: { -#if HAVE_SOCKADDR_IN_SIN_LEN - saddr.sin_len = sizeof (saddr); -#endif - MONO_ENTER_GC_SAFE; - ret = getnameinfo ((struct sockaddr*)&saddr, sizeof (saddr), hostname, sizeof (hostname), NULL, 0, 0) == 0; - MONO_EXIT_GC_SAFE; - break; - } -#ifdef HAVE_STRUCT_SOCKADDR_IN6 - case AF_INET6: { -#if HAVE_SOCKADDR_IN6_SIN_LEN - saddr6.sin6_len = sizeof (saddr6); -#endif - MONO_ENTER_GC_SAFE; - ret = getnameinfo ((struct sockaddr*)&saddr6, sizeof (saddr6), hostname, sizeof (hostname), NULL, 0, 0) == 0; - MONO_EXIT_GC_SAFE; - break; - } -#endif - default: - g_assert_not_reached (); - } - - if (!ret) - return FALSE; - - if (mono_get_address_info (hostname, 0, hint | MONO_HINT_CANONICAL_NAME | MONO_HINT_CONFIGURED_ONLY, &info) != 0) - return FALSE; - - MonoBoolean result = addrinfo_to_IPHostEntry_handles (info, h_name, h_aliases, h_addr_list, FALSE, error); - return result; -} - -MonoBoolean -ves_icall_System_Net_Dns_GetHostName (MonoStringHandleOut h_name, MonoError *error) -{ - gchar hostname [NI_MAXHOST] = { 0 }; - int ret; - - error_init (error); - MONO_ENTER_GC_SAFE; - ret = gethostname (hostname, sizeof (hostname)); - MONO_EXIT_GC_SAFE; - if (ret == -1) - return FALSE; - - MONO_HANDLE_ASSIGN (h_name, mono_string_new_handle (mono_domain_get (), hostname, error)); - return TRUE; -} - -MonoBoolean -ves_icall_System_Net_Sockets_Socket_SendFile_icall (gsize sock, MonoStringHandle filename, MonoArrayHandle pre_buffer, MonoArrayHandle post_buffer, gint flags, gint32 *werror, MonoBoolean blocking, MonoError *error) -{ - HANDLE file; - gboolean ret; - TRANSMIT_FILE_BUFFERS buffers; - MonoGCHandle pre_buffer_gchandle = 0; - MonoGCHandle post_buffer_gchandle = 0; - - error_init (error); - *werror = 0; - - if (MONO_HANDLE_IS_NULL (filename)) - return FALSE; - - /* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */ - - MonoGCHandle filename_gchandle; - gunichar2 *filename_chars = mono_string_handle_pin_chars (filename, &filename_gchandle); - file = mono_w32file_create (filename_chars, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0); - mono_gchandle_free_internal (filename_gchandle); - if (file == INVALID_HANDLE_VALUE) { - *werror = mono_w32error_get_last (); - return FALSE; - } - - memset (&buffers, 0, sizeof (buffers)); - if (!MONO_HANDLE_IS_NULL (pre_buffer)) { - buffers.Head = MONO_ARRAY_HANDLE_PIN (pre_buffer, guchar, 0, &pre_buffer_gchandle); - buffers.HeadLength = mono_array_handle_length (pre_buffer); - } - if (!MONO_HANDLE_IS_NULL (post_buffer)) { - buffers.Tail = MONO_ARRAY_HANDLE_PIN (post_buffer, guchar, 0, &post_buffer_gchandle); - buffers.TailLength = mono_array_handle_length (post_buffer); - } - - ret = mono_w32socket_transmit_file (sock, file, &buffers, flags, blocking); - - if (pre_buffer_gchandle) - mono_gchandle_free_internal (pre_buffer_gchandle); - if (post_buffer_gchandle) - mono_gchandle_free_internal (post_buffer_gchandle); - - if (!ret) - *werror = mono_w32socket_get_last_error (); - - mono_w32file_close (file); - - if (*werror) - return FALSE; - - return ret; -} - -void -mono_network_init (void) -{ - mono_networking_init (); - mono_w32socket_initialize (); -} - -void -mono_network_cleanup (void) -{ - mono_w32socket_cleanup (); - mono_networking_shutdown (); -} - -void -ves_icall_cancel_blocking_socket_operation (MonoThreadObjectHandle thread, MonoError *error) -{ - error_init (error); - MonoInternalThreadHandle internal = MONO_HANDLE_NEW_GET (MonoInternalThread, thread, internal_thread); - g_assert (!MONO_HANDLE_IS_NULL (internal)); - - guint64 tid = mono_internal_thread_handle_ptr (internal)->tid; - mono_thread_info_abort_socket_syscall_for_close (MONO_UINT_TO_NATIVE_THREAD_ID (tid)); -} - -#else - -void -mono_network_init (void) -{ -} - -void -mono_network_cleanup (void) -{ -} - -#endif // !defined(DISABLE_SOCKETS) && !defined(ENABLE_NETCORE) diff --git a/src/mono/mono/metadata/w32socket.h b/src/mono/mono/metadata/w32socket.h index 99ede9a..45a6c33 100644 --- a/src/mono/mono/metadata/w32socket.h +++ b/src/mono/mono/metadata/w32socket.h @@ -178,10 +178,4 @@ ICALL_EXPORT gint32 ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_icall (void); -void -mono_network_init(void); - -void -mono_network_cleanup(void); - #endif /* _MONO_METADATA_W32SOCKET_H_ */ diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 7473ceb..a88d31e 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -124,8 +124,6 @@ set(mini_common_sources branch-opts.c mini-generic-sharing.c simd-methods.h - tasklets.c - tasklets.h simd-intrinsics.c mini-native-types.c mini-unwind.h @@ -157,7 +155,6 @@ set(mini_common_sources mini-runtime.h llvmonly-runtime.h llvmonly-runtime.c - simd-intrinsics-netcore.c monovm.h monovm.c) diff --git a/src/mono/mono/mini/alias-analysis.c b/src/mono/mono/mini/alias-analysis.c index ea596ff..522e62d 100644 --- a/src/mono/mono/mini/alias-analysis.c +++ b/src/mono/mono/mini/alias-analysis.c @@ -311,11 +311,10 @@ handle_instruction: } g_hash_table_destroy (addr_loads); -#ifdef ENABLE_NETCORE /* There could be ldaddr instructions which already got eliminated */ if (COMPILE_LLVM (cfg)) return TRUE; -#endif + return needs_dce; } diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index e384ef6..741d5eb 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5090,7 +5090,6 @@ MONO_RESTORE_WARNING g_hash_table_insert (acfg->export_names, wrapper, export_name); } -#ifdef ENABLE_NETCORE for (j = 0; j < cattr->num_attrs; ++j) if (cattr->attrs [j].ctor && mono_is_corlib_image (m_class_get_image (cattr->attrs [j].ctor->klass)) && !strcmp (m_class_get_name (cattr->attrs [j].ctor->klass), "UnmanagedCallersOnlyAttribute")) break; @@ -5132,7 +5131,6 @@ MONO_RESTORE_WARNING if (export_name) g_hash_table_insert (acfg->export_names, wrapper, export_name); } -#endif g_free (cattr); } @@ -5424,24 +5422,6 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, else name_prefix = g_strdup_printf ("%s.%s", klass_name_space, klass_name); -#ifndef ENABLE_NETCORE - /* Add the T[]/InternalEnumerator class */ - if (!strcmp (klass_name, "IEnumerable`1") || !strcmp (klass_name, "IEnumerator`1")) { - ERROR_DECL (error); - MonoClass *nclass; - - iter = NULL; - while ((nclass = mono_class_get_nested_types (m_class_get_parent (array_class), &iter))) { - if (!strcmp (m_class_get_name (nclass), "InternalEnumerator`1")) - break; - } - g_assert (nclass); - nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (mono_class_get_generic_class (klass)), error); - mono_error_assert_ok (error); /* FIXME don't swallow the error */ - add_generic_class (acfg, nclass, FALSE, "ICollection"); - } -#endif - iter = NULL; while ((method = mono_class_get_methods (array_class, &iter))) { if (!strncmp (method->name, name_prefix, strlen (name_prefix))) { @@ -5801,24 +5781,6 @@ add_generic_instances (MonoAotCompile *acfg) insts [ninsts ++] = byte_type; enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); - -#ifndef ENABLE_NETCORE - ninsts = 0; - insts [ninsts ++] = int16_type; - enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "ShortEnumEqualityComparer`1"); - add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); - - ninsts = 0; - insts [ninsts ++] = sbyte_type; - enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "SByteEnumEqualityComparer`1"); - add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); - - enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "LongEnumEqualityComparer`1"); - ninsts = 0; - insts [ninsts ++] = int64_type; - insts [ninsts ++] = uint64_type; - add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); -#endif } /* Add instances of the array generic interfaces for primitive types */ diff --git a/src/mono/mono/mini/debugger-agent.c b/src/mono/mono/mini/debugger-agent.c index b8ef608..61eddf9 100644 --- a/src/mono/mono/mini/debugger-agent.c +++ b/src/mono/mono/mini/debugger-agent.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #include #include @@ -2439,11 +2438,6 @@ suspend_vm (void) */ tp_suspend = TRUE; mono_loader_unlock (); - -#ifndef ENABLE_NETCORE - if (tp_suspend) - mono_threadpool_suspend (); -#endif } /* @@ -2482,11 +2476,6 @@ resume_vm (void) if (suspend_count == 0) tp_resume = TRUE; mono_loader_unlock (); - -#ifndef ENABLE_NETCORE - if (tp_resume) - mono_threadpool_resume (); -#endif } /* @@ -6671,11 +6660,6 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) mono_environment_exitcode_set (exit_code); - /* Suspend all managed threads since the runtime is going away */ -#ifndef ENABLE_NETCORE - PRINT_DEBUG_MSG (1, "Suspending all threads...\n"); - mono_thread_suspend_all_other_threads (); -#endif PRINT_DEBUG_MSG (1, "Shutting down the runtime...\n"); mono_runtime_quit_internal (); transport_close2 (); diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index 472df6f..b67d710 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -202,9 +202,7 @@ static gboolean parse_debug_options (const char* p) { MonoDebugOptions *opt = mini_get_debug_options (); -#ifdef ENABLE_NETCORE opt->enabled = TRUE; -#endif do { if (!*p) { @@ -221,11 +219,9 @@ parse_debug_options (const char* p) } else if (!strncmp (p, "gdb", 3)) { opt->gdb = TRUE; p += 3; -#ifdef ENABLE_NETCORE } else if (!strncmp (p, "ignore", 6)) { opt->enabled = FALSE; p += 6; -#endif } else { fprintf (stderr, "Invalid debug option `%s', use --help-debug for details\n", p); return FALSE; @@ -1620,12 +1616,8 @@ mini_usage (void) "\n" "Development:\n" " --aot[=] Compiles the assembly to native code\n" -#ifdef ENABLE_NETCORE " --debug=ignore Disable debugging support (on by default)\n" " --debug=[] Disable debugging support or enable debugging extras, use --help-debug for details\n" -#else - " --debug[=] Enable debugging support, use --help-debug for details\n" -#endif " --debugger-agent=options Enable the debugger agent\n" " --profile[=profiler] Runs in profiling mode with the specified profiler module\n" " --trace[=EXPR] Enable tracing, use --help-trace for details\n" @@ -1692,17 +1684,11 @@ mini_debug_usage (void) { fprintf (stdout, "Debugging options:\n" -#ifdef ENABLE_NETCORE " --debug[=OPTIONS] Disable debugging support or enable debugging extras, optional OPTIONS is a comma\n" -#else - " --debug[=OPTIONS] Enable debugging support, optional OPTIONS is a comma\n" -#endif " separated list of options\n" "\n" "OPTIONS is composed of:\n" -#ifdef ENABLE_NETCORE " ignore Disable debugging support (on by default).\n" -#endif " casts Enable more detailed InvalidCastException messages.\n" " mdb-optimizations Disable some JIT optimizations which are normally\n" " disabled when running inside the debugger.\n" @@ -2010,14 +1996,7 @@ switch_arch (char* argv[], const char* target_arch) static void apply_root_domain_configuration_file_bindings (MonoDomain *domain, char *root_domain_configuration_file) { -#ifndef ENABLE_NETCORE - g_assert (domain->setup == NULL || domain->setup->configuration_file == NULL); - g_assert (!domain->assembly_bindings_parsed); - - mono_domain_parse_assembly_bindings (domain, 0, 0, root_domain_configuration_file); -#else g_assert_not_reached (); -#endif } static void @@ -2164,9 +2143,7 @@ mono_main (int argc, char* argv[]) opt = mono_parse_default_optimizations (NULL); -#ifdef ENABLE_NETCORE enable_debugging = TRUE; -#endif mono_options_parse_options ((const char**)argv + 1, argc - 1, &argc, error); argc ++; @@ -2415,13 +2392,11 @@ mono_main (int argc, char* argv[]) enable_debugging = TRUE; if (!parse_debug_options (argv [i] + 8)) return 1; -#ifdef ENABLE_NETCORE MonoDebugOptions *opt = mini_get_debug_options (); if (!opt->enabled) { enable_debugging = FALSE; } -#endif } else if (strncmp (argv [i], "--debugger-agent=", 17) == 0) { MonoDebugOptions *opt = mini_get_debug_options (); diff --git a/src/mono/mono/mini/exceptions-amd64.c b/src/mono/mono/mini/exceptions-amd64.c index 82f25f8..aaf7bfe 100644 --- a/src/mono/mono/mini/exceptions-amd64.c +++ b/src/mono/mono/mini/exceptions-amd64.c @@ -43,7 +43,6 @@ #include "mini-amd64.h" #include "mini-runtime.h" #include "aot-runtime.h" -#include "tasklets.h" #include "mono/utils/mono-tls-inline.h" #ifdef TARGET_WIN32 @@ -1906,59 +1905,6 @@ void mono_arch_code_chunk_destroy (void *chunk) } #endif /* MONO_ARCH_HAVE_UNWIND_TABLE */ -#if MONO_SUPPORT_TASKLETS && !defined(DISABLE_JIT) && !defined(ENABLE_NETCORE) -MonoContinuationRestore -mono_tasklets_arch_restore (void) -{ - static guint8* saved = NULL; - guint8 *code, *start; - int cont_reg = AMD64_R9; /* register usable on both call conventions */ - const int kMaxCodeSize = 64; - - if (saved) - return (MonoContinuationRestore)saved; - code = start = (guint8 *)mono_global_codeman_reserve (kMaxCodeSize); - /* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */ - /* cont is in AMD64_ARG_REG1 ($rcx or $rdi) - * state is in AMD64_ARG_REG2 ($rdx or $rsi) - * lmf_addr is in AMD64_ARG_REG3 ($r8 or $rdx) - * We move cont to cont_reg since we need both rcx and rdi for the copy - * state is moved to $rax so it's setup as the return value and we can overwrite $rsi - */ - amd64_mov_reg_reg (code, cont_reg, MONO_AMD64_ARG_REG1, 8); - amd64_mov_reg_reg (code, AMD64_RAX, MONO_AMD64_ARG_REG2, 8); - /* setup the copy of the stack */ - amd64_mov_reg_membase (code, AMD64_RCX, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, stack_used_size), sizeof (int)); - amd64_shift_reg_imm (code, X86_SHR, AMD64_RCX, 3); - x86_cld (code); - amd64_mov_reg_membase (code, AMD64_RSI, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, saved_stack), sizeof (gpointer)); - amd64_mov_reg_membase (code, AMD64_RDI, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, return_sp), sizeof (gpointer)); - amd64_prefix (code, X86_REP_PREFIX); - amd64_movsl (code); - - /* now restore the registers from the LMF */ - amd64_mov_reg_membase (code, AMD64_RCX, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 8); - amd64_mov_reg_membase (code, AMD64_RBP, AMD64_RCX, MONO_STRUCT_OFFSET (MonoLMF, rbp), 8); - amd64_mov_reg_membase (code, AMD64_RSP, AMD64_RCX, MONO_STRUCT_OFFSET (MonoLMF, rsp), 8); - -#ifdef WIN32 - amd64_mov_reg_reg (code, AMD64_R14, AMD64_ARG_REG3, 8); -#else - amd64_mov_reg_reg (code, AMD64_R12, AMD64_ARG_REG3, 8); -#endif - - /* state is already in rax */ - amd64_jump_membase (code, cont_reg, MONO_STRUCT_OFFSET (MonoContinuation, return_ip)); - g_assertf ((code - start) <= kMaxCodeSize, "%d %d", (int)(code - start), kMaxCodeSize); - - mono_arch_flush_icache (start, code - start); - MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); - - saved = start; - return (MonoContinuationRestore)saved; -} -#endif /* MONO_SUPPORT_TASKLETS && !defined(DISABLE_JIT) && !defined(ENABLE_NETCORE) */ - /* * mono_arch_setup_resume_sighandler_ctx: * @@ -1976,15 +1922,6 @@ mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func) MONO_CONTEXT_SET_IP (ctx, func); } -#if (!MONO_SUPPORT_TASKLETS || defined(DISABLE_JIT)) && !defined(ENABLE_NETCORE) -MonoContinuationRestore -mono_tasklets_arch_restore (void) -{ - g_assert_not_reached (); - return NULL; -} -#endif /* (!MONO_SUPPORT_TASKLETS || defined(DISABLE_JIT)) && !defined(ENABLE_NETCORE) */ - void mono_arch_undo_ip_adjustment (MonoContext *ctx) { diff --git a/src/mono/mono/mini/exceptions-x86.c b/src/mono/mono/mini/exceptions-x86.c index d2b3201..54f96e5 100644 --- a/src/mono/mono/mini/exceptions-x86.c +++ b/src/mono/mono/mini/exceptions-x86.c @@ -32,7 +32,6 @@ #include "mini.h" #include "mini-x86.h" #include "mini-runtime.h" -#include "tasklets.h" #include "aot-runtime.h" #include "mono/utils/mono-tls-inline.h" @@ -1175,58 +1174,6 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s #endif } -#if MONO_SUPPORT_TASKLETS && !defined(ENABLE_NETCORE) -MonoContinuationRestore -mono_tasklets_arch_restore (void) -{ - static guint8* saved = NULL; - guint8 *code, *start; - - if (saved) - return (MonoContinuationRestore)saved; - - const int size = 48; - - code = start = mono_global_codeman_reserve (size); - /* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */ - /* put cont in edx */ - x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4); - /* state in eax, so it's setup as the return value */ - x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4); - /* lmf_addr in ebx */ - x86_mov_reg_membase(code, X86_EBX, X86_ESP, 0x0C, 4); - - /* setup the copy of the stack */ - x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4); - x86_shift_reg_imm (code, X86_SHR, X86_ECX, 2); - x86_cld (code); - x86_mov_reg_membase (code, X86_ESI, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, saved_stack), 4); - x86_mov_reg_membase (code, X86_EDI, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, return_sp), 4); - x86_prefix (code, X86_REP_PREFIX); - x86_movsl (code); - - /* now restore the registers from the LMF */ - x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 4); - x86_mov_reg_membase (code, X86_EBP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebp), 4); - x86_mov_reg_membase (code, X86_ESP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esp), 4); - - /* restore the lmf chain */ - /*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4); - x86_mov_membase_reg (code, X86_ECX, 0, X86_EDX, 4);*/ - - x86_jump_membase (code, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, return_ip)); - - g_assertf ((code - start) <= size, "%d %d", (int)(code - start), size); - - mono_arch_flush_icache (start, code - start); - MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL)); - g_assert ((code - start) <= 48); - - saved = start; - return (MonoContinuationRestore)saved; -} -#endif - /* * mono_arch_setup_resume_sighandler_ctx: * diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index d80d520..13a747a 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -1570,11 +1569,9 @@ ves_pinvoke_method ( } #endif -#ifdef ENABLE_NETCORE if (save_last_error) { mono_marshal_clear_last_error (); } -#endif #ifdef MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP CallContext ccontext; @@ -1700,34 +1697,6 @@ interp_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpoint mono_delegate_ctor (this_obj, target, entry, imethod->method, error); } -/* - * From the spec: - * runtime specifies that the implementation of the method is automatically - * provided by the runtime and is primarily used for the methods of delegates. - */ -#ifndef ENABLE_NETCORE -static MONO_NEVER_INLINE MonoException* -ves_imethod (InterpFrame *frame, MonoMethod *method, MonoMethodSignature *sig, stackval *sp) -{ - const char *name = method->name; - mono_class_init_internal (method->klass); - - if (method->klass == mono_defaults.array_class) { - if (!strcmp (name, "UnsafeMov")) { - /* TODO: layout checks */ - stackval_from_data (sig->ret, sp, (char*) sp, FALSE); - return NULL; - } - if (!strcmp (name, "UnsafeLoad")) - return ves_array_get (frame, sp, sp, sig, FALSE); - } - - g_error ("Don't know how to exec runtime method %s.%s::%s", - m_class_get_name_space (method->klass), m_class_get_name (method->klass), - method->name); -} -#endif - #if DEBUG_INTERP static void dump_stackval (GString *str, stackval *s, MonoType *type) @@ -2033,10 +2002,8 @@ interp_entry (InterpEntryData *data) static void do_icall (MonoMethodSignature *sig, int op, stackval *sp, gpointer ptr, gboolean save_last_error) { -#ifdef ENABLE_NETCORE if (save_last_error) mono_marshal_clear_last_error (); -#endif switch (op) { case MINT_ICALL_V_V: { @@ -2903,7 +2870,6 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e return addr; } -#ifdef ENABLE_NETCORE /* * The runtime expects a function pointer unique to method and * the native caller expects a function pointer with the @@ -2911,7 +2877,6 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e */ mono_error_set_platform_not_supported (error, "No native to managed transitions on this platform."); return NULL; -#endif } #endif return (gpointer)interp_no_native_to_managed; @@ -3749,18 +3714,8 @@ call: MINT_IN_BREAK; } MINT_IN_CASE(MINT_CALLRUN) { -#ifndef ENABLE_NETCORE - MonoMethod *target_method = (MonoMethod*) frame->imethod->data_items [ip [2]]; - MonoMethodSignature *sig = (MonoMethodSignature*) frame->imethod->data_items [ip [3]]; - - MonoException *ex = ves_imethod (frame, target_method, sig, (stackval*)(locals + ip [1])); - if (ex) - THROW_EX (ex, ip); - - ip += 4; -#else g_assert_not_reached (); -#endif + MINT_IN_BREAK; } MINT_IN_CASE(MINT_RET) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index df461de..b076844 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1987,10 +1987,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas interp_emit_ldelema (td, target_method->klass, check_class); td->ip += 5; return TRUE; -#ifndef ENABLE_NETCORE - } else if (!strcmp (tm, "UnsafeMov") || !strcmp (tm, "UnsafeLoad")) { - *op = MINT_CALLRUN; -#endif } else if (!strcmp (tm, "Get")) { interp_emit_ldelema (td, target_method->klass, NULL); interp_emit_ldobj (td, m_class_get_element_class (target_method->klass)); @@ -2191,7 +2187,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } else if (((in_corlib && !strcmp (klass_name_space, "Internal.Runtime.CompilerServices")) || !strcmp (klass_name_space, "System.Runtime.CompilerServices")) && !strcmp (klass_name, "Unsafe")) { -#ifdef ENABLE_NETCORE if (!strcmp (tm, "AddByteOffset")) *op = MINT_INTRINS_UNSAFE_ADD_BYTE_OFFSET; else if (!strcmp (tm, "ByteOffset")) @@ -2238,9 +2233,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } else if (!strcmp (tm, "InitBlockUnaligned")) { *op = MINT_INITBLK; } -#endif } else if (in_corlib && !strcmp (klass_name_space, "System.Runtime.CompilerServices") && !strcmp (klass_name, "RuntimeHelpers")) { -#ifdef ENABLE_NETCORE if (!strcmp (tm, "get_OffsetToStringData")) { g_assert (csignature->param_count == 0); int offset = MONO_STRUCT_OFFSET (MonoString, chars); @@ -2296,7 +2289,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas *op = has_refs ? MINT_LDC_I4_1 : MINT_LDC_I4_0; } -#endif } else if (in_corlib && !strcmp (klass_name_space, "System") && !strcmp (klass_name, "RuntimeMethodHandle") && !strcmp (tm, "GetFunctionPointer") && csignature->param_count == 1) { // We must intrinsify this method on interp so we don't return a pointer to native code entering interpreter *op = MINT_LDFTN_DYNAMIC; @@ -2429,7 +2421,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } } } -#ifdef ENABLE_NETCORE else if (in_corlib && !strcmp ("System.Runtime.CompilerServices", klass_name_space) && !strcmp ("RuntimeFeature", klass_name)) { @@ -2442,7 +2433,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas !strcmp (tm, "get_IsSupported")) { *op = MINT_LDC_I4_0; } -#endif return FALSE; } @@ -3073,14 +3063,6 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_I4); #endif } - -#ifndef ENABLE_NETCORE - if (op == MINT_CALLRUN) { - interp_ins_set_dreg (td->last_ins, dreg); - td->last_ins->data [0] = get_data_item_index (td, target_method); - td->last_ins->data [1] = get_data_item_index (td, mono_method_signature_internal (target_method)); - } -#endif } else if (!calli && !is_delegate_invoke && !is_virtual && mono_interp_jit_call_supported (target_method, csignature)) { interp_add_ins (td, MINT_JIT_CALL); interp_ins_set_dreg (td->last_ins, dreg); diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index c8b9d92..52a01b1 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -568,9 +568,7 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu EMIT_NEW_BIALU (cfg, ins, OP_PSUB, dreg, args [1]->dreg, args [0]->dreg); ins->type = STACK_PTR; return ins; - } -#ifdef ENABLE_NETCORE - else if (!strcmp (cmethod->name, "InitBlockUnaligned")) { + } else if (!strcmp (cmethod->name, "InitBlockUnaligned")) { g_assert (fsig->param_count == 3); mini_emit_memory_init_bytes (cfg, args [0], args [1], args [2], MONO_INST_UNALIGNED); @@ -583,7 +581,6 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu MONO_ADD_INS (cfg->cbb, ins); return ins; } -#endif return NULL; } @@ -1926,7 +1923,6 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } } -#ifdef ENABLE_NETCORE // Return false for IsSupported for all types in System.Runtime.Intrinsics.* // if it's not handled in mono_emit_simd_intrinsics if (in_corlib && @@ -1976,7 +1972,6 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign break; } } -#endif ins = mono_emit_native_types_intrinsics (cfg, cmethod, fsig, args); if (ins) @@ -2112,23 +2107,6 @@ emit_array_unsafe_mov (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **a return NULL; } -#ifndef ENABLE_NETCORE -MonoInst* -mini_emit_inst_for_sharable_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - if (cmethod->klass == mono_defaults.array_class) { - if (strcmp (cmethod->name, "UnsafeStore") == 0) - return emit_array_unsafe_access (cfg, fsig, args, TRUE); - else if (strcmp (cmethod->name, "UnsafeLoad") == 0) - return emit_array_unsafe_access (cfg, fsig, args, FALSE); - else if (strcmp (cmethod->name, "UnsafeMov") == 0) - return emit_array_unsafe_mov (cfg, fsig, args); - } - - return NULL; -} -#endif - MonoInst* mini_emit_inst_for_field_load (MonoCompile *cfg, MonoClassField *field) { @@ -2144,13 +2122,11 @@ mini_emit_inst_for_field_load (MonoCompile *cfg, MonoClassField *field) is_le = (TARGET_BYTE_ORDER == G_LITTLE_ENDIAN); EMIT_NEW_ICONST (cfg, ins, is_le); return ins; - } -#ifdef ENABLE_NETCORE - else if ((klass == mono_defaults.int_class || klass == mono_defaults.uint_class) && strcmp (field->name, "Zero") == 0) { + } else if ((klass == mono_defaults.int_class || klass == mono_defaults.uint_class) && strcmp (field->name, "Zero") == 0) { EMIT_NEW_PCONST (cfg, ins, 0); return ins; } -#endif + return NULL; } #else diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index 29d13e3..761682a 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -1420,7 +1420,6 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl gpointer this_arg; gpointer new_args [16]; -#ifdef ENABLE_NETCORE /* Object.GetType () is an intrinsic under netcore */ if (!mono_class_is_ginst (cmethod->klass) && !cmethod->is_inflated && !strcmp (cmethod->name, "GetType")) { MonoVTable *vt; @@ -1432,7 +1431,6 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl } return vt->type; } -#endif m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg, error); if (!is_ok (error)) { diff --git a/src/mono/mono/mini/main-core.c b/src/mono/mono/mini/main-core.c index 29f575f..41318fe 100644 --- a/src/mono/mono/mini/main-core.c +++ b/src/mono/mono/mini/main-core.c @@ -1,8 +1,6 @@ #include #include -#if ENABLE_NETCORE - #include "mini.h" #include "mini-runtime.h" #include @@ -120,7 +118,3 @@ int STDAPICALLTYPE coreclr_create_delegate (void* hostHandle, unsigned int domai g_error ("Not implemented"); return 0; } -#else - -MONO_EMPTY_SOURCE_FILE (main_core); -#endif // ENABLE_NETCORE diff --git a/src/mono/mono/mini/memory-access.c b/src/mono/mono/mini/memory-access.c index b666d4c..66f3225 100644 --- a/src/mono/mono/mini/memory-access.c +++ b/src/mono/mono/mini/memory-access.c @@ -17,11 +17,7 @@ #include "ir-emit.h" #include "jit-icalls.h" -#ifdef ENABLE_NETCORE #define MAX_INLINE_COPIES 16 -#else -#define MAX_INLINE_COPIES 10 -#endif #define MAX_INLINE_COPY_SIZE 10000 void diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 5c28a70..50948e6 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -97,11 +97,7 @@ * while the jit only sees one method, so we have to inline things ourselves. */ /* Used by LLVM AOT */ -#ifdef ENABLE_NETCORE #define LLVM_AOT_INLINE_LENGTH_LIMIT 30 -#else -#define LLVM_AOT_INLINE_LENGTH_LIMIT INLINE_LENGTH_LIMIT -#endif /* Used to LLVM JIT */ #define LLVM_JIT_INLINE_LENGTH_LIMIT 100 @@ -3495,7 +3491,6 @@ method_needs_stack_walk (MonoCompile *cfg, MonoMethod *cmethod) return TRUE; } -#if defined(ENABLE_NETCORE) /* * In corelib code, methods which need to do a stack walk declare a StackCrawlMark local and pass it as an * arguments until it reaches an icall. Its hard to detect which methods do that especially with @@ -3509,7 +3504,7 @@ method_needs_stack_walk (MonoCompile *cfg, MonoMethod *cmethod) (!strcmp (cname, "Activator"))) return TRUE; } -#endif + return FALSE; } @@ -7496,19 +7491,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if ((m_class_get_parent (cmethod->klass) == mono_defaults.multicastdelegate_class) && !strcmp (cmethod->name, "Invoke")) delegate_invoke = TRUE; -#ifndef ENABLE_NETCORE - if ((cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_sharable_method (cfg, cmethod, fsig, sp))) { - if (!MONO_TYPE_IS_VOID (fsig->ret)) { - mini_type_to_eval_stack_type ((cfg), fsig->ret, ins); - emit_widen = FALSE; - } - - if (inst_tailcall) // FIXME - mono_tailcall_print ("missed tailcall intrins_sharable %s -> %s\n", method->name, cmethod->name); - goto call_end; - } -#endif - /* * Implement a workaround for the inherent races involved in locking: * Monitor.Enter () @@ -7746,11 +7728,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } } -#ifdef ENABLE_NETCORE if (save_last_error) { mono_emit_jit_icall (cfg, mono_marshal_clear_last_error, NULL); } -#endif /* Tail prefix / tailcall optimization */ @@ -9258,7 +9238,6 @@ calli_end: } } -#ifdef ENABLE_NETCORE // Optimize // // box @@ -9380,7 +9359,6 @@ calli_end: } } } -#endif gboolean is_true; diff --git a/src/mono/mono/mini/mini-arm64.h b/src/mono/mono/mini/mini-arm64.h index 2448573..2f89ecd 100644 --- a/src/mono/mono/mini/mini-arm64.h +++ b/src/mono/mono/mini/mini-arm64.h @@ -21,7 +21,7 @@ #define MONO_MAX_FREGS 32 #define MONO_MAX_XREGS 32 -#if !defined(DISABLE_SIMD) && defined(ENABLE_NETCORE) +#if !defined(DISABLE_SIMD) #define MONO_ARCH_SIMD_INTRINSICS 1 #endif diff --git a/src/mono/mono/mini/mini-cross-helpers.c b/src/mono/mono/mini/mini-cross-helpers.c index d456b4a..e61ed81 100644 --- a/src/mono/mono/mini/mini-cross-helpers.c +++ b/src/mono/mono/mini/mini-cross-helpers.c @@ -11,7 +11,6 @@ #include "mini.h" #include "mini-runtime.h" #include "interp/interp.h" -#include "tasklets.h" #include void diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index 83734f2..cf5ad93 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -2193,7 +2193,6 @@ setup_stack_trace (MonoException *mono_ex, GSList **dynamic_methods, GList *trac if (*dynamic_methods) { /* These methods could go away anytime, so save a reference to them in the exception object */ MonoDomain *domain = mono_domain_get (); -#ifdef ENABLE_NETCORE int methods_len = g_slist_length (*dynamic_methods); MonoArray *old_methods = mono_ex->dynamic_methods; int old_methods_len = 0; @@ -2225,29 +2224,6 @@ setup_stack_trace (MonoException *mono_ex, GSList **dynamic_methods, GList *trac } MONO_OBJECT_SETREF_INTERNAL (mono_ex, dynamic_methods, all_methods); -#else - GSList *l; - MonoMList *list = (MonoMList*)mono_ex->dynamic_methods; - - for (l = *dynamic_methods; l; l = l->next) { - MonoGCHandle dis_link; - - if (domain->method_to_dyn_method) { - mono_domain_lock (domain); - dis_link = (MonoGCHandle)g_hash_table_lookup (domain->method_to_dyn_method, l->data); - mono_domain_unlock (domain); - if (dis_link) { - MonoObject *o = mono_gchandle_get_target_internal (dis_link); - if (o) { - list = mono_mlist_prepend_checked (list, o, error); - mono_error_assert_ok (error); - } - } - } - } - - MONO_OBJECT_SETREF_INTERNAL (mono_ex, dynamic_methods, list); -#endif g_slist_free (*dynamic_methods); *dynamic_methods = NULL; @@ -2747,9 +2723,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu MONO_PROFILER_RAISE (exception_throw, (obj)); jit_tls->orig_ex_ctx_set = FALSE; -#ifdef ENABLE_NETCORE mono_first_chance_exception_internal (obj); -#endif StackFrameInfo catch_frame; MonoFirstPassResult res; @@ -2772,20 +2746,6 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu } else { gboolean unhandled = FALSE; - /* - * The exceptions caught by the mono_runtime_invoke_checked () calls - * in the threadpool needs to be treated as unhandled (#669836). - * - * FIXME: The check below is hackish, but its hard to distinguish - * these runtime invoke calls from others in the runtime. - */ -#ifndef ENABLE_NETCORE - if (ji && jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) { - if (prev_ji && jinfo_get_method (prev_ji) == mono_defaults.threadpool_perform_wait_callback_method) - unhandled = TRUE; - } -#endif - if (unhandled) mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, NULL, NULL); else if (!ji || (jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) { diff --git a/src/mono/mono/mini/mini-llvm-cpp.cpp b/src/mono/mono/mini/mini-llvm-cpp.cpp index 7240b06..7d4d31b 100644 --- a/src/mono/mono/mini/mini-llvm-cpp.cpp +++ b/src/mono/mono/mini/mini-llvm-cpp.cpp @@ -323,7 +323,6 @@ mono_llvm_set_func_nonnull_arg (LLVMValueRef func, int argNo) gboolean mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* gep_base, LLVMValueRef* gep_offset) { -#ifdef ENABLE_NETCORE // Look for a pattern like this: // %1 = ptrtoint i8* %gep_base to i64 // %2 = add i64 %1, %gep_offset @@ -338,7 +337,6 @@ mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* gep_base, LLVMValueRef* g } } } -#endif return FALSE; } diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 29658ab..02c2cfe 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -3730,11 +3730,9 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) case LLVMArgVtypeInReg: case LLVMArgVtypeByVal: case LLVMArgAsIArgs: -#ifdef ENABLE_NETCORE // FIXME: Enabling this fails on windows case LLVMArgVtypeAddr: case LLVMArgVtypeByRef: -#endif { if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type))) /* Treat these as normal values */ @@ -6986,11 +6984,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) LLVMValueRef mask [32], v; int i; -#ifdef ENABLE_NETCORE t = simd_class_to_llvm_type (ctx, ins->klass); -#else - t = simd_op_to_llvm_type (ins->opcode); -#endif for (i = 0; i < 32; ++i) mask [i] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); @@ -8794,7 +8788,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) } #endif -#ifdef ENABLE_NETCORE case OP_XCAST: { LLVMTypeRef t = simd_class_to_llvm_type (ctx, ins->klass); @@ -9036,11 +9029,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) values [ins->dreg] = call_intrins (ctx, ins->opcode == OP_PDEP32 ? INTRINS_PDEP_I32 : INTRINS_PDEP_I64, args, ""); break; } -#endif /* ENABLE_NETCORE */ #endif /* defined(TARGET_X86) || defined(TARGET_AMD64) */ // Shared between ARM64 and X86 -#if defined(ENABLE_NETCORE) && (defined(TARGET_ARM64) || defined(TARGET_X86) || defined(TARGET_AMD64)) +#if defined(TARGET_ARM64) || defined(TARGET_X86) || defined(TARGET_AMD64) case OP_LZCNT32: case OP_LZCNT64: { LLVMValueRef args [2]; @@ -9051,7 +9043,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) } #endif -#if defined(ENABLE_NETCORE) && defined(TARGET_ARM64) +#if defined(TARGET_ARM64) case OP_XOP_I4_I4: case OP_XOP_I8_I8: { IntrinsicId id = (IntrinsicId)0; diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index c1b4c12..e7f78c6 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -72,7 +72,6 @@ #include #include #include -#include #ifdef ENABLE_PERFTRACING #include @@ -81,13 +80,9 @@ #include "mini.h" #include "seq-points.h" -#include "tasklets.h" #include #include #include "trace.h" -#ifndef ENABLE_NETCORE -#include "version.h" -#endif #include "aot-compiler.h" #include "aot-runtime.h" #include "llvmonly-runtime.h" @@ -373,16 +368,6 @@ gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee) if (caller->domain_neutral && !callee->domain_neutral) return FALSE; -#ifndef ENABLE_NETCORE - MonoMethod *cmethod; - - cmethod = jinfo_get_method (caller); - if ((cmethod->klass == mono_defaults.appdomain_class) && - (strstr (cmethod->name, "InvokeInDomain"))) { - /* The InvokeInDomain methods change the current appdomain */ - return FALSE; - } -#endif return TRUE; } @@ -4618,10 +4603,6 @@ mini_init (const char *filename, const char *runtime_version) mono_simd_intrinsics_init (); #endif -#ifndef ENABLE_NETCORE - mono_tasklets_init (); -#endif - register_trampolines (domain); if (mono_compile_aot) @@ -5067,10 +5048,6 @@ mini_cleanup (MonoDomain *domain) mono_runtime_cleanup (domain); #endif -#ifndef ENABLE_NETCORE - mono_threadpool_cleanup (); -#endif - MONO_PROFILER_RAISE (runtime_shutdown_end, ()); mono_profiler_cleanup (); diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index e44e7bd..d149ce4 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -273,9 +273,7 @@ typedef struct MonoDebugOptions { */ gboolean top_runtime_invoke_unhandled; -#ifdef ENABLE_NETCORE gboolean enabled; -#endif } MonoDebugOptions; /* diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index f8d3e18..90de96b 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -545,11 +545,7 @@ mono_set_timeout_exec (int id) { ERROR_DECL (error); -#ifdef ENABLE_NETCORE MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "TimerQueue"); -#else - MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "WasmRuntime"); -#endif g_assert (klass); MonoMethod *method = mono_class_get_method_from_name_checked (klass, "TimeoutCallback", -1, 0, error); @@ -625,12 +621,8 @@ void mono_arch_register_icall (void) { #ifdef HOST_WASM -#ifdef ENABLE_NETCORE mono_add_internal_call_internal ("System.Threading.TimerQueue::SetTimeout", mono_wasm_set_timeout); mono_add_internal_call_internal ("System.Threading.ThreadPool::QueueCallback", mono_wasm_queue_tp_cb); -#else - mono_add_internal_call_internal ("System.Threading.WasmRuntime::SetTimeout", mono_wasm_set_timeout); -#endif #endif } diff --git a/src/mono/mono/mini/mini-wasm.h b/src/mono/mono/mini/mini-wasm.h index 57c73a4..bef8ef7 100644 --- a/src/mono/mono/mini/mini-wasm.h +++ b/src/mono/mono/mini/mini-wasm.h @@ -89,9 +89,7 @@ typedef struct { #define MONO_ARCH_GSHAREDVT_SUPPORTED 1 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1 -#ifdef ENABLE_NETCORE #define MONO_ARCH_SIMD_INTRINSICS 1 -#endif #define MONO_ARCH_INTERPRETER_SUPPORTED 1 #define MONO_ARCH_HAS_REGISTER_ICALL 1 diff --git a/src/mono/mono/mini/mini-x86.h b/src/mono/mono/mini/mini-x86.h index 6d44cb5..edebbcc 100644 --- a/src/mono/mono/mini/mini-x86.h +++ b/src/mono/mono/mini/mini-x86.h @@ -64,13 +64,6 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep); #define MONO_ARCH_SUPPORT_TASKLETS 1 -#ifndef DISABLE_SIMD -#ifndef ENABLE_NETCORE -#define MONO_ARCH_SIMD_INTRINSICS 1 -#define MONO_ARCH_NEED_SIMD_BANK 1 -#endif -#endif - /* we should lower this size and make sure we don't call heavy stack users in the segv handler */ #if defined(__APPLE__) #define MONO_ARCH_SIGNAL_STACK_SIZE MINSIGSTKSZ diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index d12f3b0..c381fb9 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -65,7 +65,6 @@ #include "mini.h" #include "seq-points.h" -#include "tasklets.h" #include #include #include "trace.h" @@ -753,7 +752,6 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode) { int dreg; -#ifdef ENABLE_NETCORE if (type->type == MONO_TYPE_VALUETYPE && !type->byref) { MonoClass *klass = mono_class_from_mono_type_internal (type); if (m_class_is_enumtype (klass) && m_class_get_image (klass) == mono_get_corlib () && !strcmp (m_class_get_name (klass), "StackCrawlMark")) { @@ -761,7 +759,6 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode) g_error ("Method '%s' which contains a StackCrawlMark local variable must be decorated with [System.Security.DynamicSecurityMethod].", mono_method_get_full_name (cfg->method)); } } -#endif type = mini_get_underlying_type (type); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 6027a5a..e396925 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -2285,9 +2285,6 @@ void mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoI MonoInst* mini_emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboolean safety_checks); MonoInst* mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args); MonoInst* mini_emit_inst_for_ctor (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args); -#ifndef ENABLE_NETCORE -MonoInst* mini_emit_inst_for_sharable_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args); -#endif MonoInst* mini_emit_inst_for_field_load (MonoCompile *cfg, MonoClassField *field); MonoInst* mini_handle_enum_has_flag (MonoCompile *cfg, MonoClass *klass, MonoInst *enum_this, int enum_val_reg, MonoInst *enum_flag); diff --git a/src/mono/mono/mini/monovm.c b/src/mono/mono/mini/monovm.c index bbde28c..f189961 100644 --- a/src/mono/mono/mini/monovm.c +++ b/src/mono/mono/mini/monovm.c @@ -2,8 +2,6 @@ #include #include "monovm.h" -#if ENABLE_NETCORE - #include #include #include @@ -271,25 +269,3 @@ monovm_shutdown (int *latchedExitCode) return 0; } - -#else - -int -monovm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues) -{ - return -1; -} - -int -monovm_execute_assembly (int argc, const char **argv, const char *managedAssemblyPath, unsigned int *exitCode) -{ - return -1; -} - -int -monovm_shutdown (int *latchedExitCode) -{ - return -1; -} - -#endif // ENABLE_NETCORE diff --git a/src/mono/mono/mini/simd-intrinsics-netcore.c b/src/mono/mono/mini/simd-intrinsics-netcore.c deleted file mode 100644 index 33d307d..0000000 --- a/src/mono/mono/mini/simd-intrinsics-netcore.c +++ /dev/null @@ -1,2329 +0,0 @@ -/** - * SIMD Intrinsics support for netcore. - * Only LLVM is supported as a backend. - */ - -#include -#include -#include -#include "mini.h" -#include "mini-runtime.h" -#include "ir-emit.h" -#ifdef ENABLE_LLVM -#include "mini-llvm.h" -#endif -#include "mono/utils/bsearch.h" -#include -#include -#include - -#if defined (MONO_ARCH_SIMD_INTRINSICS) && defined(ENABLE_NETCORE) - -#if defined(DISABLE_JIT) - -void -mono_simd_intrinsics_init (void) -{ -} - -#else - -#define MSGSTRFIELD(line) MSGSTRFIELD1(line) -#define MSGSTRFIELD1(line) str##line -static const struct msgstr_t { -#define METHOD(name) char MSGSTRFIELD(__LINE__) [sizeof (#name)]; -#define METHOD2(str,name) char MSGSTRFIELD(__LINE__) [sizeof (str)]; -#include "simd-methods-netcore.h" -#undef METHOD -#undef METHOD2 -} method_names = { -#define METHOD(name) #name, -#define METHOD2(str,name) str, -#include "simd-methods-netcore.h" -#undef METHOD -#undef METHOD2 -}; - -enum { -#define METHOD(name) SN_ ## name = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)), -#define METHOD2(str,name) SN_ ## name = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)), -#include "simd-methods-netcore.h" -}; -#define method_name(idx) ((const char*)&method_names + (idx)) - -static int register_size; - -typedef struct { - // One of the SN_ constants - guint16 id; - // ins->opcode - int op; - // ins->inst_c0 - int instc0; -} SimdIntrinsic; - -void -mono_simd_intrinsics_init (void) -{ - register_size = 16; -#if FALSE - if ((mini_get_cpu_features () & MONO_CPU_X86_AVX) != 0) - register_size = 32; -#endif - /* Tell the class init code the size of the System.Numerics.Register type */ - mono_simd_register_size = register_size; -} - -MonoInst* -mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field, MonoInst *addr) -{ - return NULL; -} - -static int -simd_intrinsic_compare_by_name (const void *key, const void *value) -{ - return strcmp ((const char*)key, method_name (*(guint16*)value)); -} - -static int -simd_intrinsic_info_compare_by_name (const void *key, const void *value) -{ - SimdIntrinsic *info = (SimdIntrinsic*)value; - return strcmp ((const char*)key, method_name (info->id)); -} - -static int -lookup_intrins (guint16 *intrinsics, int size, MonoMethod *cmethod) -{ - const guint16 *result = (const guint16 *)mono_binary_search (cmethod->name, intrinsics, size / sizeof (guint16), sizeof (guint16), &simd_intrinsic_compare_by_name); - - if (result == NULL) - return -1; - else - return (int)*result; -} - -static SimdIntrinsic* -lookup_intrins_info (SimdIntrinsic *intrinsics, int size, MonoMethod *cmethod) -{ -#if 0 - for (int i = 0; i < (size / sizeof (SimdIntrinsic)) - 1; ++i) { - const char *n1 = method_name (intrinsics [i].id); - const char *n2 = method_name (intrinsics [i + 1].id); - int len1 = strlen (n1); - int len2 = strlen (n2); - for (int j = 0; j < len1 && j < len2; ++j) { - if (n1 [j] > n2 [j]) { - printf ("%s %s\n", n1, n2); - g_assert_not_reached (); - } else if (n1 [j] < n2 [j]) { - break; - } - } - } -#endif - - return (SimdIntrinsic *)mono_binary_search (cmethod->name, intrinsics, size / sizeof (SimdIntrinsic), sizeof (SimdIntrinsic), &simd_intrinsic_info_compare_by_name); -} - -/* - * Return a simd vreg for the simd value represented by SRC. - * SRC is the 'this' argument to methods. - * Set INDIRECT to TRUE if the value was loaded from memory. - */ -static int -load_simd_vreg_class (MonoCompile *cfg, MonoClass *klass, MonoInst *src, gboolean *indirect) -{ - const char *spec = INS_INFO (src->opcode); - - if (indirect) - *indirect = FALSE; - if (src->opcode == OP_XMOVE) { - return src->sreg1; - } else if (src->opcode == OP_LDADDR) { - int res = ((MonoInst*)src->inst_p0)->dreg; - return res; - } else if (spec [MONO_INST_DEST] == 'x') { - return src->dreg; - } else if (src->type == STACK_PTR || src->type == STACK_MP) { - MonoInst *ins; - if (indirect) - *indirect = TRUE; - - MONO_INST_NEW (cfg, ins, OP_LOADX_MEMBASE); - ins->klass = klass; - ins->sreg1 = src->dreg; - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins->dreg; - } - g_warning ("load_simd_vreg:: could not infer source simd (%d) vreg for op", src->type); - mono_print_ins (src); - g_assert_not_reached (); -} - -static int -load_simd_vreg (MonoCompile *cfg, MonoMethod *cmethod, MonoInst *src, gboolean *indirect) -{ - return load_simd_vreg_class (cfg, cmethod->klass, src, indirect); -} - -/* Create and emit a SIMD instruction, dreg is auto-allocated */ -static MonoInst* -emit_simd_ins (MonoCompile *cfg, MonoClass *klass, int opcode, int sreg1, int sreg2) -{ - const char *spec = INS_INFO (opcode); - MonoInst *ins; - - MONO_INST_NEW (cfg, ins, opcode); - if (spec [MONO_INST_DEST] == 'x') { - ins->dreg = alloc_xreg (cfg); - ins->type = STACK_VTYPE; - } else if (spec [MONO_INST_DEST] == 'i') { - ins->dreg = alloc_ireg (cfg); - ins->type = STACK_I4; - } else if (spec [MONO_INST_DEST] == 'l') { - ins->dreg = alloc_lreg (cfg); - ins->type = STACK_I8; - } else if (spec [MONO_INST_DEST] == 'f') { - ins->dreg = alloc_freg (cfg); - ins->type = STACK_R8; - } - ins->sreg1 = sreg1; - ins->sreg2 = sreg2; - ins->klass = klass; - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} - -static MonoInst* -emit_simd_ins_for_sig (MonoCompile *cfg, MonoClass *klass, int opcode, int instc0, int instc1, MonoMethodSignature *fsig, MonoInst **args) -{ - g_assert (fsig->param_count <= 3); - MonoInst* ins = emit_simd_ins (cfg, klass, opcode, - fsig->param_count > 0 ? args [0]->dreg : -1, - fsig->param_count > 1 ? args [1]->dreg : -1); - if (instc0 != -1) - ins->inst_c0 = instc0; - if (instc1 != -1) - ins->inst_c1 = instc1; - if (fsig->param_count == 3) - ins->sreg3 = args [2]->dreg; - return ins; -} - -static gboolean -is_hw_intrinsics_class (MonoClass *klass, const char *name, gboolean *is_64bit) -{ - const char *class_name = m_class_get_name (klass); - if ((!strcmp (class_name, "X64") || !strcmp (class_name, "Arm64")) && m_class_get_nested_in (klass)) { - *is_64bit = TRUE; - return !strcmp (m_class_get_name (m_class_get_nested_in (klass)), name); - } else { - *is_64bit = FALSE; - return !strcmp (class_name, name); - } -} - -static MonoTypeEnum -get_underlying_type (MonoType* type) -{ - MonoClass* klass = mono_class_from_mono_type_internal (type); - if (type->type == MONO_TYPE_PTR) // e.g. int* => MONO_TYPE_I4 - return m_class_get_byval_arg (m_class_get_element_class (klass))->type; - else if (type->type == MONO_TYPE_GENERICINST) // e.g. Vector128 => MONO_TYPE_I4 - return mono_class_get_context (klass)->class_inst->type_argv [0]->type; - else - return type->type; -} - -static MonoInst* -emit_xcompare (MonoCompile *cfg, MonoClass *klass, MonoTypeEnum etype, MonoInst *arg1, MonoInst *arg2) -{ - MonoInst *ins; - gboolean is_fp = etype == MONO_TYPE_R4 || etype == MONO_TYPE_R8; - - ins = emit_simd_ins (cfg, klass, is_fp ? OP_XCOMPARE_FP : OP_XCOMPARE, arg1->dreg, arg2->dreg); - ins->inst_c0 = CMP_EQ; - ins->inst_c1 = etype; - return ins; -} - -static MonoType* -get_vector_t_elem_type (MonoType *vector_type) -{ - MonoClass *klass; - MonoType *etype; - - g_assert (vector_type->type == MONO_TYPE_GENERICINST); - klass = mono_class_from_mono_type_internal (vector_type); - g_assert ( - !strcmp (m_class_get_name (klass), "Vector`1") || - !strcmp (m_class_get_name (klass), "Vector128`1") || - !strcmp (m_class_get_name (klass), "Vector256`1")); - etype = mono_class_get_context (klass)->class_inst->type_argv [0]; - return etype; -} - -static MonoInst * -emit_arch_vector128_create_multi (MonoCompile *cfg, MonoMethodSignature *fsig, MonoClass *klass, MonoType *etype, MonoInst **args) -{ -#if defined(TARGET_AMD64) - MonoInst *ins, *load; - - // FIXME: Optimize this - MONO_INST_NEW (cfg, ins, OP_LOCALLOC_IMM); - ins->dreg = alloc_preg (cfg); - ins->inst_imm = 16; - MONO_ADD_INS (cfg->cbb, ins); - - int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - int store_opcode = mono_type_to_store_membase (cfg, etype); - for (int i = 0; i < fsig->param_count; ++i) - MONO_EMIT_NEW_STORE_MEMBASE (cfg, store_opcode, ins->dreg, i * esize, args [i]->dreg); - - load = emit_simd_ins (cfg, klass, OP_SSE_LOADU, ins->dreg, -1); - load->inst_c0 = 16; - load->inst_c1 = get_underlying_type (etype); - return load; -#else - return NULL; -#endif -} - -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) - -static int -type_to_expand_op (MonoType *type) -{ - switch (type->type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - return OP_EXPAND_I1; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - return OP_EXPAND_I2; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - return OP_EXPAND_I4; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - return OP_EXPAND_I8; - case MONO_TYPE_R4: - return OP_EXPAND_R4; - case MONO_TYPE_R8: - return OP_EXPAND_R8; - default: - g_assert_not_reached (); - } -} - -static guint16 vector_128_methods [] = { - SN_AsByte, - SN_AsDouble, - SN_AsInt16, - SN_AsInt32, - SN_AsInt64, - SN_AsSByte, - SN_AsSingle, - SN_AsUInt16, - SN_AsUInt32, - SN_AsUInt64, - SN_Create, - SN_CreateScalarUnsafe, -}; - -static MonoInst* -emit_vector128 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - if (!COMPILE_LLVM (cfg)) - return NULL; - - MonoClass *klass = cmethod->klass; - int id = lookup_intrins (vector_128_methods, sizeof (vector_128_methods), cmethod); - if (id == -1) - return NULL; - - if (!strcmp (m_class_get_name (cfg->method->klass), "Vector256")) - return NULL; // TODO: Fix Vector256.WithUpper/WithLower - - MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; - - switch (id) { - case SN_AsByte: - case SN_AsDouble: - case SN_AsInt16: - case SN_AsInt32: - case SN_AsInt64: - case SN_AsSByte: - case SN_AsSingle: - case SN_AsUInt16: - case SN_AsUInt32: - case SN_AsUInt64: - return emit_simd_ins (cfg, klass, OP_XCAST, args [0]->dreg, -1); - case SN_Create: { - MonoType *etype = get_vector_t_elem_type (fsig->ret); - if (fsig->param_count == 1 && mono_metadata_type_equal (fsig->params [0], etype)) - return emit_simd_ins (cfg, klass, type_to_expand_op (etype), args [0]->dreg, -1); - else - return emit_arch_vector128_create_multi (cfg, fsig, klass, etype, args); - } - case SN_CreateScalarUnsafe: - return emit_simd_ins_for_sig (cfg, klass, OP_CREATE_SCALAR_UNSAFE, -1, arg0_type, fsig, args); - default: - break; - } - - return NULL; -} - -#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) - -#ifdef TARGET_AMD64 - -static guint16 vector_methods [] = { - SN_ConvertToDouble, - SN_ConvertToInt32, - SN_ConvertToInt64, - SN_ConvertToSingle, - SN_ConvertToUInt32, - SN_ConvertToUInt64, - SN_Narrow, - SN_Widen, - SN_get_IsHardwareAccelerated, -}; - -static MonoInst* -emit_sys_numerics_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *ins; - gboolean supported = FALSE; - int id; - MonoType *etype; - - id = lookup_intrins (vector_methods, sizeof (vector_methods), cmethod); - if (id == -1) - return NULL; - - //printf ("%s\n", mono_method_full_name (cmethod, 1)); - -#ifdef MONO_ARCH_SIMD_INTRINSICS - supported = TRUE; -#endif - - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD intrinsic %s\n", name); - g_free (name); - } - - switch (id) { - case SN_get_IsHardwareAccelerated: - EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); - ins->type = STACK_I4; - return ins; - case SN_ConvertToInt32: - etype = get_vector_t_elem_type (fsig->params [0]); - g_assert (etype->type == MONO_TYPE_R4); - return emit_simd_ins (cfg, mono_class_from_mono_type_internal (fsig->ret), OP_CVTPS2DQ, args [0]->dreg, -1); - case SN_ConvertToSingle: - etype = get_vector_t_elem_type (fsig->params [0]); - g_assert (etype->type == MONO_TYPE_I4 || etype->type == MONO_TYPE_U4); - // FIXME: - if (etype->type == MONO_TYPE_U4) - return NULL; - return emit_simd_ins (cfg, mono_class_from_mono_type_internal (fsig->ret), OP_CVTDQ2PS, args [0]->dreg, -1); - case SN_ConvertToDouble: - case SN_ConvertToInt64: - case SN_ConvertToUInt32: - case SN_ConvertToUInt64: - case SN_Narrow: - case SN_Widen: - // FIXME: - break; - default: - break; - } - - return NULL; -} - -static guint16 vector_t_methods [] = { - SN_ctor, - SN_CopyTo, - SN_Equals, - SN_GreaterThan, - SN_GreaterThanOrEqual, - SN_LessThan, - SN_LessThanOrEqual, - SN_Max, - SN_Min, - SN_get_AllBitsSet, - SN_get_Count, - SN_get_Item, - SN_get_One, - SN_get_Zero, - SN_op_Addition, - SN_op_BitwiseAnd, - SN_op_BitwiseOr, - SN_op_Division, - SN_op_Equality, - SN_op_ExclusiveOr, - SN_op_Explicit, - SN_op_Inequality, - SN_op_Multiply, - SN_op_Subtraction -}; - -static MonoInst* -emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *ins; - MonoType *type, *etype; - MonoClass *klass; - int size, len, id; - gboolean is_unsigned; - - static const float r4_one = 1.0f; - static const double r8_one = 1.0; - - id = lookup_intrins (vector_t_methods, sizeof (vector_t_methods), cmethod); - if (id == -1) - return NULL; - - klass = cmethod->klass; - type = m_class_get_byval_arg (klass); - etype = mono_class_get_context (klass)->class_inst->type_argv [0]; - size = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - g_assert (size); - len = register_size / size; - - if (!MONO_TYPE_IS_PRIMITIVE (etype) || etype->type == MONO_TYPE_CHAR || etype->type == MONO_TYPE_BOOLEAN) - return NULL; - - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD intrinsic %s\n", name); - g_free (name); - } - - switch (id) { - case SN_get_Count: - if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4)) - break; - EMIT_NEW_ICONST (cfg, ins, len); - return ins; - case SN_get_Zero: - g_assert (fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type)); - return emit_simd_ins (cfg, klass, OP_XZERO, -1, -1); - case SN_get_One: { - g_assert (fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type)); - MonoInst *one = NULL; - int expand_opcode = type_to_expand_op (etype); - MONO_INST_NEW (cfg, one, -1); - switch (expand_opcode) { - case OP_EXPAND_R4: - one->opcode = OP_R4CONST; - one->type = STACK_R4; - one->inst_p0 = (void *) &r4_one; - break; - case OP_EXPAND_R8: - one->opcode = OP_R8CONST; - one->type = STACK_R8; - one->inst_p0 = (void *) &r8_one; - break; - default: - one->opcode = OP_ICONST; - one->type = STACK_I4; - one->inst_c0 = 1; - break; - } - one->dreg = alloc_dreg (cfg, (MonoStackType)one->type); - MONO_ADD_INS (cfg->cbb, one); - return emit_simd_ins (cfg, klass, expand_opcode, one->dreg, -1); - } - case SN_get_AllBitsSet: { - /* Compare a zero vector with itself */ - ins = emit_simd_ins (cfg, klass, OP_XZERO, -1, -1); - return emit_xcompare (cfg, klass, etype->type, ins, ins); - } - case SN_get_Item: { - if (!COMPILE_LLVM (cfg)) - return NULL; - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len); - MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "IndexOutOfRangeException"); - int opcode = -1; - int dreg; - gboolean is64 = FALSE; - switch (etype->type) { - case MONO_TYPE_I8: - case MONO_TYPE_U8: - opcode = OP_XEXTRACT_I64; - is64 = TRUE; - dreg = alloc_lreg (cfg); - break; - case MONO_TYPE_R8: - opcode = OP_XEXTRACT_R8; - dreg = alloc_freg (cfg); - break; - case MONO_TYPE_R4: - g_assert (cfg->r4fp); - opcode = OP_XEXTRACT_R4; - dreg = alloc_freg (cfg); - break; - default: - opcode = OP_XEXTRACT_I32; - dreg = alloc_ireg (cfg); - break; - } - MONO_INST_NEW (cfg, ins, opcode); - ins->dreg = dreg; - ins->sreg1 = load_simd_vreg (cfg, cmethod, args [0], NULL); - ins->sreg2 = args [1]->dreg; - ins->inst_c0 = etype->type; - mini_type_to_eval_stack_type (cfg, etype, ins); - MONO_ADD_INS (cfg->cbb, ins); - return ins; - } - case SN_ctor: - if (fsig->param_count == 1 && mono_metadata_type_equal (fsig->params [0], etype)) { - int dreg = load_simd_vreg (cfg, cmethod, args [0], NULL); - - int opcode = type_to_expand_op (etype); - ins = emit_simd_ins (cfg, klass, opcode, args [1]->dreg, -1); - ins->dreg = dreg; - return ins; - } - if ((fsig->param_count == 1 || fsig->param_count == 2) && (fsig->params [0]->type == MONO_TYPE_SZARRAY)) { - MonoInst *array_ins = args [1]; - MonoInst *index_ins; - MonoInst *ldelema_ins; - MonoInst *var; - int end_index_reg; - - if (args [0]->opcode != OP_LDADDR) - return NULL; - - /* .ctor (T[]) or .ctor (T[], index) */ - - if (fsig->param_count == 2) { - index_ins = args [2]; - } else { - EMIT_NEW_ICONST (cfg, index_ins, 0); - } - - /* Emit index check for the end (index + len - 1 < array length) */ - end_index_reg = alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, OP_IADD_IMM, end_index_reg, index_ins->dreg, len - 1); - MONO_EMIT_BOUNDS_CHECK (cfg, array_ins->dreg, MonoArray, max_length, end_index_reg); - - /* Load the array slice into the simd reg */ - ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE); - g_assert (args [0]->opcode == OP_LDADDR); - var = (MonoInst*)args [0]->inst_p0; - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADX_MEMBASE, var->dreg, ldelema_ins->dreg, 0); - ins->klass = cmethod->klass; - return args [0]; - } - break; - case SN_CopyTo: - if ((fsig->param_count == 1 || fsig->param_count == 2) && (fsig->params [0]->type == MONO_TYPE_SZARRAY)) { - MonoInst *array_ins = args [1]; - MonoInst *index_ins; - MonoInst *ldelema_ins; - int val_vreg, end_index_reg; - - val_vreg = load_simd_vreg (cfg, cmethod, args [0], NULL); - - /* CopyTo (T[]) or CopyTo (T[], index) */ - - if (fsig->param_count == 2) { - index_ins = args [2]; - } else { - EMIT_NEW_ICONST (cfg, index_ins, 0); - } - - /* CopyTo () does complicated argument checks */ - mini_emit_bounds_check_offset (cfg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), index_ins->dreg, "ArgumentOutOfRangeException"); - end_index_reg = alloc_ireg (cfg); - int len_reg = alloc_ireg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, len_reg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), MONO_INST_INVARIANT_LOAD); - EMIT_NEW_BIALU (cfg, ins, OP_ISUB, end_index_reg, len_reg, index_ins->dreg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, end_index_reg, len); - MONO_EMIT_NEW_COND_EXC (cfg, LT, "ArgumentException"); - - /* Load the array slice into the simd reg */ - ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, FALSE, FALSE); - EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ldelema_ins->dreg, 0, val_vreg); - ins->klass = cmethod->klass; - return ins; - } - break; - case SN_Equals: - if (fsig->param_count == 1 && fsig->ret->type == MONO_TYPE_BOOLEAN && mono_metadata_type_equal (fsig->params [0], type)) { - int sreg1 = load_simd_vreg (cfg, cmethod, args [0], NULL); - - return emit_simd_ins (cfg, klass, OP_XEQUAL, sreg1, args [1]->dreg); - } else if (fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)) { - /* Per element equality */ - return emit_xcompare (cfg, klass, etype->type, args [0], args [1]); - } - break; - case SN_op_Equality: - case SN_op_Inequality: - g_assert (fsig->param_count == 2 && fsig->ret->type == MONO_TYPE_BOOLEAN && - mono_metadata_type_equal (fsig->params [0], type) && - mono_metadata_type_equal (fsig->params [1], type)); - ins = emit_simd_ins (cfg, klass, OP_XEQUAL, args [0]->dreg, args [1]->dreg); - if (id == SN_op_Inequality) { - int sreg = ins->dreg; - int dreg = alloc_ireg (cfg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, sreg, 0); - EMIT_NEW_UNALU (cfg, ins, OP_CEQ, dreg, -1); - } - return ins; - case SN_GreaterThan: - case SN_GreaterThanOrEqual: - case SN_LessThan: - case SN_LessThanOrEqual: - g_assert (fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)); - is_unsigned = etype->type == MONO_TYPE_U1 || etype->type == MONO_TYPE_U2 || etype->type == MONO_TYPE_U4 || etype->type == MONO_TYPE_U8; - ins = emit_xcompare (cfg, klass, etype->type, args [0], args [1]); - switch (id) { - case SN_GreaterThan: - ins->inst_c0 = is_unsigned ? CMP_GT_UN : CMP_GT; - break; - case SN_GreaterThanOrEqual: - ins->inst_c0 = is_unsigned ? CMP_GE_UN : CMP_GE; - break; - case SN_LessThan: - ins->inst_c0 = is_unsigned ? CMP_LT_UN : CMP_LT; - break; - case SN_LessThanOrEqual: - ins->inst_c0 = is_unsigned ? CMP_LE_UN : CMP_LE; - break; - default: - g_assert_not_reached (); - } - return ins; - case SN_op_Explicit: - return emit_simd_ins (cfg, klass, OP_XCAST, args [0]->dreg, -1); - case SN_op_Addition: - case SN_op_Subtraction: - case SN_op_Division: - case SN_op_Multiply: - case SN_op_BitwiseAnd: - case SN_op_BitwiseOr: - case SN_op_ExclusiveOr: - case SN_Max: - case SN_Min: - if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type))) - return NULL; - ins = emit_simd_ins (cfg, klass, OP_XBINOP, args [0]->dreg, args [1]->dreg); - ins->inst_c1 = etype->type; - - if (etype->type == MONO_TYPE_R4 || etype->type == MONO_TYPE_R8) { - switch (id) { - case SN_op_Addition: - ins->inst_c0 = OP_FADD; - break; - case SN_op_Subtraction: - ins->inst_c0 = OP_FSUB; - break; - case SN_op_Multiply: - ins->inst_c0 = OP_FMUL; - break; - case SN_op_Division: - ins->inst_c0 = OP_FDIV; - break; - case SN_Max: - ins->inst_c0 = OP_FMAX; - break; - case SN_Min: - ins->inst_c0 = OP_FMIN; - break; - default: - NULLIFY_INS (ins); - return NULL; - } - } else { - switch (id) { - case SN_op_Addition: - ins->inst_c0 = OP_IADD; - break; - case SN_op_Subtraction: - ins->inst_c0 = OP_ISUB; - break; - /* - case SN_op_Division: - ins->inst_c0 = OP_IDIV; - break; - case SN_op_Multiply: - ins->inst_c0 = OP_IMUL; - break; - */ - case SN_op_BitwiseAnd: - ins->inst_c0 = OP_IAND; - break; - case SN_op_BitwiseOr: - ins->inst_c0 = OP_IOR; - break; - case SN_op_ExclusiveOr: - ins->inst_c0 = OP_IXOR; - break; - case SN_Max: - ins->inst_c0 = OP_IMAX; - break; - case SN_Min: - ins->inst_c0 = OP_IMIN; - break; - default: - NULLIFY_INS (ins); - return NULL; - } - } - return ins; - default: - break; - } - - return NULL; -} -#endif // TARGET_AMD64 - -static MonoInst* -emit_invalid_operation (MonoCompile *cfg, const char* message) -{ - mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); - mono_error_set_generic_error (cfg->error, "System", "InvalidOperationException", "%s", message); - return NULL; -} - -#ifdef TARGET_ARM64 - - -static SimdIntrinsic armbase_methods [] = { - {SN_LeadingSignCount}, - {SN_LeadingZeroCount}, - {SN_MultiplyHigh}, - {SN_ReverseElementBits}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic crc32_methods [] = { - {SN_ComputeCrc32}, - {SN_ComputeCrc32C}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic sha1_methods [] = { - {SN_FixedRotate, OP_XOP_X_X, SIMD_OP_ARM64_SHA1H}, - {SN_HashUpdateChoose, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1C}, - {SN_HashUpdateMajority, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1M}, - {SN_HashUpdateParity, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1P}, - {SN_ScheduleUpdate0, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1SU0}, - {SN_ScheduleUpdate1, OP_XOP_X_X_X, SIMD_OP_ARM64_SHA1SU1}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic sha256_methods [] = { - {SN_HashUpdate1, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA256H}, - {SN_HashUpdate2, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA256H2}, - {SN_ScheduleUpdate0, OP_XOP_X_X_X, SIMD_OP_ARM64_SHA256SU0}, - {SN_ScheduleUpdate1, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA256SU1}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic advsimd_methods [] = { - {SN_Abs} -}; - -static MonoInst* -emit_arm64_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - // Arm64 intrinsics are LLVM-only - if (!COMPILE_LLVM (cfg)) - return NULL; - - MonoInst *ins; - gboolean supported, is_64bit; - MonoClass *klass = cmethod->klass; - MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; - gboolean arg0_i32 = (arg0_type == MONO_TYPE_I4) || (arg0_type == MONO_TYPE_U4); - SimdIntrinsic *info; - MonoCPUFeatures feature = -1; - SimdIntrinsic *intrinsics = NULL; - int intrinsics_size; - int id = -1; - gboolean jit_supported = FALSE; - - if (is_hw_intrinsics_class (klass, "ArmBase", &is_64bit)) { - info = lookup_intrins_info (armbase_methods, sizeof (armbase_methods), cmethod); - if (!info) - return NULL; - - supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_BASE) != 0; - - switch (info->id) { - case SN_get_IsSupported: - EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); - ins->type = STACK_I4; - return ins; - case SN_LeadingZeroCount: - return emit_simd_ins_for_sig (cfg, klass, arg0_i32 ? OP_LZCNT32 : OP_LZCNT64, 0, arg0_type, fsig, args); - case SN_LeadingSignCount: - return emit_simd_ins_for_sig (cfg, klass, arg0_i32 ? OP_LSCNT32 : OP_LSCNT64, 0, arg0_type, fsig, args); - case SN_MultiplyHigh: - return emit_simd_ins_for_sig (cfg, klass, - (arg0_type == MONO_TYPE_I8 ? OP_ARM64_SMULH : OP_ARM64_UMULH), 0, arg0_type, fsig, args); - case SN_ReverseElementBits: - return emit_simd_ins_for_sig (cfg, klass, - (is_64bit ? OP_XOP_I8_I8 : OP_XOP_I4_I4), - (is_64bit ? SIMD_OP_ARM64_RBIT64 : SIMD_OP_ARM64_RBIT32), - arg0_type, fsig, args); - default: - g_assert_not_reached (); // if a new API is added we need to either implement it or change IsSupported to false - } - } - - if (is_hw_intrinsics_class (klass, "Crc32", &is_64bit)) { - info = lookup_intrins_info (crc32_methods, sizeof (crc32_methods), cmethod); - if (!info) - return NULL; - - supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_CRC) != 0; - - switch (info->id) { - case SN_get_IsSupported: - EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); - ins->type = STACK_I4; - return ins; - case SN_ComputeCrc32: - case SN_ComputeCrc32C: { - SimdOp op = (SimdOp)0; - gboolean is_c = info->id == SN_ComputeCrc32C; - switch (get_underlying_type (fsig->params [1])) { - case MONO_TYPE_U1: op = is_c ? SIMD_OP_ARM64_CRC32CB : SIMD_OP_ARM64_CRC32B; break; - case MONO_TYPE_U2: op = is_c ? SIMD_OP_ARM64_CRC32CH : SIMD_OP_ARM64_CRC32H; break; - case MONO_TYPE_U4: op = is_c ? SIMD_OP_ARM64_CRC32CW : SIMD_OP_ARM64_CRC32W; break; - case MONO_TYPE_U8: op = is_c ? SIMD_OP_ARM64_CRC32CX : SIMD_OP_ARM64_CRC32X; break; - default: g_assert_not_reached (); break; - } - return emit_simd_ins_for_sig (cfg, klass, is_64bit ? OP_XOP_I4_I4_I8 : OP_XOP_I4_I4_I4, op, arg0_type, fsig, args); - } - default: - g_assert_not_reached (); // if a new API is added we need to either implement it or change IsSupported to false - } - } - - if (is_hw_intrinsics_class (klass, "Sha256", &is_64bit)) { - feature = MONO_CPU_ARM64_CRYPTO; - intrinsics = sha256_methods; - intrinsics_size = sizeof (sha256_methods); - } - - if (is_hw_intrinsics_class (klass, "Sha1", &is_64bit)) { - feature = MONO_CPU_ARM64_CRYPTO; - intrinsics = sha1_methods; - intrinsics_size = sizeof (sha1_methods); - } - - /* - * Common logic for all instruction sets - */ - if (intrinsics) { - if (!COMPILE_LLVM (cfg) && !jit_supported) - return NULL; - info = lookup_intrins_info (intrinsics, intrinsics_size, cmethod); - if (!info) - return NULL; - id = info->id; - - if (feature) - supported = (mini_get_cpu_features (cfg) & feature) != 0; - else - supported = TRUE; - if (id == SN_get_IsSupported) { - EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); - return ins; - } - - if (!supported && cfg->compile_aot) { - // Can't emit non-supported llvm intrinsics - if (cfg->method != cmethod) { - // Keep the original call so we end up in the intrinsic method - return NULL; - } else { - // Emit an exception from the intrinsic method - mono_emit_jit_icall (cfg, mono_throw_not_supported, NULL); - return NULL; - } - } - - if (info->op != 0) - return emit_simd_ins_for_sig (cfg, klass, info->op, info->instc0, arg0_type, fsig, args); - } - - if (is_hw_intrinsics_class (klass, "AdvSimd", &is_64bit)) { - info = lookup_intrins_info (advsimd_methods, sizeof (advsimd_methods), cmethod); - - if (!info) - return NULL; - - supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_ADVSIMD) != 0; - - switch (info -> id) { - case SN_Abs: { - SimdOp op = (SimdOp)0; - switch (get_underlying_type (fsig->params [0])) { - case MONO_TYPE_R8: - op = SIMD_OP_LLVM_DABS; - break; - case MONO_TYPE_R4: - op = SIMD_OP_LLVM_FABS; - break; - case MONO_TYPE_I1: - op = SIMD_OP_LLVM_I8ABS; - break; - case MONO_TYPE_I2: - op = SIMD_OP_LLVM_I16ABS; - break; - case MONO_TYPE_I4: - op = SIMD_OP_LLVM_I32ABS; - break; - case MONO_TYPE_I8: - op = SIMD_OP_LLVM_I64ABS; - break; - } - - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X, op, arg0_type, fsig, args); - } - } - - } - - return NULL; -} -#endif // TARGET_ARM64 - -#ifdef TARGET_AMD64 - -static SimdIntrinsic sse_methods [] = { - {SN_Add, OP_XBINOP, OP_FADD}, - {SN_AddScalar, OP_SSE_ADDSS}, - {SN_And, OP_SSE_AND}, - {SN_AndNot, OP_SSE_ANDN}, - {SN_CompareEqual, OP_XCOMPARE_FP, CMP_EQ}, - {SN_CompareGreaterThan, OP_XCOMPARE_FP,CMP_GT}, - {SN_CompareGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_GE}, - {SN_CompareLessThan, OP_XCOMPARE_FP, CMP_LT}, - {SN_CompareLessThanOrEqual, OP_XCOMPARE_FP, CMP_LE}, - {SN_CompareNotEqual, OP_XCOMPARE_FP, CMP_NE}, - {SN_CompareNotGreaterThan, OP_XCOMPARE_FP, CMP_LE}, - {SN_CompareNotGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_LT}, - {SN_CompareNotLessThan, OP_XCOMPARE_FP, CMP_GE}, - {SN_CompareNotLessThanOrEqual, OP_XCOMPARE_FP, CMP_GT}, - {SN_CompareOrdered, OP_XCOMPARE_FP, CMP_ORD}, - {SN_CompareScalarEqual, OP_SSE_CMPSS, CMP_EQ}, - {SN_CompareScalarGreaterThan, OP_SSE_CMPSS, CMP_GT}, - {SN_CompareScalarGreaterThanOrEqual, OP_SSE_CMPSS, CMP_GE}, - {SN_CompareScalarLessThan, OP_SSE_CMPSS, CMP_LT}, - {SN_CompareScalarLessThanOrEqual, OP_SSE_CMPSS, CMP_LE}, - {SN_CompareScalarNotEqual, OP_SSE_CMPSS, CMP_NE}, - {SN_CompareScalarNotGreaterThan, OP_SSE_CMPSS, CMP_LE}, - {SN_CompareScalarNotGreaterThanOrEqual, OP_SSE_CMPSS, CMP_LT}, - {SN_CompareScalarNotLessThan, OP_SSE_CMPSS, CMP_GE}, - {SN_CompareScalarNotLessThanOrEqual, OP_SSE_CMPSS, CMP_GT}, - {SN_CompareScalarOrdered, OP_SSE_CMPSS, CMP_ORD}, - {SN_CompareScalarOrderedEqual, OP_SSE_COMISS, CMP_EQ}, - {SN_CompareScalarOrderedGreaterThan, OP_SSE_COMISS, CMP_GT}, - {SN_CompareScalarOrderedGreaterThanOrEqual, OP_SSE_COMISS, CMP_GE}, - {SN_CompareScalarOrderedLessThan, OP_SSE_COMISS, CMP_LT}, - {SN_CompareScalarOrderedLessThanOrEqual, OP_SSE_COMISS, CMP_LE}, - {SN_CompareScalarOrderedNotEqual, OP_SSE_COMISS, CMP_NE}, - {SN_CompareScalarUnordered, OP_SSE_CMPSS, CMP_UNORD}, - {SN_CompareScalarUnorderedEqual, OP_SSE_UCOMISS, CMP_EQ}, - {SN_CompareScalarUnorderedGreaterThan, OP_SSE_UCOMISS, CMP_GT}, - {SN_CompareScalarUnorderedGreaterThanOrEqual, OP_SSE_UCOMISS, CMP_GE}, - {SN_CompareScalarUnorderedLessThan, OP_SSE_UCOMISS, CMP_LT}, - {SN_CompareScalarUnorderedLessThanOrEqual, OP_SSE_UCOMISS, CMP_LE}, - {SN_CompareScalarUnorderedNotEqual, OP_SSE_UCOMISS, CMP_NE}, - {SN_CompareUnordered, OP_XCOMPARE_FP, CMP_UNORD}, - {SN_ConvertScalarToVector128Single}, - {SN_ConvertToInt32, OP_XOP_I4_X, SIMD_OP_SSE_CVTSS2SI}, - {SN_ConvertToInt32WithTruncation, OP_XOP_I4_X, SIMD_OP_SSE_CVTTSS2SI}, - {SN_ConvertToInt64, OP_XOP_I8_X, SIMD_OP_SSE_CVTSS2SI64}, - {SN_ConvertToInt64WithTruncation, OP_XOP_I8_X, SIMD_OP_SSE_CVTTSS2SI64}, - {SN_Divide, OP_XBINOP, OP_FDIV}, - {SN_DivideScalar, OP_SSE_DIVSS}, - {SN_LoadAlignedVector128, OP_SSE_LOADU, 16 /* alignment */}, - {SN_LoadHigh, OP_SSE_MOVHPS_LOAD}, - {SN_LoadLow, OP_SSE_MOVLPS_LOAD}, - {SN_LoadScalarVector128, OP_SSE_MOVSS}, - {SN_LoadVector128, OP_SSE_LOADU, 1 /* alignment */}, - {SN_Max, OP_XOP_X_X_X, SIMD_OP_SSE_MAXPS}, - {SN_MaxScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MAXSS}, - {SN_Min, OP_XOP_X_X_X, SIMD_OP_SSE_MINPS}, - {SN_MinScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MINSS}, - {SN_MoveHighToLow, OP_SSE_MOVEHL}, - {SN_MoveLowToHigh, OP_SSE_MOVELH}, - {SN_MoveMask, OP_SSE_MOVMSK}, - {SN_MoveScalar, OP_SSE_MOVS2}, - {SN_Multiply, OP_XBINOP, OP_FMUL}, - {SN_MultiplyScalar, OP_SSE_MULSS}, - {SN_Or, OP_SSE_OR}, - {SN_Prefetch0, OP_SSE_PREFETCHT0}, - {SN_Prefetch1, OP_SSE_PREFETCHT1}, - {SN_Prefetch2, OP_SSE_PREFETCHT2}, - {SN_PrefetchNonTemporal, OP_SSE_PREFETCHNTA}, - {SN_Reciprocal, OP_XOP_X_X, SIMD_OP_SSE_RCPPS}, - {SN_ReciprocalScalar}, - {SN_ReciprocalSqrt, OP_XOP_X_X, SIMD_OP_SSE_RSQRTPS}, - {SN_ReciprocalSqrtScalar}, - {SN_Shuffle}, - {SN_Sqrt, OP_XOP_X_X, SIMD_OP_SSE_SQRTPS}, - {SN_SqrtScalar}, - {SN_Store, OP_SSE_STORE, 1 /* alignment */}, - {SN_StoreAligned, OP_SSE_STORE, 16 /* alignment */}, - {SN_StoreAlignedNonTemporal, OP_SSE_MOVNTPS, 16 /* alignment */}, - {SN_StoreFence, OP_XOP, SIMD_OP_SSE_SFENCE}, - {SN_StoreHigh, OP_SSE_MOVHPS_STORE}, - {SN_StoreLow, OP_SSE_MOVLPS_STORE}, - {SN_StoreScalar, OP_SSE_MOVSS_STORE}, - {SN_Subtract, OP_XBINOP, OP_FSUB}, - {SN_SubtractScalar, OP_SSE_SUBSS}, - {SN_UnpackHigh, OP_SSE_UNPACKHI}, - {SN_UnpackLow, OP_SSE_UNPACKLO}, - {SN_Xor, OP_SSE_XOR}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic sse2_methods [] = { - {SN_Add}, - {SN_AddSaturate, OP_SSE2_ADDS}, - {SN_AddScalar, OP_SSE2_ADDSD}, - {SN_And, OP_SSE_AND}, - {SN_AndNot, OP_SSE_ANDN}, - {SN_Average}, - {SN_CompareEqual}, - {SN_CompareGreaterThan}, - {SN_CompareGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_GE}, - {SN_CompareLessThan}, - {SN_CompareLessThanOrEqual, OP_XCOMPARE_FP, CMP_LE}, - {SN_CompareNotEqual, OP_XCOMPARE_FP, CMP_NE}, - {SN_CompareNotGreaterThan, OP_XCOMPARE_FP, CMP_LE}, - {SN_CompareNotGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_LT}, - {SN_CompareNotLessThan, OP_XCOMPARE_FP, CMP_GE}, - {SN_CompareNotLessThanOrEqual, OP_XCOMPARE_FP, CMP_GT}, - {SN_CompareOrdered, OP_XCOMPARE_FP, CMP_ORD}, - {SN_CompareScalarEqual, OP_SSE2_CMPSD, CMP_EQ}, - {SN_CompareScalarGreaterThan, OP_SSE2_CMPSD, CMP_GT}, - {SN_CompareScalarGreaterThanOrEqual, OP_SSE2_CMPSD, CMP_GE}, - {SN_CompareScalarLessThan, OP_SSE2_CMPSD, CMP_LT}, - {SN_CompareScalarLessThanOrEqual, OP_SSE2_CMPSD, CMP_LE}, - {SN_CompareScalarNotEqual, OP_SSE2_CMPSD, CMP_NE}, - {SN_CompareScalarNotGreaterThan, OP_SSE2_CMPSD, CMP_LE}, - {SN_CompareScalarNotGreaterThanOrEqual, OP_SSE2_CMPSD, CMP_LT}, - {SN_CompareScalarNotLessThan, OP_SSE2_CMPSD, CMP_GE}, - {SN_CompareScalarNotLessThanOrEqual, OP_SSE2_CMPSD, CMP_GT}, - {SN_CompareScalarOrdered, OP_SSE2_CMPSD, CMP_ORD}, - {SN_CompareScalarOrderedEqual, OP_SSE2_COMISD, CMP_EQ}, - {SN_CompareScalarOrderedGreaterThan, OP_SSE2_COMISD, CMP_GT}, - {SN_CompareScalarOrderedGreaterThanOrEqual, OP_SSE2_COMISD, CMP_GE}, - {SN_CompareScalarOrderedLessThan, OP_SSE2_COMISD, CMP_LT}, - {SN_CompareScalarOrderedLessThanOrEqual, OP_SSE2_COMISD, CMP_LE}, - {SN_CompareScalarOrderedNotEqual, OP_SSE2_COMISD, CMP_NE}, - {SN_CompareScalarUnordered, OP_SSE2_CMPSD, CMP_UNORD}, - {SN_CompareScalarUnorderedEqual, OP_SSE2_UCOMISD, CMP_EQ}, - {SN_CompareScalarUnorderedGreaterThan, OP_SSE2_UCOMISD, CMP_GT}, - {SN_CompareScalarUnorderedGreaterThanOrEqual, OP_SSE2_UCOMISD, CMP_GE}, - {SN_CompareScalarUnorderedLessThan, OP_SSE2_UCOMISD, CMP_LT}, - {SN_CompareScalarUnorderedLessThanOrEqual, OP_SSE2_UCOMISD, CMP_LE}, - {SN_CompareScalarUnorderedNotEqual, OP_SSE2_UCOMISD, CMP_NE}, - {SN_CompareUnordered, OP_XCOMPARE_FP, CMP_UNORD}, - {SN_ConvertScalarToVector128Double}, - {SN_ConvertScalarToVector128Int32}, - {SN_ConvertScalarToVector128Int64}, - {SN_ConvertScalarToVector128Single, OP_XOP_X_X_X, SIMD_OP_SSE_CVTSD2SS}, - {SN_ConvertScalarToVector128UInt32}, - {SN_ConvertScalarToVector128UInt64}, - {SN_ConvertToInt32}, - {SN_ConvertToInt32WithTruncation, OP_XOP_I4_X, SIMD_OP_SSE_CVTTSD2SI}, - {SN_ConvertToInt64}, - {SN_ConvertToInt64WithTruncation, OP_XOP_I8_X, SIMD_OP_SSE_CVTTSD2SI64}, - {SN_ConvertToUInt32}, - {SN_ConvertToUInt64}, - {SN_ConvertToVector128Double}, - {SN_ConvertToVector128Int32}, - {SN_ConvertToVector128Int32WithTruncation}, - {SN_ConvertToVector128Single}, - {SN_Divide, OP_XBINOP, OP_FDIV}, - {SN_DivideScalar, OP_SSE2_DIVSD}, - {SN_Extract}, - {SN_Insert}, - {SN_LoadAlignedVector128}, - {SN_LoadFence, OP_XOP, SIMD_OP_SSE_LFENCE}, - {SN_LoadHigh, OP_SSE2_MOVHPD_LOAD}, - {SN_LoadLow, OP_SSE2_MOVLPD_LOAD}, - {SN_LoadScalarVector128}, - {SN_LoadVector128}, - {SN_MaskMove, OP_SSE2_MASKMOVDQU}, - {SN_Max}, - {SN_MaxScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MAXSD}, - {SN_MemoryFence, OP_XOP, SIMD_OP_SSE_MFENCE}, - {SN_Min}, // FIXME: - {SN_MinScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MINSD}, - {SN_MoveMask, OP_SSE_MOVMSK}, - {SN_MoveScalar}, - {SN_Multiply}, - {SN_MultiplyAddAdjacent, OP_XOP_X_X_X, SIMD_OP_SSE_PMADDWD}, - {SN_MultiplyHigh}, - {SN_MultiplyLow, OP_PMULW}, - {SN_MultiplyScalar, OP_SSE2_MULSD}, - {SN_Or, OP_SSE_OR}, - {SN_PackSignedSaturate}, - {SN_PackUnsignedSaturate}, - {SN_ShiftLeftLogical}, - {SN_ShiftLeftLogical128BitLane}, - {SN_ShiftRightArithmetic}, - {SN_ShiftRightLogical}, - {SN_ShiftRightLogical128BitLane}, - {SN_Shuffle}, - {SN_ShuffleHigh}, - {SN_ShuffleLow}, - {SN_Sqrt, OP_XOP_X_X, SIMD_OP_SSE_SQRTPD}, - {SN_SqrtScalar}, - {SN_Store, OP_SSE_STORE, 1 /* alignment */}, - {SN_StoreAligned, OP_SSE_STORE, 16 /* alignment */}, - {SN_StoreAlignedNonTemporal, OP_SSE_MOVNTPS, 16 /* alignment */}, - {SN_StoreHigh, OP_SSE2_MOVHPD_STORE}, - {SN_StoreLow, OP_SSE2_MOVLPD_STORE}, - {SN_StoreNonTemporal, OP_SSE_MOVNTPS, 1 /* alignment */}, - {SN_StoreScalar, OP_SSE_STORES}, - {SN_Subtract}, - {SN_SubtractSaturate, OP_SSE2_SUBS}, - {SN_SubtractScalar, OP_SSE2_SUBSD}, - {SN_SumAbsoluteDifferences, OP_XOP_X_X_X, SIMD_OP_SSE_PSADBW}, - {SN_UnpackHigh, OP_SSE_UNPACKHI}, - {SN_UnpackLow, OP_SSE_UNPACKLO}, - {SN_Xor, OP_SSE_XOR}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic sse3_methods [] = { - {SN_AddSubtract}, - {SN_HorizontalAdd}, - {SN_HorizontalSubtract}, - {SN_LoadAndDuplicateToVector128, OP_SSE3_MOVDDUP_MEM}, - {SN_LoadDquVector128, OP_XOP_X_I, SIMD_OP_SSE_LDDQU}, - {SN_MoveAndDuplicate, OP_SSE3_MOVDDUP}, - {SN_MoveHighAndDuplicate, OP_SSE3_MOVSHDUP}, - {SN_MoveLowAndDuplicate, OP_SSE3_MOVSLDUP}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic ssse3_methods [] = { - {SN_Abs, OP_SSSE3_ABS}, - {SN_AlignRight}, - {SN_HorizontalAdd}, - {SN_HorizontalAddSaturate, OP_XOP_X_X_X, SIMD_OP_SSE_PHADDSW}, - {SN_HorizontalSubtract}, - {SN_HorizontalSubtractSaturate, OP_XOP_X_X_X, SIMD_OP_SSE_PHSUBSW}, - {SN_MultiplyAddAdjacent, OP_XOP_X_X_X, SIMD_OP_SSE_PMADDUBSW}, - {SN_MultiplyHighRoundScale, OP_XOP_X_X_X, SIMD_OP_SSE_PMULHRSW}, - {SN_Shuffle, OP_SSSE3_SHUFFLE}, - {SN_Sign}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic sse41_methods [] = { - {SN_Blend}, - {SN_BlendVariable}, - {SN_Ceiling, OP_SSE41_ROUNDP, 10 /*round mode*/}, - {SN_CeilingScalar, 0, 10 /*round mode*/}, - {SN_CompareEqual, OP_XCOMPARE, CMP_EQ}, - {SN_ConvertToVector128Int16, OP_SSE_CVTII, MONO_TYPE_I2}, - {SN_ConvertToVector128Int32, OP_SSE_CVTII, MONO_TYPE_I4}, - {SN_ConvertToVector128Int64, OP_SSE_CVTII, MONO_TYPE_I8}, - {SN_DotProduct}, - {SN_Extract}, - {SN_Floor, OP_SSE41_ROUNDP, 9 /*round mode*/}, - {SN_FloorScalar, 0, 9 /*round mode*/}, - {SN_Insert}, - {SN_LoadAlignedVector128NonTemporal, OP_SSE41_LOADANT}, - {SN_Max, OP_XBINOP, OP_IMAX}, - {SN_Min, OP_XBINOP, OP_IMIN}, - {SN_MinHorizontal, OP_XOP_X_X, SIMD_OP_SSE_PHMINPOSUW}, - {SN_MultipleSumAbsoluteDifferences}, - {SN_Multiply, OP_SSE41_MUL}, - {SN_MultiplyLow, OP_SSE41_MULLO}, - {SN_PackUnsignedSaturate, OP_XOP_X_X_X, SIMD_OP_SSE_PACKUSDW}, - {SN_RoundCurrentDirection, OP_SSE41_ROUNDP, 4 /*round mode*/}, - {SN_RoundCurrentDirectionScalar, 0, 4 /*round mode*/}, - {SN_RoundToNearestInteger, OP_SSE41_ROUNDP, 8 /*round mode*/}, - {SN_RoundToNearestIntegerScalar, 0, 8 /*round mode*/}, - {SN_RoundToNegativeInfinity, OP_SSE41_ROUNDP, 9 /*round mode*/}, - {SN_RoundToNegativeInfinityScalar, 0, 9 /*round mode*/}, - {SN_RoundToPositiveInfinity, OP_SSE41_ROUNDP, 10 /*round mode*/}, - {SN_RoundToPositiveInfinityScalar, 0, 10 /*round mode*/}, - {SN_RoundToZero, OP_SSE41_ROUNDP, 11 /*round mode*/}, - {SN_RoundToZeroScalar, 0, 11 /*round mode*/}, - {SN_TestC, OP_XOP_I4_X_X, SIMD_OP_SSE_TESTC}, - {SN_TestNotZAndNotC, OP_XOP_I4_X_X, SIMD_OP_SSE_TESTNZ}, - {SN_TestZ, OP_XOP_I4_X_X, SIMD_OP_SSE_TESTZ}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic sse42_methods [] = { - {SN_CompareGreaterThan, OP_XCOMPARE, CMP_GT}, - {SN_Crc32}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic pclmulqdq_methods [] = { - {SN_CarrylessMultiply}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic aes_methods [] = { - {SN_Decrypt, OP_XOP_X_X_X, SIMD_OP_AES_DEC}, - {SN_DecryptLast, OP_XOP_X_X_X, SIMD_OP_AES_DECLAST}, - {SN_Encrypt, OP_XOP_X_X_X, SIMD_OP_AES_ENC}, - {SN_EncryptLast, OP_XOP_X_X_X, SIMD_OP_AES_ENCLAST}, - {SN_InverseMixColumns, OP_XOP_X_X, SIMD_OP_AES_IMC}, - {SN_KeygenAssist}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic popcnt_methods [] = { - {SN_PopCount}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic lzcnt_methods [] = { - {SN_LeadingZeroCount}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic bmi1_methods [] = { - {SN_AndNot}, - {SN_BitFieldExtract}, - {SN_ExtractLowestSetBit}, - {SN_GetMaskUpToLowestSetBit}, - {SN_ResetLowestSetBit}, - {SN_TrailingZeroCount}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic bmi2_methods [] = { - {SN_MultiplyNoFlags}, - {SN_ParallelBitDeposit}, - {SN_ParallelBitExtract}, - {SN_ZeroHighBits}, - {SN_get_IsSupported} -}; - -static SimdIntrinsic x86base_methods [] = { - {SN_BitScanForward}, - {SN_BitScanReverse}, - {SN_get_IsSupported} -}; - -static MonoInst* -emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *ins; - gboolean supported, is_64bit; - MonoClass *klass = cmethod->klass; - MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; - SimdIntrinsic *info = NULL; - MonoCPUFeatures feature = -1; - SimdIntrinsic *intrinsics = NULL; - int intrinsics_size; - int id = -1; - gboolean jit_supported = FALSE; - - if (is_hw_intrinsics_class (klass, "Sse", &is_64bit)) { - feature = MONO_CPU_X86_SSE; - intrinsics = sse_methods; - intrinsics_size = sizeof (sse_methods); - } else if (is_hw_intrinsics_class (klass, "Sse2", &is_64bit)) { - feature = MONO_CPU_X86_SSE2; - intrinsics = sse2_methods; - intrinsics_size = sizeof (sse2_methods); - } else if (is_hw_intrinsics_class (klass, "Sse3", &is_64bit)) { - feature = MONO_CPU_X86_SSE3; - intrinsics = sse3_methods; - intrinsics_size = sizeof (sse3_methods); - } else if (is_hw_intrinsics_class (klass, "Ssse3", &is_64bit)) { - feature = MONO_CPU_X86_SSSE3; - intrinsics = ssse3_methods; - intrinsics_size = sizeof (ssse3_methods); - } else if (is_hw_intrinsics_class (klass, "Sse41", &is_64bit)) { - feature = MONO_CPU_X86_SSE41; - intrinsics = sse41_methods; - intrinsics_size = sizeof (sse41_methods); - } else if (is_hw_intrinsics_class (klass, "Sse42", &is_64bit)) { - feature = MONO_CPU_X86_SSE42; - intrinsics = sse42_methods; - intrinsics_size = sizeof (sse42_methods); - } else if (is_hw_intrinsics_class (klass, "Pclmulqdq", &is_64bit)) { - feature = MONO_CPU_X86_PCLMUL; - intrinsics = pclmulqdq_methods; - intrinsics_size = sizeof (pclmulqdq_methods); - } else if (is_hw_intrinsics_class (klass, "Aes", &is_64bit)) { - feature = MONO_CPU_X86_AES; - intrinsics = aes_methods; - intrinsics_size = sizeof (aes_methods); - } else if (is_hw_intrinsics_class (klass, "Popcnt", &is_64bit)) { - feature = MONO_CPU_X86_POPCNT; - intrinsics = popcnt_methods; - intrinsics_size = sizeof (popcnt_methods); - jit_supported = TRUE; - } else if (is_hw_intrinsics_class (klass, "Lzcnt", &is_64bit)) { - feature = MONO_CPU_X86_LZCNT; - intrinsics = lzcnt_methods; - intrinsics_size = sizeof (lzcnt_methods); - jit_supported = TRUE; - } else if (is_hw_intrinsics_class (klass, "Bmi1", &is_64bit)) { - feature = MONO_CPU_X86_BMI1; - intrinsics = bmi1_methods; - intrinsics_size = sizeof (bmi1_methods); - } else if (is_hw_intrinsics_class (klass, "Bmi2", &is_64bit)) { - feature = MONO_CPU_X86_BMI2; - intrinsics = bmi2_methods; - intrinsics_size = sizeof (bmi2_methods); - } else if (is_hw_intrinsics_class (klass, "X86Base", &is_64bit)) { - feature = 0; - intrinsics = x86base_methods; - intrinsics_size = sizeof (x86base_methods); - } - - /* - * Common logic for all instruction sets - */ - if (intrinsics) { - if (!COMPILE_LLVM (cfg) && !jit_supported) - return NULL; - info = lookup_intrins_info (intrinsics, intrinsics_size, cmethod); - if (!info) - return NULL; - id = info->id; - - if (feature) - supported = (mini_get_cpu_features (cfg) & feature) != 0; - else - supported = TRUE; - if (id == SN_get_IsSupported) { - EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); - return ins; - } - - if (!supported && cfg->compile_aot) { - /* Can't emit non-supported llvm intrinsics */ - if (cfg->method != cmethod) { - /* Keep the original call so we end up in the intrinsic method */ - return NULL; - } else { - /* Emit an exception from the intrinsic method */ - mono_emit_jit_icall (cfg, mono_throw_not_supported, NULL); - return NULL; - } - } - - if (info->op != 0) - return emit_simd_ins_for_sig (cfg, klass, info->op, info->instc0, arg0_type, fsig, args); - } - - /* - * Instruction set specific cases - */ - if (feature == MONO_CPU_X86_SSE) { - switch (id) { - case SN_Shuffle: - if (args [2]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE_SHUFFLE, args [2]->inst_c0, arg0_type, fsig, args); - // FIXME: handle non-constant mask (generate a switch) - return emit_invalid_operation (cfg, "mask in Sse.Shuffle must be constant"); - case SN_ConvertScalarToVector128Single: { - int op = 0; - switch (fsig->params [1]->type) { - case MONO_TYPE_I4: op = OP_SSE_CVTSI2SS; break; - case MONO_TYPE_I8: op = OP_SSE_CVTSI2SS64; break; - default: g_assert_not_reached (); break; - } - return emit_simd_ins_for_sig (cfg, klass, op, 0, 0, fsig, args); - } - case SN_ReciprocalScalar: - case SN_ReciprocalSqrtScalar: - case SN_SqrtScalar: { - int op = 0; - switch (id) { - case SN_ReciprocalScalar: op = OP_SSE_RCPSS; break; - case SN_ReciprocalSqrtScalar: op = OP_SSE_RSQRTSS; break; - case SN_SqrtScalar: op = OP_SSE_SQRTSS; break; - }; - if (fsig->param_count == 1) - return emit_simd_ins (cfg, klass, op, args [0]->dreg, args[0]->dreg); - else if (fsig->param_count == 2) - return emit_simd_ins (cfg, klass, op, args [0]->dreg, args[1]->dreg); - else - g_assert_not_reached (); - break; - } - case SN_LoadScalarVector128: - return NULL; - default: - return NULL; - } - } - - if (feature == MONO_CPU_X86_SSE2) { - switch (id) { - case SN_Subtract: - return emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, arg0_type == MONO_TYPE_R8 ? OP_FSUB : OP_ISUB, arg0_type, fsig, args); - case SN_Add: - return emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, arg0_type == MONO_TYPE_R8 ? OP_FADD : OP_IADD, arg0_type, fsig, args); - case SN_Average: - if (arg0_type == MONO_TYPE_U1) - return emit_simd_ins_for_sig (cfg, klass, OP_PAVGB_UN, -1, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_U2) - return emit_simd_ins_for_sig (cfg, klass, OP_PAVGW_UN, -1, arg0_type, fsig, args); - else - return NULL; - case SN_CompareNotEqual: - return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_NE, arg0_type, fsig, args); - case SN_CompareEqual: - return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_EQ, arg0_type, fsig, args); - case SN_CompareGreaterThan: - return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_GT, arg0_type, fsig, args); - case SN_CompareLessThan: - return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_LT, arg0_type, fsig, args); - case SN_ConvertToInt32: - if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_I4_X, SIMD_OP_SSE_CVTSD2SI, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_I4) - return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I4, 0, arg0_type, fsig, args); - else - return NULL; - case SN_ConvertToInt64: - if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_I8_X, SIMD_OP_SSE_CVTSD2SI64, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_I8) - return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I8, 0 /*element index*/, arg0_type, fsig, args); - else - g_assert_not_reached (); - break; - case SN_ConvertScalarToVector128Double: { - int op = OP_SSE2_CVTSS2SD; - switch (fsig->params [1]->type) { - case MONO_TYPE_I4: op = OP_SSE2_CVTSI2SD; break; - case MONO_TYPE_I8: op = OP_SSE2_CVTSI2SD64; break; - } - return emit_simd_ins_for_sig (cfg, klass, op, 0, 0, fsig, args); - } - case SN_ConvertScalarToVector128Int32: - case SN_ConvertScalarToVector128Int64: - case SN_ConvertScalarToVector128UInt32: - case SN_ConvertScalarToVector128UInt64: - return emit_simd_ins_for_sig (cfg, klass, OP_CREATE_SCALAR, -1, arg0_type, fsig, args); - case SN_ConvertToUInt32: - return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I4, 0 /*element index*/, arg0_type, fsig, args); - case SN_ConvertToUInt64: - return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I8, 0 /*element index*/, arg0_type, fsig, args); - case SN_ConvertToVector128Double: - if (arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTPS2PD, 0, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_I4) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTDQ2PD, 0, arg0_type, fsig, args); - else - return NULL; - case SN_ConvertToVector128Int32: - if (arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTPS2DQ, 0, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTPD2DQ, 0, arg0_type, fsig, args); - else - return NULL; - case SN_ConvertToVector128Int32WithTruncation: - if (arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTTPS2DQ, 0, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTTPD2DQ, 0, arg0_type, fsig, args); - else - return NULL; - case SN_ConvertToVector128Single: - if (arg0_type == MONO_TYPE_I4) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTDQ2PS, 0, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_CVTPD2PS, 0, arg0_type, fsig, args); - else - return NULL; - case SN_LoadAlignedVector128: - return emit_simd_ins_for_sig (cfg, klass, OP_SSE_LOADU, 16 /*alignment*/, arg0_type, fsig, args); - case SN_LoadVector128: - return emit_simd_ins_for_sig (cfg, klass, OP_SSE_LOADU, 1 /*alignment*/, arg0_type, fsig, args); - case SN_MoveScalar: - return emit_simd_ins_for_sig (cfg, klass, fsig->param_count == 2 ? OP_SSE_MOVS2 : OP_SSE_MOVS, -1, arg0_type, fsig, args); - case SN_Max: - switch (arg0_type) { - case MONO_TYPE_U1: - return emit_simd_ins_for_sig (cfg, klass, OP_PMAXB_UN, 0, arg0_type, fsig, args); - case MONO_TYPE_I2: - return emit_simd_ins_for_sig (cfg, klass, OP_PMAXW, 0, arg0_type, fsig, args); - case MONO_TYPE_R8: return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_MAXPD, arg0_type, fsig, args); - default: - g_assert_not_reached (); - break; - } - break; - case SN_Min: - switch (arg0_type) { - case MONO_TYPE_U1: - return emit_simd_ins_for_sig (cfg, klass, OP_PMINB_UN, 0, arg0_type, fsig, args); - case MONO_TYPE_I2: - return emit_simd_ins_for_sig (cfg, klass, OP_PMINW, 0, arg0_type, fsig, args); - case MONO_TYPE_R8: return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_MINPD, arg0_type, fsig, args); - default: - g_assert_not_reached (); - break; - } - break; - case SN_Multiply: - if (arg0_type == MONO_TYPE_U4) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PMULUDQ, 0, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_MULPD, 0, arg0_type, fsig, args); - else - g_assert_not_reached (); - case SN_MultiplyHigh: - if (arg0_type == MONO_TYPE_I2) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PMULHW, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_U2) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PMULHUW, arg0_type, fsig, args); - else - g_assert_not_reached (); - case SN_PackSignedSaturate: - if (arg0_type == MONO_TYPE_I2) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PACKSSWB, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_I4) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PACKSSDW, arg0_type, fsig, args); - else - g_assert_not_reached (); - case SN_PackUnsignedSaturate: - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PACKUS, -1, arg0_type, fsig, args); - case SN_Extract: - g_assert (arg0_type == MONO_TYPE_U2); - return emit_simd_ins_for_sig (cfg, klass, OP_XEXTRACT_I32, arg0_type, 0, fsig, args); - case SN_Insert: - g_assert (arg0_type == MONO_TYPE_I2 || arg0_type == MONO_TYPE_U2); - return emit_simd_ins_for_sig (cfg, klass, OP_XINSERT_I2, 0, arg0_type, fsig, args); - case SN_ShiftRightLogical: { - gboolean is_imm = fsig->params [1]->type == MONO_TYPE_U1; - SimdOp op = (SimdOp)0; - switch (arg0_type) { - case MONO_TYPE_I2: - case MONO_TYPE_U2: - op = is_imm ? SIMD_OP_SSE_PSRLW_IMM : SIMD_OP_SSE_PSRLW; - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - op = is_imm ? SIMD_OP_SSE_PSRLD_IMM : SIMD_OP_SSE_PSRLD; - break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - op = is_imm ? SIMD_OP_SSE_PSRLQ_IMM : SIMD_OP_SSE_PSRLQ; - break; - default: g_assert_not_reached (); break; - } - return emit_simd_ins_for_sig (cfg, klass, is_imm ? OP_XOP_X_X_I4 : OP_XOP_X_X_X, op, arg0_type, fsig, args); - } - case SN_ShiftRightArithmetic: { - gboolean is_imm = fsig->params [1]->type == MONO_TYPE_U1; - SimdOp op = (SimdOp)0; - switch (arg0_type) { - case MONO_TYPE_I2: - case MONO_TYPE_U2: - op = is_imm ? SIMD_OP_SSE_PSRAW_IMM : SIMD_OP_SSE_PSRAW; - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - op = is_imm ? SIMD_OP_SSE_PSRAD_IMM : SIMD_OP_SSE_PSRAD; - break; - default: g_assert_not_reached (); break; - } - return emit_simd_ins_for_sig (cfg, klass, is_imm ? OP_XOP_X_X_I4 : OP_XOP_X_X_X, op, arg0_type, fsig, args); - } - case SN_ShiftLeftLogical: { - gboolean is_imm = fsig->params [1]->type == MONO_TYPE_U1; - SimdOp op = (SimdOp)0; - switch (arg0_type) { - case MONO_TYPE_I2: - case MONO_TYPE_U2: - op = is_imm ? SIMD_OP_SSE_PSLLW_IMM : SIMD_OP_SSE_PSLLW; - break; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - op = is_imm ? SIMD_OP_SSE_PSLLD_IMM : SIMD_OP_SSE_PSLLD; - break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - op = is_imm ? SIMD_OP_SSE_PSLLQ_IMM : SIMD_OP_SSE_PSLLQ; - break; - default: g_assert_not_reached (); break; - } - return emit_simd_ins_for_sig (cfg, klass, is_imm ? OP_XOP_X_X_I4 : OP_XOP_X_X_X, op, arg0_type, fsig, args); - } - case SN_ShiftLeftLogical128BitLane: - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSLLDQ, 0, arg0_type, fsig, args); - case SN_ShiftRightLogical128BitLane: - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSRLDQ, 0, arg0_type, fsig, args); - case SN_Shuffle: { - if (fsig->param_count == 2) { - g_assert (arg0_type == MONO_TYPE_I4 || arg0_type == MONO_TYPE_U4); - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSHUFD, 0, arg0_type, fsig, args); - } else if (fsig->param_count == 3) { - g_assert (arg0_type == MONO_TYPE_R8); - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_SHUFPD, 0, arg0_type, fsig, args); - } else { - g_assert_not_reached (); - break; - } - } - case SN_ShuffleHigh: - g_assert (fsig->param_count == 2); - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSHUFHW, 0, arg0_type, fsig, args); - case SN_ShuffleLow: - g_assert (fsig->param_count == 2); - return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSHUFLW, 0, arg0_type, fsig, args); - case SN_SqrtScalar: { - if (fsig->param_count == 1) - return emit_simd_ins (cfg, klass, OP_SSE2_SQRTSD, args [0]->dreg, args[0]->dreg); - else if (fsig->param_count == 2) - return emit_simd_ins (cfg, klass, OP_SSE2_SQRTSD, args [0]->dreg, args[1]->dreg); - else { - g_assert_not_reached (); - break; - } - } - case SN_LoadScalarVector128: { - int op = 0; - switch (arg0_type) { - case MONO_TYPE_I4: - case MONO_TYPE_U4: op = OP_SSE2_MOVD; break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: op = OP_SSE2_MOVQ; break; - case MONO_TYPE_R8: op = OP_SSE2_MOVUPD; break; - default: g_assert_not_reached(); break; - } - return emit_simd_ins_for_sig (cfg, klass, op, 0, 0, fsig, args); - } - default: - return NULL; - } - } - - if (feature == MONO_CPU_X86_SSE3) { - switch (id) { - case SN_AddSubtract: - if (arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_ADDSUBPS, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_ADDSUBPD, arg0_type, fsig, args); - else - g_assert_not_reached (); - break; - case SN_HorizontalAdd: - if (arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HADDPS, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HADDPD, arg0_type, fsig, args); - else - g_assert_not_reached (); - break; - case SN_HorizontalSubtract: - if (arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HSUBPS, arg0_type, fsig, args); - else if (arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HSUBPD, arg0_type, fsig, args); - else - g_assert_not_reached (); - break; - default: - g_assert_not_reached (); - break; - } - } - - if (feature == MONO_CPU_X86_SSSE3) { - switch (id) { - case SN_AlignRight: - if (args [2]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_SSSE3_ALIGNR, args [2]->inst_c0, arg0_type, fsig, args); - return emit_invalid_operation (cfg, "mask in Ssse3.AlignRight must be constant"); - case SN_HorizontalAdd: - if (arg0_type == MONO_TYPE_I2) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHADDW, arg0_type, fsig, args); - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHADDD, arg0_type, fsig, args); - case SN_HorizontalSubtract: - if (arg0_type == MONO_TYPE_I2) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHSUBW, arg0_type, fsig, args); - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHSUBD, arg0_type, fsig, args); - case SN_Sign: - if (arg0_type == MONO_TYPE_I1) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PSIGNB, arg0_type, fsig, args); - if (arg0_type == MONO_TYPE_I2) - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PSIGNW, arg0_type, fsig, args); - return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PSIGND, arg0_type, fsig, args); - default: - g_assert_not_reached (); - break; - } - } - - if (feature == MONO_CPU_X86_SSE41) { - switch (id) { - case SN_DotProduct: - if (args [2]->opcode == OP_ICONST && arg0_type == MONO_TYPE_R4) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_DPPS_IMM, args [2]->inst_c0, arg0_type, fsig, args); - else if (args [2]->opcode == OP_ICONST && arg0_type == MONO_TYPE_R8) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_DPPD_IMM, args [2]->inst_c0, arg0_type, fsig, args); - // FIXME: handle non-constant control byte (generate a switch) - return emit_invalid_operation (cfg, "control byte in Sse41.DotProduct must be constant"); - case SN_MultipleSumAbsoluteDifferences: - if (args [2]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_MPSADBW_IMM, args [2]->inst_c0, arg0_type, fsig, args); - // FIXME: handle non-constant control byte (generate a switch) - return emit_invalid_operation (cfg, "control byte in Sse41.MultipleSumAbsoluteDifferences must be constant"); - case SN_Blend: - if (args [2]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_BLEND_IMM, args [2]->inst_c0, arg0_type, fsig, args); - // FIXME: handle non-constant control byte (generate a switch) - return emit_invalid_operation (cfg, "control byte in Sse41.Blend must be constant"); - case SN_BlendVariable: - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_BLENDV, -1, arg0_type, fsig, args); - case SN_Extract: { - int op = 0; - switch (arg0_type) { - case MONO_TYPE_U1: - case MONO_TYPE_U4: - case MONO_TYPE_I4: op = OP_XEXTRACT_I32; break; - case MONO_TYPE_I8: - case MONO_TYPE_U8: op = OP_XEXTRACT_I64; break; - case MONO_TYPE_R4: op = OP_XEXTRACT_R4; break; - default: g_assert_not_reached(); break; - } - return emit_simd_ins_for_sig (cfg, klass, op, arg0_type, 0, fsig, args); - } - case SN_Insert: - if (args [2]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_INSERT, -1, arg0_type, fsig, args); - // FIXME: handle non-constant index (generate a switch) - return emit_invalid_operation (cfg, "index in Sse41.Insert must be constant"); - case SN_CeilingScalar: - case SN_FloorScalar: - case SN_RoundCurrentDirectionScalar: - case SN_RoundToNearestIntegerScalar: - case SN_RoundToNegativeInfinityScalar: - case SN_RoundToPositiveInfinityScalar: - case SN_RoundToZeroScalar: - if (fsig->param_count == 2) { - return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_ROUNDS, info->instc0, arg0_type, fsig, args); - } else { - MonoInst* ins = emit_simd_ins (cfg, klass, OP_SSE41_ROUNDS, args [0]->dreg, args [0]->dreg); - ins->inst_c0 = info->instc0; - ins->inst_c1 = arg0_type; - return ins; - } - break; - default: - g_assert_not_reached (); - break; - } - } - - if (feature == MONO_CPU_X86_SSE42) { - switch (id) { - case SN_Crc32: { - MonoTypeEnum arg1_type = get_underlying_type (fsig->params [1]); - return emit_simd_ins_for_sig (cfg, klass, - arg1_type == MONO_TYPE_U8 ? OP_SSE42_CRC64 : OP_SSE42_CRC32, - arg1_type, arg0_type, fsig, args); - } - default: - g_assert_not_reached (); - break; - } - } - - if (feature == MONO_CPU_X86_PCLMUL) { - switch (id) { - case SN_CarrylessMultiply: { - if (args [2]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_PCLMULQDQ_IMM, args [2]->inst_c0, arg0_type, fsig, args); - // FIXME: handle non-constant control byte (generate a switch) - return emit_invalid_operation (cfg, "index in Pclmulqdq.CarrylessMultiply must be constant"); - } - default: - g_assert_not_reached (); - break; - } - } - - if (feature == MONO_CPU_X86_AES) { - switch (id) { - case SN_KeygenAssist: { - if (args [1]->opcode == OP_ICONST) - return emit_simd_ins_for_sig (cfg, klass, OP_AES_KEYGEN_IMM, args [1]->inst_c0, arg0_type, fsig, args); - // FIXME: handle non-constant control byte (generate a switch) - return emit_invalid_operation (cfg, "control byte in Aes.KeygenAssist must be constant"); - } - default: - g_assert_not_reached (); - break; - } - } - - if (feature == MONO_CPU_X86_POPCNT) { - switch (id) { - case SN_PopCount: - if (!supported) - return NULL; - MONO_INST_NEW (cfg, ins, is_64bit ? OP_POPCNT64 : OP_POPCNT32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - default: - return NULL; - } - } - if (feature == MONO_CPU_X86_LZCNT) { - switch (id) { - case SN_LeadingZeroCount: - if (!supported) - return NULL; - MONO_INST_NEW (cfg, ins, is_64bit ? OP_LZCNT64 : OP_LZCNT32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - default: - return NULL; - } - } - if (feature == MONO_CPU_X86_BMI1) { - switch (id) { - case SN_AndNot: { - // (a ^ -1) & b - // LLVM replaces it with `andn` - int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, is_64bit ? OP_LXOR_IMM : OP_IXOR_IMM, tmp_reg, args [0]->dreg, -1); - EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LAND : OP_IAND, result_reg, tmp_reg, args [1]->dreg); - return ins; - } - case SN_BitFieldExtract: { - if (fsig->param_count == 2) { - MONO_INST_NEW (cfg, ins, is_64bit ? OP_BEXTR64 : OP_BEXTR32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->sreg2 = args [1]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - } - } - case SN_GetMaskUpToLowestSetBit: { - // x ^ (x - 1) - // LLVM replaces it with `blsmsk` - int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, is_64bit ? OP_LSUB_IMM : OP_ISUB_IMM, tmp_reg, args [0]->dreg, 1); - EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LXOR : OP_IXOR, result_reg, args [0]->dreg, tmp_reg); - return ins; - } - case SN_ResetLowestSetBit: { - // x & (x - 1) - // LLVM replaces it with `blsr` - int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, is_64bit ? OP_LSUB_IMM : OP_ISUB_IMM, tmp_reg, args [0]->dreg, 1); - EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LAND : OP_IAND, result_reg, args [0]->dreg, tmp_reg); - return ins; - } - case SN_ExtractLowestSetBit: { - // x & (0 - x) - // LLVM replaces it with `blsi` - int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - int zero_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - MONO_EMIT_NEW_ICONST (cfg, zero_reg, 0); - EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LSUB : OP_ISUB, tmp_reg, zero_reg, args [0]->dreg); - EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LAND : OP_IAND, result_reg, args [0]->dreg, tmp_reg); - return ins; - } - case SN_TrailingZeroCount: - MONO_INST_NEW (cfg, ins, is_64bit ? OP_CTTZ64 : OP_CTTZ32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - default: - g_assert_not_reached (); - } - } - if (feature == MONO_CPU_X86_BMI2) { - switch (id) { - case SN_MultiplyNoFlags: - if (fsig->param_count == 2) { - MONO_INST_NEW (cfg, ins, is_64bit ? OP_MULX_H64 : OP_MULX_H32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->sreg2 = args [1]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - } else if (fsig->param_count == 3) { - MONO_INST_NEW (cfg, ins, is_64bit ? OP_MULX_HL64 : OP_MULX_HL32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->sreg2 = args [1]->dreg; - ins->sreg3 = args [2]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - } else { - g_assert_not_reached (); - } - return ins; - case SN_ZeroHighBits: - MONO_INST_NEW (cfg, ins, is_64bit ? OP_BZHI64 : OP_BZHI32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->sreg2 = args [1]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - case SN_ParallelBitExtract: - MONO_INST_NEW (cfg, ins, is_64bit ? OP_PEXT64 : OP_PEXT32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->sreg2 = args [1]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - case SN_ParallelBitDeposit: - MONO_INST_NEW (cfg, ins, is_64bit ? OP_PDEP64 : OP_PDEP32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->sreg2 = args [1]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - default: - g_assert_not_reached (); - } - } - - if (intrinsics == x86base_methods) { - switch (id) { - case SN_BitScanForward: - MONO_INST_NEW (cfg, ins, is_64bit ? OP_X86_BSF64 : OP_X86_BSF32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - case SN_BitScanReverse: - MONO_INST_NEW (cfg, ins, is_64bit ? OP_X86_BSR64 : OP_X86_BSR32); - ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); - ins->sreg1 = args [0]->dreg; - ins->type = is_64bit ? STACK_I8 : STACK_I4; - MONO_ADD_INS (cfg->cbb, ins); - return ins; - default: - g_assert_not_reached (); - } - } - - return NULL; -} - -static guint16 vector_128_t_methods [] = { - SN_get_Count, - SN_get_Zero, -}; - -static MonoInst* -emit_vector128_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *ins; - MonoType *type, *etype; - MonoClass *klass; - int size, len, id; - - id = lookup_intrins (vector_128_t_methods, sizeof (vector_128_t_methods), cmethod); - if (id == -1) - return NULL; - - klass = cmethod->klass; - type = m_class_get_byval_arg (klass); - etype = mono_class_get_context (klass)->class_inst->type_argv [0]; - size = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - g_assert (size); - len = 16 / size; - - if (!MONO_TYPE_IS_PRIMITIVE (etype) || etype->type == MONO_TYPE_CHAR || etype->type == MONO_TYPE_BOOLEAN) - return NULL; - - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD intrinsic %s\n", name); - g_free (name); - } - - switch (id) { - case SN_get_Count: - if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4)) - break; - EMIT_NEW_ICONST (cfg, ins, len); - return ins; - case SN_get_Zero: { - return emit_simd_ins (cfg, klass, OP_XZERO, -1, -1); - } - default: - break; - } - - return NULL; -} - -static guint16 vector_256_t_methods [] = { - SN_get_Count, -}; - -static MonoInst* -emit_vector256_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *ins; - MonoType *type, *etype; - MonoClass *klass; - int size, len, id; - - id = lookup_intrins (vector_256_t_methods, sizeof (vector_256_t_methods), cmethod); - if (id == -1) - return NULL; - - klass = cmethod->klass; - type = m_class_get_byval_arg (klass); - etype = mono_class_get_context (klass)->class_inst->type_argv [0]; - size = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - g_assert (size); - len = 32 / size; - - if (!MONO_TYPE_IS_PRIMITIVE (etype) || etype->type == MONO_TYPE_CHAR || etype->type == MONO_TYPE_BOOLEAN) - return NULL; - - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD intrinsic %s\n", name); - g_free (name); - } - - switch (id) { - case SN_get_Count: - if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4)) - break; - EMIT_NEW_ICONST (cfg, ins, len); - return ins; - default: - break; - } - - return NULL; -} - -static -MonoInst* -emit_amd64_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - if (!strcmp (class_ns, "System.Runtime.Intrinsics.X86")) { - return emit_x86_intrinsics (cfg, cmethod, fsig, args); - } - - if (!strcmp (class_ns, "System.Runtime.Intrinsics")) { - if (!strcmp (class_name, "Vector128`1")) - return emit_vector128_t (cfg, cmethod, fsig, args); - if (!strcmp (class_name, "Vector256`1")) - return emit_vector256_t (cfg, cmethod, fsig, args); - } - - if (!strcmp (class_ns, "System.Numerics")) { - if (!strcmp (class_name, "Vector")) - return emit_sys_numerics_vector (cfg, cmethod, fsig, args); - if (!strcmp (class_name, "Vector`1")) - return emit_sys_numerics_vector_t (cfg, cmethod, fsig, args); - } - - return NULL; -} -#endif // !TARGET_ARM64 - -#ifdef TARGET_ARM64 -static -MonoInst* -emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - // FIXME: implement Vector64, Vector128 and Vector for Arm64 - if (!strcmp (class_ns, "System.Runtime.Intrinsics.Arm")) { - return emit_arm64_intrinsics (cfg, cmethod, fsig, args); - } - - return NULL; -} -#elif TARGET_AMD64 -// TODO: test and enable for x86 too -static -MonoInst* -emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - MonoInst *simd_inst = emit_amd64_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args); - if (simd_inst != NULL) { - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS; - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE; - } - return simd_inst; -} -#else -static -MonoInst* -emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - return NULL; -} -#endif - -MonoInst* -mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - const char *class_name; - const char *class_ns; - MonoImage *image = m_class_get_image (cmethod->klass); - - if (image != mono_get_corlib ()) - return NULL; - - class_ns = m_class_get_name_space (cmethod->klass); - class_name = m_class_get_name (cmethod->klass); - - // If cmethod->klass is nested, the namespace is on the enclosing class. - if (m_class_get_nested_in (cmethod->klass)) - class_ns = m_class_get_name_space (m_class_get_nested_in (cmethod->klass)); - -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) - if (!strcmp (class_ns, "System.Runtime.Intrinsics")) { - if (!strcmp (class_name, "Vector128")) - return emit_vector128 (cfg, cmethod, fsig, args); - } -#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) - - return emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args); -} - -/* -* Windows x64 value type ABI uses reg/stack references (ArgValuetypeAddrInIReg/ArgValuetypeAddrOnStack) -* for function arguments. When using SIMD intrinsics arguments optimized into OP_ARG needs to be decomposed -* into correspondig SIMD LOADX/STOREX instructions. -*/ -#if defined(TARGET_WIN32) && defined(TARGET_AMD64) -static gboolean -decompose_vtype_opt_uses_simd_intrinsics (MonoCompile *cfg, MonoInst *ins) -{ - if (cfg->uses_simd_intrinsics & MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE) - return TRUE; - - switch (ins->opcode) { - case OP_XMOVE: - case OP_XZERO: - case OP_LOADX_MEMBASE: - case OP_LOADX_ALIGNED_MEMBASE: - case OP_STOREX_MEMBASE: - case OP_STOREX_ALIGNED_MEMBASE_REG: - return TRUE; - default: - return FALSE; - } -} - -static void -decompose_vtype_opt_load_arg (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, gint32 *sreg_int32) -{ - guint32 *sreg = (guint32*)sreg_int32; - MonoInst *src_var = get_vreg_to_inst (cfg, *sreg); - if (src_var && src_var->opcode == OP_ARG && src_var->klass && MONO_CLASS_IS_SIMD (cfg, src_var->klass)) { - MonoInst *varload_ins, *load_ins; - NEW_VARLOADA (cfg, varload_ins, src_var, src_var->inst_vtype); - mono_bblock_insert_before_ins (bb, ins, varload_ins); - MONO_INST_NEW (cfg, load_ins, OP_LOADX_MEMBASE); - load_ins->klass = src_var->klass; - load_ins->type = STACK_VTYPE; - load_ins->sreg1 = varload_ins->dreg; - load_ins->dreg = alloc_xreg (cfg); - mono_bblock_insert_after_ins (bb, varload_ins, load_ins); - *sreg = load_ins->dreg; - } -} - -void -mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) -{ - if (cfg->opt & MONO_OPT_SIMD && decompose_vtype_opt_uses_simd_intrinsics (cfg, ins)) { - decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg1)); - decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg2)); - decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg3)); - MonoInst *dest_var = get_vreg_to_inst (cfg, ins->dreg); - if (dest_var && dest_var->opcode == OP_ARG && dest_var->klass && MONO_CLASS_IS_SIMD (cfg, dest_var->klass)) { - MonoInst *varload_ins, *store_ins; - ins->dreg = alloc_xreg (cfg); - NEW_VARLOADA (cfg, varload_ins, dest_var, dest_var->inst_vtype); - mono_bblock_insert_after_ins (bb, ins, varload_ins); - MONO_INST_NEW (cfg, store_ins, OP_STOREX_MEMBASE); - store_ins->klass = dest_var->klass; - store_ins->type = STACK_VTYPE; - store_ins->sreg1 = ins->dreg; - store_ins->dreg = varload_ins->dreg; - mono_bblock_insert_after_ins (bb, varload_ins, store_ins); - } - } -} -#else -void -mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) -{ -} -#endif /*defined(TARGET_WIN32) && defined(TARGET_AMD64)*/ - -void -mono_simd_simplify_indirection (MonoCompile *cfg) -{ -} - -#endif /* DISABLE_JIT */ -#endif /* MONO_ARCH_SIMD_INTRINSICS */ - -#if defined(ENABLE_NETCORE) && defined(TARGET_AMD64) -void -ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id) -{ -#ifndef MONO_CROSS_COMPILE - mono_hwcap_x86_call_cpuidex (function_id, subfunction_id, - &abcd [0], &abcd [1], &abcd [2], &abcd [3]); -#endif -} -#endif - -MONO_EMPTY_SOURCE_FILE (simd_intrinsics_netcore); diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index cadf38a..df49b40 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1,72 +1,25 @@ /** - * \file - * simd support for intrinsics - * - * Author: - * Rodrigo Kumpera (rkumpera@novell.com) - * - * (C) 2008 Novell, Inc. + * SIMD Intrinsics support for netcore. + * Only LLVM is supported as a backend. */ #include -#include - +#include +#include #include "mini.h" +#include "mini-runtime.h" #include "ir-emit.h" +#ifdef ENABLE_LLVM +#include "mini-llvm.h" +#endif +#include "mono/utils/bsearch.h" #include #include -#include -#include +#include -/* -General notes on SIMD intrinsics - -TODO handle operands with non SIMD args, such as op_Addition (Vector4f, float) -TODO optimize r4const in .ctor so it doesn't go into the FP stack first -TODO extend op_to_op_dest_membase to handle simd ops -TODO add support for indexed versions of simd ops -TODO to an amd64 port and figure out how to properly handle extractors/.ctor -TODO make sure locals, arguments and spills are properly aligned. -TODO add support for fusing a XMOVE into a simd op in mono_spill_global_vars. -TODO add stuff to man pages -TODO document this under /docs -TODO make passing a xmm as argument not cause it to be LDADDR'ed (introduce an OP_XPUSH) -TODO revamp the .ctor sequence as it looks very fragile, maybe use a var just like move_i4_to_f. (or just pinst sse ops) -TODO figure out what's wrong with OP_STOREX_MEMBASE_REG and OP_STOREX_MEMBASE (the 2nd is for imm operands) -TODO maybe add SSE3 emulation on top of SSE2, or just implement the corresponding functions using SSE2 intrinsics. -TODO pass simd arguments in registers or, at least, add SSE support for pushing large (>=16) valuetypes -TODO pass simd args byval to a non-intrinsic method cause some useless local var load/store to happen. -TODO check if we need to init the SSE control word with better precision. -TODO add support for 3 reg sources in mini without slowing the common path. Or find a way to make MASKMOVDQU work. -TODO make SimdRuntime.get_AccelMode work under AOT -TODO patterns such as "a ^= b" generate slower code as the LDADDR op will be copied to a tmp first. Look at adding a indirection reduction pass after the dce pass. -TODO extend bounds checking code to support for range checking. - -General notes for SIMD intrinsics. - --Bad extractor and constructor performance -Extracting a float from a XMM is a complete disaster if you are passing it as an argument. -It will be loaded in the FP stack just to be pushed on the call stack. - -A similar thing happens with Vector4f constructor that require float vars to be - -The fix for this issue is similar to the one required for r4const as method args. Avoiding the -trip to the FP stack is desirable. - --Extractor and constructor code doesn't make sense under amd64. Both currently assume separate banks -for simd and fp. - - --Promote OP_EXTRACT_I4 to a STORE op -The advantage of this change is that it could have a _membase version and promote further optimizations. - --Create a MONO_INST_DONT_REGALLOC and use it in all places that MONO_INST_INDIRECT is used -without a OP_LDADDR. -*/ +#if defined (MONO_ARCH_SIMD_INTRINSICS) -#if defined (MONO_ARCH_SIMD_INTRINSICS) && !defined(ENABLE_NETCORE) - -#if defined (DISABLE_JIT) +#if defined(DISABLE_JIT) void mono_simd_intrinsics_init (void) @@ -75,838 +28,109 @@ mono_simd_intrinsics_init (void) #else -//#define IS_DEBUG_ON(cfg) (0) - -#define IS_DEBUG_ON(cfg) ((cfg)->verbose_level >= 3) -#define DEBUG(a) do { if (IS_DEBUG_ON(cfg)) { a; } } while (0) - -/* -This enum MUST be kept in sync with its managed mirror Mono.Simd.AccelMode. - */ -enum { - SIMD_VERSION_SSE1 = 1 << 0, - SIMD_VERSION_SSE2 = 1 << 1, - SIMD_VERSION_SSE3 = 1 << 2, - SIMD_VERSION_SSSE3 = 1 << 3, - SIMD_VERSION_SSE41 = 1 << 4, - SIMD_VERSION_SSE42 = 1 << 5, - SIMD_VERSION_SSE4a = 1 << 6, -}; - -enum { - SIMD_EMIT_BINARY, - SIMD_EMIT_UNARY, - SIMD_EMIT_SETTER, - SIMD_EMIT_GETTER, - SIMD_EMIT_GETTER_QWORD, - SIMD_EMIT_CTOR, - SIMD_EMIT_CAST, - SIMD_EMIT_SHUFFLE, - SIMD_EMIT_SHIFT, - SIMD_EMIT_EQUALITY, - SIMD_EMIT_LOAD_ALIGNED, - SIMD_EMIT_STORE, - SIMD_EMIT_EXTRACT_MASK, - SIMD_EMIT_PREFETCH -}; - -// This, instead of an array of pointers, to optimize away a pointer and a relocation per string. #define MSGSTRFIELD(line) MSGSTRFIELD1(line) #define MSGSTRFIELD1(line) str##line static const struct msgstr_t { -#define SIMD_METHOD(str,name) char MSGSTRFIELD(__LINE__) [sizeof (str)]; -#include "simd-methods.h" -#undef SIMD_METHOD +#define METHOD(name) char MSGSTRFIELD(__LINE__) [sizeof (#name)]; +#define METHOD2(str,name) char MSGSTRFIELD(__LINE__) [sizeof (str)]; +#include "simd-methods-netcore.h" +#undef METHOD +#undef METHOD2 } method_names = { -#define SIMD_METHOD(str,name) str, -#include "simd-methods.h" -#undef SIMD_METHOD +#define METHOD(name) #name, +#define METHOD2(str,name) str, +#include "simd-methods-netcore.h" +#undef METHOD +#undef METHOD2 }; enum { -#define SIMD_METHOD(str,name) name = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)), -#include "simd-methods.h" +#define METHOD(name) SN_ ## name = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)), +#define METHOD2(str,name) SN_ ## name = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)), +#include "simd-methods-netcore.h" }; #define method_name(idx) ((const char*)&method_names + (idx)) +static int register_size; + typedef struct { - guint16 name; - guint16 opcode; - guint32 simd_version; - guint8 simd_emit_mode : 4; - guint8 flags : 4; + // One of the SN_ constants + guint16 id; + // ins->opcode + int op; + // ins->inst_c0 + int instc0; } SimdIntrinsic; -static const SimdIntrinsic vector4f_intrinsics[] = { - { SN_ctor, OP_EXPAND_R4, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_AddSub, OP_ADDSUBPS, MONO_CPU_X86_SSE3, SIMD_EMIT_BINARY}, - { SN_AndNot, OP_ANDNPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY}, - { SN_CompareEqual, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_EQ }, - { SN_CompareLessEqual, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_LE }, - { SN_CompareLessThan, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_LT }, - { SN_CompareNotEqual, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_NEQ }, - { SN_CompareNotLessEqual, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_NLE }, - { SN_CompareNotLessThan, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_NLT }, - { SN_CompareOrdered, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_ORD }, - { SN_CompareUnordered, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_UNORD }, - { SN_ConvertToDouble, OP_CVTPS2PD, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_ConvertToInt, OP_CVTPS2DQ, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_ConvertToIntTruncated, OP_CVTTPS2DQ, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_DuplicateHigh, OP_DUPPS_HIGH, MONO_CPU_X86_SSE3, SIMD_EMIT_UNARY }, - { SN_DuplicateLow, OP_DUPPS_LOW, MONO_CPU_X86_SSE3, SIMD_EMIT_UNARY }, - { SN_HorizontalAdd, OP_HADDPS, MONO_CPU_X86_SSE3, SIMD_EMIT_BINARY }, - { SN_HorizontalSub, OP_HSUBPS, MONO_CPU_X86_SSE3, SIMD_EMIT_BINARY }, - { SN_InterleaveHigh, OP_UNPACK_HIGHPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_InterleaveLow, OP_UNPACK_LOWPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_InvSqrt, OP_RSQRTPS, MONO_CPU_X86_SSE, SIMD_EMIT_UNARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_Max, OP_MAXPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_Min, OP_MINPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_Reciprocal, OP_RCPPS, MONO_CPU_X86_SSE, SIMD_EMIT_UNARY }, - { SN_Shuffle, OP_PSHUFLED, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_Sqrt, OP_SQRTPS, MONO_CPU_X86_SSE, SIMD_EMIT_UNARY }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_StoreNonTemporal, OP_STOREX_NTA_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_get_W, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_Z, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_ADDPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_ANDPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_ORPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Division, OP_DIVPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_XORPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_Multiply, OP_MULPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Subtraction, OP_SUBPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_W, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Z, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER } -}; - -static const SimdIntrinsic vector2d_intrinsics[] = { - { SN_ctor, OP_EXPAND_R8, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_AddSub, OP_ADDSUBPD, MONO_CPU_X86_SSE3, SIMD_EMIT_BINARY,}, - { SN_AndNot, OP_ANDNPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareEqual, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_EQ }, - { SN_CompareLessEqual, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_LE }, - { SN_CompareLessThan, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_LT }, - { SN_CompareNotEqual, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_NEQ }, - { SN_CompareNotLessEqual, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_NLE }, - { SN_CompareNotLessThan, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_NLT }, - { SN_CompareOrdered, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_ORD }, - { SN_CompareUnordered, OP_COMPPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, SIMD_COMP_UNORD }, - { SN_ConvertToFloat, OP_CVTPD2PS, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_ConvertToInt, OP_CVTPD2DQ, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_ConvertToIntTruncated, OP_CVTTPD2DQ, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_Duplicate, OP_DUPPD, MONO_CPU_X86_SSE3, SIMD_EMIT_UNARY }, - { SN_HorizontalAdd, OP_HADDPD, MONO_CPU_X86_SSE3, SIMD_EMIT_BINARY }, - { SN_HorizontalSub, OP_HSUBPD, MONO_CPU_X86_SSE3, SIMD_EMIT_BINARY }, - { SN_InterleaveHigh, OP_UNPACK_HIGHPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_InterleaveLow, OP_UNPACK_LOWPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_Max, OP_MAXPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_Min, OP_MINPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_Shuffle, OP_SHUFPD, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_Sqrt, OP_SQRTPD, MONO_CPU_X86_SSE, SIMD_EMIT_UNARY }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_get_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER_QWORD }, - { SN_get_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER_QWORD }, - { SN_op_Addition, OP_ADDPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_ANDPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_ORPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Division, OP_DIVPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_ExclusiveOr, OP_XORPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Multiply, OP_MULPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Subtraction, OP_SUBPD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector2ul_intrinsics[] = { - { SN_ctor, OP_EXPAND_I8, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_CompareEqual, OP_PCMPEQQ, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_Shuffle, OP_SHUFPD, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_UnpackHigh, OP_UNPACK_HIGHQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER_QWORD }, - { SN_get_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER_QWORD }, - { SN_op_Addition, OP_PADDQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_ExclusiveOr, OP_PXOR, SIMD_EMIT_BINARY, MONO_CPU_X86_SSE }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_LeftShift, OP_PSHLQ, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Multiply, OP_PMULQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_RightShift, OP_PSHRQ, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Subtraction, OP_PSUBQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector2l_intrinsics[] = { - { SN_ctor, OP_EXPAND_I8, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_CompareEqual, OP_PCMPEQQ, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_CompareGreaterThan, OP_PCMPGTQ, MONO_CPU_X86_SSE42, SIMD_EMIT_BINARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_LogicalRightShift, OP_PSHRQ, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_Shuffle, OP_SHUFPD, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_UnpackHigh, OP_UNPACK_HIGHQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER_QWORD }, - { SN_get_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER_QWORD }, - { SN_op_Addition, OP_PADDQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_LeftShift, OP_PSHLQ, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Multiply, OP_PMULQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Subtraction, OP_PSUBQ, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector4ui_intrinsics[] = { - { SN_ctor, OP_EXPAND_I4, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_ArithmeticRightShift, OP_PSARD, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_CompareEqual, OP_PCMPEQD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_Max, OP_PMAXD_UN, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_Min, OP_PMIND_UN, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_Shuffle, OP_PSHUFLED, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_SignedPackWithSignedSaturation, OP_PACKD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_SignedPackWithUnsignedSaturation, OP_PACKD_UN, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_UnpackHigh, OP_UNPACK_HIGHD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_W, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_Z, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_PADDD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_PCMPEQD, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_PCMPEQD, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_LeftShift, OP_PSHLD, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Multiply, OP_PMULD, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_op_RightShift, OP_PSHRD, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Subtraction, OP_PSUBD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_W, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Z, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector4i_intrinsics[] = { - { SN_ctor, OP_EXPAND_I4, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_CompareEqual, OP_PCMPEQD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareGreaterThan, OP_PCMPGTD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_ConvertToDouble, OP_CVTDQ2PD, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_ConvertToFloat, OP_CVTDQ2PS, MONO_CPU_X86_SSE2, SIMD_EMIT_UNARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_LogicalRightShift, OP_PSHRD, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_Max, OP_PMAXD, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_Min, OP_PMIND, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_PackWithSignedSaturation, OP_PACKD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PackWithUnsignedSaturation, OP_PACKD_UN, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_Shuffle, OP_PSHUFLED, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_UnpackHigh, OP_UNPACK_HIGHD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_W, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_Z, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_PADDD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_PCMPEQD, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_PCMPEQD, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_LeftShift, OP_PSHLD, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Multiply, OP_PMULD, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_op_RightShift, OP_PSARD, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Subtraction, OP_PSUBD, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_W, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_X, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Y, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_Z, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector8us_intrinsics[] = { - { SN_ctor, OP_EXPAND_I2, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_AddWithSaturation, OP_PADDW_SAT_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_ArithmeticRightShift, OP_PSARW, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_Average, OP_PAVGW_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareEqual, OP_PCMPEQW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY, MONO_CPU_X86_SSE }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_Max, OP_PMAXW_UN, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_Min, OP_PMINW_UN, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_MultiplyStoreHigh, OP_PMULW_HIGH_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_ShuffleHigh, OP_PSHUFLEW_HIGH, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_ShuffleLow, OP_PSHUFLEW_LOW, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_SignedPackWithSignedSaturation, OP_PACKW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_SignedPackWithUnsignedSaturation, OP_PACKW_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_SubtractWithSaturation, OP_PSUBW_SAT_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackHigh, OP_UNPACK_HIGHW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_PADDW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_PCMPEQW, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_PCMPEQW, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_LeftShift, OP_PSHLW, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Multiply, OP_PMULW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_RightShift, OP_PSHRW, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Subtraction, OP_PSUBW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector8s_intrinsics[] = { - { SN_ctor, OP_EXPAND_I2, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_AddWithSaturation, OP_PADDW_SAT, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareEqual, OP_PCMPEQW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareGreaterThan, OP_PCMPGTW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_LogicalRightShift, OP_PSHRW, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_Max, OP_PMAXW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_Min, OP_PMINW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_MultiplyStoreHigh, OP_PMULW_HIGH, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PackWithSignedSaturation, OP_PACKW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PackWithUnsignedSaturation, OP_PACKW_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_ShuffleHigh, OP_PSHUFLEW_HIGH, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_ShuffleLow, OP_PSHUFLEW_LOW, MONO_CPU_X86_SSE, SIMD_EMIT_SHUFFLE }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_SubtractWithSaturation, OP_PSUBW_SAT_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackHigh, OP_UNPACK_HIGHW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_PADDW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_PCMPEQW, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_PCMPEQW, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_LeftShift, OP_PSHLW, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Multiply, OP_PMULW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_RightShift, OP_PSARW, MONO_CPU_X86_SSE, SIMD_EMIT_SHIFT }, - { SN_op_Subtraction, OP_PSUBW, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static const SimdIntrinsic vector16b_intrinsics[] = { - { SN_ctor, OP_EXPAND_I1, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_AddWithSaturation, OP_PADDB_SAT_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_Average, OP_PAVGB_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareEqual, OP_PCMPEQB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_ExtractByteMask, 0, MONO_CPU_X86_SSE, SIMD_EMIT_EXTRACT_MASK }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_Max, OP_PMAXB_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_Min, OP_PMINB_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_SubtractWithSaturation, OP_PSUBB_SAT_UN, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_SumOfAbsoluteDifferences, OP_PSUM_ABS_DIFF, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackHigh, OP_UNPACK_HIGHB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V10, 10, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V11, 11, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V12, 12, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V13, 13, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V14, 14, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V15, 15, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V8, 8, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V9, 9, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_PADDB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_PCMPEQB, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_PCMPEQB, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_Subtraction, OP_PSUBB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V10, 10, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V11, 11, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V12, 12, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V13, 13, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V14, 14, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V15, 15, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V8, 8, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V9, 9, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -/* -Missing: -setters - */ -static const SimdIntrinsic vector16sb_intrinsics[] = { - { SN_ctor, OP_EXPAND_I1, MONO_CPU_X86_SSE, SIMD_EMIT_CTOR }, - { SN_AddWithSaturation, OP_PADDB_SAT, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareEqual, OP_PCMPEQB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_CompareGreaterThan, OP_PCMPGTB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_ExtractByteMask, 0, MONO_CPU_X86_SSE, SIMD_EMIT_EXTRACT_MASK }, - { SN_LoadAligned, 0, MONO_CPU_X86_SSE, SIMD_EMIT_LOAD_ALIGNED }, - { SN_Max, OP_PMAXB, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_Min, OP_PMINB, MONO_CPU_X86_SSE41, SIMD_EMIT_BINARY }, - { SN_PrefetchTemporalAllCacheLevels, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_0 }, - { SN_PrefetchTemporal1stLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 }, - { SN_PrefetchTemporal2ndLevelCache, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 }, - { SN_PrefetchNonTemporal, 0, MONO_CPU_X86_SSE, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA }, - { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, MONO_CPU_X86_SSE, SIMD_EMIT_STORE }, - { SN_SubtractWithSaturation, OP_PSUBB_SAT, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackHigh, OP_UNPACK_HIGHB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_UnpackLow, OP_UNPACK_LOWB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_get_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V10, 10, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V11, 11, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V12, 12, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V13, 13, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V14, 14, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V15, 15, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V8, 8, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_get_V9, 9, MONO_CPU_X86_SSE, SIMD_EMIT_GETTER }, - { SN_op_Addition, OP_PADDB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseAnd, OP_PAND, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_BitwiseOr, OP_POR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Equality, OP_PCMPEQB, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_op_ExclusiveOr, OP_PXOR, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Explicit, 0, MONO_CPU_X86_SSE, SIMD_EMIT_CAST }, - { SN_op_Inequality, OP_PCMPEQB, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_NEQ }, - { SN_op_Subtraction, OP_PSUBB, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_set_V0, 0, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V1, 1, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V10, 10, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V11, 11, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V12, 12, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V13, 13, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V14, 14, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V15, 15, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V2, 2, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V3, 3, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V4, 4, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V5, 5, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V6, 6, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V7, 7, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V8, 8, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, - { SN_set_V9, 9, MONO_CPU_X86_SSE, SIMD_EMIT_SETTER }, -}; - -static MonoInst* emit_sys_numerics_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args); -static MonoInst* emit_sys_numerics_vectors_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args); - -/*TODO match using number of parameters as well*/ -static int -simd_intrinsic_compare_by_name (const void *key, const void *value) -{ - return strcmp ((const char*)key, method_name (((SimdIntrinsic *)value)->name)); -} - -typedef enum { - VREG_USED = 0x01, - VREG_HAS_XZERO_BB0 = 0x02, - VREG_HAS_OTHER_OP_BB0 = 0x04, - VREG_SINGLE_BB_USE = 0x08, - VREG_MANY_BB_USE = 0x10, -} KillFlags; - void mono_simd_intrinsics_init (void) { + register_size = 16; +#if FALSE + if ((mini_get_cpu_features () & MONO_CPU_X86_AVX) != 0) + register_size = 32; +#endif + /* Tell the class init code the size of the System.Numerics.Register type */ + mono_simd_register_size = register_size; } -static gboolean -apply_vreg_first_block_interference (MonoCompile *cfg, MonoInst *ins, int reg, int max_vreg, char *vreg_flags) -{ - if (reg != -1 && reg <= max_vreg && vreg_flags [reg]) { - vreg_flags [reg] &= ~VREG_HAS_XZERO_BB0; - vreg_flags [reg] |= VREG_HAS_OTHER_OP_BB0; - DEBUG (printf ("[simd-simplify] R%d used: ", reg); mono_print_ins(ins)); - return TRUE; - } - return FALSE; -} - -static gboolean -apply_vreg_following_block_interference (MonoCompile *cfg, MonoInst *ins, int reg, MonoBasicBlock *bb, int max_vreg, char *vreg_flags, MonoBasicBlock **target_bb) +MonoInst* +mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field, MonoInst *addr) { - if (reg == -1 || reg > max_vreg || !(vreg_flags [reg] & VREG_HAS_XZERO_BB0) || target_bb [reg] == bb) - return FALSE; - - if (vreg_flags [reg] & VREG_SINGLE_BB_USE) { - vreg_flags [reg] &= ~VREG_SINGLE_BB_USE; - vreg_flags [reg] |= VREG_MANY_BB_USE; - DEBUG (printf ("[simd-simplify] R%d used by many bb: ", reg); mono_print_ins(ins)); - return TRUE; - } else if (!(vreg_flags [reg] & VREG_MANY_BB_USE)) { - vreg_flags [reg] |= VREG_SINGLE_BB_USE; - target_bb [reg] = bb; - DEBUG (printf ("[simd-simplify] R%d first used by: ", reg); mono_print_ins(ins)); - return TRUE; - } - return FALSE; + return NULL; } -/* -This pass recalculate which vars need MONO_INST_INDIRECT. - -We cannot do this for non SIMD vars since code like mono_get_vtable_var -uses MONO_INST_INDIRECT to signal that the variable must be stack allocated. -*/ -void -mono_simd_simplify_indirection (MonoCompile *cfg) +static int +simd_intrinsic_compare_by_name (const void *key, const void *value) { - int i, max_vreg = 0; - MonoBasicBlock *bb, *first_bb = NULL, **target_bb; - MonoInst *ins; - char *vreg_flags; - - for (i = 0; i < cfg->num_varinfo; i++) { - MonoInst *var = cfg->varinfo [i]; - if (m_class_is_simd_type (var->klass)) { - var->flags &= ~MONO_INST_INDIRECT; - max_vreg = MAX (var->dreg, max_vreg); - } - } - - for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { - if (!first_bb && bb->code) - first_bb = bb; - for (ins = bb->code; ins; ins = ins->next) { - if (ins->opcode == OP_LDADDR) { - MonoInst *var = (MonoInst*)ins->inst_p0; - if (m_class_is_simd_type (var->klass)) { - var->flags |= MONO_INST_INDIRECT; - } - } - } - } - - DEBUG (printf ("[simd-simplify] max vreg is %d\n", max_vreg)); - vreg_flags = (char *)g_malloc0 (max_vreg + 1); - target_bb = g_new0 (MonoBasicBlock*, max_vreg + 1); - - for (i = 0; i < cfg->num_varinfo; i++) { - MonoInst *var = cfg->varinfo [i]; - if (m_class_is_simd_type (var->klass) && !(var->flags & (MONO_INST_INDIRECT|MONO_INST_VOLATILE))) { - vreg_flags [var->dreg] = VREG_USED; - DEBUG (printf ("[simd-simplify] processing var %d with vreg %d\n", i, var->dreg)); - } - } - - /*Scan the first basic block looking xzeros not used*/ - for (ins = first_bb->code; ins; ins = ins->next) { - int num_sregs; - int sregs [MONO_MAX_SRC_REGS]; - - if (ins->opcode == OP_XZERO) { - if (!(vreg_flags [ins->dreg] & VREG_HAS_OTHER_OP_BB0)) { - DEBUG (printf ("[simd-simplify] R%d has vzero: ", ins->dreg); mono_print_ins(ins)); - vreg_flags [ins->dreg] |= VREG_HAS_XZERO_BB0; - } - continue; - } - if (ins->opcode == OP_LDADDR && apply_vreg_first_block_interference (cfg, ins, ((MonoInst*)ins->inst_p0)->dreg, max_vreg, vreg_flags)) - continue; - if (apply_vreg_first_block_interference (cfg, ins, ins->dreg, max_vreg, vreg_flags)) - continue; - num_sregs = mono_inst_get_src_registers (ins, sregs); - for (i = 0; i < num_sregs; ++i) { - if (apply_vreg_first_block_interference (cfg, ins, sregs [i], max_vreg, vreg_flags)) - break; - } - } - - if (IS_DEBUG_ON (cfg)) { - for (i = 0; i < cfg->num_varinfo; i++) { - MonoInst *var = cfg->varinfo [i]; - if (m_class_is_simd_type (var->klass)) { - if ((vreg_flags [var->dreg] & VREG_HAS_XZERO_BB0)) - DEBUG (printf ("[simd-simplify] R%d has xzero only\n", var->dreg)); - if ((vreg_flags [var->dreg] & VREG_HAS_OTHER_OP_BB0)) - DEBUG (printf ("[simd-simplify] R%d has other ops on bb0\n", var->dreg)); - } - } - } - - /*TODO stop here if no var is xzero only*/ - - /* - Scan all other bb and check if it has only one other use - Ideally this would be done after an extended bb formation pass - - FIXME This pass could use dominator information to properly - place the XZERO on the bb that dominates all uses of the var, - but this will have zero effect with the current local reg alloc - - TODO simply the use of flags. - */ - - for (bb = first_bb->next_bb; bb; bb = bb->next_bb) { - for (ins = bb->code; ins; ins = ins->next) { - int num_sregs; - int sregs [MONO_MAX_SRC_REGS]; - - if (ins->opcode == OP_LDADDR && apply_vreg_following_block_interference (cfg, ins, ((MonoInst*)ins->inst_p0)->dreg, bb, max_vreg, vreg_flags, target_bb)) - continue; - if (apply_vreg_following_block_interference (cfg, ins, ins->dreg, bb, max_vreg, vreg_flags, target_bb)) - continue; - num_sregs = mono_inst_get_src_registers (ins, sregs); - for (i = 0; i < num_sregs; ++i) { - if (apply_vreg_following_block_interference (cfg, ins, sregs [i], bb, - max_vreg, vreg_flags, target_bb)) - continue; - } - } - } - - for (i = 0; i < cfg->num_varinfo; i++) { - MonoInst *var = cfg->varinfo [i]; - if (!m_class_is_simd_type (var->klass)) - continue; - if ((vreg_flags [var->dreg] & VREG_SINGLE_BB_USE)) - DEBUG (printf ("[simd-simplify] R%d has single bb use\n", var->dreg)); - if ((vreg_flags [var->dreg] & VREG_MANY_BB_USE)) - DEBUG (printf ("[simd-simplify] R%d has many bb in use\n", var->dreg)); - - if (!(vreg_flags [var->dreg] & VREG_SINGLE_BB_USE)) - continue; - for (ins = target_bb [var->dreg]->code; ins; ins = ins->next) { - int num_sregs, j; - int sregs [MONO_MAX_SRC_REGS]; - gboolean found = FALSE; - - num_sregs = mono_inst_get_src_registers (ins, sregs); - for (j = 0; j < num_sregs; ++j) { - if (sregs [j] == var->dreg) - found = TRUE; - } - /*We can avoid inserting the XZERO if the first use doesn't depend on the zero'ed value.*/ - if (ins->dreg == var->dreg && !found) { - DEBUG (printf ("[simd-simplify] INGORING R%d on BB %d because first op is a def", i, target_bb [var->dreg]->block_num);); - break; - } else if (found) { - DEBUG (printf ("[simd-simplify] Adding XZERO for R%d on BB %d: ", i, target_bb [var->dreg]->block_num); ); - MonoInst *tmp; - MONO_INST_NEW (cfg, tmp, OP_XZERO); - tmp->dreg = var->dreg; - tmp->type = STACK_VTYPE; - tmp->klass = var->klass; - mono_bblock_insert_before_ins (target_bb [var->dreg], ins, tmp); - break; - } - } - } - - for (ins = first_bb->code; ins; ins = ins->next) { - if (ins->opcode == OP_XZERO && (vreg_flags [ins->dreg] & VREG_SINGLE_BB_USE)) { - DEBUG (printf ("[simd-simplify] Nullify %d on first BB: ", ins->dreg); mono_print_ins(ins)); - NULLIFY_INS (ins); - } - } - - g_free (vreg_flags); - g_free (target_bb); + return strcmp ((const char*)key, method_name (*(guint16*)value)); } -/* -* Windows x64 value type ABI uses reg/stack references (ArgValuetypeAddrInIReg/ArgValuetypeAddrOnStack) -* for function arguments. When using SIMD intrinsics arguments optimized into OP_ARG needs to be decomposed -* into correspondig SIMD LOADX/STOREX instructions. -*/ -#if defined(TARGET_WIN32) && defined(TARGET_AMD64) -static gboolean -decompose_vtype_opt_uses_simd_intrinsics (MonoCompile *cfg, MonoInst *ins) +static int +simd_intrinsic_info_compare_by_name (const void *key, const void *value) { - if (cfg->uses_simd_intrinsics & MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE) - return TRUE; - - switch (ins->opcode) { - case OP_XMOVE: - case OP_XZERO: - case OP_LOADX_MEMBASE: - case OP_LOADX_ALIGNED_MEMBASE: - case OP_STOREX_MEMBASE: - case OP_STOREX_ALIGNED_MEMBASE_REG: - return TRUE; - default: - return FALSE; - } + SimdIntrinsic *info = (SimdIntrinsic*)value; + return strcmp ((const char*)key, method_name (info->id)); } -static void -decompose_vtype_opt_load_arg (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, gint32 *sreg_int32) +static int +lookup_intrins (guint16 *intrinsics, int size, MonoMethod *cmethod) { - guint32 *sreg = (guint32*)sreg_int32; - MonoInst *src_var = get_vreg_to_inst (cfg, *sreg); - if (src_var && src_var->opcode == OP_ARG && src_var->klass && MONO_CLASS_IS_SIMD (cfg, src_var->klass)) { - MonoInst *varload_ins, *load_ins; - NEW_VARLOADA (cfg, varload_ins, src_var, src_var->inst_vtype); - mono_bblock_insert_before_ins (bb, ins, varload_ins); - MONO_INST_NEW (cfg, load_ins, OP_LOADX_MEMBASE); - load_ins->klass = src_var->klass; - load_ins->type = STACK_VTYPE; - load_ins->sreg1 = varload_ins->dreg; - load_ins->dreg = alloc_xreg (cfg); - mono_bblock_insert_after_ins (bb, varload_ins, load_ins); - *sreg = load_ins->dreg; - } + const guint16 *result = (const guint16 *)mono_binary_search (cmethod->name, intrinsics, size / sizeof (guint16), sizeof (guint16), &simd_intrinsic_compare_by_name); + + if (result == NULL) + return -1; + else + return (int)*result; } -void -mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) +static SimdIntrinsic* +lookup_intrins_info (SimdIntrinsic *intrinsics, int size, MonoMethod *cmethod) { - if (cfg->opt & MONO_OPT_SIMD && decompose_vtype_opt_uses_simd_intrinsics (cfg, ins)) { - decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg1)); - decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg2)); - decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg3)); - MonoInst *dest_var = get_vreg_to_inst (cfg, ins->dreg); - if (dest_var && dest_var->opcode == OP_ARG && dest_var->klass && MONO_CLASS_IS_SIMD (cfg, dest_var->klass)) { - MonoInst *varload_ins, *store_ins; - ins->dreg = alloc_xreg (cfg); - NEW_VARLOADA (cfg, varload_ins, dest_var, dest_var->inst_vtype); - mono_bblock_insert_after_ins (bb, ins, varload_ins); - MONO_INST_NEW (cfg, store_ins, OP_STOREX_MEMBASE); - store_ins->klass = dest_var->klass; - store_ins->type = STACK_VTYPE; - store_ins->sreg1 = ins->dreg; - store_ins->dreg = varload_ins->dreg; - mono_bblock_insert_after_ins (bb, varload_ins, store_ins); +#if 0 + for (int i = 0; i < (size / sizeof (SimdIntrinsic)) - 1; ++i) { + const char *n1 = method_name (intrinsics [i].id); + const char *n2 = method_name (intrinsics [i + 1].id); + int len1 = strlen (n1); + int len2 = strlen (n2); + for (int j = 0; j < len1 && j < len2; ++j) { + if (n1 [j] > n2 [j]) { + printf ("%s %s\n", n1, n2); + g_assert_not_reached (); + } else if (n1 [j] < n2 [j]) { + break; + } } } -} -#else -void -mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) -{ -} -#endif /*defined(TARGET_WIN32) && defined(TARGET_AMD64)*/ - -/* - * This function expect that src be a value. - */ -static int -get_simd_vreg (MonoCompile *cfg, MonoMethod *cmethod, MonoInst *src) -{ - const char *spec = INS_INFO (src->opcode); - - if (src->opcode == OP_XMOVE) { - return src->sreg1; - } else if (spec [MONO_INST_DEST] == 'x') { - return src->dreg; - } else if (src->opcode == OP_VCALL || src->opcode == OP_VCALL_MEMBASE) { - return src->dreg; - } +#endif - g_warning ("get_simd_vreg:: could not infer source simd vreg for op"); - mono_print_ins (src); - g_assert_not_reached (); + return (SimdIntrinsic *)mono_binary_search (cmethod->name, intrinsics, size / sizeof (SimdIntrinsic), sizeof (SimdIntrinsic), &simd_intrinsic_info_compare_by_name); } /* - * This function will load the value if needed. + * Return a simd vreg for the simd value represented by SRC. + * SRC is the 'this' argument to methods. + * Set INDIRECT to TRUE if the value was loaded from memory. */ static int load_simd_vreg_class (MonoCompile *cfg, MonoClass *klass, MonoInst *src, gboolean *indirect) @@ -946,28 +170,133 @@ load_simd_vreg (MonoCompile *cfg, MonoMethod *cmethod, MonoInst *src, gboolean * return load_simd_vreg_class (cfg, cmethod->klass, src, indirect); } -/*We share the var with fconv_to_r8_x to save some stack space.*/ +/* Create and emit a SIMD instruction, dreg is auto-allocated */ +static MonoInst* +emit_simd_ins (MonoCompile *cfg, MonoClass *klass, int opcode, int sreg1, int sreg2) +{ + const char *spec = INS_INFO (opcode); + MonoInst *ins; + + MONO_INST_NEW (cfg, ins, opcode); + if (spec [MONO_INST_DEST] == 'x') { + ins->dreg = alloc_xreg (cfg); + ins->type = STACK_VTYPE; + } else if (spec [MONO_INST_DEST] == 'i') { + ins->dreg = alloc_ireg (cfg); + ins->type = STACK_I4; + } else if (spec [MONO_INST_DEST] == 'l') { + ins->dreg = alloc_lreg (cfg); + ins->type = STACK_I8; + } else if (spec [MONO_INST_DEST] == 'f') { + ins->dreg = alloc_freg (cfg); + ins->type = STACK_R8; + } + ins->sreg1 = sreg1; + ins->sreg2 = sreg2; + ins->klass = klass; + MONO_ADD_INS (cfg->cbb, ins); + return ins; +} + static MonoInst* -get_double_spill_area (MonoCompile *cfg) +emit_simd_ins_for_sig (MonoCompile *cfg, MonoClass *klass, int opcode, int instc0, int instc1, MonoMethodSignature *fsig, MonoInst **args) +{ + g_assert (fsig->param_count <= 3); + MonoInst* ins = emit_simd_ins (cfg, klass, opcode, + fsig->param_count > 0 ? args [0]->dreg : -1, + fsig->param_count > 1 ? args [1]->dreg : -1); + if (instc0 != -1) + ins->inst_c0 = instc0; + if (instc1 != -1) + ins->inst_c1 = instc1; + if (fsig->param_count == 3) + ins->sreg3 = args [2]->dreg; + return ins; +} + +static gboolean +is_hw_intrinsics_class (MonoClass *klass, const char *name, gboolean *is_64bit) +{ + const char *class_name = m_class_get_name (klass); + if ((!strcmp (class_name, "X64") || !strcmp (class_name, "Arm64")) && m_class_get_nested_in (klass)) { + *is_64bit = TRUE; + return !strcmp (m_class_get_name (m_class_get_nested_in (klass)), name); + } else { + *is_64bit = FALSE; + return !strcmp (class_name, name); + } +} + +static MonoTypeEnum +get_underlying_type (MonoType* type) { - if (!cfg->fconv_to_r8_x_var) { - cfg->fconv_to_r8_x_var = mono_compile_create_var (cfg, m_class_get_byval_arg (mono_defaults.double_class), OP_LOCAL); - cfg->fconv_to_r8_x_var->flags |= MONO_INST_VOLATILE; /*FIXME, use the don't regalloc flag*/ - } - return cfg->fconv_to_r8_x_var; + MonoClass* klass = mono_class_from_mono_type_internal (type); + if (type->type == MONO_TYPE_PTR) // e.g. int* => MONO_TYPE_I4 + return m_class_get_byval_arg (m_class_get_element_class (klass))->type; + else if (type->type == MONO_TYPE_GENERICINST) // e.g. Vector128 => MONO_TYPE_I4 + return mono_class_get_context (klass)->class_inst->type_argv [0]->type; + else + return type->type; } + static MonoInst* -get_simd_ctor_spill_area (MonoCompile *cfg, MonoClass *avector_klass) +emit_xcompare (MonoCompile *cfg, MonoClass *klass, MonoTypeEnum etype, MonoInst *arg1, MonoInst *arg2) +{ + MonoInst *ins; + gboolean is_fp = etype == MONO_TYPE_R4 || etype == MONO_TYPE_R8; + + ins = emit_simd_ins (cfg, klass, is_fp ? OP_XCOMPARE_FP : OP_XCOMPARE, arg1->dreg, arg2->dreg); + ins->inst_c0 = CMP_EQ; + ins->inst_c1 = etype; + return ins; +} + +static MonoType* +get_vector_t_elem_type (MonoType *vector_type) +{ + MonoClass *klass; + MonoType *etype; + + g_assert (vector_type->type == MONO_TYPE_GENERICINST); + klass = mono_class_from_mono_type_internal (vector_type); + g_assert ( + !strcmp (m_class_get_name (klass), "Vector`1") || + !strcmp (m_class_get_name (klass), "Vector128`1") || + !strcmp (m_class_get_name (klass), "Vector256`1")); + etype = mono_class_get_context (klass)->class_inst->type_argv [0]; + return etype; +} + +static MonoInst * +emit_arch_vector128_create_multi (MonoCompile *cfg, MonoMethodSignature *fsig, MonoClass *klass, MonoType *etype, MonoInst **args) { - if (!cfg->simd_ctor_var) { - cfg->simd_ctor_var = mono_compile_create_var (cfg, m_class_get_byval_arg (avector_klass), OP_LOCAL); - cfg->simd_ctor_var->flags |= MONO_INST_VOLATILE; /*FIXME, use the don't regalloc flag*/ - } - return cfg->simd_ctor_var; +#if defined(TARGET_AMD64) + MonoInst *ins, *load; + + // FIXME: Optimize this + MONO_INST_NEW (cfg, ins, OP_LOCALLOC_IMM); + ins->dreg = alloc_preg (cfg); + ins->inst_imm = 16; + MONO_ADD_INS (cfg->cbb, ins); + + int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + int store_opcode = mono_type_to_store_membase (cfg, etype); + for (int i = 0; i < fsig->param_count; ++i) + MONO_EMIT_NEW_STORE_MEMBASE (cfg, store_opcode, ins->dreg, i * esize, args [i]->dreg); + + load = emit_simd_ins (cfg, klass, OP_SSE_LOADU, ins->dreg, -1); + load->inst_c0 = 16; + load->inst_c1 = get_underlying_type (etype); + return load; +#else + return NULL; +#endif } +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) + static int -mono_type_to_expand_op (MonoType *type) +type_to_expand_op (MonoType *type) { switch (type->type) { case MONO_TYPE_I1: @@ -991,1353 +320,1764 @@ mono_type_to_expand_op (MonoType *type) } } -static int -type_to_comp_op (MonoType *t) +static guint16 vector_128_methods [] = { + SN_AsByte, + SN_AsDouble, + SN_AsInt16, + SN_AsInt32, + SN_AsInt64, + SN_AsSByte, + SN_AsSingle, + SN_AsUInt16, + SN_AsUInt32, + SN_AsUInt64, + SN_Create, + SN_CreateScalarUnsafe, +}; + +static MonoInst* +emit_vector128 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - switch (t->type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - return OP_PCMPEQB; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - return OP_PCMPEQW; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - return OP_PCMPEQD; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - return OP_PCMPEQQ; - case MONO_TYPE_R4: - return OP_COMPPS; - case MONO_TYPE_R8: - return OP_COMPPD; - default: - g_assert_not_reached (); - return -1; - } -} - -static int -type_to_gt_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_I1: - return OP_PCMPGTB; - case MONO_TYPE_I2: - return OP_PCMPGTW; - case MONO_TYPE_I4: - return OP_PCMPGTD; - case MONO_TYPE_I8: - return OP_PCMPGTQ; - default: - return -1; - } -} - -static int -type_to_padd_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_U1: - case MONO_TYPE_I1: - return OP_PADDB; - case MONO_TYPE_U2: - case MONO_TYPE_I2: - return OP_PADDW; - case MONO_TYPE_U4: - case MONO_TYPE_I4: - return OP_PADDD; - case MONO_TYPE_U8: - case MONO_TYPE_I8: - return OP_PADDQ; - case MONO_TYPE_R4: - return OP_ADDPS; - case MONO_TYPE_R8: - return OP_ADDPD; - default: - break; - } - return -1; -} + if (!COMPILE_LLVM (cfg)) + return NULL; -static int -type_to_psub_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_U1: - case MONO_TYPE_I1: - return OP_PSUBB; - case MONO_TYPE_U2: - case MONO_TYPE_I2: - return OP_PSUBW; - case MONO_TYPE_U4: - case MONO_TYPE_I4: - return OP_PSUBD; - case MONO_TYPE_U8: - case MONO_TYPE_I8: - return OP_PSUBQ; - case MONO_TYPE_R4: - return OP_SUBPS; - case MONO_TYPE_R8: - return OP_SUBPD; - default: - break; - } - return -1; -} + MonoClass *klass = cmethod->klass; + int id = lookup_intrins (vector_128_methods, sizeof (vector_128_methods), cmethod); + if (id == -1) + return NULL; -static int -type_to_pmul_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_U2: - case MONO_TYPE_I2: - return OP_PMULW; - case MONO_TYPE_U4: - case MONO_TYPE_I4: - return OP_PMULD; - case MONO_TYPE_R4: - return OP_MULPS; - case MONO_TYPE_R8: - return OP_MULPD; - case MONO_TYPE_U8: - /* PMULQ multiplies two 32 bit numbers into a 64 bit one */ - return -1; - case MONO_TYPE_I8: - return -1; - default: - break; + if (!strcmp (m_class_get_name (cfg->method->klass), "Vector256")) + return NULL; // TODO: Fix Vector256.WithUpper/WithLower + + MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; + + switch (id) { + case SN_AsByte: + case SN_AsDouble: + case SN_AsInt16: + case SN_AsInt32: + case SN_AsInt64: + case SN_AsSByte: + case SN_AsSingle: + case SN_AsUInt16: + case SN_AsUInt32: + case SN_AsUInt64: + return emit_simd_ins (cfg, klass, OP_XCAST, args [0]->dreg, -1); + case SN_Create: { + MonoType *etype = get_vector_t_elem_type (fsig->ret); + if (fsig->param_count == 1 && mono_metadata_type_equal (fsig->params [0], etype)) + return emit_simd_ins (cfg, klass, type_to_expand_op (etype), args [0]->dreg, -1); + else + return emit_arch_vector128_create_multi (cfg, fsig, klass, etype, args); } - return -1; -} - -static int -type_to_pdiv_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_R4: - return OP_DIVPS; - case MONO_TYPE_R8: - return OP_DIVPD; + case SN_CreateScalarUnsafe: + return emit_simd_ins_for_sig (cfg, klass, OP_CREATE_SCALAR_UNSAFE, -1, arg0_type, fsig, args); default: break; } - return -1; -} - -static int -type_to_pxor_op (MonoType *t) -{ - /* - * These opcodes have the same semantics, but using the - * correctly typed version is better for performance. - */ - switch (t->type) { - case MONO_TYPE_R4: - return OP_XORPS; - case MONO_TYPE_R8: - return OP_XORPD; - default: - return OP_PXOR; - } -} -static int -type_to_pand_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_R4: - return OP_ANDPS; - case MONO_TYPE_R8: - return OP_ANDPD; - default: - return OP_PAND; - } -} - -static int -type_to_por_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_R4: - return OP_ORPS; - case MONO_TYPE_R8: - return OP_ORPD; - default: - return OP_POR; - } -} - -static int -type_to_pmin_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_R4: - return OP_MINPS; - case MONO_TYPE_R8: - return OP_MINPD; - case MONO_TYPE_I1: - return OP_PMINB; - case MONO_TYPE_U1: - return OP_PMINB_UN; - case MONO_TYPE_I2: - return OP_PMINW; - case MONO_TYPE_U2: - return OP_PMINW_UN; - case MONO_TYPE_I4: - return OP_PMIND; - case MONO_TYPE_U4: - return OP_PMIND_UN; - default: - return -1; - } -} - -static int -type_to_pmax_op (MonoType *t) -{ - switch (t->type) { - case MONO_TYPE_R4: - return OP_MAXPS; - case MONO_TYPE_R8: - return OP_MAXPD; - case MONO_TYPE_I1: - return OP_PMAXB; - case MONO_TYPE_U1: - return OP_PMAXB_UN; - case MONO_TYPE_I2: - return OP_PMAXW; - case MONO_TYPE_U2: - return OP_PMAXW_UN; - case MONO_TYPE_I4: - return OP_PMAXD; - case MONO_TYPE_U4: - return OP_PMAXD_UN; - default: - return -1; - } -} - -static int -get_simd_vreg_or_expanded_scalar (MonoCompile *cfg, MonoClass *klass, MonoType *param_type, MonoInst *src) -{ - MonoInst *ins; - int expand_op; - - if (m_class_is_simd_type (mono_class_from_mono_type_internal (param_type))) - return get_simd_vreg (cfg, NULL, src); - - expand_op = mono_type_to_expand_op (param_type); - MONO_INST_NEW (cfg, ins, expand_op); - ins->klass = klass; - ins->sreg1 = src->dreg; - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - - if (expand_op == OP_EXPAND_R4) - ins->backend.spill_var = mini_get_int_to_float_spill_area (cfg); - else if (expand_op == OP_EXPAND_R8) - ins->backend.spill_var = get_double_spill_area (cfg); - - return ins->dreg; + return NULL; } -/* - * simd_intrinsic_emit_binary_op: - * - * Emit a binary SIMD opcode. - * @LHS/@RHS are the two arguments, they can be either a SIMD type or a scalar one. Scalar arguments are - * expanded to the SIMD type. - */ -static MonoInst* -simd_intrinsic_emit_binary_op (MonoCompile *cfg, int opcode, int flags, MonoClass *klass, MonoType *lhs_type, MonoType *rhs_type, MonoInst *lhs, MonoInst *rhs) -{ - MonoInst* ins; - int left_vreg, right_vreg; +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) - left_vreg = get_simd_vreg_or_expanded_scalar (cfg, klass, lhs_type, lhs); - right_vreg = get_simd_vreg_or_expanded_scalar (cfg, klass, rhs_type, rhs); +#ifdef TARGET_AMD64 - MONO_INST_NEW (cfg, ins, opcode); - ins->klass = klass; - ins->sreg1 = left_vreg; - ins->sreg2 = right_vreg; - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - ins->inst_c0 = flags; - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} +static guint16 vector_methods [] = { + SN_ConvertToDouble, + SN_ConvertToInt32, + SN_ConvertToInt64, + SN_ConvertToSingle, + SN_ConvertToUInt32, + SN_ConvertToUInt64, + SN_Narrow, + SN_Widen, + SN_get_IsHardwareAccelerated, +}; static MonoInst* -simd_intrinsic_emit_binary (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) +emit_sys_numerics_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - MonoMethodSignature *sig = mono_method_signature_internal (cmethod); + MonoInst *ins; + gboolean supported = FALSE; + int id; + MonoType *etype; - g_assert (sig->param_count == 2); + id = lookup_intrins (vector_methods, sizeof (vector_methods), cmethod); + if (id == -1) + return NULL; - return simd_intrinsic_emit_binary_op (cfg, intrinsic->opcode, intrinsic->flags, cmethod->klass, sig->params [0], sig->params [1], args [0], args [1]); -} + //printf ("%s\n", mono_method_full_name (cmethod, 1)); -static MonoInst* -simd_intrinsic_emit_unary (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst* ins; - int vreg; - - vreg = get_simd_vreg (cfg, cmethod, args [0]); - - MONO_INST_NEW (cfg, ins, intrinsic->opcode); - ins->klass = cmethod->klass; - ins->sreg1 = vreg; - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} +#ifdef MONO_ARCH_SIMD_INTRINSICS + supported = TRUE; +#endif -static int -mono_type_to_extract_op (MonoCompile *cfg, MonoType *type) -{ - switch (type->type) { - case MONO_TYPE_I1: - return OP_EXTRACT_I1; - case MONO_TYPE_U1: - return OP_EXTRACT_U1; - case MONO_TYPE_I2: - return OP_EXTRACT_I2; - case MONO_TYPE_U2: - return OP_EXTRACT_U2; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - return OP_EXTRACT_I4; - case MONO_TYPE_R4: - if (COMPILE_LLVM (cfg)) - return OP_EXTRACT_R4; - else - return OP_EXTRACT_I4; - default: - g_assert_not_reached (); + if (cfg->verbose_level > 1) { + char *name = mono_method_full_name (cmethod, TRUE); + printf (" SIMD intrinsic %s\n", name); + g_free (name); } -} -/*Returns the amount to shift the element index to get the dword it belongs to*/ -static int -mono_type_elements_shift_bits (MonoType *type) -{ - switch (type->type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - return 2; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - return 1; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_R4: - return 0; + switch (id) { + case SN_get_IsHardwareAccelerated: + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + ins->type = STACK_I4; + return ins; + case SN_ConvertToInt32: + etype = get_vector_t_elem_type (fsig->params [0]); + g_assert (etype->type == MONO_TYPE_R4); + return emit_simd_ins (cfg, mono_class_from_mono_type_internal (fsig->ret), OP_CVTPS2DQ, args [0]->dreg, -1); + case SN_ConvertToSingle: + etype = get_vector_t_elem_type (fsig->params [0]); + g_assert (etype->type == MONO_TYPE_I4 || etype->type == MONO_TYPE_U4); + // FIXME: + if (etype->type == MONO_TYPE_U4) + return NULL; + return emit_simd_ins (cfg, mono_class_from_mono_type_internal (fsig->ret), OP_CVTDQ2PS, args [0]->dreg, -1); + case SN_ConvertToDouble: + case SN_ConvertToInt64: + case SN_ConvertToUInt32: + case SN_ConvertToUInt64: + case SN_Narrow: + case SN_Widen: + // FIXME: + break; default: - g_assert_not_reached (); + break; } -} -static G_GNUC_UNUSED int -mono_type_to_insert_op (MonoType *type) -{ - switch (type->type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - return OP_INSERT_I1; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - return OP_INSERT_I2; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - return OP_INSERT_I4; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - return OP_INSERT_I8; - case MONO_TYPE_R4: - return OP_INSERT_R4; - case MONO_TYPE_R8: - return OP_INSERT_R8; - default: - g_assert_not_reached (); - } + return NULL; } -static int -mono_type_to_slow_insert_op (MonoType *type) -{ - switch (type->type) { - case MONO_TYPE_I1: - case MONO_TYPE_U1: - return OP_INSERTX_U1_SLOW; - case MONO_TYPE_I2: - case MONO_TYPE_U2: - return OP_INSERT_I2; - case MONO_TYPE_I4: - case MONO_TYPE_U4: - return OP_INSERTX_I4_SLOW; - case MONO_TYPE_I8: - case MONO_TYPE_U8: - return OP_INSERTX_I8_SLOW; - case MONO_TYPE_R4: - return OP_INSERTX_R4_SLOW; - case MONO_TYPE_R8: - return OP_INSERTX_R8_SLOW; - default: - g_assert_not_reached (); - } -} +static guint16 vector_t_methods [] = { + SN_ctor, + SN_CopyTo, + SN_Equals, + SN_GreaterThan, + SN_GreaterThanOrEqual, + SN_LessThan, + SN_LessThanOrEqual, + SN_Max, + SN_Min, + SN_get_AllBitsSet, + SN_get_Count, + SN_get_Item, + SN_get_One, + SN_get_Zero, + SN_op_Addition, + SN_op_BitwiseAnd, + SN_op_BitwiseOr, + SN_op_Division, + SN_op_Equality, + SN_op_ExclusiveOr, + SN_op_Explicit, + SN_op_Inequality, + SN_op_Multiply, + SN_op_Subtraction +}; static MonoInst* -simd_intrinsic_emit_setter (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) +emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { MonoInst *ins; - MonoMethodSignature *sig = mono_method_signature_internal (cmethod); - int size, align; - gboolean indirect; - int dreg; + MonoType *type, *etype; + MonoClass *klass; + int size, len, id; + gboolean is_unsigned; - size = mono_type_size (sig->params [0], &align); + static const float r4_one = 1.0f; + static const double r8_one = 1.0; - if (COMPILE_LLVM (cfg)) { - MONO_INST_NEW (cfg, ins, mono_type_to_insert_op (sig->params [0])); - ins->klass = cmethod->klass; - ins->dreg = ins->sreg1 = dreg = load_simd_vreg (cfg, cmethod, args [0], &indirect); - ins->sreg2 = args [1]->dreg; - ins->inst_c0 = intrinsic->opcode; - MONO_ADD_INS (cfg->cbb, ins); - } else if (size == 2 || size == 4 || size == 8) { - MONO_INST_NEW (cfg, ins, mono_type_to_slow_insert_op (sig->params [0])); - ins->klass = cmethod->klass; - /*This is a partial load so we encode the dependency on the previous value by setting dreg and sreg1 to the same value.*/ - ins->dreg = ins->sreg1 = dreg = load_simd_vreg (cfg, cmethod, args [0], &indirect); - ins->sreg2 = args [1]->dreg; - ins->inst_c0 = intrinsic->opcode; - if (sig->params [0]->type == MONO_TYPE_R4) - ins->backend.spill_var = mini_get_int_to_float_spill_area (cfg); - else if (sig->params [0]->type == MONO_TYPE_R8) - ins->backend.spill_var = get_double_spill_area (cfg); - MONO_ADD_INS (cfg->cbb, ins); - } else { - int vreg, sreg; + id = lookup_intrins (vector_t_methods, sizeof (vector_t_methods), cmethod); + if (id == -1) + return NULL; - MONO_INST_NEW (cfg, ins, OP_EXTRACTX_U2); - ins->klass = cmethod->klass; - ins->sreg1 = sreg = dreg = load_simd_vreg (cfg, cmethod, args [0], &indirect); - ins->type = STACK_I4; - ins->dreg = vreg = alloc_ireg (cfg); - ins->inst_c0 = intrinsic->opcode / 2; - MONO_ADD_INS (cfg->cbb, ins); + klass = cmethod->klass; + type = m_class_get_byval_arg (klass); + etype = mono_class_get_context (klass)->class_inst->type_argv [0]; + size = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + g_assert (size); + len = register_size / size; - MONO_INST_NEW (cfg, ins, OP_INSERTX_U1_SLOW); - ins->klass = cmethod->klass; - ins->sreg1 = vreg; - ins->sreg2 = args [1]->dreg; - ins->dreg = sreg; - ins->inst_c0 = intrinsic->opcode; - MONO_ADD_INS (cfg->cbb, ins); - } + if (!MONO_TYPE_IS_PRIMITIVE (etype) || etype->type == MONO_TYPE_CHAR || etype->type == MONO_TYPE_BOOLEAN) + return NULL; - if (indirect) { - MONO_INST_NEW (cfg, ins, OP_STOREX_MEMBASE); - ins->klass = cmethod->klass; - ins->dreg = args [0]->dreg; - ins->sreg1 = dreg; - MONO_ADD_INS (cfg->cbb, ins); + if (cfg->verbose_level > 1) { + char *name = mono_method_full_name (cmethod, TRUE); + printf (" SIMD intrinsic %s\n", name); + g_free (name); } - return ins; -} - -/* - * simd_intrinsic_emit_getter_op: - * - * Emit IR for loading an element of a SIMD value. - * - * @klass is the simd type, @type is the element type. - */ -static MonoInst* -simd_intrinsic_emit_getter_op (MonoCompile *cfg, int index, MonoClass *klass, MonoType *type, MonoInst *arg) -{ - MonoInst *ins; - int vreg, shift_bits; - - vreg = load_simd_vreg_class (cfg, klass, arg, NULL); - - if (type->type == MONO_TYPE_I8 || type->type == MONO_TYPE_U8 || type->type == MONO_TYPE_R8) { - MonoInst *ins; - gboolean is_r8 = type->type == MONO_TYPE_R8; - MONO_INST_NEW (cfg, ins, is_r8 ? OP_EXTRACT_R8 : OP_EXTRACT_I8); - ins->klass = klass; - ins->sreg1 = vreg; - ins->inst_c0 = index; - if (is_r8) { - ins->type = STACK_R8; - ins->dreg = alloc_freg (cfg); - ins->backend.spill_var = get_double_spill_area (cfg); - } else { - ins->type = STACK_I8; - ins->dreg = alloc_lreg (cfg); - } - MONO_ADD_INS (cfg->cbb, ins); + switch (id) { + case SN_get_Count: + if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4)) + break; + EMIT_NEW_ICONST (cfg, ins, len); return ins; + case SN_get_Zero: + g_assert (fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type)); + return emit_simd_ins (cfg, klass, OP_XZERO, -1, -1); + case SN_get_One: { + g_assert (fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type)); + MonoInst *one = NULL; + int expand_opcode = type_to_expand_op (etype); + MONO_INST_NEW (cfg, one, -1); + switch (expand_opcode) { + case OP_EXPAND_R4: + one->opcode = OP_R4CONST; + one->type = STACK_R4; + one->inst_p0 = (void *) &r4_one; + break; + case OP_EXPAND_R8: + one->opcode = OP_R8CONST; + one->type = STACK_R8; + one->inst_p0 = (void *) &r8_one; + break; + default: + one->opcode = OP_ICONST; + one->type = STACK_I4; + one->inst_c0 = 1; + break; + } + one->dreg = alloc_dreg (cfg, (MonoStackType)one->type); + MONO_ADD_INS (cfg->cbb, one); + return emit_simd_ins (cfg, klass, expand_opcode, one->dreg, -1); } - - shift_bits = mono_type_elements_shift_bits (type); - - if ((index >> shift_bits) && !cfg->compile_llvm) { - MONO_INST_NEW (cfg, ins, OP_PSHUFLED); - ins->klass = klass; - ins->sreg1 = vreg; - ins->inst_c0 = index >> shift_bits; - ins->type = STACK_VTYPE; - ins->dreg = vreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - } - - MONO_INST_NEW (cfg, ins, mono_type_to_extract_op (cfg, type)); - ins->klass = klass; - ins->sreg1 = vreg; - if (ins->opcode == OP_EXTRACT_R4) { - ins->type = STACK_R4; - ins->dreg = vreg = alloc_freg (cfg); - } else { - ins->type = STACK_I4; - ins->dreg = vreg = alloc_ireg (cfg); - } - if (cfg->compile_llvm) - ins->inst_c0 = index; - else - ins->inst_c0 = index & ((1 << shift_bits) - 1); - MONO_ADD_INS (cfg->cbb, ins); - - if (type->type == MONO_TYPE_R4 && ins->opcode != OP_EXTRACT_R4) { - MONO_INST_NEW (cfg, ins, cfg->r4fp ? OP_ICONV_TO_R4_RAW : OP_MOVE_I4_TO_F); - ins->klass = mono_defaults.single_class; - ins->sreg1 = vreg; - ins->type = cfg->r4_stack_type; - ins->dreg = alloc_freg (cfg); - ins->backend.spill_var = mini_get_int_to_float_spill_area (cfg); - MONO_ADD_INS (cfg->cbb, ins); - } - return ins; -} - -static MonoInst* -simd_intrinsic_emit_getter (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoMethodSignature *sig = mono_method_signature_internal (cmethod); - - return simd_intrinsic_emit_getter_op (cfg, intrinsic->opcode, cmethod->klass, sig->ret, args [0]); -} - -static MonoInst* -simd_intrinsic_emit_long_getter (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins; - int vreg; - gboolean is_r8 = mono_method_signature_internal (cmethod)->ret->type == MONO_TYPE_R8; - - vreg = load_simd_vreg (cfg, cmethod, args [0], NULL); - - MONO_INST_NEW (cfg, ins, is_r8 ? OP_EXTRACT_R8 : OP_EXTRACT_I8); - ins->klass = cmethod->klass; - ins->sreg1 = vreg; - ins->inst_c0 = intrinsic->opcode; - if (is_r8) { - ins->type = STACK_R8; - ins->dreg = alloc_freg (cfg); - ins->backend.spill_var = get_double_spill_area (cfg); - } else { - ins->type = STACK_I8; - ins->dreg = alloc_lreg (cfg); + case SN_get_AllBitsSet: { + /* Compare a zero vector with itself */ + ins = emit_simd_ins (cfg, klass, OP_XZERO, -1, -1); + return emit_xcompare (cfg, klass, etype->type, ins, ins); } - MONO_ADD_INS (cfg->cbb, ins); - - return ins; -} - -static MonoInst* -simd_intrinsic_emit_ctor (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins = NULL; - int i, addr_reg; - gboolean is_ldaddr = (args [0]->opcode == OP_LDADDR && args [0]->inst_left->opcode != OP_ARG); - MonoMethodSignature *sig = mono_method_signature_internal (cmethod); - int store_op = mono_type_to_store_membase (cfg, sig->params [0]); - int arg_size = mono_type_size (sig->params [0], &i); - int opcode; - - if (sig->param_count == 1) { + case SN_get_Item: { + if (!COMPILE_LLVM (cfg)) + return NULL; + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len); + MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "IndexOutOfRangeException"); + int opcode = -1; int dreg; - - if (is_ldaddr) { - dreg = args [0]->inst_i0->dreg; - NULLIFY_INS (args [0]); - } else { - g_assert (args [0]->type == STACK_MP || args [0]->type == STACK_PTR); + gboolean is64 = FALSE; + switch (etype->type) { + case MONO_TYPE_I8: + case MONO_TYPE_U8: + opcode = OP_XEXTRACT_I64; + is64 = TRUE; + dreg = alloc_lreg (cfg); + break; + case MONO_TYPE_R8: + opcode = OP_XEXTRACT_R8; + dreg = alloc_freg (cfg); + break; + case MONO_TYPE_R4: + g_assert (cfg->r4fp); + opcode = OP_XEXTRACT_R4; + dreg = alloc_freg (cfg); + break; + default: + opcode = OP_XEXTRACT_I32; dreg = alloc_ireg (cfg); - } - - if (intrinsic) - opcode = intrinsic->opcode; - else - opcode = mono_type_to_expand_op (sig->params [0]); - MONO_INST_NEW (cfg, ins, opcode); - ins->klass = cmethod->klass; - ins->sreg1 = args [1]->dreg; - ins->type = STACK_VTYPE; - ins->dreg = dreg; - MONO_ADD_INS (cfg->cbb, ins); - if (sig->params [0]->type == MONO_TYPE_R4) - ins->backend.spill_var = mini_get_int_to_float_spill_area (cfg); - else if (sig->params [0]->type == MONO_TYPE_R8) - ins->backend.spill_var = get_double_spill_area (cfg); - - if (!is_ldaddr) { - MONO_INST_NEW (cfg, ins, OP_STOREX_MEMBASE); - ins->dreg = args [0]->dreg; - ins->sreg1 = dreg; - MONO_ADD_INS (cfg->cbb, ins); - } - return ins; - } - - if (is_ldaddr) { - NEW_VARLOADA (cfg, ins, get_simd_ctor_spill_area (cfg, cmethod->klass), &cmethod->klass->byref_arg); - MONO_ADD_INS (cfg->cbb, ins); - addr_reg = ins->dreg; - } else { - g_assert (args [0]->type == STACK_MP || args [0]->type == STACK_PTR); - addr_reg = args [0]->dreg; - } - - for (i = sig->param_count - 1; i >= 0; --i) { - EMIT_NEW_STORE_MEMBASE (cfg, ins, store_op, addr_reg, i * arg_size, args [i + 1]->dreg); - } - - if (sig->param_count * arg_size < 16) { - /* If there are not enough arguments, fill the rest with 0s */ - for (i = sig->param_count; i < 16 / arg_size; ++i) { - switch (arg_size) { - case 4: - MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI4_MEMBASE_IMM, addr_reg, i * arg_size, 0); - break; - default: - g_assert_not_reached (); - break; - } - } - } - - if (is_ldaddr) { /*Eliminate LDADDR if it's initing a local var*/ - int vreg = ((MonoInst*)args [0]->inst_p0)->dreg; - NULLIFY_INS (args [0]); - - MONO_INST_NEW (cfg, ins, OP_LOADX_MEMBASE); - ins->klass = cmethod->klass; - ins->sreg1 = addr_reg; - ins->type = STACK_VTYPE; - ins->dreg = vreg; + break; + } + MONO_INST_NEW (cfg, ins, opcode); + ins->dreg = dreg; + ins->sreg1 = load_simd_vreg (cfg, cmethod, args [0], NULL); + ins->sreg2 = args [1]->dreg; + ins->inst_c0 = etype->type; + mini_type_to_eval_stack_type (cfg, etype, ins); MONO_ADD_INS (cfg->cbb, ins); + return ins; } - return ins; -} - -static MonoInst* -simd_intrinsic_emit_cast (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins; - MonoClass *klass; - int vreg; - - vreg = get_simd_vreg (cfg, cmethod, args [0]); - - if (cmethod->is_inflated) - /* Vector */ - klass = mono_class_from_mono_type_internal (mono_method_signature_internal (cmethod)->ret); - else - klass = cmethod->klass; + case SN_ctor: + if (fsig->param_count == 1 && mono_metadata_type_equal (fsig->params [0], etype)) { + int dreg = load_simd_vreg (cfg, cmethod, args [0], NULL); - MONO_INST_NEW (cfg, ins, OP_XMOVE); - ins->klass = klass; - ins->type = STACK_VTYPE; - ins->sreg1 = vreg; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} + int opcode = type_to_expand_op (etype); + ins = emit_simd_ins (cfg, klass, opcode, args [1]->dreg, -1); + ins->dreg = dreg; + return ins; + } + if ((fsig->param_count == 1 || fsig->param_count == 2) && (fsig->params [0]->type == MONO_TYPE_SZARRAY)) { + MonoInst *array_ins = args [1]; + MonoInst *index_ins; + MonoInst *ldelema_ins; + MonoInst *var; + int end_index_reg; -static MonoInst* -simd_intrinsic_emit_shift (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins; - int vreg, vreg2 = -1, opcode = intrinsic->opcode; + if (args [0]->opcode != OP_LDADDR) + return NULL; - vreg = get_simd_vreg (cfg, cmethod, args [0]); + /* .ctor (T[]) or .ctor (T[], index) */ - if (args [1]->opcode != OP_ICONST) { - MONO_INST_NEW (cfg, ins, OP_ICONV_TO_X); - ins->klass = mono_defaults.int32_class; - ins->sreg1 = args [1]->dreg; - ins->type = STACK_I4; - ins->dreg = vreg2 = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); + if (fsig->param_count == 2) { + index_ins = args [2]; + } else { + EMIT_NEW_ICONST (cfg, index_ins, 0); + } - ++opcode; /*The shift_reg version op is always +1 from the regular one.*/ - } + /* Emit index check for the end (index + len - 1 < array length) */ + end_index_reg = alloc_ireg (cfg); + EMIT_NEW_BIALU_IMM (cfg, ins, OP_IADD_IMM, end_index_reg, index_ins->dreg, len - 1); + MONO_EMIT_BOUNDS_CHECK (cfg, array_ins->dreg, MonoArray, max_length, end_index_reg); - MONO_INST_NEW (cfg, ins, opcode); - ins->klass = cmethod->klass; - ins->sreg1 = vreg; - ins->sreg2 = vreg2; + /* Load the array slice into the simd reg */ + ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE); + g_assert (args [0]->opcode == OP_LDADDR); + var = (MonoInst*)args [0]->inst_p0; + EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADX_MEMBASE, var->dreg, ldelema_ins->dreg, 0); + ins->klass = cmethod->klass; + return args [0]; + } + break; + case SN_CopyTo: + if ((fsig->param_count == 1 || fsig->param_count == 2) && (fsig->params [0]->type == MONO_TYPE_SZARRAY)) { + MonoInst *array_ins = args [1]; + MonoInst *index_ins; + MonoInst *ldelema_ins; + int val_vreg, end_index_reg; - if (args [1]->opcode == OP_ICONST) { - ins->inst_imm = args [1]->inst_c0; - NULLIFY_INS (args [1]); - } + val_vreg = load_simd_vreg (cfg, cmethod, args [0], NULL); - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} + /* CopyTo (T[]) or CopyTo (T[], index) */ -static gboolean -mono_op_is_packed_compare (int op) -{ - return op >= OP_PCMPEQB && op <= OP_PCMPEQQ; -} + if (fsig->param_count == 2) { + index_ins = args [2]; + } else { + EMIT_NEW_ICONST (cfg, index_ins, 0); + } -static MonoInst* -simd_intrinsic_emit_equality_op (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args, int opcode, int flags) -{ - MonoInst* ins; - int left_vreg, right_vreg, tmp_vreg; + /* CopyTo () does complicated argument checks */ + mini_emit_bounds_check_offset (cfg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), index_ins->dreg, "ArgumentOutOfRangeException"); + end_index_reg = alloc_ireg (cfg); + int len_reg = alloc_ireg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, len_reg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length), MONO_INST_INVARIANT_LOAD); + EMIT_NEW_BIALU (cfg, ins, OP_ISUB, end_index_reg, len_reg, index_ins->dreg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, end_index_reg, len); + MONO_EMIT_NEW_COND_EXC (cfg, LT, "ArgumentException"); - left_vreg = load_simd_vreg (cfg, cmethod, args [0], NULL); - right_vreg = get_simd_vreg (cfg, cmethod, args [1]); - - MONO_INST_NEW (cfg, ins, opcode); - ins->klass = cmethod->klass; - ins->sreg1 = left_vreg; - ins->sreg2 = right_vreg; - ins->type = STACK_VTYPE; - ins->klass = cmethod->klass; - ins->dreg = tmp_vreg = alloc_ireg (cfg); - ins->inst_c0 = flags; - MONO_ADD_INS (cfg->cbb, ins); + /* Load the array slice into the simd reg */ + ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, FALSE, FALSE); + EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ldelema_ins->dreg, 0, val_vreg); + ins->klass = cmethod->klass; + return ins; + } + break; + case SN_Equals: + if (fsig->param_count == 1 && fsig->ret->type == MONO_TYPE_BOOLEAN && mono_metadata_type_equal (fsig->params [0], type)) { + int sreg1 = load_simd_vreg (cfg, cmethod, args [0], NULL); - /*FIXME the next ops are SSE specific*/ - MONO_INST_NEW (cfg, ins, OP_EXTRACT_MASK); - ins->klass = cmethod->klass; - ins->sreg1 = tmp_vreg; - ins->type = STACK_I4; - ins->dreg = tmp_vreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); + return emit_simd_ins (cfg, klass, OP_XEQUAL, sreg1, args [1]->dreg); + } else if (fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)) { + /* Per element equality */ + return emit_xcompare (cfg, klass, etype->type, args [0], args [1]); + } + break; + case SN_op_Equality: + case SN_op_Inequality: + g_assert (fsig->param_count == 2 && fsig->ret->type == MONO_TYPE_BOOLEAN && + mono_metadata_type_equal (fsig->params [0], type) && + mono_metadata_type_equal (fsig->params [1], type)); + ins = emit_simd_ins (cfg, klass, OP_XEQUAL, args [0]->dreg, args [1]->dreg); + if (id == SN_op_Inequality) { + int sreg = ins->dreg; + int dreg = alloc_ireg (cfg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, sreg, 0); + EMIT_NEW_UNALU (cfg, ins, OP_CEQ, dreg, -1); + } + return ins; + case SN_GreaterThan: + case SN_GreaterThanOrEqual: + case SN_LessThan: + case SN_LessThanOrEqual: + g_assert (fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)); + is_unsigned = etype->type == MONO_TYPE_U1 || etype->type == MONO_TYPE_U2 || etype->type == MONO_TYPE_U4 || etype->type == MONO_TYPE_U8; + ins = emit_xcompare (cfg, klass, etype->type, args [0], args [1]); + switch (id) { + case SN_GreaterThan: + ins->inst_c0 = is_unsigned ? CMP_GT_UN : CMP_GT; + break; + case SN_GreaterThanOrEqual: + ins->inst_c0 = is_unsigned ? CMP_GE_UN : CMP_GE; + break; + case SN_LessThan: + ins->inst_c0 = is_unsigned ? CMP_LT_UN : CMP_LT; + break; + case SN_LessThanOrEqual: + ins->inst_c0 = is_unsigned ? CMP_LE_UN : CMP_LE; + break; + default: + g_assert_not_reached (); + } + return ins; + case SN_op_Explicit: + return emit_simd_ins (cfg, klass, OP_XCAST, args [0]->dreg, -1); + case SN_op_Addition: + case SN_op_Subtraction: + case SN_op_Division: + case SN_op_Multiply: + case SN_op_BitwiseAnd: + case SN_op_BitwiseOr: + case SN_op_ExclusiveOr: + case SN_Max: + case SN_Min: + if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type))) + return NULL; + ins = emit_simd_ins (cfg, klass, OP_XBINOP, args [0]->dreg, args [1]->dreg); + ins->inst_c1 = etype->type; - /*FP ops have a not equal instruction, which means that we must test the results with OR semantics.*/ - if (mono_op_is_packed_compare (opcode) || flags == SIMD_COMP_EQ) { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_vreg, 0xFFFF); - NEW_UNALU (cfg, ins, flags == SIMD_COMP_EQ ? OP_CEQ : OP_CLT_UN, tmp_vreg, -1); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_vreg, 0); - NEW_UNALU (cfg, ins, OP_CGT_UN, tmp_vreg, -1); + if (etype->type == MONO_TYPE_R4 || etype->type == MONO_TYPE_R8) { + switch (id) { + case SN_op_Addition: + ins->inst_c0 = OP_FADD; + break; + case SN_op_Subtraction: + ins->inst_c0 = OP_FSUB; + break; + case SN_op_Multiply: + ins->inst_c0 = OP_FMUL; + break; + case SN_op_Division: + ins->inst_c0 = OP_FDIV; + break; + case SN_Max: + ins->inst_c0 = OP_FMAX; + break; + case SN_Min: + ins->inst_c0 = OP_FMIN; + break; + default: + NULLIFY_INS (ins); + return NULL; + } + } else { + switch (id) { + case SN_op_Addition: + ins->inst_c0 = OP_IADD; + break; + case SN_op_Subtraction: + ins->inst_c0 = OP_ISUB; + break; + /* + case SN_op_Division: + ins->inst_c0 = OP_IDIV; + break; + case SN_op_Multiply: + ins->inst_c0 = OP_IMUL; + break; + */ + case SN_op_BitwiseAnd: + ins->inst_c0 = OP_IAND; + break; + case SN_op_BitwiseOr: + ins->inst_c0 = OP_IOR; + break; + case SN_op_ExclusiveOr: + ins->inst_c0 = OP_IXOR; + break; + case SN_Max: + ins->inst_c0 = OP_IMAX; + break; + case SN_Min: + ins->inst_c0 = OP_IMIN; + break; + default: + NULLIFY_INS (ins); + return NULL; + } + } + return ins; + default: + break; } - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} -static MonoInst* -simd_intrinsic_emit_equality (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - return simd_intrinsic_emit_equality_op (cfg, cmethod, args, intrinsic->opcode, intrinsic->flags); + return NULL; } +#endif // TARGET_AMD64 static MonoInst* -simd_intrinsic_emit_shuffle (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) +emit_invalid_operation (MonoCompile *cfg, const char* message) { - MonoInst *ins; - int vreg, vreg2 = -1; - int param_count = mono_method_signature_internal (cmethod)->param_count; - - if (args [param_count - 1]->opcode != OP_ICONST) { - /*TODO Shuffle with non literals is not yet supported */ - return NULL; - } - - vreg = get_simd_vreg (cfg, cmethod, args [0]); - if (param_count == 3) - vreg2 = get_simd_vreg (cfg, cmethod, args [1]); - - NULLIFY_INS (args [param_count - 1]); - - - MONO_INST_NEW (cfg, ins, intrinsic->opcode); - ins->klass = cmethod->klass; - ins->sreg1 = vreg; - ins->sreg2 = vreg2; - ins->inst_c0 = args [param_count - 1]->inst_c0; - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - - if (param_count == 3 && ins->opcode == OP_PSHUFLED) - ins->opcode = OP_SHUFPS; - return ins; + mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); + mono_error_set_generic_error (cfg->error, "System", "InvalidOperationException", "%s", message); + return NULL; } -static MonoInst* -simd_intrinsic_emit_load_aligned (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins; - - MONO_INST_NEW (cfg, ins, OP_LOADX_ALIGNED_MEMBASE); - ins->klass = cmethod->klass; - ins->sreg1 = args [0]->dreg; - ins->type = STACK_VTYPE; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} +#ifdef TARGET_ARM64 -static MonoInst* -simd_intrinsic_emit_store (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins; - int vreg; - vreg = get_simd_vreg (cfg, cmethod, args [1]); +static SimdIntrinsic armbase_methods [] = { + {SN_LeadingSignCount}, + {SN_LeadingZeroCount}, + {SN_MultiplyHigh}, + {SN_ReverseElementBits}, + {SN_get_IsSupported} +}; - MONO_INST_NEW (cfg, ins, intrinsic->opcode); - ins->klass = cmethod->klass; - ins->dreg = args [0]->dreg; - ins->sreg1 = vreg; - ins->type = STACK_VTYPE; - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} +static SimdIntrinsic crc32_methods [] = { + {SN_ComputeCrc32}, + {SN_ComputeCrc32C}, + {SN_get_IsSupported} +}; -static MonoInst* -simd_intrinsic_emit_extract_mask (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ - MonoInst *ins; - int vreg; - - vreg = get_simd_vreg (cfg, cmethod, args [0]); +static SimdIntrinsic sha1_methods [] = { + {SN_FixedRotate, OP_XOP_X_X, SIMD_OP_ARM64_SHA1H}, + {SN_HashUpdateChoose, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1C}, + {SN_HashUpdateMajority, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1M}, + {SN_HashUpdateParity, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1P}, + {SN_ScheduleUpdate0, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA1SU0}, + {SN_ScheduleUpdate1, OP_XOP_X_X_X, SIMD_OP_ARM64_SHA1SU1}, + {SN_get_IsSupported} +}; - MONO_INST_NEW (cfg, ins, OP_EXTRACT_MASK); - ins->klass = cmethod->klass; - ins->sreg1 = vreg; - ins->type = STACK_I4; - ins->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, ins); +static SimdIntrinsic sha256_methods [] = { + {SN_HashUpdate1, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA256H}, + {SN_HashUpdate2, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA256H2}, + {SN_ScheduleUpdate0, OP_XOP_X_X_X, SIMD_OP_ARM64_SHA256SU0}, + {SN_ScheduleUpdate1, OP_XOP_X_X_X_X, SIMD_OP_ARM64_SHA256SU1}, + {SN_get_IsSupported} +}; - return ins; -} +static SimdIntrinsic advsimd_methods [] = { + {SN_Abs} +}; static MonoInst* -simd_intrinsic_emit_prefetch (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) +emit_arm64_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - MonoInst *ins; - - MONO_INST_NEW (cfg, ins, OP_PREFETCH_MEMBASE); - ins->klass = cmethod->klass; - ins->sreg1 = args [0]->dreg; - ins->backend.arg_info = intrinsic->flags; - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} + // Arm64 intrinsics are LLVM-only + if (!COMPILE_LLVM (cfg)) + return NULL; -static MonoInst* -simd_intrinsic_emit_const (const SimdIntrinsic *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args) -{ MonoInst *ins; + gboolean supported, is_64bit; + MonoClass *klass = cmethod->klass; + MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; + gboolean arg0_i32 = (arg0_type == MONO_TYPE_I4) || (arg0_type == MONO_TYPE_U4); + SimdIntrinsic *info; + MonoCPUFeatures feature = -1; + SimdIntrinsic *intrinsics = NULL; + int intrinsics_size; + int id = -1; + gboolean jit_supported = FALSE; + + if (is_hw_intrinsics_class (klass, "ArmBase", &is_64bit)) { + info = lookup_intrins_info (armbase_methods, sizeof (armbase_methods), cmethod); + if (!info) + return NULL; - MONO_INST_NEW (cfg, ins, intrinsic->opcode); - ins->klass = cmethod->klass; - ins->type = STACK_VTYPE; - ins->dreg = alloc_xreg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins; -} + supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_BASE) != 0; -static MonoInst* -emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args, const SimdIntrinsic *intrinsics, guint32 size) -{ - const SimdIntrinsic *result = (const SimdIntrinsic *)mono_binary_search (cmethod->name, intrinsics, size, sizeof (SimdIntrinsic), &simd_intrinsic_compare_by_name); - if (!result) { - DEBUG (printf ("function doesn't have a simd intrinsic %s::%s/%d\n", m_class_get_name (cmethod->klass), cmethod->name, fsig->param_count)); - return NULL; - } - if (IS_DEBUG_ON (cfg)) { - int i, max; - printf ("found call to intrinsic %s::%s/%d -> %s\n", m_class_get_name (cmethod->klass), cmethod->name, fsig->param_count, method_name (result->name)); - max = fsig->param_count + fsig->hasthis; - for (i = 0; i < max; ++i) { - printf ("param %d: ", i); - mono_print_ins (args [i]); + switch (info->id) { + case SN_get_IsSupported: + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + ins->type = STACK_I4; + return ins; + case SN_LeadingZeroCount: + return emit_simd_ins_for_sig (cfg, klass, arg0_i32 ? OP_LZCNT32 : OP_LZCNT64, 0, arg0_type, fsig, args); + case SN_LeadingSignCount: + return emit_simd_ins_for_sig (cfg, klass, arg0_i32 ? OP_LSCNT32 : OP_LSCNT64, 0, arg0_type, fsig, args); + case SN_MultiplyHigh: + return emit_simd_ins_for_sig (cfg, klass, + (arg0_type == MONO_TYPE_I8 ? OP_ARM64_SMULH : OP_ARM64_UMULH), 0, arg0_type, fsig, args); + case SN_ReverseElementBits: + return emit_simd_ins_for_sig (cfg, klass, + (is_64bit ? OP_XOP_I8_I8 : OP_XOP_I4_I4), + (is_64bit ? SIMD_OP_ARM64_RBIT64 : SIMD_OP_ARM64_RBIT32), + arg0_type, fsig, args); + default: + g_assert_not_reached (); // if a new API is added we need to either implement it or change IsSupported to false } } - if (result->simd_version) { - MonoCPUFeatures features = mini_get_cpu_features (cfg); - if ((result->simd_version & features) == 0) { - printf ("function %s::%s/%d requires one of unsuported SIMD instruction set(s). \n", m_class_get_name (cmethod->klass), cmethod->name, fsig->param_count); - if (IS_DEBUG_ON (cfg)) - printf ("function %s::%s/%d requires one of unsuported SIMD instruction set(s). \n", m_class_get_name (cmethod->klass), cmethod->name, fsig->param_count); + + if (is_hw_intrinsics_class (klass, "Crc32", &is_64bit)) { + info = lookup_intrins_info (crc32_methods, sizeof (crc32_methods), cmethod); + if (!info) return NULL; + + supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_CRC) != 0; + + switch (info->id) { + case SN_get_IsSupported: + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + ins->type = STACK_I4; + return ins; + case SN_ComputeCrc32: + case SN_ComputeCrc32C: { + SimdOp op = (SimdOp)0; + gboolean is_c = info->id == SN_ComputeCrc32C; + switch (get_underlying_type (fsig->params [1])) { + case MONO_TYPE_U1: op = is_c ? SIMD_OP_ARM64_CRC32CB : SIMD_OP_ARM64_CRC32B; break; + case MONO_TYPE_U2: op = is_c ? SIMD_OP_ARM64_CRC32CH : SIMD_OP_ARM64_CRC32H; break; + case MONO_TYPE_U4: op = is_c ? SIMD_OP_ARM64_CRC32CW : SIMD_OP_ARM64_CRC32W; break; + case MONO_TYPE_U8: op = is_c ? SIMD_OP_ARM64_CRC32CX : SIMD_OP_ARM64_CRC32X; break; + default: g_assert_not_reached (); break; + } + return emit_simd_ins_for_sig (cfg, klass, is_64bit ? OP_XOP_I4_I4_I8 : OP_XOP_I4_I4_I4, op, arg0_type, fsig, args); + } + default: + g_assert_not_reached (); // if a new API is added we need to either implement it or change IsSupported to false } } - switch (result->simd_emit_mode) { - case SIMD_EMIT_BINARY: - return simd_intrinsic_emit_binary (result, cfg, cmethod, args); - case SIMD_EMIT_UNARY: - return simd_intrinsic_emit_unary (result, cfg, cmethod, args); - case SIMD_EMIT_SETTER: - return simd_intrinsic_emit_setter (result, cfg, cmethod, args); - case SIMD_EMIT_GETTER: - return simd_intrinsic_emit_getter (result, cfg, cmethod, args); - case SIMD_EMIT_GETTER_QWORD: - return simd_intrinsic_emit_long_getter (result, cfg, cmethod, args); - case SIMD_EMIT_CTOR: - return simd_intrinsic_emit_ctor (result, cfg, cmethod, args); - case SIMD_EMIT_CAST: - return simd_intrinsic_emit_cast (result, cfg, cmethod, args); - case SIMD_EMIT_SHUFFLE: - return simd_intrinsic_emit_shuffle (result, cfg, cmethod, args); - case SIMD_EMIT_SHIFT: - return simd_intrinsic_emit_shift (result, cfg, cmethod, args); - case SIMD_EMIT_EQUALITY: - return simd_intrinsic_emit_equality (result, cfg, cmethod, args); - case SIMD_EMIT_LOAD_ALIGNED: - return simd_intrinsic_emit_load_aligned (result, cfg, cmethod, args); - case SIMD_EMIT_STORE: - return simd_intrinsic_emit_store (result, cfg, cmethod, args); - case SIMD_EMIT_EXTRACT_MASK: - return simd_intrinsic_emit_extract_mask (result, cfg, cmethod, args); - case SIMD_EMIT_PREFETCH: - return simd_intrinsic_emit_prefetch (result, cfg, cmethod, args); + if (is_hw_intrinsics_class (klass, "Sha256", &is_64bit)) { + feature = MONO_CPU_ARM64_CRYPTO; + intrinsics = sha256_methods; + intrinsics_size = sizeof (sha256_methods); } - g_assert_not_reached (); -} - -static int -mono_emit_vector_ldelema (MonoCompile *cfg, MonoType *array_type, MonoInst *arr, MonoInst *index, gboolean check_bounds) -{ - MonoInst *ins; - guint32 size; - int mult_reg, add_reg, array_reg, index_reg, index2_reg, index3_reg; - - size = mono_array_element_size (mono_class_from_mono_type_internal (array_type)); - mult_reg = alloc_preg (cfg); - array_reg = arr->dreg; - index_reg = index->dreg; - -#if TARGET_SIZEOF_VOID_P == 8 - /* The array reg is 64 bits but the index reg is only 32 */ - index2_reg = alloc_preg (cfg); - MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, index2_reg, index_reg); -#else - index2_reg = index_reg; -#endif - index3_reg = alloc_preg (cfg); - if (check_bounds) { - MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index2_reg); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PADD_IMM, index3_reg, index2_reg, 16 / size - 1); - MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index3_reg); + if (is_hw_intrinsics_class (klass, "Sha1", &is_64bit)) { + feature = MONO_CPU_ARM64_CRYPTO; + intrinsics = sha1_methods; + intrinsics_size = sizeof (sha1_methods); } - add_reg = alloc_preg (cfg); + /* + * Common logic for all instruction sets + */ + if (intrinsics) { + if (!COMPILE_LLVM (cfg) && !jit_supported) + return NULL; + info = lookup_intrins_info (intrinsics, intrinsics_size, cmethod); + if (!info) + return NULL; + id = info->id; - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_MUL_IMM, mult_reg, index2_reg, size); - MONO_EMIT_NEW_BIALU (cfg, OP_PADD, add_reg, array_reg, mult_reg); - NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, add_reg, add_reg, MONO_STRUCT_OFFSET (MonoArray, vector)); - ins->type = STACK_PTR; - MONO_ADD_INS (cfg->cbb, ins); + if (feature) + supported = (mini_get_cpu_features (cfg) & feature) != 0; + else + supported = TRUE; + if (id == SN_get_IsSupported) { + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + return ins; + } - return add_reg; -} + if (!supported && cfg->compile_aot) { + // Can't emit non-supported llvm intrinsics + if (cfg->method != cmethod) { + // Keep the original call so we end up in the intrinsic method + return NULL; + } else { + // Emit an exception from the intrinsic method + mono_emit_jit_icall (cfg, mono_throw_not_supported, NULL); + return NULL; + } + } -static MonoInst* -emit_array_extension_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - if ((!strcmp ("GetVector", cmethod->name) || !strcmp ("GetVectorAligned", cmethod->name)) && fsig->param_count == 2) { - MonoInst *load; - int addr = mono_emit_vector_ldelema (cfg, fsig->params [0], args [0], args [1], TRUE); - - MONO_INST_NEW (cfg, load, !strcmp ("GetVectorAligned", cmethod->name) ? OP_LOADX_ALIGNED_MEMBASE : OP_LOADX_MEMBASE ); - load->klass = cmethod->klass; - load->sreg1 = addr; - load->type = STACK_VTYPE; - load->dreg = alloc_ireg (cfg); - MONO_ADD_INS (cfg->cbb, load); - - return load; - } - if ((!strcmp ("SetVector", cmethod->name) || !strcmp ("SetVectorAligned", cmethod->name)) && fsig->param_count == 3) { - MonoInst *store; - int vreg = get_simd_vreg (cfg, cmethod, args [1]); - int addr = mono_emit_vector_ldelema (cfg, fsig->params [0], args [0], args [2], TRUE); - - MONO_INST_NEW (cfg, store, !strcmp ("SetVectorAligned", cmethod->name) ? OP_STOREX_ALIGNED_MEMBASE_REG : OP_STOREX_MEMBASE); - store->klass = cmethod->klass; - store->dreg = addr; - store->sreg1 = vreg; - MONO_ADD_INS (cfg->cbb, store); - - return store; + if (info->op != 0) + return emit_simd_ins_for_sig (cfg, klass, info->op, info->instc0, arg0_type, fsig, args); } - if (!strcmp ("IsAligned", cmethod->name) && fsig->param_count == 2) { - MonoInst *ins; - int addr = mono_emit_vector_ldelema (cfg, fsig->params [0], args [0], args [1], FALSE); + + if (is_hw_intrinsics_class (klass, "AdvSimd", &is_64bit)) { + info = lookup_intrins_info (advsimd_methods, sizeof (advsimd_methods), cmethod); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, addr, addr, 15); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, addr, 0); - NEW_UNALU (cfg, ins, OP_CEQ, addr, -1); - MONO_ADD_INS (cfg->cbb, ins); + if (!info) + return NULL; - return ins; - } - return NULL; -} + supported = (mini_get_cpu_features (cfg) & MONO_CPU_ARM64_ADVSIMD) != 0; -static guint32 -get_simd_supported_versions (MonoCompile *cfg) -{ - MonoCPUFeatures features = mini_get_cpu_features (cfg); - guint32 versions = 0; - - if (features & MONO_CPU_X86_SSE) - versions |= SIMD_VERSION_SSE1; - if (features & MONO_CPU_X86_SSE2) - versions |= SIMD_VERSION_SSE2; - if (features & MONO_CPU_X86_SSE3) - versions |= SIMD_VERSION_SSE3; - if (features & MONO_CPU_X86_SSSE3) - versions |= SIMD_VERSION_SSSE3; - if (features & MONO_CPU_X86_SSE41) - versions |= SIMD_VERSION_SSE41; - if (features & MONO_CPU_X86_SSE42) - versions |= SIMD_VERSION_SSE42; - return versions; -} + switch (info -> id) { + case SN_Abs: { + SimdOp op = (SimdOp)0; + switch (get_underlying_type (fsig->params [0])) { + case MONO_TYPE_R8: + op = SIMD_OP_LLVM_DABS; + break; + case MONO_TYPE_R4: + op = SIMD_OP_LLVM_FABS; + break; + case MONO_TYPE_I1: + op = SIMD_OP_LLVM_I8ABS; + break; + case MONO_TYPE_I2: + op = SIMD_OP_LLVM_I16ABS; + break; + case MONO_TYPE_I4: + op = SIMD_OP_LLVM_I32ABS; + break; + case MONO_TYPE_I8: + op = SIMD_OP_LLVM_I64ABS; + break; + } -static MonoInst* -emit_simd_runtime_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - if (!strcmp ("get_AccelMode", cmethod->name) && fsig->param_count == 0) { - MonoInst *ins; - guint32 versions = get_simd_supported_versions (cfg); - EMIT_NEW_ICONST (cfg, ins, versions); - return ins; + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X, op, arg0_type, fsig, args); + } + } + } - return NULL; -} -static gboolean -is_sys_numerics_assembly (MonoAssembly *assembly) -{ - return !strcmp ("System.Numerics", assembly->aname.name); + return NULL; } +#endif // TARGET_ARM64 + +#ifdef TARGET_AMD64 + +static SimdIntrinsic sse_methods [] = { + {SN_Add, OP_XBINOP, OP_FADD}, + {SN_AddScalar, OP_SSE_ADDSS}, + {SN_And, OP_SSE_AND}, + {SN_AndNot, OP_SSE_ANDN}, + {SN_CompareEqual, OP_XCOMPARE_FP, CMP_EQ}, + {SN_CompareGreaterThan, OP_XCOMPARE_FP,CMP_GT}, + {SN_CompareGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_GE}, + {SN_CompareLessThan, OP_XCOMPARE_FP, CMP_LT}, + {SN_CompareLessThanOrEqual, OP_XCOMPARE_FP, CMP_LE}, + {SN_CompareNotEqual, OP_XCOMPARE_FP, CMP_NE}, + {SN_CompareNotGreaterThan, OP_XCOMPARE_FP, CMP_LE}, + {SN_CompareNotGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_LT}, + {SN_CompareNotLessThan, OP_XCOMPARE_FP, CMP_GE}, + {SN_CompareNotLessThanOrEqual, OP_XCOMPARE_FP, CMP_GT}, + {SN_CompareOrdered, OP_XCOMPARE_FP, CMP_ORD}, + {SN_CompareScalarEqual, OP_SSE_CMPSS, CMP_EQ}, + {SN_CompareScalarGreaterThan, OP_SSE_CMPSS, CMP_GT}, + {SN_CompareScalarGreaterThanOrEqual, OP_SSE_CMPSS, CMP_GE}, + {SN_CompareScalarLessThan, OP_SSE_CMPSS, CMP_LT}, + {SN_CompareScalarLessThanOrEqual, OP_SSE_CMPSS, CMP_LE}, + {SN_CompareScalarNotEqual, OP_SSE_CMPSS, CMP_NE}, + {SN_CompareScalarNotGreaterThan, OP_SSE_CMPSS, CMP_LE}, + {SN_CompareScalarNotGreaterThanOrEqual, OP_SSE_CMPSS, CMP_LT}, + {SN_CompareScalarNotLessThan, OP_SSE_CMPSS, CMP_GE}, + {SN_CompareScalarNotLessThanOrEqual, OP_SSE_CMPSS, CMP_GT}, + {SN_CompareScalarOrdered, OP_SSE_CMPSS, CMP_ORD}, + {SN_CompareScalarOrderedEqual, OP_SSE_COMISS, CMP_EQ}, + {SN_CompareScalarOrderedGreaterThan, OP_SSE_COMISS, CMP_GT}, + {SN_CompareScalarOrderedGreaterThanOrEqual, OP_SSE_COMISS, CMP_GE}, + {SN_CompareScalarOrderedLessThan, OP_SSE_COMISS, CMP_LT}, + {SN_CompareScalarOrderedLessThanOrEqual, OP_SSE_COMISS, CMP_LE}, + {SN_CompareScalarOrderedNotEqual, OP_SSE_COMISS, CMP_NE}, + {SN_CompareScalarUnordered, OP_SSE_CMPSS, CMP_UNORD}, + {SN_CompareScalarUnorderedEqual, OP_SSE_UCOMISS, CMP_EQ}, + {SN_CompareScalarUnorderedGreaterThan, OP_SSE_UCOMISS, CMP_GT}, + {SN_CompareScalarUnorderedGreaterThanOrEqual, OP_SSE_UCOMISS, CMP_GE}, + {SN_CompareScalarUnorderedLessThan, OP_SSE_UCOMISS, CMP_LT}, + {SN_CompareScalarUnorderedLessThanOrEqual, OP_SSE_UCOMISS, CMP_LE}, + {SN_CompareScalarUnorderedNotEqual, OP_SSE_UCOMISS, CMP_NE}, + {SN_CompareUnordered, OP_XCOMPARE_FP, CMP_UNORD}, + {SN_ConvertScalarToVector128Single}, + {SN_ConvertToInt32, OP_XOP_I4_X, SIMD_OP_SSE_CVTSS2SI}, + {SN_ConvertToInt32WithTruncation, OP_XOP_I4_X, SIMD_OP_SSE_CVTTSS2SI}, + {SN_ConvertToInt64, OP_XOP_I8_X, SIMD_OP_SSE_CVTSS2SI64}, + {SN_ConvertToInt64WithTruncation, OP_XOP_I8_X, SIMD_OP_SSE_CVTTSS2SI64}, + {SN_Divide, OP_XBINOP, OP_FDIV}, + {SN_DivideScalar, OP_SSE_DIVSS}, + {SN_LoadAlignedVector128, OP_SSE_LOADU, 16 /* alignment */}, + {SN_LoadHigh, OP_SSE_MOVHPS_LOAD}, + {SN_LoadLow, OP_SSE_MOVLPS_LOAD}, + {SN_LoadScalarVector128, OP_SSE_MOVSS}, + {SN_LoadVector128, OP_SSE_LOADU, 1 /* alignment */}, + {SN_Max, OP_XOP_X_X_X, SIMD_OP_SSE_MAXPS}, + {SN_MaxScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MAXSS}, + {SN_Min, OP_XOP_X_X_X, SIMD_OP_SSE_MINPS}, + {SN_MinScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MINSS}, + {SN_MoveHighToLow, OP_SSE_MOVEHL}, + {SN_MoveLowToHigh, OP_SSE_MOVELH}, + {SN_MoveMask, OP_SSE_MOVMSK}, + {SN_MoveScalar, OP_SSE_MOVS2}, + {SN_Multiply, OP_XBINOP, OP_FMUL}, + {SN_MultiplyScalar, OP_SSE_MULSS}, + {SN_Or, OP_SSE_OR}, + {SN_Prefetch0, OP_SSE_PREFETCHT0}, + {SN_Prefetch1, OP_SSE_PREFETCHT1}, + {SN_Prefetch2, OP_SSE_PREFETCHT2}, + {SN_PrefetchNonTemporal, OP_SSE_PREFETCHNTA}, + {SN_Reciprocal, OP_XOP_X_X, SIMD_OP_SSE_RCPPS}, + {SN_ReciprocalScalar}, + {SN_ReciprocalSqrt, OP_XOP_X_X, SIMD_OP_SSE_RSQRTPS}, + {SN_ReciprocalSqrtScalar}, + {SN_Shuffle}, + {SN_Sqrt, OP_XOP_X_X, SIMD_OP_SSE_SQRTPS}, + {SN_SqrtScalar}, + {SN_Store, OP_SSE_STORE, 1 /* alignment */}, + {SN_StoreAligned, OP_SSE_STORE, 16 /* alignment */}, + {SN_StoreAlignedNonTemporal, OP_SSE_MOVNTPS, 16 /* alignment */}, + {SN_StoreFence, OP_XOP, SIMD_OP_SSE_SFENCE}, + {SN_StoreHigh, OP_SSE_MOVHPS_STORE}, + {SN_StoreLow, OP_SSE_MOVLPS_STORE}, + {SN_StoreScalar, OP_SSE_MOVSS_STORE}, + {SN_Subtract, OP_XBINOP, OP_FSUB}, + {SN_SubtractScalar, OP_SSE_SUBSS}, + {SN_UnpackHigh, OP_SSE_UNPACKHI}, + {SN_UnpackLow, OP_SSE_UNPACKLO}, + {SN_Xor, OP_SSE_XOR}, + {SN_get_IsSupported} +}; -static gboolean -is_sys_numerics_vectors_assembly (MonoAssembly *assembly) -{ - return !strcmp ("System.Numerics.Vectors", assembly->aname.name); -} +static SimdIntrinsic sse2_methods [] = { + {SN_Add}, + {SN_AddSaturate, OP_SSE2_ADDS}, + {SN_AddScalar, OP_SSE2_ADDSD}, + {SN_And, OP_SSE_AND}, + {SN_AndNot, OP_SSE_ANDN}, + {SN_Average}, + {SN_CompareEqual}, + {SN_CompareGreaterThan}, + {SN_CompareGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_GE}, + {SN_CompareLessThan}, + {SN_CompareLessThanOrEqual, OP_XCOMPARE_FP, CMP_LE}, + {SN_CompareNotEqual, OP_XCOMPARE_FP, CMP_NE}, + {SN_CompareNotGreaterThan, OP_XCOMPARE_FP, CMP_LE}, + {SN_CompareNotGreaterThanOrEqual, OP_XCOMPARE_FP, CMP_LT}, + {SN_CompareNotLessThan, OP_XCOMPARE_FP, CMP_GE}, + {SN_CompareNotLessThanOrEqual, OP_XCOMPARE_FP, CMP_GT}, + {SN_CompareOrdered, OP_XCOMPARE_FP, CMP_ORD}, + {SN_CompareScalarEqual, OP_SSE2_CMPSD, CMP_EQ}, + {SN_CompareScalarGreaterThan, OP_SSE2_CMPSD, CMP_GT}, + {SN_CompareScalarGreaterThanOrEqual, OP_SSE2_CMPSD, CMP_GE}, + {SN_CompareScalarLessThan, OP_SSE2_CMPSD, CMP_LT}, + {SN_CompareScalarLessThanOrEqual, OP_SSE2_CMPSD, CMP_LE}, + {SN_CompareScalarNotEqual, OP_SSE2_CMPSD, CMP_NE}, + {SN_CompareScalarNotGreaterThan, OP_SSE2_CMPSD, CMP_LE}, + {SN_CompareScalarNotGreaterThanOrEqual, OP_SSE2_CMPSD, CMP_LT}, + {SN_CompareScalarNotLessThan, OP_SSE2_CMPSD, CMP_GE}, + {SN_CompareScalarNotLessThanOrEqual, OP_SSE2_CMPSD, CMP_GT}, + {SN_CompareScalarOrdered, OP_SSE2_CMPSD, CMP_ORD}, + {SN_CompareScalarOrderedEqual, OP_SSE2_COMISD, CMP_EQ}, + {SN_CompareScalarOrderedGreaterThan, OP_SSE2_COMISD, CMP_GT}, + {SN_CompareScalarOrderedGreaterThanOrEqual, OP_SSE2_COMISD, CMP_GE}, + {SN_CompareScalarOrderedLessThan, OP_SSE2_COMISD, CMP_LT}, + {SN_CompareScalarOrderedLessThanOrEqual, OP_SSE2_COMISD, CMP_LE}, + {SN_CompareScalarOrderedNotEqual, OP_SSE2_COMISD, CMP_NE}, + {SN_CompareScalarUnordered, OP_SSE2_CMPSD, CMP_UNORD}, + {SN_CompareScalarUnorderedEqual, OP_SSE2_UCOMISD, CMP_EQ}, + {SN_CompareScalarUnorderedGreaterThan, OP_SSE2_UCOMISD, CMP_GT}, + {SN_CompareScalarUnorderedGreaterThanOrEqual, OP_SSE2_UCOMISD, CMP_GE}, + {SN_CompareScalarUnorderedLessThan, OP_SSE2_UCOMISD, CMP_LT}, + {SN_CompareScalarUnorderedLessThanOrEqual, OP_SSE2_UCOMISD, CMP_LE}, + {SN_CompareScalarUnorderedNotEqual, OP_SSE2_UCOMISD, CMP_NE}, + {SN_CompareUnordered, OP_XCOMPARE_FP, CMP_UNORD}, + {SN_ConvertScalarToVector128Double}, + {SN_ConvertScalarToVector128Int32}, + {SN_ConvertScalarToVector128Int64}, + {SN_ConvertScalarToVector128Single, OP_XOP_X_X_X, SIMD_OP_SSE_CVTSD2SS}, + {SN_ConvertScalarToVector128UInt32}, + {SN_ConvertScalarToVector128UInt64}, + {SN_ConvertToInt32}, + {SN_ConvertToInt32WithTruncation, OP_XOP_I4_X, SIMD_OP_SSE_CVTTSD2SI}, + {SN_ConvertToInt64}, + {SN_ConvertToInt64WithTruncation, OP_XOP_I8_X, SIMD_OP_SSE_CVTTSD2SI64}, + {SN_ConvertToUInt32}, + {SN_ConvertToUInt64}, + {SN_ConvertToVector128Double}, + {SN_ConvertToVector128Int32}, + {SN_ConvertToVector128Int32WithTruncation}, + {SN_ConvertToVector128Single}, + {SN_Divide, OP_XBINOP, OP_FDIV}, + {SN_DivideScalar, OP_SSE2_DIVSD}, + {SN_Extract}, + {SN_Insert}, + {SN_LoadAlignedVector128}, + {SN_LoadFence, OP_XOP, SIMD_OP_SSE_LFENCE}, + {SN_LoadHigh, OP_SSE2_MOVHPD_LOAD}, + {SN_LoadLow, OP_SSE2_MOVLPD_LOAD}, + {SN_LoadScalarVector128}, + {SN_LoadVector128}, + {SN_MaskMove, OP_SSE2_MASKMOVDQU}, + {SN_Max}, + {SN_MaxScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MAXSD}, + {SN_MemoryFence, OP_XOP, SIMD_OP_SSE_MFENCE}, + {SN_Min}, // FIXME: + {SN_MinScalar, OP_XOP_X_X_X, SIMD_OP_SSE_MINSD}, + {SN_MoveMask, OP_SSE_MOVMSK}, + {SN_MoveScalar}, + {SN_Multiply}, + {SN_MultiplyAddAdjacent, OP_XOP_X_X_X, SIMD_OP_SSE_PMADDWD}, + {SN_MultiplyHigh}, + {SN_MultiplyLow, OP_PMULW}, + {SN_MultiplyScalar, OP_SSE2_MULSD}, + {SN_Or, OP_SSE_OR}, + {SN_PackSignedSaturate}, + {SN_PackUnsignedSaturate}, + {SN_ShiftLeftLogical}, + {SN_ShiftLeftLogical128BitLane}, + {SN_ShiftRightArithmetic}, + {SN_ShiftRightLogical}, + {SN_ShiftRightLogical128BitLane}, + {SN_Shuffle}, + {SN_ShuffleHigh}, + {SN_ShuffleLow}, + {SN_Sqrt, OP_XOP_X_X, SIMD_OP_SSE_SQRTPD}, + {SN_SqrtScalar}, + {SN_Store, OP_SSE_STORE, 1 /* alignment */}, + {SN_StoreAligned, OP_SSE_STORE, 16 /* alignment */}, + {SN_StoreAlignedNonTemporal, OP_SSE_MOVNTPS, 16 /* alignment */}, + {SN_StoreHigh, OP_SSE2_MOVHPD_STORE}, + {SN_StoreLow, OP_SSE2_MOVLPD_STORE}, + {SN_StoreNonTemporal, OP_SSE_MOVNTPS, 1 /* alignment */}, + {SN_StoreScalar, OP_SSE_STORES}, + {SN_Subtract}, + {SN_SubtractSaturate, OP_SSE2_SUBS}, + {SN_SubtractScalar, OP_SSE2_SUBSD}, + {SN_SumAbsoluteDifferences, OP_XOP_X_X_X, SIMD_OP_SSE_PSADBW}, + {SN_UnpackHigh, OP_SSE_UNPACKHI}, + {SN_UnpackLow, OP_SSE_UNPACKLO}, + {SN_Xor, OP_SSE_XOR}, + {SN_get_IsSupported} +}; -MonoInst* -mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) -{ - const char *class_name; - MonoInst *simd_inst = NULL; +static SimdIntrinsic sse3_methods [] = { + {SN_AddSubtract}, + {SN_HorizontalAdd}, + {SN_HorizontalSubtract}, + {SN_LoadAndDuplicateToVector128, OP_SSE3_MOVDDUP_MEM}, + {SN_LoadDquVector128, OP_XOP_X_I, SIMD_OP_SSE_LDDQU}, + {SN_MoveAndDuplicate, OP_SSE3_MOVDDUP}, + {SN_MoveHighAndDuplicate, OP_SSE3_MOVSHDUP}, + {SN_MoveLowAndDuplicate, OP_SSE3_MOVSLDUP}, + {SN_get_IsSupported} +}; - if (is_sys_numerics_assembly (m_class_get_image (cmethod->klass)->assembly)) { - simd_inst = emit_sys_numerics_intrinsics (cfg, cmethod, fsig, args); - goto on_exit; - } +static SimdIntrinsic ssse3_methods [] = { + {SN_Abs, OP_SSSE3_ABS}, + {SN_AlignRight}, + {SN_HorizontalAdd}, + {SN_HorizontalAddSaturate, OP_XOP_X_X_X, SIMD_OP_SSE_PHADDSW}, + {SN_HorizontalSubtract}, + {SN_HorizontalSubtractSaturate, OP_XOP_X_X_X, SIMD_OP_SSE_PHSUBSW}, + {SN_MultiplyAddAdjacent, OP_XOP_X_X_X, SIMD_OP_SSE_PMADDUBSW}, + {SN_MultiplyHighRoundScale, OP_XOP_X_X_X, SIMD_OP_SSE_PMULHRSW}, + {SN_Shuffle, OP_SSSE3_SHUFFLE}, + {SN_Sign}, + {SN_get_IsSupported} +}; - if (is_sys_numerics_vectors_assembly (m_class_get_image (cmethod->klass)->assembly)) { - simd_inst = emit_sys_numerics_vectors_intrinsics (cfg, cmethod, fsig, args); - goto on_exit; - } +static SimdIntrinsic sse41_methods [] = { + {SN_Blend}, + {SN_BlendVariable}, + {SN_Ceiling, OP_SSE41_ROUNDP, 10 /*round mode*/}, + {SN_CeilingScalar, 0, 10 /*round mode*/}, + {SN_CompareEqual, OP_XCOMPARE, CMP_EQ}, + {SN_ConvertToVector128Int16, OP_SSE_CVTII, MONO_TYPE_I2}, + {SN_ConvertToVector128Int32, OP_SSE_CVTII, MONO_TYPE_I4}, + {SN_ConvertToVector128Int64, OP_SSE_CVTII, MONO_TYPE_I8}, + {SN_DotProduct}, + {SN_Extract}, + {SN_Floor, OP_SSE41_ROUNDP, 9 /*round mode*/}, + {SN_FloorScalar, 0, 9 /*round mode*/}, + {SN_Insert}, + {SN_LoadAlignedVector128NonTemporal, OP_SSE41_LOADANT}, + {SN_Max, OP_XBINOP, OP_IMAX}, + {SN_Min, OP_XBINOP, OP_IMIN}, + {SN_MinHorizontal, OP_XOP_X_X, SIMD_OP_SSE_PHMINPOSUW}, + {SN_MultipleSumAbsoluteDifferences}, + {SN_Multiply, OP_SSE41_MUL}, + {SN_MultiplyLow, OP_SSE41_MULLO}, + {SN_PackUnsignedSaturate, OP_XOP_X_X_X, SIMD_OP_SSE_PACKUSDW}, + {SN_RoundCurrentDirection, OP_SSE41_ROUNDP, 4 /*round mode*/}, + {SN_RoundCurrentDirectionScalar, 0, 4 /*round mode*/}, + {SN_RoundToNearestInteger, OP_SSE41_ROUNDP, 8 /*round mode*/}, + {SN_RoundToNearestIntegerScalar, 0, 8 /*round mode*/}, + {SN_RoundToNegativeInfinity, OP_SSE41_ROUNDP, 9 /*round mode*/}, + {SN_RoundToNegativeInfinityScalar, 0, 9 /*round mode*/}, + {SN_RoundToPositiveInfinity, OP_SSE41_ROUNDP, 10 /*round mode*/}, + {SN_RoundToPositiveInfinityScalar, 0, 10 /*round mode*/}, + {SN_RoundToZero, OP_SSE41_ROUNDP, 11 /*round mode*/}, + {SN_RoundToZeroScalar, 0, 11 /*round mode*/}, + {SN_TestC, OP_XOP_I4_X_X, SIMD_OP_SSE_TESTC}, + {SN_TestNotZAndNotC, OP_XOP_I4_X_X, SIMD_OP_SSE_TESTNZ}, + {SN_TestZ, OP_XOP_I4_X_X, SIMD_OP_SSE_TESTZ}, + {SN_get_IsSupported} +}; - if (strcmp ("Mono.Simd", m_class_get_image (cmethod->klass)->assembly->aname.name) || - strcmp ("Mono.Simd", m_class_get_name_space (cmethod->klass))) { - goto on_exit; - } +static SimdIntrinsic sse42_methods [] = { + {SN_CompareGreaterThan, OP_XCOMPARE, CMP_GT}, + {SN_Crc32}, + {SN_get_IsSupported} +}; - class_name = m_class_get_name (cmethod->klass); - if (!strcmp ("SimdRuntime", class_name)) { - simd_inst = emit_simd_runtime_intrinsics (cfg, cmethod, fsig, args); - goto on_exit; - } +static SimdIntrinsic pclmulqdq_methods [] = { + {SN_CarrylessMultiply}, + {SN_get_IsSupported} +}; - if (!strcmp ("ArrayExtensions", class_name)) { - simd_inst = emit_array_extension_intrinsics (cfg, cmethod, fsig, args); - goto on_exit; - } - - if (!strcmp ("VectorOperations", class_name)) { - if (!(cmethod->flags & METHOD_ATTRIBUTE_STATIC)) - goto on_exit; - class_name = m_class_get_name (mono_class_from_mono_type_internal (mono_method_signature_internal (cmethod)->params [0])); - } else if (!m_class_is_simd_type (cmethod->klass)) - goto on_exit; - - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS_SIMPLIFY_INDIRECTION; - if (!strcmp ("Vector2d", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector2d_intrinsics, sizeof (vector2d_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector4f", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector4f_intrinsics, sizeof (vector4f_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector2ul", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector2ul_intrinsics, sizeof (vector2ul_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector2l", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector2l_intrinsics, sizeof (vector2l_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector4ui", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector4ui_intrinsics, sizeof (vector4ui_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector4i", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector4i_intrinsics, sizeof (vector4i_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector8us", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector8us_intrinsics, sizeof (vector8us_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector8s", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector8s_intrinsics, sizeof (vector8s_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector16b", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector16b_intrinsics, sizeof (vector16b_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } - if (!strcmp ("Vector16sb", class_name)) { - simd_inst = emit_intrinsics (cfg, cmethod, fsig, args, vector16sb_intrinsics, sizeof (vector16sb_intrinsics) / sizeof (SimdIntrinsic)); - goto on_exit; - } +static SimdIntrinsic aes_methods [] = { + {SN_Decrypt, OP_XOP_X_X_X, SIMD_OP_AES_DEC}, + {SN_DecryptLast, OP_XOP_X_X_X, SIMD_OP_AES_DECLAST}, + {SN_Encrypt, OP_XOP_X_X_X, SIMD_OP_AES_ENC}, + {SN_EncryptLast, OP_XOP_X_X_X, SIMD_OP_AES_ENCLAST}, + {SN_InverseMixColumns, OP_XOP_X_X, SIMD_OP_AES_IMC}, + {SN_KeygenAssist}, + {SN_get_IsSupported} +}; -on_exit: - if (simd_inst != NULL) { - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS; - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE; - } +static SimdIntrinsic popcnt_methods [] = { + {SN_PopCount}, + {SN_get_IsSupported} +}; - return simd_inst; -} +static SimdIntrinsic lzcnt_methods [] = { + {SN_LeadingZeroCount}, + {SN_get_IsSupported} +}; -static void -assert_handled (MonoCompile *cfg, MonoMethod *method) -{ - MonoCustomAttrInfo *cattr; - ERROR_DECL (error); +static SimdIntrinsic bmi1_methods [] = { + {SN_AndNot}, + {SN_BitFieldExtract}, + {SN_ExtractLowestSetBit}, + {SN_GetMaskUpToLowestSetBit}, + {SN_ResetLowestSetBit}, + {SN_TrailingZeroCount}, + {SN_get_IsSupported} +}; - if (cfg->verbose_level > 1) { - cattr = mono_custom_attrs_from_method_checked (method, error); - - if (cattr) { - gboolean has_attr = FALSE; - for (int i = 0; i < cattr->num_attrs; ++i) - if (cattr->attrs [i].ctor && (!strcmp (m_class_get_name (cattr->attrs [i].ctor->klass), "JitIntrinsicAttribute"))) - has_attr = TRUE; - if (has_attr) { - printf ("SIMD intrinsic unhandled: %s\n", mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL)); - fflush (stdout); - //g_assert_not_reached (); - } - mono_custom_attrs_free (cattr); - } - } -} +static SimdIntrinsic bmi2_methods [] = { + {SN_MultiplyNoFlags}, + {SN_ParallelBitDeposit}, + {SN_ParallelBitExtract}, + {SN_ZeroHighBits}, + {SN_get_IsSupported} +}; -// The entries should be ordered by name -// System.Numerics.Vector2/Vector3/Vector4 -static const SimdIntrinsic vector2_intrinsics[] = { - { SN_ctor, OP_EXPAND_R4 }, - { SN_Abs }, - { SN_Dot, OP_DPPS }, - { SN_Equals, OP_COMPPS, MONO_CPU_X86_SSE, SIMD_EMIT_EQUALITY, SIMD_COMP_EQ }, - { SN_Max, OP_MAXPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_Min, OP_MINPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_SquareRoot, OP_SQRTPS, MONO_CPU_X86_SSE, SIMD_EMIT_UNARY }, - { SN_op_Addition, OP_ADDPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Division, OP_DIVPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Multiply, OP_MULPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, - { SN_op_Subtraction, OP_SUBPS, MONO_CPU_X86_SSE, SIMD_EMIT_BINARY }, +static SimdIntrinsic x86base_methods [] = { + {SN_BitScanForward}, + {SN_BitScanReverse}, + {SN_get_IsSupported} }; static MonoInst* -emit_vector_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - const SimdIntrinsic *intrins; - MonoMethodSignature *sig = mono_method_signature_internal (cmethod); - MonoType *type = m_class_get_byval_arg (cmethod->klass); - - if (!m_class_is_simd_type (cmethod->klass)) - return NULL; + MonoInst *ins; + gboolean supported, is_64bit; + MonoClass *klass = cmethod->klass; + MonoTypeEnum arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID; + SimdIntrinsic *info = NULL; + MonoCPUFeatures feature = -1; + SimdIntrinsic *intrinsics = NULL; + int intrinsics_size; + int id = -1; + gboolean jit_supported = FALSE; + + if (is_hw_intrinsics_class (klass, "Sse", &is_64bit)) { + feature = MONO_CPU_X86_SSE; + intrinsics = sse_methods; + intrinsics_size = sizeof (sse_methods); + } else if (is_hw_intrinsics_class (klass, "Sse2", &is_64bit)) { + feature = MONO_CPU_X86_SSE2; + intrinsics = sse2_methods; + intrinsics_size = sizeof (sse2_methods); + } else if (is_hw_intrinsics_class (klass, "Sse3", &is_64bit)) { + feature = MONO_CPU_X86_SSE3; + intrinsics = sse3_methods; + intrinsics_size = sizeof (sse3_methods); + } else if (is_hw_intrinsics_class (klass, "Ssse3", &is_64bit)) { + feature = MONO_CPU_X86_SSSE3; + intrinsics = ssse3_methods; + intrinsics_size = sizeof (ssse3_methods); + } else if (is_hw_intrinsics_class (klass, "Sse41", &is_64bit)) { + feature = MONO_CPU_X86_SSE41; + intrinsics = sse41_methods; + intrinsics_size = sizeof (sse41_methods); + } else if (is_hw_intrinsics_class (klass, "Sse42", &is_64bit)) { + feature = MONO_CPU_X86_SSE42; + intrinsics = sse42_methods; + intrinsics_size = sizeof (sse42_methods); + } else if (is_hw_intrinsics_class (klass, "Pclmulqdq", &is_64bit)) { + feature = MONO_CPU_X86_PCLMUL; + intrinsics = pclmulqdq_methods; + intrinsics_size = sizeof (pclmulqdq_methods); + } else if (is_hw_intrinsics_class (klass, "Aes", &is_64bit)) { + feature = MONO_CPU_X86_AES; + intrinsics = aes_methods; + intrinsics_size = sizeof (aes_methods); + } else if (is_hw_intrinsics_class (klass, "Popcnt", &is_64bit)) { + feature = MONO_CPU_X86_POPCNT; + intrinsics = popcnt_methods; + intrinsics_size = sizeof (popcnt_methods); + jit_supported = TRUE; + } else if (is_hw_intrinsics_class (klass, "Lzcnt", &is_64bit)) { + feature = MONO_CPU_X86_LZCNT; + intrinsics = lzcnt_methods; + intrinsics_size = sizeof (lzcnt_methods); + jit_supported = TRUE; + } else if (is_hw_intrinsics_class (klass, "Bmi1", &is_64bit)) { + feature = MONO_CPU_X86_BMI1; + intrinsics = bmi1_methods; + intrinsics_size = sizeof (bmi1_methods); + } else if (is_hw_intrinsics_class (klass, "Bmi2", &is_64bit)) { + feature = MONO_CPU_X86_BMI2; + intrinsics = bmi2_methods; + intrinsics_size = sizeof (bmi2_methods); + } else if (is_hw_intrinsics_class (klass, "X86Base", &is_64bit)) { + feature = 0; + intrinsics = x86base_methods; + intrinsics_size = sizeof (x86base_methods); + } /* - * Vector2/3/4 are handled the same way, since the underlying SIMD type is the same (4 * r4). + * Common logic for all instruction sets */ - intrins = (const SimdIntrinsic*)mono_binary_search (cmethod->name, vector2_intrinsics, sizeof (vector2_intrinsics) / sizeof (SimdIntrinsic), sizeof (SimdIntrinsic), &simd_intrinsic_compare_by_name); - if (!intrins) { - assert_handled (cfg, cmethod); - return NULL; - } + if (intrinsics) { + if (!COMPILE_LLVM (cfg) && !jit_supported) + return NULL; + info = lookup_intrins_info (intrinsics, intrinsics_size, cmethod); + if (!info) + return NULL; + id = info->id; - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD intrinsic %s\n", name); - g_free (name); + if (feature) + supported = (mini_get_cpu_features (cfg) & feature) != 0; + else + supported = TRUE; + if (id == SN_get_IsSupported) { + EMIT_NEW_ICONST (cfg, ins, supported ? 1 : 0); + return ins; + } + + if (!supported && cfg->compile_aot) { + /* Can't emit non-supported llvm intrinsics */ + if (cfg->method != cmethod) { + /* Keep the original call so we end up in the intrinsic method */ + return NULL; + } else { + /* Emit an exception from the intrinsic method */ + mono_emit_jit_icall (cfg, mono_throw_not_supported, NULL); + return NULL; + } + } + + if (info->op != 0) + return emit_simd_ins_for_sig (cfg, klass, info->op, info->instc0, arg0_type, fsig, args); } - switch (intrins->name) { - case SN_ctor: { - gboolean match = TRUE; - for (int i = 0; i < fsig->param_count; ++i) - if (fsig->params [i]->type != MONO_TYPE_R4) - match = FALSE; - if (!match) + /* + * Instruction set specific cases + */ + if (feature == MONO_CPU_X86_SSE) { + switch (id) { + case SN_Shuffle: + if (args [2]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE_SHUFFLE, args [2]->inst_c0, arg0_type, fsig, args); + // FIXME: handle non-constant mask (generate a switch) + return emit_invalid_operation (cfg, "mask in Sse.Shuffle must be constant"); + case SN_ConvertScalarToVector128Single: { + int op = 0; + switch (fsig->params [1]->type) { + case MONO_TYPE_I4: op = OP_SSE_CVTSI2SS; break; + case MONO_TYPE_I8: op = OP_SSE_CVTSI2SS64; break; + default: g_assert_not_reached (); break; + } + return emit_simd_ins_for_sig (cfg, klass, op, 0, 0, fsig, args); + } + case SN_ReciprocalScalar: + case SN_ReciprocalSqrtScalar: + case SN_SqrtScalar: { + int op = 0; + switch (id) { + case SN_ReciprocalScalar: op = OP_SSE_RCPSS; break; + case SN_ReciprocalSqrtScalar: op = OP_SSE_RSQRTSS; break; + case SN_SqrtScalar: op = OP_SSE_SQRTSS; break; + }; + if (fsig->param_count == 1) + return emit_simd_ins (cfg, klass, op, args [0]->dreg, args[0]->dreg); + else if (fsig->param_count == 2) + return emit_simd_ins (cfg, klass, op, args [0]->dreg, args[1]->dreg); + else + g_assert_not_reached (); break; - return simd_intrinsic_emit_ctor (intrins, cfg, cmethod, args); + } + case SN_LoadScalarVector128: + return NULL; + default: + return NULL; + } } - case SN_Equals: - if (!(fsig->param_count == 1 && fsig->ret->type == MONO_TYPE_BOOLEAN && fsig->params [0] == type)) + + if (feature == MONO_CPU_X86_SSE2) { + switch (id) { + case SN_Subtract: + return emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, arg0_type == MONO_TYPE_R8 ? OP_FSUB : OP_ISUB, arg0_type, fsig, args); + case SN_Add: + return emit_simd_ins_for_sig (cfg, klass, OP_XBINOP, arg0_type == MONO_TYPE_R8 ? OP_FADD : OP_IADD, arg0_type, fsig, args); + case SN_Average: + if (arg0_type == MONO_TYPE_U1) + return emit_simd_ins_for_sig (cfg, klass, OP_PAVGB_UN, -1, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_U2) + return emit_simd_ins_for_sig (cfg, klass, OP_PAVGW_UN, -1, arg0_type, fsig, args); + else + return NULL; + case SN_CompareNotEqual: + return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_NE, arg0_type, fsig, args); + case SN_CompareEqual: + return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_EQ, arg0_type, fsig, args); + case SN_CompareGreaterThan: + return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_GT, arg0_type, fsig, args); + case SN_CompareLessThan: + return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_XCOMPARE_FP : OP_XCOMPARE, CMP_LT, arg0_type, fsig, args); + case SN_ConvertToInt32: + if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_I4_X, SIMD_OP_SSE_CVTSD2SI, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_I4) + return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I4, 0, arg0_type, fsig, args); + else + return NULL; + case SN_ConvertToInt64: + if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_I8_X, SIMD_OP_SSE_CVTSD2SI64, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_I8) + return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I8, 0 /*element index*/, arg0_type, fsig, args); + else + g_assert_not_reached (); break; - return simd_intrinsic_emit_equality (intrins, cfg, cmethod, args); - case SN_SquareRoot: - if (!(fsig->param_count == 1 && fsig->ret == type && fsig->params [0] == type)) + case SN_ConvertScalarToVector128Double: { + int op = OP_SSE2_CVTSS2SD; + switch (fsig->params [1]->type) { + case MONO_TYPE_I4: op = OP_SSE2_CVTSI2SD; break; + case MONO_TYPE_I8: op = OP_SSE2_CVTSI2SD64; break; + } + return emit_simd_ins_for_sig (cfg, klass, op, 0, 0, fsig, args); + } + case SN_ConvertScalarToVector128Int32: + case SN_ConvertScalarToVector128Int64: + case SN_ConvertScalarToVector128UInt32: + case SN_ConvertScalarToVector128UInt64: + return emit_simd_ins_for_sig (cfg, klass, OP_CREATE_SCALAR, -1, arg0_type, fsig, args); + case SN_ConvertToUInt32: + return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I4, 0 /*element index*/, arg0_type, fsig, args); + case SN_ConvertToUInt64: + return emit_simd_ins_for_sig (cfg, klass, OP_EXTRACT_I8, 0 /*element index*/, arg0_type, fsig, args); + case SN_ConvertToVector128Double: + if (arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTPS2PD, 0, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_I4) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTDQ2PD, 0, arg0_type, fsig, args); + else + return NULL; + case SN_ConvertToVector128Int32: + if (arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTPS2DQ, 0, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTPD2DQ, 0, arg0_type, fsig, args); + else + return NULL; + case SN_ConvertToVector128Int32WithTruncation: + if (arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTTPS2DQ, 0, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTTPD2DQ, 0, arg0_type, fsig, args); + else + return NULL; + case SN_ConvertToVector128Single: + if (arg0_type == MONO_TYPE_I4) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTDQ2PS, 0, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_CVTPD2PS, 0, arg0_type, fsig, args); + else + return NULL; + case SN_LoadAlignedVector128: + return emit_simd_ins_for_sig (cfg, klass, OP_SSE_LOADU, 16 /*alignment*/, arg0_type, fsig, args); + case SN_LoadVector128: + return emit_simd_ins_for_sig (cfg, klass, OP_SSE_LOADU, 1 /*alignment*/, arg0_type, fsig, args); + case SN_MoveScalar: + return emit_simd_ins_for_sig (cfg, klass, fsig->param_count == 2 ? OP_SSE_MOVS2 : OP_SSE_MOVS, -1, arg0_type, fsig, args); + case SN_Max: + switch (arg0_type) { + case MONO_TYPE_U1: + return emit_simd_ins_for_sig (cfg, klass, OP_PMAXB_UN, 0, arg0_type, fsig, args); + case MONO_TYPE_I2: + return emit_simd_ins_for_sig (cfg, klass, OP_PMAXW, 0, arg0_type, fsig, args); + case MONO_TYPE_R8: return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_MAXPD, arg0_type, fsig, args); + default: + g_assert_not_reached (); + break; + } break; - return simd_intrinsic_emit_unary (intrins, cfg, cmethod, args); - case SN_Dot: - if (!(fsig->param_count == 2 && fsig->ret->type == MONO_TYPE_R4 && fsig->params [0] == type && fsig->params [1] == type)) + case SN_Min: + switch (arg0_type) { + case MONO_TYPE_U1: + return emit_simd_ins_for_sig (cfg, klass, OP_PMINB_UN, 0, arg0_type, fsig, args); + case MONO_TYPE_I2: + return emit_simd_ins_for_sig (cfg, klass, OP_PMINW, 0, arg0_type, fsig, args); + case MONO_TYPE_R8: return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_MINPD, arg0_type, fsig, args); + default: + g_assert_not_reached (); + break; + } break; - if (COMPILE_LLVM (cfg)) { - MonoInst *ins; - - if (!(mini_get_cpu_features (cfg) & MONO_CPU_X86_SSE41)) + case SN_Multiply: + if (arg0_type == MONO_TYPE_U4) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PMULUDQ, 0, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_MULPD, 0, arg0_type, fsig, args); + else + g_assert_not_reached (); + case SN_MultiplyHigh: + if (arg0_type == MONO_TYPE_I2) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PMULHW, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_U2) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PMULHUW, arg0_type, fsig, args); + else + g_assert_not_reached (); + case SN_PackSignedSaturate: + if (arg0_type == MONO_TYPE_I2) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PACKSSWB, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_I4) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PACKSSDW, arg0_type, fsig, args); + else + g_assert_not_reached (); + case SN_PackUnsignedSaturate: + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PACKUS, -1, arg0_type, fsig, args); + case SN_Extract: + g_assert (arg0_type == MONO_TYPE_U2); + return emit_simd_ins_for_sig (cfg, klass, OP_XEXTRACT_I32, arg0_type, 0, fsig, args); + case SN_Insert: + g_assert (arg0_type == MONO_TYPE_I2 || arg0_type == MONO_TYPE_U2); + return emit_simd_ins_for_sig (cfg, klass, OP_XINSERT_I2, 0, arg0_type, fsig, args); + case SN_ShiftRightLogical: { + gboolean is_imm = fsig->params [1]->type == MONO_TYPE_U1; + SimdOp op = (SimdOp)0; + switch (arg0_type) { + case MONO_TYPE_I2: + case MONO_TYPE_U2: + op = is_imm ? SIMD_OP_SSE_PSRLW_IMM : SIMD_OP_SSE_PSRLW; + break; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + op = is_imm ? SIMD_OP_SSE_PSRLD_IMM : SIMD_OP_SSE_PSRLD; + break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: + op = is_imm ? SIMD_OP_SSE_PSRLQ_IMM : SIMD_OP_SSE_PSRLQ; + break; + default: g_assert_not_reached (); break; + } + return emit_simd_ins_for_sig (cfg, klass, is_imm ? OP_XOP_X_X_I4 : OP_XOP_X_X_X, op, arg0_type, fsig, args); + } + case SN_ShiftRightArithmetic: { + gboolean is_imm = fsig->params [1]->type == MONO_TYPE_U1; + SimdOp op = (SimdOp)0; + switch (arg0_type) { + case MONO_TYPE_I2: + case MONO_TYPE_U2: + op = is_imm ? SIMD_OP_SSE_PSRAW_IMM : SIMD_OP_SSE_PSRAW; + break; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + op = is_imm ? SIMD_OP_SSE_PSRAD_IMM : SIMD_OP_SSE_PSRAD; + break; + default: g_assert_not_reached (); break; + } + return emit_simd_ins_for_sig (cfg, klass, is_imm ? OP_XOP_X_X_I4 : OP_XOP_X_X_X, op, arg0_type, fsig, args); + } + case SN_ShiftLeftLogical: { + gboolean is_imm = fsig->params [1]->type == MONO_TYPE_U1; + SimdOp op = (SimdOp)0; + switch (arg0_type) { + case MONO_TYPE_I2: + case MONO_TYPE_U2: + op = is_imm ? SIMD_OP_SSE_PSLLW_IMM : SIMD_OP_SSE_PSLLW; + break; + case MONO_TYPE_I4: + case MONO_TYPE_U4: + op = is_imm ? SIMD_OP_SSE_PSLLD_IMM : SIMD_OP_SSE_PSLLD; + break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: + op = is_imm ? SIMD_OP_SSE_PSLLQ_IMM : SIMD_OP_SSE_PSLLQ; + break; + default: g_assert_not_reached (); break; + } + return emit_simd_ins_for_sig (cfg, klass, is_imm ? OP_XOP_X_X_I4 : OP_XOP_X_X_X, op, arg0_type, fsig, args); + } + case SN_ShiftLeftLogical128BitLane: + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSLLDQ, 0, arg0_type, fsig, args); + case SN_ShiftRightLogical128BitLane: + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSRLDQ, 0, arg0_type, fsig, args); + case SN_Shuffle: { + if (fsig->param_count == 2) { + g_assert (arg0_type == MONO_TYPE_I4 || arg0_type == MONO_TYPE_U4); + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSHUFD, 0, arg0_type, fsig, args); + } else if (fsig->param_count == 3) { + g_assert (arg0_type == MONO_TYPE_R8); + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_SHUFPD, 0, arg0_type, fsig, args); + } else { + g_assert_not_reached (); + break; + } + } + case SN_ShuffleHigh: + g_assert (fsig->param_count == 2); + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSHUFHW, 0, arg0_type, fsig, args); + case SN_ShuffleLow: + g_assert (fsig->param_count == 2); + return emit_simd_ins_for_sig (cfg, klass, OP_SSE2_PSHUFLW, 0, arg0_type, fsig, args); + case SN_SqrtScalar: { + if (fsig->param_count == 1) + return emit_simd_ins (cfg, klass, OP_SSE2_SQRTSD, args [0]->dreg, args[0]->dreg); + else if (fsig->param_count == 2) + return emit_simd_ins (cfg, klass, OP_SSE2_SQRTSD, args [0]->dreg, args[1]->dreg); + else { + g_assert_not_reached (); break; + } + } + case SN_LoadScalarVector128: { + int op = 0; + switch (arg0_type) { + case MONO_TYPE_I4: + case MONO_TYPE_U4: op = OP_SSE2_MOVD; break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: op = OP_SSE2_MOVQ; break; + case MONO_TYPE_R8: op = OP_SSE2_MOVUPD; break; + default: g_assert_not_reached(); break; + } + return emit_simd_ins_for_sig (cfg, klass, op, 0, 0, fsig, args); + } + default: + return NULL; + } + } + + if (feature == MONO_CPU_X86_SSE3) { + switch (id) { + case SN_AddSubtract: + if (arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_ADDSUBPS, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_ADDSUBPD, arg0_type, fsig, args); + else + g_assert_not_reached (); + break; + case SN_HorizontalAdd: + if (arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HADDPS, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HADDPD, arg0_type, fsig, args); + else + g_assert_not_reached (); + break; + case SN_HorizontalSubtract: + if (arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HSUBPS, arg0_type, fsig, args); + else if (arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_HSUBPD, arg0_type, fsig, args); + else + g_assert_not_reached (); + break; + default: + g_assert_not_reached (); + break; + } + } - ins = simd_intrinsic_emit_binary (intrins, cfg, cmethod, args); - /* The end result is in the lowest element */ - return simd_intrinsic_emit_getter_op (cfg, 0, cmethod->klass, mono_method_signature_internal (cmethod)->ret, ins); + if (feature == MONO_CPU_X86_SSSE3) { + switch (id) { + case SN_AlignRight: + if (args [2]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_SSSE3_ALIGNR, args [2]->inst_c0, arg0_type, fsig, args); + return emit_invalid_operation (cfg, "mask in Ssse3.AlignRight must be constant"); + case SN_HorizontalAdd: + if (arg0_type == MONO_TYPE_I2) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHADDW, arg0_type, fsig, args); + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHADDD, arg0_type, fsig, args); + case SN_HorizontalSubtract: + if (arg0_type == MONO_TYPE_I2) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHSUBW, arg0_type, fsig, args); + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PHSUBD, arg0_type, fsig, args); + case SN_Sign: + if (arg0_type == MONO_TYPE_I1) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PSIGNB, arg0_type, fsig, args); + if (arg0_type == MONO_TYPE_I2) + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PSIGNW, arg0_type, fsig, args); + return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X_X, SIMD_OP_SSE_PSIGND, arg0_type, fsig, args); + default: + g_assert_not_reached (); + break; } - break; - case SN_Abs: { - // abs(x) = max(x, sub(0,x)) - MonoInst *sub; - MonoInst *zero; + } - if (!(fsig->param_count == 1 && fsig->ret == type && fsig->params [0] == type)) + if (feature == MONO_CPU_X86_SSE41) { + switch (id) { + case SN_DotProduct: + if (args [2]->opcode == OP_ICONST && arg0_type == MONO_TYPE_R4) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_DPPS_IMM, args [2]->inst_c0, arg0_type, fsig, args); + else if (args [2]->opcode == OP_ICONST && arg0_type == MONO_TYPE_R8) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_DPPD_IMM, args [2]->inst_c0, arg0_type, fsig, args); + // FIXME: handle non-constant control byte (generate a switch) + return emit_invalid_operation (cfg, "control byte in Sse41.DotProduct must be constant"); + case SN_MultipleSumAbsoluteDifferences: + if (args [2]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_MPSADBW_IMM, args [2]->inst_c0, arg0_type, fsig, args); + // FIXME: handle non-constant control byte (generate a switch) + return emit_invalid_operation (cfg, "control byte in Sse41.MultipleSumAbsoluteDifferences must be constant"); + case SN_Blend: + if (args [2]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_BLEND_IMM, args [2]->inst_c0, arg0_type, fsig, args); + // FIXME: handle non-constant control byte (generate a switch) + return emit_invalid_operation (cfg, "control byte in Sse41.Blend must be constant"); + case SN_BlendVariable: + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_BLENDV, -1, arg0_type, fsig, args); + case SN_Extract: { + int op = 0; + switch (arg0_type) { + case MONO_TYPE_U1: + case MONO_TYPE_U4: + case MONO_TYPE_I4: op = OP_XEXTRACT_I32; break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: op = OP_XEXTRACT_I64; break; + case MONO_TYPE_R4: op = OP_XEXTRACT_R4; break; + default: g_assert_not_reached(); break; + } + return emit_simd_ins_for_sig (cfg, klass, op, arg0_type, 0, fsig, args); + } + case SN_Insert: + if (args [2]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_INSERT, -1, arg0_type, fsig, args); + // FIXME: handle non-constant index (generate a switch) + return emit_invalid_operation (cfg, "index in Sse41.Insert must be constant"); + case SN_CeilingScalar: + case SN_FloorScalar: + case SN_RoundCurrentDirectionScalar: + case SN_RoundToNearestIntegerScalar: + case SN_RoundToNegativeInfinityScalar: + case SN_RoundToPositiveInfinityScalar: + case SN_RoundToZeroScalar: + if (fsig->param_count == 2) { + return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_ROUNDS, info->instc0, arg0_type, fsig, args); + } else { + MonoInst* ins = emit_simd_ins (cfg, klass, OP_SSE41_ROUNDS, args [0]->dreg, args [0]->dreg); + ins->inst_c0 = info->instc0; + ins->inst_c1 = arg0_type; + return ins; + } break; + default: + g_assert_not_reached (); + break; + } + } - MONO_INST_NEW (cfg, zero, OP_XZERO); - zero->dreg = alloc_xreg (cfg); - zero->klass = cmethod->klass; - MONO_ADD_INS (cfg->cbb, zero); + if (feature == MONO_CPU_X86_SSE42) { + switch (id) { + case SN_Crc32: { + MonoTypeEnum arg1_type = get_underlying_type (fsig->params [1]); + return emit_simd_ins_for_sig (cfg, klass, + arg1_type == MONO_TYPE_U8 ? OP_SSE42_CRC64 : OP_SSE42_CRC32, + arg1_type, arg0_type, fsig, args); + } + default: + g_assert_not_reached (); + break; + } + } - sub = simd_intrinsic_emit_binary_op (cfg, OP_SUBPS, 0, cmethod->klass, sig->params [0], sig->params [0], zero, args [0]); - return simd_intrinsic_emit_binary_op (cfg, OP_MAXPS, 0, cmethod->klass, sig->params [0], sig->params [0], args [0], sub); + if (feature == MONO_CPU_X86_PCLMUL) { + switch (id) { + case SN_CarrylessMultiply: { + if (args [2]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_PCLMULQDQ_IMM, args [2]->inst_c0, arg0_type, fsig, args); + // FIXME: handle non-constant control byte (generate a switch) + return emit_invalid_operation (cfg, "index in Pclmulqdq.CarrylessMultiply must be constant"); + } + default: + g_assert_not_reached (); + break; + } } - case SN_Max: - case SN_Min: - case SN_op_Addition: - case SN_op_Division: - case SN_op_Multiply: - case SN_op_Subtraction: - if (!(fsig->param_count == 2 && fsig->ret == type && (fsig->params [0] == type || fsig->params [0]->type == MONO_TYPE_R4) && (fsig->params [1] == type || fsig->params [1]->type == MONO_TYPE_R4))) + + if (feature == MONO_CPU_X86_AES) { + switch (id) { + case SN_KeygenAssist: { + if (args [1]->opcode == OP_ICONST) + return emit_simd_ins_for_sig (cfg, klass, OP_AES_KEYGEN_IMM, args [1]->inst_c0, arg0_type, fsig, args); + // FIXME: handle non-constant control byte (generate a switch) + return emit_invalid_operation (cfg, "control byte in Aes.KeygenAssist must be constant"); + } + default: + g_assert_not_reached (); break; - return simd_intrinsic_emit_binary (intrins, cfg, cmethod, args); - default: - break; + } } - assert_handled (cfg, cmethod); + if (feature == MONO_CPU_X86_POPCNT) { + switch (id) { + case SN_PopCount: + if (!supported) + return NULL; + MONO_INST_NEW (cfg, ins, is_64bit ? OP_POPCNT64 : OP_POPCNT32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + return NULL; + } + } + if (feature == MONO_CPU_X86_LZCNT) { + switch (id) { + case SN_LeadingZeroCount: + if (!supported) + return NULL; + MONO_INST_NEW (cfg, ins, is_64bit ? OP_LZCNT64 : OP_LZCNT32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + return NULL; + } + } + if (feature == MONO_CPU_X86_BMI1) { + switch (id) { + case SN_AndNot: { + // (a ^ -1) & b + // LLVM replaces it with `andn` + int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + EMIT_NEW_BIALU_IMM (cfg, ins, is_64bit ? OP_LXOR_IMM : OP_IXOR_IMM, tmp_reg, args [0]->dreg, -1); + EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LAND : OP_IAND, result_reg, tmp_reg, args [1]->dreg); + return ins; + } + case SN_BitFieldExtract: { + if (fsig->param_count == 2) { + MONO_INST_NEW (cfg, ins, is_64bit ? OP_BEXTR64 : OP_BEXTR32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->sreg2 = args [1]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + } + } + case SN_GetMaskUpToLowestSetBit: { + // x ^ (x - 1) + // LLVM replaces it with `blsmsk` + int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + EMIT_NEW_BIALU_IMM (cfg, ins, is_64bit ? OP_LSUB_IMM : OP_ISUB_IMM, tmp_reg, args [0]->dreg, 1); + EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LXOR : OP_IXOR, result_reg, args [0]->dreg, tmp_reg); + return ins; + } + case SN_ResetLowestSetBit: { + // x & (x - 1) + // LLVM replaces it with `blsr` + int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + EMIT_NEW_BIALU_IMM (cfg, ins, is_64bit ? OP_LSUB_IMM : OP_ISUB_IMM, tmp_reg, args [0]->dreg, 1); + EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LAND : OP_IAND, result_reg, args [0]->dreg, tmp_reg); + return ins; + } + case SN_ExtractLowestSetBit: { + // x & (0 - x) + // LLVM replaces it with `blsi` + int tmp_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + int result_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + int zero_reg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + MONO_EMIT_NEW_ICONST (cfg, zero_reg, 0); + EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LSUB : OP_ISUB, tmp_reg, zero_reg, args [0]->dreg); + EMIT_NEW_BIALU (cfg, ins, is_64bit ? OP_LAND : OP_IAND, result_reg, args [0]->dreg, tmp_reg); + return ins; + } + case SN_TrailingZeroCount: + MONO_INST_NEW (cfg, ins, is_64bit ? OP_CTTZ64 : OP_CTTZ32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + g_assert_not_reached (); + } + } + if (feature == MONO_CPU_X86_BMI2) { + switch (id) { + case SN_MultiplyNoFlags: + if (fsig->param_count == 2) { + MONO_INST_NEW (cfg, ins, is_64bit ? OP_MULX_H64 : OP_MULX_H32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->sreg2 = args [1]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + } else if (fsig->param_count == 3) { + MONO_INST_NEW (cfg, ins, is_64bit ? OP_MULX_HL64 : OP_MULX_HL32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->sreg2 = args [1]->dreg; + ins->sreg3 = args [2]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + } else { + g_assert_not_reached (); + } + return ins; + case SN_ZeroHighBits: + MONO_INST_NEW (cfg, ins, is_64bit ? OP_BZHI64 : OP_BZHI32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->sreg2 = args [1]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + case SN_ParallelBitExtract: + MONO_INST_NEW (cfg, ins, is_64bit ? OP_PEXT64 : OP_PEXT32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->sreg2 = args [1]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + case SN_ParallelBitDeposit: + MONO_INST_NEW (cfg, ins, is_64bit ? OP_PDEP64 : OP_PDEP32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->sreg2 = args [1]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + g_assert_not_reached (); + } + } - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD method %s not handled.\n", name); - g_free (name); + if (intrinsics == x86base_methods) { + switch (id) { + case SN_BitScanForward: + MONO_INST_NEW (cfg, ins, is_64bit ? OP_X86_BSF64 : OP_X86_BSF32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + case SN_BitScanReverse: + MONO_INST_NEW (cfg, ins, is_64bit ? OP_X86_BSR64 : OP_X86_BSR32); + ins->dreg = is_64bit ? alloc_lreg (cfg) : alloc_ireg (cfg); + ins->sreg1 = args [0]->dreg; + ins->type = is_64bit ? STACK_I8 : STACK_I4; + MONO_ADD_INS (cfg->cbb, ins); + return ins; + default: + g_assert_not_reached (); + } } - return NULL; -} - -static MonoInst* -emit_vector_is_hardware_accelerated_intrinsic (MonoCompile *cfg) -{ - MonoInst *ins; - if (get_simd_supported_versions (cfg)) - EMIT_NEW_ICONST (cfg, ins, 1); - else - EMIT_NEW_ICONST (cfg, ins, 0); - ins->type = STACK_I4; - return ins; + return NULL; } -/* These should be ordered by name */ -static const SimdIntrinsic vector_t_intrinsics[] = { - { SN_ctor }, - { SN_Abs }, - { SN_CopyTo }, - { SN_Equals }, - { SN_GreaterThan }, - { SN_GreaterThanOrEqual }, - { SN_LessThan }, - { SN_LessThanOrEqual }, - { SN_Max }, - { SN_Min }, - { SN_get_AllOnes, OP_XONES }, - { SN_get_Count }, - { SN_get_Item }, - { SN_get_Zero, OP_XZERO }, - { SN_op_Addition }, - { SN_op_BitwiseAnd }, - { SN_op_BitwiseOr }, - { SN_op_Division }, - { SN_op_ExclusiveOr }, - { SN_op_Explicit }, - { SN_op_Multiply }, - { SN_op_Subtraction } +static guint16 vector_128_t_methods [] = { + SN_get_Count, + SN_get_Zero, }; static MonoInst* -emit_vector_t_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +emit_vector128_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - const SimdIntrinsic *intrins; - MonoType *type, *etype; MonoInst *ins; - int size, len, index; + MonoType *type, *etype; + MonoClass *klass; + int size, len, id; - intrins = (const SimdIntrinsic*)mono_binary_search (cmethod->name, vector_t_intrinsics, sizeof (vector_t_intrinsics) / sizeof (SimdIntrinsic), sizeof (SimdIntrinsic), &simd_intrinsic_compare_by_name); - if (!intrins) { - assert_handled (cfg, cmethod); + id = lookup_intrins (vector_128_t_methods, sizeof (vector_128_t_methods), cmethod); + if (id == -1) return NULL; - } - type = m_class_get_byval_arg (cmethod->klass); - etype = mono_class_get_context (cmethod->klass)->class_inst->type_argv [0]; + klass = cmethod->klass; + type = m_class_get_byval_arg (klass); + etype = mono_class_get_context (klass)->class_inst->type_argv [0]; size = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); g_assert (size); len = 16 / size; - if (!MONO_TYPE_IS_PRIMITIVE (etype)) + if (!MONO_TYPE_IS_PRIMITIVE (etype) || etype->type == MONO_TYPE_CHAR || etype->type == MONO_TYPE_BOOLEAN) return NULL; if (cfg->verbose_level > 1) { @@ -2346,299 +2086,244 @@ emit_vector_t_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna g_free (name); } - switch (intrins->name) { + switch (id) { case SN_get_Count: if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4)) break; EMIT_NEW_ICONST (cfg, ins, len); return ins; - case SN_get_AllOnes: - case SN_get_Zero: - if (!(fsig->param_count == 0 && mono_metadata_type_equal (fsig->ret, type))) - break; - return simd_intrinsic_emit_const (intrins, cfg, cmethod, args); - case SN_get_Item: - g_assert (fsig->param_count == 1); - if (args [1]->opcode != OP_ICONST) - return NULL; - index = args [1]->inst_c0; - if (index < 0 || index >= len) - return NULL; - return simd_intrinsic_emit_getter_op (cfg, index, cmethod->klass, etype, args [0]); - case SN_ctor: - if (fsig->param_count == 1 && mono_metadata_type_equal (fsig->params [0], etype)) - return simd_intrinsic_emit_ctor (NULL, cfg, cmethod, args); - if ((fsig->param_count == 1 || fsig->param_count == 2) && (fsig->params [0]->type == MONO_TYPE_SZARRAY)) { - MonoInst *array_ins = args [1]; - MonoInst *index_ins; - MonoInst *ldelema_ins; - MonoInst *var; - int end_index_reg; - - if (args [0]->opcode != OP_LDADDR) - return NULL; - - /* .ctor (T[]) or .ctor (T[], index) */ + case SN_get_Zero: { + return emit_simd_ins (cfg, klass, OP_XZERO, -1, -1); + } + default: + break; + } - if (fsig->param_count == 2) { - index_ins = args [2]; - } else { - EMIT_NEW_ICONST (cfg, index_ins, 0); - } + return NULL; +} - /* Emit index check for the end (index + len - 1 < array length) */ - end_index_reg = alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, OP_IADD_IMM, end_index_reg, index_ins->dreg, len - 1); - MONO_EMIT_BOUNDS_CHECK (cfg, array_ins->dreg, MonoArray, max_length, end_index_reg); +static guint16 vector_256_t_methods [] = { + SN_get_Count, +}; - /* Load the array slice into the simd reg */ - ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE); - g_assert (args [0]->opcode == OP_LDADDR); - var = (MonoInst*)args [0]->inst_p0; - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADX_MEMBASE, var->dreg, ldelema_ins->dreg, 0); - ins->klass = cmethod->klass; - return args [0]; - } - break; - case SN_op_Explicit: - return simd_intrinsic_emit_cast (intrins, cfg, cmethod, args); - case SN_Equals: - if (fsig->param_count == 1 && fsig->ret->type == MONO_TYPE_BOOLEAN && mono_metadata_type_equal (fsig->params [0], type)) - return simd_intrinsic_emit_equality_op (cfg, cmethod, args, type_to_comp_op (etype), SIMD_COMP_EQ); - if (fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, type) && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)) - return simd_intrinsic_emit_binary_op (cfg, type_to_comp_op (etype), 0, cmethod->klass, fsig->params [0], fsig->params [1], args [0], args [1]); - break; +static MonoInst* +emit_vector256_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + MonoInst *ins; + MonoType *type, *etype; + MonoClass *klass; + int size, len, id; - case SN_GreaterThan: - case SN_GreaterThanOrEqual: - case SN_LessThan: - case SN_LessThanOrEqual: { - MonoInst *cmp1, *cmp2; - int eq_op, gt_op; + id = lookup_intrins (vector_256_t_methods, sizeof (vector_256_t_methods), cmethod); + if (id == -1) + return NULL; - switch (etype->type) { - case MONO_TYPE_I1: - case MONO_TYPE_I2: - case MONO_TYPE_I4: - case MONO_TYPE_I8: - break; - default: - return NULL; - } + klass = cmethod->klass; + type = m_class_get_byval_arg (klass); + etype = mono_class_get_context (klass)->class_inst->type_argv [0]; + size = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); + g_assert (size); + len = 32 / size; - eq_op = type_to_comp_op (etype); - gt_op = type_to_gt_op (etype); + if (!MONO_TYPE_IS_PRIMITIVE (etype) || etype->type == MONO_TYPE_CHAR || etype->type == MONO_TYPE_BOOLEAN) + return NULL; - switch (intrins->name) { - case SN_GreaterThan: - return simd_intrinsic_emit_binary_op (cfg, gt_op, 0, cmethod->klass, fsig->params [0], fsig->params [1], args [0], args [1]); - case SN_LessThan: - return simd_intrinsic_emit_binary_op (cfg, gt_op, 0, cmethod->klass, fsig->params [0], fsig->params [1], args [1], args [0]); - case SN_LessThanOrEqual: - cmp1 = simd_intrinsic_emit_binary_op (cfg, eq_op, 0, cmethod->klass, fsig->params [0], fsig->params [1], args [1], args [0]); - cmp2 = simd_intrinsic_emit_binary_op (cfg, gt_op, 0, cmethod->klass, fsig->params [0], fsig->params [1], args [1], args [0]); - return simd_intrinsic_emit_binary_op (cfg, OP_POR, 0, cmethod->klass, fsig->params [0], fsig->params [1], cmp1, cmp2); - case SN_GreaterThanOrEqual: - cmp1 = simd_intrinsic_emit_binary_op (cfg, eq_op, 0, cmethod->klass, fsig->params [0], fsig->params [1], args [0], args [1]); - cmp2 = simd_intrinsic_emit_binary_op (cfg, gt_op, 0, cmethod->klass, fsig->params [0], fsig->params [1], args [0], args [1]); - return simd_intrinsic_emit_binary_op (cfg, OP_POR, 0, cmethod->klass, fsig->params [0], fsig->params [1], cmp1, cmp2); - default: - g_assert_not_reached (); - break; - } + if (cfg->verbose_level > 1) { + char *name = mono_method_full_name (cmethod, TRUE); + printf (" SIMD intrinsic %s\n", name); + g_free (name); } - case SN_Abs: - /* Vector.Abs */ - switch (etype->type) { - case MONO_TYPE_U1: - case MONO_TYPE_U2: - case MONO_TYPE_U4: - case MONO_TYPE_U8: { - MonoInst *ins; - - /* No-op */ - MONO_INST_NEW (cfg, ins, OP_XMOVE); - ins->klass = cmethod->klass; - ins->type = STACK_VTYPE; - ins->sreg1 = args [0]->dreg; - ins->dreg = alloc_xreg (cfg); - MONO_ADD_INS (cfg->cbb, ins); - return ins; - } - default: - break; - } - break; - case SN_op_Addition: - case SN_op_Subtraction: - case SN_op_Multiply: - case SN_op_Division: - case SN_op_ExclusiveOr: - case SN_op_BitwiseAnd: - case SN_op_BitwiseOr: - case SN_Max: - case SN_Min: { - if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->ret, fsig->params [0]) && mono_metadata_type_equal (fsig->params [0], fsig->params [1]))) - break; - int op = 0; - switch (intrins->name) { - case SN_op_Addition: - op = type_to_padd_op (etype); - break; - case SN_op_Subtraction: - op = type_to_psub_op (etype); - break; - case SN_op_Multiply: - op = type_to_pmul_op (etype); - break; - case SN_op_Division: - op = type_to_pdiv_op (etype); - break; - case SN_op_ExclusiveOr: - op = type_to_pxor_op (etype); - break; - case SN_op_BitwiseAnd: - op = type_to_pand_op (etype); - break; - case SN_op_BitwiseOr: - op = type_to_por_op (etype); - break; - case SN_Min: - op = type_to_pmin_op (etype); - break; - case SN_Max: - op = type_to_pmax_op (etype); + + switch (id) { + case SN_get_Count: + if (!(fsig->param_count == 0 && fsig->ret->type == MONO_TYPE_I4)) break; - default: - g_assert_not_reached (); - } - if (op != -1) - return simd_intrinsic_emit_binary_op (cfg, op, 0, cmethod->klass, fsig->params [0], fsig->params [0], args [0], args [1]); + EMIT_NEW_ICONST (cfg, ins, len); + return ins; + default: break; } - case SN_CopyTo: { - MonoInst *array_ins = args [1]; - MonoInst *index_ins = args [2]; - MonoInst *ldelema_ins; - MonoInst *var; - int end_index_reg; - - if (args [0]->opcode != OP_LDADDR) - return NULL; - /* Emit index check for the end (index + len - 1 < array length) */ - end_index_reg = alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, OP_IADD_IMM, end_index_reg, index_ins->dreg, len - 1); - - int length_reg = alloc_ireg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT (cfg, OP_LOADI4_MEMBASE, length_reg, array_ins->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length)); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, length_reg, end_index_reg); - MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "ArgumentException"); - - /* Load the simd reg into the array slice */ - ldelema_ins = mini_emit_ldelema_1_ins (cfg, mono_class_from_mono_type_internal (etype), array_ins, index_ins, TRUE, FALSE); - g_assert (args [0]->opcode == OP_LDADDR); - var = (MonoInst*)args [0]->inst_p0; - EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREX_MEMBASE, ldelema_ins->dreg, 0, var->dreg); - ins->klass = cmethod->klass; - return args [0]; - break; - } - default: - break; + return NULL; +} + +static +MonoInst* +emit_amd64_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + if (!strcmp (class_ns, "System.Runtime.Intrinsics.X86")) { + return emit_x86_intrinsics (cfg, cmethod, fsig, args); } - assert_handled (cfg, cmethod); + if (!strcmp (class_ns, "System.Runtime.Intrinsics")) { + if (!strcmp (class_name, "Vector128`1")) + return emit_vector128_t (cfg, cmethod, fsig, args); + if (!strcmp (class_name, "Vector256`1")) + return emit_vector256_t (cfg, cmethod, fsig, args); + } - if (cfg->verbose_level > 1) { - char *name = mono_method_full_name (cmethod, TRUE); - printf (" SIMD method %s not handled.\n", name); - g_free (name); + if (!strcmp (class_ns, "System.Numerics")) { + if (!strcmp (class_name, "Vector")) + return emit_sys_numerics_vector (cfg, cmethod, fsig, args); + if (!strcmp (class_name, "Vector`1")) + return emit_sys_numerics_vector_t (cfg, cmethod, fsig, args); } return NULL; } +#endif // !TARGET_ARM64 -/* - * emit_sys_numerics_intrinsics: - * - * Emit intrinsics for the System.Numerics assembly. - */ -static MonoInst* -emit_sys_numerics_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +#ifdef TARGET_ARM64 +static +MonoInst* +emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - const char *nspace = m_class_get_name_space (cmethod->klass); - const char *class_name = m_class_get_name (cmethod->klass); - - if (!strcmp ("Vector2", class_name) || !strcmp ("Vector4", class_name) || !strcmp ("Vector3", class_name)) - return emit_vector_intrinsics (cfg, cmethod, fsig, args); - - if (!strcmp ("System.Numerics", nspace) && !strcmp ("Vector", class_name)) { - if (!strcmp (cmethod->name, "get_IsHardwareAccelerated")) - return emit_vector_is_hardware_accelerated_intrinsic (cfg); + // FIXME: implement Vector64, Vector128 and Vector for Arm64 + if (!strcmp (class_ns, "System.Runtime.Intrinsics.Arm")) { + return emit_arm64_intrinsics (cfg, cmethod, fsig, args); } return NULL; } +#elif TARGET_AMD64 +// TODO: test and enable for x86 too +static +MonoInst* +emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + MonoInst *simd_inst = emit_amd64_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args); + if (simd_inst != NULL) { + cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS; + cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE; + } + return simd_inst; +} +#else +static +MonoInst* +emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +{ + return NULL; +} +#endif -static MonoInst* -emit_sys_numerics_vectors_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +MonoInst* +mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { - const char *nspace = m_class_get_name_space (cmethod->klass); - const char *class_name = m_class_get_name (cmethod->klass); + const char *class_name; + const char *class_ns; + MonoImage *image = m_class_get_image (cmethod->klass); + + if (image != mono_get_corlib ()) + return NULL; - if (!strcmp (class_name, "Vector`1")) - return emit_vector_t_intrinsics (cfg, cmethod, fsig, args); + class_ns = m_class_get_name_space (cmethod->klass); + class_name = m_class_get_name (cmethod->klass); + + // If cmethod->klass is nested, the namespace is on the enclosing class. + if (m_class_get_nested_in (cmethod->klass)) + class_ns = m_class_get_name_space (m_class_get_nested_in (cmethod->klass)); - if (!strcmp ("System.Numerics", nspace) && !strcmp ("Vector", class_name)) { - if (!strcmp (cmethod->name, "get_IsHardwareAccelerated")) - return emit_vector_is_hardware_accelerated_intrinsic (cfg); +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) + if (!strcmp (class_ns, "System.Runtime.Intrinsics")) { + if (!strcmp (class_name, "Vector128")) + return emit_vector128 (cfg, cmethod, fsig, args); } +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) - return NULL; + return emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args); } -MonoInst* -mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field, MonoInst *addr) +/* +* Windows x64 value type ABI uses reg/stack references (ArgValuetypeAddrInIReg/ArgValuetypeAddrOnStack) +* for function arguments. When using SIMD intrinsics arguments optimized into OP_ARG needs to be decomposed +* into correspondig SIMD LOADX/STOREX instructions. +*/ +#if defined(TARGET_WIN32) && defined(TARGET_AMD64) +static gboolean +decompose_vtype_opt_uses_simd_intrinsics (MonoCompile *cfg, MonoInst *ins) { - MonoInst * simd_inst = NULL; - - if (is_sys_numerics_assembly (m_class_get_image (field->parent)->assembly)) { - int index = -1; - - const char *parent_name = m_class_get_name (field->parent); - if (!strcmp (parent_name, "Vector2") || - !strcmp (parent_name, "Vector3") || - !strcmp (parent_name, "Vector4")) { - if (!strcmp (field->name, "X")) - index = 0; - else if (!strcmp (field->name, "Y")) - index = 1; - else if (!strcmp (field->name, "Z")) - index = 2; - else if (!strcmp (field->name, "W")) - index = 3; - } - - if (index != -1) { - if (cfg->verbose_level > 1) - printf (" SIMD intrinsic field access: %s\n", field->name); + if (cfg->uses_simd_intrinsics & MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE) + return TRUE; - simd_inst = simd_intrinsic_emit_getter_op (cfg, index, field->parent, mono_field_get_type_internal (field), addr); - goto on_exit; - } + switch (ins->opcode) { + case OP_XMOVE: + case OP_XZERO: + case OP_LOADX_MEMBASE: + case OP_LOADX_ALIGNED_MEMBASE: + case OP_STOREX_MEMBASE: + case OP_STOREX_ALIGNED_MEMBASE_REG: + return TRUE; + default: + return FALSE; } +} -on_exit: +static void +decompose_vtype_opt_load_arg (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, gint32 *sreg_int32) +{ + guint32 *sreg = (guint32*)sreg_int32; + MonoInst *src_var = get_vreg_to_inst (cfg, *sreg); + if (src_var && src_var->opcode == OP_ARG && src_var->klass && MONO_CLASS_IS_SIMD (cfg, src_var->klass)) { + MonoInst *varload_ins, *load_ins; + NEW_VARLOADA (cfg, varload_ins, src_var, src_var->inst_vtype); + mono_bblock_insert_before_ins (bb, ins, varload_ins); + MONO_INST_NEW (cfg, load_ins, OP_LOADX_MEMBASE); + load_ins->klass = src_var->klass; + load_ins->type = STACK_VTYPE; + load_ins->sreg1 = varload_ins->dreg; + load_ins->dreg = alloc_xreg (cfg); + mono_bblock_insert_after_ins (bb, varload_ins, load_ins); + *sreg = load_ins->dreg; + } +} - if (simd_inst != NULL) { - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS; - cfg->uses_simd_intrinsics |= MONO_CFG_USES_SIMD_INTRINSICS_DECOMPOSE_VTYPE; +void +mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) +{ + if (cfg->opt & MONO_OPT_SIMD && decompose_vtype_opt_uses_simd_intrinsics (cfg, ins)) { + decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg1)); + decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg2)); + decompose_vtype_opt_load_arg (cfg, bb, ins, &(ins->sreg3)); + MonoInst *dest_var = get_vreg_to_inst (cfg, ins->dreg); + if (dest_var && dest_var->opcode == OP_ARG && dest_var->klass && MONO_CLASS_IS_SIMD (cfg, dest_var->klass)) { + MonoInst *varload_ins, *store_ins; + ins->dreg = alloc_xreg (cfg); + NEW_VARLOADA (cfg, varload_ins, dest_var, dest_var->inst_vtype); + mono_bblock_insert_after_ins (bb, ins, varload_ins); + MONO_INST_NEW (cfg, store_ins, OP_STOREX_MEMBASE); + store_ins->klass = dest_var->klass; + store_ins->type = STACK_VTYPE; + store_ins->sreg1 = ins->dreg; + store_ins->dreg = varload_ins->dreg; + mono_bblock_insert_after_ins (bb, varload_ins, store_ins); + } } +} +#else +void +mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) +{ +} +#endif /*defined(TARGET_WIN32) && defined(TARGET_AMD64)*/ - return simd_inst; +void +mono_simd_simplify_indirection (MonoCompile *cfg) +{ } #endif /* DISABLE_JIT */ -MONO_EMPTY_SOURCE_FILE (simd_intrinsics); #endif /* MONO_ARCH_SIMD_INTRINSICS */ + +#if defined(TARGET_AMD64) +void +ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id) +{ +#ifndef MONO_CROSS_COMPILE + mono_hwcap_x86_call_cpuidex (function_id, subfunction_id, + &abcd [0], &abcd [1], &abcd [2], &abcd [3]); +#endif +} +#endif + +MONO_EMPTY_SOURCE_FILE (simd_intrinsics_netcore); diff --git a/src/mono/mono/mini/tasklets.c b/src/mono/mono/mini/tasklets.c deleted file mode 100644 index 402a3a9..0000000 --- a/src/mono/mono/mini/tasklets.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * \file - */ - -#include "config.h" -#include "tasklets.h" -#include "mono/metadata/exception.h" -#include "mono/metadata/gc-internals.h" -#include "mono/metadata/icall-internals.h" -#include "mini.h" -#include "mini-runtime.h" -#include "mono/metadata/loader-internals.h" -#include "mono/utils/mono-tls-inline.h" - -#if !defined(ENABLE_NETCORE) -#if defined(MONO_SUPPORT_TASKLETS) - -#include "mono/metadata/loader-internals.h" - -static mono_mutex_t tasklets_mutex; -#define tasklets_lock() mono_os_mutex_lock(&tasklets_mutex) -#define tasklets_unlock() mono_os_mutex_unlock(&tasklets_mutex) - -/* LOCKING: tasklets_mutex is assumed to e taken */ -static void -internal_init (void) -{ - if (!mono_gc_is_moving ()) - /* Boehm requires the keepalive stacks to be kept in a hash since mono_gc_alloc_fixed () returns GC memory */ - g_assert_not_reached (); -} - -static void* -continuation_alloc (void) -{ - MonoContinuation *cont = g_new0 (MonoContinuation, 1); - return cont; -} - -static void -continuation_free (MonoContinuation *cont) -{ - if (cont->saved_stack) - mono_gc_free_fixed (cont->saved_stack); - g_free (cont); -} - -static MonoException* -continuation_mark_frame (MonoContinuation *cont) -{ - MonoJitTlsData *jit_tls; - MonoLMF *lmf; - MonoContext ctx, new_ctx; - MonoJitInfo *ji, rji; - int endloop = FALSE; - - if (cont->domain) - return mono_get_exception_argument ("cont", "Already marked"); - - jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls (); - lmf = mono_get_lmf(); - cont->domain = mono_domain_get (); - cont->thread_id = mono_native_thread_id_get (); - - /* get to the frame that called Mark () */ - memset (&rji, 0, sizeof (rji)); - memset (&ctx, 0, sizeof (ctx)); - do { - ji = mono_find_jit_info (cont->domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL); - if (!ji || ji == (gpointer)-1) { - return mono_get_exception_not_supported ("Invalid stack frame"); - } - ctx = new_ctx; - if (endloop) - break; - if (!ji->is_trampoline && strcmp (jinfo_get_method (ji)->name, "Mark") == 0) - endloop = TRUE; - } while (1); - - cont->top_sp = MONO_CONTEXT_GET_SP (&ctx); - /*g_print ("method: %s, sp: %p\n", jinfo_get_method (ji)->name, cont->top_sp);*/ - - return NULL; -} - -static int -continuation_store (MonoContinuation *cont, int state, MonoException **e) -{ - MonoLMF *lmf = mono_get_lmf (); - gsize num_bytes; - - if (!cont->domain) { - *e = mono_get_exception_argument ("cont", "Continuation not initialized"); - return 0; - } - if (cont->domain != mono_domain_get () || !mono_native_thread_id_equals (cont->thread_id, mono_native_thread_id_get ())) { - *e = mono_get_exception_argument ("cont", "Continuation from another thread or domain"); - return 0; - } - - cont->lmf = lmf; - cont->return_ip = __builtin_extract_return_addr (__builtin_return_address (0)); - cont->return_sp = __builtin_frame_address (0); - - num_bytes = (char*)cont->top_sp - (char*)cont->return_sp; - - /*g_print ("store: %d bytes, sp: %p, ip: %p, lmf: %p\n", num_bytes, cont->return_sp, cont->return_ip, lmf);*/ - - if (cont->saved_stack && num_bytes <= cont->stack_alloc_size) { - /* clear to avoid GC retention */ - if (num_bytes < cont->stack_used_size) { - memset ((char*)cont->saved_stack + num_bytes, 0, cont->stack_used_size - num_bytes); - } - cont->stack_used_size = num_bytes; - } else { - tasklets_lock (); - internal_init (); - if (cont->saved_stack) - mono_gc_free_fixed (cont->saved_stack); - cont->stack_used_size = num_bytes; - cont->stack_alloc_size = num_bytes * 1.1; - cont->saved_stack = mono_gc_alloc_fixed_no_descriptor (cont->stack_alloc_size, MONO_ROOT_SOURCE_THREADING, NULL, "Tasklet Saved Stack"); - tasklets_unlock (); - } - memcpy (cont->saved_stack, cont->return_sp, num_bytes); - - return state; -} - -static MonoException* -continuation_restore (MonoContinuation *cont, int state) -{ - MonoLMF **lmf_addr = mono_get_lmf_addr (); - MonoContinuationRestore restore_state = mono_tasklets_arch_restore (); - - if (!cont->domain || !cont->return_sp) - return mono_get_exception_argument ("cont", "Continuation not initialized"); - if (cont->domain != mono_domain_get () || !mono_native_thread_id_equals (cont->thread_id, mono_native_thread_id_get ())) - return mono_get_exception_argument ("cont", "Continuation from another thread or domain"); - - /*g_print ("restore: %p, state: %d\n", cont, state);*/ - *lmf_addr = cont->lmf; - restore_state (cont, state, lmf_addr); - g_assert_not_reached (); -} - -void -mono_tasklets_init (void) -{ - mono_os_mutex_init_recursive (&tasklets_mutex); - - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::alloc", continuation_alloc); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::free", continuation_free); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::mark", continuation_mark_frame); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::store", continuation_store); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::restore", continuation_restore); -} - -void -mono_tasklets_cleanup (void) -{ -} -#else - -static -void continuations_not_supported (void) -{ - ERROR_DECL (error); - mono_error_set_not_implemented (error, "Tasklets are not implemented on this platform."); - mono_error_set_pending_exception (error); -} - -static void* -continuation_alloc (void) -{ - continuations_not_supported (); - return NULL; -} - -static void -continuation_free (MonoContinuation *cont) -{ - continuations_not_supported (); -} - -static MonoException* -continuation_mark_frame (MonoContinuation *cont) -{ - continuations_not_supported (); - return NULL; -} - -static int -continuation_store (MonoContinuation *cont, int state, MonoException **e) -{ - continuations_not_supported (); - return 0; -} - -static MonoException* -continuation_restore (MonoContinuation *cont, int state) -{ - continuations_not_supported (); - return NULL; -} - -void -mono_tasklets_init(void) -{ - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::alloc", continuation_alloc); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::free", continuation_free); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::mark", continuation_mark_frame); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::store", continuation_store); - mono_add_internal_call_internal ("Mono.Tasklets.Continuation::restore", continuation_restore); - -} -#endif /* MONO_SUPPORT_TASKLETS */ - -#endif /* ENABLE_NETCORE */ - diff --git a/src/mono/mono/mini/tasklets.h b/src/mono/mono/mini/tasklets.h deleted file mode 100644 index dd8750f..0000000 --- a/src/mono/mono/mini/tasklets.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * \file - */ - -#ifndef __MONO_TASKLETS_H__ -#define __MONO_TASKLETS_H__ - -#include "mini.h" - -#if !defined(ENABLE_NETCORE) -typedef struct { - MonoLMF *lmf; - gpointer top_sp; - MonoNativeThreadId thread_id; - MonoDomain *domain; - - /* the instruction pointer and stack to return to on Restore */ - gpointer return_ip; - gpointer return_sp; - - /* the saved stack information */ - int stack_alloc_size; - int stack_used_size; - /* pointer to GC memory */ - gpointer saved_stack; -} MonoContinuation; - -typedef void (*MonoContinuationRestore) (MonoContinuation *cont, int state, MonoLMF **lmf_addr); - -void mono_tasklets_init (void); -void mono_tasklets_cleanup (void); - -MonoContinuationRestore mono_tasklets_arch_restore (void); - -#endif /* ENABLE_NETCORE */ - -#endif /* __MONO_TASKLETS_H__ */ - diff --git a/src/mono/mono/sgen/sgen-debug.c b/src/mono/mono/sgen/sgen-debug.c index b62c4ce..e6a2eb9 100644 --- a/src/mono/mono/sgen/sgen-debug.c +++ b/src/mono/mono/sgen/sgen-debug.c @@ -947,21 +947,6 @@ sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type) static gboolean is_xdomain_ref_allowed (GCObject **ptr, GCObject *obj, MonoDomain *domain) { -#ifndef ENABLE_NETCORE - MonoObject *o = (MonoObject*)(obj); - size_t offset = (char*)(ptr) - (char*)o; - - if (o->vtable->klass == mono_defaults.thread_class && offset == G_STRUCT_OFFSET (MonoThread, internal_thread)) - return TRUE; - if (o->vtable->klass == mono_defaults.internal_thread_class && offset == G_STRUCT_OFFSET (MonoInternalThread, current_appcontext)) - return TRUE; - -#ifndef DISABLE_REMOTING - if (m_class_get_supertypes (mono_defaults.real_proxy_class) && mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) && - offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server)) - return TRUE; -#endif -#endif return FALSE; } diff --git a/src/mono/mono/tools/offsets-tool/offsets-tool.py b/src/mono/mono/tools/offsets-tool/offsets-tool.py index cef736a..c9bfec1 100644 --- a/src/mono/mono/tools/offsets-tool/offsets-tool.py +++ b/src/mono/mono/tools/offsets-tool/offsets-tool.py @@ -194,9 +194,6 @@ class OffsetsTool: print ("ABI '" + args.abi + "' is not supported.", file=sys.stderr) sys.exit (1) - if args.netcore: - self.target_args += ["-DENABLE_NETCORE"] - self.args = args # diff --git a/src/mono/mono/utils/CMakeLists.txt b/src/mono/mono/utils/CMakeLists.txt index 09d14dc..466a5e5 100644 --- a/src/mono/mono/utils/CMakeLists.txt +++ b/src/mono/mono/utils/CMakeLists.txt @@ -35,7 +35,6 @@ set(utils_common_sources mono-codeman.c mono-counters.c mono-compiler.h - mono-complex.h mono-dl.c mono-dl-windows.c mono-dl-darwin.c diff --git a/src/mono/mono/utils/mono-complex.h b/src/mono/mono/utils/mono-complex.h deleted file mode 100644 index 6b3fe75..0000000 --- a/src/mono/mono/utils/mono-complex.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * \file -* C99 Complex math cross-platform support code -* -* Author: -* Joao Matos (joao.matos@xamarin.com) -* -* Copyright 2015 Xamarin, Inc (http://www.xamarin.com) -* Licensed under the MIT license. See LICENSE file in the project root for full license information. -*/ - -#include -#include -#define _USE_MATH_DEFINES // needed by MSVC to define math constants -#include - -#ifndef ENABLE_NETCORE - -typedef struct double_complex { - double real; - double imag; -} double_complex; - -#define mono_creal(c) ((c).real) -#define mono_cimag(c) ((c).imag) - -static inline -double_complex mono_double_complex_make(gdouble re, gdouble im) -{ - double_complex const a = { re, im }; - return a; -} - -static inline -double_complex mono_double_complex_scalar_div(double_complex c, gdouble s) -{ - return mono_double_complex_make (mono_creal (c) / s, mono_cimag (c) / s); -} - -static inline -double_complex mono_double_complex_scalar_mul(double_complex c, gdouble s) -{ - return mono_double_complex_make (mono_creal (c) * s, mono_cimag (c) * s); -} - -static inline -double_complex mono_double_complex_div(double_complex left, double_complex right) -{ - double denom = mono_creal (right) * mono_creal (right) + mono_cimag (right) * mono_cimag (right); - - return mono_double_complex_make( - (mono_creal (left) * mono_creal (right) + mono_cimag (left) * mono_cimag (right)) / denom, - (-mono_creal (left) * mono_cimag (right) + mono_cimag (left) * mono_creal (right)) / denom); -} - -static inline -double_complex mono_double_complex_sub(double_complex left, double_complex right) -{ - return mono_double_complex_make (mono_creal (left) - mono_creal (right), mono_cimag (left) - - mono_cimag (right)); -} - -#include "../../support/libm/complex.c" - -#endif diff --git a/src/mono/mono/utils/mono-dl-posix.c b/src/mono/mono/utils/mono-dl-posix.c index 7b19cd5..b716b83 100644 --- a/src/mono/mono/utils/mono-dl-posix.c +++ b/src/mono/mono/utils/mono-dl-posix.c @@ -134,15 +134,11 @@ mono_dl_convert_flags (int mono_flags, int native_flags) { int lflags = native_flags; -#ifdef ENABLE_NETCORE // Specifying both will default to LOCAL if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL)) lflags |= RTLD_GLOBAL; else lflags |= RTLD_LOCAL; -#else - lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL; -#endif if (mono_flags & MONO_DL_LAZY) lflags |= RTLD_LAZY; diff --git a/src/mono/mono/utils/mono-dl-wasm.c b/src/mono/mono/utils/mono-dl-wasm.c index 333d54db..df7d607 100644 --- a/src/mono/mono/utils/mono-dl-wasm.c +++ b/src/mono/mono/utils/mono-dl-wasm.c @@ -62,15 +62,11 @@ mono_dl_convert_flags (int mono_flags, int native_flags) { int lflags = native_flags; -#ifdef ENABLE_NETCORE // Specifying both will default to LOCAL if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL)) lflags |= RTLD_GLOBAL; else lflags |= RTLD_LOCAL; -#else - lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL; -#endif if (mono_flags & MONO_DL_LAZY) lflags |= RTLD_LAZY; diff --git a/src/mono/mono/utils/mono-dl.c b/src/mono/mono/utils/mono-dl.c index ab47127..19c28cf 100644 --- a/src/mono/mono/utils/mono-dl.c +++ b/src/mono/mono/utils/mono-dl.c @@ -21,7 +21,7 @@ #include #include #include -#if defined(ENABLE_NETCORE) && defined(TARGET_ANDROID) +#ifdef TARGET_ANDROID #include #endif @@ -151,7 +151,6 @@ get_dl_name_from_libtool (const char *libtool_file) return line; } -#ifdef ENABLE_NETCORE static const char * fix_libc_name (const char *name) { @@ -169,7 +168,6 @@ fix_libc_name (const char *name) } return name; } -#endif /** * mono_dl_open_self: @@ -182,7 +180,7 @@ fix_libc_name (const char *name) MonoDl* mono_dl_open_self (char **error_msg) { -#if defined(ENABLE_NETCORE) && defined(TARGET_ANDROID) +#ifdef TARGET_ANDROID MonoDl *module; if (error_msg) *error_msg = NULL; @@ -244,9 +242,7 @@ mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **er } module->main_module = name == NULL? TRUE: FALSE; -#ifdef ENABLE_NETCORE name = fix_libc_name (name); -#endif // No GC safe transition because this is called early in main.c lib = mono_dl_open_file (name, lflags); @@ -438,17 +434,11 @@ mono_dl_build_path (const char *directory, const char *name, void **iter) need_suffix = FALSE; suffix = ""; } else if (idx == 1) { -#ifdef ENABLE_NETCORE /* netcore system libs have a suffix but no prefix */ need_prefix = FALSE; need_suffix = TRUE; suffix = mono_dl_get_so_suffixes () [0]; suffixlen = strlen (suffix); -#else - suffix = mono_dl_get_so_suffixes () [idx - 1]; - if (suffix [0] == '\0') - return NULL; -#endif } else { /* Prefix.Name.suffix */ suffix = mono_dl_get_so_suffixes () [idx - 2]; diff --git a/src/mono/mono/utils/mono-merp.c b/src/mono/mono/utils/mono-merp.c index 7a21658..14efd13 100644 --- a/src/mono/mono/utils/mono-merp.c +++ b/src/mono/mono/utils/mono-merp.c @@ -25,7 +25,6 @@ #include #include -#include #include #if defined(HAVE_SYS_UTSNAME_H) @@ -37,6 +36,7 @@ #include #include +#include #include #include #include @@ -427,7 +427,7 @@ mono_init_merp (const intptr_t crashed_pid, const char *signal, MonoStackHash *h merp->moduleOffset = 0; - merp->uiLidArg = MONO_LOCALE_INVARIANT; + merp->uiLidArg = 0x007F; // MONO_LOCALE_INVARIANT #if defined (TARGET_OSX) merp->osVersion = macos_version_string (); #else diff --git a/src/mono/mono/utils/mono-threads-posix.c b/src/mono/mono/utils/mono-threads-posix.c index c3ddb64..b5e86aa 100644 --- a/src/mono/mono/utils/mono-threads-posix.c +++ b/src/mono/mono/utils/mono-threads-posix.c @@ -32,12 +32,6 @@ #include -#if !defined(ENABLE_NETCORE) && defined(HOST_ANDROID) && !defined(TARGET_ARM64) && !defined(TARGET_AMD64) -// tkill was deprecated and removed in the recent versions of Android NDK -#define USE_TKILL_ON_ANDROID 1 -extern int tkill (pid_t tid, int signal); -#endif - #if defined(_POSIX_VERSION) && !defined (HOST_WASM) #include diff --git a/src/mono/mono/utils/mono-threads-windows.c b/src/mono/mono/utils/mono-threads-windows.c index faeecbb..bd639ad 100644 --- a/src/mono/mono/utils/mono-threads-windows.c +++ b/src/mono/mono/utils/mono-threads-windows.c @@ -383,12 +383,8 @@ mono_threads_suspend_get_abort_signal (void) #if defined (HOST_WIN32) -#ifndef ENABLE_NETCORE -#define MONO_WIN32_DEFAULT_NATIVE_STACK_SIZE (1024 * 1024) -#else // Use default stack size on netcore. #define MONO_WIN32_DEFAULT_NATIVE_STACK_SIZE 0 -#endif gboolean mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid) diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 8b9ac50..79468ae 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -71,8 +71,8 @@ ifeq ($(ENABLE_METADATA_UPDATE),true) EMCC_FLAGS+=-DENABLE_METADATA_UPDATE=1 endif -EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1 -EMCC_RELEASE_FLAGS=-Oz --llvm-opts 2 -DENABLE_NETCORE=1 +EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DDEBUG=1 +EMCC_RELEASE_FLAGS=-Oz --llvm-opts 2 ifeq ($(NOSTRIP),) STRIP_CMD=&& $(EMSDK_PATH)/upstream/bin/wasm-opt --strip-dwarf $(NATIVE_BIN_DIR)/dotnet.wasm -o $(NATIVE_BIN_DIR)/dotnet.wasm diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index dc0ba41..9b6d683 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -274,9 +274,7 @@ mono_wasm_setenv (const char *name, const char *value) monoeg_g_setenv (strdup (name), strdup (value), 1); } -#ifdef ENABLE_NETCORE static void *sysglobal_native_handle; -#endif static void* wasm_dl_load (const char *name, int flags, char **err, void *user_data) @@ -285,10 +283,8 @@ wasm_dl_load (const char *name, int flags, char **err, void *user_data) if (handle) return handle; -#ifdef ENABLE_NETCORE if (!strcmp (name, "System.Globalization.Native")) return sysglobal_native_handle; -#endif #if WASM_SUPPORTS_DLOPEN return dlopen(name, flags); @@ -300,10 +296,8 @@ wasm_dl_load (const char *name, int flags, char **err, void *user_data) static void* wasm_dl_symbol (void *handle, const char *name, char **err, void *user_data) { -#ifdef ENABLE_NETCORE if (handle == sysglobal_native_handle) assert (0); -#endif #if WASM_SUPPORTS_DLOPEN if (!wasm_dl_is_pinvoke_tables (handle)) { -- 2.7.4