[runtime] Call error_init instead of mono_error_init (#4425)
[mono.git] / mono / metadata / method-builder.c
index 74b42a204e0695da6718cc55b505a8e26c8e676d..09e6027f4a0d53b7f5c2d50eed49cc7c59b1479b 100644 (file)
@@ -6,10 +6,12 @@
  *
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
 #include "loader.h"
+#include "mono/metadata/abi-details.h"
 #include "mono/metadata/method-builder.h"
 #include "mono/metadata/tabledefs.h"
 #include "mono/metadata/exception.h"
@@ -64,8 +66,11 @@ mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
        m->inline_info = 1;
        m->wrapper_type = type;
 
+#ifndef DISABLE_JIT
        mb->code_size = 40;
-       mb->code = g_malloc (mb->code_size);
+       mb->code = (unsigned char *)g_malloc (mb->code_size);
+       mb->init_locals = TRUE;
+#endif
        /* placeholder for the wrapper always at index 1 */
        mono_mb_add_data (mb, NULL);
 
@@ -92,6 +97,13 @@ mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
 void
 mono_mb_free (MonoMethodBuilder *mb)
 {
+#ifndef DISABLE_JIT
+       GList *l;
+
+       for (l = mb->locals_list; l; l = l->next) {
+               /* Allocated in mono_mb_add_local () */
+               g_free (l->data);
+       }
        g_list_free (mb->locals_list);
        if (!mb->dynamic) {
                g_free (mb->method);
@@ -99,36 +111,27 @@ mono_mb_free (MonoMethodBuilder *mb)
                        g_free (mb->name);
                g_free (mb->code);
        }
+#else
+       g_free (mb->method);
+       if (!mb->no_dup_name)
+               g_free (mb->name);
+#endif
        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)
 {
+#ifndef DISABLE_JIT
        MonoMethodHeader *header;
+#endif
        MonoMethodWrapper *mw;
        MonoImage *image;
        MonoMethod *method;
@@ -139,69 +142,84 @@ mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, in
 
        image = mb->method->klass->image;
 
-       mono_loader_lock (); /*FIXME I think this lock can go.*/
+#ifndef DISABLE_JIT
        if (mb->dynamic) {
                method = mb->method;
+               mw = (MonoMethodWrapper*)method;
 
                method->name = mb->name;
                method->dynamic = TRUE;
 
-               ((MonoMethodNormal *)method)->header = header = (MonoMethodHeader *) 
+               mw->header = header = (MonoMethodHeader *) 
                        g_malloc0 (MONO_SIZEOF_METHOD_HEADER + 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);
+                       header->locals [i] = (MonoType*)l->data;
                }
-       } else {
+       } else
+#endif
+       {
                /* Realloc the method info into a mempool */
 
-               method = mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
+               method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
                memcpy (method, mb->method, sizeof (MonoMethodWrapper));
+               mw = (MonoMethodWrapper*) method;
 
                if (mb->no_dup_name)
                        method->name = mb->name;
                else
                        method->name = mono_image_strdup (image, mb->name);
 
-               ((MonoMethodNormal *)method)->header = header = (MonoMethodHeader *) 
+#ifndef DISABLE_JIT
+               mw->header = header = (MonoMethodHeader *) 
                        mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
 
-               header->code = mono_image_alloc (image, mb->pos);
+               header->code = (const unsigned char *)mono_image_alloc (image, 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;
+                       header->locals [i] = (MonoType*)l->data;
                }
+#endif
        }
 
+#ifndef DISABLE_JIT
+       /* Free the locals list so mono_mb_free () doesn't free the types twice */
+       g_list_free (mb->locals_list);
+       mb->locals_list = NULL;
+#endif
+
+       method->signature = signature;
+       if (!signature->hasthis)
+               method->flags |= METHOD_ATTRIBUTE_STATIC;
+
+#ifndef DISABLE_JIT
        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;
+       header->init_locals = mb->init_locals;
 
        header->num_clauses = mb->num_clauses;
        header->clauses = mb->clauses;
 
        method->skip_visibility = mb->skip_visibility;
+#endif
 
-       mw = (MonoMethodWrapper*) mb->method;
-       i = g_list_length (mw->method_data);
+       i = g_list_length ((GList *)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));
+               l = g_list_reverse ((GList *)mw->method_data);
+               if (method_is_dynamic (method))
+                       data = (void **)g_malloc (sizeof (gpointer) * (i + 1));
                else
