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

ruby-changes:69588

From: Maxime <ko1@a...>
Date: Fri, 5 Nov 2021 05:05:56 +0900 (JST)
Subject: [ruby-changes:69588] 2421527d6e (master): YJIT code pages refactoring for code GC (#5073)

https://git.ruby-lang.org/ruby.git/commit/?id=2421527d6e

From 2421527d6e4737c371bca0cf7e694f8a2a0f923d Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Thu, 4 Nov 2021 13:05:41 -0700
Subject: YJIT code pages refactoring for code GC (#5073)

* New code page allocation logic

* Fix leaked globals

* Fix leaked symbols, yjit asm tests

* Make COUNTED_EXIT take a jit argument, so we can eliminate global ocb

* Remove extra whitespace

* Change block start_pos/end_pos to be pointers instead of uint32_t

* Change branch end_pos and start_pos to end_addr, start_addr
---
 misc/yjit_asm_tests.c |   4 --
 yjit_asm.c            |  37 +------------
 yjit_asm.h            |  26 +---------
 yjit_codegen.c        |  54 +++++++++----------
 yjit_core.c           |  67 ++++++++++++------------
 yjit_core.h           |  16 +++---
 yjit_iface.c          | 141 ++++++++++++++++++++++++++++++++++++++++++--------
 yjit_iface.h          |   8 +--
 8 files changed, 194 insertions(+), 159 deletions(-)

diff --git a/misc/yjit_asm_tests.c b/misc/yjit_asm_tests.c
index 0bd11e47528..5708d3abadb 100644
--- a/misc/yjit_asm_tests.c
+++ b/misc/yjit_asm_tests.c
@@ -426,10 +426,6 @@ void run_runtime_tests(void) https://github.com/ruby/ruby/blob/trunk/misc/yjit_asm_tests.c#L426
 
 int main(int argc, char** argv)
 {
-    // suppress -Wunused-function
-    (void)alloc_code_page;
-    (void)free_code_page;
-
     run_assembler_tests();
     run_runtime_tests();
 
diff --git a/yjit_asm.c b/yjit_asm.c
index 0d074d5e4d5..49844145cb3 100644
--- a/yjit_asm.c
+++ b/yjit_asm.c
@@ -147,7 +147,7 @@ static uint8_t *align_ptr(uint8_t *ptr, uint32_t multiple) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L147
 }
 
 // Allocate a block of executable memory
-uint8_t *alloc_exec_mem(uint32_t mem_size)
+static uint8_t *alloc_exec_mem(uint32_t mem_size)
 {
 #ifndef _WIN32
     uint8_t *mem_block;
@@ -221,41 +221,6 @@ uint8_t *alloc_exec_mem(uint32_t mem_size) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L221
 #endif
 }
 
-// Head of the list of free code pages
-static code_page_t *freelist = NULL;
-
-// Allocate a single code page from a pool of free pages
-code_page_t *alloc_code_page(void)
-{
-    // If the free list is empty
-    if (!freelist) {
-        // Allocate many pages at once
-        uint8_t *code_chunk = alloc_exec_mem(PAGES_PER_ALLOC * CODE_PAGE_SIZE);
-
-        // Do this in reverse order so we allocate our pages in order
-        for (int i = PAGES_PER_ALLOC - 1; i >= 0; --i) {
-            code_page_t *code_page = malloc(sizeof(code_page_t));
-            code_page->mem_block = code_chunk + i * CODE_PAGE_SIZE;
-            assert ((intptr_t)code_page->mem_block % CODE_PAGE_SIZE == 0);
-            code_page->page_size = CODE_PAGE_SIZE;
-            code_page->_next = freelist;
-            freelist = code_page;
-        }
-    }
-
-    code_page_t *free_page = freelist;
-    freelist = freelist->_next;
-
-    return free_page;
-}
-
-// Put a code page back into the allocation pool
-void free_code_page(code_page_t *code_page)
-{
-    code_page->_next = freelist;
-    freelist = code_page;
-}
-
 // Initialize a code block object
 void cb_init(codeblock_t *cb, uint8_t *mem_block, uint32_t mem_size)
 {
diff --git a/yjit_asm.h b/yjit_asm.h
index 30682b5078a..b1b2baae2e5 100644
--- a/yjit_asm.h
+++ b/yjit_asm.h
@@ -5,12 +5,6 @@ https://github.com/ruby/ruby/blob/trunk/yjit_asm.h#L5
 #include <stddef.h>
 #include <stdbool.h>
 
-// Size of code pages to allocate
-#define CODE_PAGE_SIZE 16 * 1024
-
-// How many code pages to allocate at once
-#define PAGES_PER_ALLOC 512
-
 // Maximum number of labels to link
 #define MAX_LABELS 32
 
@@ -137,20 +131,6 @@ typedef struct X86Opnd https://github.com/ruby/ruby/blob/trunk/yjit_asm.h#L131
 
 } x86opnd_t;
 
-// Struct representing a code page
-typedef struct code_page_struct
-{
-    // Chunk of executable memory
-    uint8_t *mem_block;
-
-    // Size of the executable memory chunk
-    uint32_t page_size;
-
-    // Next node in the free list (private)
-    struct code_page_struct *_next;
-
-} code_page_t;
-
 // Dummy none/null operand
 static const x86opnd_t NO_OPND = { OPND_NONE, 0, .as.imm = 0 };
 
@@ -264,12 +244,10 @@ static inline x86opnd_t const_ptr_opnd(const void *ptr); https://github.com/ruby/ruby/blob/trunk/yjit_asm.h#L244
      sizeof(((struct_type*)0)->member_name[0]) * idx)  \
 )
 
-// Machine code allocation
+// Allocate executable memory
 static uint8_t *alloc_exec_mem(uint32_t mem_size);
