Skip to content

Commit 6dbe24f

Browse files
committed
Use the shape_id rather than FL_EXIVAR
We still keep setting `FL_EXIVAR` so that `rb_shape_verify_consistency` can detect discrepancies.
1 parent b51078f commit 6dbe24f

File tree

9 files changed

+54
-51
lines changed

9 files changed

+54
-51
lines changed

gc.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,7 +2070,7 @@ rb_gc_obj_free_vm_weak_references(VALUE obj)
20702070
{
20712071
obj_free_object_id(obj);
20722072

2073-
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
2073+
if (rb_obj_exivar_p(obj)) {
20742074
rb_free_generic_ivar((VALUE)obj);
20752075
}
20762076

@@ -2316,7 +2316,7 @@ rb_obj_memsize_of(VALUE obj)
23162316
return 0;
23172317
}
23182318

2319-
if (FL_TEST(obj, FL_EXIVAR)) {
2319+
if (rb_obj_exivar_p(obj)) {
23202320
size += rb_generic_ivar_memsize(obj);
23212321
}
23222322

@@ -3141,7 +3141,7 @@ rb_gc_mark_children(void *objspace, VALUE obj)
31413141
{
31423142
struct gc_mark_classext_foreach_arg foreach_args;
31433143

3144-
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
3144+
if (rb_obj_exivar_p(obj)) {
31453145
rb_mark_generic_ivar(obj);
31463146
}
31473147

@@ -4012,6 +4012,7 @@ vm_weak_table_gen_fields_foreach(st_data_t key, st_data_t value, st_data_t data)
40124012
free_gen_fields_tbl((VALUE)key, (struct gen_fields_tbl *)value);
40134013

40144014
FL_UNSET((VALUE)key, FL_EXIVAR);
4015+
RBASIC_SET_SHAPE_ID((VALUE)key, ROOT_SHAPE_ID);
40154016
return ST_DELETE;
40164017

40174018
case ST_REPLACE: {

hash.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,10 +1597,11 @@ VALUE
15971597
rb_hash_dup(VALUE hash)
15981598
{
15991599
const VALUE flags = RBASIC(hash)->flags;
1600-
VALUE ret = hash_dup(hash, rb_obj_class(hash),
1601-
flags & (FL_EXIVAR|RHASH_PROC_DEFAULT));
1602-
if (flags & FL_EXIVAR)
1600+
VALUE ret = hash_dup(hash, rb_obj_class(hash), flags & RHASH_PROC_DEFAULT);
1601+
1602+
if (rb_obj_exivar_p(hash)) {
16031603
rb_copy_generic_ivar(ret, hash);
1604+
}
16041605
return ret;
16051606
}
16061607

@@ -2920,7 +2921,7 @@ hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
29202921
VALUE
29212922
rb_hash_key_str(VALUE key)
29222923
{
2923-
if (!RB_FL_ANY_RAW(key, FL_EXIVAR) && RBASIC_CLASS(key) == rb_cString) {
2924+
if (!rb_obj_exivar_p(key) && RBASIC_CLASS(key) == rb_cString) {
29242925
return rb_fstring(key);
29252926
}
29262927
else {

object.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,9 @@ init_copy(VALUE dest, VALUE obj)
373373
if (OBJ_FROZEN(dest)) {
374374
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
375375
}
376-
RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
376+
RBASIC(dest)->flags &= ~T_MASK;
377377
// Copies the shape id from obj to dest
378-
RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR);
378+
RBASIC(dest)->flags |= RBASIC(obj)->flags & T_MASK;
379379
switch (BUILTIN_TYPE(obj)) {
380380
case T_IMEMO:
381381
rb_bug("Unreacheable");

ractor.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
16561656
else if (data->replacement != _val) { RB_OBJ_WRITE(obj, &v, data->replacement); } \
16571657
} while (0)
16581658

1659-
if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
1659+
if (UNLIKELY(rb_obj_exivar_p(obj))) {
16601660
struct gen_fields_tbl *fields_tbl;
16611661
rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl);
16621662

@@ -1885,7 +1885,7 @@ move_leave(VALUE obj, struct obj_traverse_replace_data *data)
18851885

18861886
rb_gc_obj_id_moved(data->replacement);
18871887

1888-
if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
1888+
if (UNLIKELY(rb_obj_exivar_p(obj))) {
18891889
rb_replace_generic_ivar(data->replacement, obj);
18901890
}
18911891

shape.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,10 +1267,10 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
12671267
}
12681268

12691269
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
1270-
RUBY_ASSERT(rb_obj_has_exivar(obj));
1270+
RUBY_ASSERT(rb_obj_exivar_p(obj));
12711271
}
12721272
else {
1273-
RUBY_ASSERT(!rb_obj_has_exivar(obj));
1273+
RUBY_ASSERT(!rb_obj_exivar_p(obj));
12741274
}
12751275

12761276
return true;

shape.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ rb_shape_obj_has_fields(VALUE obj)
355355
}
356356

357357
static inline bool
358-
rb_obj_has_exivar(VALUE obj)
358+
rb_obj_exivar_p(VALUE obj)
359359
{
360360
switch (TYPE(obj)) {
361361
case T_NONE:

string.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ build_fstring(VALUE str, struct fstr_update_arg *arg)
486486
RUBY_ASSERT(OBJ_FROZEN(str));
487487
RUBY_ASSERT(!FL_TEST_RAW(str, STR_FAKESTR));
488488
RUBY_ASSERT(!FL_TEST_RAW(str, FL_EXIVAR));
489+
RUBY_ASSERT(!rb_obj_exivar_p(str));
489490
RUBY_ASSERT(RBASIC_CLASS(str) == rb_cString);
490491
RUBY_ASSERT(!rb_objspace_garbage_object_p(str));
491492

variable.c

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,22 +1255,25 @@ rb_mark_generic_ivar(VALUE obj)
12551255
void
12561256
rb_free_generic_ivar(VALUE obj)
12571257
{
1258-
st_data_t key = (st_data_t)obj, value;
1258+
if (rb_obj_exivar_p(obj)) {
1259+
st_data_t key = (st_data_t)obj, value;
12591260

1260-
bool too_complex = rb_shape_obj_too_complex_p(obj);
1261+
bool too_complex = rb_shape_obj_too_complex_p(obj);
12611262

1262-
RB_VM_LOCKING() {
1263-
if (st_delete(generic_fields_tbl_no_ractor_check(obj), &key, &value)) {
1264-
struct gen_fields_tbl *fields_tbl = (struct gen_fields_tbl *)value;
1263+
RB_VM_LOCKING() {
1264+
if (st_delete(generic_fields_tbl_no_ractor_check(obj), &key, &value)) {
1265+
struct gen_fields_tbl *fields_tbl = (struct gen_fields_tbl *)value;
12651266

1266-
if (UNLIKELY(too_complex)) {
1267-
st_free_table(fields_tbl->as.complex.table);
1268-
}
1267+
if (UNLIKELY(too_complex)) {
1268+
st_free_table(fields_tbl->as.complex.table);
1269+
}
12691270

1270-
xfree(fields_tbl);
1271+
xfree(fields_tbl);
1272+
}
12711273
}
1274+
FL_UNSET_RAW(obj, FL_EXIVAR);
1275+
RBASIC_SET_SHAPE_ID(obj, ROOT_SHAPE_ID);
12721276
}
1273-
FL_UNSET_RAW(obj, FL_EXIVAR);
12741277
}
12751278

12761279
size_t
@@ -1327,6 +1330,7 @@ rb_obj_field_get(VALUE obj, shape_id_t target_shape_id)
13271330
break;
13281331
default:
13291332
RUBY_ASSERT(FL_TEST_RAW(obj, FL_EXIVAR));
1333+
RUBY_ASSERT(rb_obj_exivar_p(obj));
13301334
struct gen_fields_tbl *fields_tbl = NULL;
13311335
rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl);
13321336
RUBY_ASSERT(fields_tbl);
@@ -1358,6 +1362,7 @@ rb_obj_field_get(VALUE obj, shape_id_t target_shape_id)
13581362
break;
13591363
default:
13601364
RUBY_ASSERT(FL_TEST_RAW(obj, FL_EXIVAR));
1365+
RUBY_ASSERT(rb_obj_exivar_p(obj));
13611366
struct gen_fields_tbl *fields_tbl = NULL;
13621367
rb_ivar_generic_fields_tbl_lookup(obj, &fields_tbl);
13631368
RUBY_ASSERT(fields_tbl);
@@ -1435,7 +1440,7 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
14351440
}
14361441
default:
14371442
shape_id = RBASIC_SHAPE_ID(obj);
1438-
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
1443+
if (rb_obj_exivar_p(obj)) {
14391444
struct gen_fields_tbl *fields_tbl;
14401445
rb_gen_fields_tbl_get(obj, id, &fields_tbl);
14411446

@@ -1551,22 +1556,20 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
15511556
size_t trailing_fields = new_fields_count - removed_index;
15521557

15531558
MEMMOVE(&fields[removed_index], &fields[removed_index + 1], VALUE, trailing_fields);
1554-
1555-
if (RB_TYPE_P(obj, T_OBJECT) &&
1556-
!RB_FL_TEST_RAW(obj, ROBJECT_EMBED) &&
1557-
rb_obj_embedded_size(new_fields_count) <= rb_gc_obj_slot_size(obj)) {
1558-
// Re-embed objects when instances become small enough
1559-
// This is necessary because YJIT assumes that objects with the same shape
1560-
// have the same embeddedness for efficiency (avoid extra checks)
1561-
RB_FL_SET_RAW(obj, ROBJECT_EMBED);
1562-
MEMCPY(ROBJECT_FIELDS(obj), fields, VALUE, new_fields_count);
1563-
xfree(fields);
1564-
}
15651559
}
15661560
else {
1567-
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
1568-
rb_free_generic_ivar(obj);
1569-
}
1561+
rb_free_generic_ivar(obj);
1562+
}
1563+
1564+
if (RB_TYPE_P(obj, T_OBJECT) &&
1565+
!RB_FL_TEST_RAW(obj, ROBJECT_EMBED) &&
1566+
rb_obj_embedded_size(new_fields_count) <= rb_gc_obj_slot_size(obj)) {
1567+
// Re-embed objects when instances become small enough
1568+
// This is necessary because YJIT assumes that objects with the same shape
1569+
// have the same embeddedness for efficiency (avoid extra checks)
1570+
RB_FL_SET_RAW(obj, ROBJECT_EMBED);
1571+
MEMCPY(ROBJECT_FIELDS(obj), fields, VALUE, new_fields_count);
1572+
xfree(fields);
15701573
}
15711574
rb_obj_set_shape_id(obj, next_shape_id);
15721575

@@ -1844,13 +1847,14 @@ generic_fields_lookup_ensure_size(st_data_t *k, st_data_t *v, st_data_t u, int e
18441847
*v = (st_data_t)fields_tbl;
18451848
}
18461849

1847-
RUBY_ASSERT(FL_TEST((VALUE)*k, FL_EXIVAR));
1848-
18491850
fields_lookup->fields_tbl = fields_tbl;
18501851
if (fields_lookup->shape_id) {
18511852
rb_obj_set_shape_id(fields_lookup->obj, fields_lookup->shape_id);
18521853
}
18531854

1855+
RUBY_ASSERT(FL_TEST((VALUE)*k, FL_EXIVAR));
1856+
RUBY_ASSERT(rb_obj_exivar_p((VALUE)*k));
1857+
18541858
return ST_CONTINUE;
18551859
}
18561860

@@ -2349,8 +2353,8 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj)
23492353

23502354
rb_check_frozen(dest);
23512355

2352-
if (!FL_TEST(obj, FL_EXIVAR)) {
2353-
goto clear;
2356+
if (!rb_obj_exivar_p(obj)) {
2357+
return;
23542358
}
23552359

23562360
unsigned long src_num_ivs = rb_ivar_count(obj);
@@ -2414,11 +2418,7 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj)
24142418
return;
24152419

24162420
clear:
2417-
if (FL_TEST(dest, FL_EXIVAR)) {
2418-
rb_free_generic_ivar(dest);
2419-
FL_UNSET(dest, FL_EXIVAR);
2420-
RBASIC_SET_SHAPE_ID(dest, ROOT_SHAPE_ID);
2421-
}
2421+
rb_free_generic_ivar(dest);
24222422
}
24232423

24242424
void
@@ -2464,7 +2464,7 @@ rb_field_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
24642464
}
24652465
break;
24662466
default:
2467-
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
2467+
if (rb_obj_exivar_p(obj)) {
24682468
gen_fields_each(obj, func, arg, ivar_only);
24692469
}
24702470
break;
@@ -2500,7 +2500,7 @@ rb_ivar_count(VALUE obj)
25002500
return RBASIC_FIELDS_COUNT(fields_obj);
25012501
}
25022502
default:
2503-
if (FL_TEST(obj, FL_EXIVAR)) {
2503+
if (rb_obj_exivar_p(obj)) {
25042504
struct gen_fields_tbl *fields_tbl;
25052505

25062506
if (rb_gen_fields_tbl_get(obj, 0, &fields_tbl)) {

vm_insnhelper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
12581258
break;
12591259
}
12601260
default:
1261-
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
1261+
if (rb_obj_exivar_p(obj)) {
12621262
struct gen_fields_tbl *fields_tbl;
12631263
rb_gen_fields_tbl_get(obj, id, &fields_tbl);
12641264
ivar_list = fields_tbl->as.shape.fields;

0 commit comments

Comments
 (0)