-                       data = mono_image_alloc (image, sizeof (gpointer) * (i + 1));
+                       data = (void **)mono_image_alloc (image, sizeof (gpointer) * (i + 1));
                /* store the size in the first element */
                data [0] = GUINT_TO_POINTER (i);
                i = 1;
@@ -210,8 +228,10 @@ mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, in
                }
                g_list_free (l);
 
-               ((MonoMethodWrapper*)method)->method_data = data;
+               mw->method_data = data;
        }
+
+#ifndef DISABLE_JIT
        /*{
                static int total_code = 0;
                static int total_alloc = 0;
@@ -225,7 +245,19 @@ mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, in
        printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, mb->code + mb->pos));
 #endif
 
-       mono_loader_unlock ();
+       if (mb->param_names) {
+               char **param_names = (char **)mono_image_alloc0 (image, signature->param_count * sizeof (gpointer));
+               for (i = 0; i < signature->param_count; ++i)
+                       param_names [i] = mono_image_strdup (image, mb->param_names [i]);
+
+               mono_image_lock (image);
+               if (!image->wrapper_param_names)
+                       image->wrapper_param_names = g_hash_table_new (NULL, NULL);
+               g_hash_table_insert (image->wrapper_param_names, method, param_names);
+               mono_image_unlock (image);
+       }
+#endif
+
        return method;
 }
 
@@ -239,9 +271,33 @@ mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
        mw = (MonoMethodWrapper *)mb->method;
 
        /* one O(n) is enough */
-       mw->method_data = g_list_prepend (mw->method_data, data);
+       mw->method_data = g_list_prepend ((GList *)mw->method_data, data);
 
-       return g_list_length (mw->method_data);
+       return g_list_length ((GList *)mw->method_data);
+}
+
+#ifndef DISABLE_JIT
+
+int
+mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
+{
+       int res;
+       MonoType *t;
+
+       /*
+        * Have to make a copy early since type might be sig->ret,
+        * which is transient, see mono_metadata_signature_dup_internal_with_padding ().
+        */
+       t = mono_metadata_type_dup (NULL, type);
+
+       g_assert (mb != NULL);
+       g_assert (type != NULL);
+
+       res = mb->locals;
+       mb->locals_list = g_list_append (mb->locals_list, t);
+       mb->locals++;
+
+       return res;
 }
 
 void
@@ -264,7 +320,7 @@ 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 = (unsigned char *)g_realloc (mb->code, mb->code_size);
        }
 
        mb->code [mb->pos++] = op;
@@ -287,19 +343,32 @@ 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);
+               mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
        }
 
        mono_mb_patch_addr (mb, mb->pos, data);
        mb->pos += 4;
 }
 
+void
+mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data)
+{
+       if ((mb->pos + 8) >= mb->code_size) {
+               mb->code_size += mb->code_size >> 1;
+               mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
+       }
+
+       mono_mb_patch_addr (mb, mb->pos, data);
+       mono_mb_patch_addr (mb, mb->pos + 4, data >> 32);
+       mb->pos += 8;
+}
+
 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 = (unsigned char *)g_realloc (mb->code, mb->code_size);
        }
 
        mb->code [mb->pos] = data & 0xff;
@@ -405,6 +474,13 @@ mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
        }
 }
 
+void
+mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value)
+{
+       mono_mb_emit_byte (mb, CEE_LDC_I8);
+       mono_mb_emit_i8 (mb, value);
+}
+
 int
 mono_mb_get_label (MonoMethodBuilder *mb)
 {
@@ -495,14 +571,14 @@ mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, cons
 {
        MonoMethod *ctor = NULL;
 
-       MonoClass *mme = mono_class_from_name (mono_defaults.corlib, exc_nspace, exc_name);
+       MonoClass *mme = mono_class_load_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_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, message));
                mono_mb_emit_ldstr (mb, (char*)msg);
                mono_mb_emit_byte (mb, CEE_STIND_REF);
        }
@@ -530,3 +606,17 @@ mono_mb_set_clauses (MonoMethodBuilder *mb, int num_clauses, MonoExceptionClause
        mb->num_clauses = num_clauses;
        mb->clauses = clauses;
 }
+
+/*
+ * mono_mb_set_param_names:
+ *
+ *   PARAM_NAMES should have length equal to the sig->param_count, the caller retains
+ * ownership of the array, and its entries.
+ */
+void
+mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names)
+{
+       mb->param_names = param_names;
+}
+
+#endif /* DISABLE_JIT */