-static code_page_t *alloc_code_page(void);
-static void free_code_page(code_page_t *code_page);
-
 
+// Code block functions
 static inline void cb_init(codeblock_t *cb, uint8_t *mem_block, uint32_t mem_size);
 static inline void cb_align_pos(codeblock_t *cb, uint32_t multiple);
 static inline void cb_set_pos(codeblock_t *cb, uint32_t pos);
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 327e74b8111..ac79ce1e75e 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -23,7 +23,7 @@ static codegen_fn gen_fns[VM_INSTRUCTION_SIZE] = { NULL }; https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L23
 // Map from method entries to code generation functions
 static st_table *yjit_method_codegen_table = NULL;
 
-// Code for exiting back to the interpreter from the leave insn
+// Code for exiting back to the interpreter from the leave instruction
 static void *leave_exit_code;
 
 // Code for full logic of returning from C method and exiting to the interpreter
@@ -303,22 +303,22 @@ _gen_counter_inc(codeblock_t *cb, int64_t *counter) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L303
 }
 
 // Increment a counter then take an existing side exit.
-#define COUNTED_EXIT(side_exit, counter_name) _counted_side_exit(side_exit, &(yjit_runtime_counters . counter_name))
+#define COUNTED_EXIT(jit, side_exit, counter_name) _counted_side_exit(jit, side_exit, &(yjit_runtime_counters . counter_name))
 static uint8_t *
-_counted_side_exit(uint8_t *existing_side_exit, int64_t *counter)
+_counted_side_exit(jitstate_t* jit, uint8_t *existing_side_exit, int64_t *counter)
 {
     if (!rb_yjit_opts.gen_stats) return existing_side_exit;
 
-    uint8_t *start = cb_get_ptr(ocb, ocb->write_pos);
-    _gen_counter_inc(ocb, counter);
-    jmp_ptr(ocb, existing_side_exit);
+    uint8_t *start = cb_get_ptr(jit->ocb, jit->ocb->write_pos);
+    _gen_counter_inc(jit->ocb, counter);
+    jmp_ptr(jit->ocb, existing_side_exit);
     return start;
 }
 
 #else
 
 #define GEN_COUNTER_INC(cb, counter_name) ((void)0)
-#define COUNTED_EXIT(side_exit, counter_name) side_exit
+#define COUNTED_EXIT(jit, side_exit, counter_name) side_exit
 
 #endif // if YJIT_STATS
 
@@ -512,7 +512,7 @@ yjit_entry_prologue(codeblock_t *cb, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L512
     cb_align_pos(cb, 64);
 
     uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
-    ADD_COMMENT(cb, "yjit prolog");
+    ADD_COMMENT(cb, "yjit entry");
 
     push(cb, REG_CFP);
     push(cb, REG_EC);
@@ -571,8 +571,8 @@ jit_jump_to_next_insn(jitstate_t *jit, const ctx_t *current_context) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L571
 
     // We are at the end of the current instruction. Record the boundary.
     if (jit->record_boundary_patch_point) {
-        uint32_t exit_pos = yjit_gen_exit(jit->pc + insn_len(jit->opcode), &reset_depth, ocb);
-        record_global_inval_patch(cb, exit_pos);
+        uint32_t exit_pos = yjit_gen_exit(jit->pc + insn_len(jit->opcode), &reset_depth, jit->ocb);
+        record_global_inval_patch(jit->cb, exit_pos);
         jit->record_boundary_patch_point = false;
     }
 
@@ -620,7 +620,7 @@ yjit_gen_block(block_t *block, rb_execution_context_t *ec) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L620
     };
 
     // Mark the start position of the block
-    block->start_pos = cb->write_pos;
+    block->start_addr = cb_get_write_ptr(cb);
 
     // For each instruction to compile
     for (;;) {
@@ -704,7 +704,7 @@ yjit_gen_block(block_t *block, rb_execution_context_t *ec) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L704
     }
 
     // Mark the end position of the block
-    block->end_pos = cb->write_pos;
+    block->end_addr = cb_get_write_ptr(cb);
 
     // Store the index of the last instruction in the block
     block->end_idx = insn_idx;
@@ -1030,8 +1030,8 @@ gen_expandarray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1030
 
     // Move the array from the stack into REG0 and check that it's an array.
     mov(cb, REG0, array_opnd);
-    guard_object_is_heap(cb, REG0, ctx, COUNTED_EXIT(side_exit, expandarray_not_array));
-    guard_object_is_array(cb, REG0, REG1, ctx, COUNTED_EXIT(side_exit, expandarray_not_array));
+    guard_object_is_heap(cb, REG0, ctx, COUNTED_EXIT(jit, side_exit, expandarray_not_array));
+    guard_object_is_array(cb, REG0, REG1, ctx, COUNTED_EXIT(jit, side_exit, expandarray_not_array));
 
     // If we don't actually want any values, then just return.
     if (num == 0) {
@@ -1053,7 +1053,7 @@ gen_expandarray(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1053
     // Only handle the case where the number of values in the array is greater
     // than or equal to the number of values requested.
     cmp(cb, REG1, imm_opnd(num));
-    jl_ptr(cb, COUNTED_EXIT(side_exit, expandarray_rhs_too_small));
+    jl_ptr(cb, COUNTED_EXIT(jit, side_exit, expandarray_rhs_too_small));
 
     // Load the address of the embedded array into REG1.
     // (struct RArray *)(obj)->as.ary
@@ -1663,7 +1663,7 @@ gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE compt https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1663
             // Check that the slot is inside the extended table (num_slots > index)
             x86opnd_t num_slots = mem_opnd(32, REG0, offsetof(struct RObject, as.heap.numiv));
             cmp(cb, num_slots, (... truncated)

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

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