[前][次][番号順一覧][スレッド一覧]

ruby-changes:70618

From: U.Nakamura <ko1@a...>
Date: Mon, 27 Dec 2021 15:59:47 +0900 (JST)
Subject: [ruby-changes:70618] 85a426dc86 (master): Tiny mmap emulation for Windows

https://git.ruby-lang.org/ruby.git/commit/?id=85a426dc86

From 85a426dc8678f04a78ffd799943b690ce2984c49 Mon Sep 17 00:00:00 2001
From: "U.Nakamura" <usa@r...>
Date: Mon, 27 Dec 2021 15:56:23 +0900
Subject: Tiny mmap emulation for Windows

- prerequisite of supporting YJIT with VC++.
- note that now can specfily `--yjit` on mswin64, but not enabled
  YJIT'ed code because of YJIT requires `OPT_DIRECT_THREADED_CODE`
  or `OPT_CALL_THREADED_CODE` in `rb_yjit_compile_iseq`.
---
 include/ruby/win32.h | 19 +++++++++++++++++++
 win32/win32.c        | 31 +++++++++++++++++++++++++++++++
 yjit.h               |  2 +-
 yjit_asm.c           | 15 +++++++--------
 4 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index c8ae599f2f8..287ac34270b 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -796,6 +796,25 @@ double rb_w32_pow(double x, double y); https://github.com/ruby/ruby/blob/trunk/include/ruby/win32.h#L796
 #define pow rb_w32_pow
 #endif
 
+// mmap tiny emulation
+#define MAP_FAILED	((void *)-1)
+
+#define PROT_READ	0x01
+#define PROT_WRITE	0x02
+#define PROT_EXEC	0x04
+
+#define MAP_PRIVATE	0x0002
+#define MAP_ANON	0x1000
+#define MAP_ANONYMOUS	MAP_ANON
+
+extern void *rb_w32_mmap(void *, size_t, int, int, int, off_t);
+extern int rb_w32_munmap(void *, size_t);
+extern int rb_w32_mprotect(void *, size_t, int);
+
+#define mmap(a, l, p, f, d, o) rb_w32_mmap(a, l, p, f, d, o)
+#define munmap(a, l) rb_w32_munmap(a. l)
+#define mprotect(a, l, p) 0
+
 #if defined(__cplusplus)
 #if 0
 { /* satisfy cc-mode */
diff --git a/win32/win32.c b/win32/win32.c
index c938e197a7d..889046ceaa5 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -8204,3 +8204,34 @@ VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE) = rb_f_notim https://github.com/ruby/ruby/blob/trunk/win32/win32.c#L8204
 #if RUBY_MSVCRT_VERSION < 120
 #include "missing/nextafter.c"
 #endif
+
+void *
+rb_w32_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+    void *ptr;
+
+    if (fd > 0 || offset) {
+        /* not supported */
+        errno = EINVAL;
+        return MAP_FAILED;
+    }
+
+    ptr = VirtualAlloc(addr, len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+    if (!ptr) {
+        errno = rb_w32_map_errno(GetLastError());
+        return MAP_FAILED;
+    }
+
+    return ptr;
+}
+
+int
+rb_w32_munmap(void *addr, size_t len)
+{
+    if (!VirtualFree(addr, 0, MEM_RELEASE)) {
+        errno = rb_w32_map_errno(GetLastError());
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/yjit.h b/yjit.h
index 6f66f59f01a..53e8b531a97 100644
--- a/yjit.h
+++ b/yjit.h
@@ -16,7 +16,7 @@ https://github.com/ruby/ruby/blob/trunk/yjit.h#L16
 #endif
 
 // We generate x86 assembly and rely on mmap(2).
-#if defined(__x86_64__) && !defined(_WIN32)
+#if defined(__x86_64__) || defined(_WIN64)
 # define YJIT_SUPPORTED_P 1
 #else
 # define YJIT_SUPPORTED_P 0
diff --git a/yjit_asm.c b/yjit_asm.c
index 9f84e3974b7..4cc3a538fa3 100644
--- a/yjit_asm.c
+++ b/yjit_asm.c
@@ -149,11 +149,10 @@ static uint8_t *align_ptr(uint8_t *ptr, uint32_t multiple) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L149
 // Allocate a block of executable memory
 static uint8_t *alloc_exec_mem(uint32_t mem_size)
 {
-#ifndef _WIN32
     uint8_t *mem_block;
 
     // On Linux
-    #if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
+#if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
         // Align the requested address to page size
         uint32_t page_size = (uint32_t)sysconf(_SC_PAGESIZE);
         uint8_t *req_addr = align_ptr((uint8_t*)&alloc_exec_mem, page_size);
@@ -179,7 +178,7 @@ static uint8_t *alloc_exec_mem(uint32_t mem_size) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L178
         } while (req_addr < (uint8_t*)&alloc_exec_mem + INT32_MAX);
 
     // On MacOS and other platforms
-    #else
+#else
         // Try to map a chunk of memory as executable
         mem_block = (uint8_t*)mmap(
             (void*)alloc_exec_mem,
@@ -189,7 +188,7 @@ static uint8_t *alloc_exec_mem(uint32_t mem_size) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L188
             -1,
             0
         );
-    #endif
+#endif
 
     // Fallback
     if (mem_block == MAP_FAILED) {
@@ -223,10 +222,6 @@ static uint8_t *alloc_exec_mem(uint32_t mem_size) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L222
     cb_mark_all_executable(cb);
 
     return mem_block;
-#else
-    // Windows not supported for now
-    return NULL;
-#endif
 }
 
 // Initialize a code block object
@@ -1811,7 +1806,11 @@ void cb_mark_all_writeable(codeblock_t * cb) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L1806
 
 void cb_mark_position_writeable(codeblock_t * cb, uint32_t write_pos)
 {
+#ifdef _WIN32
+    uint32_t pagesize = 0x1000; // 4KB
+#else
     uint32_t pagesize = (uint32_t)sysconf(_SC_PAGESIZE);
+#endif
     uint32_t aligned_position = (write_pos / pagesize) * pagesize;
 
     if (cb->current_aligned_write_pos != aligned_position) {
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]