2008-07-12 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Fri, 11 Jul 2008 22:20:41 +0000 (22:20 -0000)
committerZoltan Varga <vargaz@gmail.com>
Fri, 11 Jul 2008 22:20:41 +0000 (22:20 -0000)
* exceptions-arm.c (mono_arch_get_call_filter_full): Initialize ji.

* aot-runtime.c (mono_aot_get_plt_info_offset): New helper function to
return the plt info offset belonging to a given plt entry.

* mini-trampolines.c (mono_aot_plt_trampoline): Use
mono_aot_get_plt_info_offset.

* aot-runtime.c aot-compiler.c tramp-arm.c: Change the arm plt code to be
similar to the amd64 code by makeing jumps through a separate jump table
instead of embedding the jump addresses into the code.

svn path=/trunk/mono/; revision=107764

mono/mini/ChangeLog
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/exceptions-arm.c
mono/mini/mini-arm.h
mono/mini/mini-trampolines.c
mono/mini/mini.h
mono/mini/tramp-arm.c

index f978dd5d3fb91c26d44339945d1c7da015ef09eb..b7bf76cfb3a6e02d6802137e70450c1bb2f5f71f 100644 (file)
@@ -1,3 +1,17 @@
+2008-07-12  Zoltan Varga  <vargaz@gmail.com>
+
+       * exceptions-arm.c (mono_arch_get_call_filter_full): Initialize ji.
+
+       * aot-runtime.c (mono_aot_get_plt_info_offset): New helper function to
+       return the plt info offset belonging to a given plt entry.
+
+       * mini-trampolines.c (mono_aot_plt_trampoline): Use 
+       mono_aot_get_plt_info_offset.
+       
+       * aot-runtime.c aot-compiler.c tramp-arm.c: Change the arm plt code to be
+       similar to the amd64 code by makeing jumps through a separate jump table 
+       instead of embedding the jump addresses into the code.
+
 2008-07-11  Zoltan Varga  <vargaz@gmail.com>
 
        * mini.c (mono_method_to_ir): Disable aot for calling ldtoken in a generic
index 20abcd7a9fadd9194daffe60316f9fc145b6250e..d45b1dcc2b4f834a6e323cbf9d736579d4a53e9a 100644 (file)
@@ -2684,6 +2684,7 @@ emit_plt (MonoAotCompile *acfg)
        g_assert_not_reached ();
 #endif
 
+#if 0
        /* 
         * The first plt entry is used to transfer code to the AOT loader. 
         */
@@ -2699,27 +2700,55 @@ emit_plt (MonoAotCompile *acfg)
        emit_symbol_diff (acfg, "plt_jump_table", ".", -4);
        emit_zero_bytes (acfg, 10);
 #elif defined(__arm__)
-       /* This is 8 bytes long, init_plt () depends on this */
-       emit_unset_mode (acfg);
-       fprintf (acfg->fp, "\tldr pc, [pc, #-4]\n");
-       /* This is filled up during loading by the AOT loader */
-       fprintf (acfg->fp, "\t.word 0\n");
+       if (1 || acfg->aot_opts.full_aot) {
+               /* Generate non-patchable code */
+               /* FIXME: Use this for the non-aot-only case as well */
+               emit_unset_mode (acfg);
+               fprintf (acfg->fp, "\tldr ip, [pc, #4]\n");
+               fprintf (acfg->fp, "\tadd ip, pc, ip\n");
+               fprintf (acfg->fp, "\tldr pc, [ip, #0]\n");
+               emit_symbol_diff (acfg, "plt_jump_table", ".", 4);
+
+               /* Default entry */
+               /* This is 12 bytes long, init_plt () depends on this */
+               emit_unset_mode (acfg);
+               fprintf (acfg->fp, "\tldr ip, [pc, #0]\n");
+               fprintf (acfg->fp, "\tb .Lp_0\n");
+               fprintf (acfg->fp, "\t.word %d\n", plt_info_offsets [i]);
+       } else {
+               /* This is 8 bytes long, init_plt () depends on this */
+               emit_unset_mode (acfg);
+               fprintf (acfg->fp, "\tldr pc, [pc, #-4]\n");
+               /* This is filled up during loading by the AOT loader */
+               fprintf (acfg->fp, "\t.word 0\n");
+       }
 #else
        g_assert_not_reached ();
