Hi,

Rodrigo Kumpera wrote:
 From your email the advantage of the patch is that by replacing some icalls
with managed code we would get rid of some managed-native transitions.

The long term goal would be to replace all native icalls with managed
icalls (build by icall builders) that call no native code that could
eliminate all unnecessary managed to native transitions.

-It makes the new full AOT mode a bit more complicated as these would be another
kind of wrappers that would need to be AOT'ed.

The current string constructor hach is implemented using
managed-to-managed wrappers. If that works, there should be no problem
with AOT. But I don't use AOT so I have little experience with it.

-Increases the footprint by just a bit, as we need to store the icalls internal representation as well. The amount of extra code generated is bounded, specially since we replace a managed-to-native wrapper with a managed-to-managed with more code.

All the three reference implementations implement very small and fast
code blocks and I believe that it's worth to aviod managed to native
transitions. OffsetToStringData is an exception because that is managed
already but I wanted to show that mini_get_inst_for_method could be
replaced by icall builders.

-JIT time should not change much, but this is only a guess.

JIT time should be the same as for IL code contained in assemblies. Lots
of our current icalls are native because we couldn't implement them in
C#. Other icalls are native calls because they call external native code
so it's faster to have only one managed to native transition. I don't
think that there are icalls that are in native code because have better
performance than an IL implementation.

I wonder if it is really an advantage of following this patch as, for example, OffsetToStringData has 22 lines in your patch but 6 in the current setup. Of course the code in your patch ends more organized and I find it easier to follow, but should be interesting to rear from the others.

The 22 lines are the builder but that gets executed only once. After
that only the generated (and JITed) code is used. The actual IL code
just returns a constant.

-For simple methods such as OffsetToStringData the method call overhead might be a killer. We
should make sure that these new wrappers get a change to be inlined.

Currently it doesn't get inlined because the JIT has some logic
preventing (at least types) of wrappers being inlined but should be
possible to inline them.

-I'm not aware of how stack traces behave with wrappers, but are they preserved with your patch?

As long as they are not inlined the stack trace is preserved. But this
is true for Class Library methods implemented in C# so icall builders
should not be treated differently.

-Does it work under trunk?

It should but the patch may be outdated.

-Do you have performance numbers on your change? Since it changes performance sensitive parts of the runtime, attaching a benchmark (or pointing to an existing one) showing the implications is
fundamental.

These are only reference implementations and OffsetToStringData for
example is slower for sure because it don't get inlined. I expect string .ctors to have the same performance because the generated IL code is the same but using icall builder is a clean way as opposed to the current hack. UnsafeAddrOfPinnedArrayElement should benefit because no native code will be called.

As for OffsetToStringData I don't know whether mini_get_inst_for_method or an icall builder is faster when generating the code but using an icall builder solves the things at the highest possible level letting low level optimizations do their job.

I don't insist on getting these reference icall builder implementations
into trunk I just would like to get approval for the concept and the support code of icall builders. Actual icall builder implementations could be evaluated independently.

With the attched test I got:
mono r109162: 99060
mono r109162 with my patch: 17375 (5.7x faster)
MS.NET 2.0 SP1: 17898

The imporvement is purely because of the method being implemented in managed code. So mono would benefit form icall builders for sure.

The code that decides what to be inlined is too cryptic to me because I believe that there are redundant checks against wrappers but if someone could enable the inlining of managed-to-managed wrappers icall builders could provide even more performance improvement.

I also have attached an updated patch. (Only line numbers were updated no code modification was necessary.)

Kornél

2008/7/29 Kornél Pál <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>

    Hi,

    There is a pending patch:
    http://lists.ximian.com/pipermail/mono-devel-list/2008-June/028291.html

    As far as I can remember I didn't get any feedback regarding this patch.

    Please review the patch. Thanks.

    Kornél
    _______________________________________________
    Mono-devel-list mailing list
    Mono-devel-list@lists.ximian.com
    <mailto:Mono-devel-list@lists.ximian.com>
    http://lists.ximian.com/mailman/listinfo/mono-devel-list



------------------------------------------------------------------------

_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

using System;
using System.Globalization;
using System.Runtime.InteropServices;

