From 65be1863ffa425a64fe52f0c62de87c300b5eed2 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 5 Feb 2008 19:47:33 +0000 Subject: [PATCH] 2008-02-05 Mark Probst * 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 * 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 | 7 +++++++ mono/metadata/marshal.c | 21 +++++++++++++++++++++ mono/metadata/marshal.h | 11 +++++++++++ mono/mini/ChangeLog | 6 ++++++ mono/mini/mini-trampolines.c | 4 ++++ mono/mini/tramp-amd64.c | 18 ++++++++++++++++++ mono/mini/tramp-x86.c | 22 ++++++++++++++++++++-- 7 files changed, 87 insertions(+), 2 deletions(-) diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 06a1c6e59cc..a4e91b3e4dd 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,10 @@ +2008-02-05 Mark Probst + + * 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 * marshal.c (mono_marshal_get_ptr_to_struct): Make the signature non-pinvoke. diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 9f14f65204d..7033e3293a5 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -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]; +} diff --git a/mono/metadata/marshal.h b/mono/metadata/marshal.h index 19052c9311e..b19ddbe5b85 100644 --- a/mono/metadata/marshal.h +++ b/mono/metadata/marshal.h @@ -18,6 +18,14 @@ #include #include +#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__ */ diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 014fcefbae7..72959202e59 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,9 @@ +2008-02-05 Mark Probst + + * 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 * tramp-amd64.c (mono_arch_patch_callsite): Add some diagnostics to help debug diff --git a/mono/mini/mini-trampolines.c b/mono/mini/mini-trampolines.c index c5767d85a60..dbca5af2293 100644 --- a/mono/mini/mini-trampolines.c +++ b/mono/mini/mini-trampolines.c @@ -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"); diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c index 59776c17e2b..9501cfdafee 100644 --- a/mono/mini/tramp-amd64.c +++ b/mono/mini/tramp-amd64.c @@ -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. diff --git a/mono/mini/tramp-x86.c b/mono/mini/tramp-x86.c index 4bfda4bd522..04f8fb5c016 100644 --- a/mono/mini/tramp-x86.c +++ b/mono/mini/tramp-x86.c @@ -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 -- 2.25.1