mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Get rid of ROBJECT_HEAP flag
This flag is now entirely redundant with the shape_id layout bits.
This commit is contained in:
1 parent
e9444aa0da
commit
86951165b8
18 files changed
+171
-184
Notes:
git
2026-07-15 13:43:58 +00:00
No files matched your search
@@ -52,7 +52,6 @@ const union {
|
||||
enum ruby_econv_flag_type econv_flag_types;
|
||||
rb_econv_result_t econv_result;
|
||||
enum ruby_preserved_encindex encoding_index;
|
||||
enum ruby_robject_flags robject_flags;
|
||||
enum ruby_rmodule_flags rmodule_flags;
|
||||
enum ruby_rstring_flags rstring_flags;
|
||||
enum ruby_rarray_flags rarray_flags;
|
||||
|
||||
@@ -592,7 +592,7 @@ dump_object(VALUE obj, struct dump_config *dc)
|
||||
break;
|
||||
|
||||
case T_OBJECT:
|
||||
if (!FL_TEST_RAW(obj, ROBJECT_HEAP)) {
|
||||
if (rb_obj_shape_embedded_p(obj)) {
|
||||
dump_append(dc, ", \"embedded\":true");
|
||||
}
|
||||
|
||||
|
||||
@@ -1434,7 +1434,6 @@ rb_gc_obj_needs_cleanup_p(VALUE obj)
|
||||
|
||||
switch (flags & RUBY_T_MASK) {
|
||||
case T_OBJECT:
|
||||
if (flags & ROBJECT_HEAP) return true;
|
||||
return false;
|
||||
|
||||
case T_DATA:
|
||||
@@ -3300,18 +3299,18 @@ rb_gc_mark_children(void *objspace, VALUE obj)
|
||||
}
|
||||
|
||||
case T_OBJECT: {
|
||||
uint32_t len;
|
||||
if (FL_TEST_RAW(obj, ROBJECT_HEAP)) {
|
||||
if (!rb_gc_checking_shareable()) {
|
||||
gc_mark_internal(ROBJECT(obj)->as.extended);
|
||||
shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
|
||||
if (rb_shape_embedded_p(shape_id)) {
|
||||
uint32_t len = RSHAPE_LEN(shape_id);
|
||||
const VALUE * const ptr = ROBJECT(obj)->as.ary;
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
gc_mark_internal(ptr[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const VALUE * const ptr = ROBJECT(obj)->as.ary;
|
||||
|
||||
len = ROBJECT_FIELDS_COUNT_NOT_COMPLEX(obj);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
gc_mark_internal(ptr[i]);
|
||||
if (!rb_gc_checking_shareable()) {
|
||||
gc_mark_internal(ROBJECT(obj)->as.extended);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3680,15 +3679,15 @@ gc_ref_update_object(void *objspace, VALUE v)
|
||||
RUBY_ASSERT(rb_gc_obj_slot_size(v) == rb_obj_shape_slot_size(v));
|
||||
shape_id_t shape_id = RBASIC_SHAPE_ID(v);
|
||||
|
||||
if (FL_TEST_RAW(v, ROBJECT_HEAP)) {
|
||||
if (!rb_shape_embedded_p(shape_id)) {
|
||||
UPDATE_IF_MOVED(objspace, ROBJECT(v)->as.extended);
|
||||
|
||||
if (!rb_shape_complex_p(shape_id) && rb_shape_embedded_capacity(shape_id) >= RSHAPE_LEN(shape_id)) {
|
||||
VALUE *embedded_fields = ROBJECT_EMBEDDED_FIELDS(v);
|
||||
VALUE *extended_fields = ROBJECT_FIELDS(v);
|
||||
MEMCPY(embedded_fields, extended_fields, VALUE, RSHAPE_LEN(shape_id));
|
||||
FL_UNSET_RAW(v, ROBJECT_HEAP);
|
||||
RBASIC_SET_FULL_SHAPE_ID(v, rb_shape_transition_robject(shape_id));
|
||||
shape_id = rb_shape_transition_robject(shape_id);
|
||||
RBASIC_SET_FULL_SHAPE_ID(v, shape_id);
|
||||
rb_gc_writebarrier_remember(v);
|
||||
}
|
||||
else {
|
||||
@@ -3697,7 +3696,8 @@ gc_ref_update_object(void *objspace, VALUE v)
|
||||
}
|
||||
|
||||
VALUE *ptr = ROBJECT_FIELDS(v);
|
||||
for (uint32_t i = 0; i < ROBJECT_FIELDS_COUNT(v); i++) {
|
||||
attr_index_t len = RSHAPE_LEN(shape_id);
|
||||
for (attr_index_t i = 0; i < len; i++) {
|
||||
UPDATE_IF_MOVED(objspace, ptr[i]);
|
||||
}
|
||||
}
|
||||
@@ -4855,17 +4855,19 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
|
||||
}
|
||||
case T_OBJECT:
|
||||
{
|
||||
if (FL_TEST_RAW(obj, ROBJECT_HEAP)) {
|
||||
if (rb_obj_shape_complex_p(obj)) {
|
||||
size_t hash_len = rb_st_table_size(ROBJECT_FIELDS_HASH(obj));
|
||||
APPEND_F("(complex) len:%zu", hash_len);
|
||||
}
|
||||
else {
|
||||
APPEND_F("len:%d capa:%d extended:%p", RSHAPE_LEN(RBASIC_SHAPE_ID(obj)), ROBJECT_FIELDS_CAPACITY(obj), (void *)ROBJECT_FIELDS_OBJ(obj));
|
||||
}
|
||||
shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
|
||||
if (rb_shape_embedded_p(shape_id)) {
|
||||
APPEND_F("(embed) len:%d capa:%d", RSHAPE_LEN(shape_id), RSHAPE_CAPACITY(shape_id));
|
||||
}
|
||||
else {
|
||||
APPEND_F("(embed) len:%d capa:%d", RSHAPE_LEN(RBASIC_SHAPE_ID(obj)), ROBJECT_FIELDS_CAPACITY(obj));
|
||||
VALUE fields_obj = ROBJECT_FIELDS_OBJ(obj);
|
||||
if (rb_shape_complex_p(shape_id)) {
|
||||
size_t hash_len = rb_st_table_size(rb_imemo_fields_complex_tbl(fields_obj));
|
||||
APPEND_F("(complex) len:%zu extended:%p", hash_len, (void *)fields_obj);
|
||||
}
|
||||
else {
|
||||
APPEND_F("(extended) len:%d capa:%d extended:%p", RSHAPE_LEN(shape_id), RSHAPE_CAPACITY(shape_id), (void *)fields_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -43,39 +43,10 @@
|
||||
#define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj))
|
||||
/** @cond INTERNAL_MACRO */
|
||||
#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
|
||||
#define ROBJECT_HEAP ROBJECT_HEAP
|
||||
#define ROBJECT_FIELDS_CAPACITY ROBJECT_FIELDS_CAPACITY
|
||||
#define ROBJECT_FIELDS ROBJECT_FIELDS
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Bits that you can set to ::RBasic::flags.
|
||||
*/
|
||||
enum ruby_robject_flags {
|
||||
/**
|
||||
* This flag marks that the object's instance variables are stored in an
|
||||
* external heap buffer.
|
||||
* Normally, instance variable references are stored inside the object slot,
|
||||
* but if it overflow, Ruby may have to allocate a separate buffer and spills
|
||||
* the instance variables there.
|
||||
* This flag denotes that situation.
|
||||
*
|
||||
* @warning This bit has to be considered read-only. Setting/clearing
|
||||
* this bit without corresponding fix up must cause immediate
|
||||
* SEGV. Also, internal structures of an object change
|
||||
* dynamically and transparently throughout of its lifetime.
|
||||
* Don't assume it being persistent.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* 3rd parties must not be aware that there even is more than one way to
|
||||
* store instance variables. Might better be hidden.
|
||||
*/
|
||||
ROBJECT_HEAP = RUBY_FL_USER4
|
||||
};
|
||||
|
||||
struct st_table;
|
||||
|
||||
/**
|
||||
|
||||
@@ -252,8 +252,6 @@ struct rb_fields {
|
||||
|
||||
// IMEMO/fields and T_OBJECT have exactly the same layout.
|
||||
// This is useful for JIT and common codepaths.
|
||||
#define OBJ_FIELD_HEAP ROBJECT_HEAP
|
||||
STATIC_ASSERT(imemo_fields_flags, OBJ_FIELD_HEAP == IMEMO_FL_USER0);
|
||||
STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.ary) == offsetof(struct rb_fields, as.embed.fields));
|
||||
|
||||
#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
|
||||
@@ -292,39 +290,4 @@ rb_imemo_fields_owner(VALUE fields_obj)
|
||||
return CLASS_OF(fields_obj);
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
rb_imemo_fields_ptr(VALUE fields_obj)
|
||||
{
|
||||
if (!fields_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
|
||||
|
||||
if (UNLIKELY(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP))) {
|
||||
RUBY_ASSERT(RB_TYPE_P(fields_obj, T_OBJECT));
|
||||
fields_obj = ROBJECT(fields_obj)->as.extended;
|
||||
RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
|
||||
}
|
||||
|
||||
return IMEMO_OBJ_FIELDS(fields_obj)->as.embed.fields;
|
||||
}
|
||||
|
||||
static inline st_table *
|
||||
rb_imemo_fields_complex_tbl(VALUE fields_obj)
|
||||
{
|
||||
if (!fields_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
|
||||
RUBY_ASSERT(!FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP));
|
||||
|
||||
// Some codepaths unconditionally access the fields_ptr, and assume it can be used as st_table if the
|
||||
// shape is complex.
|
||||
RUBY_ASSERT((st_table *)rb_imemo_fields_ptr(fields_obj) == &IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table);
|
||||
|
||||
return &IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
|
||||
}
|
||||
|
||||
#endif /* INTERNAL_IMEMO_H */
|
||||
@@ -68,35 +68,12 @@ RBASIC_SET_CLASS(VALUE obj, VALUE klass)
|
||||
RB_OBJ_WRITTEN(obj, oldv, klass);
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
ROBJECT_FIELDS_OBJ(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
|
||||
return FL_TEST_RAW(obj, ROBJECT_HEAP) ? ROBJECT(obj)->as.extended : obj;
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
ROBJECT_EMBEDDED_FIELDS(VALUE obj)
|
||||
{
|
||||
return ROBJECT(obj)->as.ary;
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
ROBJECT_FIELDS(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
|
||||
return ROBJECT_EMBEDDED_FIELDS(ROBJECT_FIELDS_OBJ(obj));
|
||||
}
|
||||
|
||||
static inline void
|
||||
ROBJECT_SET_EXTENDED(VALUE obj, VALUE fields_obj)
|
||||
{
|
||||
RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
|
||||
RUBY_ASSERT(RB_TYPE_P(fields_obj, T_IMEMO));
|
||||
RB_OBJ_WRITE(obj, &ROBJECT(obj)->as.extended, fields_obj);
|
||||
FL_SET_RAW(obj, ROBJECT_HEAP);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
|
||||
@@ -46,9 +46,6 @@
|
||||
|
||||
/* Flags of RObject
|
||||
*
|
||||
* 4: ROBJECT_HEAP
|
||||
* The object has its instance variables in a separately allocated buffer.
|
||||
* This can be either a flat buffer of reference, or an st_table for complex objects.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -355,8 +352,8 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
|
||||
RUBY_ASSERT(src_num_ivs <= dest_capa);
|
||||
if (initial_capa < dest_capa) {
|
||||
// We we need to transition the object to an extended layout.
|
||||
VALUE fields_obj = rb_imemo_fields_new(dest, dest_shape_id, false);
|
||||
ROBJECT_SET_EXTENDED(dest, fields_obj);
|
||||
rb_obj_replace_fields(dest, rb_imemo_fields_new(dest, dest_shape_id, false));
|
||||
|
||||
dest_buf = ROBJECT_FIELDS(dest);
|
||||
rb_shape_copy_fields(dest, dest_buf, dest_shape_id, src_buf, src_shape_id);
|
||||
RBASIC_SET_SHAPE_ID_WITH_LAYOUT(dest, dest_shape_id, SHAPE_ID_LAYOUT_EXTENDED);
|
||||
|
||||
@@ -1216,8 +1216,9 @@ static shape_id_t
|
||||
rb_shape_expected_layout(VALUE obj)
|
||||
{
|
||||
switch (BUILTIN_TYPE(obj)) {
|
||||
case T_OBJECT:
|
||||
return FL_TEST_RAW(obj, ROBJECT_HEAP) ? SHAPE_ID_LAYOUT_EXTENDED : SHAPE_ID_LAYOUT_ROBJECT;
|
||||
case T_OBJECT: {
|
||||
return SHAPE_ID_LAYOUT_ROBJECT;
|
||||
}
|
||||
case T_CLASS:
|
||||
case T_MODULE:
|
||||
if (FL_TEST_RAW(obj, RCLASS_BOXABLE)) {
|
||||
@@ -1278,8 +1279,10 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
|
||||
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=%s actual=%s shape_id=%u obj=%s",
|
||||
shape_layout_name(expected_layout), shape_layout_name(actual_layout), shape_id, rb_obj_info(obj));
|
||||
if (!(RB_TYPE_P(obj, T_OBJECT) && actual_layout == SHAPE_ID_LAYOUT_EXTENDED)) {
|
||||
rb_bug("shape_id layout mismatch: expected=%s actual=%s shape_id=%u obj=%s",
|
||||
shape_layout_name(expected_layout), shape_layout_name(actual_layout), shape_id, rb_obj_info(obj));
|
||||
}
|
||||
}
|
||||
|
||||
if (shape_id == ROOT_SHAPE_ID) {
|
||||
@@ -1294,10 +1297,10 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
|
||||
|
||||
// Ensure complex object don't appear as embedded
|
||||
if (RB_TYPE_P(obj, T_OBJECT)) {
|
||||
RUBY_ASSERT(FL_TEST_RAW(obj, ROBJECT_HEAP));
|
||||
RUBY_ASSERT(rb_obj_shape_extended_p(obj));
|
||||
}
|
||||
else if (IMEMO_TYPE_P(obj, imemo_fields)) {
|
||||
RUBY_ASSERT(!FL_TEST_RAW(obj, ROBJECT_HEAP));
|
||||
RUBY_ASSERT(rb_obj_shape_embedded_p(obj));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -191,6 +191,30 @@ rb_shape_layout(shape_id_t shape_id)
|
||||
return shape_id & SHAPE_ID_LAYOUT_MASK;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
rb_shape_embedded_p(shape_id_t shape_id)
|
||||
{
|
||||
return rb_shape_layout(shape_id) == SHAPE_ID_LAYOUT_ROBJECT;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
rb_shape_extended_p(shape_id_t shape_id)
|
||||
{
|
||||
return rb_shape_layout(shape_id) == SHAPE_ID_LAYOUT_EXTENDED;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
rb_obj_shape_embedded_p(VALUE obj)
|
||||
{
|
||||
return rb_shape_embedded_p(RBASIC_SHAPE_ID(obj));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
rb_obj_shape_extended_p(VALUE obj)
|
||||
{
|
||||
return rb_shape_extended_p(RBASIC_SHAPE_ID(obj));
|
||||
}
|
||||
|
||||
// Assigns the entire shape_id.
|
||||
// shape_id_t is composed of two parts:
|
||||
// - The layout and capacity part, which never changes except on GC compaction.
|
||||
@@ -381,49 +405,20 @@ RSHAPE_EDGE_NAME(shape_id_t shape_id)
|
||||
return RSHAPE(shape_id)->edge_name;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_CAPACITY(VALUE obj)
|
||||
static inline VALUE *
|
||||
rb_imemo_fields_ptr(VALUE fields_obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
// Asking for capacity doesn't make sense when the object is using
|
||||
// a hash table for storing instance variables
|
||||
RUBY_ASSERT(!rb_obj_shape_complex_p(obj));
|
||||
return RSHAPE_CAPACITY(RBASIC_SHAPE_ID(obj));
|
||||
}
|
||||
|
||||
static inline st_table *
|
||||
ROBJECT_FIELDS_HASH(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
RUBY_ASSERT(rb_obj_shape_complex_p(obj));
|
||||
RUBY_ASSERT(FL_TEST_RAW(obj, ROBJECT_HEAP));
|
||||
|
||||
return rb_imemo_fields_complex_tbl(ROBJECT(obj)->as.extended);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_COUNT_COMPLEX(VALUE obj)
|
||||
{
|
||||
return (uint32_t)rb_st_table_size(ROBJECT_FIELDS_HASH(obj));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_COUNT_NOT_COMPLEX(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
RUBY_ASSERT(!rb_obj_shape_complex_p(obj));
|
||||
return RSHAPE(RBASIC_SHAPE_ID(obj))->next_field_index;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_COUNT(VALUE obj)
|
||||
{
|
||||
if (rb_obj_shape_complex_p(obj)) {
|
||||
return ROBJECT_FIELDS_COUNT_COMPLEX(obj);
|
||||
if (!fields_obj) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
return ROBJECT_FIELDS_COUNT_NOT_COMPLEX(obj);
|
||||
|
||||
if (UNLIKELY(rb_obj_shape_extended_p(fields_obj))) {
|
||||
RUBY_ASSERT(RB_TYPE_P(fields_obj, T_OBJECT));
|
||||
fields_obj = ROBJECT(fields_obj)->as.extended;
|
||||
RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
|
||||
}
|
||||
|
||||
return IMEMO_OBJ_FIELDS(fields_obj)->as.embed.fields;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
@@ -688,4 +683,87 @@ rb_setivar_cache_revalidate(shape_id_t shape_id, shape_id_t fields_shape_id, rb_
|
||||
return rb_shape_transition_offset(shape_id, cache.dest_shape_offset);
|
||||
}
|
||||
|
||||
static inline st_table *
|
||||
rb_imemo_fields_complex_tbl(VALUE fields_obj)
|
||||
{
|
||||
if (!fields_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
|
||||
|
||||
// Some codepaths unconditionally access the fields_ptr, and assume it can be used as st_table if the
|
||||
// shape is complex.
|
||||
RUBY_ASSERT((st_table *)rb_imemo_fields_ptr(fields_obj) == &IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table);
|
||||
|
||||
return &IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_CAPACITY(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
// Asking for capacity doesn't make sense when the object is using
|
||||
// a hash table for storing instance variables
|
||||
RUBY_ASSERT(!rb_obj_shape_complex_p(obj));
|
||||
return RSHAPE_CAPACITY(RBASIC_SHAPE_ID(obj));
|
||||
}
|
||||
|
||||
static inline st_table *
|
||||
ROBJECT_FIELDS_HASH(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
RUBY_ASSERT(rb_obj_shape_complex_p(obj));
|
||||
RUBY_ASSERT(rb_obj_shape_extended_p(obj));
|
||||
|
||||
return rb_imemo_fields_complex_tbl(ROBJECT(obj)->as.extended);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_COUNT_COMPLEX(VALUE obj)
|
||||
{
|
||||
return (uint32_t)rb_st_table_size(ROBJECT_FIELDS_HASH(obj));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_COUNT_NOT_COMPLEX(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
RUBY_ASSERT(!rb_obj_shape_complex_p(obj));
|
||||
return RSHAPE(RBASIC_SHAPE_ID(obj))->next_field_index;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ROBJECT_FIELDS_COUNT(VALUE obj)
|
||||
{
|
||||
if (rb_obj_shape_complex_p(obj)) {
|
||||
return ROBJECT_FIELDS_COUNT_COMPLEX(obj);
|
||||
}
|
||||
else {
|
||||
return ROBJECT_FIELDS_COUNT_NOT_COMPLEX(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
ROBJECT_FIELDS_OBJ(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
|
||||
return rb_obj_shape_embedded_p(obj) ? obj : ROBJECT(obj)->as.extended;
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
ROBJECT_EMBEDDED_FIELDS(VALUE obj)
|
||||
{
|
||||
return ROBJECT(obj)->as.ary;
|
||||
}
|
||||
|
||||
static inline VALUE *
|
||||
ROBJECT_FIELDS(VALUE obj)
|
||||
{
|
||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||
|
||||
return ROBJECT_EMBEDDED_FIELDS(ROBJECT_FIELDS_OBJ(obj));
|
||||
}
|
||||
|
||||
#endif
|
||||
+1
-4
@@ -1710,10 +1710,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
|
||||
if (fields_obj != original_fields_obj) {
|
||||
switch (type) {
|
||||
case T_OBJECT:
|
||||
if (!fields_obj) {
|
||||
FL_UNSET_RAW(obj, ROBJECT_HEAP);
|
||||
}
|
||||
else if (fields_obj != obj) {
|
||||
if (fields_obj && fields_obj != obj) {
|
||||
ROBJECT_SET_EXTENDED(obj, fields_obj);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -439,6 +439,12 @@ rb_yjit_shape_obj_complex_p(VALUE obj)
|
||||
return rb_obj_shape_complex_p(obj);
|
||||
}
|
||||
|
||||
bool
|
||||
rb_yjit_shape_obj_embedded_p(VALUE obj)
|
||||
{
|
||||
return rb_obj_shape_embedded_p(obj);
|
||||
}
|
||||
|
||||
attr_index_t
|
||||
rb_yjit_shape_capacity(shape_id_t shape_id)
|
||||
{
|
||||
|
||||
@@ -88,6 +88,7 @@ fn main() {
|
||||
.allowlist_function("rb_shape_get_iv_index")
|
||||
.allowlist_function("rb_shape_transition_add_ivar_no_warnings")
|
||||
.allowlist_function("rb_yjit_shape_obj_complex_p")
|
||||
.allowlist_function("rb_yjit_shape_obj_embedded_p")
|
||||
.allowlist_function("rb_yjit_shape_capacity")
|
||||
.allowlist_function("rb_yjit_shape_index")
|
||||
.allowlist_var("SHAPE_ID_NUM_BITS")
|
||||
|
||||
+1
-3
@@ -453,9 +453,7 @@ impl VALUE {
|
||||
}
|
||||
|
||||
pub fn embedded_p(self) -> bool {
|
||||
unsafe {
|
||||
FL_TEST_RAW(self, VALUE(ROBJECT_HEAP as usize)) == VALUE(0)
|
||||
}
|
||||
unsafe { rb_yjit_shape_obj_embedded_p(self) }
|
||||
}
|
||||
|
||||
pub fn as_isize(self) -> isize {
|
||||
|
||||
Generated
+1
-2
@@ -271,8 +271,6 @@ pub const RARRAY_EMBED_LEN_SHIFT: ruby_rarray_consts = 15;
|
||||
pub type ruby_rarray_consts = u32;
|
||||
pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 8192;
|
||||
pub type ruby_rmodule_flags = u32;
|
||||
pub const ROBJECT_HEAP: ruby_robject_flags = 65536;
|
||||
pub type ruby_robject_flags = u32;
|
||||
pub type rb_block_call_func = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
yielded_arg: VALUE,
|
||||
@@ -1219,6 +1217,7 @@ extern "C" {
|
||||
);
|
||||
pub fn rb_object_shape_count() -> VALUE;
|
||||
pub fn rb_yjit_shape_obj_complex_p(obj: VALUE) -> bool;
|
||||
pub fn rb_yjit_shape_obj_embedded_p(obj: VALUE) -> bool;
|
||||
pub fn rb_yjit_shape_capacity(shape_id: shape_id_t) -> attr_index_t;
|
||||
pub fn rb_yjit_shape_index(shape_id: shape_id_t) -> attr_index_t;
|
||||
pub fn rb_yjit_sendish_sp_pops(ci: *const rb_callinfo) -> usize;
|
||||
|
||||
+2
-4
@@ -648,10 +648,8 @@ impl VALUE {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn embedded_p(self) -> bool {
|
||||
unsafe {
|
||||
FL_TEST_RAW(self, VALUE(ROBJECT_HEAP as usize)) == VALUE(0)
|
||||
}
|
||||
pub fn layout(self) -> ShapeLayout {
|
||||
self.shape_id_of().layout()
|
||||
}
|
||||
|
||||
pub fn struct_embedded_p(self) -> bool {
|
||||
|
||||
Generated
-2
@@ -367,8 +367,6 @@ pub struct RArray__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 {
|
||||
}
|
||||
pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 8192;
|
||||
pub type ruby_rmodule_flags = u32;
|
||||
pub const ROBJECT_HEAP: ruby_robject_flags = 65536;
|
||||
pub type ruby_robject_flags = u32;
|
||||
pub type rb_event_flag_t = u32;
|
||||
pub type rb_block_call_func = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
|
||||
@@ -6706,7 +6706,7 @@ mod hir_opt_tests {
|
||||
TEST = ExtendedSetIvar.instance_method(:test)
|
||||
OBJ
|
||||
"#);
|
||||
assert!(!obj.embedded_p());
|
||||
assert!(obj.layout() == ShapeLayout::Extended);
|
||||
|
||||
assert_snapshot!(hir_string_proc("TEST"), @"
|
||||
fn test@<compiled>:4:
|
||||
@@ -17016,7 +17016,7 @@ mod hir_opt_tests {
|
||||
OBJ
|
||||
"#);
|
||||
// Skip builds where five ivars already force heap-backed storage.
|
||||
if !obj.embedded_p() {
|
||||
if obj.layout() != ShapeLayout::RObject {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17027,7 +17027,7 @@ mod hir_opt_tests {
|
||||
probe.instance_variable_set(:@overflow, 1)
|
||||
probe
|
||||
"#);
|
||||
if probe.embedded_p() {
|
||||
if probe.layout() == ShapeLayout::RObject {
|
||||
return;
|
||||
}
|
||||
eval("OBJ.test");
|
||||
|
||||
+1
-1
@@ -332,7 +332,7 @@ impl ProfiledType {
|
||||
flags: Flags::immediate() };
|
||||
}
|
||||
let mut flags = Flags::none();
|
||||
if obj.embedded_p() {
|
||||
if obj.shape_id_of().layout() == ShapeLayout::RObject {
|
||||
flags.0 |= Flags::IS_EMBEDDED;
|
||||
}
|
||||
if obj.struct_embedded_p() {
|
||||
|
||||
Reference in new issue
Block a user