+#endif
 #endif
 
-       for (i = 1; i < acfg->plt_offset; ++i) {
+       for (i = 0; i < acfg->plt_offset; ++i) {
                char *label;
 
                label = g_strdup_printf (".Lp_%d", i);
                emit_label (acfg, label);
                g_free (label);
+
+               /* 
+                * The first plt entry is used to transfer code to the AOT loader. 
+                */
+
 #if defined(__i386__)
-               /* Need to make sure this is 5 bytes long */
-               emit_byte (acfg, '\xe9');
-               label = g_strdup_printf (".Lpd_%d", i);
-               emit_symbol_diff (acfg, label, ".", -4);
-               g_free (label);
+               if (i == 0) {
+                       /* It is filled up during loading by the AOT loader. */
+                       emit_zero_bytes (acfg, 16);
+               } else {
+                       /* Need to make sure this is 5 bytes long */
+                       emit_byte (acfg, '\xe9');
+                       label = g_strdup_printf (".Lpd_%d", i);
+                       emit_symbol_diff (acfg, label, ".", -4);
+                       g_free (label);
+               }
 #elif defined(__x86_64__)
                /*
                 * We can't emit jumps because they are 32 bits only so they can't be patched.
@@ -2750,11 +2779,21 @@ emit_plt (MonoAotCompile *acfg)
                 * - optimize SWITCH AOT implementation
                 * - implement IMT support
                 */
-               /* This is 8 bytes long, init_plt () depends on this */
-               emit_unset_mode (acfg);
-               fprintf (acfg->fp, "\tldr pc, [pc, #-4]\n");
-               /* This is filled up during loading by the AOT loader */
-               fprintf (acfg->fp, "\t.word 0\n");
+               if (1 || acfg->aot_opts.full_aot) {
+                       emit_unset_mode (acfg);
+                       fprintf (acfg->fp, "\tldr ip, [pc, #4]\n");
+                       fprintf (acfg->fp, "\tadd ip, pc, ip\n");
+                       fprintf (acfg->fp, "\tldr pc, [ip, #0]\n");
+                       emit_symbol_diff (acfg, "plt_jump_table", ".", 0);
+                       /* Used by mono_aot_get_plt_info_offset */
+                       fprintf (acfg->fp, "\n\t.word %d\n", plt_info_offsets [i]);
+               } else {
+                       /* This is 8 bytes long, init_plt () depends on this */
+                       emit_unset_mode (acfg);
+                       fprintf (acfg->fp, "\tldr pc, [pc, #-4]\n");
+                       /* This is filled up during loading by the AOT loader */
+                       fprintf (acfg->fp, "\t.word 0\n");
+               }
 #else
                g_assert_not_reached ();
 #endif
@@ -2786,11 +2825,14 @@ emit_plt (MonoAotCompile *acfg)
 #elif defined(__x86_64__)
                /* Emitted along with the PLT entries since they will not be patched */
 #elif defined(__arm__)
+               /* Emitted along with the PLT entries since they will not be patched */
+#if 0
                /* This is 12 bytes long, init_plt () depends on this */
                emit_unset_mode (acfg);
                fprintf (acfg->fp, "\tldr ip, [pc, #0]\n");
                fprintf (acfg->fp, "\tb .Lp_0\n");
                fprintf (acfg->fp, "\t.word %d\n", plt_info_offsets [i]);
+#endif
 #else
                g_assert_not_reached ();
 #endif
@@ -2824,7 +2866,7 @@ emit_plt (MonoAotCompile *acfg)
        emit_section_change (acfg, ".bss", 0);
        emit_label (acfg, symbol);
 
-#ifdef __x86_64__
+#if defined(__x86_64__) || defined(__arm__)
        emit_zero_bytes (acfg, (int)(acfg->plt_offset * sizeof (gpointer)));
 #endif 
 
index e4bdb68f5f6ad4108c62b053e96458a1ce35bb1e..92e5bc36bcf9b8cd6794c67f731c9d911afef9f1 100644 (file)
@@ -2074,7 +2074,7 @@ init_plt (MonoAotModule *info)
        /* Initialize the first PLT entry */
        make_writable (info->plt, info->plt_end - info->plt);
        x86_jump_code (buf, tramp);
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__arm__)
        /*
         * Initialize the entries in the plt_jump_table to point to the default targets.
         */
@@ -2083,8 +2083,13 @@ init_plt (MonoAotModule *info)
         /* The first entry points to the AOT trampoline */
         ((gpointer*)info->plt_jump_table)[0] = tramp;
         for (i = 1; i < n_entries; ++i)
+#ifdef __arm__
+                /* All the default entries point to the first entry */
+                ((gpointer*)info->plt_jump_table)[i] = info->plt;
+#else
                 /* Each PLT entry is 16 bytes long, the default entry begins at offset 6 */
                 ((gpointer*)info->plt_jump_table)[i] = info->plt + (i * 16) + 6;
+#endif
 #elif defined(__arm__)
         /* Initialize the first PLT entry */
         make_writable (info->plt, info->plt_end - info->plt);
@@ -2150,6 +2155,29 @@ mono_aot_get_plt_entry (guint8 *code)
        return NULL;
 }
 
