+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.
{
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];
+}
#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 */
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__ */
+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
{
//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");
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.
*/
/* 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