Skip to content

Commit ad63b66

Browse files
jemmaissrofftenderlove
authored andcommitted
Revert "Revert "This commit implements the Object Shapes technique in CRuby.""
This reverts commit 9a6803c.
1 parent 5ffbb2b commit ad63b66

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2298
-880
lines changed

bootstraptest/test_attr.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,19 @@ class A
3434
print "ok"
3535
end
3636
}, '[ruby-core:15120]'
37+
38+
assert_equal %{ok}, %{
39+
class Big
40+
attr_reader :foo
41+
def initialize
42+
@foo = "ok"
43+
end
44+
end
45+
46+
obj = Big.new
47+
100.times do |i|
48+
obj.instance_variable_set(:"@ivar_\#{i}", i)
49+
end
50+
51+
Big.new.foo
52+
}

common.mk

Lines changed: 322 additions & 0 deletions
Large diffs are not rendered by default.

compile.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,20 +2058,7 @@ cdhash_set_label_i(VALUE key, VALUE val, VALUE ptr)
20582058
static inline VALUE
20592059
get_ivar_ic_value(rb_iseq_t *iseq,ID id)
20602060
{
2061-
VALUE val;
2062-
struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
2063-
if (tbl) {
2064-
if (rb_id_table_lookup(tbl,id,&val)) {
2065-
return val;
2066-
}
2067-
}
2068-
else {
2069-
tbl = rb_id_table_create(1);
2070-
ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
2071-
}
2072-
val = INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
2073-
rb_id_table_insert(tbl,id,val);
2074-
return val;
2061+
return INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
20752062
}
20762063

20772064
static inline VALUE
@@ -2472,9 +2459,13 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
24722459
generated_iseq[code_index + 1 + j] = (VALUE)ic;
24732460
}
24742461
break;
2462+
case TS_IVC: /* inline ivar cache */
2463+
{
2464+
unsigned int ic_index = FIX2UINT(operands[j]);
2465+
vm_ic_attr_index_initialize(((IVC)&body->is_entries[ic_index]), INVALID_SHAPE_ID);
2466+
}
24752467
case TS_ISE: /* inline storage entry: `once` insn */
24762468
case TS_ICVARC: /* inline cvar cache */
2477-
case TS_IVC: /* inline ivar cache */
24782469
{
24792470
unsigned int ic_index = FIX2UINT(operands[j]);
24802471
IC ic = &ISEQ_IS_ENTRY_START(body, type)[ic_index].ic_cache;
@@ -11514,6 +11505,11 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
1151411505

1151511506
ISE ic = ISEQ_IS_ENTRY_START(load_body, operand_type) + op;
1151611507
code[code_index] = (VALUE)ic;
11508+
11509+
if (operand_type == TS_IVC) {
11510+
vm_ic_attr_index_initialize(((IVC)code[code_index]), INVALID_SHAPE_ID);
11511+
}
11512+
1151711513
}
1151811514
break;
1151911515
case TS_CALLDATA:

