Skip to content

Commit b6bf44a

Browse files
committed
variable.c: handle cleared fields_obj in genfields cache
[Bug #21547] Followup: ruby#14201 When adding an instance variable and the IMEMO/fields need to be larger, we allocate a new one and clear the old one. Since the old one may still be in other ec's cache, on a hit we must check the IMEMO/fields isn't a stale one.
1 parent a837ec0 commit b6bf44a

File tree

4 files changed

+18
-3
lines changed

4 files changed

+18
-3
lines changed

depend

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6306,6 +6306,7 @@ imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h
63066306
imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h
63076307
imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h
63086308
imemo.$(OBJEXT): $(top_srcdir)/internal/namespace.h
6309+
imemo.$(OBJEXT): $(top_srcdir)/internal/object.h
63096310
imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
63106311
imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h
63116312
imemo.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -7159,7 +7160,6 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h
71597160
iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h
71607161
iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
71617162
iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
7162-
iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
71637163
iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h
71647164
iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
71657165
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
@@ -11676,7 +11676,6 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
1167611676
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
1167711677
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
1167811678
prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
11679-
prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
1168011679
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/ast.h
1168111680
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h
1168211681
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h

imemo.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "id_table.h"
44
#include "internal.h"
55
#include "internal/imemo.h"
6+
#include "internal/object.h"
67
#include "internal/st.h"
78
#include "vm_callinfo.h"
89

@@ -208,6 +209,8 @@ rb_imemo_fields_clear(VALUE fields_obj)
208209
else {
209210
RBASIC_SET_SHAPE_ID(fields_obj, ROOT_SHAPE_ID);
210211
}
212+
// Invalidate the ec->gen_fields_cache.
213+
RBASIC_CLEAR_CLASS(fields_obj);
211214
}
212215

213216
/* =========================================================================

test/ruby/test_variable.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,19 @@ def test_local_variables_encoding
447447
assert_equal(%i[α b], b.local_variables)
448448
end
449449

450+
def test_genivar_cache
451+
bug21547 = '[Bug #21547]'
452+
klass = Class.new(Array)
453+
instance = klass.new
454+
instance.instance_variable_set(:@a1, 1)
455+
instance.instance_variable_set(:@a2, 2)
456+
Fiber.new do
457+
instance.instance_variable_set(:@a3, 3)
458+
instance.instance_variable_set(:@a4, 4)
459+
end.resume
460+
assert_equal 4, instance.instance_variable_get(:@a4)
461+
end
462+
450463
private
451464
def with_kwargs_11(v1:, v2:, v3:, v4:, v5:, v6:, v7:, v8:, v9:, v10:, v11:)
452465
local_variables

variable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ rb_obj_fields(VALUE obj, ID field_name)
12471247
generic_fields:
12481248
{
12491249
rb_execution_context_t *ec = GET_EC();
1250-
if (ec->gen_fields_cache.obj == obj) {
1250+
if (ec->gen_fields_cache.obj == obj && rb_imemo_fields_owner(ec->gen_fields_cache.fields_obj) == obj) {
12511251
fields_obj = ec->gen_fields_cache.fields_obj;
12521252
}
12531253
else {

0 commit comments

Comments
 (0)