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

ruby-changes:68682

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:12:20 +0900 (JST)
Subject: [ruby-changes:68682] 5e39d83fbd (master): Split out compile_entry() from compile_block()

https://git.ruby-lang.org/ruby.git/commit/?id=5e39d83fbd

From 5e39d83fbd560a5151facba10e95889aff84c93e Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Fri, 18 Dec 2020 13:49:53 -0500
Subject: Split out compile_entry() from compile_block()

---
 ujit_codegen.c | 75 ++++++++++++++++++++++++++++++++++------------------------
 ujit_codegen.h |  4 +++-
 ujit_core.c    |  3 ++-
 ujit_core.h    | 12 +++++++++-
 ujit_iface.c   |  2 +-
 5 files changed, 61 insertions(+), 35 deletions(-)

diff --git a/ujit_codegen.c b/ujit_codegen.c
index ebffef424a..09b61a9bea 100644
--- a/ujit_codegen.c
+++ b/ujit_codegen.c
@@ -86,11 +86,49 @@ ujit_side_exit(codeblock_t* cb, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L86
 }
 
 /*
-Compile a sequence of bytecode instructions starting at `insn_idx`.
+Compile an interpreter entry point to be inserted into an iseq
 Returns `NULL` if compilation fails.
 */
+uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx)
+{
+    assert (cb != NULL);
+
+    if (cb->write_pos + 1024 >= cb->mem_size) {
+        rb_bug("out of executable memory");
+    }
+
+    // Align the current write positon to cache line boundaries
+    cb_align_pos(cb, 64);
+
+    uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
+
+    // Write the interpreter entry prologue
+    ujit_gen_entry(cb);
+
+    // Compile the block starting at this instruction
+    uint32_t num_instrs = 0;
+    ujit_compile_block(iseq, insn_idx, &num_instrs);
+
+    // If no instructions were compiled
+    if (num_instrs == 0) {
+        return NULL;
+    }
+
+    // Get the first opcode in the sequence
+    VALUE *encoded = iseq->body->iseq_encoded;
+    int first_opcode = opcode_at_pc(iseq, &encoded[insn_idx]);
+
+    // Map the code address to the corresponding opcode
+    map_addr2insn(code_ptr, first_opcode);
+
+    return code_ptr;
+}
+
+/*
+Compile a sequence of bytecode instructions starting at `insn_idx`.
+*/
 uint8_t *
-ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool entry_point)
+ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instrs)
 {
     assert (cb != NULL);
     VALUE *encoded = iseq->body->iseq_encoded;
@@ -105,15 +143,8 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool entry_point) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L143
         rb_bug("out of executable memory (outlined block)");
     }
 
-    // Align the current write positon to cache line boundaries
-    cb_align_pos(cb, 64);
-
     // Get a pointer to the current write position in the code block
-    uint8_t *code_ptr = &cb->mem_block[cb->write_pos];
-    //printf("write pos: %ld\n", cb->write_pos);
-
-    // Get the first opcode in the sequence
-    int first_opcode = opcode_at_pc(iseq, &encoded[insn_idx]);
+    uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
 
     // Create codegen context
     ctx_t ctx = { 0 };
@@ -122,7 +153,6 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool entry_point) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L153
     ctx.start_idx = insn_idx;
 
     // For each instruction to compile
-    unsigned num_instrs = 0;
     for (;;) {
         // Set the current instruction
         ctx.insn_idx = insn_idx;
@@ -139,12 +169,6 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool entry_point) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L169
             break;
         }
 
-        // If this is an interpreter entry point, write the interpreter
-        // entry prologue before the first instruction
-        if (entry_point && num_instrs == 0) {
-            ujit_gen_entry(cb);
-        }
-
         //fprintf(stderr, "compiling %s\n", insn_name(opcode));
         //print_str(cb, insn_name(opcode));
 
