@@ -874,72 +874,77 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int
874874 /* special/collectible static */
875875 continue ;
876876
877- pos = field_offset / TARGET_SIZEOF_VOID_P ;
878- pos += offset ;
879-
880- type = mono_type_get_underlying_type (field -> type );
881-
882- switch (type -> type ) {
883- case MONO_TYPE_U :
884- case MONO_TYPE_I :
885- case MONO_TYPE_PTR :
886- case MONO_TYPE_FNPTR :
887- break ;
888- case MONO_TYPE_STRING :
889- case MONO_TYPE_SZARRAY :
890- case MONO_TYPE_CLASS :
891- case MONO_TYPE_OBJECT :
892- case MONO_TYPE_ARRAY :
893- g_assert ((m_field_get_offset (field ) % wordsize ) == 0 );
894-
895- g_assert (pos < GINT_TO_UINT32 (size ) || pos <= GINT_TO_UINT32 (max_size ));
896- bitmap [pos / BITMAP_EL_SIZE ] |= ((gsize )1 ) << (pos % BITMAP_EL_SIZE );
897- * max_set = MAX (GINT_TO_UINT32 (* max_set ), pos );
898- break ;
899- case MONO_TYPE_GENERICINST :
900- if (!mono_type_generic_inst_is_valuetype (type )) {
877+ guint32 field_iter = 1 ;
878+ guint32 field_instance_offset = field_offset ;
879+ // If struct has InlineArray attribute, iterate `length` times to set a bitmap
880+ if (m_class_is_inlinearray (p ))
881+ field_iter = m_class_inlinearray_value (p );
882+
883+ if (field_iter > 500 )
884+ g_warning ("Large number of iterations detected when creating a GC bitmap, might affect performance." );
885+
886+ while (field_iter ) {
887+ pos = field_instance_offset / TARGET_SIZEOF_VOID_P ;
888+ pos += offset ;
889+
890+ type = mono_type_get_underlying_type (field -> type );
891+
892+ switch (type -> type ) {
893+ case MONO_TYPE_U :
894+ case MONO_TYPE_I :
895+ case MONO_TYPE_PTR :
896+ case MONO_TYPE_FNPTR :
897+ break ;
898+ case MONO_TYPE_STRING :
899+ case MONO_TYPE_SZARRAY :
900+ case MONO_TYPE_CLASS :
901+ case MONO_TYPE_OBJECT :
902+ case MONO_TYPE_ARRAY :
901903 g_assert ((m_field_get_offset (field ) % wordsize ) == 0 );
902904
905+ g_assert (pos < GINT_TO_UINT32 (size ) || pos <= GINT_TO_UINT32 (max_size ));
903906 bitmap [pos / BITMAP_EL_SIZE ] |= ((gsize )1 ) << (pos % BITMAP_EL_SIZE );
904907 * max_set = MAX (GINT_TO_UINT32 (* max_set ), pos );
905908 break ;
906- } else {
907- /* fall through */
909+ case MONO_TYPE_GENERICINST :
910+ if (!mono_type_generic_inst_is_valuetype (type )) {
911+ g_assert ((m_field_get_offset (field ) % wordsize ) == 0 );
912+
913+ bitmap [pos / BITMAP_EL_SIZE ] |= ((gsize )1 ) << (pos % BITMAP_EL_SIZE );
914+ * max_set = MAX (GINT_TO_UINT32 (* max_set ), pos );
915+ break ;
916+ } else {
917+ /* fall through */
918+ }
919+ case MONO_TYPE_TYPEDBYREF :
920+ case MONO_TYPE_VALUETYPE : {
921+ MonoClass * fclass = mono_class_from_mono_type_internal (field -> type );
922+ if (m_class_has_references (fclass )) {
923+ /* remove the object header */
924+ compute_class_bitmap (fclass , bitmap , size , pos - MONO_OBJECT_HEADER_BITS , max_set , FALSE);
925+ }
926+ break ;
908927 }
909- case MONO_TYPE_TYPEDBYREF :
910- case MONO_TYPE_VALUETYPE : {
911- MonoClass * fclass = mono_class_from_mono_type_internal (field -> type );
912- if (m_class_has_references (fclass )) {
913- /* remove the object header */
914- compute_class_bitmap (fclass , bitmap , size , pos - MONO_OBJECT_HEADER_BITS , max_set , FALSE);
928+ case MONO_TYPE_I1 :
929+ case MONO_TYPE_U1 :
930+ case MONO_TYPE_I2 :
931+ case MONO_TYPE_U2 :
932+ case MONO_TYPE_I4 :
933+ case MONO_TYPE_U4 :
934+ case MONO_TYPE_I8 :
935+ case MONO_TYPE_U8 :
936+ case MONO_TYPE_R4 :
937+ case MONO_TYPE_R8 :
938+ case MONO_TYPE_BOOLEAN :
939+ case MONO_TYPE_CHAR :
940+ break ;
941+ default :
942+ g_error ("compute_class_bitmap: Invalid type %x for field %s:%s\n" , type -> type , mono_type_get_full_name (m_field_get_parent (field )), field -> name );
943+ break ;
915944 }
916- break ;
917- }
918- case MONO_TYPE_I1 :
919- case MONO_TYPE_U1 :
920- case MONO_TYPE_I2 :
921- case MONO_TYPE_U2 :
922- case MONO_TYPE_I4 :
923- case MONO_TYPE_U4 :
924- case MONO_TYPE_I8 :
925- case MONO_TYPE_U8 :
926- case MONO_TYPE_R4 :
927- case MONO_TYPE_R8 :
928- case MONO_TYPE_BOOLEAN :
929- case MONO_TYPE_CHAR :
930- break ;
931- default :
932- g_error ("compute_class_bitmap: Invalid type %x for field %s:%s\n" , type -> type , mono_type_get_full_name (m_field_get_parent (field )), field -> name );
933- break ;
934- }
935-
936- // A struct with the inline array attribute is handled in the same way as an array
937- if (m_class_is_inlinearray (klass )) {
938- g_assert ((m_field_get_offset (field ) % wordsize ) == 0 );
939945
940- g_assert (pos < GINT_TO_UINT32 (size ) || pos <= GINT_TO_UINT32 (max_size ));
941- bitmap [pos / BITMAP_EL_SIZE ] |= ((gsize )1 ) << (pos % BITMAP_EL_SIZE );
942- * max_set = MAX (GINT_TO_UINT32 (* max_set ), pos );
946+ field_instance_offset += field_offset ;
947+ field_iter -- ;
943948 }
944949 }
945950 if (static_fields )
0 commit comments