@@ -1415,17 +1415,17 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
14151415 case T_MODULE :
14161416 {
14171417 bool found = false;
1418- VALUE val ;
1418+ VALUE val = undef ;
14191419
1420- RB_VM_LOCK_ENTER ();
1421- {
1420+ VALUE fields_obj = RCLASS_PRIME_FIELDS_VALUE ( obj ); // TODO: figure namespaces
1421+ if ( fields_obj ) {
14221422#if !SHAPE_IN_BASIC_FLAGS
1423- shape_id = RCLASS_SHAPE_ID ( obj );
1423+ shape_id = get_shape_id_from_flags ( fields_obj );
14241424#endif
14251425
1426- if (rb_shape_obj_too_complex_p (obj )) {
1427- st_table * iv_table = RCLASS_FIELDS_HASH ( obj ) ;
1428- if (rb_st_lookup (iv_table , (st_data_t )id , (st_data_t * )& val )) {
1426+ if (rb_shape_obj_too_complex_p (fields_obj )) {
1427+ st_table * fields_tbl = IMEMO_OBJ_FIELDS ( fields_obj ) -> as . complex . table ;
1428+ if (rb_st_lookup (fields_tbl , (st_data_t )id , (st_data_t * )& val )) {
14291429 found = true;
14301430 }
14311431 else {
@@ -1438,7 +1438,7 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
14381438 found = rb_shape_get_iv_index (shape , id , & index );
14391439
14401440 if (found ) {
1441- ivar_list = RCLASS_PRIME_FIELDS ( obj );
1441+ ivar_list = rb_imemo_obj_fields_ptr ( fields_obj );
14421442 RUBY_ASSERT (ivar_list );
14431443
14441444 val = ivar_list [index ];
@@ -1448,7 +1448,6 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
14481448 }
14491449 }
14501450 }
1451- RB_VM_LOCK_LEAVE ();
14521451
14531452 if (found &&
14541453 rb_is_instance_id (id ) &&
@@ -4738,7 +4737,7 @@ class_ivar_set_shape_fields(VALUE obj, void *_data)
47384737static void
47394738class_ivar_set_shape_resize_fields (VALUE obj , attr_index_t old_capa , attr_index_t new_capa , void * _data )
47404739{
4741- VALUE new_fields = rb_imemo_obj_fields_new (new_capa );
4740+ VALUE new_fields = rb_imemo_obj_fields_new (obj , new_capa );
47424741 if (old_capa ) {
47434742 MEMCPY (rb_imemo_obj_fields_ptr (new_fields ), RCLASS_PRIME_FIELDS (obj ), VALUE , old_capa );
47444743 }
@@ -4765,27 +4764,85 @@ class_ivar_set_too_complex_table(VALUE obj, void *_data)
47654764 return RCLASS_WRITABLE_FIELDS_HASH (obj );
47664765}
47674766
4767+ int
4768+ class_atomic_ivar_set (VALUE obj , ID id , VALUE val )
4769+ {
4770+ bool existing = true;
4771+
4772+ VALUE original_fields_obj = RCLASS_PRIME_FIELDS_VALUE (obj ); // TODO: figure out namespaces
4773+ VALUE fields_obj = original_fields_obj ;
4774+
4775+ if (!fields_obj ) {
4776+ fields_obj = rb_imemo_obj_fields_new (obj , 0 );
4777+ }
4778+
4779+ rb_shape_t * current_shape = rb_obj_shape (fields_obj );
4780+ if (UNLIKELY (rb_shape_too_complex_p (current_shape ))) {
4781+ goto too_complex ;
4782+ }
4783+
4784+ attr_index_t index ;
4785+ shape_id_t next_shape_id = 0 ;
4786+ if (!rb_shape_get_iv_index (current_shape , id , & index )) {
4787+ existing = false;
4788+
4789+ index = current_shape -> next_field_index ;
4790+ if (index >= SHAPE_MAX_FIELDS ) {
4791+ rb_raise (rb_eArgError , "too many instance variables" );
4792+ }
4793+
4794+ next_shape_id = rb_shape_transition_add_ivar (obj , id );
4795+ rb_shape_t * next_shape = RSHAPE (next_shape_id );
4796+ if (UNLIKELY (rb_shape_too_complex_p (next_shape ))) {
4797+ rb_bug ("TODO: transition_too_complex" );
4798+ goto too_complex ;
4799+ }
4800+ else if (UNLIKELY (next_shape -> capacity != current_shape -> capacity )) {
4801+ RUBY_ASSERT (next_shape -> capacity > current_shape -> capacity );
4802+ fields_obj = rb_imemo_obj_fields_new (obj , next_shape -> capacity );
4803+ }
4804+
4805+ RUBY_ASSERT (next_shape -> type == SHAPE_IVAR );
4806+ RUBY_ASSERT (index == (next_shape -> next_field_index - 1 ));
4807+ }
4808+
4809+ VALUE * fields = rb_imemo_obj_fields_ptr (fields_obj );
4810+ RB_OBJ_WRITE (obj , & fields [index ], val );
4811+ if (!existing ) {
4812+ rb_shape_set_shape_id (fields_obj , next_shape_id );
4813+ }
4814+
4815+ if (fields_obj != original_fields_obj ) {
4816+ RUBY_ATOMIC_VALUE_SET (RCLASS_PRIME_FIELDS_VALUE (obj ), fields_obj );
4817+ }
4818+
4819+ return existing ;
4820+
4821+ too_complex :
4822+ {
4823+ rb_bug ("TODO: handle too_complex" );
4824+ }
4825+ return existing ;
4826+ }
4827+
47684828int
47694829rb_class_ivar_set (VALUE obj , ID id , VALUE val )
47704830{
47714831 RUBY_ASSERT (RB_TYPE_P (obj , T_CLASS ) || RB_TYPE_P (obj , T_MODULE ));
4772- bool existing = false;
47734832 rb_check_frozen (obj );
4774-
47754833 rb_class_ensure_writable (obj );
47764834
4777- RB_VM_LOCK_ENTER ();
4778- {
4779- existing = general_ivar_set (obj , id , val , NULL ,
4780- class_ivar_set_shape_fields ,
4781- class_ivar_set_shape_resize_fields ,
4782- class_ivar_set_set_shape_id ,
4783- class_ivar_set_transition_too_complex ,
4784- class_ivar_set_too_complex_table ).existing ;
4835+ if (rb_multi_ractor_p ()) {
4836+ return class_atomic_ivar_set (obj , id , val );
4837+ }
4838+ else {
4839+ return general_ivar_set (obj , id , val , NULL ,
4840+ class_ivar_set_shape_fields ,
4841+ class_ivar_set_shape_resize_fields ,
4842+ class_ivar_set_set_shape_id ,
4843+ class_ivar_set_transition_too_complex ,
4844+ class_ivar_set_too_complex_table ).existing ;
47854845 }
4786- RB_VM_LOCK_LEAVE ();
4787-
4788- return existing ;
47894846}
47904847
47914848static void
0 commit comments