2008-02-05 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Tue, 5 Feb 2008 19:47:33 +0000 (19:47 -0000)
committerMark Probst <mark.probst@gmail.com>
Tue, 5 Feb 2008 19:47:33 +0000 (19:47 -0000)
* tramp-amd64.c, tramp-x86.c, mini-trampolines.c: Added a check in
the generic class init trampoline to return quickly if the class
is already inited.

2008-02-05  Mark Probst  <mark.probst@gmail.com>

* marshal.c, marshal.h (mono_marshal_find_bitfield_offset,
mono_marshal_find_nonzero_bit_offset): Added macro and function
for finding the byte- and bit-offset of a bitfield within a
struct.

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

mono/metadata/ChangeLog
mono/metadata/marshal.c
mono/metadata/marshal.h
mono/mini/ChangeLog
mono/mini/mini-trampolines.c
mono/mini/tramp-amd64.c
mono/mini/tramp-x86.c

index 06a1c6e59ccfd70e3626592d9f43d26fc46a2ea3..a4e91b3e4dd2381ce2427ea33a4a7e1a38d74c5e 100644 (file)
@@ -1,3 +1,10 @@
+2008-02-05  Mark Probst  <mark.probst@gmail.com>
+
+       * marshal.c, marshal.h (mono_marshal_find_bitfield_offset,
+       mono_marshal_find_nonzero_bit_offset): Added macro and function
+       for finding the byte- and bit-offset of a bitfield within a
+       struct.
+
 2008-02-05  Zoltan Varga  <vargaz@gmail.com>
 
        * marshal.c (mono_marshal_get_ptr_to_struct): Make the signature non-pinvoke.
index 9f14f65204d646cd5c9b4941a1948d5bc35fba5b..7033e3293a5544f418f361a5b95bbeb0ff016e1a 100644 (file)
@@ -11798,3 +11798,24 @@ cominterop_ccw_invoke (MonoCCWInterface* ccwe, guint32 dispIdMember,
 {
        return MONO_E_NOTIMPL;
 }
+
+void
+mono_marshal_find_nonzero_bit_offset (guint8 *buf, int len, int *byte_offset, guint8 *bitmask)
+{
+       int i;
+       guint8 byte;
+
+       for (i = 0; i < len; ++i)
+               if (buf [i])
+                       break;
+
+       g_assert (i < len);
+
+       byte = buf [i];
+       while (byte && !(byte & 1))
+               byte >>= 1;
+       g_assert (byte == 1);
+
+       *byte_offset = i;
+       *bitmask = buf [i];
+}
index 19052c9311e1fe6100e4851ee53796f53be45e91..b19ddbe5b85ad081bb7b31382878f4018794dc3a 100644 (file)
 #include <mono/metadata/opcodes.h>
 #include <mono/metadata/reflection.h>
 
+#define mono_marshal_find_bitfield_offset(type, elem, byte_offset, bitmask) \
+       do { \
+               type tmp; \
+               memset (&tmp, 0, sizeof (tmp)); \
+               tmp.elem = 1; \
+               mono_marshal_find_nonzero_bit_offset ((guint8*)&tmp, sizeof (tmp), (byte_offset), (bitmask)); \
+       } while (0)
+
 G_BEGIN_DECLS
 
 /* marshaling helper functions */
@@ -365,6 +373,9 @@ mono_win32_compat_MoveMemory (gpointer dest, gconstpointer source, gsize length)
 void
 mono_win32_compat_ZeroMemory (gpointer dest, gsize length);
 
+void
+mono_marshal_find_nonzero_bit_offset (guint8 *buf, int len, int *byte_offset, guint8 *bitmask) MONO_INTERNAL;
+
 G_END_DECLS
 
 #endif /* __MONO_MARSHAL_H__ */
index 014fcefbae78924bc2867df092266bc24639f9d0..72959202e59507f029e62ed613098e295938d718 100644 (file)
@@ -1,3 +1,9 @@
+2008-02-05  Mark Probst  <mark.probst@gmail.com>
+
+       * tramp-amd64.c, tramp-x86.c, mini-trampolines.c: Added a check in
+       the generic class init trampoline to return quickly if the class
+       is already inited.
+
 2008-02-04  Zoltan Varga  <vargaz@gmail.com>
 
        * tramp-amd64.c (mono_arch_patch_callsite): Add some diagnostics to help debug
index c5767d85a601c638fc531b0fc7a513340d82ac00..dbca5af2293f9e093ac784862a2cdff7c78b7c7f 100644 (file)
@@ -303,6 +303,10 @@ mono_generic_class_init_trampoline (gssize *regs, guint8 *code, MonoVTable *vtab
 {
        //g_print ("generic class init for class %s.%s\n", vtable->klass->name_space, vtable->klass->name);
 
+#if defined(__i386__) || defined(__x86_64__)
+       g_assert (!vtable->initialized);
+#endif
+
        mono_runtime_class_init (vtable);
 
        //g_print ("done initing generic\n");
index 59776c17e2b01a51b495dd0b894ffde316c91cbb..9501cfdafee7bdac2d0c8bd4d5265e46a3a4102b 100644 (file)
@@ -204,6 +204,24 @@ mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
 
        offset = 0;
 
+       if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
+               static int byte_offset = -1;
+               static guint8 bitmask;
+
+               guint8 *jump;
+
+               if (byte_offset < 0)
+                       mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+
+               amd64_test_membase_imm_size (code, MONO_ARCH_VTABLE_REG, byte_offset, bitmask, 1);
+               jump = code;
+               amd64_branch8 (code, X86_CC_Z, -1, 1);
+
+               amd64_ret (code);
+
+               x86_patch (jump, code);
+       }
+
        /*
         * The generic class init trampoline is called directly by JITted code, there is no
         * specific trampoline.
index 4bfda4bd5229422d48e98c7b05b04ac5a2836586..04f8fb5c0169cfb64e2952109b32f812d64b0611 100644 (file)
@@ -192,10 +192,28 @@ mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
         */
 
        /* If this is a generic class init the argument is not on the
-        * stack yet but in MONO_ARCH_VTABLE_REG.
+        * stack yet but in MONO_ARCH_VTABLE_REG.  We first check
+        * whether the vtable is already initialized in which case we
+        * just return.  Otherwise we push it and continue.
         */
-       if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
+       if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
+               static int byte_offset = -1;
+               static guint8 bitmask;
+
+               guint8 *jump;
+
+               if (byte_offset < 0)
+                       mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
+
+               x86_test_membase_imm (buf, MONO_ARCH_VTABLE_REG, byte_offset, bitmask);
+               jump = buf;
+               x86_branch8 (buf, X86_CC_Z, -1, 1);
+
+               x86_ret (buf);
+
+               x86_patch (jump, buf);
                x86_push_reg (buf, MONO_ARCH_VTABLE_REG);
+       }
 
        /* Put all registers into an array on the stack
         * If this code is changed, make sure to update the offset value in