Skip to content

Commit 07ad5fc

Browse files
committed
Introduce T_IMEMO/class_fields
This behave almost exactly as a T_OBJECT, the layout is entirely compatible.
1 parent 989bce8 commit 07ad5fc

14 files changed

Lines changed: 336 additions & 77 deletions

File tree

class.c

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

320320
if (orig->fields_obj) {
321-
ext->fields_obj = rb_obj_clone(orig->fields_obj);
321+
RB_OBJ_WRITE(klass, &ext->fields_obj, rb_imemo_class_fields_clone(orig->fields_obj));
322322
}
323323

324324
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
@@ -20388,7 +20382,6 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h
2038820382
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h
2038920383
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
2039020384
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/namespace.h
20391-
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/object.h
2039220385
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
2039320386
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
2039420387
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -21067,7 +21060,6 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
2106721060
vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
2106821061
vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
2106921062
vm_trace.$(OBJEXT): $(top_srcdir)/internal/namespace.h
21070-
vm_trace.$(OBJEXT): $(top_srcdir)/internal/object.h
2107121063
vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
2107221064
vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h
2107321065
vm_trace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
@@ -21515,7 +21507,6 @@ yjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
2151521507
yjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
2151621508
yjit.$(OBJEXT): $(top_srcdir)/internal/namespace.h
2151721509
yjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
21518-
yjit.$(OBJEXT): $(top_srcdir)/internal/object.h
2151921510
yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
2152021511
yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
2152121512
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

gc.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,8 +1486,6 @@ internal_object_p(VALUE obj)
14861486
return rb_singleton_class_internal_p(obj);
14871487
}
14881488
return 0;
1489-
case T_OBJECT:
1490-
if (FL_TEST_RAW(obj, ROBJECT_HIDDEN)) break;
14911489
default:
14921490
if (!RBASIC(obj)->klass) break;
14931491
return 0;

imemo.c

Lines changed: 100 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+
rb_shape_t *shape = rb_obj_shape(fields_obj);
155+
VALUE clone;
156+
157+
if (rb_shape_too_complex_p(shape)) {
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), shape->capacity);
164+
MEMCPY(rb_imemo_class_fields_ptr(clone), rb_imemo_class_fields_ptr(fields_obj), VALUE, shape->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 += 0; // TODO: Get record the size
223+
}
158224
break;
159225
default:
160226
rb_bug("unreachable");
@@ -420,6 +486,22 @@ 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+
rb_mark_tbl_no_pin(rb_imemo_class_fields_complex_tbl(obj));
495+
}
496+
else {
497+
VALUE *fields = rb_imemo_class_fields_ptr(obj);
498+
uint32_t len = RSHAPE(rb_obj_shape_id(obj))->next_field_index;
499+
for (uint32_t i = 0; i < len; i++) {
500+
rb_gc_mark_and_move(&fields[i]);
501+
}
502+
}
503+
break;
504+
}
423505
default:
424506
rb_bug("unreachable");
425507
}
@@ -513,6 +595,17 @@ rb_cc_tbl_free(struct rb_id_table *cc_tbl, VALUE klass)
513595
rb_id_table_free(cc_tbl);
514596
}
515597

