From 65bc7f05277bf67c8219eda5ed59b519dcef3439 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 52f108fc7cc9a0..feb62a97475703 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -1762,7 +1762,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; @@ -1776,7 +1776,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 ba56a62ad6b818..2eab8f4a7045cf 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 618e6b05019abe..2d0a245e033be0 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -346,10 +346,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 6f453f88610ff4..41b0f2c0054e5a 100644 --- a/src/mono/mono/mini/type-checking.c +++ b/src/mono/mono/mini/type-checking.c @@ -137,7 +137,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 c70b284c46cf4b5b0b29de8b9ba343837c47767f 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 feb62a97475703..348883da0ad715 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -1706,8 +1706,6 @@ mono_class_setup_count_virtual_methods (MonoClass *klass) return vcount; } -#ifdef COMPRESSED_INTERFACE_BITMAP - /* * Compressed interface bitmap design. * @@ -1797,7 +1795,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; @@ -1810,7 +1808,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 2eab8f4a7045cf..e439368454dc0b 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 2d0a245e033be0..144abac0e508fd 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); @@ -331,11 +329,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)); @@ -345,16 +344,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 8c849752f42a90..c58a320f89ab5b 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 e6d7f80d8e7365..9a14986eda883d 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 9a932fe84c7888..181466118222a4 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 7800c04959b57c..5349e634ed9684 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -15107,6 +15107,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 1f2da3264b2601..8822b06f822eb4 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 468534bc16ba41..7cf63847ff61b9 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -5080,9 +5080,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 41b0f2c0054e5a..9921df2ef4328e 100644 --- a/src/mono/mono/mini/type-checking.c +++ b/src/mono/mono/mini/type-checking.c @@ -134,40 +134,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 2397b3dd4ede3a..5f865543d175d2 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -180,6 +180,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