class ICallBuilderPerfTest
{
    static void Main()
    {
        DateTime startTime = DateTime.Now;
        DateTime endTime;
        byte[] array = new byte[0x1000];

        for (int i = 0; i < 0x100000; i++)
            for (int j = 0; j < 0x1000; j++)
                Marshal.UnsafeAddrOfPinnedArrayElement(array, j);

        endTime = DateTime.Now;
        
Console.WriteLine(((long)endTime.Subtract(startTime).TotalMilliseconds).ToString(CultureInfo.InvariantCulture));
    }
}
Index: mono/mono/metadata/string-icalls.c
===================================================================
--- mono/mono/metadata/string-icalls.c  (revision 109162)
+++ mono/mono/metadata/string-icalls.c  (working copy)
@@ -27,14 +27,6 @@
 static gboolean
 string_icall_is_in_array (MonoArray *chars, gint32 arraylength, gunichar2 chr);
 
-/* This function is redirected to String.CreateString ()
-   by mono_marshal_get_native_wrapper () */
-void
-ves_icall_System_String_ctor_RedirectToCreateString (void)
-{
-       g_assert_not_reached ();
-}
-
 MonoString * 
 ves_icall_System_String_InternalJoin (MonoString *separator, MonoArray * 
value, gint32 sindex, gint32 count)
 {
Index: mono/mono/metadata/string-icalls.h
===================================================================
--- mono/mono/metadata/string-icalls.h  (revision 109162)
+++ mono/mono/metadata/string-icalls.h  (working copy)
@@ -14,9 +14,6 @@
 #include <mono/metadata/object.h>
 #include "mono/utils/mono-compiler.h"
 
-void
-ves_icall_System_String_ctor_RedirectToCreateString (void) MONO_INTERNAL;
-
 MonoString * 
 ves_icall_System_String_InternalJoin (MonoString *separator, MonoArray * 
value, gint32 sindex, gint32 count) MONO_INTERNAL;
 
Index: mono/mono/metadata/icall-def.h
===================================================================
--- mono/mono/metadata/icall-def.h      (revision 109162)
+++ mono/mono/metadata/icall-def.h      (working copy)
@@ -604,12 +604,10 @@
 
 ICALL_TYPE(RUNH, "System.Runtime.CompilerServices.RuntimeHelpers", RUNH_1)
 ICALL(RUNH_1, "GetObjectValue", 
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue)
-        /* REMOVEME: no longer needed, just so we dont break things when not 
needed */
-ICALL(RUNH_2, "GetOffsetToStringData", 
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData)
 ICALL(RUNH_3, "InitializeArray", 
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray)
 ICALL(RUNH_4, "RunClassConstructor", 
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor)
 ICALL(RUNH_5, "RunModuleConstructor", 
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor)
-ICALL(RUNH_6, "get_OffsetToStringData", 
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData)
+ICALL_METHOD(RUNH_6, "get_OffsetToStringData", 
build_icall_System_Runtime_CompilerServices_RuntimeHelpers_get_OffsetToStringData,
 BUILDER)
 
 ICALL_TYPE(GCH, "System.Runtime.InteropServices.GCHandle", GCH_1)
 ICALL(GCH_1, "CheckCurrentDomain", GCHandle_CheckCurrentDomain)
@@ -660,7 +658,7 @@
 ICALL(MARSHAL_32, "StringToHGlobalAnsi", 
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi)
 ICALL(MARSHAL_33, "StringToHGlobalUni", 
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni)
 ICALL(MARSHAL_34, "StructureToPtr", 
ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr)
-ICALL(MARSHAL_35, "UnsafeAddrOfPinnedArrayElement", 
ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement)
+ICALL_METHOD(MARSHAL_35, "UnsafeAddrOfPinnedArrayElement", 
build_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement,
 BUILDER)
 ICALL(MARSHAL_36, "WriteByte", 
ves_icall_System_Runtime_InteropServices_Marshal_WriteByte)
 ICALL(MARSHAL_37, "WriteInt16", 
ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16)
 ICALL(MARSHAL_38, "WriteInt32", 
ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32)
@@ -725,14 +723,7 @@
 ICALL(SECMAN_5, "set_SecurityEnabled", 
ves_icall_System_Security_SecurityManager_set_SecurityEnabled)
 
 ICALL_TYPE(STRING, "System.String", STRING_1)
-ICALL(STRING_1, ".ctor(char*)", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_2, ".ctor(char*,int,int)", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_3, ".ctor(char,int)", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_4, ".ctor(char[])", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_5, ".ctor(char[],int,int)", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_6, ".ctor(sbyte*)", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_7, ".ctor(sbyte*,int,int)", 
ves_icall_System_String_ctor_RedirectToCreateString)
-ICALL(STRING_8, ".ctor(sbyte*,int,int,System.Text.Encoding)", 
ves_icall_System_String_ctor_RedirectToCreateString)
+ICALL_METHOD(STRING_1, ".ctor", build_icall_System_String_ctor, BUILDER)
 ICALL(STRING_9, "InternalAllocateStr", 
ves_icall_System_String_InternalAllocateStr)
 ICALL(STRING_11, "InternalCopyTo", ves_icall_System_String_InternalCopyTo)
 ICALL(STRING_14, "InternalIntern", ves_icall_System_String_InternalIntern)
Index: mono/mono/metadata/marshal.c
===================================================================
--- mono/mono/metadata/marshal.c        (revision 109162)
+++ mono/mono/metadata/marshal.c        (working copy)
@@ -2744,6 +2744,13 @@
        return res;
 }              
 