598+
static inline void
599+
imemo_class_fields_free(struct rb_class_fields *fields)
600+
{
601+
if (FL_TEST_RAW((VALUE)fields, OBJ_FIELD_COMPLEX)) {
602+
st_free_table(fields->as.complex.table);
603+
}
604+
else if (FL_TEST_RAW((VALUE)fields, OBJ_FIELD_EXTERNAL)) {
605+
xfree(fields->as.external.ptr);
606+
}
607+
}
608+
516609
void
517610
rb_imemo_free(VALUE obj)
518611
{
@@ -576,6 +669,7 @@ rb_imemo_free(VALUE obj)
576669
break;
577670
case imemo_svar:
578671
RB_DEBUG_COUNTER_INC(obj_imemo_svar);
672+
579673
break;
580674
case imemo_throw_data:
581675
RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
@@ -585,6 +679,10 @@ rb_imemo_free(VALUE obj)
585679
xfree(((rb_imemo_tmpbuf_t *)obj)->ptr);
586680
RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
587681

682+
break;
683+
case imemo_class_fields:
684+
imemo_class_fields_free(IMEMO_OBJ_FIELDS(obj));
685+
RB_DEBUG_COUNTER_INC(obj_imemo_class_fields);
588686
break;
589687
default:
590688
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 & 31 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"
@@ -258,8 +257,6 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE
258257
static inline void RCLASS_SET_SUPER(VALUE klass, VALUE super);
259258
static inline void RCLASS_WRITE_SUPER(VALUE klass, VALUE super);
260259
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);
263260
// TODO: rename RCLASS_SET_M_TBL_WORKAROUND (and _WRITE_) to RCLASS_SET_M_TBL with write barrier
264261
static inline void RCLASS_SET_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted);
265262
static inline void RCLASS_WRITE_M_TBL_WORKAROUND(VALUE klass, struct rb_id_table *table, bool check_promoted);
@@ -538,21 +535,13 @@ RCLASS_FIELDS_OBJ(VALUE obj)
538535
return RCLASSEXT_FIELDS_OBJ(RCLASS_EXT_READABLE(obj));
539536
}
540537

541-
static inline VALUE
542-
rb_allocate_fields_obj(VALUE klass)
543-
{
544-
VALUE fields_obj = rb_class_allocate_instance(rb_singleton_class(klass));
545-
FL_SET_RAW(fields_obj, ROBJECT_HIDDEN); // HACK
546-
return fields_obj;
547-
}
548-
549538
static inline VALUE
550539
RCLASS_ENSURE_FIELDS_OBJ(VALUE obj)
551540
{
552541
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
553542
rb_classext_t *ext = RCLASS_EXT_READABLE(obj);
554543
if (!ext->fields_obj) {
555-
RB_OBJ_WRITE(obj, &ext->fields_obj, rb_allocate_fields_obj(obj));
544+
RB_OBJ_WRITE(obj, &ext->fields_obj, rb_imemo_class_fields_new(obj, 1));
556545
}
557546
return ext->fields_obj;
558547
}
@@ -565,33 +554,18 @@ RCLASS_WRITABLE_FIELDS_OBJ(VALUE obj)
565554
}
566555

567556
static inline void
568-
RCLASSEXT_SET_FIELDS_HASH(VALUE obj, rb_classext_t *ext, const st_table *tbl)
557+
RCLASSEXT_SET_FIELDS_OBJ(VALUE obj, rb_classext_t *ext, VALUE fields_obj)
569558
{
570559
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
571-
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
572-
573-
if (!ext->fields_obj) {
574-
// FIXME: We can trigger GC here and `*tbl` may not be marked
575-
RB_OBJ_WRITE(obj, &ext->fields_obj, rb_allocate_fields_obj(obj));
576-
}
577-
ROBJECT_SET_FIELDS_HASH(ext->fields_obj, tbl);
560+
RB_OBJ_WRITE(obj, &ext->fields_obj, fields_obj);
578561
}
579562

580563
static inline void
581-
RCLASS_SET_FIELDS_HASH(VALUE obj, const st_table *tbl)
564+
RCLASS_SET_FIELDS_OBJ(VALUE obj, VALUE fields_obj)
582565
{
583566
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
584-
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
585-
586-
RCLASSEXT_SET_FIELDS_HASH(obj, RCLASS_EXT_PRIME(obj), tbl);
587-
}
588567

589-
static inline void
590-
RCLASS_WRITE_FIELDS_HASH(VALUE obj, const st_table *tbl)
591-
{
592-
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
593-
RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
594-
RCLASSEXT_SET_FIELDS_HASH(obj, RCLASS_EXT_WRITABLE(obj), tbl);
568+
RCLASSEXT_SET_FIELDS_OBJ(obj, RCLASS_EXT_PRIME(obj), fields_obj);
595569
}
596570

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

0 commit comments

Comments
 (0)