ruby-changes:72999
From: Takashi <ko1@a...>
Date: Sun, 21 Aug 2022 10:35:52 +0900 (JST)
Subject: [ruby-changes:72999] ddf96b7693 (master): Drop mswin support of MJIT (#6265)
https://git.ruby-lang.org/ruby.git/commit/?id=ddf96b7693 From ddf96b7693639e354e95b4d0c6021586968a5a5f Mon Sep 17 00:00:00 2001 From: Takashi Kokubun <takashikkbn@g...> Date: Sat, 20 Aug 2022 18:35:36 -0700 Subject: Drop mswin support of MJIT (#6265) The current MJIT relies on SIGCHLD and fork(2) to be performant, and it's something mswin can't offer. You could run Linux MJIT on WSL instead. [Misc #18968] --- mjit.c | 334 +----------------------------------------- mjit_compile.c | 3 - test/ruby/test_rubyoptions.rb | 3 +- tool/transform_mjit_header.rb | 14 +- win32/Makefile.sub | 111 +------------- win32/configure.bat | 12 -- win32/setup.mak | 1 - 7 files changed, 13 insertions(+), 465 deletions(-) diff --git a/mjit.c b/mjit.c index 7912f8fb8d..e519a3091d 100644 --- a/mjit.c +++ b/mjit.c @@ -98,14 +98,9 @@ https://github.com/ruby/ruby/blob/trunk/mjit.c#L98 #include "insns_info.inc" #include "internal/compile.h" -#ifdef _WIN32 -#include <winsock2.h> -#include <windows.h> -#else #include <sys/wait.h> #include <sys/time.h> #include <dlfcn.h> -#endif #include <errno.h> #ifdef HAVE_FCNTL_H #include <fcntl.h> @@ -122,34 +117,11 @@ https://github.com/ruby/ruby/blob/trunk/mjit.c#L117 # define MAXPATHLEN 1024 #endif -#ifdef _WIN32 -#define dlopen(name,flag) ((void*)LoadLibrary(name)) -#define dlerror() strerror(rb_w32_map_errno(GetLastError())) -#define dlsym(handle,name) ((void*)GetProcAddress((handle),(name))) -#define dlclose(handle) (!FreeLibrary(handle)) -#define RTLD_NOW -1 - -#define waitpid(pid,stat_loc,options) (WaitForSingleObject((HANDLE)(pid), INFINITE), GetExitCodeProcess((HANDLE)(pid), (LPDWORD)(stat_loc)), CloseHandle((HANDLE)pid), (pid)) -#define WIFEXITED(S) ((S) != STILL_ACTIVE) -#define WEXITSTATUS(S) (S) -#define WIFSIGNALED(S) (0) -typedef intptr_t pid_t; -#endif - // Atomically set function pointer if possible. #define MJIT_ATOMIC_SET(var, val) (void)ATOMIC_PTR_EXCHANGE(var, val) #define MJIT_TMP_PREFIX "_ruby_mjit_" -// JIT compaction requires the header transformation because linking multiple .o files -// doesn't work without having `static` in the same function definitions. We currently -// don't support transforming the MJIT header on Windows. -#ifdef _WIN32 -# define USE_JIT_COMPACTION 0 -#else -# define USE_JIT_COMPACTION 1 -#endif - // Linked list of struct rb_mjit_unit. struct rb_mjit_unit_list { struct ccan_list_head head; @@ -237,15 +209,8 @@ static struct rb_mjit_unit *current_cc_unit = NULL; https://github.com/ruby/ruby/blob/trunk/mjit.c#L209 // PID of currently running C compiler process. 0 if nothing is running. static pid_t current_cc_pid = 0; // TODO: make this part of unit? -#ifndef _MSC_VER // Name of the header file. static char *header_file; -#endif - -#ifdef _WIN32 -// Linker option to enable libruby. -static char *libruby_pathflag; -#endif #include "mjit_config.h" @@ -261,7 +226,7 @@ static char *libruby_pathflag; https://github.com/ruby/ruby/blob/trunk/mjit.c#L226 // Use `-nodefaultlibs -nostdlib` for GCC where possible, which does not work on cygwin, AIX, and OpenBSD. // This seems to improve MJIT performance on GCC. -#if defined __GNUC__ && !defined __clang__ && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__OpenBSD__) +#if defined __GNUC__ && !defined __clang__ && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__OpenBSD__) # define GCC_NOSTDLIB_FLAGS "-nodefaultlibs", "-nostdlib", #else # define GCC_NOSTDLIB_FLAGS // empty @@ -286,7 +251,7 @@ static const char *const CC_LINKER_ARGS[] = { https://github.com/ruby/ruby/blob/trunk/mjit.c#L251 }; static const char *const CC_LIBS[] = { -#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(__CYGWIN__) MJIT_LIBS // mswin, cygwin #endif #if defined __GNUC__ && !defined __clang__ @@ -371,22 +336,6 @@ remove_file(const char *filename) https://github.com/ruby/ruby/blob/trunk/mjit.c#L336 } } -// Lazily delete .so files. -static void -clean_temp_files(struct rb_mjit_unit *unit) -{ -#if defined(_WIN32) - if (unit->so_file) { - char *so_file = unit->so_file; - - unit->so_file = NULL; - // unit->so_file is set only when mjit_opts.save_temps is false. - remove_file(so_file); - free(so_file); - } -#endif -} - // This is called in the following situations: // 1) On dequeue or `unload_units()`, associated ISeq is already GCed. // 2) The unit is not called often and unloaded by `unload_units()`. @@ -409,7 +358,6 @@ free_unit(struct rb_mjit_unit *unit) https://github.com/ruby/ruby/blob/trunk/mjit.c#L358 if (unit->handle && dlclose(unit->handle)) { // handle is NULL if it's in queue mjit_warning("failed to close handle for u%d: %s", unit->id, dlerror()); } - clean_temp_files(unit); free(unit); } @@ -556,22 +504,6 @@ start_process(const char *abspath, char *const *argv) https://github.com/ruby/ruby/blob/trunk/mjit.c#L504 } pid_t pid; -#ifdef _WIN32 - extern HANDLE rb_w32_start_process(const char *abspath, char *const *argv, int out_fd); - int out_fd = 0; - if (mjit_opts.verbose <= 1) { - // Discard cl.exe's outputs like: - // _ruby_mjit_p12u3.c - // Creating library C:.../_ruby_mjit_p12u3.lib and object C:.../_ruby_mjit_p12u3.exp - out_fd = dev_null; - } - - pid = (pid_t)rb_w32_start_process(abspath, argv, out_fd); - if (pid == 0) { - verbose(1, "MJIT: Failed to create process: %s", dlerror()); - return -1; - } -#else if ((pid = vfork()) == 0) { /* TODO: reuse some function in process.c */ umask(0077); if (mjit_opts.verbose == 0) { @@ -589,7 +521,6 @@ start_process(const char *abspath, char *const *argv) https://github.com/ruby/ruby/blob/trunk/mjit.c#L521 verbose(1, "MJIT: Error in execv: %s", abspath); _exit(1); } -#endif (void)close(dev_null); return pid; } @@ -629,14 +560,7 @@ exec_process(const char *path, char *const argv[]) https://github.com/ruby/ruby/blob/trunk/mjit.c#L560 static void remove_so_file(const char *so_file, struct rb_mjit_unit *unit) { -#if defined(_WIN32) - // Windows can't remove files while it's used. - unit->so_file = strdup(so_file); // lazily delete on `clean_temp_files()` - if (unit->so_file == NULL) - mjit_warning("failed to allocate memory to lazily remove '%s': %s", so_file, strerror(errno)); -#else remove_file(so_file); -#endif } // Print _mjitX, but make a human-readable funcname when --mjit-debug is used @@ -683,87 +607,6 @@ static const int c_file_access_mode = https://github.com/ruby/ruby/blob/trunk/mjit.c#L607 #define append_str(p, str) append_str2(p, str, sizeof(str)-1) #define append_lit(p, str) append_str2(p, str, rb_strlen_lit(str)) -#ifdef _MSC_VER -// Compile C file to so. It returns true if it succeeds. (mswin) -static bool -compile_c_to_so(const char *c_file, const char *so_file) -{ - const char *files[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-link", libruby_pathflag, NULL }; - char *p; - - // files[0] = "-Fe*.dll" - files[0] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fe") + strlen(so_file) + 1)); - p = append_lit(p, "-Fe"); - p = append_str2(p, so_file, strlen(so_file)); - *p = '\0'; - - // files[1] = "-Fo*.obj" - // We don't need .obj file, but it's somehow created to cwd without -Fo and we want to control the output directory. - files[1] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fo") + strlen(so_file) - rb_strlen_lit(DLEXT) + rb_strlen_lit(".obj") + 1)); - char *obj_file = p = append_lit(p, "-Fo"); - p = append_str2(p, so_file, strlen(so_file) - rb_strlen_lit(DLEXT)); - p = append_lit(p, ".obj"); - *p = '\0'; - - // files[2] = "-Yu*.pch" - files[2] = p = alloca(sizeof(char) * (rb_strlen_lit("-Yu") + strlen(pch_file) + 1)); - p = append_lit(p, "-Yu"); - p = append_str2(p, pch_file, strlen(pch_file)); - *p = '\0'; - - // files[3] = "C:/.../rb_mjit_header-*.obj" - files[3] = p = alloca(sizeof(char) * (strlen(pch_file) + 1)); - p = append_str2(p, pch_file, strlen(pch_file) - strlen(".pch")); - p = append_lit(p, ".obj"); - *p = '\0'; - - // files[4] = "-Tc*.c" - files[4] = p = alloca(sizeof(char) * (rb_strlen_lit("-Tc") + strlen(c_file) + 1)); - p = append_lit(p, "-Tc"); - p = append_str2(p, c_file, strlen(c_file)); - *p = '\0'; - - // files[5] = "-Fd*.pdb" - // Generate .pdb file in temporary directory instead of cwd. - files[5] = p = alloca(sizeof(char) * (rb_strlen_lit("-Fd") + strlen(so_file) - rb_strlen_lit(DLEXT) + rb_strlen_lit(".pdb") + 1)); - p = append_lit(p, "-Fd"); - p = append_str2(p, so_file, strlen(so_file) - rb_strlen_lit(DLEXT)); - p = append_lit(p, ".pdb"); - *p = '\0'; - - // files[6] = "-Z7" - // Put this last to override any debug options that came previously. - files[6] = p = alloca(sizeof(char) * rb_strlen_lit("-Z7") + 1); - p = append_lit(p, "-Z7"); - *p = '\0'; - - char **args = form_args(5, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS, - files, CC_LIBS, CC_DLDFLAGS_ARGS); - if (args == NULL) - return false; - - int exit_code = exec_process(cc_path, args); - free(args); - - if (exit_code == 0) { - // remove never-used files (.obj, .lib, .exp, .pdb). XXX: Is there any way not to generate this? - if (!mjit_opts.save_temps) { - char *before_dot; - remove_file(obj_file); - - before_dot = obj_file + strlen(obj_file) - rb_strlen_lit(".obj"); - append_lit(before_dot, ".lib"); remove_file(obj_file); - append_lit(before_dot, ".exp"); remove_file(obj_file); - append_lit(before_dot, ".pdb"); remove_file(obj_file); - } - } - else { - verbose(2, "compile_c_to_so: compile error: %d", exit_code); - } - return exit_code == 0; -} -#else // _MSC_VER - // The fu (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/