@@ -1197,6 +1197,29 @@ rb_generic_fields_tbl_get(void)
11971197 return generic_fields_tbl_ ;
11981198}
11991199
1200+ static inline VALUE
1201+ generic_fields_lookup (VALUE obj , ID id , bool force_check_ractor )
1202+ {
1203+ VALUE fields_obj = Qfalse ;
1204+ RB_VM_LOCKING () {
1205+ st_table * generic_tbl = generic_fields_tbl (obj , id , false);
1206+ st_lookup (generic_tbl , obj , (st_data_t * )& fields_obj );
1207+ }
1208+ return fields_obj ;
1209+ }
1210+
1211+ static inline void
1212+ generic_fields_insert (VALUE obj , VALUE fields_obj )
1213+ {
1214+ RUBY_ASSERT (IMEMO_TYPE_P (fields_obj , imemo_fields ));
1215+
1216+ RB_VM_LOCKING () {
1217+ st_table * generic_tbl = generic_fields_tbl_no_ractor_check (obj );
1218+ st_insert (generic_tbl , obj , fields_obj );
1219+ }
1220+ RB_OBJ_WRITTEN (obj , Qundef , fields_obj );
1221+ }
1222+
12001223int
12011224rb_gen_fields_tbl_get (VALUE obj , ID id , VALUE * fields_obj )
12021225{
@@ -1758,17 +1781,25 @@ general_field_set(VALUE obj, shape_id_t target_shape_id, VALUE val, void *data,
17581781 }
17591782}
17601783
1784+ static inline void
1785+ generic_update_fields_obj (VALUE obj , VALUE fields_obj , const VALUE original_fields_obj )
1786+ {
1787+ if (fields_obj != original_fields_obj ) {
1788+ if (original_fields_obj ) {
1789+ // Clear root shape to avoid triggering cleanup such as free_object_id.
1790+ RBASIC_SET_SHAPE_ID (original_fields_obj , ROOT_SHAPE_ID );
1791+ }
1792+
1793+ generic_fields_insert (obj , fields_obj );
1794+ }
1795+ }
1796+
17611797static void
17621798generic_ivar_set (VALUE obj , ID id , VALUE val )
17631799{
1764- VALUE fields_obj = 0 ;
1765- st_table * generic_tbl ;
17661800 bool existing = true;
17671801
1768- RB_VM_LOCKING () {
1769- generic_tbl = generic_fields_tbl (obj , id , false);
1770- st_lookup (generic_tbl , obj , (st_data_t * )& fields_obj );
1771- }
1802+ VALUE fields_obj = generic_fields_lookup (obj , id , false);
17721803
17731804 const VALUE original_fields_obj = fields_obj ;
17741805 if (!fields_obj ) {
@@ -1831,17 +1862,7 @@ generic_ivar_set(VALUE obj, ID id, VALUE val)
18311862 RBASIC_SET_SHAPE_ID (fields_obj , next_shape_id );
18321863 }
18331864
1834- if (fields_obj != original_fields_obj ) {
1835- RB_VM_LOCKING () {
1836- st_insert (generic_tbl , obj , fields_obj );
1837- }
1838- RB_OBJ_WRITTEN (obj , original_fields_obj , fields_obj );
1839-
1840- if (original_fields_obj ) {
1841- // Clear root shape to avoid triggering cleanup such as free_object_id.
1842- RBASIC_SET_SHAPE_ID (original_fields_obj , ROOT_SHAPE_ID );
1843- }
1844- }
1865+ generic_update_fields_obj (obj , fields_obj , original_fields_obj );
18451866
18461867 if (!existing ) {
18471868 RBASIC_SET_SHAPE_ID (obj , next_shape_id );
@@ -1857,17 +1878,8 @@ generic_ivar_set(VALUE obj, ID id, VALUE val)
18571878 existing = st_insert (table , (st_data_t )id , (st_data_t )val );
18581879 RB_OBJ_WRITTEN (fields_obj , Qundef , val );
18591880
1860- if (fields_obj != original_fields_obj ) {
1861- RB_VM_LOCKING () {
1862- st_insert (generic_tbl , obj , fields_obj );
1863- }
1864- RB_OBJ_WRITTEN (obj , original_fields_obj , fields_obj );
1881+ generic_update_fields_obj (obj , fields_obj , original_fields_obj );
18651882
1866- if (original_fields_obj ) {
1867- // Clear root shape to avoid triggering cleanup such as free_object_id.
1868- RBASIC_SET_SHAPE_ID (original_fields_obj , ROOT_SHAPE_ID );
1869- }
1870- }
18711883 if (!existing ) {
18721884 RBASIC_SET_SHAPE_ID (obj , next_shape_id );
18731885 }
@@ -1881,15 +1893,9 @@ generic_ivar_set(VALUE obj, ID id, VALUE val)
18811893static void
18821894generic_field_set (VALUE obj , shape_id_t target_shape_id , VALUE val )
18831895{
1884- VALUE fields_obj = 0 ;
1885- st_table * generic_tbl ;
18861896 bool existing = true;
18871897
1888- RB_VM_LOCKING () {
1889- generic_tbl = generic_fields_tbl (obj , RSHAPE_EDGE_NAME (target_shape_id ), false);
1890- st_lookup (generic_tbl , obj , (st_data_t * )& fields_obj );
1891- }
1892-
1898+ VALUE fields_obj = generic_fields_lookup (obj , RSHAPE_EDGE_NAME (target_shape_id ), false);
18931899 const VALUE original_fields_obj = fields_obj ;
18941900
18951901 shape_id_t current_shape_id = fields_obj ? RBASIC_SHAPE_ID (fields_obj ) : ROOT_SHAPE_ID ;
@@ -1908,10 +1914,10 @@ generic_field_set(VALUE obj, shape_id_t target_shape_id, VALUE val)
19081914 existing = false;
19091915 st_table * table = rb_imemo_fields_complex_tbl (fields_obj );
19101916
1911- RBASIC_SET_SHAPE_ID (fields_obj , target_shape_id );
19121917 RUBY_ASSERT (RSHAPE_EDGE_NAME (target_shape_id ));
19131918 st_insert (table , (st_data_t )RSHAPE_EDGE_NAME (target_shape_id ), (st_data_t )val );
19141919 RB_OBJ_WRITTEN (fields_obj , Qundef , val );
1920+ RBASIC_SET_SHAPE_ID (fields_obj , target_shape_id );
19151921 }
19161922 else {
19171923 attr_index_t index = RSHAPE_INDEX (target_shape_id );
@@ -1927,26 +1933,16 @@ generic_field_set(VALUE obj, shape_id_t target_shape_id, VALUE val)
19271933 }
19281934 }
19291935
1936+ VALUE * table = rb_imemo_fields_ptr (fields_obj );
1937+ RB_OBJ_WRITE (fields_obj , & table [index ], val );
1938+
19301939 if (RSHAPE_LEN (target_shape_id ) > RSHAPE_LEN (current_shape_id )) {
19311940 existing = false;
19321941 RBASIC_SET_SHAPE_ID (fields_obj , target_shape_id );
19331942 }
1934-
1935- VALUE * table = rb_imemo_fields_ptr (fields_obj );
1936- RB_OBJ_WRITE (fields_obj , & table [index ], val );
19371943 }
19381944
1939- if (fields_obj != original_fields_obj ) {
1940- RB_VM_LOCKING () {
1941- st_insert (generic_tbl , obj , fields_obj );
1942- }
1943- RB_OBJ_WRITTEN (obj , original_fields_obj , fields_obj );
1944-
1945- if (original_fields_obj ) {
1946- // Clear root shape to avoid triggering cleanup such as free_object_id.
1947- RBASIC_SET_SHAPE_ID (original_fields_obj , ROOT_SHAPE_ID );
1948- }
1949- }
1945+ generic_update_fields_obj (obj , fields_obj , original_fields_obj );
19501946
19511947 if (!existing ) {
19521948 RBASIC_SET_SHAPE_ID (obj , target_shape_id );
0 commit comments