summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2022-09-26 16:09:50 -0700
committerAaron Patterson <tenderlove@ruby-lang.org>2022-09-26 16:10:11 -0700
commit06abfa5be60e589052eb3bdfdae6c132bea3d20b (patch)
tree32200df9a517d30a92dfe1003057e03cfba44701
parentb39690df3a90a838cdb2de71e70a20651ebafaf4 (diff)
Revert this until we can figure out WB issues or remove shapes from GC
Revert "* expand tabs. [ci skip]" This reverts commit 830b5b5c351c5c6efa5ad461ae4ec5085e5f0275. Revert "This commit implements the Object Shapes technique in CRuby." This reverts commit 9ddfd2ca004d1952be79cf1b84c52c79a55978f4.
-rw-r--r--bootstraptest/test_attr.rb16
-rw-r--r--common.mk322
-rw-r--r--compile.c26
-rw-r--r--debug_counter.h10
-rw-r--r--ext/coverage/depend4
-rw-r--r--ext/objspace/depend5
-rw-r--r--ext/objspace/objspace.c1
-rw-r--r--gc.c215
-rw-r--r--include/ruby/internal/core/robject.h3
-rw-r--r--include/ruby/internal/fl_type.h19
-rw-r--r--inits.c1
-rw-r--r--internal.h3
-rw-r--r--internal/class.h11
-rw-r--r--internal/imemo.h1
-rw-r--r--internal/object.h22
-rw-r--r--internal/variable.h5
-rw-r--r--iseq.c16
-rw-r--r--lib/mjit/compiler.rb117
-rw-r--r--marshal.c10
-rwxr-xr-xmisc/lldb_cruby.py6
-rw-r--r--mjit_c.rb37
-rw-r--r--mjit_compiler.h2
-rw-r--r--object.c46
-rw-r--r--ractor_core.h6
-rw-r--r--shape.c571
-rw-r--r--shape.h153
-rw-r--r--spec/ruby/library/objectspace/reachable_objects_from_spec.rb2
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb11
-rw-r--r--test/-ext-/marshal/test_internal_ivar.rb1
-rw-r--r--test/objspace/test_objspace.rb14
-rw-r--r--test/ruby/test_mjit.rb4
-rw-r--r--test/ruby/test_shapes.rb171
-rwxr-xr-xtool/mjit/bindgen.rb10
-rw-r--r--variable.c752
-rw-r--r--variable.h10
-rw-r--r--vm.c45
-rw-r--r--vm_callinfo.h108
-rw-r--r--vm_core.h11
-rw-r--r--vm_eval.c4
-rw-r--r--vm_insnhelper.c490
-rw-r--r--yjit/bindgen/src/main.rs7
-rw-r--r--yjit/src/asm/x86_64/mod.rs2
-rw-r--r--yjit/src/codegen.rs135
-rw-r--r--yjit/src/cruby.rs12
-rw-r--r--yjit/src/cruby_bindings.inc.rs41
45 files changed, 928 insertions, 2530 deletions
diff --git a/bootstraptest/test_attr.rb b/bootstraptest/test_attr.rb
index 3cb9d3eb39..721a847145 100644
--- a/bootstraptest/test_attr.rb
+++ b/bootstraptest/test_attr.rb
@@ -34,19 +34,3 @@ assert_equal %{ok}, %{
print "ok"
end
}, '[ruby-core:15120]'
-
-assert_equal %{ok}, %{
- class Big
- attr_reader :foo
- def initialize
- @foo = "ok"
- end
- end
-
- obj = Big.new
- 100.times do |i|
- obj.instance_variable_set(:"@ivar_\#{i}", i)
- end
-
- Big.new.foo
-}
diff --git a/common.mk b/common.mk
index cfcd6bd5a0..150add3026 100644
--- a/common.mk
+++ b/common.mk
@@ -136,7 +136,6 @@ COMMONOBJS = array.$(OBJEXT) \
regsyntax.$(OBJEXT) \
ruby.$(OBJEXT) \
scheduler.$(OBJEXT) \
- shape.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
st.$(OBJEXT) \
@@ -1833,7 +1832,6 @@ array.$(OBJEXT): $(top_srcdir)/internal/proc.h
array.$(OBJEXT): $(top_srcdir)/internal/rational.h
array.$(OBJEXT): $(top_srcdir)/internal/serial.h
array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-array.$(OBJEXT): $(top_srcdir)/internal/variable.h
array.$(OBJEXT): $(top_srcdir)/internal/vm.h
array.$(OBJEXT): $(top_srcdir)/internal/warnings.h
array.$(OBJEXT): {$(VPATH)}array.c
@@ -1850,7 +1848,6 @@ array.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
array.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
array.$(OBJEXT): {$(VPATH)}builtin.h
array.$(OBJEXT): {$(VPATH)}config.h
-array.$(OBJEXT): {$(VPATH)}constant.h
array.$(OBJEXT): {$(VPATH)}debug_counter.h
array.$(OBJEXT): {$(VPATH)}defines.h
array.$(OBJEXT): {$(VPATH)}encoding.h
@@ -2013,7 +2010,6 @@ array.$(OBJEXT): {$(VPATH)}oniguruma.h
array.$(OBJEXT): {$(VPATH)}probes.dmyh
array.$(OBJEXT): {$(VPATH)}probes.h
array.$(OBJEXT): {$(VPATH)}ruby_assert.h
-array.$(OBJEXT): {$(VPATH)}shape.h
array.$(OBJEXT): {$(VPATH)}st.h
array.$(OBJEXT): {$(VPATH)}subst.h
array.$(OBJEXT): {$(VPATH)}transient_heap.h
@@ -2032,7 +2028,6 @@ ast.$(OBJEXT): $(top_srcdir)/internal/parse.h
ast.$(OBJEXT): $(top_srcdir)/internal/serial.h
ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-ast.$(OBJEXT): $(top_srcdir)/internal/variable.h
ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ast.$(OBJEXT): {$(VPATH)}assert.h
@@ -2050,11 +2045,9 @@ ast.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ast.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ast.$(OBJEXT): {$(VPATH)}builtin.h
ast.$(OBJEXT): {$(VPATH)}config.h
-ast.$(OBJEXT): {$(VPATH)}constant.h
ast.$(OBJEXT): {$(VPATH)}defines.h
ast.$(OBJEXT): {$(VPATH)}encoding.h
ast.$(OBJEXT): {$(VPATH)}id.h
-ast.$(OBJEXT): {$(VPATH)}id_table.h
ast.$(OBJEXT): {$(VPATH)}intern.h
ast.$(OBJEXT): {$(VPATH)}internal.h
ast.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -2214,7 +2207,6 @@ ast.$(OBJEXT): {$(VPATH)}onigmo.h
ast.$(OBJEXT): {$(VPATH)}oniguruma.h
ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-ast.$(OBJEXT): {$(VPATH)}shape.h
ast.$(OBJEXT): {$(VPATH)}st.h
ast.$(OBJEXT): {$(VPATH)}subst.h
ast.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -2398,7 +2390,6 @@ bignum.$(OBJEXT): {$(VPATH)}internal/warning_push.h
bignum.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
bignum.$(OBJEXT): {$(VPATH)}missing.h
bignum.$(OBJEXT): {$(VPATH)}ruby_assert.h
-bignum.$(OBJEXT): {$(VPATH)}shape.h
bignum.$(OBJEXT): {$(VPATH)}st.h
bignum.$(OBJEXT): {$(VPATH)}subst.h
bignum.$(OBJEXT): {$(VPATH)}thread.h
@@ -2414,7 +2405,6 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h
builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h
builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h
builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h
builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
builtin.$(OBJEXT): {$(VPATH)}assert.h
@@ -2432,10 +2422,8 @@ builtin.$(OBJEXT): {$(VPATH)}builtin.c
builtin.$(OBJEXT): {$(VPATH)}builtin.h
builtin.$(OBJEXT): {$(VPATH)}builtin_binary.inc
builtin.$(OBJEXT): {$(VPATH)}config.h
-builtin.$(OBJEXT): {$(VPATH)}constant.h
builtin.$(OBJEXT): {$(VPATH)}defines.h
builtin.$(OBJEXT): {$(VPATH)}id.h
-builtin.$(OBJEXT): {$(VPATH)}id_table.h
builtin.$(OBJEXT): {$(VPATH)}intern.h
builtin.$(OBJEXT): {$(VPATH)}internal.h
builtin.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -2584,7 +2572,6 @@ builtin.$(OBJEXT): {$(VPATH)}missing.h
builtin.$(OBJEXT): {$(VPATH)}node.h
builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-builtin.$(OBJEXT): {$(VPATH)}shape.h
builtin.$(OBJEXT): {$(VPATH)}st.h
builtin.$(OBJEXT): {$(VPATH)}subst.h
builtin.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -2787,7 +2774,6 @@ class.$(OBJEXT): {$(VPATH)}onigmo.h
class.$(OBJEXT): {$(VPATH)}oniguruma.h
class.$(OBJEXT): {$(VPATH)}ruby_assert.h
class.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-class.$(OBJEXT): {$(VPATH)}shape.h
class.$(OBJEXT): {$(VPATH)}st.h
class.$(OBJEXT): {$(VPATH)}subst.h
class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -3191,7 +3177,6 @@ compile.$(OBJEXT): {$(VPATH)}re.h
compile.$(OBJEXT): {$(VPATH)}regex.h
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-compile.$(OBJEXT): {$(VPATH)}shape.h
compile.$(OBJEXT): {$(VPATH)}st.h
compile.$(OBJEXT): {$(VPATH)}subst.h
compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -3216,7 +3201,6 @@ complex.$(OBJEXT): $(top_srcdir)/internal/object.h
complex.$(OBJEXT): $(top_srcdir)/internal/rational.h
complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-complex.$(OBJEXT): $(top_srcdir)/internal/variable.h
complex.$(OBJEXT): $(top_srcdir)/internal/vm.h
complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h
complex.$(OBJEXT): {$(VPATH)}assert.h
@@ -3231,7 +3215,6 @@ complex.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
complex.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
complex.$(OBJEXT): {$(VPATH)}complex.c
complex.$(OBJEXT): {$(VPATH)}config.h
-complex.$(OBJEXT): {$(VPATH)}constant.h
complex.$(OBJEXT): {$(VPATH)}defines.h
complex.$(OBJEXT): {$(VPATH)}id.h
complex.$(OBJEXT): {$(VPATH)}id_table.h
@@ -3379,7 +3362,6 @@ complex.$(OBJEXT): {$(VPATH)}internal/warning_push.h
complex.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
complex.$(OBJEXT): {$(VPATH)}missing.h
complex.$(OBJEXT): {$(VPATH)}ruby_assert.h
-complex.$(OBJEXT): {$(VPATH)}shape.h
complex.$(OBJEXT): {$(VPATH)}st.h
complex.$(OBJEXT): {$(VPATH)}subst.h
cont.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -3397,7 +3379,6 @@ cont.$(OBJEXT): $(top_srcdir)/internal/proc.h
cont.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
cont.$(OBJEXT): $(top_srcdir)/internal/serial.h
cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-cont.$(OBJEXT): $(top_srcdir)/internal/variable.h
cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
@@ -3413,7 +3394,6 @@ cont.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
cont.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
cont.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
cont.$(OBJEXT): {$(VPATH)}config.h
-cont.$(OBJEXT): {$(VPATH)}constant.h
cont.$(OBJEXT): {$(VPATH)}cont.c
cont.$(OBJEXT): {$(VPATH)}debug_counter.h
cont.$(OBJEXT): {$(VPATH)}defines.h
@@ -3572,7 +3552,6 @@ cont.$(OBJEXT): {$(VPATH)}ractor.h
cont.$(OBJEXT): {$(VPATH)}ractor_core.h
cont.$(OBJEXT): {$(VPATH)}ruby_assert.h
cont.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-cont.$(OBJEXT): {$(VPATH)}shape.h
cont.$(OBJEXT): {$(VPATH)}st.h
cont.$(OBJEXT): {$(VPATH)}subst.h
cont.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -3593,7 +3572,6 @@ debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
debug.$(OBJEXT): $(top_srcdir)/internal/serial.h
debug.$(OBJEXT): $(top_srcdir)/internal/signal.h
debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-debug.$(OBJEXT): $(top_srcdir)/internal/variable.h
debug.$(OBJEXT): $(top_srcdir)/internal/vm.h
debug.$(OBJEXT): $(top_srcdir)/internal/warnings.h
debug.$(OBJEXT): {$(VPATH)}assert.h
@@ -3608,7 +3586,6 @@ debug.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
debug.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
debug.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
debug.$(OBJEXT): {$(VPATH)}config.h
-debug.$(OBJEXT): {$(VPATH)}constant.h
debug.$(OBJEXT): {$(VPATH)}debug.c
debug.$(OBJEXT): {$(VPATH)}debug_counter.h
debug.$(OBJEXT): {$(VPATH)}defines.h
@@ -3779,7 +3756,6 @@ debug.$(OBJEXT): {$(VPATH)}ractor.h
debug.$(OBJEXT): {$(VPATH)}ractor_core.h
debug.$(OBJEXT): {$(VPATH)}ruby_assert.h
debug.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-debug.$(OBJEXT): {$(VPATH)}shape.h
debug.$(OBJEXT): {$(VPATH)}st.h
debug.$(OBJEXT): {$(VPATH)}subst.h
debug.$(OBJEXT): {$(VPATH)}symbol.h
@@ -3964,7 +3940,6 @@ dir.$(OBJEXT): $(top_srcdir)/internal/object.h
dir.$(OBJEXT): $(top_srcdir)/internal/serial.h
dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
dir.$(OBJEXT): $(top_srcdir)/internal/string.h
-dir.$(OBJEXT): $(top_srcdir)/internal/variable.h
dir.$(OBJEXT): $(top_srcdir)/internal/vm.h
dir.$(OBJEXT): $(top_srcdir)/internal/warnings.h
dir.$(OBJEXT): {$(VPATH)}assert.h
@@ -3979,7 +3954,6 @@ dir.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
dir.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
dir.$(OBJEXT): {$(VPATH)}builtin.h
dir.$(OBJEXT): {$(VPATH)}config.h
-dir.$(OBJEXT): {$(VPATH)}constant.h
dir.$(OBJEXT): {$(VPATH)}defines.h
dir.$(OBJEXT): {$(VPATH)}dir.c
dir.$(OBJEXT): {$(VPATH)}dir.rbinc
@@ -4142,7 +4116,6 @@ dir.$(OBJEXT): {$(VPATH)}io.h
dir.$(OBJEXT): {$(VPATH)}missing.h
dir.$(OBJEXT): {$(VPATH)}onigmo.h
dir.$(OBJEXT): {$(VPATH)}oniguruma.h
-dir.$(OBJEXT): {$(VPATH)}shape.h
dir.$(OBJEXT): {$(VPATH)}st.h
dir.$(OBJEXT): {$(VPATH)}subst.h
dir.$(OBJEXT): {$(VPATH)}thread.h
@@ -5468,7 +5441,6 @@ encoding.$(OBJEXT): $(top_srcdir)/internal/object.h
encoding.$(OBJEXT): $(top_srcdir)/internal/serial.h
encoding.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
encoding.$(OBJEXT): $(top_srcdir)/internal/string.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/variable.h
encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h
encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h
encoding.$(OBJEXT): {$(VPATH)}assert.h
@@ -5482,7 +5454,6 @@ encoding.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
encoding.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
encoding.$(OBJEXT): {$(VPATH)}config.h
-encoding.$(OBJEXT): {$(VPATH)}constant.h
encoding.$(OBJEXT): {$(VPATH)}debug_counter.h
encoding.$(OBJEXT): {$(VPATH)}defines.h
encoding.$(OBJEXT): {$(VPATH)}encindex.h
@@ -5645,7 +5616,6 @@ encoding.$(OBJEXT): {$(VPATH)}onigmo.h
encoding.$(OBJEXT): {$(VPATH)}oniguruma.h
encoding.$(OBJEXT): {$(VPATH)}regenc.h
encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h
-encoding.$(OBJEXT): {$(VPATH)}shape.h
encoding.$(OBJEXT): {$(VPATH)}st.h
encoding.$(OBJEXT): {$(VPATH)}subst.h
encoding.$(OBJEXT): {$(VPATH)}util.h
@@ -5670,7 +5640,6 @@ enum.$(OBJEXT): $(top_srcdir)/internal/rational.h
enum.$(OBJEXT): $(top_srcdir)/internal/re.h
enum.$(OBJEXT): $(top_srcdir)/internal/serial.h
enum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-enum.$(OBJEXT): $(top_srcdir)/internal/variable.h
enum.$(OBJEXT): $(top_srcdir)/internal/vm.h
enum.$(OBJEXT): $(top_srcdir)/internal/warnings.h
enum.$(OBJEXT): {$(VPATH)}assert.h
@@ -5684,7 +5653,6 @@ enum.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
enum.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
enum.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enum.$(OBJEXT): {$(VPATH)}config.h
-enum.$(OBJEXT): {$(VPATH)}constant.h
enum.$(OBJEXT): {$(VPATH)}defines.h
enum.$(OBJEXT): {$(VPATH)}encoding.h
enum.$(OBJEXT): {$(VPATH)}enum.c
@@ -5845,7 +5813,6 @@ enum.$(OBJEXT): {$(VPATH)}missing.h
enum.$(OBJEXT): {$(VPATH)}onigmo.h
enum.$(OBJEXT): {$(VPATH)}oniguruma.h
enum.$(OBJEXT): {$(VPATH)}ruby_assert.h
-enum.$(OBJEXT): {$(VPATH)}shape.h
enum.$(OBJEXT): {$(VPATH)}st.h
enum.$(OBJEXT): {$(VPATH)}subst.h
enum.$(OBJEXT): {$(VPATH)}symbol.h
@@ -6245,7 +6212,6 @@ error.$(OBJEXT): {$(VPATH)}onigmo.h
error.$(OBJEXT): {$(VPATH)}oniguruma.h
error.$(OBJEXT): {$(VPATH)}ruby_assert.h
error.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-error.$(OBJEXT): {$(VPATH)}shape.h
error.$(OBJEXT): {$(VPATH)}st.h
error.$(OBJEXT): {$(VPATH)}subst.h
error.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -6467,7 +6433,6 @@ eval.$(OBJEXT): {$(VPATH)}ractor.h
eval.$(OBJEXT): {$(VPATH)}ractor_core.h
eval.$(OBJEXT): {$(VPATH)}ruby_assert.h
eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-eval.$(OBJEXT): {$(VPATH)}shape.h
eval.$(OBJEXT): {$(VPATH)}st.h
eval.$(OBJEXT): {$(VPATH)}subst.h
eval.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -6508,7 +6473,6 @@ file.$(OBJEXT): $(top_srcdir)/internal/serial.h
file.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
file.$(OBJEXT): $(top_srcdir)/internal/string.h
file.$(OBJEXT): $(top_srcdir)/internal/thread.h
-file.$(OBJEXT): $(top_srcdir)/internal/variable.h
file.$(OBJEXT): $(top_srcdir)/internal/vm.h
file.$(OBJEXT): $(top_srcdir)/internal/warnings.h
file.$(OBJEXT): {$(VPATH)}assert.h
@@ -6522,7 +6486,6 @@ file.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
file.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
file.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
file.$(OBJEXT): {$(VPATH)}config.h
-file.$(OBJEXT): {$(VPATH)}constant.h
file.$(OBJEXT): {$(VPATH)}defines.h
file.$(OBJEXT): {$(VPATH)}dln.h
file.$(OBJEXT): {$(VPATH)}encindex.h
@@ -6685,7 +6648,6 @@ file.$(OBJEXT): {$(VPATH)}io.h
file.$(OBJEXT): {$(VPATH)}missing.h
file.$(OBJEXT): {$(VPATH)}onigmo.h
file.$(OBJEXT): {$(VPATH)}oniguruma.h
-file.$(OBJEXT): {$(VPATH)}shape.h
file.$(OBJEXT): {$(VPATH)}st.h
file.$(OBJEXT): {$(VPATH)}subst.h
file.$(OBJEXT): {$(VPATH)}thread.h
@@ -6918,7 +6880,6 @@ gc.$(OBJEXT): {$(VPATH)}regex.h
gc.$(OBJEXT): {$(VPATH)}regint.h
gc.$(OBJEXT): {$(VPATH)}ruby_assert.h
gc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-gc.$(OBJEXT): {$(VPATH)}shape.h
gc.$(OBJEXT): {$(VPATH)}st.h
gc.$(OBJEXT): {$(VPATH)}subst.h
gc.$(OBJEXT): {$(VPATH)}symbol.h
@@ -6944,7 +6905,6 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
goruby.$(OBJEXT): {$(VPATH)}assert.h
@@ -6960,13 +6920,11 @@ goruby.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
goruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
goruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
goruby.$(OBJEXT): {$(VPATH)}config.h
-goruby.$(OBJEXT): {$(VPATH)}constant.h
goruby.$(OBJEXT): {$(VPATH)}defines.h
goruby.$(OBJEXT): {$(VPATH)}golf_prelude.c
goruby.$(OBJEXT): {$(VPATH)}golf_prelude.rb
goruby.$(OBJEXT): {$(VPATH)}goruby.c
goruby.$(OBJEXT): {$(VPATH)}id.h
-goruby.$(OBJEXT): {$(VPATH)}id_table.h
goruby.$(OBJEXT): {$(VPATH)}intern.h
goruby.$(OBJEXT): {$(VPATH)}internal.h
goruby.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -7116,7 +7074,6 @@ goruby.$(OBJEXT): {$(VPATH)}missing.h
goruby.$(OBJEXT): {$(VPATH)}node.h
goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-goruby.$(OBJEXT): {$(VPATH)}shape.h
goruby.$(OBJEXT): {$(VPATH)}st.h
goruby.$(OBJEXT): {$(VPATH)}subst.h
goruby.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -7142,7 +7099,6 @@ hash.$(OBJEXT): $(top_srcdir)/internal/string.h
hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h
hash.$(OBJEXT): $(top_srcdir)/internal/thread.h
hash.$(OBJEXT): $(top_srcdir)/internal/time.h
-hash.$(OBJEXT): $(top_srcdir)/internal/variable.h
hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
hash.$(OBJEXT): {$(VPATH)}assert.h
@@ -7156,7 +7112,6 @@ hash.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
hash.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
hash.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
hash.$(OBJEXT): {$(VPATH)}config.h
-hash.$(OBJEXT): {$(VPATH)}constant.h
hash.$(OBJEXT): {$(VPATH)}debug_counter.h
hash.$(OBJEXT): {$(VPATH)}defines.h
hash.$(OBJEXT): {$(VPATH)}encoding.h
@@ -7321,7 +7276,6 @@ hash.$(OBJEXT): {$(VPATH)}probes.dmyh
hash.$(OBJEXT): {$(VPATH)}probes.h
hash.$(OBJEXT): {$(VPATH)}ractor.h
hash.$(OBJEXT): {$(VPATH)}ruby_assert.h
-hash.$(OBJEXT): {$(VPATH)}shape.h
hash.$(OBJEXT): {$(VPATH)}st.h
hash.$(OBJEXT): {$(VPATH)}subst.h
hash.$(OBJEXT): {$(VPATH)}symbol.h
@@ -7706,7 +7660,6 @@ io.$(OBJEXT): {$(VPATH)}oniguruma.h
io.$(OBJEXT): {$(VPATH)}ractor.h
io.$(OBJEXT): {$(VPATH)}ruby_assert.h
io.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-io.$(OBJEXT): {$(VPATH)}shape.h
io.$(OBJEXT): {$(VPATH)}st.h
io.$(OBJEXT): {$(VPATH)}subst.h
io.$(OBJEXT): {$(VPATH)}thread.h
@@ -8109,7 +8062,6 @@ iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
iseq.$(OBJEXT): {$(VPATH)}ractor.h
iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-iseq.$(OBJEXT): {$(VPATH)}shape.h
iseq.$(OBJEXT): {$(VPATH)}st.h
iseq.$(OBJEXT): {$(VPATH)}subst.h
iseq.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -8322,7 +8274,6 @@ load.$(OBJEXT): {$(VPATH)}probes.dmyh
load.$(OBJEXT): {$(VPATH)}probes.h
load.$(OBJEXT): {$(VPATH)}ruby_assert.h
load.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-load.$(OBJEXT): {$(VPATH)}shape.h
load.$(OBJEXT): {$(VPATH)}st.h
load.$(OBJEXT): {$(VPATH)}subst.h
load.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -8841,7 +8792,6 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h
marshal.$(OBJEXT): $(top_srcdir)/internal/symbol.h
marshal.$(OBJEXT): $(top_srcdir)/internal/util.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/variable.h
marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
marshal.$(OBJEXT): {$(VPATH)}assert.h
@@ -8856,7 +8806,6 @@ marshal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
marshal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
marshal.$(OBJEXT): {$(VPATH)}builtin.h
marshal.$(OBJEXT): {$(VPATH)}config.h
-marshal.$(OBJEXT): {$(VPATH)}constant.h
marshal.$(OBJEXT): {$(VPATH)}defines.h
marshal.$(OBJEXT): {$(VPATH)}encindex.h
marshal.$(OBJEXT): {$(VPATH)}encoding.h
@@ -9018,7 +8967,6 @@ marshal.$(OBJEXT): {$(VPATH)}marshal.rbinc
marshal.$(OBJEXT): {$(VPATH)}missing.h
marshal.$(OBJEXT): {$(VPATH)}onigmo.h
marshal.$(OBJEXT): {$(VPATH)}oniguruma.h
-marshal.$(OBJEXT): {$(VPATH)}shape.h
marshal.$(OBJEXT): {$(VPATH)}st.h
marshal.$(OBJEXT): {$(VPATH)}subst.h
marshal.$(OBJEXT): {$(VPATH)}util.h
@@ -9032,7 +8980,6 @@ math.$(OBJEXT): $(top_srcdir)/internal/math.h
math.$(OBJEXT): $(top_srcdir)/internal/object.h
math.$(OBJEXT): $(top_srcdir)/internal/serial.h
math.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-math.$(OBJEXT): $(top_srcdir)/internal/variable.h
math.$(OBJEXT): $(top_srcdir)/internal/vm.h
math.$(OBJEXT): $(top_srcdir)/internal/warnings.h
math.$(OBJEXT): {$(VPATH)}assert.h
@@ -9046,7 +8993,6 @@ math.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
math.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
math.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
math.$(OBJEXT): {$(VPATH)}config.h
-math.$(OBJEXT): {$(VPATH)}constant.h
math.$(OBJEXT): {$(VPATH)}defines.h
math.$(OBJEXT): {$(VPATH)}id_table.h
math.$(OBJEXT): {$(VPATH)}intern.h
@@ -9193,7 +9139,6 @@ math.$(OBJEXT): {$(VPATH)}internal/warning_push.h
math.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
math.$(OBJEXT): {$(VPATH)}math.c
math.$(OBJEXT): {$(VPATH)}missing.h
-math.$(OBJEXT): {$(VPATH)}shape.h
math.$(OBJEXT): {$(VPATH)}st.h
math.$(OBJEXT): {$(VPATH)}subst.h
memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h
@@ -9375,7 +9320,6 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
miniinit.$(OBJEXT): {$(VPATH)}array.rb
@@ -9393,14 +9337,12 @@ miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
miniinit.$(OBJEXT): {$(VPATH)}builtin.h
miniinit.$(OBJEXT): {$(VPATH)}config.h
-miniinit.$(OBJEXT): {$(VPATH)}constant.h
miniinit.$(OBJEXT): {$(VPATH)}defines.h
miniinit.$(OBJEXT): {$(VPATH)}dir.rb
miniinit.$(OBJEXT): {$(VPATH)}encoding.h
miniinit.$(OBJEXT): {$(VPATH)}gc.rb
miniinit.$(OBJEXT): {$(VPATH)}gem_prelude.rb
miniinit.$(OBJEXT): {$(VPATH)}id.h
-miniinit.$(OBJEXT): {$(VPATH)}id_table.h
miniinit.$(OBJEXT): {$(VPATH)}intern.h
miniinit.$(OBJEXT): {$(VPATH)}internal.h
miniinit.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -9574,7 +9516,6 @@ miniinit.$(OBJEXT): {$(VPATH)}prelude.rb
miniinit.$(OBJEXT): {$(VPATH)}ractor.rb
miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h
miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-miniinit.$(OBJEXT): {$(VPATH)}shape.h
miniinit.$(OBJEXT): {$(VPATH)}st.h
miniinit.$(OBJEXT): {$(VPATH)}subst.h
miniinit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -9606,7 +9547,6 @@ mjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
mjit.$(OBJEXT): $(top_srcdir)/internal/process.h
mjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
mjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-mjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
mjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
mjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
mjit.$(OBJEXT): {$(VPATH)}assert.h
@@ -9801,7 +9741,6 @@ mjit.$(OBJEXT): {$(VPATH)}ractor.h
mjit.$(OBJEXT): {$(VPATH)}ractor_core.h
mjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
mjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-mjit.$(OBJEXT): {$(VPATH)}shape.h
mjit.$(OBJEXT): {$(VPATH)}st.h
mjit.$(OBJEXT): {$(VPATH)}subst.h
mjit.$(OBJEXT): {$(VPATH)}thread.h
@@ -10012,7 +9951,6 @@ mjit_compiler.$(OBJEXT): {$(VPATH)}mjit_unit.h
mjit_compiler.$(OBJEXT): {$(VPATH)}node.h
mjit_compiler.$(OBJEXT): {$(VPATH)}ruby_assert.h
mjit_compiler.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-mjit_compiler.$(OBJEXT): {$(VPATH)}shape.h
mjit_compiler.$(OBJEXT): {$(VPATH)}st.h
mjit_compiler.$(OBJEXT): {$(VPATH)}subst.h
mjit_compiler.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -10202,7 +10140,6 @@ node.$(OBJEXT): {$(VPATH)}node.c
node.$(OBJEXT): {$(VPATH)}node.h
node.$(OBJEXT): {$(VPATH)}ruby_assert.h
node.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-node.$(OBJEXT): {$(VPATH)}shape.h
node.$(OBJEXT): {$(VPATH)}st.h
node.$(OBJEXT): {$(VPATH)}subst.h
node.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -10405,7 +10342,6 @@ numeric.$(OBJEXT): {$(VPATH)}numeric.rbinc
numeric.$(OBJEXT): {$(VPATH)}onigmo.h
numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
-numeric.$(OBJEXT): {$(VPATH)}shape.h
numeric.$(OBJEXT): {$(VPATH)}st.h
numeric.$(OBJEXT): {$(VPATH)}subst.h
numeric.$(OBJEXT): {$(VPATH)}util.h
@@ -10607,7 +10543,6 @@ object.$(OBJEXT): {$(VPATH)}onigmo.h
object.$(OBJEXT): {$(VPATH)}oniguruma.h
object.$(OBJEXT): {$(VPATH)}probes.dmyh
object.$(OBJEXT): {$(VPATH)}probes.h
-object.$(OBJEXT): {$(VPATH)}shape.h
object.$(OBJEXT): {$(VPATH)}st.h
object.$(OBJEXT): {$(VPATH)}subst.h
object.$(OBJEXT): {$(VPATH)}util.h
@@ -11026,7 +10961,6 @@ proc.$(OBJEXT): $(top_srcdir)/internal/serial.h
proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
proc.$(OBJEXT): $(top_srcdir)/internal/string.h
proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-proc.$(OBJEXT): $(top_srcdir)/internal/variable.h
proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
proc.$(OBJEXT): {$(VPATH)}assert.h
@@ -11041,7 +10975,6 @@ proc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
proc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
proc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
proc.$(OBJEXT): {$(VPATH)}config.h
-proc.$(OBJEXT): {$(VPATH)}constant.h
proc.$(OBJEXT): {$(VPATH)}defines.h
proc.$(OBJEXT): {$(VPATH)}encoding.h
proc.$(OBJEXT): {$(VPATH)}eval_intern.h
@@ -11208,7 +11141,6 @@ proc.$(OBJEXT): {$(VPATH)}oniguruma.h
proc.$(OBJEXT): {$(VPATH)}proc.c
proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-proc.$(OBJEXT): {$(VPATH)}shape.h
proc.$(OBJEXT): {$(VPATH)}st.h
proc.$(OBJEXT): {$(VPATH)}subst.h
proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -11428,7 +11360,6 @@ process.$(OBJEXT): {$(VPATH)}process.c
process.$(OBJEXT): {$(VPATH)}ractor.h
process.$(OBJEXT): {$(VPATH)}ruby_assert.h
process.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-process.$(OBJEXT): {$(VPATH)}shape.h
process.$(OBJEXT): {$(VPATH)}st.h
process.$(OBJEXT): {$(VPATH)}subst.h
process.$(OBJEXT): {$(VPATH)}thread.h
@@ -11459,7 +11390,6 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ractor.$(OBJEXT): $(top_srcdir)/internal/string.h
ractor.$(OBJEXT): $(top_srcdir)/internal/struct.h
ractor.$(OBJEXT): $(top_srcdir)/internal/thread.h
-ractor.$(OBJEXT): $(top_srcdir)/internal/variable.h
ractor.$(OBJEXT): $(top_srcdir)/internal/vm.h
ractor.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ractor.$(OBJEXT): {$(VPATH)}assert.h
@@ -11475,7 +11405,6 @@ ractor.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ractor.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ractor.$(OBJEXT): {$(VPATH)}builtin.h
ractor.$(OBJEXT): {$(VPATH)}config.h
-ractor.$(OBJEXT): {$(VPATH)}constant.h
ractor.$(OBJEXT): {$(VPATH)}debug_counter.h
ractor.$(OBJEXT): {$(VPATH)}defines.h
ractor.$(OBJEXT): {$(VPATH)}encoding.h
@@ -11645,7 +11574,6 @@ ractor.$(OBJEXT): {$(VPATH)}ractor.rbinc
ractor.$(OBJEXT): {$(VPATH)}ractor_core.h
ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h
ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-ractor.$(OBJEXT): {$(VPATH)}shape.h
ractor.$(OBJEXT): {$(VPATH)}st.h
ractor.$(OBJEXT): {$(VPATH)}subst.h
ractor.$(OBJEXT): {$(VPATH)}thread.h
@@ -12043,7 +11971,6 @@ rational.$(OBJEXT): $(top_srcdir)/internal/object.h
rational.$(OBJEXT): $(top_srcdir)/internal/rational.h
rational.$(OBJEXT): $(top_srcdir)/internal/serial.h
rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-rational.$(OBJEXT): $(top_srcdir)/internal/variable.h
rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
rational.$(OBJEXT): {$(VPATH)}assert.h
@@ -12057,7 +11984,6 @@ rational.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
rational.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
rational.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
rational.$(OBJEXT): {$(VPATH)}config.h
-rational.$(OBJEXT): {$(VPATH)}constant.h
rational.$(OBJEXT): {$(VPATH)}defines.h
rational.$(OBJEXT): {$(VPATH)}id.h
rational.$(OBJEXT): {$(VPATH)}id_table.h
@@ -12206,7 +12132,6 @@ rational.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
rational.$(OBJEXT): {$(VPATH)}missing.h
rational.$(OBJEXT): {$(VPATH)}rational.c
rational.$(OBJEXT): {$(VPATH)}ruby_assert.h
-rational.$(OBJEXT): {$(VPATH)}shape.h
rational.$(OBJEXT): {$(VPATH)}st.h
rational.$(OBJEXT): {$(VPATH)}subst.h
re.$(OBJEXT): $(hdrdir)/ruby.h
@@ -12404,7 +12329,6 @@ re.$(OBJEXT): {$(VPATH)}re.h
re.$(OBJEXT): {$(VPATH)}regenc.h
re.$(OBJEXT): {$(VPATH)}regex.h
re.$(OBJEXT): {$(VPATH)}regint.h
-re.$(OBJEXT): {$(VPATH)}shape.h
re.$(OBJEXT): {$(VPATH)}st.h
re.$(OBJEXT): {$(VPATH)}subst.h
re.$(OBJEXT): {$(VPATH)}util.h
@@ -13602,7 +13526,6 @@ ruby.$(OBJEXT): {$(VPATH)}oniguruma.h
ruby.$(OBJEXT): {$(VPATH)}ruby.c
ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
ruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-ruby.$(OBJEXT): {$(VPATH)}shape.h
ruby.$(OBJEXT): {$(VPATH)}st.h
ruby.$(OBJEXT): {$(VPATH)}subst.h
ruby.$(OBJEXT): {$(VPATH)}thread.h
@@ -13624,7 +13547,6 @@ scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h
-scheduler.$(OBJEXT): $(top_srcdir)/internal/variable.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/vm.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/warnings.h
scheduler.$(OBJEXT): {$(VPATH)}assert.h
@@ -13639,12 +13561,10 @@ scheduler.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
scheduler.$(OBJEXT): {$(VPATH)}config.h
-scheduler.$(OBJEXT): {$(VPATH)}constant.h
scheduler.$(OBJEXT): {$(VPATH)}defines.h
scheduler.$(OBJEXT): {$(VPATH)}encoding.h
scheduler.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
scheduler.$(OBJEXT): {$(VPATH)}id.h
-scheduler.$(OBJEXT): {$(VPATH)}id_table.h
scheduler.$(OBJEXT): {$(VPATH)}intern.h
scheduler.$(OBJEXT): {$(VPATH)}internal.h
scheduler.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -13806,7 +13726,6 @@ scheduler.$(OBJEXT): {$(VPATH)}oniguruma.h
scheduler.$(OBJEXT): {$(VPATH)}ruby_assert.h
scheduler.$(OBJEXT): {$(VPATH)}ruby_atomic.h
scheduler.$(OBJEXT): {$(VPATH)}scheduler.c
-scheduler.$(OBJEXT): {$(VPATH)}shape.h
scheduler.$(OBJEXT): {$(VPATH)}st.h
scheduler.$(OBJEXT): {$(VPATH)}subst.h
scheduler.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -13972,208 +13891,6 @@ setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c
setproctitle.$(OBJEXT): {$(VPATH)}st.h
setproctitle.$(OBJEXT): {$(VPATH)}subst.h
setproctitle.$(OBJEXT): {$(VPATH)}util.h
-shape.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-shape.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-shape.$(OBJEXT): $(CCAN_DIR)/list/list.h
-shape.$(OBJEXT): $(CCAN_DIR)/str/str.h
-shape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-shape.$(OBJEXT): $(top_srcdir)/internal/array.h
-shape.$(OBJEXT): $(top_srcdir)/internal/class.h
-shape.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-shape.$(OBJEXT): $(top_srcdir)/internal/gc.h
-shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-shape.$(OBJEXT): $(top_srcdir)/internal/serial.h
-shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-shape.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-shape.$(OBJEXT): $(top_srcdir)/internal/variable.h
-shape.$(OBJEXT): $(top_srcdir)/internal/vm.h
-shape.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-shape.$(OBJEXT): {$(VPATH)}assert.h
-shape.$(OBJEXT): {$(VPATH)}atomic.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-shape.$(OBJEXT): {$(VPATH)}config.h
-shape.$(OBJEXT): {$(VPATH)}constant.h
-shape.$(OBJEXT): {$(VPATH)}debug_counter.h
-shape.$(OBJEXT): {$(VPATH)}defines.h
-shape.$(OBJEXT): {$(VPATH)}encoding.h
-shape.$(OBJEXT): {$(VPATH)}id.h
-shape.$(OBJEXT): {$(VPATH)}id_table.h
-shape.$(OBJEXT): {$(VPATH)}intern.h
-shape.$(OBJEXT): {$(VPATH)}internal.h
-shape.$(OBJEXT): {$(VPATH)}internal/abi.h
-shape.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/assume.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-shape.$(OBJEXT): {$(VPATH)}internal/cast.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-shape.$(OBJEXT): {$(VPATH)}internal/config.h
-shape.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-shape.$(OBJEXT): {$(VPATH)}internal/core.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-shape.$(OBJEXT): {$(VPATH)}internal/ctype.h
-shape.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-shape.$(OBJEXT): {$(VPATH)}internal/dosish.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-shape.$(OBJEXT): {$(VPATH)}internal/error.h
-shape.$(OBJEXT): {$(VPATH)}internal/eval.h
-shape.$(OBJEXT): {$(VPATH)}internal/event.h
-shape.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-shape.$(OBJEXT): {$(VPATH)}internal/gc.h
-shape.$(OBJEXT): {$(VPATH)}internal/glob.h
-shape.$(OBJEXT): {$(VPATH)}internal/globals.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-shape.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-shape.$(OBJEXT): {$(VPATH)}internal/iterator.h
-shape.$(OBJEXT): {$(VPATH)}internal/memory.h
-shape.$(OBJEXT): {$(VPATH)}internal/method.h
-shape.$(OBJEXT): {$(VPATH)}internal/module.h
-shape.$(OBJEXT): {$(VPATH)}internal/newobj.h
-shape.$(OBJEXT): {$(VPATH)}internal/rgengc.h
-shape.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-shape.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-shape.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-shape.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-shape.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-shape.$(OBJEXT): {$(VPATH)}internal/symbol.h
-shape.$(OBJEXT): {$(VPATH)}internal/value.h
-shape.$(OBJEXT): {$(VPATH)}internal/value_type.h
-shape.$(OBJEXT): {$(VPATH)}internal/variable.h
-shape.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-shape.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-shape.$(OBJEXT): {$(VPATH)}method.h
-shape.$(OBJEXT): {$(VPATH)}missing.h
-shape.$(OBJEXT): {$(VPATH)}node.h
-shape.$(OBJEXT): {$(VPATH)}onigmo.h
-shape.$(OBJEXT): {$(VPATH)}oniguruma.h
-shape.$(OBJEXT): {$(VPATH)}ruby_assert.h
-shape.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-shape.$(OBJEXT): {$(VPATH)}shape.c
-shape.$(OBJEXT): {$(VPATH)}shape.h
-shape.$(OBJEXT): {$(VPATH)}st.h
-shape.$(OBJEXT): {$(VPATH)}subst.h
-shape.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-shape.$(OBJEXT): {$(VPATH)}thread_native.h
-shape.$(OBJEXT): {$(VPATH)}vm_core.h
-shape.$(OBJEXT): {$(VPATH)}vm_debug.h
-shape.$(OBJEXT): {$(VPATH)}vm_opts.h
-shape.$(OBJEXT): {$(VPATH)}vm_sync.h
signal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
signal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
signal.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -14190,7 +13907,6 @@ signal.$(OBJEXT): $(top_srcdir)/internal/signal.h
signal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
signal.$(OBJEXT): $(top_srcdir)/internal/string.h
signal.$(OBJEXT): $(top_srcdir)/internal/thread.h
-signal.$(OBJEXT): $(top_srcdir)/internal/variable.h
signal.$(OBJEXT): $(top_srcdir)/internal/vm.h
signal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
signal.$(OBJEXT): {$(VPATH)}assert.h
@@ -14205,7 +13921,6 @@ signal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
signal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
signal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
signal.$(OBJEXT): {$(VPATH)}config.h
-signal.$(OBJEXT): {$(VPATH)}constant.h
signal.$(OBJEXT): {$(VPATH)}debug_counter.h
signal.$(OBJEXT): {$(VPATH)}defines.h
signal.$(OBJEXT): {$(VPATH)}encoding.h
@@ -14372,7 +14087,6 @@ signal.$(OBJEXT): {$(VPATH)}ractor.h
signal.$(OBJEXT): {$(VPATH)}ractor_core.h
signal.$(OBJEXT): {$(VPATH)}ruby_assert.h
signal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-signal.$(OBJEXT): {$(VPATH)}shape.h
signal.$(OBJEXT): {$(VPATH)}signal.c
signal.$(OBJEXT): {$(VPATH)}st.h
signal.$(OBJEXT): {$(VPATH)}subst.h
@@ -14397,7 +14111,6 @@ sprintf.$(OBJEXT): $(top_srcdir)/internal/serial.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/string.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-sprintf.$(OBJEXT): $(top_srcdir)/internal/variable.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/vm.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/warnings.h
sprintf.$(OBJEXT): {$(VPATH)}assert.h
@@ -14411,7 +14124,6 @@ sprintf.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
sprintf.$(OBJEXT): {$(VPATH)}config.h
-sprintf.$(OBJEXT): {$(VPATH)}constant.h
sprintf.$(OBJEXT): {$(VPATH)}defines.h
sprintf.$(OBJEXT): {$(VPATH)}encoding.h
sprintf.$(OBJEXT): {$(VPATH)}id.h
@@ -14573,7 +14285,6 @@ sprintf.$(OBJEXT): {$(VPATH)}onigmo.h
sprintf.$(OBJEXT): {$(VPATH)}oniguruma.h
sprintf.$(OBJEXT): {$(VPATH)}re.h
sprintf.$(OBJEXT): {$(VPATH)}regex.h
-sprintf.$(OBJEXT): {$(VPATH)}shape.h
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c
sprintf.$(OBJEXT): {$(VPATH)}st.h
sprintf.$(OBJEXT): {$(VPATH)}subst.h
@@ -14942,7 +14653,6 @@ string.$(OBJEXT): $(top_srcdir)/internal/serial.h
string.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
string.$(OBJEXT): $(top_srcdir)/internal/string.h
string.$(OBJEXT): $(top_srcdir)/internal/transcode.h
-string.$(OBJEXT): $(top_srcdir)/internal/variable.h
string.$(OBJEXT): $(top_srcdir)/internal/vm.h
string.$(OBJEXT): $(top_srcdir)/internal/warnings.h
string.$(OBJEXT): {$(VPATH)}assert.h
@@ -14957,7 +14667,6 @@ string.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
string.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
string.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
string.$(OBJEXT): {$(VPATH)}config.h
-string.$(OBJEXT): {$(VPATH)}constant.h
string.$(OBJEXT): {$(VPATH)}debug_counter.h
string.$(OBJEXT): {$(VPATH)}defines.h
string.$(OBJEXT): {$(VPATH)}encindex.h
@@ -15125,7 +14834,6 @@ string.$(OBJEXT): {$(VPATH)}probes.h
string.$(OBJEXT): {$(VPATH)}re.h
string.$(OBJEXT): {$(VPATH)}regex.h
string.$(OBJEXT): {$(VPATH)}ruby_assert.h
-string.$(OBJEXT): {$(VPATH)}shape.h
string.$(OBJEXT): {$(VPATH)}st.h
string.$(OBJEXT): {$(VPATH)}string.c
string.$(OBJEXT): {$(VPATH)}subst.h
@@ -15182,7 +14890,6 @@ struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
struct.$(OBJEXT): $(top_srcdir)/internal/string.h
struct.$(OBJEXT): $(top_srcdir)/internal/struct.h
struct.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-struct.$(OBJEXT): $(top_srcdir)/internal/variable.h
struct.$(OBJEXT): $(top_srcdir)/internal/vm.h
struct.$(OBJEXT): $(top_srcdir)/internal/warnings.h
struct.$(OBJEXT): {$(VPATH)}assert.h
@@ -15198,7 +14905,6 @@ struct.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
struct.$(OBJEXT): {$(VPATH)}builtin.h
struct.$(OBJEXT): {$(VPATH)}config.h
-struct.$(OBJEXT): {$(VPATH)}constant.h
struct.$(OBJEXT): {$(VPATH)}defines.h
struct.$(OBJEXT): {$(VPATH)}encoding.h
struct.$(OBJEXT): {$(VPATH)}id.h
@@ -15361,7 +15067,6 @@ struct.$(OBJEXT): {$(VPATH)}onigmo.h
struct.$(OBJEXT): {$(VPATH)}oniguruma.h
struct.$(OBJEXT): {$(VPATH)}ruby_assert.h
struct.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-struct.$(OBJEXT): {$(VPATH)}shape.h
struct.$(OBJEXT): {$(VPATH)}st.h
struct.$(OBJEXT): {$(VPATH)}struct.c
struct.$(OBJEXT): {$(VPATH)}subst.h
@@ -15381,7 +15086,6 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h
symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
symbol.$(OBJEXT): $(top_srcdir)/internal/string.h
symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/variable.h
symbol.$(OBJEXT): $(top_srcdir)/internal/vm.h
symbol.$(OBJEXT): $(top_srcdir)/internal/warnings.h
symbol.$(OBJEXT): {$(VPATH)}assert.h
@@ -15395,7 +15099,6 @@ symbol.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
symbol.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
symbol.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
symbol.$(OBJEXT): {$(VPATH)}config.h
-symbol.$(OBJEXT): {$(VPATH)}constant.h
symbol.$(OBJEXT): {$(VPATH)}debug_counter.h
symbol.$(OBJEXT): {$(VPATH)}defines.h
symbol.$(OBJEXT): {$(VPATH)}encoding.h
@@ -15561,7 +15264,6 @@ symbol.$(OBJEXT): {$(VPATH)}oniguruma.h
symbol.$(OBJEXT): {$(VPATH)}probes.dmyh
symbol.$(OBJEXT): {$(VPATH)}probes.h
symbol.$(OBJEXT): {$(VPATH)}ruby_assert.h
-symbol.$(OBJEXT): {$(VPATH)}shape.h
symbol.$(OBJEXT): {$(VPATH)}st.h
symbol.$(OBJEXT): {$(VPATH)}subst.h
symbol.$(OBJEXT): {$(VPATH)}symbol.c
@@ -15592,7 +15294,6 @@ thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
thread.$(OBJEXT): $(top_srcdir)/internal/string.h
thread.$(OBJEXT): $(top_srcdir)/internal/thread.h
thread.$(OBJEXT): $(top_srcdir)/internal/time.h
-thread.$(OBJEXT): $(top_srcdir)/internal/variable.h
thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
thread.$(OBJEXT): {$(VPATH)}assert.h
@@ -15608,7 +15309,6 @@ thread.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
thread.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
thread.$(OBJEXT): {$(VPATH)}builtin.h
thread.$(OBJEXT): {$(VPATH)}config.h
-thread.$(OBJEXT): {$(VPATH)}constant.h
thread.$(OBJEXT): {$(VPATH)}debug.h
thread.$(OBJEXT): {$(VPATH)}debug_counter.h
thread.$(OBJEXT): {$(VPATH)}defines.h
@@ -15782,7 +15482,6 @@ thread.$(OBJEXT): {$(VPATH)}ractor.h
thread.$(OBJEXT): {$(VPATH)}ractor_core.h
thread.$(OBJEXT): {$(VPATH)}ruby_assert.h
thread.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-thread.$(OBJEXT): {$(VPATH)}shape.h
thread.$(OBJEXT): {$(VPATH)}st.h
thread.$(OBJEXT): {$(VPATH)}subst.h
thread.$(OBJEXT): {$(VPATH)}thread.c
@@ -16003,7 +15702,6 @@ transcode.$(OBJEXT): $(top_srcdir)/internal/serial.h
transcode.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
transcode.$(OBJEXT): $(top_srcdir)/internal/string.h
transcode.$(OBJEXT): $(top_srcdir)/internal/transcode.h
-transcode.$(OBJEXT): $(top_srcdir)/internal/variable.h
transcode.$(OBJEXT): $(top_srcdir)/internal/warnings.h
transcode.$(OBJEXT): {$(VPATH)}assert.h
transcode.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -16016,7 +15714,6 @@ transcode.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
transcode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
transcode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
transcode.$(OBJEXT): {$(VPATH)}config.h
-transcode.$(OBJEXT): {$(VPATH)}constant.h
transcode.$(OBJEXT): {$(VPATH)}defines.h
transcode.$(OBJEXT): {$(VPATH)}encoding.h
transcode.$(OBJEXT): {$(VPATH)}id.h
@@ -16175,7 +15872,6 @@ transcode.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
transcode.$(OBJEXT): {$(VPATH)}missing.h
transcode.$(OBJEXT): {$(VPATH)}onigmo.h
transcode.$(OBJEXT): {$(VPATH)}oniguruma.h
-transcode.$(OBJEXT): {$(VPATH)}shape.h
transcode.$(OBJEXT): {$(VPATH)}st.h
transcode.$(OBJEXT): {$(VPATH)}subst.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c
@@ -16725,7 +16421,6 @@ variable.$(OBJEXT): {$(VPATH)}ractor.h
variable.$(OBJEXT): {$(VPATH)}ractor_core.h
variable.$(OBJEXT): {$(VPATH)}ruby_assert.h
variable.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-variable.$(OBJEXT): {$(VPATH)}shape.h
variable.$(OBJEXT): {$(VPATH)}st.h
variable.$(OBJEXT): {$(VPATH)}subst.h
variable.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -16751,7 +16446,6 @@ version.$(OBJEXT): $(top_srcdir)/internal/gc.h
version.$(OBJEXT): $(top_srcdir)/internal/imemo.h
version.$(OBJEXT): $(top_srcdir)/internal/serial.h
version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-version.$(OBJEXT): $(top_srcdir)/internal/variable.h
version.$(OBJEXT): $(top_srcdir)/internal/vm.h
version.$(OBJEXT): $(top_srcdir)/internal/warnings.h
version.$(OBJEXT): $(top_srcdir)/revision.h
@@ -16768,11 +16462,9 @@ version.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
version.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
version.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
version.$(OBJEXT): {$(VPATH)}config.h
-version.$(OBJEXT): {$(VPATH)}constant.h
version.$(OBJEXT): {$(VPATH)}debug_counter.h
version.$(OBJEXT): {$(VPATH)}defines.h
version.$(OBJEXT): {$(VPATH)}id.h
-version.$(OBJEXT): {$(VPATH)}id_table.h
version.$(OBJEXT): {$(VPATH)}intern.h
version.$(OBJEXT): {$(VPATH)}internal.h
version.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -16921,7 +16613,6 @@ version.$(OBJEXT): {$(VPATH)}mjit.h
version.$(OBJEXT): {$(VPATH)}node.h
version.$(OBJEXT): {$(VPATH)}ruby_assert.h
version.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-version.$(OBJEXT): {$(VPATH)}shape.h
version.$(OBJEXT): {$(VPATH)}st.h
version.$(OBJEXT): {$(VPATH)}subst.h
version.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -17157,7 +16848,6 @@ vm.$(OBJEXT): {$(VPATH)}ractor.h
vm.$(OBJEXT): {$(VPATH)}ractor_core.h
vm.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm.$(OBJEXT): {$(VPATH)}shape.h
vm.$(OBJEXT): {$(VPATH)}st.h
vm.$(OBJEXT): {$(VPATH)}subst.h
vm.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -17194,7 +16884,6 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h
@@ -17209,13 +16898,11 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_backtrace.$(OBJEXT): {$(VPATH)}config.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}constant.h
vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h
vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h
vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h
vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h
vm_backtrace.$(OBJEXT): {$(VPATH)}id.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}id_table.h
vm_backtrace.$(OBJEXT): {$(VPATH)}intern.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -17375,7 +17062,6 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}shape.h
vm_backtrace.$(OBJEXT): {$(VPATH)}st.h
vm_backtrace.$(OBJEXT): {$(VPATH)}subst.h
vm_backtrace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -17566,7 +17252,6 @@ vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h
vm_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_dump.$(OBJEXT): {$(VPATH)}shape.h
vm_dump.$(OBJEXT): {$(VPATH)}st.h
vm_dump.$(OBJEXT): {$(VPATH)}subst.h
vm_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -17586,7 +17271,6 @@ vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_sync.$(OBJEXT): {$(VPATH)}assert.h
@@ -17601,7 +17285,6 @@ vm_sync.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
vm_sync.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_sync.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_sync.$(OBJEXT): {$(VPATH)}config.h
-vm_sync.$(OBJEXT): {$(VPATH)}constant.h
vm_sync.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_sync.$(OBJEXT): {$(VPATH)}defines.h
vm_sync.$(OBJEXT): {$(VPATH)}gc.h
@@ -17756,7 +17439,6 @@ vm_sync.$(OBJEXT): {$(VPATH)}ractor.h
vm_sync.$(OBJEXT): {$(VPATH)}ractor_core.h
vm_sync.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_sync.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_sync.$(OBJEXT): {$(VPATH)}shape.h
vm_sync.$(OBJEXT): {$(VPATH)}st.h
vm_sync.$(OBJEXT): {$(VPATH)}subst.h
vm_sync.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -17780,7 +17462,6 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_trace.$(OBJEXT): {$(VPATH)}assert.h
@@ -17796,14 +17477,12 @@ vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_trace.$(OBJEXT): {$(VPATH)}builtin.h
vm_trace.$(OBJEXT): {$(VPATH)}config.h
-vm_trace.$(OBJEXT): {$(VPATH)}constant.h
vm_trace.$(OBJEXT): {$(VPATH)}debug.h
vm_trace.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_trace.$(OBJEXT): {$(VPATH)}defines.h
vm_trace.$(OBJEXT): {$(VPATH)}encoding.h
vm_trace.$(OBJEXT): {$(VPATH)}eval_intern.h
vm_trace.$(OBJEXT): {$(VPATH)}id.h
-vm_trace.$(OBJEXT): {$(VPATH)}id_table.h
vm_trace.$(OBJEXT): {$(VPATH)}intern.h
vm_trace.$(OBJEXT): {$(VPATH)}internal.h
vm_trace.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -17965,7 +17644,6 @@ vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h
vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_trace.$(OBJEXT): {$(VPATH)}shape.h
vm_trace.$(OBJEXT): {$(VPATH)}st.h
vm_trace.$(OBJEXT): {$(VPATH)}subst.h
vm_trace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
diff --git a/compile.c b/compile.c
index 9051ecfcd6..a5da919c0a 100644
--- a/compile.c
+++ b/compile.c
@@ -2058,7 +2058,20 @@ cdhash_set_label_i(VALUE key, VALUE val, VALUE ptr)
static inline VALUE
get_ivar_ic_value(rb_iseq_t *iseq,ID id)
{
- return INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
+ VALUE val;
+ struct rb_id_table *tbl = ISEQ_COMPILE_DATA(iseq)->ivar_cache_table;
+ if (tbl) {
+ if (rb_id_table_lookup(tbl,id,&val)) {
+ return val;
+ }
+ }
+ else {
+ tbl = rb_id_table_create(1);
+ ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = tbl;
+ }
+ val = INT2FIX(ISEQ_BODY(iseq)->ivc_size++);
+ rb_id_table_insert(tbl,id,val);
+ return val;
}
static inline VALUE
@@ -2459,13 +2472,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
generated_iseq[code_index + 1 + j] = (VALUE)ic;
}
break;
- case TS_IVC: /* inline ivar cache */
- {
- unsigned int ic_index = FIX2UINT(operands[j]);
- vm_ic_attr_index_initialize(((IVC)&body->is_entries[ic_index]), INVALID_SHAPE_ID);
- }
case TS_ISE: /* inline storage entry: `once` insn */
case TS_ICVARC: /* inline cvar cache */
+ case TS_IVC: /* inline ivar cache */
{
unsigned int ic_index = FIX2UINT(operands[j]);
IC ic = &ISEQ_IS_ENTRY_START(body, type)[ic_index].ic_cache;
@@ -11505,11 +11514,6 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
ISE ic = ISEQ_IS_ENTRY_START(load_body, operand_type) + op;
code[code_index] = (VALUE)ic;
-
- if (operand_type == TS_IVC) {
- vm_ic_attr_index_initialize(((IVC)code[code_index]), INVALID_SHAPE_ID);
- }
-
}
break;
case TS_CALLDATA:
diff --git a/debug_counter.h b/debug_counter.h
index 256633727f..c6f4176e97 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -130,6 +130,7 @@ RB_DEBUG_COUNTER(frame_C2R)
/* instance variable counts
*
* * ivar_get_ic_hit/miss: ivar_get inline cache (ic) hit/miss counts (VM insn)
+ * * ivar_get_ic_miss_serial: ivar_get ic miss reason by serial (VM insn)
* * ivar_get_ic_miss_unset: ... by unset (VM insn)
* * ivar_get_ic_miss_noobject: ... by "not T_OBJECT" (VM insn)
* * ivar_set_...: same counts with ivar_set (VM insn)
@@ -139,17 +140,17 @@ RB_DEBUG_COUNTER(frame_C2R)
*/
RB_DEBUG_COUNTER(ivar_get_ic_hit)
RB_DEBUG_COUNTER(ivar_get_ic_miss)
+RB_DEBUG_COUNTER(ivar_get_ic_miss_serial)
+RB_DEBUG_COUNTER(ivar_get_ic_miss_unset)
RB_DEBUG_COUNTER(ivar_get_ic_miss_noobject)
RB_DEBUG_COUNTER(ivar_set_ic_hit)
RB_DEBUG_COUNTER(ivar_set_ic_miss)
+RB_DEBUG_COUNTER(ivar_set_ic_miss_serial)
+RB_DEBUG_COUNTER(ivar_set_ic_miss_unset)
RB_DEBUG_COUNTER(ivar_set_ic_miss_iv_hit)
RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject)
RB_DEBUG_COUNTER(ivar_get_base)
RB_DEBUG_COUNTER(ivar_set_base)
-RB_DEBUG_COUNTER(ivar_get_ic_miss_set)
-RB_DEBUG_COUNTER(ivar_get_cc_miss_set)
-RB_DEBUG_COUNTER(ivar_get_ic_miss_unset)
-RB_DEBUG_COUNTER(ivar_get_cc_miss_unset)
/* local variable counts
*
@@ -320,7 +321,6 @@ RB_DEBUG_COUNTER(obj_imemo_parser_strterm)
RB_DEBUG_COUNTER(obj_imemo_callinfo)
RB_DEBUG_COUNTER(obj_imemo_callcache)
RB_DEBUG_COUNTER(obj_imemo_constcache)
-RB_DEBUG_COUNTER(obj_imemo_shape)
/* ar_table */
RB_DEBUG_COUNTER(artable_hint_hit)
diff --git a/ext/coverage/depend b/ext/coverage/depend
index 719c6c6e79..57d368d3f5 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -165,9 +165,7 @@ coverage.o: $(top_srcdir)/ccan/check_type/check_type.h
coverage.o: $(top_srcdir)/ccan/container_of/container_of.h
coverage.o: $(top_srcdir)/ccan/list/list.h
coverage.o: $(top_srcdir)/ccan/str/str.h
-coverage.o: $(top_srcdir)/constant.h
coverage.o: $(top_srcdir)/gc.h
-coverage.o: $(top_srcdir)/id_table.h
coverage.o: $(top_srcdir)/internal.h
coverage.o: $(top_srcdir)/internal/array.h
coverage.o: $(top_srcdir)/internal/compilers.h
@@ -178,14 +176,12 @@ coverage.o: $(top_srcdir)/internal/sanitizers.h
coverage.o: $(top_srcdir)/internal/serial.h
coverage.o: $(top_srcdir)/internal/static_assert.h
coverage.o: $(top_srcdir)/internal/thread.h
-coverage.o: $(top_srcdir)/internal/variable.h
coverage.o: $(top_srcdir)/internal/vm.h
coverage.o: $(top_srcdir)/internal/warnings.h
coverage.o: $(top_srcdir)/method.h
coverage.o: $(top_srcdir)/node.h
coverage.o: $(top_srcdir)/ruby_assert.h
coverage.o: $(top_srcdir)/ruby_atomic.h
-coverage.o: $(top_srcdir)/shape.h
coverage.o: $(top_srcdir)/thread_pthread.h
coverage.o: $(top_srcdir)/vm_core.h
coverage.o: $(top_srcdir)/vm_opts.h
diff --git a/ext/objspace/depend b/ext/objspace/depend
index 88c66a232b..c4da8031cc 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -350,7 +350,6 @@ objspace.o: $(top_srcdir)/internal/serial.h
objspace.o: $(top_srcdir)/internal/static_assert.h
objspace.o: $(top_srcdir)/internal/warnings.h
objspace.o: $(top_srcdir)/node.h
-objspace.o: $(top_srcdir)/shape.h
objspace.o: $(top_srcdir)/symbol.h
objspace.o: objspace.c
objspace.o: {$(VPATH)}id.h
@@ -534,9 +533,7 @@ objspace_dump.o: $(top_srcdir)/ccan/check_type/check_type.h
objspace_dump.o: $(top_srcdir)/ccan/container_of/container_of.h
objspace_dump.o: $(top_srcdir)/ccan/list/list.h
objspace_dump.o: $(top_srcdir)/ccan/str/str.h
-objspace_dump.o: $(top_srcdir)/constant.h
objspace_dump.o: $(top_srcdir)/gc.h
-objspace_dump.o: $(top_srcdir)/id_table.h
objspace_dump.o: $(top_srcdir)/internal.h
objspace_dump.o: $(top_srcdir)/internal/array.h
objspace_dump.o: $(top_srcdir)/internal/compilers.h
@@ -547,14 +544,12 @@ objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
objspace_dump.o: $(top_srcdir)/internal/serial.h
objspace_dump.o: $(top_srcdir)/internal/static_assert.h
objspace_dump.o: $(top_srcdir)/internal/string.h
-objspace_dump.o: $(top_srcdir)/internal/variable.h
objspace_dump.o: $(top_srcdir)/internal/vm.h
objspace_dump.o: $(top_srcdir)/internal/warnings.h
objspace_dump.o: $(top_srcdir)/method.h
objspace_dump.o: $(top_srcdir)/node.h
objspace_dump.o: $(top_srcdir)/ruby_assert.h
objspace_dump.o: $(top_srcdir)/ruby_atomic.h
-objspace_dump.o: $(top_srcdir)/shape.h
objspace_dump.o: $(top_srcdir)/thread_pthread.h
objspace_dump.o: $(top_srcdir)/vm_core.h
objspace_dump.o: $(top_srcdir)/vm_opts.h
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 364d36e696..0b1b094325 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -644,7 +644,6 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
INIT_IMEMO_TYPE_ID(imemo_callinfo);
INIT_IMEMO_TYPE_ID(imemo_callcache);
INIT_IMEMO_TYPE_ID(imemo_constcache);
- INIT_IMEMO_TYPE_ID(imemo_shape);
#undef INIT_IMEMO_TYPE_ID
}
diff --git a/gc.c b/gc.c
index 77e2d1aeb8..d026139d7b 100644
--- a/gc.c
+++ b/gc.c
@@ -2895,7 +2895,8 @@ rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected)
GC_ASSERT((flags & RUBY_T_MASK) == T_OBJECT);
GC_ASSERT(flags & ROBJECT_EMBED);
- uint32_t index_tbl_num_entries = RCLASS_EXT(klass)->max_iv_count;
+ st_table *index_tbl = RCLASS_IV_INDEX_TBL(klass);
+ uint32_t index_tbl_num_entries = index_tbl == NULL ? 0 : (uint32_t)index_tbl->num_entries;
size_t size;
bool embed = true;
@@ -2930,7 +2931,7 @@ rb_class_instance_allocate_internal(VALUE klass, VALUE flags, bool wb_protected)
#endif
}
else {
- rb_ensure_iv_list_size(obj, 0, index_tbl_num_entries);
+ rb_init_iv_list(obj);
}
return obj;
@@ -2971,7 +2972,6 @@ rb_imemo_name(enum imemo_type type)
IMEMO_NAME(callinfo);
IMEMO_NAME(callcache);
IMEMO_NAME(constcache);
- IMEMO_NAME(shape);
#undef IMEMO_NAME
}
return "unknown";
@@ -3018,14 +3018,6 @@ imemo_memsize(VALUE obj)
case imemo_iseq:
size += rb_iseq_memsize((rb_iseq_t *)obj);
break;
- case imemo_shape:
- {
- struct rb_id_table* edges = ((rb_shape_t *) obj)->edges;
- if (edges) {
- size += rb_id_table_memsize(edges);
- }
- break;
- }
case imemo_env:
size += RANY(obj)->as.imemo.env.env_size * sizeof(VALUE);
break;
@@ -3214,6 +3206,20 @@ rb_free_const_table(struct rb_id_table *tbl)
rb_id_table_free(tbl);
}
+static int
+free_iv_index_tbl_free_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ xfree((void *)value);
+ return ST_CONTINUE;
+}
+
+static void
+iv_index_tbl_free(struct st_table *tbl)
+{
+ st_foreach(tbl, free_iv_index_tbl_free_i, 0);
+ st_free_table(tbl);
+}
+
// alive: if false, target pointers can be freed already.
// To check it, we need objspace parameter.
static void
@@ -3381,22 +3387,6 @@ obj_free_object_id(rb_objspace_t *objspace, VALUE obj)
}
}
-static enum rb_id_table_iterator_result
-remove_child_shapes_parent(VALUE value, void *ref)
-{
- rb_shape_t * shape = (rb_shape_t *) value;
- GC_ASSERT(IMEMO_TYPE_P(shape, imemo_shape));
-
- // If both objects live on the same page and we're currently
- // sweeping that page, then we need to assert that neither are marked
- if (GET_HEAP_PAGE(shape) == GET_HEAP_PAGE(shape->parent)) {
- GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(shape), shape));
- }
-
- shape->parent = NULL;
- return ID_TABLE_CONTINUE;
-}
-
static int
obj_free(rb_objspace_t *objspace, VALUE obj)
{
@@ -3445,19 +3435,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
RB_DEBUG_COUNTER_INC(obj_obj_transient);
}
else {
- // A shape can be collected before an object is collected (if both
- // happened to be garbage at the same time), so when we look up the shape, _do not_
- // assert that the shape is an IMEMO because it could be null
- rb_shape_t *shape = rb_shape_get_shape_by_id_without_assertion(ROBJECT_SHAPE_ID(obj));
- if (shape) {
- VALUE klass = RBASIC_CLASS(obj);
-
- // Increment max_iv_count if applicable, used to determine size pool allocation
- uint32_t num_of_ivs = shape->iv_count;
- if (RCLASS_EXT(klass)->max_iv_count < num_of_ivs) {
- RCLASS_EXT(klass)->max_iv_count = num_of_ivs;
- }
- }
xfree(RANY(obj)->as.object.as.heap.ivptr);
RB_DEBUG_COUNTER_INC(obj_obj_ptr);
}
@@ -3472,6 +3449,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
if (RCLASS_CONST_TBL(obj)) {
rb_free_const_table(RCLASS_CONST_TBL(obj));
}
+ if (RCLASS_IV_INDEX_TBL(obj)) {
+ iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj));
+ }
if (RCLASS_CVC_TBL(obj)) {
rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL);
rb_id_table_free(RCLASS_CVC_TBL(obj));
@@ -3748,37 +3728,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case imemo_constcache:
RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
break;
- case imemo_shape:
- {
- rb_shape_t *shape = (rb_shape_t *)obj;
- rb_shape_t *parent = shape->parent;
-
- if (parent) {
- RUBY_ASSERT(IMEMO_TYPE_P(parent, imemo_shape));
- RUBY_ASSERT(parent->edges);
- VALUE res; // Only used to temporarily store lookup value
- if (rb_id_table_lookup(parent->edges, shape->edge_name, &res)) {
- if ((rb_shape_t *)res == shape) {
- rb_id_table_delete(parent->edges, shape->edge_name);
- }
- }
- else {
- rb_bug("Edge %s should exist", rb_id2name(shape->edge_name));
- }
- }
- if (shape->edges) {
- rb_id_table_foreach_values(shape->edges, remove_child_shapes_parent, NULL);
- rb_id_table_free(shape->edges);
- shape->edges = NULL;
- }
-
- shape->parent = NULL;
-
- rb_shape_set_shape_by_id(SHAPE_ID(shape), NULL);
-
- RB_DEBUG_COUNTER_INC(obj_imemo_shape);
- break;
- }
}
return TRUE;
@@ -4924,6 +4873,10 @@ obj_memsize_of(VALUE obj, int use_all_types)
if (RCLASS_CVC_TBL(obj)) {
size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
}
+ if (RCLASS_IV_INDEX_TBL(obj)) {
+ // TODO: more correct value
+ size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
+ }
if (RCLASS_EXT(obj)->iv_tbl) {
size += st_memsize(RCLASS_EXT(obj)->iv_tbl);
}
@@ -7201,21 +7154,6 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
const struct rb_callcache *cc = (const struct rb_callcache *)obj;
// should not mark klass here
gc_mark(objspace, (VALUE)vm_cc_cme(cc));
-
- // Check it's an attr_(reader|writer)
- if (cc->cme_ && (cc->cme_->def->type == VM_METHOD_TYPE_ATTRSET ||
- cc->cme_->def->type == VM_METHOD_TYPE_IVAR)) {
- shape_id_t source_shape_id = vm_cc_attr_index_source_shape_id(cc);
- shape_id_t dest_shape_id = vm_cc_attr_index_dest_shape_id(cc);
- if (source_shape_id != INVALID_SHAPE_ID) {
- rb_shape_t *shape = rb_shape_get_shape_by_id(source_shape_id);
- rb_gc_mark((VALUE)shape);
- }
- if (dest_shape_id != INVALID_SHAPE_ID) {
- rb_shape_t *shape = rb_shape_get_shape_by_id(dest_shape_id);
- rb_gc_mark((VALUE)shape);
- }
- }
}
return;
case imemo_constcache:
@@ -7224,14 +7162,6 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, ice->value);
}
return;
- case imemo_shape:
- {
- rb_shape_t *shape = (rb_shape_t *)obj;
- if (shape->edges) {
- mark_m_tbl(objspace, shape->edges);
- }
- }
- return;
#if VM_CHECK_MODE > 0
default:
VM_UNREACHABLE(gc_mark_imemo);
@@ -9835,10 +9765,6 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
GC_ASSERT(!SPECIAL_CONST_P(obj));
switch (BUILTIN_TYPE(obj)) {
- case T_IMEMO:
- if (IMEMO_TYPE_P(obj, imemo_shape)) {
- return FALSE;
- }
case T_NONE:
case T_NIL:
case T_MOVED:
@@ -9852,6 +9778,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
case T_STRING:
case T_OBJECT:
case T_FLOAT:
+ case T_IMEMO:
case T_ARRAY:
case T_BIGNUM:
case T_ICLASS:
@@ -10251,38 +10178,6 @@ gc_update_values(rb_objspace_t *objspace, long n, VALUE *values)
}
}
-static enum rb_id_table_iterator_result
-check_id_table_move(VALUE value, void *data)
-{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
-
- if (gc_object_moved_p(objspace, (VALUE)value)) {
- return ID_TABLE_REPLACE;
- }
-
- return ID_TABLE_CONTINUE;
-}
-
-static enum rb_id_table_iterator_result
-update_id_table(VALUE *value, void *data, int existing)
-{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
-
- if (gc_object_moved_p(objspace, (VALUE)*value)) {
- *value = rb_gc_location((VALUE)*value);
- }
-
- return ID_TABLE_CONTINUE;
-}
-
-static void
-update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
-{
- if (tbl) {
- rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace);
- }
-}
-
static void
gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
{
@@ -10355,23 +10250,24 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
case imemo_tmpbuf:
case imemo_callinfo:
break;
- case imemo_shape:
- {
- rb_shape_t * shape = (rb_shape_t *)obj;
- if(shape->edges) {
- update_m_tbl(objspace, shape->edges);
- }
- if (shape->parent) {
- shape->parent = (rb_shape_t *)rb_gc_location((VALUE)shape->parent);
- }
- }
- break;
default:
rb_bug("not reachable %d", imemo_type(obj));
break;
}
}
+static enum rb_id_table_iterator_result
+check_id_table_move(VALUE value, void *data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+
+ if (gc_object_moved_p(objspace, (VALUE)value)) {
+ return ID_TABLE_REPLACE;
+ }
+
+ return ID_TABLE_CONTINUE;
+}
+
/* Returns the new location of an object, if it moved. Otherwise returns
* the existing location. */
VALUE
@@ -10405,6 +10301,26 @@ rb_gc_location(VALUE value)
}
static enum rb_id_table_iterator_result
+update_id_table(VALUE *value, void *data, int existing)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+
+ if (gc_object_moved_p(objspace, (VALUE)*value)) {
+ *value = rb_gc_location((VALUE)*value);
+ }
+
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
+{
+ if (tbl) {
+ rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace);
+ }
+}
+
+static enum rb_id_table_iterator_result
update_cc_tbl_i(VALUE ccs_ptr, void *data)
{
rb_objspace_t *objspace = (rb_objspace_t *)data;
@@ -10491,6 +10407,15 @@ update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry)
}
}
+static int
+update_iv_index_tbl_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)arg;
+ struct rb_iv_index_tbl_entry *ent = (struct rb_iv_index_tbl_entry *)value;
+ UPDATE_IF_MOVED(objspace, ent->class_value);
+ return ST_CONTINUE;
+}
+
static void
update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext)
{
@@ -10498,6 +10423,11 @@ update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext)
UPDATE_IF_MOVED(objspace, ext->includer);
UPDATE_IF_MOVED(objspace, ext->refined_class);
update_subclass_entries(objspace, ext->subclasses);
+
+ // ext->iv_index_tbl
+ if (ext->iv_index_tbl) {
+ st_foreach(ext->iv_index_tbl, update_iv_index_tbl_i, (st_data_t)objspace);
+ }
}
static void
@@ -10739,8 +10669,6 @@ gc_update_references(rb_objspace_t *objspace)
struct heap_page *page = NULL;
- rb_vm_update_references(vm);
-
for (int i = 0; i < SIZE_POOL_COUNT; i++) {
bool should_set_mark_bits = TRUE;
rb_size_pool_t *size_pool = &size_pools[i];
@@ -10759,6 +10687,7 @@ gc_update_references(rb_objspace_t *objspace)
}
}
}
+ rb_vm_update_references(vm);
rb_transient_heap_update_references();
rb_gc_update_global_tbl();
global_symbols.ids = rb_gc_location(global_symbols.ids);
diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h
index bec0b45fd4..7823061d8f 100644
--- a/include/ruby/internal/core/robject.h
+++ b/include/ruby/internal/core/robject.h
@@ -46,6 +46,7 @@
#define ROBJECT_EMBED ROBJECT_EMBED
#define ROBJECT_NUMIV ROBJECT_NUMIV
#define ROBJECT_IVPTR ROBJECT_IVPTR
+#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL
/** @endcond */
/**
@@ -131,7 +132,7 @@ struct RObject {
*
* This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`.
*/
- struct rb_id_table *iv_index_tbl;
+ struct st_table *iv_index_tbl;
} heap;
#if USE_RVARGC
diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h
index 7383426b23..c51bd2e9d9 100644
--- a/include/ruby/internal/fl_type.h
+++ b/include/ruby/internal/fl_type.h
@@ -941,8 +941,21 @@ RB_OBJ_FREEZE_RAW(VALUE obj)
RB_FL_SET_RAW(obj, RUBY_FL_FREEZE);
}
-RUBY_SYMBOL_EXPORT_BEGIN
-void rb_obj_freeze_inline(VALUE obj);
-RUBY_SYMBOL_EXPORT_END
+/**
+ * Prevents further modifications to the given object. ::rb_eFrozenError shall
+ * be raised if modification is attempted.
+ *
+ * @param[out] x Object in question.
+ */
+static inline void
+rb_obj_freeze_inline(VALUE x)
+{
+ if (RB_FL_ABLE(x)) {
+ RB_OBJ_FREEZE_RAW(x);
+ if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) {
+ rb_freeze_singleton_class(x);
+ }
+ }
+}
#endif /* RBIMPL_FL_TYPE_H */
diff --git a/inits.c b/inits.c
index d1204c1324..9decba3c11 100644
--- a/inits.c
+++ b/inits.c
@@ -77,7 +77,6 @@ rb_call_inits(void)
CALL(vm_stack_canary);
CALL(ast);
CALL(gc_stress);
- CALL(shape);
// enable builtin loading
CALL(builtin);
diff --git a/internal.h b/internal.h
index 695c9cfb7e..0740ae99e5 100644
--- a/internal.h
+++ b/internal.h
@@ -48,6 +48,9 @@
#undef RHASH_TBL
#undef RHASH_EMPTY_P
+/* internal/object.h */
+#undef ROBJECT_IV_INDEX_TBL
+
/* internal/struct.h */
#undef RSTRUCT_LEN
#undef RSTRUCT_PTR
diff --git a/internal/class.h b/internal/class.h
index 36635d6eaa..ae680564a6 100644
--- a/internal/class.h
+++ b/internal/class.h
@@ -14,7 +14,6 @@
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/intern.h" /* for rb_alloc_func_t */
#include "ruby/ruby.h" /* for struct RBasic */
-#include "shape.h"
#ifdef RCLASS_SUPER
# undef RCLASS_SUPER
@@ -27,9 +26,9 @@ struct rb_subclass_entry {
};
struct rb_iv_index_tbl_entry {
- uint32_t idx;
- shape_id_t source_shape_id;
- shape_id_t dest_shape_id;
+ uint32_t index;
+ rb_serial_t class_serial;
+ VALUE class_value;
};
struct rb_cvar_class_tbl_entry {
@@ -39,6 +38,7 @@ struct rb_cvar_class_tbl_entry {
};
struct rb_classext_struct {
+ struct st_table *iv_index_tbl; // ID -> struct rb_iv_index_tbl_entry
struct st_table *iv_tbl;
#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */
struct rb_id_table *m_tbl;
@@ -64,8 +64,6 @@ struct rb_classext_struct {
const VALUE refined_class;
rb_alloc_func_t allocator;
const VALUE includer;
- uint32_t max_iv_count;
- uint16_t shape_id;
};
struct RClass {
@@ -104,6 +102,7 @@ typedef struct rb_classext_struct rb_classext_t;
#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
#define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl)
#define RCLASS_CVC_TBL(c) (RCLASS_EXT(c)->cvc_tbl)
+#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl)
#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_)
#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
#if SIZEOF_SERIAL_T == SIZEOF_VALUE
diff --git a/internal/imemo.h b/internal/imemo.h
index 20bfff8d7c..91b524e0a6 100644
--- a/internal/imemo.h
+++ b/internal/imemo.h
@@ -45,7 +45,6 @@ enum imemo_type {
imemo_callinfo = 11,
imemo_callcache = 12,
imemo_constcache = 13,
- imemo_shape = 14,
};
/* CREF (Class REFerence) is defined in method.h */
diff --git a/internal/object.h b/internal/object.h
index 7b54e13dd2..88f3a44bc6 100644
--- a/internal/object.h
+++ b/internal/object.h
@@ -9,6 +9,11 @@
* @brief Internal header for Object.
*/
#include "ruby/ruby.h" /* for VALUE */
+#include "internal/class.h" /* for RCLASS_IV_INDEX_TBL */
+
+#ifdef ROBJECT_IV_INDEX_TBL
+# undef ROBJECT_IV_INDEX_TBL
+#endif
/* object.c */
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
@@ -21,6 +26,7 @@ int rb_bool_expected(VALUE, const char *, int raise);
static inline void RBASIC_CLEAR_CLASS(VALUE obj);
static inline void RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass);
static inline void RBASIC_SET_CLASS(VALUE obj, VALUE klass);
+static inline struct st_table *ROBJECT_IV_INDEX_TBL_inline(VALUE obj);
RUBY_SYMBOL_EXPORT_BEGIN
/* object.c (export) */
@@ -58,4 +64,20 @@ RBASIC_SET_CLASS(VALUE obj, VALUE klass)
RBASIC_SET_CLASS_RAW(obj, klass);
RB_OBJ_WRITTEN(obj, oldv, klass);
}
+
+RBIMPL_ATTR_PURE()
+static inline struct st_table *
+ROBJECT_IV_INDEX_TBL_inline(VALUE obj)
+{
+ if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) {
+ VALUE klass = rb_obj_class(obj);
+ return RCLASS_IV_INDEX_TBL(klass);
+ }
+ else {
+ const struct RObject *const ptr = ROBJECT(obj);
+ return ptr->as.heap.iv_index_tbl;
+ }
+}
+#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL_inline
+
#endif /* INTERNAL_OBJECT_H */
diff --git a/internal/variable.h b/internal/variable.h
index 47037a3392..1a19e8964b 100644
--- a/internal/variable.h
+++ b/internal/variable.h
@@ -37,9 +37,6 @@ static inline void ROBJ_TRANSIENT_SET(VALUE obj);
static inline void ROBJ_TRANSIENT_UNSET(VALUE obj);
uint32_t rb_obj_ensure_iv_index_mapping(VALUE obj, ID id);
-struct gen_ivtbl;
-int rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl);
-
RUBY_SYMBOL_EXPORT_BEGIN
/* variable.c (export) */
void rb_mark_generic_ivar(VALUE);
@@ -55,8 +52,6 @@ VALUE rb_gvar_set(ID, VALUE);
VALUE rb_gvar_defined(ID);
void rb_const_warn_if_deprecated(const rb_const_entry_t *, VALUE, ID);
void rb_init_iv_list(VALUE obj);
-void rb_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize);
-struct gen_ivtbl * rb_ensure_generic_iv_list_size(VALUE obj, uint32_t newsize);
MJIT_SYMBOL_EXPORT_END
static inline bool
diff --git a/iseq.c b/iseq.c
index 7014162a19..a4792d81fd 100644
--- a/iseq.c
+++ b/iseq.c
@@ -233,15 +233,13 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data)
// IVC entries
for (unsigned int i = 0; i < body->ivc_size; i++, is_entries++) {
IVC ivc = (IVC)is_entries;
- shape_id_t source_shape_id = vm_ic_attr_index_source_shape_id(ivc);
- shape_id_t dest_shape_id = vm_ic_attr_index_dest_shape_id(ivc);
- if (source_shape_id != INVALID_SHAPE_ID) {
- rb_shape_t *shape = rb_shape_get_shape_by_id(source_shape_id);
- func(data, (VALUE)shape);
- }
- if (dest_shape_id != INVALID_SHAPE_ID) {
- rb_shape_t *shape = rb_shape_get_shape_by_id(dest_shape_id);
- func(data, (VALUE)shape);
+ if (ivc->entry) {
+ RUBY_ASSERT(!RB_TYPE_P(ivc->entry->class_value, T_NONE));
+
+ VALUE nv = func(data, ivc->entry->class_value);
+ if (ivc->entry->class_value != nv) {
+ ivc->entry->class_value = nv;
+ }
}
}
diff --git a/lib/mjit/compiler.rb b/lib/mjit/compiler.rb
index 06f018c934..49f28ab690 100644
--- a/lib/mjit/compiler.rb
+++ b/lib/mjit/compiler.rb
@@ -73,6 +73,23 @@ module RubyVM::MJIT
src << "#undef GET_SELF\n"
src << "#define GET_SELF() cfp_self\n"
+ # Generate merged ivar guards first if needed
+ if !status.compile_info.disable_ivar_cache && status.merge_ivar_guards_p
+ src << " if (UNLIKELY(!(RB_TYPE_P(GET_SELF(), T_OBJECT) && (rb_serial_t)#{status.ivar_serial} == RCLASS_SERIAL(RBASIC(GET_SELF())->klass) &&"
+ if USE_RVARGC
+ src << "#{status.max_ivar_index} < ROBJECT_NUMIV(GET_SELF())" # index < ROBJECT_NUMIV(obj)
+ else
+ if status.max_ivar_index >= ROBJECT_EMBED_LEN_MAX
+ src << "#{status.max_ivar_index} < ROBJECT_NUMIV(GET_SELF())" # index < ROBJECT_NUMIV(obj) && !RB_FL_ANY_RAW(obj, ROBJECT_EMBED)
+ else
+ src << "ROBJECT_EMBED_LEN_MAX == ROBJECT_NUMIV(GET_SELF())" # index < ROBJECT_NUMIV(obj) && RB_FL_ANY_RAW(obj, ROBJECT_EMBED)
+ end
+ end
+ src << "))) {\n"
+ src << " goto ivar_cancel;\n"
+ src << " }\n"
+ end
+
# Simulate `opt_pc` in setup_parameters_complex. Other PCs which may be passed by catch tables
# are not considered since vm_exec doesn't call jit_exec for catch tables.
if iseq.body.param.flags.has_opt
@@ -86,13 +103,6 @@ module RubyVM::MJIT
src << " }\n"
end
- # Generate merged ivar guards first if needed
- if !status.compile_info.disable_ivar_cache && status.merge_ivar_guards_p
- src << " if (UNLIKELY(!(RB_TYPE_P(GET_SELF(), T_OBJECT)))) {"
- src << " goto ivar_cancel;\n"
- src << " }\n"
- end
-
C.fprintf(f, src)
compile_insns(0, 0, status, iseq.body, f)
compile_cancel_handler(f, iseq.body, status)
@@ -353,37 +363,52 @@ module RubyVM::MJIT
ic_copy = (status.is_entries + (C.iseq_inline_storage_entry.new(operands[1]) - body.is_entries)).iv_cache
src = +''
- if !status.compile_info.disable_ivar_cache && ic_copy.source_shape_id != C.INVALID_SHAPE_ID
+ if !status.compile_info.disable_ivar_cache && ic_copy.entry
# JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`.
# compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
# JIT: prepare vm_getivar/vm_setivar arguments and variables
src << "{\n"
src << " VALUE obj = GET_SELF();\n"
- src << " const shape_id_t source_shape_id = (rb_serial_t)#{ic_copy.source_shape_id};\n"
- # JIT: cache hit path of vm_getivar/vm_setivar, or cancel JIT (recompile it with exivar)
- if insn_name == :setinstancevariable
- src << " const uint32_t index = #{ic_copy.attr_index - 1};\n"
- src << " const shape_id_t dest_shape_id = (rb_serial_t)#{ic_copy.dest_shape_id};\n"
- src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj) && \n"
- src << " dest_shape_id != ROBJECT_SHAPE_ID(obj)) {\n"
- src << " if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {\n"
- src << " rb_init_iv_list(obj);\n"
- src << " }\n"
- src << " ROBJECT_SET_SHAPE_ID(obj, dest_shape_id);\n"
- src << " VALUE *ptr = ROBJECT_IVPTR(obj);\n"
- src << " RB_OBJ_WRITE(obj, &ptr[index], stack[#{stack_size - 1}]);\n"
- src << " }\n"
+ src << " const uint32_t index = #{ic_copy.entry.index};\n"
+ if status.merge_ivar_guards_p
+ # JIT: Access ivar without checking these VM_ASSERTed prerequisites as we checked them in the beginning of `mjit_compile_body`
+ src << " VM_ASSERT(RB_TYPE_P(obj, T_OBJECT));\n"
+ src << " VM_ASSERT((rb_serial_t)#{ic_copy.entry.class_serial} == RCLASS_SERIAL(RBASIC(obj)->klass));\n"
+ src << " VM_ASSERT(index < ROBJECT_NUMIV(obj));\n"
+ if insn_name == :setinstancevariable
+ if USE_RVARGC
+ src << " if (LIKELY(!RB_OBJ_FROZEN_RAW(obj) && index < ROBJECT_NUMIV(obj))) {\n"
+ src << " RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[index], stack[#{stack_size - 1}]);\n"
+ else
+ heap_ivar_p = status.max_ivar_index >= ROBJECT_EMBED_LEN_MAX
+ src << " if (LIKELY(!RB_OBJ_FROZEN_RAW(obj) && #{heap_ivar_p ? 'true' : 'RB_FL_ANY_RAW(obj, ROBJECT_EMBED)'})) {\n"
+ src << " RB_OBJ_WRITE(obj, &ROBJECT(obj)->as.#{heap_ivar_p ? 'heap.ivptr[index]' : 'ary[index]'}, stack[#{stack_size - 1}]);\n"
+ end
+ src << " }\n"
+ else
+ src << " VALUE val;\n"
+ if USE_RVARGC
+ src << " if (LIKELY(index < ROBJECT_NUMIV(obj) && (val = ROBJECT_IVPTR(obj)[index]) != Qundef)) {\n"
+ else
+ heap_ivar_p = status.max_ivar_index >= ROBJECT_EMBED_LEN_MAX
+ src << " if (LIKELY(#{heap_ivar_p ? 'true' : 'RB_FL_ANY_RAW(obj, ROBJECT_EMBED)'} && (val = ROBJECT(obj)->as.#{heap_ivar_p ? 'heap.ivptr[index]' : 'ary[index]'}) != Qundef)) {\n"
+ end
+ src << " stack[#{stack_size}] = val;\n"
+ src << " }\n"
+ end
else
- if ic_copy.attr_index == 0 # cache hit, but uninitialized iv
- src << " /* Uninitialized instance variable */\n"
- src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj)) {\n"
- src << " stack[#{stack_size}] = Qnil;\n"
+ src << " const rb_serial_t ic_serial = (rb_serial_t)#{ic_copy.entry.class_serial};\n"
+ # JIT: cache hit path of vm_getivar/vm_setivar, or cancel JIT (recompile it with exivar)
+ if insn_name == :setinstancevariable
+ src << " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && !RB_OBJ_FROZEN_RAW(obj))) {\n"
+ src << " VALUE *ptr = ROBJECT_IVPTR(obj);\n"
+ src << " RB_OBJ_WRITE(obj, &ptr[index], stack[#{stack_size - 1}]);\n"
src << " }\n"
else
- src << " const uint32_t index = #{ic_copy.attr_index - 1};\n"
- src << " if (source_shape_id == ROBJECT_SHAPE_ID(obj)) {\n"
- src << " stack[#{stack_size}] = ROBJECT_IVPTR(obj)[index];\n"
+ src << " VALUE val;\n"
+ src << " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && (val = ROBJECT_IVPTR(obj)[index]) != Qundef)) {\n"
+ src << " stack[#{stack_size}] = val;\n"
src << " }\n"
end
end
@@ -394,19 +419,20 @@ module RubyVM::MJIT
src << " }\n"
src << "}\n"
return src
- elsif insn_name == :getinstancevariable && !status.compile_info.disable_exivar_cache && ic_copy.source_shape_id != C.INVALID_SHAPE_ID
+ elsif insn_name == :getinstancevariable && !status.compile_info.disable_exivar_cache && ic_copy.entry
# JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`.
# compile_pc_and_sp(src, insn, stack_size, sp_inc, local_stack_p, next_pos)
# JIT: prepare vm_getivar's arguments and variables
src << "{\n"
src << " VALUE obj = GET_SELF();\n"
- src << " const shape_id_t source_shape_id = (rb_serial_t)#{ic_copy.source_shape_id};\n"
- src << " const uint32_t index = #{ic_copy.attr_index - 1};\n"
+ src << " const rb_serial_t ic_serial = (rb_serial_t)#{ic_copy.entry.class_serial};\n"
+ src << " const uint32_t index = #{ic_copy.entry.index};\n"
# JIT: cache hit path of vm_getivar, or cancel JIT (recompile it without any ivar optimization)
src << " struct gen_ivtbl *ivtbl;\n"
- src << " if (LIKELY(FL_TEST_RAW(obj, FL_EXIVAR) && source_shape_id == rb_shape_get_shape_id(obj) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl))) {\n"
- src << " stack[#{stack_size}] = ivtbl->ivptr[index];\n"
+ src << " VALUE val;\n"
+ src << " if (LIKELY(FL_TEST_RAW(obj, FL_EXIVAR) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl) && index < ivtbl->numiv && (val = ivtbl->ivptr[index]) != Qundef)) {\n"
+ src << " stack[#{stack_size}] = val;\n"
src << " }\n"
src << " else {\n"
src << " reg_cfp->pc = original_body_iseq + #{pos};\n"
@@ -806,16 +832,35 @@ module RubyVM::MJIT
def init_ivar_compile_status(body, status)
C.mjit_capture_is_entries(body, status.is_entries)
+ num_ivars = 0
pos = 0
+ status.max_ivar_index = 0
+ status.ivar_serial = 0
while pos < body.iseq_size
insn = INSNS.fetch(C.rb_vm_insn_decode(body.iseq_encoded[pos]))
if insn.name == :getinstancevariable || insn.name == :setinstancevariable
- status.merge_ivar_guards_p = true
- return
+ ic = body.iseq_encoded[pos+2]
+ ic_copy = (status.is_entries + (C.iseq_inline_storage_entry.new(ic) - body.is_entries)).iv_cache
+ if ic_copy.entry # Only initialized (ic_serial > 0) IVCs are optimized
+ num_ivars += 1
+
+ if status.max_ivar_index < ic_copy.entry.index
+ status.max_ivar_index = ic_copy.entry.index
+ end
+
+ if status.ivar_serial == 0
+ status.ivar_serial = ic_copy.entry.class_serial
+ elsif status.ivar_serial != ic_copy.entry.class_serial
+ # Multiple classes have used this ISeq. Give up assuming one serial.
+ status.merge_ivar_guards_p = false
+ return
+ end
+ end
end
pos += insn.len
end
+ status.merge_ivar_guards_p = status.ivar_serial > 0 && num_ivars >= 2
end
# Expand simple macro that doesn't require dynamic C code.
diff --git a/marshal.c b/marshal.c
index 59edbfe53a..e4b40c0607 100644
--- a/marshal.c
+++ b/marshal.c
@@ -39,7 +39,6 @@
#include "ruby/st.h"
#include "ruby/util.h"
#include "builtin.h"
-#include "shape.h"
#define BITSPERSHORT (2*CHAR_BIT)
#define SHORTMASK ((1<<BITSPERSHORT)-1)
@@ -623,6 +622,10 @@ w_obj_each(st_data_t key, st_data_t val, st_data_t a)
}
return ST_CONTINUE;
}
+ if (!ivarg->num_ivar) {
+ rb_raise(rb_eRuntimeError, "instance variable added to %"PRIsVALUE" instance",
+ CLASS_OF(arg->obj));
+ }
--ivarg->num_ivar;
w_symbol(ID2SYM(id), arg->arg);
w_object(value, arg->arg, arg->limit);
@@ -717,7 +720,6 @@ has_ivars(VALUE obj, VALUE encname, VALUE *ivobj)
static void
w_ivar_each(VALUE obj, st_index_t num, struct dump_call_arg *arg)
{
- shape_id_t shape_id = rb_shape_get_shape_id(arg->obj);
struct w_ivar_arg ivarg = {arg, num};
if (!num) return;
rb_ivar_foreach(obj, w_obj_each, (st_data_t)&ivarg);
@@ -725,10 +727,6 @@ w_ivar_each(VALUE obj, st_index_t num, struct dump_call_arg *arg)
rb_raise(rb_eRuntimeError, "instance variable removed from %"PRIsVALUE" instance",
CLASS_OF(arg->obj));
}
- if (shape_id != rb_shape_get_shape_id(arg->obj)) {
- rb_raise(rb_eRuntimeError, "instance variable added to %"PRIsVALUE" instance",
- CLASS_OF(arg->obj));
- }
}
static void
diff --git a/misc/lldb_cruby.py b/misc/lldb_cruby.py
index da97e28b69..595d54dfab 100755
--- a/misc/lldb_cruby.py
+++ b/misc/lldb_cruby.py
@@ -418,13 +418,9 @@ def lldb_inspect(debugger, target, result, val):
elif flType == RUBY_T_IMEMO:
# I'm not sure how to get IMEMO_MASK out of lldb. It's not in globals()
imemo_type = (flags >> RUBY_FL_USHIFT) & 0x0F # IMEMO_MASK
-
print("T_IMEMO: ", file=result)
append_command_output(debugger, "p (enum imemo_type) %d" % imemo_type, result)
- if imemo_type == imemo_shape:
- append_command_output(debugger, "p *(rb_shape_t *) %0#x" % val.GetValueAsUnsigned(), result)
- else:
- append_command_output(debugger, "p *(struct MEMO *) %0#x" % val.GetValueAsUnsigned(), result)
+ append_command_output(debugger, "p *(struct MEMO *) %0#x" % val.GetValueAsUnsigned(), result)
elif flType == RUBY_T_STRUCT:
tRTypedData = target.FindFirstType("struct RStruct").GetPointerType()
val = val.Cast(tRTypedData)
diff --git a/mjit_c.rb b/mjit_c.rb
index fd8991af3f..d8e5628bda 100644
--- a/mjit_c.rb
+++ b/mjit_c.rb
@@ -5,10 +5,6 @@ module RubyVM::MJIT
C = Object.new
class << C
- def SHAPE_BITS
- RubyVM::Shape::SHAPE_BITS
- end
-
def ROBJECT_EMBED_LEN_MAX
Primitive.cexpr! 'INT2NUM(RBIMPL_EMBED_LEN_MAX_OF(VALUE))'
end
@@ -169,14 +165,6 @@ module RubyVM::MJIT
Primitive.cexpr! %q{ INT2NUM(VM_METHOD_TYPE_ISEQ) }
end
- def C.INVALID_SHAPE_ID
- Primitive.cexpr! %q{ ULONG2NUM(INVALID_SHAPE_ID) }
- end
-
- def C.SHAPE_MASK
- Primitive.cexpr! %q{ ULONG2NUM(SHAPE_MASK) }
- end
-
def C.CALL_DATA
@CALL_DATA ||= self.rb_call_data
end
@@ -193,10 +181,6 @@ module RubyVM::MJIT
@RB_BUILTIN ||= self.rb_builtin_function
end
- def C.attr_index_t
- @attr_index_t ||= CType::Immediate.parse("uint32_t")
- end
-
def C.compile_branch
@compile_branch ||= CType::Struct.new(
"compile_branch", Primitive.cexpr!("SIZEOF(struct compile_branch)"),
@@ -217,6 +201,7 @@ module RubyVM::MJIT
compiled_id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compiled_id)")],
compile_info: [CType::Pointer.new { self.rb_mjit_compile_info }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), compile_info)")],
merge_ivar_guards_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), merge_ivar_guards_p)")],
+ ivar_serial: [self.rb_serial_t, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), ivar_serial)")],
max_ivar_index: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), max_ivar_index)")],
inlined_iseqs: [CType::Pointer.new { CType::Pointer.new { self.rb_iseq_constant_body } }, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inlined_iseqs)")],
inline_context: [self.inlined_call_context, Primitive.cexpr!("OFFSETOF((*((struct compile_status *)NULL)), inline_context)")],
@@ -255,9 +240,7 @@ module RubyVM::MJIT
def C.iseq_inline_iv_cache_entry
@iseq_inline_iv_cache_entry ||= CType::Struct.new(
"iseq_inline_iv_cache_entry", Primitive.cexpr!("SIZEOF(struct iseq_inline_iv_cache_entry)"),
- source_shape_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), source_shape_id)")],
- dest_shape_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), dest_shape_id)")],
- attr_index: [self.attr_index_t, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), attr_index)")],
+ entry: [CType::Pointer.new { self.rb_iv_index_tbl_entry }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), entry)")],
)
end
@@ -330,11 +313,7 @@ module RubyVM::MJIT
call_: [self.vm_call_handler, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), call_)")],
aux_: [CType::Union.new(
"", Primitive.cexpr!("SIZEOF(((struct rb_callcache *)NULL)->aux_)"),
- attr: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_callcache *)NULL)->aux_.attr)"),
- index: [self.attr_index_t, Primitive.cexpr!("OFFSETOF(((struct rb_callcache *)NULL)->aux_.attr, index)")],
- dest_shape_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF(((struct rb_callcache *)NULL)->aux_.attr, dest_shape_id)")],
- ),
+ attr_index: CType::Immediate.parse("unsigned int"),
method_missing_reason: self.method_missing_reason,
v: self.VALUE,
), Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), aux_)")],
@@ -523,9 +502,9 @@ module RubyVM::MJIT
def C.rb_iv_index_tbl_entry
@rb_iv_index_tbl_entry ||= CType::Struct.new(
"rb_iv_index_tbl_entry", Primitive.cexpr!("SIZEOF(struct rb_iv_index_tbl_entry)"),
- idx: [CType::Immediate.parse("uint32_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_iv_index_tbl_entry *)NULL)), idx)")],
- source_shape_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iv_index_tbl_entry *)NULL)), source_shape_id)")],
- dest_shape_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iv_index_tbl_entry *)NULL)), dest_shape_id)")],
+ index: [CType::Immediate.parse("uint32_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_iv_index_tbl_entry *)NULL)), index)")],
+ class_serial: [self.rb_serial_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iv_index_tbl_entry *)NULL)), class_serial)")],
+ class_value: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iv_index_tbl_entry *)NULL)), class_value)")],
)
end
@@ -598,10 +577,6 @@ module RubyVM::MJIT
@VALUE ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(VALUE)"), Primitive.cexpr!("SIGNED_TYPE_P(VALUE)"))
end
- def C.shape_id_t
- @shape_id_t ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(shape_id_t)"), Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)"))
- end
-
def C._Bool
CType::Bool.new
end
diff --git a/mjit_compiler.h b/mjit_compiler.h
index b465be00fd..da79054420 100644
--- a/mjit_compiler.h
+++ b/mjit_compiler.h
@@ -8,7 +8,6 @@
#include "builtin.h"
#include "mjit.h"
#include "mjit_unit.h"
-#include "shape.h"
// Macros to check if a position is already compiled using compile_status.stack_size_for_pos
#define NOT_COMPILED_STACK_SIZE -1
@@ -49,6 +48,7 @@ struct compile_status {
// Mutated optimization levels
struct rb_mjit_compile_info *compile_info;
bool merge_ivar_guards_p; // If true, merge guards of ivar accesses
+ rb_serial_t ivar_serial; // ic_serial of IVC in is_entries (used only when merge_ivar_guards_p)
size_t max_ivar_index; // Max IVC index in is_entries (used only when merge_ivar_guards_p)
// If `inlined_iseqs[pos]` is not NULL, `mjit_compile_body` tries to inline ISeq there.
const struct rb_iseq_constant_body **inlined_iseqs;
diff --git a/object.c b/object.c
index 213f9760be..2328b20757 100644
--- a/object.c
+++ b/object.c
@@ -39,7 +39,6 @@
#include "ruby/util.h"
#include "ruby/assert.h"
#include "builtin.h"
-#include "shape.h"
/*!
* \addtogroup object
@@ -272,33 +271,9 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
VALUE *src_buf = ROBJECT_IVPTR(obj);
uint32_t dest_len = ROBJECT_NUMIV(dest);
uint32_t src_len = ROBJECT_NUMIV(obj);
- uint32_t max_len = dest_len < src_len ? src_len : dest_len;
+ uint32_t len = dest_len < src_len ? dest_len : src_len;
- rb_ensure_iv_list_size(dest, dest_len, max_len);
-
- dest_len = ROBJECT_NUMIV(dest);
- uint32_t min_len = dest_len > src_len ? src_len : dest_len;
-
- if (RBASIC(obj)->flags & ROBJECT_EMBED) {
- src_buf = ROBJECT(obj)->as.ary;
-
- // embedded -> embedded
- if (RBASIC(dest)->flags & ROBJECT_EMBED) {
- dest_buf = ROBJECT(dest)->as.ary;
- }
- // embedded -> extended
- else {
- dest_buf = ROBJECT(dest)->as.heap.ivptr;
- }
- }
- // extended -> extended
- else {
- RUBY_ASSERT(!(RBASIC(dest)->flags & ROBJECT_EMBED));
- dest_buf = ROBJECT(dest)->as.heap.ivptr;
- src_buf = ROBJECT(obj)->as.heap.ivptr;
- }
-
- MEMCPY(dest_buf, src_buf, VALUE, min_len);
+ MEMCPY(dest_buf, src_buf, VALUE, len);
}
static void
@@ -308,23 +283,10 @@ init_copy(VALUE dest, VALUE obj)
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
- // Copies the shape id from obj to dest
RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR);
rb_copy_wb_protected_attribute(dest, obj);
rb_copy_generic_ivar(dest, obj);
rb_gc_copy_finalizer(dest, obj);
-
- rb_shape_t *shape_to_set = rb_shape_get_shape(obj);
-
- // If the object is frozen, the "dup"'d object will *not* be frozen,
- // so we need to copy the frozen shape's parent to the new object.
- if (rb_shape_frozen_shape_p(shape_to_set)) {
- shape_to_set = shape_to_set->parent;
- }
-
- // shape ids are different
- rb_shape_set_shape(dest, shape_to_set);
-
if (RB_TYPE_P(obj, T_OBJECT)) {
rb_obj_copy_ivar(dest, obj);
}
@@ -430,9 +392,6 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze)
case Qnil:
rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
- if (RB_OBJ_FROZEN(obj)) {
- rb_shape_transition_shape_frozen(clone);
- }
break;
case Qtrue:
{
@@ -448,7 +407,6 @@ mutable_obj_clone(VALUE obj, VALUE kwfreeze)
argv[1] = freeze_true_hash;
rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS);
RBASIC(clone)->flags |= FL_FREEZE;
- rb_shape_transition_shape_frozen(clone);
break;
}
case Qfalse:
diff --git a/ractor_core.h b/ractor_core.h
index 9d4b8387c7..a065f5f809 100644
--- a/ractor_core.h
+++ b/ractor_core.h
@@ -289,13 +289,11 @@ rb_ractor_id(const rb_ractor_t *r)
#if RACTOR_CHECK_MODE > 0
uint32_t rb_ractor_current_id(void);
-// If ractor check mode is enabled, shape bits needs to be smaller
-STATIC_ASSERT(shape_bits, SHAPE_BITS == 16);
static inline void
rb_ractor_setup_belonging_to(VALUE obj, uint32_t rid)
{
- VALUE flags = RBASIC(obj)->flags & 0xffff0000ffffffff; // 4B
+ VALUE flags = RBASIC(obj)->flags & 0xffffffff; // 4B
RBASIC(obj)->flags = flags | ((VALUE)rid << 32);
}
@@ -312,7 +310,7 @@ rb_ractor_belonging(VALUE obj)
return 0;
}
else {
- return RBASIC(obj)->flags >> 32 & 0xFFFF;
+ return RBASIC(obj)->flags >> 32;
}
}
diff --git a/shape.c b/shape.c
deleted file mode 100644
index fa91466340..0000000000
--- a/shape.c
+++ /dev/null
@@ -1,571 +0,0 @@
-#include "vm_core.h"
-#include "vm_sync.h"
-#include "shape.h"
-#include "internal/class.h"
-#include "internal/symbol.h"
-#include "internal/variable.h"
-#include <stdbool.h>
-
-/*
- * Shape getters
- */
-static rb_shape_t*
-rb_shape_get_root_shape(void) {
- return GET_VM()->root_shape;
-}
-
-static rb_shape_t*
-rb_shape_get_frozen_root_shape(void) {
- return GET_VM()->frozen_root_shape;
-}
-
-bool
-rb_shape_root_shape_p(rb_shape_t* shape) {
- return shape == rb_shape_get_root_shape();
-}
-
-rb_shape_t*
-rb_shape_get_shape_by_id(shape_id_t shape_id)
-{
- RUBY_ASSERT(shape_id != INVALID_SHAPE_ID);
-
- rb_vm_t *vm = GET_VM();
- rb_shape_t *shape = vm->shape_list[shape_id];
- RUBY_ASSERT(IMEMO_TYPE_P(shape, imemo_shape));
- return shape;
-}
-
-rb_shape_t*
-rb_shape_get_shape_by_id_without_assertion(shape_id_t shape_id)
-{
- RUBY_ASSERT(shape_id != INVALID_SHAPE_ID);
-
- rb_vm_t *vm = GET_VM();
- rb_shape_t *shape = vm->shape_list[shape_id];
- return shape;
-}
-
-static inline shape_id_t
-shape_set_shape_id(rb_shape_t *shape, shape_id_t id) {
- VALUE flags = shape->flags & ~((uint64_t)SHAPE_MASK << 16);
- return (shape_id_t)(shape->flags = (flags | ((VALUE)id << SHAPE_FLAG_SHIFT)));
-}
-
-#if !SHAPE_IN_BASIC_FLAGS
-static inline shape_id_t
-RCLASS_SHAPE_ID(VALUE obj)
-{
- return RCLASS_EXT(obj)->shape_id;
-}
-
-shape_id_t rb_generic_shape_id(VALUE obj);
-#endif
-
-shape_id_t
-rb_shape_get_shape_id(VALUE obj)
-{
- if (RB_SPECIAL_CONST_P(obj)) {
- return SHAPE_ID(rb_shape_get_frozen_root_shape());
- }
-
-#if SHAPE_IN_BASIC_FLAGS
- return RBASIC_SHAPE_ID(obj);
-#else
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- return ROBJECT_SHAPE_ID(obj);
- break;
- case T_CLASS:
- case T_MODULE:
- return RCLASS_SHAPE_ID(obj);
- default:
- return rb_generic_shape_id(obj);
- }
-#endif
-}
-
-rb_shape_t*
-rb_shape_get_shape(VALUE obj)
-{
- return rb_shape_get_shape_by_id(rb_shape_get_shape_id(obj));
-}
-
-static shape_id_t
-get_next_shape_id(void)
-{
- rb_vm_t *vm = GET_VM();
- vm->max_shape_count++;
- return vm->max_shape_count;
-}
-
-static rb_shape_t *
-rb_shape_lookup_id(rb_shape_t* shape, ID id, enum shape_type shape_type) {
- while (shape->parent) {
- if (shape->edge_name == id) {
- // If the shape type is different, we don't
- // want this to count as a "found" ID
- if (shape_type == (enum shape_type)shape->type) {
- return shape;
- }
- else {
- return NULL;
- }
- }
- shape = shape->parent;
- }
- return NULL;
-}
-
-static rb_shape_t*
-get_next_shape_internal(rb_shape_t* shape, ID id, VALUE obj, enum shape_type shape_type)
-{
- rb_shape_t *res = NULL;
- RUBY_ASSERT(SHAPE_FROZEN != (enum shape_type)shape->type);
- RB_VM_LOCK_ENTER();
- {
- if (rb_shape_lookup_id(shape, id, shape_type)) {
- // If shape already contains the ivar that is being set, we'll return shape
- res = shape;
- }
- else {
- if (!shape->edges) {
- shape->edges = rb_id_table_create(0);
- }
-
- // Lookup the shape in edges - if there's already an edge and a corresponding shape for it,
- // we can return that. Otherwise, we'll need to get a new shape
- if (!rb_id_table_lookup(shape->edges, id, (VALUE *)&res) || rb_objspace_garbage_object_p((VALUE)res)) {
- // In this case, the shape exists, but the shape is garbage, so we need to recreate it
- if (res) {
- rb_id_table_delete(shape->edges, id);
- res->parent = NULL;
- }
-
- shape_id_t next_shape_id = get_next_shape_id();
-
- if (next_shape_id == MAX_SHAPE_ID) {
- // TODO: Make an OutOfShapesError ??
- rb_bug("Out of shapes\n");
- }
- else {
- RUBY_ASSERT(next_shape_id < MAX_SHAPE_ID);
- rb_shape_t * new_shape = rb_shape_alloc(next_shape_id,
- id,
- shape);
-
- new_shape->type = (uint8_t)shape_type;
-
- switch(shape_type) {
- case SHAPE_FROZEN:
- RB_OBJ_FREEZE_RAW((VALUE)new_shape);
- break;
- case SHAPE_IVAR:
- new_shape->iv_count = new_shape->parent->iv_count + 1;
-
- // Check if we should update max_iv_count on the object's class
- if (BUILTIN_TYPE(obj) == T_OBJECT) {
- VALUE klass = rb_obj_class(obj);
- if (new_shape->iv_count > RCLASS_EXT(klass)->max_iv_count) {
- RCLASS_EXT(klass)->max_iv_count = new_shape->iv_count;
- }
- }
- break;
- case SHAPE_IVAR_UNDEF:
- new_shape->iv_count = new_shape->parent->iv_count;
- break;
- case SHAPE_ROOT:
- rb_bug("Unreachable");
- break;
- }
-
- rb_id_table_insert(shape->edges, id, (VALUE)new_shape);
- RB_OBJ_WRITTEN((VALUE)shape, Qundef, (VALUE)new_shape);
- rb_shape_set_shape_by_id(next_shape_id, new_shape);
-
- res = new_shape;
- }
- }
- }
- }
- RB_VM_LOCK_LEAVE();
- return res;
-}
-
-MJIT_FUNC_EXPORTED int
-rb_shape_frozen_shape_p(rb_shape_t* shape)
-{
- return SHAPE_FROZEN == (enum shape_type)shape->type;
-}
-
-void
-rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape)
-{
- rb_shape_t* next_shape = get_next_shape_internal(shape, id, obj, SHAPE_IVAR_UNDEF);
-
- if (shape == next_shape) {
- return;
- }
-
- RUBY_ASSERT(!rb_objspace_garbage_object_p((VALUE)next_shape));
- rb_shape_set_shape(obj, next_shape);
-}
-
-void
-rb_shape_transition_shape_frozen(VALUE obj)
-{
- rb_shape_t* shape = rb_shape_get_shape(obj);
- RUBY_ASSERT(shape);
- RUBY_ASSERT(RB_OBJ_FROZEN(obj));
-
- if (rb_shape_frozen_shape_p(shape)) {
- return;
- }
-
- rb_shape_t* next_shape;
-
- if (shape == rb_shape_get_root_shape()) {
- switch(BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- return;
- }
- next_shape = rb_shape_get_frozen_root_shape();
- }
- else {
- static ID id_frozen;
- if (!id_frozen) {
- id_frozen = rb_make_internal_id();
- }
-
- next_shape = get_next_shape_internal(shape, (ID)id_frozen, obj, SHAPE_FROZEN);
- }
-
- RUBY_ASSERT(next_shape);
- rb_shape_set_shape(obj, next_shape);
-}
-
-void
-rb_shape_transition_shape(VALUE obj, ID id, rb_shape_t *shape)
-{
- rb_shape_t* next_shape = rb_shape_get_next(shape, obj, id);
- if (shape == next_shape) {
- return;
- }
-
- RUBY_ASSERT(!rb_objspace_garbage_object_p((VALUE)next_shape));
- rb_shape_set_shape(obj, next_shape);
-}
-
-rb_shape_t*
-rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id)
-{
- return get_next_shape_internal(shape, id, obj, SHAPE_IVAR);
-}
-
-bool
-rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t *value) {
- while (shape->parent) {
- if (shape->edge_name == id) {
- enum shape_type shape_type;
- shape_type = (enum shape_type)shape->type;
-
- switch(shape_type) {
- case SHAPE_IVAR:
- RUBY_ASSERT(shape->iv_count > 0);
- *value = shape->iv_count - 1;
- return true;
- case SHAPE_IVAR_UNDEF:
- case SHAPE_ROOT:
- return false;
- case SHAPE_FROZEN:
- rb_bug("Ivar should not exist on frozen transition\n");
- }
- }
- shape = shape->parent;
- }
- return false;
-}
-
-static rb_shape_t *
-shape_alloc(void)
-{
- rb_shape_t *shape = (rb_shape_t *)rb_imemo_new(imemo_shape, 0, 0, 0, 0);
- FL_SET_RAW((VALUE)shape, RUBY_FL_SHAREABLE);
- FL_SET_RAW((VALUE)shape, RUBY_FL_PROMOTED1);
- return shape;
-}
-
-rb_shape_t *
-rb_shape_alloc(shape_id_t shape_id, ID edge_name, rb_shape_t * parent)
-{
- rb_shape_t * shape = shape_alloc();
- shape_set_shape_id(shape, shape_id);
-
- shape->edge_name = edge_name;
- shape->iv_count = 0;
-
- RB_OBJ_WRITE(shape, &shape->parent, parent);
-
- RUBY_ASSERT(!parent || IMEMO_TYPE_P(parent, imemo_shape));
-
- return shape;
-}
-
-MJIT_FUNC_EXPORTED void
-rb_shape_set_shape(VALUE obj, rb_shape_t* shape)
-{
- RUBY_ASSERT(IMEMO_TYPE_P(shape, imemo_shape));
- RUBY_ASSERT(SHAPE_FROZEN == shape->type ? RB_OBJ_FROZEN(obj) : 1);
-
- if(rb_shape_set_shape_id(obj, SHAPE_ID(shape))) {
- if (shape != rb_shape_get_frozen_root_shape()) {
- RB_OBJ_WRITTEN(obj, Qundef, (VALUE)shape);
- }
- }
-}
-
-void
-rb_shape_set_shape_by_id(shape_id_t shape_id, rb_shape_t *shape)
-{
- rb_vm_t *vm = GET_VM();
-
- RUBY_ASSERT(shape == NULL || IMEMO_TYPE_P(shape, imemo_shape));
- vm->shape_list[shape_id] = shape;
-}
-
-VALUE rb_cShape;
-
-static void
-shape_mark(void *ptr)
-{
- rb_gc_mark((VALUE)ptr);
-}
-
-/*
- * Exposing Shape to Ruby via RubyVM.debug_shape
- */
-static const rb_data_type_t shape_data_type = {
- "Shape",
- {shape_mark, NULL, NULL,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
-};
-
-static VALUE
-rb_shape_id(VALUE self) {
- rb_shape_t * shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
- return INT2NUM(SHAPE_ID(shape));
-}
-
-static VALUE
-rb_shape_type(VALUE self) {
- rb_shape_t * shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
- return INT2NUM(shape->type);
-}
-
-static VALUE
-rb_shape_parent_id(VALUE self)
-{
- rb_shape_t * shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
- if (shape->parent) {
- return INT2NUM(SHAPE_ID(shape->parent));
- }
- else {
- return Qnil;
- }
-}
-
-static VALUE parse_key(ID key) {
- if ((key & RUBY_ID_INTERNAL) == RUBY_ID_INTERNAL) {
- return LONG2NUM(key);
- } else {
- return ID2SYM(key);
- }
-}
-
-static VALUE
-rb_shape_t_to_rb_cShape(rb_shape_t *shape) {
- union { const rb_shape_t *in; void *out; } deconst;
- VALUE res;
- deconst.in = shape;
- res = TypedData_Wrap_Struct(rb_cShape, &shape_data_type, deconst.out);
- RB_OBJ_WRITTEN(res, Qundef, shape);
-
- return res;
-}
-
-static enum rb_id_table_iterator_result rb_edges_to_hash(ID key, VALUE value, void *ref)
-{
- rb_hash_aset(*(VALUE *)ref, parse_key(key), rb_shape_t_to_rb_cShape((rb_shape_t*)value));
- return ID_TABLE_CONTINUE;
-}
-
-static VALUE
-rb_shape_edges(VALUE self)
-{
- rb_shape_t* shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
-
- VALUE hash = rb_hash_new();
-
- if (shape->edges) {
- rb_id_table_foreach(shape->edges, rb_edges_to_hash, &hash);
- }
-
- return hash;
-}
-
-static VALUE
-rb_shape_edge_name(VALUE self)
-{
- rb_shape_t* shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
-
- if (shape->edge_name) {
- return ID2SYM(shape->edge_name);
- }
- else {
- return Qnil;
- }
-}
-
-static VALUE
-rb_shape_iv_count(VALUE self)
-{
- rb_shape_t* shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
-
- return INT2NUM(shape->iv_count);
-}
-
-static VALUE
-rb_shape_export_depth(VALUE self)
-{
- rb_shape_t* shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
-
- unsigned int depth = 0;
- while (shape->parent) {
- depth++;
- shape = shape->parent;
- }
- return INT2NUM(depth);
-}
-
-static VALUE
-rb_shape_parent(VALUE self)
-{
- rb_shape_t * shape;
- TypedData_Get_Struct(self, rb_shape_t, &shape_data_type, shape);
- if (shape->parent) {
- return rb_shape_t_to_rb_cShape(shape->parent);
- }
- else {
- return Qnil;
- }
-}
-
-VALUE rb_shape_debug_shape(VALUE self, VALUE obj) {
- return rb_shape_t_to_rb_cShape(rb_shape_get_shape(obj));
-}
-
-VALUE rb_shape_debug_root_shape(VALUE self) {
- return rb_shape_t_to_rb_cShape(rb_shape_get_root_shape());
-}
-
-VALUE rb_shape_debug_frozen_root_shape(VALUE self) {
- return rb_shape_t_to_rb_cShape(rb_shape_get_frozen_root_shape());
-}
-
-VALUE rb_obj_shape(rb_shape_t* shape);
-
-static enum rb_id_table_iterator_result collect_keys_and_values(ID key, VALUE value, void *ref)
-{
- rb_hash_aset(*(VALUE *)ref, parse_key(key), rb_obj_shape((rb_shape_t*)value));
- return ID_TABLE_CONTINUE;
-}
-
-static VALUE edges(struct rb_id_table* edges)
-{
- VALUE hash = rb_hash_new();
- if (edges)
- rb_id_table_foreach(edges, collect_keys_and_values, &hash);
- return hash;
-}
-
-VALUE rb_obj_shape(rb_shape_t* shape) {
- VALUE rb_shape = rb_hash_new();
-
- rb_hash_aset(rb_shape, ID2SYM(rb_intern("id")), INT2NUM(SHAPE_ID(shape)));
- rb_hash_aset(rb_shape, ID2SYM(rb_intern("edges")), edges(shape->edges));
-
- if (shape == rb_shape_get_root_shape()) {
- rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_id")), INT2NUM(ROOT_SHAPE_ID));
- }
- else {
- rb_hash_aset(rb_shape, ID2SYM(rb_intern("parent_id")), INT2NUM(SHAPE_ID(shape->parent)));
- }
-
- rb_hash_aset(rb_shape, ID2SYM(rb_intern("edge_name")), rb_id2str(shape->edge_name));
- return rb_shape;
-}
-
-static VALUE shape_transition_tree(VALUE self) {
- return rb_obj_shape(rb_shape_get_root_shape());
-}
-
-static VALUE shape_count(VALUE self) {
- int shape_count = 0;
- rb_vm_t *vm = GET_VM();
- for(shape_id_t i = 0; i < vm->max_shape_count; i++) {
- if(rb_shape_get_shape_by_id_without_assertion(i)) {
- shape_count++;
- }
- }
- return INT2NUM(shape_count);
-}
-
-static VALUE
-shape_max_shape_count(VALUE self)
-{
- return INT2NUM(GET_VM()->max_shape_count);
-}
-
-VALUE
-rb_shape_flags_mask(void)
-{
- return SHAPE_FLAG_MASK;
-}
-
-void
-Init_shape(void)
-{
- rb_cShape = rb_define_class_under(rb_cRubyVM, "Shape", rb_cObject);
- rb_undef_alloc_func(rb_cShape);
-
- rb_define_method(rb_cShape, "parent_id", rb_shape_parent_id, 0);
- rb_define_method(rb_cShape, "parent", rb_shape_parent, 0);
- rb_define_method(rb_cShape, "edges", rb_shape_edges, 0);
- rb_define_method(rb_cShape, "edge_name", rb_shape_edge_name, 0);
- rb_define_method(rb_cShape, "iv_count", rb_shape_iv_count, 0);
- rb_define_method(rb_cShape, "depth", rb_shape_export_depth, 0);
- rb_define_method(rb_cShape, "id", rb_shape_id, 0);
- rb_define_method(rb_cShape, "type", rb_shape_type, 0);
- rb_define_const(rb_cShape, "SHAPE_ROOT", INT2NUM(SHAPE_ROOT));
- rb_define_const(rb_cShape, "SHAPE_IVAR", INT2NUM(SHAPE_IVAR));
- rb_define_const(rb_cShape, "SHAPE_IVAR_UNDEF", INT2NUM(SHAPE_IVAR_UNDEF));
- rb_define_const(rb_cShape, "SHAPE_FROZEN", INT2NUM(SHAPE_FROZEN));
- rb_define_const(rb_cShape, "SHAPE_BITS", INT2NUM(SHAPE_BITS));
-
- rb_define_module_function(rb_cRubyVM, "debug_shape_transition_tree", shape_transition_tree, 0);
- rb_define_module_function(rb_cRubyVM, "debug_shape_count", shape_count, 0);
- rb_define_singleton_method(rb_cRubyVM, "debug_shape", rb_shape_debug_shape, 1);
- rb_define_singleton_method(rb_cRubyVM, "debug_max_shape_count", shape_max_shape_count, 0);
- rb_define_singleton_method(rb_cRubyVM, "debug_root_shape", rb_shape_debug_root_shape, 0);
- rb_define_singleton_method(rb_cRubyVM, "debug_frozen_root_shape", rb_shape_debug_frozen_root_shape, 0);
-}
diff --git a/shape.h b/shape.h
deleted file mode 100644
index b381b9e6ba..0000000000
--- a/shape.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef RUBY_SHAPE_H
-#define RUBY_SHAPE_H
-#if (SIZEOF_UINT64_T == SIZEOF_VALUE)
-#define SIZEOF_SHAPE_T 4
-#define SHAPE_IN_BASIC_FLAGS 1
-typedef uint32_t attr_index_t;
-#else
-#define SIZEOF_SHAPE_T 2
-#define SHAPE_IN_BASIC_FLAGS 0
-typedef uint16_t attr_index_t;
-#endif
-
-#define MAX_IVARS (attr_index_t)(-1)
-
-#if RUBY_DEBUG || (defined(VM_CHECK_MODE) && VM_CHECK_MODE > 0)
-# if SIZEOF_SHAPE_T == 4
-typedef uint32_t shape_id_t;
-# define SHAPE_BITS 16
-# else
-typedef uint16_t shape_id_t;
-# define SHAPE_BITS 16
-# endif
-#else
-# if SIZEOF_SHAPE_T == 4
-typedef uint32_t shape_id_t;
-# define SHAPE_BITS 32
-# else
-typedef uint16_t shape_id_t;
-# define SHAPE_BITS 16
-# endif
-#endif
-
-# define SHAPE_MASK (((uintptr_t)1 << SHAPE_BITS) - 1)
-# define SHAPE_FLAG_MASK (((VALUE)-1) >> SHAPE_BITS)
-
-# define SHAPE_FLAG_SHIFT ((SIZEOF_VALUE * 8) - SHAPE_BITS)
-
-# define SHAPE_BITMAP_SIZE 16384
-
-# define MAX_SHAPE_ID (SHAPE_MASK - 1)
-# define INVALID_SHAPE_ID SHAPE_MASK
-# define ROOT_SHAPE_ID 0x0
-# define FROZEN_ROOT_SHAPE_ID 0x1
-
-#define SHAPE_ID(shape) ((((rb_shape_t *)shape)->flags >> SHAPE_FLAG_SHIFT) & SHAPE_MASK)
-
-struct rb_shape {
- VALUE flags; // Shape ID and frozen status encoded within flags
- struct rb_shape * parent; // Pointer to the parent
- struct rb_id_table * edges; // id_table from ID (ivar) to next shape
- ID edge_name; // ID (ivar) for transition from parent to rb_shape
- attr_index_t iv_count;
- uint8_t type;
-};
-
-typedef struct rb_shape rb_shape_t;
-
-enum shape_type {
- SHAPE_ROOT,
- SHAPE_IVAR,
- SHAPE_FROZEN,
- SHAPE_IVAR_UNDEF,
-};
-
-static inline shape_id_t
-IMEMO_CACHED_SHAPE_ID(VALUE cc)
-{
- RBIMPL_ASSERT_TYPE((VALUE)cc, RUBY_T_IMEMO);
- return (shape_id_t)(SHAPE_MASK & (RBASIC(cc)->flags >> SHAPE_FLAG_SHIFT));
-}
-
-static inline void
-IMEMO_SET_CACHED_SHAPE_ID(VALUE cc, shape_id_t shape_id)
-{
- RBIMPL_ASSERT_TYPE((VALUE)cc, RUBY_T_IMEMO);
- RBASIC(cc)->flags &= SHAPE_FLAG_MASK;
- RBASIC(cc)->flags |= ((VALUE)(shape_id) << SHAPE_FLAG_SHIFT);
-}
-
-#if SHAPE_IN_BASIC_FLAGS
-static inline shape_id_t
-RBASIC_SHAPE_ID(VALUE obj)
-{
- RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj));
- return (shape_id_t)(SHAPE_MASK & ((RBASIC(obj)->flags) >> SHAPE_FLAG_SHIFT));
-}
-
-static inline void
-RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
-{
- // Ractors are occupying the upper 32 bits of flags, but only in debug mode
- // Object shapes are occupying top bits
- RBASIC(obj)->flags &= SHAPE_FLAG_MASK;
- RBASIC(obj)->flags |= ((VALUE)(shape_id) << SHAPE_FLAG_SHIFT);
-}
-
-static inline shape_id_t
-ROBJECT_SHAPE_ID(VALUE obj)
-{
- RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- return RBASIC_SHAPE_ID(obj);
-}
-
-static inline void
-ROBJECT_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
-{
- RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- RBASIC_SET_SHAPE_ID(obj, shape_id);
-}
-
-#else
-
-static inline shape_id_t
-ROBJECT_SHAPE_ID(VALUE obj)
-{
- RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- return (shape_id_t)(SHAPE_MASK & (RBASIC(obj)->flags >> SHAPE_FLAG_SHIFT));
-}
-
-static inline void
-ROBJECT_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
-{
- RBASIC(obj)->flags &= SHAPE_FLAG_MASK;
- RBASIC(obj)->flags |= ((VALUE)(shape_id) << SHAPE_FLAG_SHIFT);
-}
-#endif
-
-bool rb_shape_root_shape_p(rb_shape_t* shape);
-
-rb_shape_t* rb_shape_get_shape_by_id_without_assertion(shape_id_t shape_id);
-
-MJIT_SYMBOL_EXPORT_BEGIN
-rb_shape_t* rb_shape_get_shape_by_id(shape_id_t shape_id);
-void rb_shape_set_shape(VALUE obj, rb_shape_t* shape);
-shape_id_t rb_shape_get_shape_id(VALUE obj);
-rb_shape_t* rb_shape_get_shape(VALUE obj);
-int rb_shape_frozen_shape_p(rb_shape_t* shape);
-void rb_shape_transition_shape_frozen(VALUE obj);
-void rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape);
-void rb_shape_transition_shape(VALUE obj, ID id, rb_shape_t *shape);
-rb_shape_t* rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id);
-bool rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t * value);
-MJIT_SYMBOL_EXPORT_END
-
-rb_shape_t * rb_shape_alloc(shape_id_t shape_id, ID edge_name, rb_shape_t * parent);
-
-bool rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id);
-void rb_shape_set_shape_by_id(shape_id_t, rb_shape_t *);
-
-VALUE rb_obj_debug_shape(VALUE self, VALUE obj);
-VALUE rb_shape_flags_mask(void);
-
-#endif
diff --git a/spec/ruby/library/objectspace/reachable_objects_from_spec.rb b/spec/ruby/library/objectspace/reachable_objects_from_spec.rb
index 61ebc9f93d..7e70bc8569 100644
--- a/spec/ruby/library/objectspace/reachable_objects_from_spec.rb
+++ b/spec/ruby/library/objectspace/reachable_objects_from_spec.rb
@@ -17,7 +17,7 @@ describe "ObjectSpace.reachable_objects_from" do
it "enumerates objects directly reachable from a given object" do
ObjectSpace.reachable_objects_from(['a', 'b', 'c']).should include(Array, 'a', 'b', 'c')
- ObjectSpace.reachable_objects_from(Object.new).should include(Object)
+ ObjectSpace.reachable_objects_from(Object.new).should == [Object]
end
it "finds an object stored in an Array" do
diff --git a/spec/ruby/optional/capi/shared/rbasic.rb b/spec/ruby/optional/capi/shared/rbasic.rb
index 105408ec3d..99c2044bd7 100644
--- a/spec/ruby/optional/capi/shared/rbasic.rb
+++ b/spec/ruby/optional/capi/shared/rbasic.rb
@@ -8,9 +8,16 @@ describe :rbasic, shared: true do
it "reports the appropriate FREEZE flag for the object when reading" do
obj, _ = @data.call
- (@specs.get_flags(obj) & @freeze).should == 0
+ initial = @specs.get_flags(obj)
obj.freeze
- (@specs.get_flags(obj) & @freeze).should == @freeze
+ @specs.get_flags(obj).should == @freeze | initial
+ end
+
+ it "supports setting the FREEZE flag" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ @specs.set_flags(obj, @freeze | initial).should == @freeze | initial
+ obj.should.frozen?
end
it "supports retrieving the (meta)class" do
diff --git a/test/-ext-/marshal/test_internal_ivar.rb b/test/-ext-/marshal/test_internal_ivar.rb
index 9359c7f113..a32138f6e8 100644
--- a/test/-ext-/marshal/test_internal_ivar.rb
+++ b/test/-ext-/marshal/test_internal_ivar.rb
@@ -7,7 +7,6 @@ module Bug end
module Bug::Marshal
class TestInternalIVar < Test::Unit::TestCase
def test_marshal
- pend "We don't support IVs with ID of 0"
v = InternalIVar.new("hello", "world", "bye")
assert_equal("hello", v.normal)
assert_equal("world", v.internal)
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 94d68dc093..3b90319858 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -116,16 +116,12 @@ class TestObjSpace < Test::Unit::TestCase
opts = %w[--disable-gem --disable=frozen-string-literal -robjspace]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
- def assert_reachable_object_as_expected(expectation, reachable_objects_from_array)
- reachable_objects = ObjectSpace.reachable_objects_from(reachable_objects_from_array)
- assert_equal(expectation, reachable_objects)
- end
-
assert_equal(nil, ObjectSpace.reachable_objects_from(nil))
- assert_reachable_object_as_expected([Array, 'a', 'b', 'c'], ['a', 'b', 'c'])
- assert_reachable_object_as_expected([Array, 'a', 'a', 'a'], ['a', 'a', 'a'])
- assert_reachable_object_as_expected([Array, 'a', 'a'], ['a', v = 'a', v])
- assert_reachable_object_as_expected([Array, 'a'], [v = 'a', v, v])
+ assert_equal([Array, 'a', 'b', 'c'], ObjectSpace.reachable_objects_from(['a', 'b', 'c']))
+
+ assert_equal([Array, 'a', 'a', 'a'], ObjectSpace.reachable_objects_from(['a', 'a', 'a']))
+ assert_equal([Array, 'a', 'a'], ObjectSpace.reachable_objects_from(['a', v = 'a', v]))
+ assert_equal([Array, 'a'], ObjectSpace.reachable_objects_from([v = 'a', v, v]))
long_ary = Array.new(1_000){''}
max = 0
diff --git a/test/ruby/test_mjit.rb b/test/ruby/test_mjit.rb
index 4c6cc6f39f..e49195f763 100644
--- a/test/ruby/test_mjit.rb
+++ b/test/ruby/test_mjit.rb
@@ -831,7 +831,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_inlined_exivar
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 4, recompile_count: 2, min_calls: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2)
begin;
class Foo < Hash
def initialize
@@ -850,7 +850,7 @@ class TestMJIT < Test::Unit::TestCase
end
def test_inlined_undefined_ivar
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 2, min_calls: 2)
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 3, min_calls: 3)
begin;
class Foo
def initialize
diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb
deleted file mode 100644
index cdca08dbb4..0000000000
--- a/test/ruby/test_shapes.rb
+++ /dev/null
@@ -1,171 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-
-# These test the functionality of object shapes
-class TestShapes < Test::Unit::TestCase
- class Example
- def initialize
- @a = 1
- end
- end
-
- class RemoveAndAdd
- def add_foo
- @foo = 1
- end
-
- def remove
- remove_instance_variable(:@foo)
- end
-
- def add_bar
- @bar = 1
- end
- end
-
- # RubyVM.debug_shape returns new instances of shape objects for
- # each call. This helper method allows us to define equality for
- # shapes
- def assert_shape_equal(shape1, shape2)
- assert_equal(shape1.id, shape2.id)
- assert_equal(shape1.parent_id, shape2.parent_id)
- assert_equal(shape1.depth, shape2.depth)
- assert_equal(shape1.type, shape2.type)
- end
-
- def refute_shape_equal(shape1, shape2)
- refute_equal(shape1.id, shape2.id)
- end
-
- def test_iv_index
- example = RemoveAndAdd.new
- shape = RubyVM.debug_shape(example)
- assert_equal 0, shape.iv_count
-
- example.add_foo # makes a transition
- new_shape = RubyVM.debug_shape(example)
- assert_equal([:@foo], example.instance_variables)
- assert_equal(shape.id, new_shape.parent.id)
- assert_equal(1, new_shape.iv_count)
-
- example.remove # makes a transition
- remove_shape = RubyVM.debug_shape(example)
- assert_equal([], example.instance_variables)
- assert_equal(new_shape.id, remove_shape.parent.id)
- assert_equal(1, remove_shape.iv_count)
-
- example.add_bar # makes a transition
- bar_shape = RubyVM.debug_shape(example)
- assert_equal([:@bar], example.instance_variables)
- assert_equal(remove_shape.id, bar_shape.parent.id)
- assert_equal(2, bar_shape.iv_count)
- end
-
- def test_new_obj_has_root_shape
- assert_shape_equal(RubyVM.debug_root_shape, RubyVM.debug_shape(Object.new))
- end
-
- def test_frozen_new_obj_has_frozen_root_shape
- assert_shape_equal(
- RubyVM.debug_frozen_root_shape,
- RubyVM.debug_shape(Object.new.freeze)
- )
- end
-
- def test_str_has_root_shape
- assert_shape_equal(RubyVM.debug_root_shape, RubyVM.debug_shape(""))
- end
-
- def test_array_has_root_shape
- assert_shape_equal(RubyVM.debug_root_shape, RubyVM.debug_shape([]))
- end
-
- def test_hash_has_root_shape
- assert_shape_equal(RubyVM.debug_root_shape, RubyVM.debug_shape({}))
- end
-
- def test_true_has_frozen_root_shape
- assert_shape_equal(RubyVM.debug_frozen_root_shape, RubyVM.debug_shape(true))
- end
-
- def test_nil_has_frozen_root_shape
- assert_shape_equal(RubyVM.debug_frozen_root_shape, RubyVM.debug_shape(nil))
- end
-
- def test_basic_shape_transition
- obj = Example.new
- refute_equal(RubyVM.debug_root_shape, RubyVM.debug_shape(obj))
- assert_shape_equal(RubyVM.debug_root_shape.edges[:@a], RubyVM.debug_shape(obj))
- assert_equal(obj.instance_variable_get(:@a), 1)
- end
-
- def test_different_objects_make_same_transition
- obj = Example.new
- obj2 = ""
- obj2.instance_variable_set(:@a, 1)
- assert_shape_equal(RubyVM.debug_shape(obj), RubyVM.debug_shape(obj2))
- end
-
- def test_duplicating_objects
- obj = Example.new
- obj2 = obj.dup
- assert_shape_equal(RubyVM.debug_shape(obj), RubyVM.debug_shape(obj2))
- end
-
- def test_freezing_and_duplicating_object
- obj = Object.new.freeze
- obj2 = obj.dup
- refute_predicate(obj2, :frozen?)
- refute_equal(RubyVM.debug_shape(obj).id, RubyVM.debug_shape(obj2).id)
- end
-
- def test_freezing_and_duplicating_object_with_ivars
- obj = Example.new.freeze
- obj2 = obj.dup
- refute_predicate(obj2, :frozen?)
- refute_shape_equal(RubyVM.debug_shape(obj), RubyVM.debug_shape(obj2))
- assert_equal(obj2.instance_variable_get(:@a), 1)
- end
-
- def test_freezing_and_duplicating_string_with_ivars
- str = "str"
- str.instance_variable_set(:@a, 1)
- str.freeze
- str2 = str.dup
- refute_predicate(str2, :frozen?)
- refute_equal(RubyVM.debug_shape(str).id, RubyVM.debug_shape(str2).id)
- assert_equal(str2.instance_variable_get(:@a), 1)
- end
-
- def test_freezing_and_cloning_objects
- obj = Object.new.freeze
- obj2 = obj.clone(freeze: true)
- assert_predicate(obj2, :frozen?)
- assert_shape_equal(RubyVM.debug_shape(obj), RubyVM.debug_shape(obj2))
- end
-
- def test_freezing_and_cloning_object_with_ivars
- obj = Example.new.freeze
- obj2 = obj.clone(freeze: true)
- assert_predicate(obj2, :frozen?)
- assert_shape_equal(RubyVM.debug_shape(obj), RubyVM.debug_shape(obj2))
- assert_equal(obj2.instance_variable_get(:@a), 1)
- end
-
- def test_freezing_and_cloning_string
- str = "str".freeze
- str2 = str.clone(freeze: true)
- assert_predicate(str2, :frozen?)
- assert_shape_equal(RubyVM.debug_shape(str), RubyVM.debug_shape(str2))
- end
-
- def test_freezing_and_cloning_string_with_ivars
- str = "str"
- str.instance_variable_set(:@a, 1)
- str.freeze
- str2 = str.clone(freeze: true)
- assert_predicate(str2, :frozen?)
- assert_shape_equal(RubyVM.debug_shape(str), RubyVM.debug_shape(str2))
- assert_equal(str2.instance_variable_get(:@a), 1)
- end
-end
diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb
index 8c21d42449..d0f9bf527b 100755
--- a/tool/mjit/bindgen.rb
+++ b/tool/mjit/bindgen.rb
@@ -341,17 +341,12 @@ generator = BindingGenerator.new(
VM_METHOD_TYPE_CFUNC
VM_METHOD_TYPE_ISEQ
],
- ULONG: %w[
- INVALID_SHAPE_ID
- SHAPE_MASK
- ],
},
types: %w[
CALL_DATA
IC
IVC
RB_BUILTIN
- attr_index_t
compile_branch
compile_status
inlined_call_context
@@ -365,10 +360,10 @@ generator = BindingGenerator.new(
rb_callable_method_entry_struct
rb_callcache
rb_callinfo
- rb_control_frame_t
rb_cref_t
- rb_execution_context_struct
+ rb_control_frame_t
rb_execution_context_t
+ rb_execution_context_struct
rb_iseq_constant_body
rb_iseq_location_t
rb_iseq_struct
@@ -383,7 +378,6 @@ generator = BindingGenerator.new(
],
dynamic_types: %w[
VALUE
- shape_id_t
],
skip_fields: {
'rb_execution_context_struct.machine': %w[regs], # differs between macOS and Linux
diff --git a/variable.c b/variable.c
index abbe76eba7..056a1000b8 100644
--- a/variable.c
+++ b/variable.c
@@ -34,7 +34,6 @@
#include "ruby/st.h"
#include "ruby/util.h"
#include "transient_heap.h"
-#include "shape.h"
#include "variable.h"
#include "vm_core.h"
#include "ractor_core.h"
@@ -64,9 +63,12 @@ static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int v
static st_table *generic_iv_tbl_;
struct ivar_update {
- struct gen_ivtbl *ivtbl;
- uint32_t iv_index;
- rb_shape_t* shape;
+ union {
+ st_table *iv_index_tbl;
+ struct gen_ivtbl *ivtbl;
+ } u;
+ st_data_t index;
+ int iv_extended;
};
void
@@ -894,6 +896,30 @@ rb_alias_variable(ID name1, ID name2)
entry1->var = entry2->var;
}
+static bool
+iv_index_tbl_lookup(struct st_table *tbl, ID id, uint32_t *indexp)
+{
+ st_data_t ent_data;
+ int r;
+
+ if (tbl == NULL) return false;
+
+ RB_VM_LOCK_ENTER();
+ {
+ r = st_lookup(tbl, (st_data_t)id, &ent_data);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ if (r) {
+ struct rb_iv_index_tbl_entry *ent = (void *)ent_data;
+ *indexp = ent->index;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static void
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
{
@@ -931,20 +957,7 @@ generic_ivtbl_no_ractor_check(VALUE obj)
}
static int
-gen_ivtbl_get_unlocked(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
-{
- st_data_t data;
-
- if (st_lookup(generic_ivtbl(obj, id, false), (st_data_t)obj, &data)) {
- *ivtbl = (struct gen_ivtbl *)data;
- return 1;
- }
-
- return 0;
-}
-
-MJIT_FUNC_EXPORTED int
-rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
+gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
{
st_data_t data;
int r = 0;
@@ -964,7 +977,63 @@ rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
MJIT_FUNC_EXPORTED int
rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **ivtbl)
{
- return rb_gen_ivtbl_get(obj, 0, ivtbl);
+ return gen_ivtbl_get(obj, 0, ivtbl);
+}
+
+MJIT_FUNC_EXPORTED VALUE
+rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index)
+{
+ struct gen_ivtbl *ivtbl;
+
+ if (gen_ivtbl_get(obj, id, &ivtbl)) {
+ if (LIKELY(index < ivtbl->numiv)) {
+ VALUE val = ivtbl->ivptr[index];
+ return val;
+ }
+ }
+
+ return Qundef;
+}
+
+static VALUE
+generic_ivar_delete(VALUE obj, ID id, VALUE undef)
+{
+ struct gen_ivtbl *ivtbl;
+
+ if (gen_ivtbl_get(obj, id, &ivtbl)) {
+ st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
+ uint32_t index;
+
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) {
+ if (index < ivtbl->numiv) {
+ VALUE ret = ivtbl->ivptr[index];
+
+ ivtbl->ivptr[index] = Qundef;
+ return ret == Qundef ? undef : ret;
+ }
+ }
+ }
+ return undef;
+}
+
+static VALUE
+generic_ivar_get(VALUE obj, ID id, VALUE undef)
+{
+ struct gen_ivtbl *ivtbl;
+
+ if (gen_ivtbl_get(obj, id, &ivtbl)) {
+ st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
+ uint32_t index;
+
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) {
+ if (index < ivtbl->numiv) {
+ VALUE ret = ivtbl->ivptr[index];
+
+ return ret == Qundef ? undef : ret;
+ }
+ }
+ }
+ return undef;
}
static size_t
@@ -976,8 +1045,6 @@ gen_ivtbl_bytes(size_t n)
static struct gen_ivtbl *
gen_ivtbl_resize(struct gen_ivtbl *old, uint32_t n)
{
- RUBY_ASSERT(n > 0);
-
uint32_t len = old ? old->numiv : 0;
struct gen_ivtbl *ivtbl = xrealloc(old, gen_ivtbl_bytes(n));
@@ -1002,6 +1069,18 @@ gen_ivtbl_dup(const struct gen_ivtbl *orig)
}
#endif
+static uint32_t
+iv_index_tbl_newsize(struct ivar_update *ivup)
+{
+ if (!ivup->iv_extended) {
+ return (uint32_t)ivup->u.iv_index_tbl->num_entries;
+ }
+ else {
+ uint32_t index = (uint32_t)ivup->index; /* should not overflow */
+ return (index+1) + (index+1)/4; /* (index+1)*1.25 */
+ }
+}
+
static int
generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
{
@@ -1012,22 +1091,53 @@ generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
if (existing) {
ivtbl = (struct gen_ivtbl *)*v;
- if (ivup->iv_index < ivtbl->numiv) {
- ivup->ivtbl = ivtbl;
+ if (ivup->index < ivtbl->numiv) {
+ ivup->u.ivtbl = ivtbl;
return ST_STOP;
}
}
FL_SET((VALUE)*k, FL_EXIVAR);
- ivtbl = gen_ivtbl_resize(ivtbl, ivup->shape->iv_count);
- // Reinsert in to the hash table because ivtbl might be a newly resized chunk of memory
+ uint32_t newsize = iv_index_tbl_newsize(ivup);
+ ivtbl = gen_ivtbl_resize(ivtbl, newsize);
*v = (st_data_t)ivtbl;
- ivup->ivtbl = ivtbl;
-#if !SHAPE_IN_BASIC_FLAGS
- ivtbl->shape_id = SHAPE_ID(ivup->shape);
-#endif
+ ivup->u.ivtbl = ivtbl;
return ST_CONTINUE;
}
+static VALUE
+generic_ivar_defined(VALUE obj, ID id)
+{
+ struct gen_ivtbl *ivtbl;
+ st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
+ uint32_t index;
+
+ if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return Qfalse;
+ if (!gen_ivtbl_get(obj, id, &ivtbl)) return Qfalse;
+
+ return RBOOL((index < ivtbl->numiv) && (ivtbl->ivptr[index] != Qundef));
+}
+
+static int
+generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
+{
+ struct gen_ivtbl *ivtbl;
+ uint32_t index;
+ st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
+
+ if (!iv_index_tbl) return 0;
+ if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return 0;
+ if (!gen_ivtbl_get(obj, id, &ivtbl)) return 0;
+
+ if (index < ivtbl->numiv) {
+ if (ivtbl->ivptr[index] != Qundef) {
+ *valp = ivtbl->ivptr[index];
+ ivtbl->ivptr[index] = Qundef;
+ return 1;
+ }
+ }
+ return 0;
+}
+
static void
gen_ivtbl_mark(const struct gen_ivtbl *ivtbl)
{
@@ -1043,11 +1153,7 @@ rb_mark_generic_ivar(VALUE obj)
{
struct gen_ivtbl *ivtbl;
- if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
-
-#if !SHAPE_IN_BASIC_FLAGS
- rb_gc_mark((VALUE)rb_shape_get_shape_by_id(ivtbl->shape_id));
-#endif
+ if (gen_ivtbl_get(obj, 0, &ivtbl)) {
gen_ivtbl_mark(ivtbl);
}
}
@@ -1076,35 +1182,11 @@ rb_generic_ivar_memsize(VALUE obj)
{
struct gen_ivtbl *ivtbl;
- if (rb_gen_ivtbl_get(obj, 0, &ivtbl))
+ if (gen_ivtbl_get(obj, 0, &ivtbl))
return gen_ivtbl_bytes(ivtbl->numiv);
return 0;
}
-#if !SHAPE_IN_BASIC_FLAGS
-MJIT_FUNC_EXPORTED shape_id_t
-rb_generic_shape_id(VALUE obj)
-{
- struct gen_ivtbl *ivtbl = 0;
- shape_id_t shape_id = 0;
-
- RB_VM_LOCK_ENTER();
- {
- st_table* global_iv_table = generic_ivtbl(obj, 0, false);
-
- if (global_iv_table && st_lookup(global_iv_table, obj, (st_data_t *)&ivtbl)) {
- shape_id = ivtbl->shape_id;
- }
- else if (OBJ_FROZEN(obj)) {
- shape_id = FROZEN_ROOT_SHAPE_ID;
- }
- }
- RB_VM_LOCK_LEAVE();
-
- return shape_id;
-}
-#endif
-
static size_t
gen_ivtbl_count(const struct gen_ivtbl *ivtbl)
{
@@ -1172,16 +1254,23 @@ VALUE
rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
{
if (SPECIAL_CONST_P(obj)) return undef;
-
- shape_id_t shape_id;
- VALUE * ivar_list;
- rb_shape_t * shape;
-
-#if SHAPE_IN_BASIC_FLAGS
- shape_id = RBASIC_SHAPE_ID(obj);
-#endif
-
switch (BUILTIN_TYPE(obj)) {
+ case T_OBJECT:
+ {
+ uint32_t index;
+ uint32_t len = ROBJECT_NUMIV(obj);
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ VALUE val;
+
+ if (iv_index_tbl_lookup(ROBJECT_IV_INDEX_TBL(obj), id, &index) &&
+ index < len &&
+ (val = ptr[index]) != Qundef) {
+ return val;
+ }
+ else {
+ break;
+ }
+ }
case T_CLASS:
case T_MODULE:
{
@@ -1198,37 +1287,14 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
return val;
}
else {
- return undef;
+ break;
}
}
- case T_OBJECT:
- {
-#if !SHAPE_IN_BASIC_FLAGS
- shape_id = ROBJECT_SHAPE_ID(obj);
-#endif
- ivar_list = ROBJECT_IVPTR(obj);
- break;
- }
default:
- if (FL_TEST_RAW(obj, FL_EXIVAR)) {
- struct gen_ivtbl *ivtbl;
- rb_gen_ivtbl_get(obj, id, &ivtbl);
-#if !SHAPE_IN_BASIC_FLAGS
- shape_id = ivtbl->shape_id;
-#endif
- ivar_list = ivtbl->ivptr;
- } else {
- return undef;
- }
+ if (FL_TEST(obj, FL_EXIVAR))
+ return generic_ivar_get(obj, id, undef);
break;
}
-
- attr_index_t index = 0;
- shape = rb_shape_get_shape_by_id(shape_id);
- if (rb_shape_get_iv_index(shape, id, &index)) {
- return ivar_list[index];
- }
-
return undef;
}
@@ -1249,12 +1315,26 @@ rb_attr_get(VALUE obj, ID id)
static VALUE
rb_ivar_delete(VALUE obj, ID id, VALUE undef)
{
- rb_check_frozen(obj);
-
- VALUE val = Qnil;
- attr_index_t index;
+ VALUE *ptr;
+ struct st_table *iv_index_tbl;
+ uint32_t len, index;
+ rb_check_frozen(obj);
switch (BUILTIN_TYPE(obj)) {
+ case T_OBJECT:
+ len = ROBJECT_NUMIV(obj);
+ ptr = ROBJECT_IVPTR(obj);
+ iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
+ index < len) {
+ VALUE val = ptr[index];
+ ptr[index] = Qundef;
+
+ if (val != Qundef) {
+ return val;
+ }
+ }
+ break;
case T_CLASS:
case T_MODULE:
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
@@ -1265,33 +1345,11 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
}
}
break;
- case T_OBJECT: {
- rb_shape_t * shape = rb_shape_get_shape(obj);
- if (rb_shape_get_iv_index(shape, id, &index)) {
- rb_shape_transition_shape_remove_ivar(obj, id, shape);
- val = ROBJECT_IVPTR(obj)[index];
- ROBJECT_IVPTR(obj)[index] = Qundef;
- return val;
- }
-
- break;
- }
- default: {
- rb_shape_t * shape = rb_shape_get_shape(obj);
-
- if (rb_shape_get_iv_index(shape, id, &index)) {
- rb_shape_transition_shape_remove_ivar(obj, id, shape);
- struct gen_ivtbl *ivtbl;
- rb_gen_ivtbl_get(obj, id, &ivtbl);
- val = ivtbl->ivptr[index];
- ivtbl->ivptr[index] = Qundef;
- return val;
- }
-
+ default:
+ if (FL_TEST(obj, FL_EXIVAR))
+ return generic_ivar_delete(obj, id, undef);
break;
- }
}
-
return undef;
}
@@ -1301,34 +1359,67 @@ rb_attr_delete(VALUE obj, ID id)
return rb_ivar_delete(obj, id, Qnil);
}
+static st_table *
+iv_index_tbl_make(VALUE obj, VALUE klass)
+{
+ st_table *iv_index_tbl;
+
+ if (UNLIKELY(!klass)) {
+ rb_raise(rb_eTypeError, "hidden object cannot have instance variables");
+ }
+
+ if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
+ RB_VM_LOCK_ENTER();
+ if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
+ iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
+ }
+ RB_VM_LOCK_LEAVE();
+ }
+
+ return iv_index_tbl;
+}
+
+static void
+iv_index_tbl_extend(struct ivar_update *ivup, ID id, VALUE klass)
+{
+ ASSERT_vm_locking();
+ st_data_t ent_data;
+ struct rb_iv_index_tbl_entry *ent;
+
+ if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, &ent_data)) {
+ ent = (void *)ent_data;
+ ivup->index = ent->index;
+ return;
+ }
+ if (ivup->u.iv_index_tbl->num_entries >= INT_MAX) {
+ rb_raise(rb_eArgError, "too many instance variables");
+ }
+ ent = ALLOC(struct rb_iv_index_tbl_entry);
+ ent->index = ivup->index = (uint32_t)ivup->u.iv_index_tbl->num_entries;
+ ent->class_value = klass;
+ ent->class_serial = RCLASS_SERIAL(klass);
+ st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, (st_data_t)ent);
+ ivup->iv_extended = 1;
+}
+
static void
generic_ivar_set(VALUE obj, ID id, VALUE val)
{
+ VALUE klass = rb_obj_class(obj);
struct ivar_update ivup;
- // The returned shape will have `id` in its iv_table
- rb_shape_t * shape = rb_shape_get_next(rb_shape_get_shape(obj), obj, id);
- ivup.shape = shape;
+ ivup.iv_extended = 0;
+ ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
RB_VM_LOCK_ENTER();
{
- attr_index_t ent_data;
- if (rb_shape_get_iv_index(shape, id, &ent_data)) {
- ivup.iv_index = (uint32_t) ent_data;
- }
- else {
- rb_bug("unreachable. Shape was not found for id: %s", rb_id2name(id));
- }
-
- if (!st_update(generic_ivtbl(obj, id, false), (st_data_t)obj, generic_ivar_update,
- (st_data_t)&ivup)) {
- RB_OBJ_WRITTEN(obj, Qundef, shape);
- }
+ iv_index_tbl_extend(&ivup, id, klass);
+ st_update(generic_ivtbl(obj, id, false), (st_data_t)obj, generic_ivar_update,
+ (st_data_t)&ivup);
}
RB_VM_LOCK_LEAVE();
- ivup.ivtbl->ivptr[ivup.iv_index] = val;
+ ivup.u.ivtbl->ivptr[ivup.index] = val;
- rb_shape_set_shape(obj, shape);
RB_OBJ_WRITTEN(obj, Qundef, val);
}
@@ -1395,8 +1486,8 @@ rb_obj_transient_heap_evacuate(VALUE obj, int promote)
}
#endif
-void
-rb_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize)
+static void
+init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table *index_tbl)
{
VALUE *ptr = ROBJECT_IVPTR(obj);
VALUE *newptr;
@@ -1419,34 +1510,35 @@ rb_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize)
#else
ROBJECT(obj)->as.heap.numiv = newsize;
#endif
+ ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl;
+}
+
+void
+rb_init_iv_list(VALUE obj)
+{
+ st_table *index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ uint32_t newsize = (uint32_t)index_tbl->num_entries;
+ uint32_t len = ROBJECT_NUMIV(obj);
+ init_iv_list(obj, len, newsize, index_tbl);
}
-struct gen_ivtbl *
-rb_ensure_generic_iv_list_size(VALUE obj, uint32_t newsize)
+// Retrieve or create the id-to-index mapping for a given object and an
+// instance variable name.
+static struct ivar_update
+obj_ensure_iv_index_mapping(VALUE obj, ID id)
{
- struct gen_ivtbl * ivtbl = 0;
+ VALUE klass = rb_obj_class(obj);
+ struct ivar_update ivup;
+ ivup.iv_extended = 0;
+ ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
RB_VM_LOCK_ENTER();
{
- if (UNLIKELY(!gen_ivtbl_get_unlocked(obj, 0, &ivtbl) || newsize > ivtbl->numiv)) {
- ivtbl = gen_ivtbl_resize(ivtbl, newsize);
- st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)obj, (st_data_t)ivtbl);
- FL_SET_RAW(obj, FL_EXIVAR);
- }
+ iv_index_tbl_extend(&ivup, id, klass);
}
RB_VM_LOCK_LEAVE();
- RUBY_ASSERT(ivtbl);
-
- return ivtbl;
-}
-
-void
-rb_init_iv_list(VALUE obj)
-{
- uint32_t newsize = rb_shape_get_shape(obj)->iv_count * 2.0;
- uint32_t len = ROBJECT_NUMIV(obj);
- rb_ensure_iv_list_size(obj, len, newsize < len ? len : newsize);
+ return ivup;
}
// Return the instance variable index for a given name and T_OBJECT object. The
@@ -1460,114 +1552,26 @@ uint32_t
rb_obj_ensure_iv_index_mapping(VALUE obj, ID id)
{
RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
- attr_index_t index;
-
- // Ensure there is a transition for IVAR +id+
- rb_shape_transition_shape(obj, id, rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj)));
-
- // Get the current shape
- rb_shape_t * shape = rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj));
-
- if (!rb_shape_get_iv_index(shape, id, &index)) {
- rb_bug("unreachable. Shape was not found for id: %s", rb_id2name(id));
- }
-
- uint32_t len = ROBJECT_NUMIV(obj);
- if (len <= index) {
- uint32_t newsize = (shape->iv_count + 1) * 1.25;
- rb_ensure_iv_list_size(obj, len, newsize);
- }
- RUBY_ASSERT(index <= ROBJECT_NUMIV(obj));
- return index;
+ // This uint32_t cast shouldn't lose information as it's checked in
+ // iv_index_tbl_extend(). The index is stored as an uint32_t in
+ // struct rb_iv_index_tbl_entry.
+ return (uint32_t)obj_ensure_iv_index_mapping(obj, id).index;
}
static VALUE
obj_ivar_set(VALUE obj, ID id, VALUE val)
{
- attr_index_t index = rb_obj_ensure_iv_index_mapping(obj, id);
- RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[index], val);
- return val;
-}
-
-/* Set the instance variable +val+ on object +obj+ at ivar name +id+.
- * This function only works with T_OBJECT objects, so make sure
- * +obj+ is of type T_OBJECT before using this function.
- */
-VALUE
-rb_vm_set_ivar_id(VALUE obj, ID id, VALUE val)
-{
- rb_check_frozen_internal(obj);
- obj_ivar_set(obj, id, val);
- return val;
-}
-
-bool
-rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id)
-{
- if (rb_shape_get_shape_id(obj) == shape_id) {
- return false;
- }
+ uint32_t len;
+ struct ivar_update ivup = obj_ensure_iv_index_mapping(obj, id);
-#if SHAPE_IN_BASIC_FLAGS
- RBASIC_SET_SHAPE_ID(obj, shape_id);
-#else
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- ROBJECT_SET_SHAPE_ID(obj, shape_id);
- break;
- case T_CLASS:
- case T_MODULE:
- {
- RCLASS_EXT(obj)->shape_id = shape_id;
- break;
- }
- case T_IMEMO:
- if (imemo_type(obj) == imemo_shape) {
- RBASIC(obj)->flags &= 0xffffffff0000ffff;
- RBASIC(obj)->flags |= ((uint32_t)(shape_id) << 16);
- }
- break;
- default:
- {
- if (shape_id != FROZEN_ROOT_SHAPE_ID) {
- struct gen_ivtbl *ivtbl = 0;
- RB_VM_LOCK_ENTER();
- {
- st_table* global_iv_table = generic_ivtbl(obj, 0, false);
-
- if (st_lookup(global_iv_table, obj, (st_data_t *)&ivtbl)) {
- ivtbl->shape_id = shape_id;
- }
- else {
- rb_bug("Expected shape_id entry in global iv table");
- }
- }
- RB_VM_LOCK_LEAVE();
- }
- }
+ len = ROBJECT_NUMIV(obj);
+ if (len <= ivup.index) {
+ uint32_t newsize = iv_index_tbl_newsize(&ivup);
+ init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl);
}
-#endif
-
- return true;
-}
-
-/**
- * Prevents further modifications to the given object. ::rb_eFrozenError shall
- * be raised if modification is attempted.
- *
- * @param[out] x Object in question.
- */
-void rb_obj_freeze_inline(VALUE x)
-{
- if (RB_FL_ABLE(x)) {
- RB_OBJ_FREEZE_RAW(x);
-
- rb_shape_transition_shape_frozen(x);
+ RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val);
- if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) {
- rb_freeze_singleton_class(x);
- }
- }
+ return val;
}
static void
@@ -1577,14 +1581,10 @@ ivar_set(VALUE obj, ID id, VALUE val)
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- {
- obj_ivar_set(obj, id, val);
- break;
- }
+ obj_ivar_set(obj, id, val);
+ break;
case T_CLASS:
case T_MODULE:
- // TODO: Transition shapes on classes
- //rb_shape_transition_shape(obj, id, rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj)));
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
rb_class_ivar_set(obj, id, val);
break;
@@ -1614,86 +1614,161 @@ rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
VALUE
rb_ivar_defined(VALUE obj, ID id)
{
- attr_index_t index;
+ VALUE val;
+ struct st_table *iv_index_tbl;
+ uint32_t index;
if (SPECIAL_CONST_P(obj)) return Qfalse;
switch (BUILTIN_TYPE(obj)) {
+ case T_OBJECT:
+ iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
+ index < ROBJECT_NUMIV(obj) &&
+ (val = ROBJECT_IVPTR(obj)[index]) != Qundef) {
+ return Qtrue;
+ }
+ break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id)) {
+ if (RCLASS_IV_TBL(obj) && lock_st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
return Qtrue;
- }
- else {
- return Qfalse;
- }
+ break;
default:
- return RBOOL(rb_shape_get_iv_index(rb_shape_get_shape(obj), id, &index));
+ if (FL_TEST(obj, FL_EXIVAR))
+ return generic_ivar_defined(obj, id);
+ break;
}
+ return Qfalse;
}
typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg);
st_data_t rb_st_nth_key(st_table *tab, st_index_t index);
-static void
-iterate_over_shapes_with_callback(rb_shape_t *shape, VALUE* iv_list, rb_ivar_foreach_callback_func *callback, st_data_t arg) {
- switch ((enum shape_type)shape->type) {
- case SHAPE_ROOT:
- return;
- case SHAPE_IVAR:
- iterate_over_shapes_with_callback(shape->parent, iv_list, callback, arg);
- VALUE val = iv_list[shape->iv_count - 1];
- if (val != Qundef) {
- callback(shape->edge_name, val, arg);
- }
- return;
- case SHAPE_IVAR_UNDEF:
- case SHAPE_FROZEN:
- iterate_over_shapes_with_callback(shape->parent, iv_list, callback, arg);
- return;
+static ID
+iv_index_tbl_nth_id(st_table *iv_index_tbl, uint32_t index)
+{
+ st_data_t key;
+ RB_VM_LOCK_ENTER();
+ {
+ key = rb_st_nth_key(iv_index_tbl, index);
}
+ RB_VM_LOCK_LEAVE();
+ return (ID)key;
+}
+
+static inline bool
+ivar_each_i(st_table *iv_index_tbl, VALUE val, uint32_t i, rb_ivar_foreach_callback_func *func, st_data_t arg)
+{
+ if (val != Qundef) {
+ ID id = iv_index_tbl_nth_id(iv_index_tbl, i);
+ switch (func(id, val, arg)) {
+ case ST_CHECK:
+ case ST_CONTINUE:
+ break;
+ case ST_STOP:
+ return true;
+ default:
+ rb_bug("unreachable");
+ }
+ }
+ return false;
}
static void
obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
{
- rb_shape_t* shape = rb_shape_get_shape(obj);
- iterate_over_shapes_with_callback(shape, ROBJECT_IVPTR(obj), func, arg);
+ st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ if (!iv_index_tbl) return;
+ uint32_t i=0;
+
+ for (i=0; i < ROBJECT_NUMIV(obj); i++) {
+ VALUE val = ROBJECT_IVPTR(obj)[i];
+ if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
+ return;
+ }
+ }
}
static void
gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
{
- rb_shape_t *shape = rb_shape_get_shape(obj);
struct gen_ivtbl *ivtbl;
- if (!rb_gen_ivtbl_get(obj, 0, &ivtbl)) return;
+ st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
+ if (!iv_index_tbl) return;
+ if (!gen_ivtbl_get(obj, 0, &ivtbl)) return;
+
+ for (uint32_t i=0; i<ivtbl->numiv; i++) {
+ VALUE val = ivtbl->ivptr[i];
+ if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
+ return;
+ }
+ }
+}
+
+struct givar_copy {
+ VALUE obj;
+ VALUE klass;
+ st_table *iv_index_tbl;
+ struct gen_ivtbl *ivtbl;
+};
+
+static int
+gen_ivar_copy(ID id, VALUE val, st_data_t arg)
+{
+ struct givar_copy *c = (struct givar_copy *)arg;
+ struct ivar_update ivup;
+
+ ivup.iv_extended = 0;
+ ivup.u.iv_index_tbl = c->iv_index_tbl;
+
+ RB_VM_LOCK_ENTER();
+ {
+ iv_index_tbl_extend(&ivup, id, c->klass);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ if (ivup.index >= c->ivtbl->numiv) {
+ uint32_t newsize = iv_index_tbl_newsize(&ivup);
+ c->ivtbl = gen_ivtbl_resize(c->ivtbl, newsize);
+ }
+ c->ivtbl->ivptr[ivup.index] = val;
+
+ RB_OBJ_WRITTEN(c->obj, Qundef, val);
- iterate_over_shapes_with_callback(shape, ivtbl->ivptr, func, arg);
+ return ST_CONTINUE;
}
void
rb_copy_generic_ivar(VALUE clone, VALUE obj)
{
- struct gen_ivtbl *obj_ivtbl;
- struct gen_ivtbl *new_ivtbl;
+ struct gen_ivtbl *ivtbl;
rb_check_frozen(clone);
if (!FL_TEST(obj, FL_EXIVAR)) {
goto clear;
}
+ if (gen_ivtbl_get(obj, 0, &ivtbl)) {
+ struct givar_copy c;
+ uint32_t i;
- if (rb_gen_ivtbl_get(obj, 0, &obj_ivtbl)) {
- if (gen_ivtbl_count(obj_ivtbl) == 0)
+ if (gen_ivtbl_count(ivtbl) == 0)
goto clear;
- new_ivtbl = gen_ivtbl_resize(0, obj_ivtbl->numiv);
- FL_SET(clone, FL_EXIVAR);
-
- for (uint32_t i=0; i<obj_ivtbl->numiv; i++) {
- new_ivtbl->ivptr[i] = obj_ivtbl->ivptr[i];
- RB_OBJ_WRITTEN(clone, Qundef, &new_ivtbl[i]);
+ if (gen_ivtbl_get(clone, 0, &c.ivtbl)) {
+ for (i = 0; i < c.ivtbl->numiv; i++)
+ c.ivtbl->ivptr[i] = Qundef;
+ }
+ else {
+ c.ivtbl = gen_ivtbl_resize(0, ivtbl->numiv);
+ FL_SET(clone, FL_EXIVAR);
}
+ VALUE klass = rb_obj_class(clone);
+ c.iv_index_tbl = iv_index_tbl_make(clone, klass);
+ c.obj = clone;
+ c.klass = klass;
+ gen_ivar_each(obj, gen_ivar_copy, (st_data_t)&c);
/*
* c.ivtbl may change in gen_ivar_copy due to realloc,
* no need to free
@@ -1701,17 +1776,9 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj)
RB_VM_LOCK_ENTER();
{
generic_ivtbl_no_ractor_check(clone);
- st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)new_ivtbl);
+ st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)c.ivtbl);
}
RB_VM_LOCK_LEAVE();
-
- rb_shape_t * obj_shape = rb_shape_get_shape(obj);
- if (rb_shape_frozen_shape_p(obj_shape)) {
- rb_shape_set_shape(clone, obj_shape->parent);
- }
- else {
- rb_shape_set_shape(clone, obj_shape);
- }
}
return;
@@ -1779,7 +1846,7 @@ rb_ivar_count(VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if (rb_shape_get_shape(obj)->iv_count > 0) {
+ if (ROBJECT_IV_INDEX_TBL(obj) != 0) {
st_index_t i, count, num = ROBJECT_NUMIV(obj);
const VALUE *const ivptr = ROBJECT_IVPTR(obj);
for (i = count = 0; i < num; ++i) {
@@ -1800,7 +1867,7 @@ rb_ivar_count(VALUE obj)
if (FL_TEST(obj, FL_EXIVAR)) {
struct gen_ivtbl *ivtbl;
- if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
+ if (gen_ivtbl_get(obj, 0, &ivtbl)) {
return gen_ivtbl_count(ivtbl);
}
}
@@ -1898,53 +1965,40 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
{
VALUE val = Qnil;
const ID id = id_for_var(obj, name, an, instance);
+ st_data_t n, v;
+ struct st_table *iv_index_tbl;
+ uint32_t index;
- // Frozen check comes here because it's expected that we raise a
- // NameError (from the id_for_var check) before we raise a FrozenError
rb_check_frozen(obj);
-
- attr_index_t index;
-
if (!id) {
goto not_defined;
}
switch (BUILTIN_TYPE(obj)) {
+ case T_OBJECT:
+ iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
+ index < ROBJECT_NUMIV(obj) &&
+ (val = ROBJECT_IVPTR(obj)[index]) != Qundef) {
+ ROBJECT_IVPTR(obj)[index] = Qundef;
+ return val;
+ }
+ break;
case T_CLASS:
case T_MODULE:
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
- if (RCLASS_IV_TBL(obj)) {
- st_data_t id_data = (st_data_t)id, val;
- if (lock_st_delete(RCLASS_IV_TBL(obj), &id_data, &val)) {
- return (VALUE)val;
- }
- }
- break;
- case T_OBJECT: {
- rb_shape_t * shape = rb_shape_get_shape(obj);
- if (rb_shape_get_iv_index(shape, id, &index)) {
- rb_shape_transition_shape_remove_ivar(obj, id, shape);
- val = ROBJECT_IVPTR(obj)[index];
- ROBJECT_IVPTR(obj)[index] = Qundef;
- return val;
+ n = id;
+ if (RCLASS_IV_TBL(obj) && lock_st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
+ return (VALUE)v;
}
-
break;
- }
- default: {
- rb_shape_t * shape = rb_shape_get_shape(obj);
-
- if (rb_shape_get_iv_index(shape, id, &index)) {
- rb_shape_transition_shape_remove_ivar(obj, id, shape);
- struct gen_ivtbl *ivtbl;
- rb_gen_ivtbl_get(obj, id, &ivtbl);
- val = ivtbl->ivptr[index];
- ivtbl->ivptr[index] = Qundef;
- return val;
+ default:
+ if (FL_TEST(obj, FL_EXIVAR)) {
+ if (generic_ivar_remove(obj, id, &val)) {
+ return val;
+ }
}
-
break;
- }
}
not_defined:
diff --git a/variable.h b/variable.h
index 314ac82df0..55596b00de 100644
--- a/variable.h
+++ b/variable.h
@@ -11,19 +11,11 @@
/* per-object */
struct gen_ivtbl {
-#if !SHAPE_IN_BASIC_FLAGS
- uint16_t shape_id;
-#endif
uint32_t numiv;
VALUE ivptr[FLEX_ARY_LEN];
};
int rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **);
-
-#include "shape.h"
-#if !SHAPE_IN_BASIC_FLAGS
-shape_id_t rb_generic_shape_id(VALUE obj);
-#endif
-
+VALUE rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index);
#endif /* RUBY_TOPLEVEL_VARIABLE_H */
diff --git a/vm.c b/vm.c
index 77393458c2..0de461392f 100644
--- a/vm.c
+++ b/vm.c
@@ -26,7 +26,6 @@
#include "internal/thread.h"
#include "internal/vm.h"
#include "internal/sanitizers.h"
-#include "internal/variable.h"
#include "iseq.h"
#include "mjit.h"
#include "yjit.h"
@@ -2721,12 +2720,6 @@ rb_vm_update_references(void *ptr)
vm->top_self = rb_gc_location(vm->top_self);
vm->orig_progname = rb_gc_location(vm->orig_progname);
- for (shape_id_t i = 0; i <= vm->max_shape_count; i++) {
- if (vm->shape_list[i]) {
- vm->shape_list[i] = (rb_shape_t *)rb_gc_location((VALUE)vm->shape_list[i]);
- }
- }
-
rb_gc_update_tbl_refs(vm->overloaded_cme_table);
if (vm->coverages) {
@@ -2808,8 +2801,6 @@ rb_vm_mark(void *ptr)
obj_ary++;
}
- rb_gc_mark((VALUE)vm->root_shape);
- rb_gc_mark((VALUE)vm->frozen_root_shape);
rb_gc_mark_movable(vm->load_path);
rb_gc_mark_movable(vm->load_path_snapshot);
RUBY_MARK_MOVABLE_UNLESS_NULL(vm->load_path_check_cache);
@@ -4030,11 +4021,6 @@ Init_BareVM(void)
rb_native_cond_initialize(&vm->ractor.sync.terminate_cond);
}
-#ifndef _WIN32
-#include <unistd.h>
-#include <sys/mman.h>
-#endif
-
void
Init_vm_objects(void)
{
@@ -4046,37 +4032,6 @@ Init_vm_objects(void)
vm->mark_object_ary = rb_ary_hidden_new(128);
vm->loading_table = st_init_strtable();
vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 10000);
-
-#if HAVE_MMAP
- vm->shape_list = (rb_shape_t **)mmap(NULL, rb_size_mul_or_raise(SHAPE_BITMAP_SIZE * 32, sizeof(rb_shape_t *), rb_eRuntimeError),
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (vm->shape_list == MAP_FAILED) {
- vm->shape_list = 0;
- }
-#else
- vm->shape_list = xcalloc(SHAPE_BITMAP_SIZE * 32, sizeof(rb_shape_t *));
-#endif
-
- if (!vm->shape_list) {
- rb_memerror();
- }
-
- // Root shape
- vm->root_shape = rb_shape_alloc(ROOT_SHAPE_ID,
- 0,
- 0);
- rb_shape_set_shape_by_id(ROOT_SHAPE_ID, vm->root_shape);
- RB_OBJ_WRITTEN(vm->root_shape, Qundef, (VALUE)vm);
-
- // Frozen root shape
- vm->frozen_root_shape = rb_shape_alloc(FROZEN_ROOT_SHAPE_ID,
- rb_make_internal_id(),
- vm->root_shape);
- vm->frozen_root_shape->type = (uint8_t)SHAPE_FROZEN;
- RB_OBJ_FREEZE_RAW((VALUE)vm->frozen_root_shape);
- rb_shape_set_shape_by_id(FROZEN_ROOT_SHAPE_ID, vm->frozen_root_shape);
- RB_OBJ_WRITTEN(vm->frozen_root_shape, Qundef, (VALUE)vm);
- vm->max_shape_count = 1;
}
/* Stub for builtin function when not building YJIT units*/
diff --git a/vm_callinfo.h b/vm_callinfo.h
index e5b04c0709..fd2215be7d 100644
--- a/vm_callinfo.h
+++ b/vm_callinfo.h
@@ -10,7 +10,6 @@
#include "debug_counter.h"
#include "internal/class.h"
-#include "shape.h"
enum vm_call_flag_bits {
VM_CALL_ARGS_SPLAT_bit, /* m(*args) */
@@ -285,32 +284,14 @@ struct rb_callcache {
const vm_call_handler call_;
union {
- struct {
- const attr_index_t index;
- shape_id_t dest_shape_id;
- } attr;
+ const unsigned int attr_index;
const enum method_missing_reason method_missing_reason; /* used by method_missing */
VALUE v;
} aux_;
};
-#define VM_CALLCACHE_UNMARKABLE FL_FREEZE
-#define VM_CALLCACHE_ON_STACK FL_EXIVAR
-
-extern const struct rb_callcache *rb_vm_empty_cc(void);
-extern const struct rb_callcache *rb_vm_empty_cc_for_super(void);
-
-#define vm_cc_empty() rb_vm_empty_cc()
-
-static inline void
-vm_cc_attr_index_initialize(const struct rb_callcache *cc, shape_id_t shape_id)
-{
- VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
- VM_ASSERT(cc != vm_cc_empty());
- IMEMO_SET_CACHED_SHAPE_ID((VALUE)cc, shape_id);
- *(attr_index_t *)&cc->aux_.attr.index = 0;
- *(shape_id_t *)&cc->aux_.attr.dest_shape_id = shape_id;
-}
+#define VM_CALLCACHE_UNMARKABLE IMEMO_FL_USER0
+#define VM_CALLCACHE_ON_STACK IMEMO_FL_USER1
static inline const struct rb_callcache *
vm_cc_new(VALUE klass,
@@ -318,7 +299,6 @@ vm_cc_new(VALUE klass,
vm_call_handler call)
{
const struct rb_callcache *cc = (const struct rb_callcache *)rb_imemo_new(imemo_callcache, (VALUE)cme, (VALUE)call, 0, klass);
- vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
RB_DEBUG_COUNTER_INC(cc_new);
return cc;
}
@@ -370,71 +350,30 @@ vm_cc_call(const struct rb_callcache *cc)
return cc->call_;
}
-static inline attr_index_t
+static inline unsigned int
vm_cc_attr_index(const struct rb_callcache *cc)
{
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
- return cc->aux_.attr.index - 1;
+ return cc->aux_.attr_index - 1;
}
static inline bool
vm_cc_attr_index_p(const struct rb_callcache *cc)
{
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
- return cc->aux_.attr.index != 0;
-}
-
-static inline shape_id_t
-vm_cc_attr_index_source_shape_id(const struct rb_callcache *cc)
-{
- VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
-
- return IMEMO_CACHED_SHAPE_ID((VALUE)cc);
+ return cc->aux_.attr_index > 0;
}
-static inline shape_id_t
-vm_cc_attr_shape_id(const struct rb_callcache *cc)
+static inline uint32_t
+vm_ic_entry_index(const struct iseq_inline_iv_cache_entry *ic)
{
- VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
- return vm_cc_attr_index_source_shape_id(cc);
-}
-
-static inline shape_id_t
-vm_cc_attr_index_dest_shape_id(const struct rb_callcache *cc)
-{
- VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
-
- return cc->aux_.attr.dest_shape_id;
-}
-
-static inline attr_index_t
-vm_ic_attr_index(const struct iseq_inline_iv_cache_entry *ic)
-{
- return ic->attr_index - 1;
+ return ic->entry->index;
}
static inline bool
-vm_ic_attr_index_p(const struct iseq_inline_iv_cache_entry *ic)
-{
- return ic->attr_index > 0;
-}
-
-static inline shape_id_t
-vm_ic_attr_shape_id(const struct iseq_inline_iv_cache_entry *ic)
-{
- return ic->source_shape_id;
-}
-
-static inline shape_id_t
-vm_ic_attr_index_source_shape_id(const struct iseq_inline_iv_cache_entry *ic)
+vm_ic_entry_p(const struct iseq_inline_iv_cache_entry *ic)
{
- return ic->source_shape_id;
-}
-
-static inline shape_id_t
-vm_ic_attr_index_dest_shape_id(const struct iseq_inline_iv_cache_entry *ic)
-{
- return ic->dest_shape_id;
+ return ic->entry;
}
static inline unsigned int
@@ -468,6 +407,10 @@ vm_cc_valid_p(const struct rb_callcache *cc, const rb_callable_method_entry_t *c
}
}
+extern const struct rb_callcache *rb_vm_empty_cc(void);
+extern const struct rb_callcache *rb_vm_empty_cc_for_super(void);
+#define vm_cc_empty() rb_vm_empty_cc()
+
/* callcache: mutate */
static inline void
@@ -479,29 +422,26 @@ vm_cc_call_set(const struct rb_callcache *cc, vm_call_handler call)
}
static inline void
-vm_cc_attr_index_set(const struct rb_callcache *cc, attr_index_t index, shape_id_t source_shape_id, shape_id_t dest_shape_id)
+vm_cc_attr_index_set(const struct rb_callcache *cc, int index)
{
VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
VM_ASSERT(cc != vm_cc_empty());
- IMEMO_SET_CACHED_SHAPE_ID((VALUE)cc, source_shape_id);
- *(attr_index_t *)&cc->aux_.attr.index = (index + 1);
- *(shape_id_t *)&cc->aux_.attr.dest_shape_id = dest_shape_id;
+ *(int *)&cc->aux_.attr_index = index + 1;
}
static inline void
-vm_ic_attr_index_set(const rb_iseq_t *iseq, const struct iseq_inline_iv_cache_entry *ic, attr_index_t index, shape_id_t source_shape_id, shape_id_t dest_shape_id)
+vm_ic_entry_set(struct iseq_inline_iv_cache_entry *ic, struct rb_iv_index_tbl_entry *entry, const rb_iseq_t *iseq)
{
- *(shape_id_t *)&ic->source_shape_id = source_shape_id;
- *(shape_id_t *)&ic->dest_shape_id = dest_shape_id;
- *(attr_index_t *)&ic->attr_index = index + 1;
+ ic->entry = entry;
+ RB_OBJ_WRITTEN(iseq, Qundef, entry->class_value);
}
static inline void
-vm_ic_attr_index_initialize(const struct iseq_inline_iv_cache_entry *ic, shape_id_t shape_id)
+vm_cc_attr_index_initialize(const struct rb_callcache *cc)
{
- *(shape_id_t *)&ic->source_shape_id = shape_id;
- *(shape_id_t *)&ic->dest_shape_id = shape_id;
- *(attr_index_t *)&ic->attr_index = 0;
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc != vm_cc_empty());
+ *(int *)&cc->aux_.attr_index = 0;
}
static inline void
diff --git a/vm_core.h b/vm_core.h
index b4768be136..e11838a59a 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -99,7 +99,6 @@ extern int ruby_assert_critical_section_entered;
#include "ruby/st.h"
#include "ruby_atomic.h"
#include "vm_opts.h"
-#include "shape.h"
#include "ruby/thread_native.h"
@@ -273,9 +272,7 @@ struct iseq_inline_constant_cache {
};
struct iseq_inline_iv_cache_entry {
- shape_id_t source_shape_id;
- shape_id_t dest_shape_id;
- attr_index_t attr_index;
+ struct rb_iv_index_tbl_entry *entry;
};
struct iseq_inline_cvar_cache_entry {
@@ -690,12 +687,6 @@ typedef struct rb_vm_struct {
VALUE mark_object_ary;
const VALUE special_exceptions[ruby_special_error_count];
- /* object shapes */
- rb_shape_t **shape_list;
- rb_shape_t *root_shape;
- rb_shape_t *frozen_root_shape;
- shape_id_t max_shape_count;
-
/* load */
VALUE top_self;
VALUE load_path;
diff --git a/vm_eval.c b/vm_eval.c
index bfa812f3d3..c0558fce2b 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -47,7 +47,7 @@ rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE
{
struct rb_calling_info calling = {
.ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
- .cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, {{ 0 }}, cme),
+ .cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme),
.block_handler = vm_passed_block_handler(ec),
.recv = recv,
.argc = argc,
@@ -89,7 +89,7 @@ vm_call0_cc(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE
static VALUE
vm_call0_cme(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, const rb_callable_method_entry_t *cme)
{
- calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, {{ 0 }}, cme);
+ calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme);
return vm_call0_body(ec, calling, argv);
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 1cd66cf1eb..a662de468d 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -50,11 +50,6 @@ MJIT_STATIC VALUE
ruby_vm_special_exception_copy(VALUE exc)
{
VALUE e = rb_obj_alloc(rb_class_real(RBASIC_CLASS(exc)));
- rb_shape_t * shape = rb_shape_get_shape(exc);
- if (rb_shape_frozen_shape_p(shape)) {
- shape = shape->parent;
- }
- rb_shape_set_shape(e, shape);
rb_obj_copy_ivar(e, exc);
return e;
}
@@ -1090,19 +1085,35 @@ vm_get_cvar_base(const rb_cref_t *cref, const rb_control_frame_t *cfp, int top_l
return klass;
}
-ALWAYS_INLINE(static void fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, attr_index_t index, shape_id_t shape_id));
+static bool
+iv_index_tbl_lookup(struct st_table *iv_index_tbl, ID id, struct rb_iv_index_tbl_entry **ent)
+{
+ int found;
+ st_data_t ent_data;
+
+ if (iv_index_tbl == NULL) return false;
+
+ RB_VM_LOCK_ENTER();
+ {
+ found = st_lookup(iv_index_tbl, (st_data_t)id, &ent_data);
+ }
+ RB_VM_LOCK_LEAVE();
+ if (found) *ent = (struct rb_iv_index_tbl_entry *)ent_data;
+
+ return found ? true : false;
+}
+
+ALWAYS_INLINE(static void fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, struct rb_iv_index_tbl_entry *ent));
+
static inline void
-fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, attr_index_t index, shape_id_t shape_id)
+fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, struct rb_iv_index_tbl_entry *ent)
{
- if (is_attr) {
- if (vm_cc_markable(cc)) {
- vm_cc_attr_index_set(cc, index, shape_id, shape_id);
- RB_OBJ_WRITTEN(cc, Qundef, rb_shape_get_shape_by_id(shape_id));
- }
+ // fill cache
+ if (!is_attr) {
+ vm_ic_entry_set(ic, ent, iseq);
}
else {
- vm_ic_attr_index_set(iseq, ic, index, shape_id, shape_id);
- RB_OBJ_WRITTEN(iseq, Qundef, rb_shape_get_shape_by_id(shape_id));
+ vm_cc_attr_index_set(cc, ent->index);
}
}
@@ -1112,120 +1123,68 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
{
#if OPT_IC_FOR_IVAR
VALUE val = Qundef;
- shape_id_t shape_id;
- VALUE * ivar_list;
if (SPECIAL_CONST_P(obj)) {
- return Qnil;
+ // frozen?
}
+ else if (LIKELY(is_attr ?
+ RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_unset, vm_cc_attr_index_p(cc)) :
+ RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_serial, vm_ic_entry_p(ic) && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass)))) {
+ uint32_t index = !is_attr ? vm_ic_entry_index(ic): (vm_cc_attr_index(cc));
-#if SHAPE_IN_BASIC_FLAGS
- shape_id = RBASIC_SHAPE_ID(obj);
-#endif
+ RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- ivar_list = ROBJECT_IVPTR(obj);
- VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true);
+ if (LIKELY(BUILTIN_TYPE(obj) == T_OBJECT) &&
+ LIKELY(index < ROBJECT_NUMIV(obj))) {
+ val = ROBJECT_IVPTR(obj)[index];
-#if !SHAPE_IN_BASIC_FLAGS
- shape_id = ROBJECT_SHAPE_ID(obj);
-#endif
- break;
- case T_CLASS:
- case T_MODULE:
- {
- goto general_path;
- }
- default:
- if (FL_TEST_RAW(obj, FL_EXIVAR)) {
- struct gen_ivtbl *ivtbl;
- rb_gen_ivtbl_get(obj, id, &ivtbl);
-#if !SHAPE_IN_BASIC_FLAGS
- shape_id = ivtbl->shape_id;
-#endif
- ivar_list = ivtbl->ivptr;
- } else {
- return Qnil;
- }
- }
-
- shape_id_t cached_id;
+ VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true);
+ }
+ else if (FL_TEST_RAW(obj, FL_EXIVAR)) {
+ val = rb_ivar_generic_lookup_with_index(obj, id, index);
+ }
- if (is_attr) {
- cached_id = vm_cc_attr_shape_id(cc);
+ goto ret;
}
else {
- cached_id = vm_ic_attr_shape_id(ic);
- }
+ struct rb_iv_index_tbl_entry *ent;
- attr_index_t index;
+ if (BUILTIN_TYPE(obj) == T_OBJECT) {
+ struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (LIKELY(cached_id == shape_id)) {
- RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &ent)) {
+ fill_ivar_cache(iseq, ic, cc, is_attr, ent);
- if (is_attr && vm_cc_attr_index_p(cc)) {
- index = vm_cc_attr_index(cc);
- }
- else if (!is_attr && vm_ic_attr_index_p(ic)) {
- index = vm_ic_attr_index(ic);
- }
- else {
- return Qnil;
+ // get value
+ if (ent->index < ROBJECT_NUMIV(obj)) {
+ val = ROBJECT_IVPTR(obj)[ent->index];
+
+ VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true);
+ }
+ }
}
+ else if (FL_TEST_RAW(obj, FL_EXIVAR)) {
+ struct st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
- val = ivar_list[index];
- VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true);
- }
- else { // cache miss case
-#if RUBY_DEBUG
- if (is_attr) {
- if (cached_id != INVALID_SHAPE_ID) {
- RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_set);
- } else {
- RB_DEBUG_COUNTER_INC(ivar_get_cc_miss_unset);
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &ent)) {
+ fill_ivar_cache(iseq, ic, cc, is_attr, ent);
+ val = rb_ivar_generic_lookup_with_index(obj, id, ent->index);
}
}
else {
- if (cached_id != INVALID_SHAPE_ID) {
- RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_set);
- } else {
- RB_DEBUG_COUNTER_INC(ivar_get_ic_miss_unset);
- }
+ // T_CLASS / T_MODULE
+ goto general_path;
}
-#endif
-
- attr_index_t index;
- rb_shape_t *shape = rb_shape_get_shape_by_id(shape_id);
- if (rb_shape_get_iv_index(shape, id, &index)) {
- // This fills in the cache with the shared cache object.
- // "ent" is the shared cache object
- fill_ivar_cache(iseq, ic, cc, is_attr, index, shape_id);
-
- // We fetched the ivar list above
- val = ivar_list[index];
+ ret:
+ if (LIKELY(val != Qundef)) {
+ return val;
}
else {
- if (is_attr) {
- if (vm_cc_markable(cc)) {
- vm_cc_attr_index_initialize(cc, shape_id);
- }
- }
- else {
- vm_ic_attr_index_initialize(ic, shape_id);
- }
-
- val = Qnil;
+ return Qnil;
}
-
}
-
- RUBY_ASSERT(val != Qundef);
-
- return val;
-
-general_path:
+ general_path:
#endif /* OPT_IC_FOR_IVAR */
RB_DEBUG_COUNTER_INC(ivar_get_ic_miss);
@@ -1237,24 +1196,6 @@ general_path:
}
}
-static void
-populate_cache(attr_index_t index, rb_shape_t *shape, rb_shape_t *next_shape, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, bool is_attr)
-{
- // Cache population code
- if (is_attr) {
- if (vm_cc_markable(cc)) {
- vm_cc_attr_index_set(cc, index, SHAPE_ID(shape), SHAPE_ID(next_shape));
- RB_OBJ_WRITTEN(cc, Qundef, (VALUE)shape);
- RB_OBJ_WRITTEN(cc, Qundef, (VALUE)next_shape);
- }
- }
- else {
- vm_ic_attr_index_set(iseq, ic, index, SHAPE_ID(shape), SHAPE_ID(next_shape));
- RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)shape);
- RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)next_shape);
- }
-}
-
ALWAYS_INLINE(static VALUE vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr));
NOINLINE(static VALUE vm_setivar_slowpath_ivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic));
NOINLINE(static VALUE vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, const struct rb_callcache *cc));
@@ -1262,66 +1203,35 @@ NOINLINE(static VALUE vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, cons
static VALUE
vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
{
-#if OPT_IC_FOR_IVAR
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- {
- rb_check_frozen_internal(obj);
-
- attr_index_t index;
-
- uint32_t num_iv = ROBJECT_NUMIV(obj);
- rb_shape_t* shape = rb_shape_get_shape(obj);
- rb_shape_t* next_shape = rb_shape_get_next(shape, obj, id);
- if (shape != next_shape) {
- rb_shape_set_shape(obj, next_shape);
- }
-
- if (rb_shape_get_iv_index(next_shape, id, &index)) { // based off the hash stored in the transition tree
- if (index >= MAX_IVARS) {
- rb_raise(rb_eArgError, "too many instance variables");
- }
-
- populate_cache(index, shape, next_shape, id, iseq, ic, cc, is_attr);
- }
- else {
- rb_bug("Didn't find instance variable %s\n", rb_id2name(id));
- }
-
- // Ensure the IV buffer is wide enough to store the IV
- if (UNLIKELY(index >= num_iv)) {
- rb_init_iv_list(obj);
- }
+ rb_check_frozen_internal(obj);
- VALUE *ptr = ROBJECT_IVPTR(obj);
- RB_OBJ_WRITE(obj, &ptr[index], val);
- RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_iv_hit);
+#if OPT_IC_FOR_IVAR
+ if (RB_TYPE_P(obj, T_OBJECT)) {
+ struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ struct rb_iv_index_tbl_entry *ent;
- return val;
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &ent)) {
+ if (!is_attr) {
+ vm_ic_entry_set(ic, ent, iseq);
+ }
+ else if (ent->index >= INT_MAX) {
+ rb_raise(rb_eArgError, "too many instance variables");
+ }
+ else {
+ vm_cc_attr_index_set(cc, (int)(ent->index));
}
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- {
- rb_shape_t * shape = rb_shape_get_shape(obj);
- rb_ivar_set(obj, id, val);
- rb_shape_t * next_shape = rb_shape_get_shape(obj);
- attr_index_t index;
-
- if (rb_shape_get_iv_index(next_shape, id, &index)) { // based off the hash stored in the transition tree
- if (index >= MAX_IVARS) {
- rb_raise(rb_eArgError, "too many instance variables");
- }
- populate_cache(index, shape, next_shape, id, iseq, ic, cc, is_attr);
- }
- else {
- rb_bug("didn't find the id\n");
- }
+ uint32_t index = ent->index;
- return val;
+ if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
+ rb_init_iv_list(obj);
}
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ RB_OBJ_WRITE(obj, &ptr[index], val);
+ RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_iv_hit);
+
+ return val;
+ }
}
#endif
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
@@ -1340,99 +1250,39 @@ vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, const struct rb_callcache
return vm_setivar_slowpath(obj, id, val, NULL, NULL, cc, true);
}
-NOINLINE(static VALUE vm_setivar_default(VALUE obj, ID id, VALUE val, shape_id_t source_shape_id, shape_id_t dest_shape_id, attr_index_t index));
-static VALUE
-vm_setivar_default(VALUE obj, ID id, VALUE val, shape_id_t source_shape_id, shape_id_t dest_shape_id, attr_index_t index)
-{
-#if SHAPE_IN_BASIC_FLAGS
- shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
-#else
- shape_id_t shape_id = rb_generic_shape_id(obj);
-#endif
-
- // Cache hit case
- if (shape_id == source_shape_id) {
- RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
-
- struct gen_ivtbl *ivtbl = 0;
- if (dest_shape_id != shape_id) {
- ivtbl = rb_ensure_generic_iv_list_size(obj, index + 1);
-#if SHAPE_IN_BASIC_FLAGS
- RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
-#else
- ivtbl->shape_id = dest_shape_id;
-#endif
- RB_OBJ_WRITTEN(obj, Qundef, rb_shape_get_shape_by_id(dest_shape_id));
- }
- else {
- // Just get the IV table
- RUBY_ASSERT(GET_VM()->shape_list[dest_shape_id]);
- rb_gen_ivtbl_get(obj, 0, &ivtbl);
- }
-
- VALUE *ptr = ivtbl->ivptr;
-
- RB_OBJ_WRITE(obj, &ptr[index], val);
-
- RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
-
- return val;
- }
-
- return Qundef;
-}
-
static inline VALUE
-vm_setivar(VALUE obj, ID id, VALUE val, shape_id_t source_shape_id, shape_id_t dest_shape_id, attr_index_t index)
+vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
{
#if OPT_IC_FOR_IVAR
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- {
- VM_ASSERT(!rb_ractor_shareable_p(obj) || rb_obj_frozen_p(obj));
- // If object's shape id is the same as the source
- // then do the shape transition and write the ivar
- // If object's shape id is the same as the dest
- // then write the ivar
- shape_id_t shape_id = ROBJECT_SHAPE_ID(obj);
-
- // Do we have a cache hit *and* is the CC intitialized
- if (shape_id == source_shape_id) {
- RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);
-
- VM_ASSERT(!rb_ractor_shareable_p(obj));
-
- if (dest_shape_id != shape_id) {
- if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
- rb_init_iv_list(obj);
- }
- ROBJECT_SET_SHAPE_ID(obj, dest_shape_id);
- }
- else {
- RUBY_ASSERT(GET_VM()->shape_list[dest_shape_id]);
- }
-
- RUBY_ASSERT(index < ROBJECT_NUMIV(obj));
+ if (LIKELY(RB_TYPE_P(obj, T_OBJECT)) &&
+ LIKELY(!RB_OBJ_FROZEN_RAW(obj))) {
- VALUE *ptr = ROBJECT_IVPTR(obj);
+ VM_ASSERT(!rb_ractor_shareable_p(obj));
- RB_OBJ_WRITE(obj, &ptr[index], val);
+ if (LIKELY(
+ (!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, vm_ic_entry_p(ic) && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass))) ||
+ ( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, vm_cc_attr_index_p(cc))))) {
+ uint32_t index = !is_attr ? vm_ic_entry_index(ic) : vm_cc_attr_index(cc);
- RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
-
- return val;
- }
+ if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
+ rb_init_iv_list(obj);
}
- break;
- case T_CLASS:
- case T_MODULE:
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ RB_OBJ_WRITE(obj, &ptr[index], val);
+ RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
+ return val; /* inline cache hit */
+ }
+ }
+ else {
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
- default:
- break;
}
-
- return Qundef;
#endif /* OPT_IC_FOR_IVAR */
+ if (is_attr) {
+ return vm_setivar_slowpath_attr(obj, id, val, cc);
+ }
+ else {
+ return vm_setivar_slowpath_ivar(obj, id, val, iseq, ic);
+ }
}
static VALUE
@@ -1527,22 +1377,7 @@ vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic)
static inline void
vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic)
{
- shape_id_t source_shape_id = vm_ic_attr_index_source_shape_id(ic);
- attr_index_t index = vm_ic_attr_index(ic);
- shape_id_t dest_shape_id = vm_ic_attr_index_dest_shape_id(ic);
- if (UNLIKELY(vm_setivar(obj, id, val, source_shape_id, dest_shape_id, index) == Qundef)) {
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- if (vm_setivar_default(obj, id, val, source_shape_id, dest_shape_id, index) != Qundef) {
- return;
- }
- }
- vm_setivar_slowpath_ivar(obj, id, val, iseq, ic);
- }
+ vm_setivar(obj, id, val, iseq, ic, 0, 0);
}
void
@@ -1551,6 +1386,28 @@ rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IV
vm_setinstancevariable(iseq, obj, id, val, ic);
}
+/* Set the instance variable +val+ on object +obj+ at the +index+.
+ * This function only works with T_OBJECT objects, so make sure
+ * +obj+ is of type T_OBJECT before using this function.
+ */
+VALUE
+rb_vm_set_ivar_idx(VALUE obj, uint32_t index, VALUE val)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
+
+ rb_check_frozen_internal(obj);
+
+ VM_ASSERT(!rb_ractor_shareable_p(obj));
+
+ if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
+ rb_init_iv_list(obj);
+ }
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ RB_OBJ_WRITE(obj, &ptr[index], val);
+
+ return val;
+}
+
static VALUE
vm_throw_continue(const rb_execution_context_t *ec, VALUE err)
{
@@ -3243,45 +3100,17 @@ vm_call_ivar(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_call
const struct rb_callcache *cc = calling->cc;
RB_DEBUG_COUNTER_INC(ccf_ivar);
cfp->sp -= 1;
- VALUE ivar = vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE);
- return ivar;
+ return vm_getivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, NULL, NULL, cc, TRUE);
}
static VALUE
-vm_call_attrset_direct(rb_execution_context_t *ec, rb_control_frame_t *cfp, const struct rb_callcache *cc, VALUE obj)
+vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling)
{
+ const struct rb_callcache *cc = calling->cc;
RB_DEBUG_COUNTER_INC(ccf_attrset);
VALUE val = *(cfp->sp - 1);
cfp->sp -= 2;
- shape_id_t source_shape_id = vm_cc_attr_index_source_shape_id(cc);
- attr_index_t index = vm_cc_attr_index(cc);
- shape_id_t dest_shape_id = vm_cc_attr_index_dest_shape_id(cc);
- ID id = vm_cc_cme(cc)->def->body.attr.id;
- rb_check_frozen_internal(obj);
- VALUE res = vm_setivar(obj, id, val, source_shape_id, dest_shape_id, index);
- if (res == Qundef) {
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- {
- res = vm_setivar_default(obj, id, val, source_shape_id, dest_shape_id, index);
- if (res != Qundef) {
- return res;
- }
- }
- }
- res = vm_setivar_slowpath_attr(obj, id, val, cc);
- }
- return res;
-}
-
-static VALUE
-vm_call_attrset(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling)
-{
- return vm_call_attrset_direct(ec, cfp, calling->cc, calling->recv);
+ return vm_setivar(calling->recv, vm_cc_cme(cc)->def->body.attr.id, val, NULL, NULL, cc, 1);
}
bool
@@ -3390,7 +3219,7 @@ vm_call_alias(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_cal
{
calling->cc = &VM_CC_ON_STACK(Qundef,
vm_call_general,
- {{0}},
+ { 0 },
aliased_callable_method_entry(vm_cc_cme(calling->cc)));
return vm_call_method_each_type(ec, cfp, calling);
@@ -3560,7 +3389,7 @@ vm_call_method_missing_body(rb_execution_context_t *ec, rb_control_frame_t *reg_
ec->method_missing_reason = reason;
calling->ci = &VM_CI_ON_STACK(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci));
- calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, {{ 0 }},
+ calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, { 0 },
rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv), idMethodMissing, NULL));
return vm_call_method(ec, reg_cfp, calling);
}
@@ -3586,7 +3415,7 @@ vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_ca
cme = refined_method_callable_without_refinement(cme);
}
- calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, {{ 0 }}, cme);
+ calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, { 0 }, cme);
return vm_call_method_each_type(ec, cfp, calling);
}
@@ -3693,7 +3522,7 @@ search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struc
static VALUE
vm_call_refined(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling)
{
- struct rb_callcache *ref_cc = &VM_CC_ON_STACK(Qundef, vm_call_general, {{ 0 }},
+ struct rb_callcache *ref_cc = &VM_CC_ON_STACK(Qundef, vm_call_general, { 0 },
search_refined_method(ec, cfp, calling));
if (vm_cc_cme(ref_cc)) {
@@ -3873,45 +3702,18 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
rb_check_arity(calling->argc, 1, 1);
-
+ vm_cc_attr_index_initialize(cc);
const unsigned int aset_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT | VM_CALL_KWARG);
-
- if (vm_cc_markable(cc)) {
- vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
- VM_CALL_METHOD_ATTR(v,
- vm_call_attrset_direct(ec, cfp, cc, calling->recv),
- CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
- } else {
- cc = &((struct rb_callcache) {
- .flags = T_IMEMO |
- (imemo_callcache << FL_USHIFT) |
- VM_CALLCACHE_UNMARKABLE |
- ((VALUE)INVALID_SHAPE_ID << SHAPE_FLAG_SHIFT) |
- VM_CALLCACHE_ON_STACK,
- .klass = cc->klass,
- .cme_ = cc->cme_,
- .call_ = cc->call_,
- .aux_ = {
- .attr = {
- .index = 0,
- .dest_shape_id = INVALID_SHAPE_ID,
- }
- },
- });
-
- VM_CALL_METHOD_ATTR(v,
- vm_call_attrset_direct(ec, cfp, cc, calling->recv),
- CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
- }
+ VM_CALL_METHOD_ATTR(v,
+ vm_call_attrset(ec, cfp, calling),
+ CC_SET_FASTPATH(cc, vm_call_attrset, !(vm_ci_flag(ci) & aset_mask)));
return v;
case VM_METHOD_TYPE_IVAR:
CALLER_SETUP_ARG(cfp, calling, ci);
CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
rb_check_arity(calling->argc, 0, 0);
- if (vm_cc_markable(cc)) {
- vm_cc_attr_index_initialize(cc, INVALID_SHAPE_ID);
- }
+ vm_cc_attr_index_initialize(cc);
const unsigned int ivar_mask = (VM_CALL_ARGS_SPLAT | VM_CALL_KW_SPLAT);
VM_CALL_METHOD_ATTR(v,
vm_call_ivar(ec, cfp, calling),
diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs
index 4b50d888de..c3d4a39a2b 100644
--- a/yjit/bindgen/src/main.rs
+++ b/yjit/bindgen/src/main.rs
@@ -40,7 +40,6 @@ fn main() {
.header("internal.h")
.header("internal/re.h")
.header("include/ruby/ruby.h")
- .header("shape.h")
.header("vm_core.h")
.header("vm_callinfo.h")
@@ -82,12 +81,6 @@ fn main() {
// This function prints info about a value and is useful for debugging
.allowlist_function("rb_obj_info_dump")
- // From shape.h
- .allowlist_function("rb_shape_get_shape_id")
- .allowlist_function("rb_shape_get_shape_by_id")
- .allowlist_function("rb_shape_flags_mask")
- .allowlist_function("rb_shape_get_iv_index")
-
// From ruby/internal/intern/object.h
.allowlist_function("rb_obj_is_kind_of")
diff --git a/yjit/src/asm/x86_64/mod.rs b/yjit/src/asm/x86_64/mod.rs
index 42d97b7e80..d310e3bf12 100644
--- a/yjit/src/asm/x86_64/mod.rs
+++ b/yjit/src/asm/x86_64/mod.rs
@@ -617,7 +617,7 @@ fn write_rm_multi(cb: &mut CodeBlock, op_mem_reg8: u8, op_mem_reg_pref: u8, op_r
write_rm(cb, sz_pref, rex_w, X86Opnd::None, opnd0, op_ext_imm, &[op_mem_imm_lrg]);
cb.write_int(uimm.value, if opnd_size > 32 { 32 } else { opnd_size.into() });
} else {
- panic!("immediate value too large (num_bits={})", num_bits);
+ panic!("immediate value too large");
}
},
_ => unreachable!()
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 4018a314fc..c246c7b48f 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -1938,12 +1938,14 @@ fn gen_set_ivar(
let val_opnd = ctx.stack_pop(1);
let recv_opnd = ctx.stack_pop(1);
- // Call rb_vm_set_ivar_id with the receiver, the ivar name, and the value
+ let ivar_index: u32 = unsafe { rb_obj_ensure_iv_index_mapping(recv, ivar_name) };
+
+ // Call rb_vm_set_ivar_idx with the receiver, the index of the ivar, and the value
let val = asm.ccall(
- rb_vm_set_ivar_id as *const u8,
+ rb_vm_set_ivar_idx as *const u8,
vec![
recv_opnd,
- Opnd::UImm(ivar_name.into()),
+ Opnd::Imm(ivar_index.into()),
val_opnd,
],
);
@@ -2021,82 +2023,81 @@ fn gen_get_ivar(
return EndBlock;
}
- let ivar_index = unsafe {
- let shape_id = comptime_receiver.shape_of();
- let shape = rb_shape_get_shape_by_id(shape_id);
- let mut ivar_index: u32 = 0;
- if rb_shape_get_iv_index(shape, ivar_name, &mut ivar_index) {
- Some(ivar_index as usize)
- } else {
- None
- }
- };
-
- // must be before stack_pop
- let recv_type = ctx.get_opnd_type(recv_opnd);
-
- // Upgrade type
- if !recv_type.is_heap() {
- ctx.upgrade_opnd_type(recv_opnd, Type::UnknownHeap);
- }
+ // FIXME: Mapping the index could fail when there is too many ivar names. If we're
+ // compiling for a branch stub that can cause the exception to be thrown from the
+ // wrong PC.
+ let ivar_index =
+ unsafe { rb_obj_ensure_iv_index_mapping(comptime_receiver, ivar_name) }.as_usize();
// Pop receiver if it's on the temp stack
if recv_opnd != SelfOpnd {
ctx.stack_pop(1);
}
- // Guard heap object
- if !recv_type.is_heap() {
- guard_object_is_heap(asm, recv, side_exit);
+ if USE_RVARGC != 0 {
+ // Check that the ivar table is big enough
+ // Check that the slot is inside the ivar table (num_slots > index)
+ let num_slots = Opnd::mem(32, recv, ROBJECT_OFFSET_NUMIV);
+ asm.cmp(num_slots, Opnd::UImm(ivar_index as u64));
+ asm.jbe(counted_exit!(ocb, side_exit, getivar_idx_out_of_range).into());
}
// Compile time self is embedded and the ivar index lands within the object
- let embed_test_result = unsafe { FL_TEST_RAW(comptime_receiver, VALUE(ROBJECT_EMBED.as_usize())) != VALUE(0) };
-
- let flags_mask: usize = unsafe { rb_shape_flags_mask() }.as_usize();
- let expected_flags_mask: usize = (RUBY_T_MASK as usize) | !flags_mask | (ROBJECT_EMBED as usize);
- let expected_flags = comptime_receiver.builtin_flags() & expected_flags_mask;
-
- // Combined guard for all flags: shape, embeddedness, and T_OBJECT
- let flags_opnd = Opnd::mem(64, recv, RUBY_OFFSET_RBASIC_FLAGS);
-
- asm.comment("guard shape, embedded, and T_OBJECT");
- let flags_opnd = asm.and(flags_opnd, Opnd::UImm(expected_flags_mask as u64));
- asm.cmp(flags_opnd, Opnd::UImm(expected_flags as u64));
- jit_chain_guard(
- JCC_JNE,
- jit,
- &starting_context,
- asm,
- ocb,
- max_chain_depth,
- side_exit,
- );
-
- // If there is no IVAR index, then the ivar was undefined
- // when we entered the compiler. That means we can just return
- // nil for this shape + iv name
- if ivar_index.is_none() {
- let out_opnd = ctx.stack_push(Type::Nil);
- asm.mov(out_opnd, Qnil.into());
- } else if embed_test_result {
+ let test_result = unsafe { FL_TEST_RAW(comptime_receiver, VALUE(ROBJECT_EMBED.as_usize())) != VALUE(0) };
+ if test_result {
// See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h
+ // Guard that self is embedded
+ // TODO: BT and JC is shorter
+ asm.comment("guard embedded getivar");
+ let flags_opnd = Opnd::mem(64, recv, RUBY_OFFSET_RBASIC_FLAGS);
+ asm.test(flags_opnd, Opnd::UImm(ROBJECT_EMBED as u64));
+ let side_exit = counted_exit!(ocb, side_exit, getivar_megamorphic);
+ jit_chain_guard(
+ JCC_JZ,
+ jit,
+ &starting_context,
+ asm,
+ ocb,
+ max_chain_depth,
+ side_exit,
+ );
+
// Load the variable
- let offs = ROBJECT_OFFSET_AS_ARY + (ivar_index.unwrap() * SIZEOF_VALUE) as i32;
+ let offs = ROBJECT_OFFSET_AS_ARY + (ivar_index * SIZEOF_VALUE) as i32;
let ivar_opnd = Opnd::mem(64, recv, offs);
+ // Guard that the variable is not Qundef
+ asm.cmp(ivar_opnd, Qundef.into());
+ let out_val = asm.csel_e(Qnil.into(), ivar_opnd);
+
// Push the ivar on the stack
let out_opnd = ctx.stack_push(Type::Unknown);
- asm.mov(out_opnd, ivar_opnd);
+ asm.mov(out_opnd, out_val);
} else {
// Compile time value is *not* embedded.
+ // Guard that value is *not* embedded
+ // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h
+ asm.comment("guard extended getivar");
+ let flags_opnd = Opnd::mem(64, recv, RUBY_OFFSET_RBASIC_FLAGS);
+ asm.test(flags_opnd, Opnd::UImm(ROBJECT_EMBED as u64));
+ let megamorphic_side_exit = counted_exit!(ocb, side_exit, getivar_megamorphic);
+ jit_chain_guard(
+ JCC_JNZ,
+ jit,
+ &starting_context,
+ asm,
+ ocb,
+ max_chain_depth,
+ megamorphic_side_exit,
+ );
+
if USE_RVARGC == 0 {
// Check that the extended table is big enough
// Check that the slot is inside the extended table (num_slots > index)
let num_slots = Opnd::mem(32, recv, ROBJECT_OFFSET_NUMIV);
- asm.cmp(num_slots, Opnd::UImm(ivar_index.unwrap() as u64));
+ asm.cmp(num_slots, Opnd::UImm(ivar_index as u64));
asm.jbe(counted_exit!(ocb, side_exit, getivar_idx_out_of_range).into());
}
@@ -2104,10 +2105,15 @@ fn gen_get_ivar(
let tbl_opnd = asm.load(Opnd::mem(64, recv, ROBJECT_OFFSET_AS_HEAP_IVPTR));
// Read the ivar from the extended table
- let ivar_opnd = Opnd::mem(64, tbl_opnd, (SIZEOF_VALUE * ivar_index.unwrap()) as i32);
+ let ivar_opnd = Opnd::mem(64, tbl_opnd, (SIZEOF_VALUE * ivar_index) as i32);
+
+ // Check that the ivar is not Qundef
+ asm.cmp(ivar_opnd, Qundef.into());
+ let out_val = asm.csel_ne(ivar_opnd, Qnil.into());
+ // Push the ivar on the stack
let out_opnd = ctx.stack_push(Type::Unknown);
- asm.mov(out_opnd, ivar_opnd);
+ asm.mov(out_opnd, out_val);
}
// Jump to next instruction. This allows guard chains to share the same successor.
@@ -2130,12 +2136,25 @@ fn gen_getinstancevariable(
let ivar_name = jit_get_arg(jit, 0).as_u64();
let comptime_val = jit_peek_at_self(jit);
+ let comptime_val_klass = comptime_val.class_of();
// Generate a side exit
let side_exit = get_side_exit(jit, ocb, ctx);
// Guard that the receiver has the same class as the one from compile time.
let self_asm_opnd = Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SELF);
+ jit_guard_known_klass(
+ jit,
+ ctx,
+ asm,
+ ocb,
+ comptime_val_klass,
+ self_asm_opnd,
+ SelfOpnd,
+ comptime_val,
+ GET_IVAR_MAX_DEPTH,
+ side_exit,
+ );
gen_get_ivar(
jit,
diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs
index 65f398f075..25149ab730 100644
--- a/yjit/src/cruby.rs
+++ b/yjit/src/cruby.rs
@@ -120,7 +120,7 @@ extern "C" {
obj: VALUE,
v: VALUE,
) -> bool;
- pub fn rb_vm_set_ivar_id(obj: VALUE, idx: u32, val: VALUE) -> VALUE;
+ pub fn rb_vm_set_ivar_idx(obj: VALUE, idx: u32, val: VALUE) -> VALUE;
pub fn rb_vm_setinstancevariable(iseq: IseqPtr, obj: VALUE, id: ID, val: VALUE, ic: IVC);
pub fn rb_aliased_callable_method_entry(
me: *const rb_callable_method_entry_t,
@@ -354,26 +354,18 @@ impl VALUE {
/// Read the flags bits from the RBasic object, then return a Ruby type enum (e.g. RUBY_T_ARRAY)
pub fn builtin_type(self) -> ruby_value_type {
- (self.builtin_flags() & (RUBY_T_MASK as usize)) as ruby_value_type
- }
-
- pub fn builtin_flags(self) -> usize {
assert!(!self.special_const_p());
let VALUE(cval) = self;
let rbasic_ptr = cval as *const RBasic;
let flags_bits: usize = unsafe { (*rbasic_ptr).flags }.as_usize();
- return flags_bits;
+ (flags_bits & (RUBY_T_MASK as usize)) as ruby_value_type
}
pub fn class_of(self) -> VALUE {
unsafe { CLASS_OF(self) }
}
- pub fn shape_of(self) -> u32 {
- unsafe { rb_shape_get_shape_id(self) }
- }
-
pub fn as_isize(self) -> isize {
let VALUE(is) = self;
is as isize
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index 84a778cbc5..f58bf1ca05 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -269,30 +269,6 @@ extern "C" {
extern "C" {
pub fn rb_reg_new_ary(ary: VALUE, options: ::std::os::raw::c_int) -> VALUE;
}
-pub type attr_index_t = u32;
-pub type shape_id_t = u32;
-#[repr(C)]
-pub struct rb_shape {
- pub flags: VALUE,
- pub parent: *mut rb_shape,
- pub edges: *mut rb_id_table,
- pub edge_name: ID,
- pub iv_count: attr_index_t,
- pub type_: u8,
-}
-pub type rb_shape_t = rb_shape;
-extern "C" {
- pub fn rb_shape_get_shape_by_id(shape_id: shape_id_t) -> *mut rb_shape_t;
-}
-extern "C" {
- pub fn rb_shape_get_shape_id(obj: VALUE) -> shape_id_t;
-}
-extern "C" {
- pub fn rb_shape_get_iv_index(shape: *mut rb_shape_t, id: ID, value: *mut attr_index_t) -> bool;
-}
-extern "C" {
- pub fn rb_shape_flags_mask() -> VALUE;
-}
pub const idDot2: ruby_method_ids = 128;
pub const idDot3: ruby_method_ids = 129;
pub const idUPlus: ruby_method_ids = 132;
@@ -537,7 +513,6 @@ pub const imemo_parser_strterm: imemo_type = 10;
pub const imemo_callinfo: imemo_type = 11;
pub const imemo_callcache: imemo_type = 12;
pub const imemo_constcache: imemo_type = 13;
-pub const imemo_shape: imemo_type = 14;
pub type imemo_type = u32;
pub const METHOD_VISI_UNDEF: rb_method_visibility_t = 0;
pub const METHOD_VISI_PUBLIC: rb_method_visibility_t = 1;
@@ -597,11 +572,6 @@ pub const OPTIMIZED_METHOD_TYPE_STRUCT_AREF: method_optimized_type = 3;
pub const OPTIMIZED_METHOD_TYPE_STRUCT_ASET: method_optimized_type = 4;
pub const OPTIMIZED_METHOD_TYPE__MAX: method_optimized_type = 5;
pub type method_optimized_type = u32;
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct rb_id_table {
- _unused: [u8; 0],
-}
extern "C" {
pub fn rb_method_entry_at(obj: VALUE, id: ID) -> *const rb_method_entry_t;
}
@@ -630,10 +600,9 @@ pub struct iseq_inline_constant_cache {
pub segments: *const ID,
}
#[repr(C)]
+#[derive(Debug, Copy, Clone)]
pub struct iseq_inline_iv_cache_entry {
- pub source_shape_id: shape_id_t,
- pub dest_shape_id: shape_id_t,
- pub attr_index: attr_index_t,
+ pub entry: *mut rb_iv_index_tbl_entry,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
@@ -729,6 +698,12 @@ extern "C" {
) -> *const rb_callable_method_entry_t;
}
#[repr(C)]
+pub struct rb_iv_index_tbl_entry {
+ pub index: u32,
+ pub class_serial: rb_serial_t,
+ pub class_value: VALUE,
+}
+#[repr(C)]
pub struct rb_cvar_class_tbl_entry {
pub index: u32,
pub global_cvar_state: rb_serial_t,