+static inline MonoMethod*
+mono_mb_create_icall_and_cache (MonoMethod *method, MonoMethodBuilder *mb,
+                                                                       
MonoMethodSignature *sig, int max_stack)
+{
+       return mono_mb_create_and_cache 
(method->klass->image->native_wrapper_cache,
+               method, mb, sig, max_stack);
+}
 
 static inline MonoMethod*
 mono_marshal_remoting_find_in_cache (MonoMethod *method, int wrapper_type)
@@ -8475,7 +8482,6 @@
        MonoMethod *res;
        GHashTable *cache;
        gboolean pinvoke = FALSE;
-       gpointer iter;
        int i;
        const char *exc_class = "MissingMethodException";
        const char *exc_arg = NULL;
@@ -8502,51 +8508,24 @@
                                exc_arg = "Method contains unsupported native 
code";
                        else
                                mono_lookup_pinvoke_call (method, &exc_class, 
&exc_arg);
-               else
-                       piinfo->addr = mono_lookup_internal_call (method);
-       }
+               else {
+                       const ICallDescriptor *icall_desc = 
mono_lookup_icall_descriptor (method);
 
-       /* hack - redirect certain string constructors to CreateString */
-       if (piinfo->addr == 
ves_icall_System_String_ctor_RedirectToCreateString) {
-               g_assert (!pinvoke);
-               g_assert (method->string_ctor);
-               g_assert (sig->hasthis);
-
-               /* CreateString returns a value */
-               csig = signature_dup (method->klass->image, sig);
-               csig->ret = &mono_defaults.string_class->byval_arg;
-               csig->pinvoke = 0;
-
-               iter = NULL;
-               while ((res = mono_class_get_methods 
(mono_defaults.string_class, &iter))) {
-                       if (!strcmp ("CreateString", res->name) &&
-                               mono_metadata_signature_equal (csig, 
mono_method_signature (res))) {
-
-                               g_assert (!(res->iflags & 
METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL));
-                               g_assert (!(res->flags & 
METHOD_ATTRIBUTE_PINVOKE_IMPL));
-
-                               /* create a wrapper to preserve .ctor in stack 
trace */
-                               mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_MANAGED_TO_MANAGED);
-
-                               mono_mb_emit_byte (mb, CEE_LDARG_0);
-                               for (i = 1; i <= csig->param_count; i++)
-                                       mono_mb_emit_ldarg (mb, i);
-                               mono_mb_emit_managed_call (mb, res, NULL);
-                               mono_mb_emit_byte (mb, CEE_RET);
-
-                               /* use native_wrapper_cache because internal 
calls are looked up there */
-                               res = mono_mb_create_and_cache (cache, method,
-                                       mb, csig, csig->param_count + 1);
-
-                               mono_mb_free (mb);
-
-                               return res;
+                       if (icall_desc) {
+                               switch (icall_desc->type) {
+                               case ICALL_TYPE_FTNPTR:
+                                       piinfo->addr = icall_desc->ftnptr;
+                                       break;
+                               case ICALL_TYPE_BUILDER:
+                                       res = icall_desc->builder (method);
+                                       if (res)
+                                               return res;
+                                       break;
+                               default:
+                                       g_assert_not_reached ();
+                               }
                        }
                }
-
-               /* exception will be thrown */
-               piinfo->addr = NULL;
-               g_warning ("cannot find CreateString for .ctor");
        }
 
        mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_MANAGED_TO_NATIVE);
