gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) { if (aot) NOT_IMPLEMENTED; gboolean is_mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); int index = MONO_RGCTX_SLOT_INDEX (slot); if (is_mrgctx) index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (target_mgreg_t); int depth; for (depth = 0; ; depth++) { int size = mono_class_rgctx_get_array_size (depth, is_mrgctx); if (index < size - 1) break; index -= size - 1; } guint8 *buf = mono_global_codeman_reserve (128 * depth), *code = buf; guint8 **null_jumps = g_malloc0 (sizeof (guint8 *) * (depth + 2)); if (!is_mrgctx) { } else riscv_addi (code, RISCV_T1, RISCV_A0, 0); mono_arch_flush_icache (buf, code - buf); if (info) { char *name = mono_get_rgctx_fetch_trampoline_name (slot); *info = mono_tramp_info_create (name, buf, code - buf, NULL, NULL); g_free (name); } return buf; }
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) { #ifdef MONO_ARCH_VTABLE_REG guint8 *tramp; guint8 *code, *buf; guint8 **rgctx_null_jumps; gint32 displace; int tramp_size, depth, index, iPatch = 0, i; gboolean mrgctx; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); index = MONO_RGCTX_SLOT_INDEX (slot); if (mrgctx) index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer); for (depth = 0; ; ++depth) { int size = mono_class_rgctx_get_array_size (depth, mrgctx); if (index < size - 1) break; index -= size - 1; } tramp_size = 48 + 16 * depth; if (mrgctx) tramp_size += 4; else tramp_size += 12; code = buf = mono_global_codeman_reserve (tramp_size); unwind_ops = mono_arch_get_cie_program (); rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2)); if (mrgctx) { /* get mrgctx ptr */ s390_lgr (code, s390_r1, s390_r2); } else { /* load rgctx ptr from vtable */ s390_lg (code, s390_r1, 0, s390_r2, G_STRUCT_OFFSET(MonoVTable, runtime_generic_context)); /* is the rgctx ptr null? */ s390_ltgr (code, s390_r1, s390_r1); /* if yes, jump to actual trampoline */ rgctx_null_jumps [iPatch++] = code; s390_jge (code, 0); } for (i = 0; i < depth; ++i) { /* load ptr to next array */ if (mrgctx && i == 0) s390_lg (code, s390_r1, 0, s390_r1, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT); else s390_lg (code, s390_r1, 0, s390_r1, 0); s390_ltgr (code, s390_r1, s390_r1); /* if the ptr is null then jump to actual trampoline */ rgctx_null_jumps [iPatch++] = code; s390_jge (code, 0); } /* fetch slot */ s390_lg (code, s390_r1, 0, s390_r1, (sizeof (gpointer) * (index + 1))); /* is the slot null? */ s390_ltgr (code, s390_r1, s390_r1); /* if yes, jump to actual trampoline */ rgctx_null_jumps [iPatch++] = code; s390_jge (code, 0); /* otherwise return r1 */ s390_lgr (code, s390_r2, s390_r1); s390_br (code, s390_r14); for (i = 0; i < iPatch; i++) { displace = ((uintptr_t) code - (uintptr_t) rgctx_null_jumps[i]) / 2; s390_patch_rel ((rgctx_null_jumps [i] + 2), displace); } g_free (rgctx_null_jumps); /* move the rgctx pointer to the VTABLE register */ s390_lgr (code, MONO_ARCH_VTABLE_REG, s390_r2); tramp = mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL); /* jump to the actual trampoline */ displace = (tramp - code) / 2; s390_jg (code, displace); mono_arch_flush_icache (buf, code - buf); g_assert (code - buf <= tramp_size); if (info) { char *name = mono_get_rgctx_fetch_trampoline_name (slot); *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops); g_free (name); } return(buf); #else g_assert_not_reached (); #endif return(NULL); }
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) { guint8 *tramp; guint8 *code, *buf; guint8 **rgctx_null_jumps; int tramp_size; int depth, index; int i; gboolean mrgctx; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; unwind_ops = mono_arch_get_cie_program (); mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot); index = MONO_RGCTX_SLOT_INDEX (slot); if (mrgctx) index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (target_mgreg_t); for (depth = 0; ; ++depth) { int size = mono_class_rgctx_get_array_size (depth, mrgctx); if (index < size - 1) break; index -= size - 1; } tramp_size = (aot ? 64 : 36) + 6 * depth; code = buf = mono_global_codeman_reserve (tramp_size); rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2)); /* load vtable/mrgctx ptr */ x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4); if (!mrgctx) { /* load rgctx ptr from vtable */ x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context), 4); /* is the rgctx ptr null? */ x86_test_reg_reg (code, X86_EAX, X86_EAX); /* if yes, jump to actual trampoline */ rgctx_null_jumps [0] = code; x86_branch8 (code, X86_CC_Z, -1, 1); } for (i = 0; i < depth; ++i) { /* load ptr to next array */ if (mrgctx && i == 0) x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 4); else x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, 4); /* is the ptr null? */ x86_test_reg_reg (code, X86_EAX, X86_EAX); /* if yes, jump to actual trampoline */ rgctx_null_jumps [i + 1] = code; x86_branch8 (code, X86_CC_Z, -1, 1); } /* fetch slot */ x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (target_mgreg_t) * (index + 1), 4); /* is the slot null? */ x86_test_reg_reg (code, X86_EAX, X86_EAX); /* if yes, jump to actual trampoline */ rgctx_null_jumps [depth + 1] = code; x86_branch8 (code, X86_CC_Z, -1, 1); /* otherwise return */ x86_ret (code); for (i = mrgctx ? 1 : 0; i <= depth + 1; ++i) x86_patch (rgctx_null_jumps [i], code); g_free (rgctx_null_jumps); x86_mov_reg_membase (code, MONO_ARCH_VTABLE_REG, X86_ESP, 4, 4); if (aot) { code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR, GUINT_TO_POINTER (slot)); x86_jump_reg (code, X86_EAX); } else { tramp = (guint8*)mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL); /* jump to the actual trampoline */ x86_jump_code (code, tramp); } mono_arch_flush_icache (buf, code - buf); MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL)); g_assert (code - buf <= tramp_size); char *name = mono_get_rgctx_fetch_trampoline_name (slot); *info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops); g_free (name); return buf; }