debug_counter.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ RB_DEBUG_COUNTER(frame_C2R)
130130
/* instance variable counts
131131
*
132132
* * ivar_get_ic_hit/miss: ivar_get inline cache (ic) hit/miss counts (VM insn)
133-
* * ivar_get_ic_miss_serial: ivar_get ic miss reason by serial (VM insn)
134133
* * ivar_get_ic_miss_unset: ... by unset (VM insn)
135134
* * ivar_get_ic_miss_noobject: ... by "not T_OBJECT" (VM insn)
136135
* * ivar_set_...: same counts with ivar_set (VM insn)
@@ -140,17 +139,17 @@ RB_DEBUG_COUNTER(frame_C2R)
140139
*/
141140
RB_DEBUG_COUNTER(ivar_get_ic_hit)
142141
RB_DEBUG_COUNTER(ivar_get_ic_miss)
143-
RB_DEBUG_COUNTER(ivar_get_ic_miss_serial)
144-
RB_DEBUG_COUNTER(ivar_get_ic_miss_unset)
145142
RB_DEBUG_COUNTER(ivar_get_ic_miss_noobject)
146143
RB_DEBUG_COUNTER(ivar_set_ic_hit)
147144
RB_DEBUG_COUNTER(ivar_set_ic_miss)
148-
RB_DEBUG_COUNTER(ivar_set_ic_miss_serial)
149-
RB_DEBUG_COUNTER(ivar_set_ic_miss_unset)
150145
RB_DEBUG_COUNTER(ivar_set_ic_miss_iv_hit)
151146
RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject)
152147
RB_DEBUG_COUNTER(ivar_get_base)
153148
RB_DEBUG_COUNTER(ivar_set_base)
149+
RB_DEBUG_COUNTER(ivar_get_ic_miss_set)
150+
RB_DEBUG_COUNTER(ivar_get_cc_miss_set)
151+
RB_DEBUG_COUNTER(ivar_get_ic_miss_unset)
152+
RB_DEBUG_COUNTER(ivar_get_cc_miss_unset)
154153