@@ -10782,10 +10761,44 @@
 #endif
 }
 
-void*
-ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
 (MonoArray *arrayobj, int index)
+MonoMethod*
+build_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
 (MonoMethod *method)
 {
-       return mono_array_addr_with_size (arrayobj, mono_array_element_size 
(arrayobj->obj.vtable->klass), index);
+       MonoMethod *res;
+       MonoMethodSignature *csig;
+       MonoMethodBuilder *mb;
+
+       csig = signature_dup (method->klass->image, mono_method_signature 
(method));
+       csig->pinvoke = 0;
+
+       mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_MANAGED_TO_MANAGED);
+
+       /* static IntPtr UnsafeAddrOfPinnedArrayElement (Array arr, int index); 
*/
+       /* return (char*) &arr->vector + 
arr->obj.vtable->klass->sizes.element_size * index; */
+
+       mono_mb_emit_byte (mb, CEE_LDARG_0);
+       mono_mb_emit_byte (mb, CEE_CONV_I);
+       mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
+       mono_mb_emit_byte (mb, CEE_ADD);
+
+       mono_mb_emit_byte (mb, CEE_LDARG_0);
+       mono_mb_emit_byte (mb, CEE_LDIND_I); /* vtable */
+       mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_LDIND_I);
+       mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoClass, sizes));
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_LDIND_I4);
+
+       mono_mb_emit_byte (mb, CEE_LDARG_1);
+       mono_mb_emit_byte (mb, CEE_MUL);
+
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_RET);
+
+       res = mono_mb_create_icall_and_cache (method, mb, csig, 3);
+       mono_mb_free (mb);
+       return res;
 }
 
 MonoDelegate*
@@ -10888,6 +10901,77 @@
        return proxy;
 }
 
+MonoMethod*
+build_icall_System_Runtime_CompilerServices_RuntimeHelpers_get_OffsetToStringData
 (MonoMethod *method)
+{
+       MonoMethod *res;
+       MonoMethodSignature *csig;
+       MonoMethodBuilder *mb;
+
+       csig = signature_dup (method->klass->image, mono_method_signature 
(method));
+       csig->pinvoke = 0;
+
+       mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_MANAGED_TO_MANAGED);
+
+       /* static int get_OffsetToStringData (); */
+       /* return offsetof (MonoString, chars); */
+
+       mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoString, chars));
+       mono_mb_emit_byte (mb, CEE_RET);
+
+       res = mono_mb_create_icall_and_cache (method, mb, csig, 1);
+       mono_mb_free (mb);
+       return res;
+
+}
+
+/* Redirect String constructors to CreateString () */
+MonoMethod*
+build_icall_System_String_ctor (MonoMethod *method)
+{
+       MonoMethod *res;
+       MonoMethodSignature *csig;
+       MonoMethodBuilder *mb;
+       gpointer iter;
+       gboolean found;
+       int i;
+
+       g_assert (method->string_ctor);
+
+       /* CreateString returns a value */
+       csig = signature_dup (method->klass->image, mono_method_signature 
(method));
+       csig->ret = &mono_defaults.string_class->byval_arg;
+       csig->pinvoke = 0;
+
+       /* create a wrapper to preserve .ctor in stack trace */
+       mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_MANAGED_TO_MANAGED);
+
+       iter = NULL;
+       found = FALSE;
+       while ((res = mono_class_get_methods (mono_defaults.string_class, 
&iter))) {
+               if (res->name [0] == 'C' && !strcmp ("CreateString", res->name) 
&&
+                       mono_metadata_signature_equal (csig, 
mono_method_signature (res))) {
+
+                       mono_mb_emit_byte (mb, CEE_LDARG_0);
+                       for (i = 1; i <= csig->param_count; i++)
+                               mono_mb_emit_ldarg (mb, i);
+                       mono_mb_emit_managed_call (mb, res, NULL);
+                       mono_mb_emit_byte (mb, CEE_RET);
+                       found = TRUE;
+                       break;
+               }
+       }
+
+       if (!found) {
+               g_warning ("Cannot find CreateString for string constructor.");
+               mono_mb_emit_exception (mb, "MissingMethodException", NULL);
+       }
+
+       res = mono_mb_create_icall_and_cache (method, mb, csig, 
csig->param_count + 1);
+       mono_mb_free (mb);
+       return res;
+}
+
 /**
  * mono_marshal_is_loading_type_info:
  *
Index: mono/mono/metadata/marshal.h
===================================================================
--- mono/mono/metadata/marshal.h        (revision 109162)
+++ mono/mono/metadata/marshal.h        (working copy)
@@ -30,6 +30,22 @@
 
 /* marshaling helper functions */
 
