Skip to content

Commit a701536

Browse files
committed
Introduce T_IMEMO/class_fields
This behave almost exactly as a T_OBJECT, the layout is entirely compatible.
1 parent 8eb497e commit a701536

15 files changed

Lines changed: 346 additions & 83 deletions

File tree

class.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ rb_class_duplicate_classext(rb_classext_t *orig, VALUE klass, const rb_namespace
298298
RCLASSEXT_M_TBL(ext) = duplicate_classext_m_tbl(RCLASSEXT_M_TBL(orig), klass, dup_iclass);
299299

300300
if (orig->fields_obj) {
301-
ext->fields_obj = rb_obj_clone(orig->fields_obj);
301+
RB_OBJ_WRITE(klass, &ext->fields_obj, rb_imemo_class_fields_clone(orig->fields_obj));
302302
}
303303

304304
if (RCLASSEXT_SHARED_CONST_TBL(orig)) {

common.mk

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4135,7 +4135,6 @@ debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
41354135
debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
41364136
debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
41374137
debug.$(OBJEXT): $(top_srcdir)/internal/namespace.h
4138-
debug.$(OBJEXT): $(top_srcdir)/internal/object.h
41394138
debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
41404139
debug.$(OBJEXT): $(top_srcdir)/internal/serial.h
41414140
debug.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -6451,7 +6450,6 @@ enumerator.$(OBJEXT): $(top_srcdir)/internal/hash.h
64516450
enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h
64526451
enumerator.$(OBJEXT): $(top_srcdir)/internal/namespace.h
64536452
enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h
6454-
enumerator.$(OBJEXT): $(top_srcdir)/internal/object.h
64556453
enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h
64566454
enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h
64576455
enumerator.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
@@ -8126,10 +8124,10 @@ imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h
81268124
imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h
81278125
imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h
81288126
imemo.$(OBJEXT): $(top_srcdir)/internal/namespace.h
8129-
imemo.$(OBJEXT): $(top_srcdir)/internal/object.h
81308127
imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
81318128
imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h
81328129
imemo.$(OBJEXT): $(top_srcdir)/internal/set_table.h
8130+
imemo.$(OBJEXT): $(top_srcdir)/internal/st.h
81338131
imemo.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
81348132
imemo.$(OBJEXT): $(top_srcdir)/internal/variable.h
81358133
imemo.$(OBJEXT): $(top_srcdir)/internal/vm.h
@@ -8952,7 +8950,6 @@ iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h
89528950
iseq.$(OBJEXT): $(top_srcdir)/internal/io.h
89538951
iseq.$(OBJEXT): $(top_srcdir)/internal/namespace.h
89548952
iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h
8955-
iseq.$(OBJEXT): $(top_srcdir)/internal/object.h
89568953
iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h
89578954
iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h
89588955
iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
@@ -9201,7 +9198,6 @@ jit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
92019198
jit.$(OBJEXT): $(top_srcdir)/internal/gc.h
92029199
jit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
92039200
jit.$(OBJEXT): $(top_srcdir)/internal/namespace.h
9204-
jit.$(OBJEXT): $(top_srcdir)/internal/object.h
92059201
jit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
92069202
jit.$(OBJEXT): $(top_srcdir)/internal/serial.h
92079203
jit.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -11059,7 +11055,6 @@ namespace.$(OBJEXT): $(top_srcdir)/internal/hash.h
1105911055
namespace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
1106011056
namespace.$(OBJEXT): $(top_srcdir)/internal/load.h
1106111057
namespace.$(OBJEXT): $(top_srcdir)/internal/namespace.h
11062-
namespace.$(OBJEXT): $(top_srcdir)/internal/object.h
1106311058
namespace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
1106411059
namespace.$(OBJEXT): $(top_srcdir)/internal/serial.h
1106511060
namespace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -11479,7 +11474,6 @@ node_dump.$(OBJEXT): $(top_srcdir)/internal/hash.h
1147911474
node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
1148011475
node_dump.$(OBJEXT): $(top_srcdir)/internal/namespace.h
1148111476
node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h
11482-
node_dump.$(OBJEXT): $(top_srcdir)/internal/object.h
1148311477
node_dump.$(OBJEXT): $(top_srcdir)/internal/parse.h
1148411478
node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h
1148511479
node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
@@ -20389,7 +20383,6 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h
2038920383
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h
2039020384
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
2039120385
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/namespace.h
20392-
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/object.h
2039320386
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
2039420387
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
2039520388
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -21068,7 +21061,6 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
2106821061
vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
2106921062
vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
2107021063
vm_trace.$(OBJEXT): $(top_srcdir)/internal/namespace.h
21071-
vm_trace.$(OBJEXT): $(top_srcdir)/internal/object.h
2107221064
vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
2107321065
vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h
2107421066
vm_trace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -21516,7 +21508,6 @@ yjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
2151621508
yjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
2151721509
yjit.$(OBJEXT): $(top_srcdir)/internal/namespace.h
2151821510
yjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
21519-
yjit.$(OBJEXT): $(top_srcdir)/internal/object.h
2152021511
yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
2152121512
yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
2152221513
yjit.$(OBJEXT): $(top_srcdir)/internal/set_table.h

ext/objspace/depend

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,6 @@ objspace.o: $(top_srcdir)/internal/gc.h
395395
objspace.o: $(top_srcdir)/internal/hash.h
396396
objspace.o: $(top_srcdir)/internal/imemo.h
397397
objspace.o: $(top_srcdir)/internal/namespace.h
398-
objspace.o: $(top_srcdir)/internal/object.h
399398
objspace.o: $(top_srcdir)/internal/sanitizers.h
400399
objspace.o: $(top_srcdir)/internal/serial.h
401400
objspace.o: $(top_srcdir)/internal/set_table.h
@@ -610,7 +609,6 @@ objspace_dump.o: $(top_srcdir)/internal/hash.h
610609
objspace_dump.o: $(top_srcdir)/internal/imemo.h
611610
objspace_dump.o: $(top_srcdir)/internal/io.h
612611
objspace_dump.o: $(top_srcdir)/internal/namespace.h
613-
objspace_dump.o: $(top_srcdir)/internal/object.h
614612
objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
615613
objspace_dump.o: $(top_srcdir)/internal/serial.h
616614
objspace_dump.o: $(top_srcdir)/internal/set_table.h

ext/objspace/objspace.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
504504
INIT_IMEMO_TYPE_ID(imemo_callinfo);
505505
INIT_IMEMO_TYPE_ID(imemo_callcache);
506506
INIT_IMEMO_TYPE_ID(imemo_constcache);
507+
INIT_IMEMO_TYPE_ID(imemo_class_fields);
507508
#undef INIT_IMEMO_TYPE_ID
508509
}
509510

gc.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,8 +1490,6 @@ internal_object_p(VALUE obj)
14901490
return rb_singleton_class_internal_p(obj);
14911491
}
14921492
return 0;
1493-
case T_OBJECT:
1494-
if (FL_TEST_RAW(obj, ROBJECT_HIDDEN)) break;
14951493
default:
14961494
if (!RBASIC(obj)->klass) break;
14971495
return 0;
@@ -3149,8 +3147,6 @@ rb_gc_mark_children(void *objspace, VALUE obj)
31493147
foreach_args.objspace = objspace;
31503148
foreach_args.obj = obj;
31513149
rb_class_classext_foreach(obj, gc_mark_classext_module, (void *)&foreach_args);
3152-
3153-
gc_mark_internal(RCLASS_PRIME_FIELDS_OBJ(obj));
31543150
break;
31553151

