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

ruby-changes:68661

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:12:04 +0900 (JST)
Subject: [ruby-changes:68661] 20f5b7426e (master): Start implementing BBV primitives

https://git.ruby-lang.org/ruby.git/commit/?id=20f5b7426e

From 20f5b7426e839c90819f223c1a30992fd8d4023c Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Thu, 10 Dec 2020 16:59:13 -0500
Subject: Start implementing BBV primitives

---
 ujit_codegen.c | 13 +++++++------
 ujit_codegen.h |  2 +-
 ujit_core.c    | 60 ++++++++++++++++++++++++++++++++++++++++++----------------
 ujit_core.h    | 14 ++++++++++++++
 ujit_iface.c   |  4 ++--
 5 files changed, 68 insertions(+), 25 deletions(-)

diff --git a/ujit_codegen.c b/ujit_codegen.c
index c51f7b1944..4897e38cde 100644
--- a/ujit_codegen.c
+++ b/ujit_codegen.c
@@ -34,6 +34,9 @@ static void https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L34
 ujit_gen_entry(codeblock_t* cb)
 {
     cb_write_pre_call_bytes(cb);
+
+    // Load the current SP from the CFP into REG_SP
+    mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
 }
 
 /**
@@ -98,7 +101,7 @@ Compile a sequence of bytecode instructions starting at `insn_idx`. https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L101
 Returns `NULL` if compilation fails.
 */
 uint8_t *
-ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx)
+ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry)
 {
     assert (cb != NULL);
     unsigned first_insn_idx = insn_idx;
@@ -147,12 +150,10 @@ ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L150
             break;
         }
 
-        // Write the pre call bytes before the first instruction
-        if (num_instrs == 0) {
+        // If requested, write the interpreter entry
+        // prologue before the first instruction
+        if (gen_entry && num_instrs == 0) {
             ujit_gen_entry(cb);
-
-            // Load the current SP from the CFP into REG_SP
-            mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
         }
 
         // Call the code generation function
diff --git a/ujit_codegen.h b/ujit_codegen.h
index 7c03420097..5216dbb1be 100644
--- a/ujit_codegen.h
+++ b/ujit_codegen.h
@@ -3,7 +3,7 @@ https://github.com/ruby/ruby/blob/trunk/ujit_codegen.h#L3
 
 #include "stddef.h"
 
-uint8_t * ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx);
+uint8_t *ujit_compile_block(const rb_iseq_t *iseq, unsigned int insn_idx, bool gen_entry);
 
 void ujit_init_codegen(void);
 
diff --git a/ujit_core.c b/ujit_core.c
index 261a33315f..c981ef0e30 100644
--- a/ujit_core.c
+++ b/ujit_core.c
@@ -2,35 +2,56 @@ https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L2
 #include "ujit_asm.h"
 #include "ujit_iface.h"
 #include "ujit_core.h"
-
-
-
+#include "ujit_codegen.h"
 
 // Table of block versions indexed by (iseq, index) tuples
 st_table * version_tbl;
 
-/*
-struct st_hash_type {
-    int (*compare)(st_data_t, st_data_t); // st_compare_func*
-    st_index_t (*hash)(st_data_t);        // st_hash_func*
-};
+int blockid_cmp(st_data_t arg0, st_data_t arg1)
+{
+    const blockid_t *block0 = (const blockid_t*)arg0;
+    const blockid_t *block1 = (const blockid_t*)arg1;
+    return block0->iseq == block1->iseq && block0->idx == block1->idx;
+}
+
+st_index_t blockid_hash(st_data_t arg)
+{
+    const blockid_t *blockid = (const blockid_t*)arg;
+    st_index_t hash0 = st_numhash((st_data_t)blockid->iseq);
+    st_index_t hash1 = st_numhash((st_data_t)blockid->idx);
 
-static const struct st_hash_type st_hashtype_num = {
-    st_numcmp,
-    st_numhash,
+    // Use XOR to combine the hashes
+    return hash0 ^ hash1;
+}
+
+static const struct st_hash_type hashtype_blockid = {
+    blockid_cmp,
+    blockid_hash,
 };
 
-strcasehash(st_data_t arg)
+// Retrieve a basic block version for an (iseq, idx) tuple
+// TODO: we need to add a versioning context here
+uint8_t* get_block_version(const rb_iseq_t *iseq, unsigned int idx /*, ctx_t* ctx */)
 {
-    register const char *string = (const char *)arg;
-    ...
-}
+    blockid_t blockid = { iseq, idx };
 
-*/
+    // If there exists a version for this block id
+    st_data_t st_version;
+    if (rb_st_lookup(version_tbl, (st_data_t)&blockid, &st_version)) {
+        return (uint8_t*)st_version;
+    }
 
+    uint8_t* code_ptr = ujit_compile_block(iseq, idx, false);
 
+    st_insert(version_tbl, (st_data_t)&blockid, (st_data_t)code_ptr);
 
+    return code_ptr;
+}
 
+//
+// Method to generate stubs for branches
+// TODO: get_branch_stub() or get_branch() function
+//
 
 // Get the current instruction opcode from the context object
 int
@@ -96,3 +117,10 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L117
 
     return opnd;
 }
+
+void
+ujit_init_core(void)
+{
+    // Initialize the version hash table
+    version_tbl = st_init_table(&hashtype_blockid);
+}
diff --git a/ujit_core.h b/ujit_core.h
index 320be8fa01..f42ff84ace 100644
--- a/ujit_core.h
+++ b/ujit_core.h
@@ -20,6 +20,17 @@ https://github.com/ruby/ruby/blob/trunk/ujit_core.h#L20
 // Maximum number of versions per block
 #define MAX_VERSIONS 5
 
+// Tuple of (iseq, idx) used to idenfity basic blocks
+typedef struct BlockId
+{
+    // Instruction sequence
+    const rb_iseq_t *iseq;
+
+    // Instruction index
+    const unsigned int idx;
+
+} blockid_t;
+
 // Code generation context
 typedef struct ctx_struct
 {
@@ -48,6 +59,7 @@ typedef struct ctx_struct https://github.com/ruby/ruby/blob/trunk/ujit_core.h#L59
 
 } ctx_t;
 
+// Context object methods
 int ctx_get_opcode(ctx_t *ctx);
 VALUE ctx_get_arg(ctx_t* ctx, size_t arg_idx);
 x86opnd_t ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes);
@@ -55,4 +67,6 @@ x86opnd_t ctx_stack_push(ctx_t* ctx, size_t n); https://github.com/ruby/ruby/blob/trunk/ujit_core.h#L67
 x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
 x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
 
+void ujit_init_core(void);
+
 #endif // #ifndef UJIT_CORE_H
diff --git a/ujit_iface.c b/ujit_iface.c
index ac541b7cdc..e30e3afa3b 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);
+    uint8_t* native_code_ptr = ujit_compile_block(iseq, 0, true);
 
     if (native_code_ptr) {
         encoded[0] = (VALUE)native_code_ptr;
@@ -253,7 +253,7 @@ rb_ujit_init(void) https://github.com/ruby/ruby/blob/trunk/ujit_iface.c#L253
 
     rb_ujit_enabled = true;
 
-    // Initialize ujit codegen
+    ujit_init_core();
     ujit_init_codegen();
 
     // Initialize the GC hooks
-- 
cgit v1.2.1


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

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