+enum {
+       ICALL_TYPE_FTNPTR,
+       ICALL_TYPE_BUILDER
+};
+
+typedef struct {
+       union {
+               gpointer ftnptr;
+               MonoMethod* (*builder) (MonoMethod *method);
+       };
+       guint8 type;
+} ICallDescriptor;
+
+const ICallDescriptor*
+mono_lookup_icall_descriptor (MonoMethod *method) MONO_INTERNAL;
+
 void
 mono_marshal_init (void) MONO_INTERNAL;
 
@@ -322,8 +338,8 @@
 void
 ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (void *ptr) 
MONO_INTERNAL;
 
-void*
-ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
 (MonoArray *arrayobj, int index) MONO_INTERNAL;
+MonoMethod*
+build_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
 (MonoMethod *method) MONO_INTERNAL;
 
 MonoDelegate*
 
ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal
 (void *ftn, MonoReflectionType *type) MONO_INTERNAL;
@@ -370,6 +386,12 @@
 MonoComInteropProxy*
 ves_icall_Mono_Interop_ComInteropProxy_FindProxy (gpointer pUnk) MONO_INTERNAL;
 
+MonoMethod*
+build_icall_System_Runtime_CompilerServices_RuntimeHelpers_get_OffsetToStringData
 (MonoMethod *method) MONO_INTERNAL;
+
+MonoMethod*
+build_icall_System_String_ctor (MonoMethod *method) MONO_INTERNAL;
+
 void
 mono_win32_compat_CopyMemory (gpointer dest, gconstpointer source, gsize 
length);
 
Index: mono/mono/metadata/icall.c
===================================================================
--- mono/mono/metadata/icall.c  (revision 109162)
+++ mono/mono/metadata/icall.c  (working copy)
@@ -850,14 +850,6 @@
 #endif
 }
 
-static gint
-ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData 
(void)
-{
-       MONO_ARCH_SAVE_REGS;
-
-       return offsetof (MonoString, chars);
-}
-
 static MonoObject *
 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue 
(MonoObject *obj)
 {
@@ -7365,6 +7357,7 @@
 }
 
 #define ICALL_TYPE(id,name,first)
+#define ICALL_METHOD(id,name,data,type) ICALL(id,name,data)
 #define ICALL(id,name,func) Icall_ ## id,
 
 enum {
@@ -7469,13 +7462,15 @@
 #endif /* !HAVE_ARRAY_ELEM_INIT */
 
 #undef ICALL_TYPE
+#undef ICALL_METHOD
 #undef ICALL
 #define ICALL_TYPE(id,name,first)
-#define ICALL(id,name,func) func,
-static const gconstpointer
-icall_functions [] = {
+#define ICALL_METHOD(id,name,data,type) {data, ICALL_TYPE_ ## type},
+#define ICALL(id,name,func) ICALL_METHOD(id,name,func,FTNPTR)
+static const ICallDescriptor
+icall_descriptors [] = {
 #include "metadata/icall-def.h"
-       NULL
+       {NULL, 0}
 };
 
 static GHashTable *icall_hash = NULL;
@@ -7512,7 +7507,7 @@
                }
        }
 
