summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--array.c2
-rw-r--r--class.c10
-rw-r--r--depend1
-rw-r--r--gc.c24
-rw-r--r--imemo.c18
-rw-r--r--internal/gc.h2
-rw-r--r--ractor.c2
-rw-r--r--shape.c78
-rw-r--r--shape.h54
-rw-r--r--string.c2
-rw-r--r--test/ruby/test_shapes.rb31
-rw-r--r--variable.c22
-rw-r--r--vm_insnhelper.c7
-rw-r--r--zjit/src/cruby_bindings.inc.rs7
14 files changed, 44 insertions, 216 deletions
diff --git a/array.c b/array.c
index 7f06e3c9c7..08d8d17c90 100644
--- a/array.c
+++ b/array.c
@@ -30,7 +30,6 @@
#include "ruby/thread.h"
#include "ruby/util.h"
#include "ruby/ractor.h"
-#include "shape.h"
#include "vm_core.h"
#include "builtin.h"
@@ -910,7 +909,6 @@ init_fake_ary_flags(void)
struct RArray fake_ary = {0};
fake_ary.basic.flags = T_ARRAY;
VALUE ary = (VALUE)&fake_ary;
- RBASIC_SET_SHAPE_ID(ary, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
rb_ary_freeze(ary);
return fake_ary.basic.flags;
}
diff --git a/class.c b/class.c
index 02078cc9bc..69194ccab2 100644
--- a/class.c
+++ b/class.c
@@ -585,15 +585,7 @@ class_alloc0(enum ruby_value_type type, VALUE klass, bool boxable)
VALUE flags = type | FL_SHAREABLE;
if (boxable) flags |= RCLASS_BOXABLE;
- shape_id_t shape_id = ROOT_SHAPE_ID;
- if (boxable) {
- shape_id |= SHAPE_ID_LAYOUT_OTHER;
- }
- else {
- shape_id |= SHAPE_ID_LAYOUT_RCLASS;
- }
-
- struct RClass *obj = (struct RClass *)rb_newobj(GET_EC(), klass, flags, shape_id, true, alloc_size);
+ NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size);
obj->object_id = 0;
diff --git a/depend b/depend
index a2e8312298..e61b685670 100644
--- a/depend
+++ b/depend
@@ -80,7 +80,6 @@ array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
array.$(OBJEXT): $(top_srcdir)/internal/serial.h
array.$(OBJEXT): $(top_srcdir)/internal/set_table.h
array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-array.$(OBJEXT): $(top_srcdir)/internal/struct.h
array.$(OBJEXT): $(top_srcdir)/internal/variable.h
array.$(OBJEXT): $(top_srcdir)/internal/vm.h
array.$(OBJEXT): $(top_srcdir)/internal/warnings.h
diff --git a/gc.c b/gc.c
index 6357577e63..9eb7232940 100644
--- a/gc.c
+++ b/gc.c
@@ -1056,15 +1056,7 @@ rb_newobj(rb_execution_context_t *ec, VALUE klass, VALUE flags, shape_id_t shape
VALUE
rb_ec_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags, size_t size)
{
- VALUE type = flags & T_MASK;
- RUBY_ASSERT(type != T_OBJECT);
- RUBY_ASSERT(type != T_DATA);
- RUBY_ASSERT(type != T_CLASS);
- RUBY_ASSERT(type != T_MODULE);
- RUBY_ASSERT(type != T_ICLASS);
- (void)type;
-
- return rb_newobj(ec, klass, flags, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER, true, size);
+ return rb_newobj(ec, klass, flags, ROOT_SHAPE_ID, true, size);
}
VALUE
@@ -1076,13 +1068,13 @@ rb_newobj_of_with_shape(VALUE klass, VALUE flags, shape_id_t shape_id, size_t si
VALUE
rb_newobj_of(VALUE klass, VALUE flags, size_t size)
{
- return rb_newobj(GET_EC(), klass, flags, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER, true, size);
+ return rb_newobj(GET_EC(), klass, flags, ROOT_SHAPE_ID, true, size);
}
static
VALUE class_allocate_complex_instance(VALUE klass, uint32_t capacity)
{
- shape_id_t initial_shape_id = rb_shape_id_with_robject_layout(rb_shape_root(rb_gc_heap_id_for_size(sizeof(struct RObject))));
+ shape_id_t initial_shape_id = rb_shape_root(rb_gc_heap_id_for_size(sizeof(struct RObject)));
VALUE obj = rb_newobj_of_with_shape(klass, T_OBJECT, initial_shape_id, sizeof(struct RObject));
rb_obj_init_complex(obj, rb_st_init_numtable_with_size(capacity));
return obj;
@@ -1107,7 +1099,7 @@ rb_class_allocate_instance(VALUE klass)
// There might be a NEWOBJ tracepoint callback, and it may set fields.
// So the shape must be passed to `NEWOBJ_OF`.
- obj = rb_newobj_of_with_shape(klass, T_OBJECT, rb_shape_id_with_robject_layout(rb_shape_root(rb_gc_heap_id_for_size(size))), size);
+ obj = rb_newobj_of_with_shape(klass, T_OBJECT, rb_shape_root(rb_gc_heap_id_for_size(size)), size);
#if RUBY_DEBUG
VALUE *ptr = ROBJECT_FIELDS(obj);
@@ -1157,7 +1149,7 @@ typed_data_alloc(VALUE klass, VALUE typed_flag, void *datap, const rb_data_type_
RBIMPL_NONNULL_ARG(type);
if (klass) rb_data_object_check(klass);
bool wb_protected = (type->flags & RUBY_FL_WB_PROTECTED) || !type->function.dmark;
- VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_RDATA, wb_protected, size);
+ VALUE obj = rb_newobj(GET_EC(), klass, T_DATA, ROOT_SHAPE_ID, wb_protected, size);
rb_gc_register_pinning_obj(obj);
@@ -4197,11 +4189,7 @@ vm_weak_table_gen_fields_foreach(st_data_t key, st_data_t value, st_data_t data)
break;
case ST_DELETE:
- // When we're removing an object from the weak ref table, we need to
- // set the shape on it so that the GC finalizer won't try to remove
- // it again. A "root shape" indicates to the GC that this object
- // has no fields on it, hence it won't be in the gen fields table.
- RBASIC_SET_SHAPE_ID((VALUE)key, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
+ RBASIC_SET_SHAPE_ID((VALUE)key, ROOT_SHAPE_ID);
return ST_DELETE;
case ST_REPLACE: {
diff --git a/imemo.c b/imemo.c
index 796e078c89..3448a8dcd3 100644
--- a/imemo.c
+++ b/imemo.c
@@ -141,11 +141,7 @@ rb_imemo_fields_new(VALUE owner, shape_id_t shape_id, bool shareable)
size_t embedded_size = offsetof(struct rb_fields, as.embed) + capa * sizeof(VALUE);
RUBY_ASSERT(rb_gc_size_allocatable_p(embedded_size));
VALUE fields = rb_imemo_new(imemo_fields, owner, embedded_size, shareable);
- // imemo fields objects should always have "RObject" layout. The
- // layout in the shape describes the layout of the thing on which it is set.
- // Imemo fields have the same layout as robject, therefore the layout
- // should reflect that fact.
- RBASIC_SET_SHAPE_ID(fields, rb_shape_id_with_robject_layout(shape_id));
+ RBASIC_SET_SHAPE_ID(fields, shape_id);
RUBY_ASSERT(IMEMO_TYPE_P(fields, imemo_fields));
return fields;
}
@@ -156,11 +152,7 @@ rb_imemo_fields_new_complex(VALUE owner, shape_id_t shape_id, size_t capa, bool
VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
IMEMO_OBJ_FIELDS(fields)->as.complex.table = st_init_numtable_with_size(capa);
FL_SET_RAW(fields, OBJ_FIELD_HEAP);
- // imemo fields objects should always have "RObject" layout. The
- // layout in the shape describes the layout of the thing on which it is set.
- // Imemo fields have the same layout as robject, therefore the layout
- // should reflect that fact.
- RBASIC_SET_SHAPE_ID(fields, rb_shape_id_with_robject_layout(shape_id));
+ RBASIC_SET_SHAPE_ID(fields, shape_id);
return fields;
}
@@ -185,11 +177,7 @@ rb_imemo_fields_new_complex_tbl(VALUE owner, shape_id_t shape_id, st_table *tbl,
VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
IMEMO_OBJ_FIELDS(fields)->as.complex.table = tbl;
FL_SET_RAW(fields, OBJ_FIELD_HEAP);
- // imemo fields objects should always have "RObject" layout. The
- // layout in the shape describes the layout of the thing on which it is set.
- // Imemo fields have the same layout as robject, therefore the layout
- // should reflect that fact.
- RBASIC_SET_SHAPE_ID(fields, rb_shape_id_with_robject_layout(shape_id));
+ RBASIC_SET_SHAPE_ID(fields, shape_id);
st_foreach(tbl, imemo_fields_trigger_wb_i, (st_data_t)fields);
return fields;
}
diff --git a/internal/gc.h b/internal/gc.h
index b78808370c..41675810c7 100644
--- a/internal/gc.h
+++ b/internal/gc.h
@@ -124,7 +124,7 @@ struct rb_objspace; /* in vm_core.h */
T *(var) = (T *)rb_ec_newobj_of((ec), (c), (f), s)
#define NEWOBJ_OF(var, T, c, f, s) EC_NEWOBJ_OF(var, T, c, f, s, GET_EC())
#define UNPROTECTED_NEWOBJ_OF(var, T, c, f, s) \
- T *(var) = (T *)rb_newobj((GET_EC()), (c), (f), ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER, false, s)
+ T *(var) = (T *)rb_newobj((GET_EC()), (c), (f), 0 /* ROOT_SHAPE_ID */, false, s)
#ifndef RB_GC_OBJECT_METADATA_ENTRY_DEFINED
# define RB_GC_OBJECT_METADATA_ENTRY_DEFINED
diff --git a/ractor.c b/ractor.c
index f94c06cc73..d611ca97c2 100644
--- a/ractor.c
+++ b/ractor.c
@@ -2015,7 +2015,7 @@ move_enter(VALUE obj, struct obj_traverse_replace_data *data)
else {
VALUE type = RB_BUILTIN_TYPE(obj);
size_t slot_size = rb_gc_obj_slot_size(obj);
- VALUE moved = rb_newobj(GET_EC(), 0, type, RBASIC_SHAPE_ID(obj), wb_protected_types[type], slot_size);
+ VALUE moved = rb_newobj(GET_EC(), 0, type, 0, wb_protected_types[type], slot_size);
MEMZERO(((struct RBasic *)moved) + 1, char, slot_size - sizeof(struct RBasic));
data->replacement = (VALUE)moved;
return traverse_cont;
diff --git a/shape.c b/shape.c
index 7a02b23073..24f1394f6c 100644
--- a/shape.c
+++ b/shape.c
@@ -409,14 +409,10 @@ rb_obj_shape_id(VALUE obj)
if (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) {
VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
- shape_id_t base = ROOT_SHAPE_ID;
if (fields_obj) {
- // Remove the layout from the fields object. We want to
- // combine the shape of the fields object with the layout of the
- // class / module object.
- base = RBASIC_SHAPE_ID(fields_obj) & ~SHAPE_ID_LAYOUT_MASK;
+ return RBASIC_SHAPE_ID(fields_obj);
}
- return rb_shape_layout(RBASIC_SHAPE_ID(obj)) | base;
+ return ROOT_SHAPE_ID;
}
return RBASIC_SHAPE_ID(obj);
}
@@ -701,7 +697,7 @@ rb_shape_transition_object_id(shape_id_t original_shape_id)
bool dont_care;
rb_shape_t *shape = get_next_shape_internal(RSHAPE(original_shape_id), id_object_id, SHAPE_OBJ_ID, &dont_care, true);
if (!shape) {
- return rb_shape_layout(original_shape_id) | ROOT_COMPLEX_WITH_OBJ_ID | RSHAPE_FLAGS(original_shape_id);
+ return ROOT_COMPLEX_WITH_OBJ_ID | RSHAPE_FLAGS(original_shape_id);
}
RUBY_ASSERT(shape);
@@ -1229,55 +1225,17 @@ rb_shape_foreach_field(shape_id_t initial_shape_id, rb_shape_foreach_transition_
}
#if RUBY_DEBUG
-/*
- * Get the layout of this object. The "layout" indicates what strategy
- * we should use for fetching instance variables from `obj`. It's based
- * on the C struct layout for each particular object.
- *
- * TODO: make Struct have a similar layout to RDATA
- */
-static shape_id_t
-rb_shape_expected_layout(VALUE obj)
-{
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- return SHAPE_ID_LAYOUT_ROBJECT;
- case T_CLASS:
- case T_MODULE:
- if (FL_TEST_RAW(obj, RCLASS_BOXABLE)) {
- return SHAPE_ID_LAYOUT_OTHER;
- }
- return SHAPE_ID_LAYOUT_RCLASS;
- case T_DATA:
- return SHAPE_ID_LAYOUT_RDATA;
- case T_IMEMO:
- if (IMEMO_TYPE_P(obj, imemo_fields)) {
- return SHAPE_ID_LAYOUT_ROBJECT;
- }
- return SHAPE_ID_LAYOUT_OTHER;
- default:
- return SHAPE_ID_LAYOUT_OTHER;
- }
-}
-
bool
rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
{
- if (shape_id == INVALID_SHAPE_ID) {
- rb_bug("Can't set INVALID_SHAPE_ID on an object");
- }
-
- shape_id_t actual_layout = rb_shape_layout(rb_obj_shape_id(obj));
- shape_id_t expected_layout = rb_shape_expected_layout(obj);
- if (actual_layout != expected_layout) {
- rb_bug("shape_id layout mismatch: expected=%x actual=%x shape_id=%u obj=%s",
- expected_layout, actual_layout, shape_id, rb_obj_info(obj));
- }
-
if (shape_id == ROOT_SHAPE_ID) {
return true;
}
+ if (shape_id == INVALID_SHAPE_ID) {
+ rb_bug("Can't set INVALID_SHAPE_ID on an object");
+ }
+
rb_shape_t *shape = RSHAPE(shape_id);
bool has_object_id = false;
@@ -1291,11 +1249,13 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
if (rb_shape_has_object_id(shape_id)) {
if (!has_object_id) {
+ rb_p(obj);
rb_bug("shape_id claim having obj_id but doesn't shape_id=%u, obj=%s", shape_id, rb_obj_info(obj));
}
}
else {
if (has_object_id) {
+ rb_p(obj);
rb_bug("shape_id claim not having obj_id but it does shape_id=%u, obj=%s", shape_id, rb_obj_info(obj));
}
}
@@ -1370,25 +1330,6 @@ shape_has_object_id_p(VALUE self)
}
static VALUE
-shape_layout(VALUE self)
-{
- shape_id_t shape_id = NUM2UINT(rb_struct_getmember(self, rb_intern("id")));
-
- switch (rb_shape_layout(shape_id)) {
- case SHAPE_ID_LAYOUT_ROBJECT:
- return ID2SYM(rb_intern("robject"));
- case SHAPE_ID_LAYOUT_RCLASS:
- return ID2SYM(rb_intern("rclass"));
- case SHAPE_ID_LAYOUT_RDATA:
- return ID2SYM(rb_intern("rdata"));
- case SHAPE_ID_LAYOUT_OTHER:
- return ID2SYM(rb_intern("other"));
- default:
- rb_bug("unknown shape layout: %u", rb_shape_layout(shape_id));
- }
-}
-
-static VALUE
parse_key(ID key)
{
if (is_instance_id(key)) {
@@ -1687,7 +1628,6 @@ Init_shape(void)
rb_define_method(rb_cShape, "complex?", shape_complex, 0);
rb_define_method(rb_cShape, "shape_frozen?", shape_frozen, 0);
rb_define_method(rb_cShape, "has_object_id?", shape_has_object_id_p, 0);
- rb_define_method(rb_cShape, "layout", shape_layout, 0);
rb_define_const(rb_cShape, "SHAPE_ROOT", INT2NUM(SHAPE_ROOT));
rb_define_const(rb_cShape, "SHAPE_IVAR", INT2NUM(SHAPE_IVAR));
diff --git a/shape.h b/shape.h
index a319449988..61fadca5ba 100644
--- a/shape.h
+++ b/shape.h
@@ -27,14 +27,12 @@ STATIC_ASSERT(shape_id_num_bits, SHAPE_ID_NUM_BITS == sizeof(shape_id_t) * CHAR_
// 19-22 SHAPE_ID_HEAP_INDEX_MASK
// index in rb_shape_tree.capacities. Allow to access slot size.
// Currently always 0 except for T_OBJECT.
-// 23 SHAPE_ID_FL_COMPLEX
-// The object is backed by a `st_table`.
-// 24 SHAPE_ID_FL_FROZEN
+// 23 SHAPE_ID_FL_FROZEN
// Whether the object is frozen or not.
-// 25 SHAPE_ID_FL_HAS_OBJECT_ID
+// 24 SHAPE_ID_FL_HAS_OBJECT_ID
// Whether the object has an `SHAPE_OBJ_ID` transition.
-// 26-27 SHAPE_ID_LAYOUT_MASK
-// The object's physical field layout.
+// 25 SHAPE_ID_FL_COMPLEX
+// The object is backed by a `st_table`.
enum shape_id_fl_type {
#define RBIMPL_SHAPE_ID_FL(n) (1<<(SHAPE_ID_FL_USHIFT+n))
@@ -45,26 +43,8 @@ enum shape_id_fl_type {
SHAPE_ID_FL_FROZEN = RBIMPL_SHAPE_ID_FL(1),
SHAPE_ID_FL_HAS_OBJECT_ID = RBIMPL_SHAPE_ID_FL(2),
- // Means IVs are found at an offset from the object's addr, or in a
- // malloc allocated side table
- SHAPE_ID_LAYOUT_ROBJECT = 0,
-
- // Means this object is a class/module that is NOT RCLASS_BOXABLE, and IV's
- // are found in the fields_obj found on the rclass struct
- SHAPE_ID_LAYOUT_RCLASS = RBIMPL_SHAPE_ID_FL(3),
-
- // Means this object is an RData or RTypedData and IVs are found in the
- // fields_obj found on the RData/RTypedData struct
- SHAPE_ID_LAYOUT_RDATA = RBIMPL_SHAPE_ID_FL(4),
-
- // Means this is a complicated object: boxable classes, structs, objects
- // that store IVs on the geniv table
- SHAPE_ID_LAYOUT_OTHER = SHAPE_ID_LAYOUT_RCLASS | SHAPE_ID_LAYOUT_RDATA,
-
- SHAPE_ID_LAYOUT_MASK = SHAPE_ID_LAYOUT_OTHER,
-
SHAPE_ID_FL_NON_CANONICAL_MASK = SHAPE_ID_FL_FROZEN | SHAPE_ID_FL_HAS_OBJECT_ID,
- SHAPE_ID_FLAGS_MASK = SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_NON_CANONICAL_MASK | SHAPE_ID_FL_COMPLEX | SHAPE_ID_LAYOUT_MASK,
+ SHAPE_ID_FLAGS_MASK = SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_NON_CANONICAL_MASK | SHAPE_ID_FL_COMPLEX,
#undef RBIMPL_SHAPE_ID_FL
};
@@ -75,13 +55,12 @@ enum shape_id_mask {
SHAPE_ID_HAS_IVAR_MASK = SHAPE_ID_FL_COMPLEX | (SHAPE_ID_OFFSET_MASK - 1),
};
-// The interpreter doesn't care about frozen status, slot size, or object id, and
-// has its own checks for physical field layout when reading ivars.
+// The interpreter doesn't care about frozen status, slot size or object id when reading ivars.
// So we normalize shape_id by clearing these bits to improve cache hits.
// JITs however might care about some of it.
-#define SHAPE_ID_READ_ONLY_MASK (~(SHAPE_ID_FL_FROZEN | SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_HAS_OBJECT_ID | SHAPE_ID_LAYOUT_MASK))
+#define SHAPE_ID_READ_ONLY_MASK (~(SHAPE_ID_FL_FROZEN | SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_HAS_OBJECT_ID))
// For write it's the same idea, but here we do care about frozen status.
-#define SHAPE_ID_WRITE_MASK (~(SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_HAS_OBJECT_ID | SHAPE_ID_LAYOUT_MASK))
+#define SHAPE_ID_WRITE_MASK (~(SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_HAS_OBJECT_ID))
typedef uint32_t redblack_id_t;
@@ -174,18 +153,11 @@ RBASIC_SET_SHAPE_ID_NO_CHECKS(VALUE obj, shape_id_t shape_id)
#endif
}
-static inline shape_id_t
-rb_shape_layout(shape_id_t shape_id)
-{
- return shape_id & SHAPE_ID_LAYOUT_MASK;
-}
-
static inline void
RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
{
RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj));
RUBY_ASSERT(!RB_TYPE_P(obj, T_IMEMO) || IMEMO_TYPE_P(obj, imemo_fields));
- RUBY_ASSERT(!IMEMO_TYPE_P(obj, imemo_fields) || rb_shape_layout(shape_id) == SHAPE_ID_LAYOUT_ROBJECT);
RBASIC_SET_SHAPE_ID_NO_CHECKS(obj, shape_id);
@@ -260,12 +232,6 @@ rb_shape_canonical_p(shape_id_t shape_id)
return !(shape_id & SHAPE_ID_FL_NON_CANONICAL_MASK);
}
-static inline shape_id_t
-rb_shape_id_with_robject_layout(shape_id_t shape_id)
-{
- return (shape_id & ~SHAPE_ID_LAYOUT_MASK) | SHAPE_ID_LAYOUT_ROBJECT;
-}
-
static inline uint8_t
rb_shape_heap_index(shape_id_t shape_id)
{
@@ -484,10 +450,10 @@ rb_shape_transition_frozen(shape_id_t shape_id)
static inline shape_id_t
rb_shape_transition_complex(shape_id_t shape_id)
{
- shape_id_t next_shape_id = rb_shape_layout(shape_id) | ROOT_COMPLEX_SHAPE_ID;
+ shape_id_t next_shape_id = ROOT_COMPLEX_SHAPE_ID;
if (rb_shape_has_object_id(shape_id)) {
- next_shape_id = rb_shape_layout(shape_id) | ROOT_COMPLEX_WITH_OBJ_ID;
+ next_shape_id = ROOT_COMPLEX_WITH_OBJ_ID;
}
uint8_t heap_index = rb_shape_heap_index(shape_id);
diff --git a/string.c b/string.c
index 61d4f16679..6865b0d8e6 100644
--- a/string.c
+++ b/string.c
@@ -630,7 +630,7 @@ static VALUE
setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx)
{
fake_str->basic.flags = T_STRING|RSTRING_NOEMBED|STR_NOFREE|STR_FAKESTR;
- RBASIC_SET_SHAPE_ID((VALUE)fake_str, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
+ RBASIC_SET_SHAPE_ID((VALUE)fake_str, ROOT_SHAPE_ID);
if (!name) {
RUBY_ASSERT_ALWAYS(len == 0);
diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb
index bace69658a..ef5dbd9fb1 100644
--- a/test/ruby/test_shapes.rb
+++ b/test/ruby/test_shapes.rb
@@ -1067,37 +1067,6 @@ class TestShapes < Test::Unit::TestCase
assert_nil shape.parent
end
- def test_shape_layout
- assert_equal :robject, RubyVM::Shape.of(TestObject.new).layout
-
- if ENV["RUBY_BOX"]
- assert_equal :other, RubyVM::Shape.of(Kernel).layout
- assert_equal :other, RubyVM::Shape.of(String).layout
- else
- assert_equal :rclass, RubyVM::Shape.of(Kernel).layout
- assert_equal :rclass, RubyVM::Shape.of(String).layout
- end
-
- assert_equal :rclass, RubyVM::Shape.of(Class.new).layout
- assert_equal :rclass, RubyVM::Shape.of(Module.new).layout
-
- klass = Class.new
- assert_equal :rclass, RubyVM::Shape.of(klass).layout
- klass.instance_variable_set(:@a, 123)
- assert_equal :rclass, RubyVM::Shape.of(klass).layout
-
- assert_equal :rdata, RubyVM::Shape.of(Thread.current).layout
- assert_equal :rdata, RubyVM::Shape.of(lambda {}).layout
-
- assert_equal :other, RubyVM::Shape.of(Struct.new(:x).new(1)).layout
- assert_equal :other, RubyVM::Shape.of([]).layout
- assert_equal :other, RubyVM::Shape.of("hello").layout
- assert_equal :other, RubyVM::Shape.of(/foo/).layout
- assert_equal :other, RubyVM::Shape.of(2..3).layout
- assert_equal :other, RubyVM::Shape.of(2**67).layout
- assert_equal :other, RubyVM::Shape.of(:"aaroniscool#{123}").layout
- end
-
def test_str_has_root_shape
assert_shape_equal(RubyVM::Shape.root_shape, RubyVM::Shape.of(""))
end
diff --git a/variable.c b/variable.c
index 687fa03631..857d870413 100644
--- a/variable.c
+++ b/variable.c
@@ -1343,7 +1343,7 @@ rb_free_generic_ivar(VALUE obj)
}
}
}
- RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | ROOT_SHAPE_ID);
+ RBASIC_SET_SHAPE_ID(obj, ROOT_SHAPE_ID);
}
}
@@ -1395,7 +1395,7 @@ rb_obj_set_fields(VALUE obj, VALUE fields_obj, ID field_name, VALUE original_fie
}
}
- RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | RBASIC_SHAPE_ID(fields_obj));
+ RBASIC_SET_SHAPE_ID(obj, RBASIC_SHAPE_ID(fields_obj));
}
void
@@ -1710,7 +1710,6 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
size_t trailing_fields = new_fields_count - removed_index;
MEMMOVE(&fields[removed_index], &fields[removed_index + 1], VALUE, trailing_fields);
- RUBY_ASSERT(rb_shape_layout(next_shape_id) == SHAPE_ID_LAYOUT_ROBJECT);
RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
if (FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP)) {
@@ -1733,7 +1732,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
}
}
- RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | next_shape_id);
+ RBASIC_SET_SHAPE_ID(obj, next_shape_id);
if (fields_obj != original_fields_obj) {
switch (type) {
case T_OBJECT:
@@ -1844,7 +1843,7 @@ imemo_fields_set(VALUE owner, VALUE fields_obj, shape_id_t target_shape_id, ID f
RUBY_ASSERT(field_name);
st_insert(table, (st_data_t)field_name, (st_data_t)val);
RB_OBJ_WRITTEN(fields_obj, Qundef, val);
- RBASIC_SET_SHAPE_ID(fields_obj, rb_shape_id_with_robject_layout(target_shape_id));
+ RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id);
}
else {
attr_index_t index = RSHAPE_INDEX(target_shape_id);
@@ -1856,7 +1855,7 @@ imemo_fields_set(VALUE owner, VALUE fields_obj, shape_id_t target_shape_id, ID f
RB_OBJ_WRITE(fields_obj, &table[index], val);
if (index >= RSHAPE_LEN(current_shape_id)) {
- RBASIC_SET_SHAPE_ID(fields_obj, rb_shape_id_with_robject_layout(target_shape_id));
+ RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id);
}
}
@@ -2011,12 +2010,11 @@ rb_obj_freeze_inline(VALUE x)
RB_FL_UNSET_RAW(x, FL_USER2 | FL_USER3); // STR_CHILLED
}
- // rb_obj_freeze_inline(String)
shape_id_t shape_id = rb_obj_shape_transition_frozen(x);
switch (BUILTIN_TYPE(x)) {
case T_CLASS:
case T_MODULE:
- rb_obj_freeze_inline(RCLASS_WRITABLE_ENSURE_FIELDS_OBJ(x));
+ RBASIC_SET_SHAPE_ID(RCLASS_WRITABLE_ENSURE_FIELDS_OBJ(x), shape_id);
// FIXME: How to do multi-shape?
RBASIC_SET_SHAPE_ID(x, shape_id);
break;
@@ -2305,7 +2303,7 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj)
}
if (!RSHAPE_LEN(dest_shape_id)) {
- RBASIC_SET_SHAPE_ID(dest, rb_shape_layout(RBASIC_SHAPE_ID(dest)) | dest_shape_id);
+ RBASIC_SET_SHAPE_ID(dest, dest_shape_id);
return;
}
@@ -4638,7 +4636,6 @@ class_fields_ivar_set(VALUE klass, VALUE fields_obj, ID id, VALUE val, bool conc
}
if (new_ivar) {
- RUBY_ASSERT(rb_shape_layout(next_shape_id) == SHAPE_ID_LAYOUT_ROBJECT);
RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
}
}
@@ -4661,7 +4658,6 @@ complex:
RB_OBJ_WRITTEN(fields_obj, Qundef, val);
if (fields_obj != original_fields_obj) {
- RUBY_ASSERT(rb_shape_layout(next_shape_id) == SHAPE_ID_LAYOUT_ROBJECT);
RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
}
}
@@ -4688,7 +4684,7 @@ class_ivar_set(VALUE obj, ID id, VALUE val, bool *new_ivar)
// TODO: What should we set as the T_CLASS shape_id?
// In most case we can replicate the single `fields_obj` shape
// but in namespaced case? Perhaps INVALID_SHAPE_ID?
- RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | RBASIC_SHAPE_ID(new_fields_obj));
+ RBASIC_SET_SHAPE_ID(obj, RBASIC_SHAPE_ID(new_fields_obj));
return index;
}
@@ -4713,7 +4709,7 @@ rb_fields_tbl_copy(VALUE dst, VALUE src)
VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(src);
if (fields_obj) {
RCLASS_WRITABLE_SET_FIELDS_OBJ(dst, rb_imemo_fields_clone(fields_obj));
- RBASIC_SET_SHAPE_ID(dst, rb_shape_layout(RBASIC_SHAPE_ID(dst)) | RBASIC_SHAPE_ID(src));
+ RBASIC_SET_SHAPE_ID(dst, RBASIC_SHAPE_ID(src));
}
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index f515662bf0..ac0d81092d 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1412,8 +1412,7 @@ vm_setivar_class(VALUE obj, VALUE val, rb_setivar_cache cache)
RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val);
if (shape_id != dest_shape_id) {
- // The dest_shape_id comes from the fields_obj
- RBASIC_SET_SHAPE_ID(obj, SHAPE_ID_LAYOUT_RCLASS | (dest_shape_id & ~SHAPE_ID_LAYOUT_MASK));
+ RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
}
@@ -1438,9 +1437,7 @@ vm_setivar_default(VALUE obj, ID id, VALUE val, rb_setivar_cache cache)
if (shape_id != dest_shape_id) {
RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
- // The dest_shape_id comes from the owner, but fields_obj must always
- // have layout RObject, so give the fields_object the right layout.
- RBASIC_SET_SHAPE_ID(fields_obj, rb_shape_id_with_robject_layout(dest_shape_id));
+ RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id);
}
RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs
index 08c502b0d8..bd832acc96 100644
--- a/zjit/src/cruby_bindings.inc.rs
+++ b/zjit/src/cruby_bindings.inc.rs
@@ -1491,13 +1491,8 @@ pub const SHAPE_ID_HEAP_INDEX_MASK: shape_id_fl_type = 7864320;
pub const SHAPE_ID_FL_COMPLEX: shape_id_fl_type = 8388608;
pub const SHAPE_ID_FL_FROZEN: shape_id_fl_type = 16777216;
pub const SHAPE_ID_FL_HAS_OBJECT_ID: shape_id_fl_type = 33554432;
-pub const SHAPE_ID_LAYOUT_ROBJECT: shape_id_fl_type = 0;
-pub const SHAPE_ID_LAYOUT_RCLASS: shape_id_fl_type = 67108864;
-pub const SHAPE_ID_LAYOUT_RDATA: shape_id_fl_type = 134217728;
-pub const SHAPE_ID_LAYOUT_OTHER: shape_id_fl_type = 201326592;
-pub const SHAPE_ID_LAYOUT_MASK: shape_id_fl_type = 201326592;
pub const SHAPE_ID_FL_NON_CANONICAL_MASK: shape_id_fl_type = 50331648;
-pub const SHAPE_ID_FLAGS_MASK: shape_id_fl_type = 267911168;
+pub const SHAPE_ID_FLAGS_MASK: shape_id_fl_type = 66584576;
pub type shape_id_fl_type = u32;
pub const CONST_DEPRECATED: rb_const_flag_t = 256;
pub const CONST_VISIBILITY_MASK: rb_const_flag_t = 255;