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

ruby-changes:68491

From: nagachika <ko1@a...>
Date: Sat, 16 Oct 2021 13:56:01 +0900 (JST)
Subject: [ruby-changes:68491] a2fe4b75e4 (ruby_3_0): merge revision(s) 217df51f0e5d9824ed712a4d175f555d932e44d8: [Backport #18232]

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

From a2fe4b75e4b236ad15778c59ace63006ace53889 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Sat, 16 Oct 2021 13:26:47 +0900
Subject: merge revision(s) 217df51f0e5d9824ed712a4d175f555d932e44d8: [Backport
 #18232]

	Dump outer variables tables when dumping an iseq to binary

	This commit dumps the outer variables table when dumping an iseq to
	binary.  This fixes a case where Ractors aren't able to tell what outer
	variables belong to a lambda after the lambda is loaded via ISeq.load_from_binary

	[Bug #18232] [ruby-core:105504]
	---
	 compile.c              | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-
	 test/ruby/test_iseq.rb | 10 +++++++++
	 2 files changed, 64 insertions(+), 1 deletion(-)
---
 compile.c              | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-
 test/ruby/test_iseq.rb | 10 +++++++++
 version.h              |  4 ++--
 3 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/compile.c b/compile.c
index 502d12d6c7..9844c145bc 100644
--- a/compile.c
+++ b/compile.c
@@ -9917,7 +9917,7 @@ typedef unsigned int ibf_offset_t; https://github.com/ruby/ruby/blob/trunk/compile.c#L9917
 
 #define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
 #if RUBY_DEVEL
-#define IBF_DEVEL_VERSION 2
+#define IBF_DEVEL_VERSION 3
 #define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
 #else
 #define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
@@ -10751,6 +10751,33 @@ ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L10751
     return offset;
 }
 
+static enum rb_id_table_iterator_result
+dump_outer_variable(ID id, VALUE val, void *dump)
+{
+    ibf_dump_write_small_value(dump, ibf_dump_id(dump, id));
+    ibf_dump_write_small_value(dump, val);
+
+    return ID_TABLE_CONTINUE;
+}
+
+static ibf_offset_t
+ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq)
+{
+    struct rb_id_table * ovs = iseq->body->outer_variables;
+
+    ibf_offset_t offset = ibf_dump_pos(dump);
+
+    if (ovs) {
+        ibf_dump_write_small_value(dump, (VALUE)rb_id_table_size(ovs));
+        rb_id_table_foreach(ovs, dump_outer_variable, (void *)dump);
+    }
+    else {
+        ibf_dump_write_small_value(dump, (VALUE)0);
+    }
+
+    return offset;
+}
+
 /* note that we dump out rb_call_info but load back rb_call_data */
 static void
 ibf_load_ci_entries(const struct ibf_load *load,
@@ -10795,6 +10822,28 @@ ibf_load_ci_entries(const struct ibf_load *load, https://github.com/ruby/ruby/blob/trunk/compile.c#L10822
     }
 }
 
+static struct rb_id_table *
+ibf_load_outer_variables(const struct ibf_load * load, ibf_offset_t outer_variables_offset)
+{
+    ibf_offset_t reading_pos = outer_variables_offset;
+
+    struct rb_id_table *tbl = NULL;
+
+    size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos);
+
+    if (table_size > 0) {
+        tbl = rb_id_table_create(table_size);
+    }
+
+    for (size_t i = 0; i < table_size; i++) {
+        ID key = ibf_load_id(load, (ID)ibf_load_small_value(load, &reading_pos));
+        VALUE value = ibf_load_small_value(load, &reading_pos);
+        rb_id_table_insert(tbl, key, value);
+    }
+
+    return tbl;
+}
+
 static ibf_offset_t
 ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
 {
@@ -10834,6 +10883,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L10883
     const int parent_iseq_index =           ibf_dump_iseq(dump, iseq->body->parent_iseq);
     const int local_iseq_index =            ibf_dump_iseq(dump, iseq->body->local_iseq);
     const ibf_offset_t ci_entries_offset =  ibf_dump_ci_entries(dump, iseq);
+    const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
 
 #if IBF_ISEQ_ENABLE_LOCAL_BUFFER
     ibf_offset_t local_obj_list_offset;
@@ -10895,6 +10945,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L10945
     ibf_dump_write_small_value(dump, parent_iseq_index);
     ibf_dump_write_small_value(dump, local_iseq_index);
     ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset));
+    ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset));
     ibf_dump_write_small_value(dump, body->variable.flip_count);
     ibf_dump_write_small_value(dump, body->local_table_size);
     ibf_dump_write_small_value(dump, body->is_size);
@@ -11001,6 +11052,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) https://github.com/ruby/ruby/blob/trunk/compile.c#L11052
     const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
     const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
     const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
+    const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
     const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos);
     const unsigned int local_table_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
     const unsigned int is_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
@@ -11050,6 +11102,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) https://github.com/ruby/ruby/blob/trunk/compile.c#L11102
 
     load_body->is_entries           = ZALLOC_N(union iseq_inline_storage_entry, is_size);
                                       ibf_load_ci_entries(load, ci_entries_offset, ci_size, &load_body->call_data);
+    load_body->outer_variables      = ibf_load_outer_variables(load, outer_variables_offset);
     load_body->param.opt_table      = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
     load_body->param.keyword        = ibf_load_param_keyword(load, param_keyword_offset);
     load_body->param.flags.has_kw   = (param_flags >> 4) & 1;
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index e3ca1ba926..08340c662c 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -82,6 +82,16 @@ class TestISeq < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_iseq.rb#L82
     end;
   end if defined?(RubyVM::InstructionSequence.load)
 
+  def test_lambda_with_ractor_roundtrip
+    iseq = compile(<<~EOF)
+      x = 42
+      y = lambda { x }
+      Ractor.make_shareable(y)
+      y.call
+    EOF
+    assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+  end
+
   def test_disasm_encoding
     src = "\u{3042} = 1; \u{3042}; \u{3043}"
     asm = compile(src).disasm
diff --git a/version.h b/version.h
index 0f6d8b6c05..1e1725ea88 100644
--- a/version.h
+++ b/version.h
@@ -12,11 +12,11 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L12
 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 #define RUBY_VERSION_TEENY 3
 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 143
+#define RUBY_PATCHLEVEL 144
 
 #define RUBY_RELEASE_YEAR 2021
 #define RUBY_RELEASE_MONTH 10
-#define RUBY_RELEASE_DAY 9
+#define RUBY_RELEASE_DAY 16
 
 #include "ruby/version.h"
 
-- 
cgit v1.2.1


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

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