X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-arm.c;h=88f103aaf9ea1bf9fd5a70074c6c4708d54b2259;hb=6789c06f31a98a01ea5fc766f341d0dcf1938205;hp=bcfced8d20b359a594dc362a291e6854a0c6e786;hpb=217ddc29c40bc8b11f8fbd4800e61db7f4f22bbf;p=mono.git diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c index bcfced8d20b..88f103aaf9e 100644 --- a/mono/mini/tramp-arm.c +++ b/mono/mini/tramp-arm.c @@ -60,9 +60,7 @@ mono_arch_get_unbox_trampoline (MonoGenericSharingContext *gsctx, MonoMethod *m, if (MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret)) this_pos = 1; - mono_domain_lock (domain); - start = code = mono_code_manager_reserve (domain->code_mp, 16); - mono_domain_unlock (domain); + start = code = mono_domain_code_reserve (domain, 16); ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 4); ARM_ADD_REG_IMM8 (code, this_pos, this_pos, sizeof (MonoObject)); @@ -77,6 +75,32 @@ mono_arch_get_unbox_trampoline (MonoGenericSharingContext *gsctx, MonoMethod *m, return start; } +gpointer +mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr) +{ + guint8 *code, *start; + int buf_len; + + MonoDomain *domain = mono_domain_get (); + + buf_len = 16; + + start = code = mono_domain_code_reserve (domain, buf_len); + + ARM_LDR_IMM (code, MONO_ARCH_RGCTX_REG, ARMREG_PC, 0); + ARM_LDR_IMM (code, ARMREG_PC, ARMREG_PC, 0); + *(guint32*)code = (guint32)mrgctx; + code += 4; + *(guint32*)code = (guint32)addr; + code += 4; + + g_assert ((code - start) <= buf_len); + + mono_arch_flush_icache (start, code - start); + + return start; +} + void mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) { @@ -154,16 +178,28 @@ mono_arch_create_trampoline_code (MonoTrampolineType tramp_type) { MonoJumpInfo *ji; guint32 code_size; + guchar *code; + GSList *unwind_ops, *l; + + code = mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, &unwind_ops, FALSE); - return mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, FALSE); + mono_save_trampoline_xdebug_info ("", code, code_size, unwind_ops); + + for (l = unwind_ops; l; l = l->next) + g_free (l->data); + g_slist_free (unwind_ops); + + return code; } guchar* -mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *code_size, MonoJumpInfo **ji, gboolean aot) +mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *code_size, MonoJumpInfo **ji, GSList **out_unwind_ops, gboolean aot) { guint8 *buf, *code = NULL; guint8 *load_get_lmf_addr, *load_trampoline; gpointer *constants; + GSList *unwind_ops = NULL; + int cfa_offset; *ji = NULL; @@ -178,13 +214,25 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c * saved as sp + LR_OFFSET by the push in the specific trampoline */ #define LR_OFFSET (sizeof (gpointer) * 13) + + // FIXME: Finish the unwind info, the current info allows us to unwind + // when the trampoline is not in the epilog + + // CFA = SP + (num registers pushed) * 4 + cfa_offset = 14 * sizeof (gpointer); + mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, cfa_offset); + // PC saved at sp+LR_OFFSET + mono_add_unwind_op_offset (unwind_ops, code, buf, ARMREG_LR, -4); + ARM_MOV_REG_REG (code, ARMREG_V1, ARMREG_SP); if (aot && tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) { /* - * The trampoline contains a pc-relative offset to the got slot where the - * value is stored. The offset can be found at [lr + 4]. + * The trampoline contains a pc-relative offset to the got slot + * preceeding the got slot where the value is stored. The offset can be + * found at [lr + 0]. */ - ARM_LDR_IMM (code, ARMREG_V2, ARMREG_LR, 4); + ARM_LDR_IMM (code, ARMREG_V2, ARMREG_LR, 0); + ARM_ADD_REG_IMM (code, ARMREG_V2, ARMREG_V2, 4, 0); ARM_LDR_REG_REG (code, ARMREG_V2, ARMREG_V2, ARMREG_LR); } else { if (tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) @@ -217,6 +265,8 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c * the iregs array is already allocated on the stack by push. */ ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, sizeof (MonoLMF) - sizeof (guint) * 14); + cfa_offset += sizeof (MonoLMF) - sizeof (guint) * 14; + mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset); ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_SP, STACK - sizeof (MonoLMF)); /* r0 is the result from mono_get_lmf_addr () */ ARM_STR_IMM (code, ARMREG_R0, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, lmf_addr)); @@ -343,7 +393,7 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c code += 8; /* Flush instruction cache, since we've generated code */ - mono_arch_flush_icache (code, code - buf); + mono_arch_flush_icache (buf, code - buf); /* Sanity check */ g_assert ((code - buf) <= GEN_TRAMP_SIZE); @@ -357,6 +407,8 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (&code_len); } + *out_unwind_ops = unwind_ops; + return buf; } @@ -369,7 +421,7 @@ mono_arch_get_nullified_class_init_trampoline (guint32 *code_len) ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_LR); - mono_arch_flush_icache (code, code - buf); + mono_arch_flush_icache (buf, code - buf); *code_len = code - buf; @@ -388,10 +440,10 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty tramp = mono_get_trampoline_code (tramp_type); mono_domain_lock (domain); - code = buf = mono_code_manager_reserve_align (domain->code_mp, size, 4); + code = buf = mono_domain_code_reserve_align (domain, size, 4); if ((short_branch = branch_for_target_reachable (code + 8, tramp))) { size = 12; - mono_code_manager_commit (domain->code_mp, code, SPEC_TRAMP_SIZE, size); + mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size); } mono_domain_unlock (domain); @@ -426,7 +478,7 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty } /* Flush instruction cache, since we've generated code */ - mono_arch_flush_icache (code, code - buf); + mono_arch_flush_icache (buf, code - buf); g_assert ((code - buf) <= size); @@ -547,7 +599,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline_full (guint32 slot, guint32 *code_s /* Jump to the actual trampoline */ ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */ ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1); - *(guint32*)code = tramp; + *(gpointer*)code = tramp; code += 4; } @@ -564,6 +616,15 @@ mono_arch_create_rgctx_lazy_fetch_trampoline_full (guint32 slot, guint32 *code_s gpointer mono_arch_create_generic_class_init_trampoline (void) +{ + guint32 code_size; + MonoJumpInfo *ji; + + return mono_arch_create_generic_class_init_trampoline_full (&code_size, &ji, FALSE); +} + +gpointer +mono_arch_create_generic_class_init_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) { guint8 *tramp; guint8 *code, *buf; @@ -574,6 +635,8 @@ mono_arch_create_generic_class_init_trampoline (void) guint32 code_len, imm8; gint rot_amount; + *ji = NULL; + tramp_size = 64; code = buf = mono_global_codeman_reserve (tramp_size); @@ -596,17 +659,28 @@ mono_arch_create_generic_class_init_trampoline (void) /* Uninitialized case */ arm_patch (jump, code); - tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), &code_len); + if (aot) { + *ji = mono_patch_info_list_prepend (*ji, code - buf, MONO_PATCH_INFO_JIT_ICALL_ADDR, "specific_trampoline_generic_class_init"); + ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); + ARM_B (code, 0); + *(gpointer*)code = NULL; + code += 4; + ARM_LDR_REG_REG (code, ARMREG_PC, ARMREG_PC, ARMREG_R1); + } else { + tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), &code_len); - /* Jump to the actual trampoline */ - ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */ - ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1); - *(guint32*)code = tramp; - code += 4; + /* Jump to the actual trampoline */ + ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */ + ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1); + *(gpointer*)code = tramp; + code += 4; + } mono_arch_flush_icache (buf, code - buf); g_assert (code - buf <= tramp_size); + *code_size = code - buf; + return buf; }