-       icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
NULL);
+       icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
g_free);
 }
 
 void
@@ -7526,9 +7521,14 @@
 void
 mono_add_internal_call (const char *name, gconstpointer method)
 {
+       ICallDescriptor *icall_desc = g_new(ICallDescriptor, 1);
+
+       icall_desc->ftnptr = (gpointer) method;
+       icall_desc->type = ICALL_TYPE_FTNPTR;
+
        mono_loader_lock ();
 
-       g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
+       g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) 
icall_desc);
 
        mono_loader_unlock ();
 }
@@ -7541,13 +7541,13 @@
        return strcmp (key, method_name);
 }
 
-static gpointer
+static const ICallDescriptor*
 find_method_icall (const IcallTypeDesc *imap, const char *name)
 {
        const guint16 *nameslot = bsearch (name, icall_names_idx + 
imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), 
compare_method_imap);
        if (!nameslot)
                return NULL;
-       return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
+       return &icall_descriptors [(nameslot - &icall_names_idx [0])];
 }
 
 static int
@@ -7574,13 +7574,13 @@
        return strcmp (key, *method_name);
 }
 
-static gpointer
+static const ICallDescriptor*
 find_method_icall (const IcallTypeDesc *imap, const char *name)
 {
        const char **nameslot = bsearch (name, icall_names + imap->first_icall, 
icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
        if (!nameslot)
                return NULL;
-       return (gpointer)icall_functions [(nameslot - icall_names)];
+       return &icall_descriptors [(nameslot - icall_names)];
 }
 
 static int
@@ -7622,14 +7622,14 @@
        return nspacelen + cnamelen;
 }
 
-gpointer
-mono_lookup_internal_call (MonoMethod *method)
+const ICallDescriptor*
+mono_lookup_icall_descriptor (MonoMethod *method)
 {
        char *sigstart;
        char *tmpsig;
        char mname [2048];
        int typelen = 0, mlen, siglen;
-       gpointer res;
+       const ICallDescriptor *res;
        const IcallTypeDesc *imap;
 
        g_assert (method != NULL);
@@ -7722,6 +7722,14 @@
        return NULL;
 }
 
+gpointer
+mono_lookup_internal_call (MonoMethod *method)
+{
+       const ICallDescriptor *icall_desc = mono_lookup_icall_descriptor 
(method);
+
+       return icall_desc->type == ICALL_TYPE_FTNPTR ? icall_desc->ftnptr : 
NULL;
+}
+
 static MonoType*
 type_from_typename (char *typename)
 {
Index: mono/mono/mini/mini.c
===================================================================
--- mono/mono/mini/mini.c       (revision 109162)
+++ mono/mono/mini/mini.c       (working copy)
@@ -4020,11 +4020,6 @@
 {
        MonoInst *ins = NULL;
        
-       static MonoClass *runtime_helpers_class = NULL;
-       if (! runtime_helpers_class)
-               runtime_helpers_class = mono_class_from_name 
(mono_defaults.corlib,
-                       "System.Runtime.CompilerServices", "RuntimeHelpers");
-
        if (cmethod->klass == mono_defaults.string_class) {
                if (strcmp (cmethod->name, "get_Chars") == 0) {
                        MONO_INST_NEW (cfg, ins, OP_GETCHR);
@@ -4077,12 +4072,6 @@
                        return ins;
                } else
                        return NULL;
-       } else if (cmethod->klass == runtime_helpers_class) {
-               if (strcmp (cmethod->name, "get_OffsetToStringData") == 0) {
-                       NEW_ICONST (cfg, ins, G_STRUCT_OFFSET (MonoString, 
chars));
-                       return ins;
-               } else
-                       return NULL;
        } else if (cmethod->klass == mono_defaults.thread_class) {
                if (strcmp (cmethod->name, "get_CurrentThread") == 0 && (ins = 
mono_arch_get_thread_intrinsic (cfg)))
                        return ins;
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to