method-builder.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /**
  2. * \file
  3. * Functions for creating IL methods at runtime.
  4. *
  5. * Author:
  6. * Paolo Molaro (lupus@ximian.com)
  7. *
  8. * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  9. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  10. * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  11. */
  12. #include "config.h"
  13. #include "loader.h"
  14. #include "mono/metadata/abi-details.h"
  15. #include "mono/metadata/method-builder.h"
  16. #include "mono/metadata/method-builder-internals.h"
  17. #include "mono/metadata/method-builder-ilgen.h"
  18. #include "mono/metadata/tabledefs.h"
  19. #include "mono/metadata/exception.h"
  20. #include "mono/metadata/appdomain.h"
  21. #include "mono/metadata/debug-helpers.h"
  22. #include "mono/metadata/metadata-internals.h"
  23. #include "mono/metadata/domain-internals.h"
  24. #include <string.h>
  25. #include <errno.h>
  26. /* #define DEBUG_RUNTIME_CODE */
  27. #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
  28. a = i,
  29. enum {
  30. #include "mono/cil/opcode.def"
  31. LAST = 0xff
  32. };
  33. #undef OPDEF
  34. #ifdef DEBUG_RUNTIME_CODE
  35. static char*
  36. indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
  37. {
  38. return g_strdup (" ");
  39. }
  40. static MonoDisHelper marshal_dh = {
  41. "\n",
  42. "IL_%04x: ",
  43. "IL_%04x",
  44. indenter,
  45. NULL,
  46. NULL
  47. };
  48. #endif
  49. static MonoMethodBuilderCallbacks mb_cb;
  50. static gboolean cb_inited = FALSE;
  51. #ifndef ENABLE_ILGEN
  52. static MonoMethodBuilder *
  53. new_base_noilgen (MonoClass *klass, MonoWrapperType type)
  54. {
  55. MonoMethodBuilder *mb;
  56. MonoMethod *m;
  57. g_assert (klass != NULL);
  58. mb = g_new0 (MonoMethodBuilder, 1);
  59. mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
  60. m->klass = klass;
  61. m->inline_info = 1;
  62. m->wrapper_type = type;
  63. /* placeholder for the wrapper always at index 1 */
  64. mono_mb_add_data (mb, NULL);
  65. return mb;
  66. }
  67. static void
  68. free_noilgen (MonoMethodBuilder *mb)
  69. {
  70. g_free (mb->method);
  71. if (!mb->no_dup_name)
  72. g_free (mb->name);
  73. g_free (mb);
  74. }
  75. static MonoMethod *
  76. create_method_noilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
  77. {
  78. MonoMethodWrapper *mw;
  79. MonoImage *image;
  80. MonoMethod *method;
  81. GList *l;
  82. int i;
  83. g_assert (mb != NULL);
  84. image = m_class_get_image (mb->method->klass);
  85. {
  86. /* Realloc the method info into a mempool */
  87. method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
  88. memcpy (method, mb->method, sizeof (MonoMethodWrapper));
  89. mw = (MonoMethodWrapper*) method;
  90. if (mb->no_dup_name)
  91. method->name = mb->name;
  92. else
  93. method->name = mono_image_strdup (image, mb->name);
  94. }
  95. method->signature = signature;
  96. if (!signature->hasthis)
  97. method->flags |= METHOD_ATTRIBUTE_STATIC;
  98. i = g_list_length ((GList *)mw->method_data);
  99. if (i) {
  100. GList *tmp;
  101. void **data;
  102. l = g_list_reverse ((GList *)mw->method_data);
  103. if (method_is_dynamic (method))
  104. data = (void **)g_malloc (sizeof (gpointer) * (i + 1));
  105. else
  106. data = (void **)mono_image_alloc (image, sizeof (gpointer) * (i + 1));
  107. /* store the size in the first element */
  108. data [0] = GUINT_TO_POINTER (i);
  109. i = 1;
  110. for (tmp = l; tmp; tmp = tmp->next) {
  111. data [i++] = tmp->data;
  112. }
  113. g_list_free (l);
  114. mw->method_data = data;
  115. }
  116. return method;
  117. }
  118. #endif
  119. void
  120. mono_install_method_builder_callbacks (MonoMethodBuilderCallbacks *cb)
  121. {
  122. g_assert (!cb_inited);
  123. g_assert (cb->version == MONO_METHOD_BUILDER_CALLBACKS_VERSION);
  124. memcpy (&mb_cb, cb, sizeof (MonoMethodBuilderCallbacks));
  125. cb_inited = TRUE;
  126. }
  127. #ifndef ENABLE_ILGEN
  128. static void
  129. install_noilgen (void)
  130. {
  131. MonoMethodBuilderCallbacks cb;
  132. cb.version = MONO_METHOD_BUILDER_CALLBACKS_VERSION;
  133. cb.new_base = new_base_noilgen;
  134. cb.free = free_noilgen;
  135. cb.create_method = create_method_noilgen;
  136. mono_install_method_builder_callbacks (&cb);
  137. }
  138. #endif
  139. static MonoMethodBuilderCallbacks *
  140. get_mb_cb (void)
  141. {
  142. if (G_UNLIKELY (!cb_inited)) {
  143. #ifdef ENABLE_ILGEN
  144. mono_method_builder_ilgen_init ();
  145. #else
  146. install_noilgen ();
  147. #endif
  148. }
  149. return &mb_cb;
  150. }
  151. MonoMethodBuilder *
  152. mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type)
  153. {
  154. MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type);
  155. mb->name = (char*)name;
  156. mb->no_dup_name = TRUE;
  157. return mb;
  158. }
  159. /**
  160. * mono_mb_new:
  161. */
  162. MonoMethodBuilder *
  163. mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
  164. {
  165. MonoMethodBuilder *mb = get_mb_cb ()->new_base (klass, type);
  166. mb->name = g_strdup (name);
  167. return mb;
  168. }
  169. /**
  170. * mono_mb_free:
  171. */
  172. void
  173. mono_mb_free (MonoMethodBuilder *mb)
  174. {
  175. get_mb_cb ()->free (mb);
  176. }
  177. /**
  178. * mono_mb_create_method:
  179. * Create a \c MonoMethod from this method builder.
  180. * \returns the newly created method.
  181. */
  182. MonoMethod *
  183. mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
  184. {
  185. return get_mb_cb ()->create_method (mb, signature, max_stack);
  186. }
  187. /**
  188. * mono_mb_add_data:
  189. */
  190. guint32
  191. mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
  192. {
  193. MonoMethodWrapper *mw;
  194. g_assert (mb != NULL);
  195. mw = (MonoMethodWrapper *)mb->method;
  196. /* one O(n) is enough */
  197. mw->method_data = g_list_prepend ((GList *)mw->method_data, data);
  198. return g_list_length ((GList *)mw->method_data);
  199. }