From 9e81c774c95db26eb9170fbf025c9fd07ebb0f00 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Mon, 15 Sep 2025 20:39:05 +0300 Subject: [PATCH 1/2] [mono][metadata] Enable compressed interface bitmap by default (#119694) * [mono][metadata] Enable compressed interface bitmap by default * Fix build on windows * Fix publishing of compressed bitmap Before this commit we were doing changes on the published data which is problematic for multithreaded environments. We ensure the bitmap is fully processed before publishing it so that we can rely on the data dependency memory ordering constraint for correctness. --- src/mono/mono/metadata/class-init.c | 4 ++-- src/mono/mono/metadata/class-internals.h | 4 ---- src/mono/mono/metadata/class-setup-vtable.c | 8 +++++--- src/mono/mono/mini/type-checking.c | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 76459536c24971..25c9bb4e88deb9 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -1745,7 +1745,7 @@ mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size) while (bitmap < end) { if (*bitmap || numz == 255) { if (dest) { - *dest++ = numz; + *dest++ = (uint8_t)numz; *dest++ = *bitmap; } res += 2; @@ -1759,7 +1759,7 @@ mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size) if (numz) { res += 2; if (dest) { - *dest++ = numz; + *dest++ = (uint8_t)numz; *dest++ = 0; } } diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 55067f680d1b31..2fcc0ba29eed63 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -287,11 +287,7 @@ union _MonoClassSizes { int generic_param_token; /* for generic param types, both var and mvar */ }; -/* enabled only with small config for now: we might want to do it unconditionally */ -#ifdef MONO_SMALL_CONFIG #define COMPRESSED_INTERFACE_BITMAP 1 -#endif - #ifdef ENABLE_CHECKED_BUILD_PRIVATE_TYPES #define MONO_CLASS_DEF_PRIVATE 1 diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index b2f13d72dfc47c..4883f05f400786 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -344,10 +344,12 @@ mono_class_setup_interface_offsets_internal (MonoClass *klass, int cur_slot, int } if (!klass->interface_bitmap) { #ifdef COMPRESSED_INTERFACE_BITMAP - int i = mono_compress_bitmap (NULL, bitmap, bsize); - klass->interface_bitmap = mono_class_alloc0 (klass, i); - mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize); + int len = mono_compress_bitmap (NULL, bitmap, bsize); + uint8_t *compressed_bitmap = mono_class_alloc0 (klass, len); + mono_compress_bitmap (compressed_bitmap, bitmap, bsize); g_free (bitmap); + + klass->interface_bitmap = compressed_bitmap; #else klass->interface_bitmap = bitmap; #endif diff --git a/src/mono/mono/mini/type-checking.c b/src/mono/mono/mini/type-checking.c index a847cb8e720d27..5237fdfabc2382 100644 --- a/src/mono/mono/mini/type-checking.c +++ b/src/mono/mono/mini/type-checking.c @@ -136,7 +136,7 @@ mini_emit_interface_bitmap_check (MonoCompile *cfg, int intf_bit_reg, int base_r #ifdef COMPRESSED_INTERFACE_BITMAP MonoInst *args [2]; MonoInst *res, *ins; - NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, ibitmap_reg, base_reg, offset); + NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, ibitmap_reg, base_reg, (target_mgreg_t)offset); MONO_ADD_INS (cfg->cbb, ins); args [0] = ins; args [1] = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_IID, klass); From 6f57863b13e63342bdbba7f03c45359f1341f90c Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Mon, 22 Sep 2025 16:08:44 +0300 Subject: [PATCH 2/2] [mono] Enable configuration at runtime of the compressed interface bitmap feature (#119881) * Add option to configure use of compressed interface bitmaps This optimization is disabled by default. Enable it with `MONO_COMPRESSED_INTERFACE_BITMAP=1` * Add support for detecting mismatch with aot images --- src/mono/mono/metadata/class-init.c | 5 +- src/mono/mono/metadata/class-internals.h | 13 ++--- src/mono/mono/metadata/class-setup-vtable.c | 39 +++++++------ src/mono/mono/metadata/jit-icall-reg.h | 2 +- src/mono/mono/metadata/marshal.c | 7 +-- src/mono/mono/metadata/metadata.c | 9 +++ src/mono/mono/mini/aot-compiler.c | 3 + src/mono/mono/mini/aot-runtime.c | 9 ++- src/mono/mono/mini/aot-runtime.h | 5 +- src/mono/mono/mini/mini-runtime.c | 6 +- src/mono/mono/mini/type-checking.c | 63 +++++++++++---------- src/mono/mono/utils/options-def.h | 2 + 12 files changed, 88 insertions(+), 75 deletions(-) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 25c9bb4e88deb9..e431249b184780 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -1689,8 +1689,6 @@ mono_class_setup_count_virtual_methods (MonoClass *klass) return vcount; } -#ifdef COMPRESSED_INTERFACE_BITMAP - /* * Compressed interface bitmap design. * @@ -1780,7 +1778,7 @@ mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size) * FALSE otherwise. */ int -mono_class_interface_match (const uint8_t *bitmap, int id) +mono_class_interface_match_compressed (const uint8_t *bitmap, int id) { while (TRUE) { id -= bitmap [0] * 8; @@ -1793,7 +1791,6 @@ mono_class_interface_match (const uint8_t *bitmap, int id) id -= 8; } } -#endif static char* concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2) diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 2fcc0ba29eed63..22b35e1e674c6f 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -17,6 +17,7 @@ #include "mono/utils/mono-error-internals.h" #include "mono/utils/mono-memory-model.h" #include "mono/utils/mono-compiler.h" +#include "mono/utils/options.h" #define MONO_CLASS_IS_ARRAY(c) (m_class_get_rank (c)) @@ -287,8 +288,6 @@ union _MonoClassSizes { int generic_param_token; /* for generic param types, both var and mvar */ }; -#define COMPRESSED_INTERFACE_BITMAP 1 - #ifdef ENABLE_CHECKED_BUILD_PRIVATE_TYPES #define MONO_CLASS_DEF_PRIVATE 1 #endif @@ -317,14 +316,12 @@ union _MonoClassSizes { #undef MONO_CLASS_GETTER #undef MONO_CLASS_OFFSET -#ifdef COMPRESSED_INTERFACE_BITMAP int mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size); -int mono_class_interface_match (const uint8_t *bitmap, int id); -#else +int mono_class_interface_match_compressed (const uint8_t *bitmap, int id); + #define mono_class_interface_match(bmap,uiid) ((bmap) [(uiid) >> 3] & (1 << ((uiid)&7))) -#endif -#define MONO_CLASS_IMPLEMENTS_INTERFACE(k,uiid) (((uiid) <= m_class_get_max_interface_id (k)) && mono_class_interface_match (m_class_get_interface_bitmap (k), (uiid))) +#define MONO_CLASS_IMPLEMENTS_INTERFACE(k,uiid) (((uiid) <= m_class_get_max_interface_id (k)) && (mono_opt_compressed_interface_bitmap ? mono_class_interface_match_compressed (m_class_get_interface_bitmap (k), (uiid)) : mono_class_interface_match (m_class_get_interface_bitmap (k), (uiid)))) #define MONO_VTABLE_AVAILABLE_GC_BITS 4 @@ -374,7 +371,7 @@ struct MonoVTable { #define MONO_SIZEOF_VTABLE (sizeof (MonoVTable) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P) -#define MONO_VTABLE_IMPLEMENTS_INTERFACE(vt,uiid) (((uiid) <= (vt)->max_interface_id) && mono_class_interface_match ((vt)->interface_bitmap, (uiid))) +#define MONO_VTABLE_IMPLEMENTS_INTERFACE(vt,uiid) (((uiid) <= (vt)->max_interface_id) && (mono_opt_compressed_interface_bitmap ? mono_class_interface_match_compressed ((vt)->interface_bitmap, (uiid)) : mono_class_interface_match ((vt)->interface_bitmap, (uiid)))) /* * Generic instantiation data type encoding. diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index 4883f05f400786..b4a86602079c13 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -56,8 +56,7 @@ print_implemented_interfaces (MonoClass *klass) printf ("(%d,F)", i); printf ("\n"); printf ("Dump interface flags:"); -#ifdef COMPRESSED_INTERFACE_BITMAP - { + if (mono_opt_compressed_interface_bitmap) { const uint8_t* p = klass->interface_bitmap; guint32 i = klass->max_interface_id; while (i > 0) { @@ -65,11 +64,10 @@ print_implemented_interfaces (MonoClass *klass) i -= p [0] * 8; i -= 8; } + } else { + for (guint32 i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7) ? 1 : 0)); i++) + printf (" %02X", klass->interface_bitmap [i]); } -#else - for (guint32 i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++) - printf (" %02X", klass->interface_bitmap [i]); -#endif printf ("\n"); while (klass != NULL) { printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name); @@ -329,11 +327,12 @@ mono_class_setup_interface_offsets_internal (MonoClass *klass, int cur_slot, int klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count); } bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0); -#ifdef COMPRESSED_INTERFACE_BITMAP - bitmap = g_malloc0 (bsize); -#else - bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize); -#endif + + if (mono_opt_compressed_interface_bitmap) + bitmap = g_malloc0 (bsize); + else + bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize); + for (int i = 0; i < interface_offsets_count; i++) { guint32 id = interfaces_full [i]->interface_id; bitmap [id >> 3] |= (1 << (id & 7)); @@ -343,16 +342,16 @@ mono_class_setup_interface_offsets_internal (MonoClass *klass, int cur_slot, int } } if (!klass->interface_bitmap) { -#ifdef COMPRESSED_INTERFACE_BITMAP - int len = mono_compress_bitmap (NULL, bitmap, bsize); - uint8_t *compressed_bitmap = mono_class_alloc0 (klass, len); - mono_compress_bitmap (compressed_bitmap, bitmap, bsize); - g_free (bitmap); + if (mono_opt_compressed_interface_bitmap) { + int len = mono_compress_bitmap (NULL, bitmap, bsize); + uint8_t *compressed_bitmap = mono_class_alloc0 (klass, len); + mono_compress_bitmap (compressed_bitmap, bitmap, bsize); + g_free (bitmap); - klass->interface_bitmap = compressed_bitmap; -#else - klass->interface_bitmap = bitmap; -#endif + klass->interface_bitmap = compressed_bitmap; + } else { + klass->interface_bitmap = bitmap; + } } } end: diff --git a/src/mono/mono/metadata/jit-icall-reg.h b/src/mono/mono/metadata/jit-icall-reg.h index e412fdd5448dca..4353840f66b939 100644 --- a/src/mono/mono/metadata/jit-icall-reg.h +++ b/src/mono/mono/metadata/jit-icall-reg.h @@ -162,7 +162,7 @@ MONO_JIT_ICALL (mono_break) \ MONO_JIT_ICALL (mono_byvalarray_to_byte_array) \ MONO_JIT_ICALL (mono_chkstk_win64) \ MONO_JIT_ICALL (mono_ckfinite) \ -MONO_JIT_ICALL (mono_class_interface_match) \ +MONO_JIT_ICALL (mono_class_interface_match_compressed) \ MONO_JIT_ICALL (mono_class_static_field_address) \ MONO_JIT_ICALL (mono_compile_method_icall) \ MONO_JIT_ICALL (mono_context_get_icall) \ diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index f9aa95467519f9..258ebfd09d54f6 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -4860,11 +4860,8 @@ get_virtual_stelemref_kind (MonoClass *element_class) /* Compressed interface bitmaps require code that is quite complex, so don't optimize for it. */ if (MONO_CLASS_IS_INTERFACE_INTERNAL (element_class) && !mono_class_has_variant_generic_params (element_class)) -#ifdef COMPRESSED_INTERFACE_BITMAP - return STELEMREF_COMPLEX; -#else - return STELEMREF_INTERFACE; -#endif + return mono_opt_compressed_interface_bitmap ? STELEMREF_COMPLEX : STELEMREF_INTERFACE; + /*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/ if (m_class_get_rank (element_class) || mono_class_has_variant_generic_params (element_class)) return STELEMREF_COMPLEX; diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 8a96c1ead4c337..698c9581d6245d 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -1975,6 +1975,15 @@ mono_metadata_init (void) g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]); mono_metadata_update_init (); + + char *compressed_bmap = g_getenv ("MONO_COMPRESSED_INTERFACE_BITMAP"); + if (compressed_bmap) { + if (compressed_bmap [0] == '1') + mono_opt_compressed_interface_bitmap = TRUE; + else if (compressed_bmap [0] == '0') + mono_opt_compressed_interface_bitmap = FALSE; + g_free (compressed_bmap); + } } /* diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index df45813a2e30d0..e65557514ce337 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -15120,6 +15120,9 @@ aot_assembly (MonoAssembly *ass, guint32 jit_opts, MonoAotOptions *aot_options) acfg->is_full_aot = TRUE; } + if (mono_opt_compressed_interface_bitmap) + acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_COMPRESSED_INTERFACE_BITMAP); + if (mini_safepoints_enabled ()) acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_SAFEPOINTS); diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 11c8888d17b038..8ce917fb79b9aa 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -1631,7 +1631,7 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, guint8 *blob, char char *build_info; char *msg = NULL; gboolean usable = TRUE; - gboolean full_aot, interp, safepoints; + gboolean full_aot, interp, safepoints, compressed_interface_bmap; guint32 excluded_cpu_optimizations; if (strcmp (assembly->image->guid, (const char*)info->assembly_guid)) { @@ -1713,6 +1713,13 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, guint8 *blob, char } #endif + compressed_interface_bmap = info->flags & MONO_AOT_FILE_FLAG_COMPRESSED_INTERFACE_BITMAP; + if ((mono_opt_compressed_interface_bitmap && !compressed_interface_bmap) || + (!mono_opt_compressed_interface_bitmap && compressed_interface_bmap)) { + msg = g_strdup ("mismatch with compressed interface bitmap feature"); + usable = FALSE; + } + *out_msg = msg; return usable; } diff --git a/src/mono/mono/mini/aot-runtime.h b/src/mono/mono/mini/aot-runtime.h index 13690e31904d4a..706cde519ecf62 100644 --- a/src/mono/mono/mini/aot-runtime.h +++ b/src/mono/mono/mini/aot-runtime.h @@ -11,7 +11,7 @@ #include "mini.h" /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 186 +#define MONO_AOT_FILE_VERSION 187 #define MONO_AOT_TRAMP_PAGE_SIZE 16384 @@ -74,7 +74,8 @@ typedef enum { MONO_AOT_FILE_FLAG_SEPARATE_DATA = 64, MONO_AOT_FILE_FLAG_EAGER_LOAD = 128, MONO_AOT_FILE_FLAG_INTERP = 256, - MONO_AOT_FILE_FLAG_CODE_EXEC_ONLY = 512 + MONO_AOT_FILE_FLAG_CODE_EXEC_ONLY = 512, + MONO_AOT_FILE_FLAG_COMPRESSED_INTERFACE_BITMAP = 1024 } MonoAotFileFlags; typedef enum { diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index bcd7754da660a6..14d235bd2cd0a5 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -5091,9 +5091,9 @@ register_icalls (void) #endif register_icall (mono_ckfinite, mono_icall_sig_double_double, FALSE); -#ifdef COMPRESSED_INTERFACE_BITMAP - register_icall (mono_class_interface_match, mono_icall_sig_uint32_ptr_int32, TRUE); -#endif + // opt is initialized because mono_metadata_init is ran before this + if (mono_opt_compressed_interface_bitmap) + register_icall (mono_class_interface_match_compressed, mono_icall_sig_uint32_ptr_int32, TRUE); /* other jit icalls */ register_icall (ves_icall_mono_delegate_ctor, mono_icall_sig_void_object_object_ptr, FALSE); diff --git a/src/mono/mono/mini/type-checking.c b/src/mono/mono/mini/type-checking.c index 5237fdfabc2382..4fad4d00622c4c 100644 --- a/src/mono/mono/mini/type-checking.c +++ b/src/mono/mono/mini/type-checking.c @@ -133,40 +133,41 @@ static void mini_emit_interface_bitmap_check (MonoCompile *cfg, int intf_bit_reg, int base_reg, intptr_t offset, MonoClass *klass) { int ibitmap_reg = alloc_preg (cfg); -#ifdef COMPRESSED_INTERFACE_BITMAP - MonoInst *args [2]; - MonoInst *res, *ins; - NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, ibitmap_reg, base_reg, (target_mgreg_t)offset); - MONO_ADD_INS (cfg->cbb, ins); - args [0] = ins; - args [1] = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_IID, klass); - res = mono_emit_jit_icall (cfg, mono_class_interface_match, args); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, intf_bit_reg, res->dreg); -#else - int ibitmap_byte_reg = alloc_preg (cfg); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ibitmap_reg, base_reg, GINTPTR_TO_TMREG (offset)); - if (cfg->compile_aot) { - int iid_reg = alloc_preg (cfg); - int shifted_iid_reg = alloc_preg (cfg); - int ibitmap_byte_address_reg = alloc_preg (cfg); - int masked_iid_reg = alloc_preg (cfg); - int iid_one_bit_reg = alloc_preg (cfg); - int iid_bit_reg = alloc_preg (cfg); - MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, MONO_PATCH_INFO_IID); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, shifted_iid_reg, iid_reg, 3); - MONO_EMIT_NEW_BIALU (cfg, OP_PADD, ibitmap_byte_address_reg, ibitmap_reg, shifted_iid_reg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, ibitmap_byte_reg, ibitmap_byte_address_reg, 0); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, masked_iid_reg, iid_reg, 7); - MONO_EMIT_NEW_ICONST (cfg, iid_one_bit_reg, 1); - MONO_EMIT_NEW_BIALU (cfg, OP_ISHL, iid_bit_reg, iid_one_bit_reg, masked_iid_reg); - MONO_EMIT_NEW_BIALU (cfg, OP_IAND, intf_bit_reg, ibitmap_byte_reg, iid_bit_reg); + if (mono_opt_compressed_interface_bitmap) { + MonoInst *args [2]; + MonoInst *res, *ins; + NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, ibitmap_reg, base_reg, (target_mgreg_t)offset); + MONO_ADD_INS (cfg->cbb, ins); + args [0] = ins; + args [1] = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_IID, klass); + res = mono_emit_jit_icall (cfg, mono_class_interface_match_compressed, args); + MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, intf_bit_reg, res->dreg); } else { - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, ibitmap_byte_reg, ibitmap_reg, m_class_get_interface_id (klass) >> 3); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, intf_bit_reg, ibitmap_byte_reg, ((target_mgreg_t)1) << (m_class_get_interface_id (klass) & 7)); + int ibitmap_byte_reg = alloc_preg (cfg); + + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ibitmap_reg, base_reg, GINTPTR_TO_TMREG (offset)); + + if (cfg->compile_aot) { + int iid_reg = alloc_preg (cfg); + int shifted_iid_reg = alloc_preg (cfg); + int ibitmap_byte_address_reg = alloc_preg (cfg); + int masked_iid_reg = alloc_preg (cfg); + int iid_one_bit_reg = alloc_preg (cfg); + int iid_bit_reg = alloc_preg (cfg); + MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, MONO_PATCH_INFO_IID); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, shifted_iid_reg, iid_reg, 3); + MONO_EMIT_NEW_BIALU (cfg, OP_PADD, ibitmap_byte_address_reg, ibitmap_reg, shifted_iid_reg); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, ibitmap_byte_reg, ibitmap_byte_address_reg, 0); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, masked_iid_reg, iid_reg, 7); + MONO_EMIT_NEW_ICONST (cfg, iid_one_bit_reg, 1); + MONO_EMIT_NEW_BIALU (cfg, OP_ISHL, iid_bit_reg, iid_one_bit_reg, masked_iid_reg); + MONO_EMIT_NEW_BIALU (cfg, OP_IAND, intf_bit_reg, ibitmap_byte_reg, iid_bit_reg); + } else { + MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, ibitmap_byte_reg, ibitmap_reg, m_class_get_interface_id (klass) >> 3); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, intf_bit_reg, ibitmap_byte_reg, ((target_mgreg_t)1) << (m_class_get_interface_id (klass) & 7)); + } } -#endif } /* diff --git a/src/mono/mono/utils/options-def.h b/src/mono/mono/utils/options-def.h index 7c1b2c3ff06ee8..1e70f507e13ba8 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -183,6 +183,8 @@ DEFINE_BOOL_READONLY(experimental_gshared_mrgctx, "experimental-gshared-mrgctx", DEFINE_BOOL(experimental_gshared_mrgctx, "experimental-gshared-mrgctx", FALSE, "Use a mrgctx for all gshared methods") #endif +DEFINE_BOOL(compressed_interface_bitmap, "compressed-interface-bitmap", FALSE, "Use compressed bitmap for storing implemented interfaces in vtables and classes") + #if defined(TARGET_WASI) DEFINE_BOOL_READONLY(llvm_emulate_unwind, "emulate-unwind", TRUE, "") #else