[arm] Implement handler block guards.
authorZoltan Varga <vargaz@gmail.com>
Fri, 3 Oct 2014 00:35:42 +0000 (20:35 -0400)
committerZoltan Varga <vargaz@gmail.com>
Fri, 3 Oct 2014 00:35:42 +0000 (20:35 -0400)
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/tramp-arm.c

index b644d7dca7a0ab20b6d2d6150c1de81cae6c66f4..9491a442d1a6f74175524297201d62292322bda8 100644 (file)
@@ -6929,6 +6929,26 @@ mono_arch_get_trampolines (gboolean aot)
        return mono_arm_get_exception_trampolines (aot);
 }
 
+gpointer
+mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, MonoContext *ctx, gpointer new_value)
+{
+       gpointer *lr_loc;
+       char *old_value;
+       char *bp;
+
+       /*Load the spvar*/
+       bp = MONO_CONTEXT_GET_BP (ctx);
+       lr_loc = (gpointer*)(bp + clause->exvar_offset);
+
+       old_value = *lr_loc;
+       if ((char*)old_value < (char*)ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
+               return old_value;
+
+       *lr_loc = new_value;
+
+       return old_value;
+}
+
 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED)
 /*
  * mono_arch_set_breakpoint:
index 75a8ad9d5262da6517540c01d3e7f561fbb8ba6d..0e7061c35d5b733ade63fd89a664f99ee161437a 100644 (file)
@@ -283,6 +283,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_GC_MAPS_SUPPORTED 1
 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
+#define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
 #define MONO_ARCH_GSHAREDVT_SUPPORTED 1
 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE 1
index bb500a7c0f505c954834f36b68c97deb7a424337..f9e651093b46e07958d0068840b5361de5487998 100644 (file)
@@ -505,17 +505,21 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 
        tramp = mono_get_trampoline_code (tramp_type);
 
-       mono_domain_lock (domain);
+       if (domain) {
+               mono_domain_lock (domain);
 #ifdef USE_JUMP_TABLES
-       code = buf = mono_domain_code_reserve_align (domain, size, 4);
+               code = buf = mono_domain_code_reserve_align (domain, size, 4);
 #else
-       code = buf = mono_domain_code_reserve_align (domain, size, 4);
-       if ((short_branch = branch_for_target_reachable (code + 4, tramp))) {
-               size = 12;
-               mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size);
+               code = buf = mono_domain_code_reserve_align (domain, size, 4);
+               if ((short_branch = branch_for_target_reachable (code + 4, tramp))) {
+                       size = 12;
+                       mono_domain_code_commit (domain, code, SPEC_TRAMP_SIZE, size);
        }
 #endif
-       mono_domain_unlock (domain);
+               mono_domain_unlock (domain);
+       } else {
+               code = buf = mono_global_codeman_reserve (size);
+       }
 
 #ifdef USE_JUMP_TABLES
        /* For jumptables case we always generate the same code for trampolines,
@@ -894,6 +898,59 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a
        return buf;
 }
 
+static gpointer
+handler_block_trampoline_helper (gpointer *ptr)
+{
+       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       return jit_tls->handler_block_return_address;
+}
+
+gpointer
+mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       guint8 *tramp;
+       guint8 *code, *buf;
+       int tramp_size = 64;
+       MonoJumpInfo *ji = NULL;
+       GSList *unwind_ops = NULL;
+
+       g_assert (!aot);
+
+       code = buf = mono_global_codeman_reserve (tramp_size);
+
+       tramp = mono_arch_create_specific_trampoline (NULL, MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD, NULL, NULL);
+
+       /*
+       This trampoline restore the call chain of the handler block then jumps into the code that deals with it.
+       */
+
+       /*
+        * We are in a method frame after the call emitted by OP_CALL_HANDLER.
+        */
+       /* Obtain jit_tls->handler_block_return_address */
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
+       ARM_B (code, 0);
+       *(gpointer*)code = handler_block_trampoline_helper;
+       code += 4;
+
+       /* Set it as the return address so the trampoline will return to it */
+       ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_R0);
+
+       /* Call the trampoline */
+       ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
+       code = emit_bx (code, ARMREG_R0);
+       *(gpointer*)code = tramp;
+       code += 4;
+
+       mono_arch_flush_icache (buf, code - buf);
+       g_assert (code - buf <= tramp_size);
+
+       if (info)
+               *info = mono_tramp_info_create ("handler_block_trampoline", buf, code - buf, ji, unwind_ops);
+
+       return buf;
+}
+
 #else
 
 guchar*
@@ -944,6 +1001,13 @@ mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info)
        g_assert_not_reached ();
        return NULL;
 }
+
+gpointer
+mono_arch_create_handler_block_trampoline (MonoTrampInfo **info, gboolean aot)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
        
 #endif /* DISABLE_JIT */