31563152
case T_ICLASS:

imemo.c

Lines changed: 101 additions & 2 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/st.h"
67
#include "vm_callinfo.h"
78

89
size_t rb_iseq_memsize(const rb_iseq_t *iseq);
@@ -29,10 +30,10 @@ rb_imemo_name(enum imemo_type type)
2930
IMEMO_NAME(svar);
3031
IMEMO_NAME(throw_data);
3132
IMEMO_NAME(tmpbuf);
33+
IMEMO_NAME(class_fields);
3234
#undef IMEMO_NAME
33-
default:
34-
rb_bug("unreachable");
3535
}
36+
rb_bug("unreachable");
3637
}
3738

3839
/* =========================================================================
@@ -109,6 +110,63 @@ rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt)
109110
return tmpbuf;
110111
}
111112

113+
static VALUE
114+
imemo_class_fields_new(VALUE klass, size_t capa)
115+
{
116+
size_t embedded_size = sizeof(struct rb_class_fields) + ((capa - 1) * sizeof(VALUE));
117+
if (rb_gc_size_allocatable_p(embedded_size)) {
118+
VALUE fields = rb_imemo_new(imemo_class_fields, klass, embedded_size);
119+
RUBY_ASSERT(IMEMO_TYPE_P(fields, imemo_class_fields));
120+
return fields;
121+
}
122+
else {
123+
VALUE fields = rb_imemo_new(imemo_class_fields, klass, sizeof(VALUE *));
124+
FL_SET_RAW(fields, OBJ_FIELD_EXTERNAL);
125+
IMEMO_OBJ_FIELDS(fields)->as.external.ptr = ALLOC_N(VALUE, capa);
126+
return fields;
127+
}
128+
}
129+
130+
VALUE
131+
rb_imemo_class_fields_new(VALUE klass, size_t capa)
132+
{
133+
return imemo_class_fields_new(rb_singleton_class(klass), capa);
134+
}
135+
136+
static VALUE
137+
imemo_class_fields_new_complex(VALUE klass, size_t capa)
138+
{
139+
VALUE fields = imemo_class_fields_new(klass, sizeof(struct rb_class_fields));
140+
FL_SET_RAW(fields, OBJ_FIELD_COMPLEX);
141+
IMEMO_OBJ_FIELDS(fields)->as.complex.table = st_init_numtable_with_size(capa);
142+
return fields;
143+
}
144+
145+
VALUE
146+
rb_imemo_class_fields_new_complex(VALUE klass, size_t capa)
147+
{
148+
return imemo_class_fields_new_complex(rb_singleton_class(klass), capa);
149+
}
150+
151+
VALUE
152+
rb_imemo_class_fields_clone(VALUE fields_obj)
153+
{
154+
shape_id_t shape_id = rb_obj_shape_id(fields_obj);
155+
VALUE clone;
156+
157+
if (rb_shape_too_complex_p(shape_id)) {
158+
clone = rb_imemo_class_fields_new_complex(CLASS_OF(fields_obj), 0);
159+
st_table *src_table = rb_imemo_class_fields_complex_tbl(fields_obj);
160+
st_replace(rb_imemo_class_fields_complex_tbl(clone), src_table);
161+
}
162+
else {
163+
clone = imemo_class_fields_new(CLASS_OF(fields_obj), RSHAPE(shape_id)->capacity);
164+
MEMCPY(rb_imemo_class_fields_ptr(clone), rb_imemo_class_fields_ptr(fields_obj), VALUE, RSHAPE(shape_id)->next_field_index);
165+
}
166+
167+
return clone;
168+
}
169+
112170
/* =========================================================================
113171
* memsize
114172
* ========================================================================= */
@@ -155,6 +213,14 @@ rb_imemo_memsize(VALUE obj)
155213
case imemo_tmpbuf:
156214
size += ((rb_imemo_tmpbuf_t *)obj)->cnt * sizeof(VALUE);
157215

