Author: zoltan
Date: 2007-12-23 17:01:31 -0500 (Sun, 23 Dec 2007)
New Revision: 91846
Added:
trunk/mono/mono/metadata/method-builder.c
Modified:
trunk/mono/mono/metadata/ChangeLog
trunk/mono/mono/metadata/Makefile.am
trunk/mono/mono/metadata/marshal.c
trunk/mono/mono/metadata/marshal.h
Log:
2007-12-23 Zoltan Varga <[EMAIL PROTECTED]>
* method-builder.c: New file, extraction of the method builder
functionality
from marshal.c.
* marshal.c: Move the mb functions into method-builder.c.
Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog 2007-12-23 21:47:34 UTC (rev 91845)
+++ trunk/mono/mono/metadata/ChangeLog 2007-12-23 22:01:31 UTC (rev 91846)
@@ -1,5 +1,10 @@
2007-12-23 Zoltan Varga <[EMAIL PROTECTED]>
+ * method-builder.c: New file, extraction of the method builder
functionality
+ from marshal.c.
+
+ * marshal.c: Move the mb functions into method-builder.c.
+
* marshal.h marshal.c: Export some mono_mb_... functions.
* marshal.c: Use mono_mb_get_label () and mono_mb_patch_branch () in
all places.
Modified: trunk/mono/mono/metadata/Makefile.am
===================================================================
--- trunk/mono/mono/metadata/Makefile.am 2007-12-23 21:47:34 UTC (rev
91845)
+++ trunk/mono/mono/metadata/Makefile.am 2007-12-23 22:01:31 UTC (rev
91846)
@@ -53,6 +53,7 @@
sgen-gc.h \
gc.c \
gc-internal.h \
+ method-builder.c \
marshal.c \
marshal.h \
mono-mlist.c \
Modified: trunk/mono/mono/metadata/marshal.c
===================================================================
--- trunk/mono/mono/metadata/marshal.c 2007-12-23 21:47:34 UTC (rev 91845)
+++ trunk/mono/mono/metadata/marshal.c 2007-12-23 22:01:31 UTC (rev 91846)
@@ -1204,233 +1204,6 @@
*((gunichar2 *) dst + len) = 0;
}
-void
-mono_mb_free (MonoMethodBuilder *mb)
-{
- g_list_free (mb->locals_list);
- if (!mb->dynamic) {
- g_free (mb->method);
- if (!mb->no_dup_name)
- g_free (mb->name);
- g_free (mb->code);
- }
- g_free (mb);
-}
-
-static MonoMethodBuilder *
-mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
-{
- MonoMethodBuilder *mb;
- MonoMethod *m;
-
- g_assert (klass != NULL);
-
- mb = g_new0 (MonoMethodBuilder, 1);
-
- mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
-
- m->klass = klass;
- m->inline_info = 1;
- m->wrapper_type = type;
-
- mb->code_size = 40;
- mb->code = g_malloc (mb->code_size);
-
- return mb;
-}
-
-static MonoMethodBuilder *
-mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType
type)
-{
- MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
- mb->name = (char*)name;
- mb->no_dup_name = TRUE;
- return mb;
-}
-
-MonoMethodBuilder *
-mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
-{
- MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
- mb->name = g_strdup (name);
- return mb;
-}
-
-int
-mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
-{
- int res;
-
- g_assert (mb != NULL);
- g_assert (type != NULL);
-
- res = mb->locals;
- mb->locals_list = g_list_append (mb->locals_list, type);
- mb->locals++;
-
- return res;
-}
-
-/**
- * mono_mb_create_method:
- *
- * Create a MonoMethod from this method builder.
- * Returns: the newly created method.
- *
- * LOCKING: Takes the loader lock.
- */
-MonoMethod *
-mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature,
int max_stack)
-{
- MonoMethodHeader *header;
- MonoMethodWrapper *mw;
- MonoMemPool *mp;
- MonoMethod *method;
- GList *l;
- int i;
-
- g_assert (mb != NULL);
-
- mp = mb->method->klass->image->mempool;
-
- mono_loader_lock ();
- if (mb->dynamic) {
- method = mb->method;
-
- method->name = mb->name;
- method->dynamic = TRUE;
-
- ((MonoMethodNormal *)method)->header = header =
(MonoMethodHeader *)
- g_malloc0 (sizeof (MonoMethodHeader) + mb->locals *
sizeof (MonoType *));
-
- header->code = mb->code;
-
- for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
- header->locals [i] = mono_metadata_type_dup (NULL,
(MonoType*)l->data);
- }
- } else {
- /* Realloc the method info into a mempool */
-
- method = mono_mempool_alloc0 (mp, sizeof (MonoMethodWrapper));
- memcpy (method, mb->method, sizeof (MonoMethodWrapper));
-
- if (mb->no_dup_name)
- method->name = mb->name;
- else
- method->name = mono_mempool_strdup (mp, mb->name);
-
- ((MonoMethodNormal *)method)->header = header =
(MonoMethodHeader *)
- mono_mempool_alloc0 (mp, sizeof (MonoMethodHeader) +
mb->locals * sizeof (MonoType *));
-
- header->code = mono_mempool_alloc (mp, mb->pos);
- memcpy ((char*)header->code, mb->code, mb->pos);
-
- for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
- header->locals [i] = (MonoType *)l->data;
- }
- }
-
- if (max_stack < 8)
- max_stack = 8;
-
- header->max_stack = max_stack;
-
- method->signature = signature;
-
- header->code_size = mb->pos;
- header->num_locals = mb->locals;
- header->init_locals = TRUE;
-
- mw = (MonoMethodWrapper*) mb->method;
- i = g_list_length (mw->method_data);
- if (i) {
- GList *tmp;
- void **data;
- l = g_list_reverse (mw->method_data);
- if (method->dynamic)
- data = g_malloc (sizeof (gpointer) * (i + 1));
- else
- data = mono_mempool_alloc (mp, sizeof (gpointer) * (i +
1));
- /* store the size in the first element */
- data [0] = GUINT_TO_POINTER (i);
- i = 1;
- for (tmp = l; tmp; tmp = tmp->next) {
- data [i++] = tmp->data;
- }
- g_list_free (l);
-
- ((MonoMethodWrapper*)method)->method_data = data;
- }
- /*{
- static int total_code = 0;
- static int total_alloc = 0;
- total_code += mb->pos;
- total_alloc += mb->code_size;
- g_print ("code size: %d of %d (allocated: %d)\n", mb->pos,
total_code, total_alloc);
- }*/
-
-#ifdef DEBUG_RUNTIME_CODE
- printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
- printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code,
mb->code + mb->pos));
-#endif
-
- mono_loader_unlock ();
- return method;
-}
-
-guint32
-mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
-{
- MonoMethodWrapper *mw;
-
- g_assert (mb != NULL);
-
- mw = (MonoMethodWrapper *)mb->method;
-
- /* one O(n) is enough */
- mw->method_data = g_list_prepend (mw->method_data, data);
-
- return g_list_length (mw->method_data);
-}
-
-void
-mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
-{
- mb->code [pos] = value & 0xff;
- mb->code [pos + 1] = (value >> 8) & 0xff;
- mb->code [pos + 2] = (value >> 16) & 0xff;
- mb->code [pos + 3] = (value >> 24) & 0xff;
-}
-
-void
-mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
-{
- *((gint8 *)(&mb->code [pos])) = value;
-}
-
-void
-mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
-{
- if (mb->pos >= mb->code_size) {
- mb->code_size += mb->code_size >> 1;
- mb->code = g_realloc (mb->code, mb->code_size);
- }
-
- mb->code [mb->pos++] = op;
-}
-
-void
-mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
-{
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
-
- if (offset) {
- mono_mb_emit_icon (mb, offset);
- mono_mb_emit_byte (mb, CEE_ADD);
- }
-}
-
static int
mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
{
@@ -1464,206 +1237,7 @@
return pos;
}
-void
-mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
-{
- if ((mb->pos + 4) >= mb->code_size) {
- mb->code_size += mb->code_size >> 1;
- mb->code = g_realloc (mb->code, mb->code_size);
- }
-
- mono_mb_patch_addr (mb, mb->pos, data);
- mb->pos += 4;
-}
-
-void
-mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
-{
- if ((mb->pos + 2) >= mb->code_size) {
- mb->code_size += mb->code_size >> 1;
- mb->code = g_realloc (mb->code, mb->code_size);
- }
-
- mb->code [mb->pos] = data & 0xff;
- mb->code [mb->pos + 1] = (data >> 8) & 0xff;
- mb->pos += 2;
-}
-
-void
-mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
-{
- mono_mb_emit_byte (mb, op);
- mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
-}
-
-void
-mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
-{
- mono_mb_emit_op (mb, CEE_LDSTR, str);
-}
-
-void
-mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
-{
- if (argnum < 4) {
- mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
- } else if (argnum < 256) {
- mono_mb_emit_byte (mb, CEE_LDARG_S);
- mono_mb_emit_byte (mb, argnum);
- } else {
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_LDARG);
- mono_mb_emit_i2 (mb, argnum);
- }
-}
-
-void
-mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
-{
- if (argnum < 256) {
- mono_mb_emit_byte (mb, CEE_LDARGA_S);
- mono_mb_emit_byte (mb, argnum);
- } else {
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_LDARGA);
- mono_mb_emit_i2 (mb, argnum);
- }
-}
-
-void
-mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
-{
- if (locnum < 256) {
- mono_mb_emit_byte (mb, CEE_LDLOCA_S);
- mono_mb_emit_byte (mb, locnum);
- } else {
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_LDLOCA);
- mono_mb_emit_i2 (mb, locnum);
- }
-}
-
-void
-mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
-{
- if (num < 4) {
- mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
- } else if (num < 256) {
- mono_mb_emit_byte (mb, CEE_LDLOC_S);
- mono_mb_emit_byte (mb, num);
- } else {
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_LDLOC);
- mono_mb_emit_i2 (mb, num);
- }
-}
-
-void
-mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
-{
- if (num < 4) {
- mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
- } else if (num < 256) {
- mono_mb_emit_byte (mb, CEE_STLOC_S);
- mono_mb_emit_byte (mb, num);
- } else {
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_STLOC);
- mono_mb_emit_i2 (mb, num);
- }
-}
-
-void
-mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
-{
- if (value >= -1 && value < 8) {
- mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
- } else if (value >= -128 && value <= 127) {
- mono_mb_emit_byte (mb, CEE_LDC_I4_S);
- mono_mb_emit_byte (mb, value);
- } else {
- mono_mb_emit_byte (mb, CEE_LDC_I4);
- mono_mb_emit_i4 (mb, value);
- }
-}
-
-int
-mono_mb_get_label (MonoMethodBuilder *mb)
-{
- return mb->pos;
-}
-
-guint32
-mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
-{
- guint32 res;
- mono_mb_emit_byte (mb, op);
- res = mb->pos;
- mono_mb_emit_i4 (mb, 0);
- return res;
-}
-
-guint32
-mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
-{
- guint32 res;
- mono_mb_emit_byte (mb, op);
- res = mb->pos;
- mono_mb_emit_byte (mb, 0);
-
- return res;
-}
-
-void
-mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
-{
- mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
-}
-
-void
-mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
-{
- mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
-}
-
static void
-mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
-{
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
-}
-
-void
-mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
-{
- mono_mb_emit_op (mb, CEE_CALLI, sig);
-}
-
-void
-mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method,
MonoMethodSignature *opt_sig)
-{
- mono_mb_emit_op (mb, CEE_CALL, method);
-}
-
-void
-mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig,
gpointer func)
-{
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
- mono_mb_emit_ptr (mb, func);
- mono_mb_emit_calli (mb, sig);
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
-}
-
-void
-mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
-{
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
-}
-
-static void
mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig,
MonoMethod* method)
{
// get function pointer from 1st arg, the COM interface pointer
@@ -1678,46 +1252,12 @@
mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
}
-void
-mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace,
const char *exc_name, const char *msg)
-{
- MonoMethod *ctor = NULL;
-
- MonoClass *mme = mono_class_from_name (mono_defaults.corlib,
exc_nspace, exc_name);
- mono_class_init (mme);
- ctor = mono_class_get_method_from_name (mme, ".ctor", 0);
- g_assert (ctor);
- mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
- if (msg != NULL) {
- mono_mb_emit_byte (mb, CEE_DUP);
- mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException,
message));
- mono_mb_emit_ldstr (mb, (char*)msg);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- }
- mono_mb_emit_byte (mb, CEE_THROW);
-}
-
-void
-mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const
char *msg)
-{
- mono_mb_emit_exception_full (mb, "System", exc_name, msg);
-}
-
static void
mono_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, const char
*msg)
{
mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices",
"MarshalDirectiveException", msg);
}
-void
-mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
-{
- mono_mb_emit_ldloc (mb, local);
- mono_mb_emit_icon (mb, incr);
- mono_mb_emit_byte (mb, CEE_ADD);
- mono_mb_emit_stloc (mb, local);
-}
-
guint
mono_type_to_ldind (MonoType *type)
{
Modified: trunk/mono/mono/metadata/marshal.h
===================================================================
--- trunk/mono/mono/metadata/marshal.h 2007-12-23 21:47:34 UTC (rev 91845)
+++ trunk/mono/mono/metadata/marshal.h 2007-12-23 22:01:31 UTC (rev 91846)
@@ -95,13 +95,16 @@
/* method builder functions */
-void
-mono_mb_free (MonoMethodBuilder *mb) MONO_INTERNAL;
-
MonoMethodBuilder *
mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
MONO_INTERNAL;
+MonoMethodBuilder *
+mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType
type) MONO_INTERNAL;
+
void
+mono_mb_free (MonoMethodBuilder *mb) MONO_INTERNAL;
+
+void
mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value) MONO_INTERNAL;
void
@@ -120,6 +123,9 @@
mono_mb_add_data (MonoMethodBuilder *mb, gpointer data) MONO_INTERNAL;
void
+mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr) MONO_INTERNAL;
+
+void
mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
MONO_INTERNAL;
void
Added: trunk/mono/mono/metadata/method-builder.c
===================================================================
--- trunk/mono/mono/metadata/method-builder.c 2007-12-23 21:47:34 UTC (rev
91845)
+++ trunk/mono/mono/metadata/method-builder.c 2007-12-23 22:01:31 UTC (rev
91846)
@@ -0,0 +1,528 @@
+/*
+ * method-builder.c: Functions for creating IL methods at runtime.
+ *
+ * Author:
+ * Paolo Molaro ([EMAIL PROTECTED])
+ *
+ * (C) 2002 Ximian, Inc. http://www.ximian.com
+ *
+ */
+
+#include "config.h"
+#include "object.h"
+#include "loader.h"
+#include "metadata/marshal.h"
+#include "metadata/tabledefs.h"
+#include "metadata/exception.h"
+#include "metadata/appdomain.h"
+#include "mono/metadata/debug-helpers.h"
+#include "mono/metadata/threadpool.h"
+#include "mono/metadata/threads.h"
+#include "mono/metadata/monitor.h"
+#include "mono/metadata/metadata-internals.h"
+#include "mono/metadata/domain-internals.h"
+#include "mono/metadata/gc-internal.h"
+#include "mono/metadata/threads-types.h"
+#include "mono/metadata/string-icalls.h"
+#include <mono/os/gc_wrapper.h>
+#include <string.h>
+#include <errno.h>
+
+/* #define DEBUG_RUNTIME_CODE */
+
+#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
+ a = i,
+
+enum {
+#include "mono/cil/opcode.def"
+ LAST = 0xff
+};
+#undef OPDEF
+
+struct _MonoMethodBuilder {
+ MonoMethod *method;
+ char *name;
+ GList *locals_list;
+ int locals;
+ gboolean dynamic;
+ gboolean no_dup_name;
+ guint32 code_size, pos;
+ unsigned char *code;
+};
+
+#ifdef DEBUG_RUNTIME_CODE
+static char*
+indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
+{
+ return g_strdup (" ");
+}
+
+static MonoDisHelper marshal_dh = {
+ "\n",
+ "IL_%04x: ",
+ "IL_%04x",
+ indenter,
+ NULL,
+ NULL
+};
+#endif
+
+static MonoMethodBuilder *
+mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
+{
+ MonoMethodBuilder *mb;
+ MonoMethod *m;
+
+ g_assert (klass != NULL);
+
+ mb = g_new0 (MonoMethodBuilder, 1);
+
+ mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
+
+ m->klass = klass;
+ m->inline_info = 1;
+ m->wrapper_type = type;
+
+ mb->code_size = 40;
+ mb->code = g_malloc (mb->code_size);
+
+ return mb;
+}
+
+MonoMethodBuilder *
+mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType
type)
+{
+ MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
+ mb->name = (char*)name;
+ mb->no_dup_name = TRUE;
+ return mb;
+}
+
+MonoMethodBuilder *
+mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
+{
+ MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
+ mb->name = g_strdup (name);
+ return mb;
+}
+
+void
+mono_mb_free (MonoMethodBuilder *mb)
+{
+ g_list_free (mb->locals_list);
+ if (!mb->dynamic) {
+ g_free (mb->method);
+ if (!mb->no_dup_name)
+ g_free (mb->name);
+ g_free (mb->code);
+ }
+ g_free (mb);
+}
+
+int
+mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
+{
+ int res;
+
+ g_assert (mb != NULL);
+ g_assert (type != NULL);
+
+ res = mb->locals;
+ mb->locals_list = g_list_append (mb->locals_list, type);
+ mb->locals++;
+
+ return res;
+}
+
+/**
+ * mono_mb_create_method:
+ *
+ * Create a MonoMethod from this method builder.
+ * Returns: the newly created method.
+ *
+ * LOCKING: Takes the loader lock.
+ */
+MonoMethod *
+mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature,
int max_stack)
+{
+ MonoMethodHeader *header;
+ MonoMethodWrapper *mw;
+ MonoMemPool *mp;
+ MonoMethod *method;
+ GList *l;
+ int i;
+
+ g_assert (mb != NULL);
+
+ mp = mb->method->klass->image->mempool;
+
+ mono_loader_lock ();
+ if (mb->dynamic) {
+ method = mb->method;
+
+ method->name = mb->name;
+ method->dynamic = TRUE;
+
+ ((MonoMethodNormal *)method)->header = header =
(MonoMethodHeader *)
+ g_malloc0 (sizeof (MonoMethodHeader) + mb->locals *
sizeof (MonoType *));
+
+ header->code = mb->code;
+
+ for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
+ header->locals [i] = mono_metadata_type_dup (NULL,
(MonoType*)l->data);
+ }
+ } else {
+ /* Realloc the method info into a mempool */
+
+ method = mono_mempool_alloc0 (mp, sizeof (MonoMethodWrapper));
+ memcpy (method, mb->method, sizeof (MonoMethodWrapper));
+
+ if (mb->no_dup_name)
+ method->name = mb->name;
+ else
+ method->name = mono_mempool_strdup (mp, mb->name);
+
+ ((MonoMethodNormal *)method)->header = header =
(MonoMethodHeader *)
+ mono_mempool_alloc0 (mp, sizeof (MonoMethodHeader) +
mb->locals * sizeof (MonoType *));
+
+ header->code = mono_mempool_alloc (mp, mb->pos);
+ memcpy ((char*)header->code, mb->code, mb->pos);
+
+ for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
+ header->locals [i] = (MonoType *)l->data;
+ }
+ }
+
+ if (max_stack < 8)
+ max_stack = 8;
+
+ header->max_stack = max_stack;
+
+ method->signature = signature;
+
+ header->code_size = mb->pos;
+ header->num_locals = mb->locals;
+ header->init_locals = TRUE;
+
+ mw = (MonoMethodWrapper*) mb->method;
+ i = g_list_length (mw->method_data);
+ if (i) {
+ GList *tmp;
+ void **data;
+ l = g_list_reverse (mw->method_data);
+ if (method->dynamic)
+ data = g_malloc (sizeof (gpointer) * (i + 1));
+ else
+ data = mono_mempool_alloc (mp, sizeof (gpointer) * (i +
1));
+ /* store the size in the first element */
+ data [0] = GUINT_TO_POINTER (i);
+ i = 1;
+ for (tmp = l; tmp; tmp = tmp->next) {
+ data [i++] = tmp->data;
+ }
+ g_list_free (l);
+
+ ((MonoMethodWrapper*)method)->method_data = data;
+ }
+ /*{
+ static int total_code = 0;
+ static int total_alloc = 0;
+ total_code += mb->pos;
+ total_alloc += mb->code_size;
+ g_print ("code size: %d of %d (allocated: %d)\n", mb->pos,
total_code, total_alloc);
+ }*/
+
+#ifdef DEBUG_RUNTIME_CODE
+ printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
+ printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code,
mb->code + mb->pos));
+#endif
+
+ mono_loader_unlock ();
+ return method;
+}
+
+guint32
+mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
+{
+ MonoMethodWrapper *mw;
+
+ g_assert (mb != NULL);
+
+ mw = (MonoMethodWrapper *)mb->method;
+
+ /* one O(n) is enough */
+ mw->method_data = g_list_prepend (mw->method_data, data);
+
+ return g_list_length (mw->method_data);
+}
+
+void
+mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
+{
+ mb->code [pos] = value & 0xff;
+ mb->code [pos + 1] = (value >> 8) & 0xff;
+ mb->code [pos + 2] = (value >> 16) & 0xff;
+ mb->code [pos + 3] = (value >> 24) & 0xff;
+}
+
+void
+mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
+{
+ *((gint8 *)(&mb->code [pos])) = value;
+}
+
+void
+mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
+{
+ if (mb->pos >= mb->code_size) {
+ mb->code_size += mb->code_size >> 1;
+ mb->code = g_realloc (mb->code, mb->code_size);
+ }
+
+ mb->code [mb->pos++] = op;
+}
+
+void
+mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
+{
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+
+ if (offset) {
+ mono_mb_emit_icon (mb, offset);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ }
+}
+
+void
+mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
+{
+ if ((mb->pos + 4) >= mb->code_size) {
+ mb->code_size += mb->code_size >> 1;
+ mb->code = g_realloc (mb->code, mb->code_size);
+ }
+
+ mono_mb_patch_addr (mb, mb->pos, data);
+ mb->pos += 4;
+}
+
+void
+mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
+{
+ if ((mb->pos + 2) >= mb->code_size) {
+ mb->code_size += mb->code_size >> 1;
+ mb->code = g_realloc (mb->code, mb->code_size);
+ }
+
+ mb->code [mb->pos] = data & 0xff;
+ mb->code [mb->pos + 1] = (data >> 8) & 0xff;
+ mb->pos += 2;
+}
+
+void
+mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
+{
+ mono_mb_emit_byte (mb, op);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
+}
+
+void
+mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
+{
+ mono_mb_emit_op (mb, CEE_LDSTR, str);
+}
+
+void
+mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
+{
+ if (argnum < 4) {
+ mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
+ } else if (argnum < 256) {
+ mono_mb_emit_byte (mb, CEE_LDARG_S);
+ mono_mb_emit_byte (mb, argnum);
+ } else {
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LDARG);
+ mono_mb_emit_i2 (mb, argnum);
+ }
+}
+
+void
+mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
+{
+ if (argnum < 256) {
+ mono_mb_emit_byte (mb, CEE_LDARGA_S);
+ mono_mb_emit_byte (mb, argnum);
+ } else {
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LDARGA);
+ mono_mb_emit_i2 (mb, argnum);
+ }
+}
+
+void
+mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
+{
+ if (locnum < 256) {
+ mono_mb_emit_byte (mb, CEE_LDLOCA_S);
+ mono_mb_emit_byte (mb, locnum);
+ } else {
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LDLOCA);
+ mono_mb_emit_i2 (mb, locnum);
+ }
+}
+
+void
+mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
+{
+ if (num < 4) {
+ mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
+ } else if (num < 256) {
+ mono_mb_emit_byte (mb, CEE_LDLOC_S);
+ mono_mb_emit_byte (mb, num);
+ } else {
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LDLOC);
+ mono_mb_emit_i2 (mb, num);
+ }
+}
+
+void
+mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
+{
+ if (num < 4) {
+ mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
+ } else if (num < 256) {
+ mono_mb_emit_byte (mb, CEE_STLOC_S);
+ mono_mb_emit_byte (mb, num);
+ } else {
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_STLOC);
+ mono_mb_emit_i2 (mb, num);
+ }
+}
+
+void
+mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
+{
+ if (value >= -1 && value < 8) {
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
+ } else if (value >= -128 && value <= 127) {
+ mono_mb_emit_byte (mb, CEE_LDC_I4_S);
+ mono_mb_emit_byte (mb, value);
+ } else {
+ mono_mb_emit_byte (mb, CEE_LDC_I4);
+ mono_mb_emit_i4 (mb, value);
+ }
+}
+
+int
+mono_mb_get_label (MonoMethodBuilder *mb)
+{
+ return mb->pos;
+}
+
+guint32
+mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
+{
+ guint32 res;
+ mono_mb_emit_byte (mb, op);
+ res = mb->pos;
+ mono_mb_emit_i4 (mb, 0);
+ return res;
+}
+
+guint32
+mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
+{
+ guint32 res;
+ mono_mb_emit_byte (mb, op);
+ res = mb->pos;
+ mono_mb_emit_byte (mb, 0);
+
+ return res;
+}
+
+void
+mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
+{
+ mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
+}
+
+void
+mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
+{
+ mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
+}
+
+void
+mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
+{
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
+}
+
+void
+mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
+{
+ mono_mb_emit_op (mb, CEE_CALLI, sig);
+}
+
+void
+mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method,
MonoMethodSignature *opt_sig)
+{
+ mono_mb_emit_op (mb, CEE_CALL, method);
+}
+
+void
+mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig,
gpointer func)
+{
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
+ mono_mb_emit_ptr (mb, func);
+ mono_mb_emit_calli (mb, sig);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
+}
+
+void
+mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
+{
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
+}
+
+void
+mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace,
const char *exc_name, const char *msg)
+{
+ MonoMethod *ctor = NULL;
+
+ MonoClass *mme = mono_class_from_name (mono_defaults.corlib,
exc_nspace, exc_name);
+ mono_class_init (mme);
+ ctor = mono_class_get_method_from_name (mme, ".ctor", 0);
+ g_assert (ctor);
+ mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
+ if (msg != NULL) {
+ mono_mb_emit_byte (mb, CEE_DUP);
+ mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException,
message));
+ mono_mb_emit_ldstr (mb, (char*)msg);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ }
+ mono_mb_emit_byte (mb, CEE_THROW);
+}
+
+void
+mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const
char *msg)
+{
+ mono_mb_emit_exception_full (mb, "System", exc_name, msg);
+}
+
+void
+mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
+{
+ mono_mb_emit_ldloc (mb, local);
+ mono_mb_emit_icon (mb, incr);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_stloc (mb, local);
+}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches