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

ruby-changes:68904

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:13:05 +0900 (JST)
Subject: [ruby-changes:68904] 09479c33f5 (master): Implement block version limit

https://git.ruby-lang.org/ruby.git/commit/?id=09479c33f5

From 09479c33f54423910674780d1fcb7834e98ef561 Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Wed, 27 Jan 2021 13:02:55 -0500
Subject: Implement block version limit

---
 ujit_core.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 ujit_core.h |  3 ---
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/ujit_core.c b/ujit_core.c
index 8d6680fc85..1aa6824fad 100644
--- a/ujit_core.c
+++ b/ujit_core.c
@@ -10,9 +10,15 @@ https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L10
 #include "ujit_core.h"
 #include "ujit_codegen.h"
 
+// Maximum number of versions per block
+#define MAX_VERSIONS 4
+
 // Maximum number of branch instructions we can track
 #define MAX_BRANCHES 32768
 
+// Default versioning context (no type information)
+const ctx_t DEFAULT_CTX = { { 0 }, 0 };
+
 // Table of block versions indexed by (iseq, index) tuples
 st_table * version_tbl;
 
@@ -168,6 +174,25 @@ static void add_incoming(block_t* p_block, uint32_t branch_idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L174
     p_block->num_incoming += 1;
 }
 
+// Count the number of block versions matching a given blockid
+static size_t count_block_versions(blockid_t blockid)
+{
+    // If there exists a version for this block id
+    block_t* first_version;
+    if (!rb_st_lookup(version_tbl, (st_data_t)&blockid, (st_data_t*)&first_version))
+        return 0;
+
+    size_t count = 0;
+
+    // For each version matching the blockid
+    for (block_t* version = first_version; version != NULL; version = version->next)
+    {
+        count += 1;
+    }
+
+    return count;
+}
+
 // Retrieve a basic block version for an (iseq, idx) tuple
 block_t* find_block_version(blockid_t blockid, const ctx_t* ctx)
 {
@@ -199,6 +224,7 @@ block_t* find_block_version(blockid_t blockid, const ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L224
 
     return best_version;
 }
+
 // Compile a new block version immediately
 block_t* gen_block_version(blockid_t blockid, const ctx_t* start_ctx)
 {
@@ -265,13 +291,12 @@ uint8_t* gen_entry_point(const rb_iseq_t *iseq, uint32_t insn_idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L291
 {
     // The entry context makes no assumptions about types
     blockid_t blockid = { iseq, insn_idx };
-    ctx_t ctx = { { 0 }, 0 };
 
     // Write the interpreter entry prologue
     uint8_t* code_ptr = ujit_entry_prologue();
 
     // Try to generate code for the entry block
-    block_t* block = gen_block_version(blockid, &ctx);
+    block_t* block = gen_block_version(blockid, &DEFAULT_CTX);
 
     // If we couldn't generate any code
     if (block->end_idx == insn_idx)
@@ -294,7 +319,7 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L319
     RUBY_ASSERT(target_idx < 2);
     branch_t *branch = &branch_entries[branch_idx];
     blockid_t target = branch->targets[target_idx];
-    ctx_t* target_ctx = &branch->target_ctxs[target_idx];
+    const ctx_t* target_ctx = &branch->target_ctxs[target_idx];
 
     //fprintf(stderr, "\nstub hit, branch idx: %d, target idx: %d\n", branch_idx, target_idx);
     //fprintf(stderr, "blockid.iseq=%p, blockid.idx=%d\n", target.iseq, target.idx);
@@ -311,6 +336,15 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L336
         RUBY_ASSERT(cb->write_pos <= branch->end_pos);
     }
 
+    // Limit the number of block versions
+    ctx_t generic_ctx = DEFAULT_CTX;
+    generic_ctx.stack_size = target_ctx->stack_size;
+    if (count_block_versions(target) >= MAX_VERSIONS - 1)
+    {
+        fprintf(stderr, "version limit hit in branch_stub_hit\n");
+        target_ctx = &generic_ctx;
+    }
+
     // Try to find a compiled version of this block
     block_t* p_block = find_block_version(target, target_ctx);
 
@@ -465,6 +499,15 @@ void gen_direct_jump( https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L499
     uint32_t start_pos;
     uint32_t end_pos;
 
+    // Limit the number of block versions
+    ctx_t generic_ctx = DEFAULT_CTX;
+    generic_ctx.stack_size = ctx->stack_size;
+    if (count_block_versions(target0) >= MAX_VERSIONS - 1)
+    {
+        fprintf(stderr, "version limit hit in branch_stub_hit\n");
+        ctx = &generic_ctx;
+    }
+
     block_t* p_block = find_block_version(target0, ctx);
 
     // If the version already exists
diff --git a/ujit_core.h b/ujit_core.h
index c86a9412dc..27f33c5e9b 100644
--- a/ujit_core.h
+++ b/ujit_core.h
@@ -17,9 +17,6 @@ https://github.com/ruby/ruby/blob/trunk/ujit_core.h#L17
 #define REG0_32 EAX
 #define REG1_32 ECX
 
-// Maximum number of versions per block
-#define MAX_VERSIONS 5
-
 // Maximum number of temp value types we keep track of
 #define MAX_TEMP_TYPES 8
 
-- 
cgit v1.2.1


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

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