216+
break;
217+
case imemo_class_fields:
218+
if (FL_TEST_RAW(obj, OBJ_FIELD_COMPLEX)) {
219+
size += st_memsize(IMEMO_OBJ_FIELDS(obj)->as.complex.table);
220+
}
221+
else if (FL_TEST_RAW(obj, OBJ_FIELD_EXTERNAL)) {
222+
size += RSHAPE(rb_obj_shape_id(obj))->capacity * sizeof(VALUE);
223+
}
158224
break;
159225
default:
160226
rb_bug("unreachable");
@@ -420,6 +486,23 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
420486

421487
break;
422488
}
489+
case imemo_class_fields: {
490+
struct rb_class_fields *cf = (struct rb_class_fields *)obj;
491+
rb_gc_mark_and_move(&cf->klass);
492+
493+
if (rb_shape_obj_too_complex_p(obj)) {
494+
// TODO: rb_mark_and_move_tbl
495+
rb_mark_tbl(rb_imemo_class_fields_complex_tbl(obj));
496+
}
497+
else {
498+
VALUE *fields = rb_imemo_class_fields_ptr(obj);
499+
uint32_t len = RSHAPE(rb_obj_shape_id(obj))->next_field_index;
500+
for (uint32_t i = 0; i < len; i++) {
501+
rb_gc_mark_and_move(&fields[i]);
502+
}
503+
}
504+
break;
505+
}
423506
default:
424507
rb_bug("unreachable");
425508
}
@@ -513,6 +596,17 @@ rb_cc_tbl_free(struct rb_id_table *cc_tbl, VALUE klass)
513596
rb_id_table_free(cc_tbl);
514597
}
515598