155154
/* local variable counts
156155
*

ext/coverage/depend

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,9 @@ coverage.o: $(top_srcdir)/ccan/check_type/check_type.h
165165
coverage.o: $(top_srcdir)/ccan/container_of/container_of.h
166166
coverage.o: $(top_srcdir)/ccan/list/list.h
167167
coverage.o: $(top_srcdir)/ccan/str/str.h
168+
coverage.o: $(top_srcdir)/constant.h
168169
coverage.o: $(top_srcdir)/gc.h
170+
coverage.o: $(top_srcdir)/id_table.h
169171
coverage.o: $(top_srcdir)/internal.h
170172
coverage.o: $(top_srcdir)/internal/array.h
171173
coverage.o: $(top_srcdir)/internal/compilers.h
@@ -176,12 +178,14 @@ coverage.o: $(top_srcdir)/internal/sanitizers.h
176178
coverage.o: $(top_srcdir)/internal/serial.h
177179
coverage.o: $(top_srcdir)/internal/static_assert.h
178180
coverage.o: $(top_srcdir)/internal/thread.h
181+
coverage.o: $(top_srcdir)/internal/variable.h
179182
coverage.o: $(top_srcdir)/internal/vm.h
180183
coverage.o: $(top_srcdir)/internal/warnings.h
181184
coverage.o: $(top_srcdir)/method.h
182185
coverage.o: $(top_srcdir)/node.h
183186
coverage.o: $(top_srcdir)/ruby_assert.h
184187
coverage.o: $(top_srcdir)/ruby_atomic.h
188+
coverage.o: $(top_srcdir)/shape.h
185189
coverage.o: $(top_srcdir)/thread_pthread.h
186190
coverage.o: $(top_srcdir)/vm_core.h
187191
coverage.o: $(top_srcdir)/vm_opts.h

ext/objspace/depend

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ objspace.o: $(top_srcdir)/internal/serial.h
350350
objspace.o: $(top_srcdir)/internal/static_assert.h
351351
objspace.o: $(top_srcdir)/internal/warnings.h
352352
objspace.o: $(top_srcdir)/node.h
353+
objspace.o: $(top_srcdir)/shape.h
353354
objspace.o: $(top_srcdir)/symbol.h
354355
objspace.o: objspace.c
355356
objspace.o: {$(VPATH)}id.h
@@ -533,7 +534,9 @@ objspace_dump.o: $(top_srcdir)/ccan/check_type/check_type.h
533534
objspace_dump.o: $(top_srcdir)/ccan/container_of/container_of.h
534535
objspace_dump.o: $(top_srcdir)/ccan/list/list.h
535536
objspace_dump.o: $(top_srcdir)/ccan/str/str.h
537+
objspace_dump.o: $(top_srcdir)/constant.h
536538
objspace_dump.o: $(top_srcdir)/gc.h
539+
objspace_dump.o: $(top_srcdir)/id_table.h
537540
objspace_dump.o: $(top_srcdir)/internal.h
538541
objspace_dump.o: $(top_srcdir)/internal/array.h
539542
objspace_dump.o: $(top_srcdir)/internal/compilers.h
@@ -544,12 +547,14 @@ objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
544547
objspace_dump.o: $(top_srcdir)/internal/serial.h
545548
objspace_dump.o: $(top_srcdir)/internal/static_assert.h
546549
objspace_dump.o: $(top_srcdir)/internal/string.h
550+
objspace_dump.o: $(top_srcdir)/internal/variable.h
547551
objspace_dump.o: $(top_srcdir)/internal/vm.h
548552
objspace_dump.o: $(top_srcdir)/internal/warnings.h
549553
objspace_dump.o: $(top_srcdir)/method.h
550554
objspace_dump.o: $(top_srcdir)/node.h
551555
objspace_dump.o: $(top_srcdir)/ruby_assert.h
552556
objspace_dump.o: $(top_srcdir)/ruby_atomic.h
557+
objspace_dump.o: $(top_srcdir)/shape.h
553558
objspace_dump.o: $(top_srcdir)/thread_pthread.h
554559
objspace_dump.o: $(top_srcdir)/vm_core.h
555560
objspace_dump.o: $(top_srcdir)/vm_opts.h

gc.c

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,8 +2895,7 @@ rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected)
28952895
GC_ASSERT((flags & RUBY_T_MASK) == T_OBJECT);
28962896
GC_ASSERT(flags & ROBJECT_EMBED);
28972897

2898-
st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass);
2899-
uint32_t index_tbl_num_entries = index_tbl == NULL ? 0 : (uint32_t)index_tbl->num_entries;
2898+
uint32_t index_tbl_num_entries = RCLASS_EXT(klass)->max_iv_count;
29002899

29012900
size_t size;
29022901
bool embed = true;
@@ -2931,7 +2930,7 @@ rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected)
29312930
#endif
29322931
}
29332932
else {
2934-
rb_init_iv_list(obj);
2933+
rb_ensure_iv_list_size(obj, 0, index_tbl_num_entries);
29352934
}
29362935

29372936
return obj;
@@ -3206,20 +3205,6 @@ rb_free_const_table(struct rb_id_table *tbl)
32063205
rb_id_table_free(tbl);
32073206
}
32083207

3209-
static int
3210-
free_iv_index_tbl_free_i(st_data_t key, st_data_t value, st_data_t data)
3211-
{
3212-
xfree((void *)value);
3213-
return ST_CONTINUE;
3214-
}
3215-
3216-
static void
3217-
iv_index_tbl_free(struct st_table *tbl)
3218-
{
3219-
st_foreach(tbl, free_iv_index_tbl_free_i, 0);
3220-
st_free_table(tbl);
3221-
}
3222-
32233208
// alive: if false, target pointers can be freed already.
32243209
// To check it, we need objspace parameter.
32253210
static void
@@ -3435,6 +3420,16 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
34353420
RB_DEBUG_COUNTER_INC(obj_obj_transient);
34363421
}
34373422
else {
3423+
rb_shape_t *shape = rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj));
3424+
if (shape) {
3425+
VALUE klass = RBASIC_CLASS(obj);
3426+
3427+
// Increment max_iv_count if applicable, used to determine size pool allocation
3428+
uint32_t num_of_ivs = shape->iv_count;
3429+
if (RCLASS_EXT(klass)->max_iv_count < num_of_ivs) {
3430+
RCLASS_EXT(klass)->max_iv_count = num_of_ivs;
3431+
}
3432+
}
34383433
xfree(RANY(obj)->as.object.as.heap.ivptr);
34393434
RB_DEBUG_COUNTER_INC(obj_obj_ptr);
34403435
}
@@ -3449,9 +3444,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
34493444
if (RCLASS_CONST_TBL(obj)) {
34503445
rb_free_const_table(RCLASS_CONST_TBL(obj));
34513446
}
3452-
if (RCLASS_IV_INDEX_TBL(obj)) {
3453-
iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj));
3454-
}
34553447
if (RCLASS_CVC_TBL(obj)) {
34563448
rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL);
34573449
rb_id_table_free(RCLASS_CVC_TBL(obj));
@@ -4873,10 +4865,6 @@ obj_memsize_of(VALUE obj, int use_all_types)
48734865
if (RCLASS_CVC_TBL(obj)) {
48744866
size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
48754867
}
4876-
if (RCLASS_IV_INDEX_TBL(obj)) {
4877-
// TODO: more correct value
4878-
size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
4879-
}
48804868
if (RCLASS_EXT(obj)->iv_tbl) {
48814869
size += st_memsize(RCLASS_EXT(obj)->iv_tbl);
48824870
}
@@ -10408,27 +10396,13 @@ update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry)
1040810396
}
1040910397
}
1041010398

10411-
static int
10412-
update_iv_index_tbl_i(st_data_t key, st_data_t value, st_data_t arg)
10413-
{
10414-
rb_objspace_t *objspace = (rb_objspace_t *)arg;
10415-
struct rb_iv_index_tbl_entry *ent = (struct rb_iv_index_tbl_entry *)value;
10416-
UPDATE_IF_MOVED(objspace, ent->class_value);
10417-
return ST_CONTINUE;
10418-
}
10419-
1042010399
static void
1042110400
update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext)
1042210401
{
1042310402
UPDATE_IF_MOVED(objspace, ext->origin_);
1042410403
UPDATE_IF_MOVED(objspace, ext->includer);
1042510404
UPDATE_IF_MOVED(objspace, ext->refined_class);
1042610405
update_subclass_entries(objspace, ext->subclasses);
10427-
10428-
// ext->iv_index_tbl
10429-
if (ext->iv_index_tbl) {
10430-
st_foreach(ext->iv_index_tbl, update_iv_index_tbl_i, (st_data_t)objspace);
10431-
}
1043210406
}
1043310407

1043410408
static void

include/ruby/internal/core/robject.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
#define ROBJECT_EMBED ROBJECT_EMBED
4747
#define ROBJECT_NUMIV ROBJECT_NUMIV
4848
#define ROBJECT_IVPTR ROBJECT_IVPTR
49-
#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL
5049
/** @endcond */
5150