@@ -156,7 +180,7 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool entry_point) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L180
 
     	// Move to the next instruction
         insn_idx += insn_len(opcode);
-        num_instrs++;
+        (*num_instrs)++;
 
         // Ensure we only have one send per region. Our code invalidation mechanism can't
         // invalidate running code and one send could invalidate the other if we had
@@ -166,24 +190,13 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool entry_point) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L190
         }
     }
 
-    // FIXME: maybe we want a separate function to compile entry points?
-    // If this is an entry point and no instructions were compiled
-    if (entry_point && num_instrs == 0) {
-        return NULL;
-    }
-
     //print_str(cb, "exiting to interpreter\n");
 
-    // FIXME: only generate exit if no instructions were compiled?
-    // or simply don't allow instructions to fail to compile anymore?
+    // FIXME: we only need to generate an exit if an instruction fails to compile
+    //
     // Generate code to exit to the interpreter
     ujit_gen_exit(cb, &ctx, &encoded[insn_idx]);
 
-    // If this is an interpreter entry point
-    if (entry_point) {
-        map_addr2insn(code_ptr, first_opcode);
-    }
-
     if (UJIT_DUMP_MODE >= 2) {
         // Dump list of compiled instrutions
         fprintf(stderr, "Compiled the following for iseq=%p:\n", (void *)iseq);
diff --git a/ujit_codegen.h b/ujit_codegen.h
index ab4f87057e..66a93a4796 100644
--- a/ujit_codegen.h
+++ b/ujit_codegen.h
@@ -10,7 +10,9 @@ codeblock_t* ocb; https://github.com/ruby/ruby/blob/trunk/ujit_codegen.h#L10
 // Code generation function signature
 typedef bool (*codegen_fn)(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx);
 
-uint8_t *ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, bool gen_entry);
+uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx);
+
+uint8_t *ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, uint32_t* num_instrs);
 
 void ujit_init_codegen(void);
 
diff --git a/ujit_core.c b/ujit_core.c
index a1ae75113b..449becafaf 100644
--- a/ujit_core.c
+++ b/ujit_core.c
@@ -155,7 +155,8 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L155
     {
         //fprintf(stderr, "compiling block\n");
 
-        block_ptr = ujit_compile_block(target.iseq, target.idx, false);
+        uint32_t num_instrs = 0;
+        block_ptr = ujit_compile_block(target.iseq, target.idx, &num_instrs);
         st_insert(version_tbl, (st_data_t)&target, (st_data_t)block_ptr);
         branch->dst_addrs[target_idx] = block_ptr;
     }
diff --git a/ujit_core.h b/ujit_core.h
index 6b9eaaaeac..131f2864dc 100644
--- a/ujit_core.h
+++ b/ujit_core.h
@@ -20,8 +20,18 @@ https://github.com/ruby/ruby/blob/trunk/ujit_core.h#L20
 // Maximum number of versions per block
 #define MAX_VERSIONS 5
 
+// Code generation state
+typedef struct JITState
+{
+
+
+
+
+
+} jitstate_t;
+
 // Code generation context
-typedef struct ctx_struct
+typedef struct CtxStruct
 {
     // TODO: we may want to remove information that is not
     // strictly necessary for versioning from this struct
diff --git a/ujit_iface.c b/ujit_iface.c
index e30e3afa3b..85b732e96f 100644
--- a/ujit_iface.c
+++ b/ujit_iface.c
@@ -233,7 +233,7 @@ rb_ujit_compile_iseq(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/ujit_iface.c#L233
     VALUE *encoded = (VALUE *)iseq->body->iseq_encoded;
 
     // Compile a block version starting at the first instruction
-    uint8_t* native_code_ptr = ujit_compile_block(iseq, 0, true);
+    uint8_t* native_code_ptr = ujit_compile_entry(iseq, 0);
 
     if (native_code_ptr) {
         encoded[0] = (VALUE)native_code_ptr;
-- 
cgit v1.2.1


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

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