599+
static inline void
600+
imemo_class_fields_free(struct rb_class_fields *fields)
601+
{
602+
if (FL_TEST_RAW((VALUE)fields, OBJ_FIELD_COMPLEX)) {
603+
st_free_table(fields->as.complex.table);
604+
}
605+
else if (FL_TEST_RAW((VALUE)fields, OBJ_FIELD_EXTERNAL)) {
606+
xfree(fields->as.external.ptr);
607+
}
608+
}
609+
516610
void
517611
rb_imemo_free(VALUE obj)
518612
{
@@ -576,6 +670,7 @@ rb_imemo_free(VALUE obj)
576670
break;
577671
case imemo_svar:
578672
RB_DEBUG_COUNTER_INC(obj_imemo_svar);
673+
579674
break;
580675
case imemo_throw_data:
581676
RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
@@ -585,6 +680,10 @@ rb_imemo_free(VALUE obj)
585680
xfree(((rb_imemo_tmpbuf_t *)obj)->ptr);
586681
RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
587682

683+
break;
684+
case imemo_class_fields:
685+
imemo_class_fields_free(IMEMO_OBJ_FIELDS(obj));
686+
RB_DEBUG_COUNTER_INC(obj_imemo_class_fields);
588687
break;
589688
default:
590689
rb_bug("unreachable");

include/ruby/internal/core/robject.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ enum ruby_robject_flags {
7272
* store instance variables. Might better be hidden.
7373
*/
7474
ROBJECT_EMBED = RUBY_FL_USER1,
75-
76-
ROBJECT_HIDDEN = RUBY_FL_USER2, // HACK
7775
};
7876

7977
struct st_table;

internal/class.h

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
*/
1111
#include "id.h"
1212
#include "id_table.h" /* for struct rb_id_table */
13-
#include "internal/object.h" /* for rb_class_allocate_instance */
1413
#include "internal/namespace.h" /* for rb_current_namespace */
1514
#include "internal/serial.h" /* for rb_serial_t */
1615
#include "internal/static_assert.h"
@@ -257,9 +256,6 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE
257256

258257
static inline void RCLASS_SET_SUPER(VALUE klass, VALUE super);
259258
static inline void RCLASS_WRITE_SUPER(VALUE klass, VALUE super);
260-
static inline st_table * RCLASS_WRITABLE_FIELDS_HASH(VALUE obj);
261-
static inline void RCLASS_SET_FIELDS_HASH(VALUE obj, const st_table *table);
262-
static inline void RCLASS_WRITE_FIELDS_HASH(VALUE obj, const st_table *table);
263259
// TODO: rename RCLASS_SET_M_TBL_WORKAROUND (and _WRITE_) to RCLASS_SET_M_TBL with write barrier
264260
static inline void RCLASS_SET_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted);
265261
static inline void RCLASS_WRITE_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted);
@@ -535,21 +531,13 @@ RCLASS_FIELDS_OBJ(VALUE obj)
535531
return RCLASSEXT_FIELDS_OBJ(RCLASS_EXT_READABLE(obj));
536532
}
537533

538-
static inline VALUE
539-
rb_allocate_fields_obj(VALUE klass)
540-
{
541-
VALUE fields_obj = rb_class_allocate_instance(rb_singleton_class(klass));
542-
FL_SET_RAW(fields_obj, ROBJECT_HIDDEN); // HACK
543-
return fields_obj;
544-
}
545-
546534
static inline VALUE
547535
RCLASS_ENSURE_FIELDS_OBJ(VALUE obj)
548536
{
549537
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
550538
rb_classext_t *ext = RCLASS_EXT_READABLE(obj);
551539
if (!ext->fields_obj) {
552-
RB_OBJ_WRITE(obj, &ext->fields_obj, rb_allocate_fields_obj(obj));
540+
RB_OBJ_WRITE(obj, &ext->fields_obj, rb_imemo_class_fields_new(obj, 1));
553541
}
554542
return ext->fields_obj;
555543
}
@@ -562,34 +550,18 @@ RCLASS_WRITABLE_FIELDS_OBJ(VALUE obj)
562550
}
563551

564552
static inline void
565-
RCLASSEXT_SET_FIELDS_HASH(VALUE obj, rb_classext_t *ext, const st_table *tbl)
553+
RCLASSEXT_SET_FIELDS_OBJ(VALUE obj, rb_classext_t *ext, VALUE fields_obj)
566554
{
567555
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
568-
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
569-
570-
if (!ext->fields_obj) {
571-
// FIXME: We can trigger GC here and `*tbl` may not be marked
572-
RB_OBJ_WRITE(obj, &ext->fields_obj, rb_allocate_fields_obj(obj));
573-
}
574-
ROBJECT_SET_FIELDS_HASH(ext->fields_obj, tbl);
575-
}
576-
577-
static inline void
578-
RCLASS_SET_FIELDS_HASH(VALUE obj, const st_table *tbl)
579-
{
580-
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
581-
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
582-
583-
RCLASSEXT_SET_FIELDS_HASH(obj, RCLASS_EXT_PRIME(obj), tbl);
556+
RB_OBJ_WRITE(obj, &ext->fields_obj, fields_obj);
584557
}
585558

586559
static inline void
587-
RCLASS_WRITE_FIELDS_HASH(VALUE obj, const st_table *tbl)
560+
RCLASS_SET_FIELDS_OBJ(VALUE obj, VALUE fields_obj)
588561
{
589562
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
590-
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
591563

592-
RCLASSEXT_SET_FIELDS_HASH(obj, RCLASS_EXT_WRITABLE(obj), tbl);
564+
RCLASSEXT_SET_FIELDS_OBJ(obj, RCLASS_EXT_PRIME(obj), fields_obj);
593565
}
594566

595567
#define RCLASS_SET_M_TBL_EVEN_WHEN_PROMOTED(klass, table) RCLASS_SET_M_TBL_WORKAROUND(klass, table, false)

0 commit comments

Comments
 (0)