5251
/**
@@ -132,7 +131,7 @@ struct RObject {
132131
*
133132
* This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`.
134133
*/
135-
struct st_table *iv_index_tbl;
134+
struct rb_id_table *iv_index_tbl;
136135
} heap;
137136

138137
#if USE_RVARGC

include/ruby/internal/fl_type.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -941,21 +941,8 @@ RB_OBJ_FREEZE_RAW(VALUE obj)
941941
RB_FL_SET_RAW(obj, RUBY_FL_FREEZE);
942942
}
943943

944-
/**
945-
* Prevents further modifications to the given object. ::rb_eFrozenError shall
946-
* be raised if modification is attempted.
947-
*
948-
* @param[out] x Object in question.
949-
*/
950-
static inline void
951-
rb_obj_freeze_inline(VALUE x)
952-
{
953-
if (RB_FL_ABLE(x)) {
954-
RB_OBJ_FREEZE_RAW(x);
955-
if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) {
956-
rb_freeze_singleton_class(x);
957-
}
958-
}
959-
}
944+
RUBY_SYMBOL_EXPORT_BEGIN
945+
void rb_obj_freeze_inline(VALUE obj);
946+
RUBY_SYMBOL_EXPORT_END
960947

961948
#endif /* RBIMPL_FL_TYPE_H */

inits.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ rb_call_inits(void)
7777
CALL(vm_stack_canary);
7878
CALL(ast);
7979
CALL(gc_stress);
80+
CALL(shape);
8081

8182
// enable builtin loading
8283
CALL(builtin);

0 commit comments

Comments
 (0)