+/*
+ * mono_aot_get_plt_info_offset:
+ *
+ *   Return the PLT info offset belonging to the plt entry called by CODE.
+ */
+guint32
+mono_aot_get_plt_info_offset (gssize *regs, guint8 *code)
+{
+#if defined(__i386__) || defined(__x86_64__)
+       return regs [MONO_ARCH_AOT_PLT_OFFSET_REG];
+#elif defined(__arm__)
+       guint8 *plt_entry = mono_aot_get_plt_entry (code);
+
+       g_assert (plt_entry);
+
+       /* The offset is stored as the 5th word of the plt entry */
+       return ((guint32*)plt_entry) [4];
+#else
+       g_assert_not_reached ();
+       return NULL;
+#endif
+}
+
 static gpointer
 load_named_code (MonoAotModule *amodule, const char *name)
 {
index 8558fdd6b7e6be0fbd4e7b40ba8eb83ef33a8426..baff79f6062747954d9fbe033c4691c93707e2df 100644 (file)
@@ -155,6 +155,8 @@ mono_arch_get_call_filter_full (guint32 *code_size, MonoJumpInfo **ji, gboolean
        guint8 *code;
        guint8* start;
 
+       *ji = NULL;
+
        /* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */
        start = code = mono_global_codeman_reserve (320);
 
index 10f885b3ad827140b475fcb6994717777b06f907..0dcf8dbe9a5ea6e7fcf0839ef367b8d7b2b0ccbc 100644 (file)
@@ -57,8 +57,6 @@
  * reproduceable results for benchmarks */
 #define MONO_ARCH_CODE_ALIGNMENT 32
 
-#define MONO_ARCH_AOT_PLT_OFFSET_REG ARMREG_IP
-
 void arm_patch (guchar *code, const guchar *target);
 guint8* mono_arm_emit_load_imm (guint8 *code, int dreg, guint32 val);
 
index f9b7848ddced04b5c7c1f14af7f2bb4dad4d2fe0..a3a4d9a8c856272c230d94cfaf23e6555b1a96d9 100644 (file)
@@ -378,11 +378,7 @@ gpointer
 mono_aot_plt_trampoline (gssize *regs, guint8 *code, guint8 *aot_module, 
                                                 guint8* tramp)
 {
-#ifdef MONO_ARCH_AOT_PLT_OFFSET_REG
-       guint32 plt_info_offset = regs [MONO_ARCH_AOT_PLT_OFFSET_REG];
-#else
-       guint32 plt_info_offset = -1;
-#endif
+       guint32 plt_info_offset = mono_aot_get_plt_info_offset (regs, code);
 
        return mono_aot_plt_resolve (aot_module, plt_info_offset, code);
 }
index 81ae3ff85a48709cff45cb5861d547bf284a7a40..46c9981869d04271527c89a7873f7ef05065c0b7 100644 (file)
@@ -1120,6 +1120,7 @@ gpointer  mono_aot_get_method               (MonoDomain *domain,
 gpointer  mono_aot_get_method_from_token    (MonoDomain *domain, MonoImage *image, guint32 token) MONO_INTERNAL;
 gboolean  mono_aot_is_got_entry             (guint8 *code, guint8 *addr) MONO_INTERNAL;
 guint8*   mono_aot_get_plt_entry            (guint8 *code) MONO_INTERNAL;
+guint32   mono_aot_get_plt_info_offset      (gssize *regs, guint8 *code) MONO_INTERNAL;
 gboolean  mono_aot_get_cached_class_info    (MonoClass *klass, MonoCachedClassInfo *res) MONO_INTERNAL;
 gboolean  mono_aot_get_class_from_name      (MonoImage *image, const char *name_space, const char *name, MonoClass **klass) MONO_INTERNAL;
 MonoJitInfo* mono_aot_find_jit_info         (MonoDomain *domain, MonoImage *image, gpointer addr) MONO_INTERNAL;
index 4ab13e6edc4912ea64b6818be17c336ab4561890..1ce2786d8b63985190f5161a27d8f54283a7a492 100644 (file)
@@ -18,6 +18,8 @@
 #include "mini.h"
 #include "mini-arm.h"
 
+static guint8* nullified_class_init_trampoline;
+
 /*
  * Return the instruction to jump from code to target, 0 if not
  * reachable with a single instruction
@@ -106,15 +108,11 @@ mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr)
 void
 mono_arch_patch_plt_entry (guint8 *code, guint8 *addr)
 {
-       guint32 ins = branch_for_target_reachable (code, addr);
+       /* Patch the jump table entry used by the plt entry */
+       guint32 offset = ((guint32*)code)[3];
+       guint8 *jump_entry = code + offset + 16;
 
-       if (ins)
-               /* Patch the branch */
-               ((guint32*)code) [0] = ins;
-       else
-               /* Patch the jump address */
-               ((guint32*)code) [1] = (guint32)addr;
-       mono_arch_flush_icache ((guint8*)code, 4);
+       *(guint8**)jump_entry = addr;
 }
 
 void
@@ -126,17 +124,12 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
 void
 mono_arch_nullify_plt_entry (guint8 *code)
 {
-       guint8 buf [4];
-       guint8 *p;
+       if (mono_aot_only && !nullified_class_init_trampoline)
+               nullified_class_init_trampoline = mono_aot_get_named_code ("nullified_class_init_trampoline");
 
-       p = buf;
-       ARM_MOV_REG_REG (p, ARMREG_PC, ARMREG_LR);
-
-       ((guint32*)code) [0] = ((guint32*)buf) [0];
-       mono_arch_flush_icache ((guint8*)code, 4);
+       mono_arch_patch_plt_entry (code, nullified_class_init_trampoline);
 }
 
-
 /* Stack size for trampoline function 
  */
 #define STACK (sizeof (MonoLMF))
@@ -311,6 +304,15 @@ mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *c
        /* Sanity check */
        g_assert ((buf - code) <= GEN_TRAMP_SIZE);
 
+       *code_size = buf - code;
+
+       if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
+               guint32 code_len;
+
+               /* Initialize the nullified class init trampoline used in the AOT case */
+               nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (&code_len);
+       }
+
        return code;
 }
 
@@ -321,7 +323,7 @@ mono_arch_get_nullified_class_init_trampoline (guint32 *code_len)
 
        code = buf = mono_global_codeman_reserve (16);
 
-       // FIXME:
+       ARM_MOV_REG_REG (buf, ARMREG_PC, ARMREG_LR);
 
        mono_arch_flush_icache (buf, code - buf);