5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HAVE_WCHAR_H)
35 #include <mono/utils/mono-publib.h>
36 #include <mono/utils/bsearch.h>
37 #include <mono/metadata/icalls.h>
38 #include "handle-decl.h"
39 #include "icall-decl.h"
41 // These definitions are used for multiple includes of icall-def.h and eventually undefined.
42 #define NOHANDLES(inner) inner
43 #define HANDLES(id, name, func, ...) ICALL (id, name, func ## _raw)
44 #define HANDLES_REUSE_WRAPPER HANDLES
45 #define MONO_HANDLE_REGISTER_ICALL(...) /* nothing */
47 // Generate Icall_ constants
49 #define ICALL_TYPE(id,name,first) /* nothing */
50 #define ICALL_TYPE(id,name,first)
51 #define ICALL(id,name,func) Icall_ ## id,
52 #include "metadata/icall-def.h"
59 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
60 #define ICALL(id,name,func) /* nothing */
61 #include "metadata/icall-def.h"
71 static const IcallTypeDesc icall_type_descs
[] = {
72 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
73 #define ICALL(id,name,func) /* nothing */
74 #include "metadata/icall-def.h"
80 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
82 // This, instead of an array of pointers, to optimize away a pointer and a relocation per string.
84 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
85 #define MSGSTRFIELD1(line) str##line
87 static const struct msgstrtn_t
{
88 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
89 #define ICALL(id,name,func) /* nothing */
90 #include "metadata/icall-def.h"
93 } icall_type_names_str
= {
94 #define ICALL_TYPE(id,name,first) (name),
95 #define ICALL(id,name,func)
96 #include "metadata/icall-def.h"
101 static const guint16 icall_type_names_idx
[] = {
102 #define ICALL_TYPE(id,name,first) (offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__))),
103 #define ICALL(id,name,func) /* nothing */
104 #include "metadata/icall-def.h"
109 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
111 static const struct msgstr_t
{
112 #define ICALL_TYPE(id,name,first) /* nothing */
113 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
114 #include "metadata/icall-def.h"
117 } icall_names_str
= {
118 #define ICALL_TYPE(id,name,first)
119 #define ICALL(id,name,func) (name),
120 #include "metadata/icall-def.h"
125 static const guint16 icall_names_idx
[] = {
126 #define ICALL_TYPE(id,name,first) /* nothing */
127 #define ICALL(id,name,func) (offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__))),
128 #include "metadata/icall-def.h"
133 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
135 static const gconstpointer icall_functions
[] = {
136 #define ICALL_TYPE(id,name,first) /* nothing */
137 #define ICALL(id,name,func) ((gpointer)(func)),
138 #include "metadata/icall-def.h"
144 #ifdef ENABLE_ICALL_SYMBOL_MAP
146 static const gconstpointer icall_symbols
[] = {
147 #define ICALL_TYPE(id,name,first) /* nothing */
148 #define ICALL(id,name,func) #func,
149 #include "metadata/icall-def.h"
155 #endif // ENABLE_ICALL_SYMBOL_MAP
160 static const guchar icall_uses_handles
[] = {
161 #define ICALL_TYPE(id,name,first) /* nothing */
162 #define ICALL(id,name,func) 0,
163 #define HANDLES(...) 1,
164 #define NOHANDLES(inner) 0,
165 #include "metadata/icall-def.h"
171 #undef HANDLES_REUSE_WRAPPER
173 #undef MONO_HANDLE_REGISTER_ICALL
176 compare_method_imap (const void *key
, const void *elem
)
178 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
179 return strcmp ((const char*)key
, method_name
);
183 find_slot_icall (const IcallTypeDesc
*imap
, const char *name
)
185 const guint16
*nameslot
= (const guint16
*)mono_binary_search (name
, icall_names_idx
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names_idx
[0]), compare_method_imap
);
188 return (nameslot
- &icall_names_idx
[0]);
192 find_uses_handles_icall (const IcallTypeDesc
*imap
, const char *name
)
194 gsize slotnum
= find_slot_icall (imap
, name
);
197 return (gboolean
)icall_uses_handles
[slotnum
];
201 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
203 gsize slotnum
= find_slot_icall (imap
, name
);
206 return (gpointer
)icall_functions
[slotnum
];
210 compare_class_imap (const void *key
, const void *elem
)
212 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
213 return strcmp ((const char*)key
, class_name
);
216 static const IcallTypeDesc
*
217 find_class_icalls (const char *name
)
219 const guint16
*nameslot
= (const guint16
*)mono_binary_search (name
, icall_type_names_idx
, Icall_type_num
, sizeof (icall_type_names_idx
[0]), compare_class_imap
);
222 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
226 icall_table_lookup (char *classname
, char *methodname
, char *sigstart
, gboolean
*uses_handles
)
228 const IcallTypeDesc
*imap
= NULL
;
231 imap
= find_class_icalls (classname
);
233 /* it wasn't found in the static call tables */
236 *uses_handles
= FALSE
;
239 res
= find_method_icall (imap
, methodname
);
242 *uses_handles
= find_uses_handles_icall (imap
, methodname
);
245 /* try _with_ signature */
247 res
= find_method_icall (imap
, methodname
);
250 *uses_handles
= find_uses_handles_icall (imap
, methodname
);
256 #ifdef ENABLE_ICALL_SYMBOL_MAP
258 func_cmp (gconstpointer key
, gconstpointer p
)
260 return (gsize
)key
- (gsize
)*(gsize
*)p
;
265 lookup_icall_symbol (gpointer func
)
267 #ifdef ENABLE_ICALL_SYMBOL_MAP
270 static gconstpointer
*functions_sorted
;
271 static const char**symbols_sorted
;
272 static gboolean inited
;
277 functions_sorted
= g_malloc (G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
278 memcpy (functions_sorted
, icall_functions
, G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
279 symbols_sorted
= g_malloc (G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
280 memcpy (symbols_sorted
, icall_symbols
, G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
281 /* Bubble sort the two arrays */
285 for (i
= 0; i
< G_N_ELEMENTS (icall_functions
) - 1; ++i
) {
286 if (functions_sorted
[i
] > functions_sorted
[i
+ 1]) {
289 tmp
= functions_sorted
[i
];
290 functions_sorted
[i
] = functions_sorted
[i
+ 1];
291 functions_sorted
[i
+ 1] = tmp
;
292 tmp
= symbols_sorted
[i
];
293 symbols_sorted
[i
] = symbols_sorted
[i
+ 1];
294 symbols_sorted
[i
+ 1] = (const char*)tmp
;
302 slot
= mono_binary_search (func
, functions_sorted
, G_N_ELEMENTS (icall_functions
), sizeof (gpointer
), func_cmp
);
306 return symbols_sorted
[(gpointer
*)slot
- (gpointer
*)functions_sorted
];
308 fprintf (stderr
, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
309 g_assert_not_reached ();
315 mono_icall_table_init (void)
319 /* check that tables are sorted: disable in release */
322 const char *prev_class
= NULL
;
323 const char *prev_method
;
325 for (i
= 0; i
< Icall_type_num
; ++i
) {
326 const IcallTypeDesc
*desc
;
329 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
330 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
331 prev_class
= icall_type_name_get (i
);
332 desc
= &icall_type_descs
[i
];
333 num_icalls
= icall_desc_num_icalls (desc
);
334 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
335 for (j
= 0; j
< num_icalls
; ++j
) {
336 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
337 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
338 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
339 prev_method
= methodn
;
344 MonoIcallTableCallbacks cb
;
345 memset (&cb
, 0, sizeof (MonoIcallTableCallbacks
));
346 cb
.version
= MONO_ICALL_TABLE_CALLBACKS_VERSION
;
347 cb
.lookup
= icall_table_lookup
;
348 cb
.lookup_icall_symbol
= lookup_icall_symbol
;
350 mono_install_icall_table_callbacks (&cb
);