#include <mono/metadata/object.h>
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/exception.h>
+#include <mono/metadata/exception-internals.h>
#include <mono/metadata/domain-internals.h>
#include "mono/metadata/metadata-internals.h"
#include "mono/metadata/class-internals.h"
#define ldstr_unlock() mono_os_mutex_unlock (&ldstr_section)
static mono_mutex_t ldstr_section;
+/**
+ * mono_runtime_object_init:
+ * @this_obj: the object to initialize
+ *
+ * This function calls the zero-argument constructor (which must
+ * exist) for the given object.
+ */
void
mono_runtime_object_init (MonoObject *this_obj)
+{
+ MonoError error;
+ mono_runtime_object_init_checked (this_obj, &error);
+ mono_error_assert_ok (&error);
+}
+
+/**
+ * mono_runtime_object_init_checked:
+ * @this_obj: the object to initialize
+ * @error: set on error.
+ *
+ * This function calls the zero-argument constructor (which must
+ * exist) for the given object and returns TRUE on success, or FALSE
+ * on error and sets @error.
+ */
+gboolean
+mono_runtime_object_init_checked (MonoObject *this_obj, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoError error;
MonoMethod *method = NULL;
MonoClass *klass = this_obj->vtable->klass;
+ mono_error_init (error);
method = mono_class_get_method_from_name (klass, ".ctor", 0);
if (!method)
g_error ("Could not lookup zero argument constructor for class %s", mono_type_get_full_name (klass));
if (method->klass->valuetype)
this_obj = (MonoObject *)mono_object_unbox (this_obj);
- mono_runtime_invoke_checked (method, this_obj, NULL, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_runtime_invoke_checked (method, this_obj, NULL, error);
+ return is_ok (error);
}
/* The pseudo algorithm for type initialization from the spec
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
MonoDomain *domain = vtable->domain;
MonoClass *klass = vtable->klass;
MonoException *ex;
full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
else
full_name = g_strdup (klass->name);
- ex = mono_get_exception_type_initialization (full_name, NULL);
+ ex = mono_get_exception_type_initialization_checked (full_name, NULL, &error);
g_free (full_name);
+ return_val_if_nok (&error, NULL);
}
return ex;
}
+
/*
* mono_runtime_class_init:
* @vtable: vtable that needs to be initialized
mono_runtime_class_init (MonoVTable *vtable)
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
- mono_runtime_class_init_full (vtable, TRUE);
+ mono_runtime_class_init_full (vtable, &error);
+ mono_error_assert_ok (&error);
}
-/*
+/**
* mono_runtime_class_init_full:
* @vtable that neeeds to be initialized
- * @raise_exception is TRUE, exceptions are raised intead of returned
+ * @error set on error
+ *
+ * returns TRUE if class constructor .cctor has been initialized successfully, or FALSE otherwise and sets @error.
*
*/
-MonoException *
-mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
+gboolean
+mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoError error;
- MonoException *exc;
- MonoException *exc_to_throw;
MonoMethod *method = NULL;
MonoClass *klass;
gchar *full_name;
int do_initialization = 0;
MonoDomain *last_domain = NULL;
+ mono_error_init (error);
+
if (vtable->initialized)
- return NULL;
+ return TRUE;
- exc = NULL;
klass = vtable->klass;
if (!klass->image->checked_module_cctor) {
mono_image_check_for_module_cctor (klass->image);
if (klass->image->has_module_cctor) {
- MonoError error;
MonoClass *module_klass;
MonoVTable *module_vtable;
- module_klass = mono_class_get_checked (klass->image, MONO_TOKEN_TYPE_DEF | 1, &error);
+ module_klass = mono_class_get_checked (klass->image, MONO_TOKEN_TYPE_DEF | 1, error);
if (!module_klass) {
- exc = mono_error_convert_to_exception (&error);
- if (raise_exception)
- mono_raise_exception (exc);
- return exc;
+ return FALSE;
}
- module_vtable = mono_class_vtable_full (vtable->domain, module_klass, raise_exception);
+ module_vtable = mono_class_vtable_full (vtable->domain, module_klass, error);
if (!module_vtable)
- return NULL;
- exc = mono_runtime_class_init_full (module_vtable, raise_exception);
- if (exc)
- return exc;
+ return FALSE;
+ if (!mono_runtime_class_init_full (module_vtable, error))
+ return FALSE;
}
}
method = mono_class_get_cctor (klass);
if (!method) {
vtable->initialized = 1;
- return NULL;
+ return TRUE;
}
tid = mono_native_thread_id_get ();
/* double check... */
if (vtable->initialized) {
mono_type_initialization_unlock ();
- return NULL;
+ return TRUE;
}
if (vtable->init_failed) {
mono_type_initialization_unlock ();
/* The type initialization already failed once, rethrow the same exception */
- if (raise_exception)
- mono_raise_exception (get_type_init_exception_for_vtable (vtable));
- return get_type_init_exception_for_vtable (vtable);
+ mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
+ return FALSE;
}
lock = (TypeInitializationLock *)g_hash_table_lookup (type_initialization_hash, vtable);
if (lock == NULL) {
if (!mono_domain_set (domain, FALSE)) {
vtable->initialized = 1;
mono_type_initialization_unlock ();
- if (raise_exception)
- mono_raise_exception (mono_get_exception_appdomain_unloaded ());
- return mono_get_exception_appdomain_unloaded ();
+ mono_error_set_exception_instance (error, mono_get_exception_appdomain_unloaded ());
+ return FALSE;
}
}
lock = (TypeInitializationLock *)g_malloc (sizeof (TypeInitializationLock));
if (mono_native_thread_id_equals (lock->initializing_tid, tid) || lock->done) {
mono_type_initialization_unlock ();
- return NULL;
+ return TRUE;
}
/* see if the thread doing the initialization is already blocked on this thread */
blocked = GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (lock->initializing_tid));
if (mono_native_thread_id_equals (pending_lock->initializing_tid, tid)) {
if (!pending_lock->done) {
mono_type_initialization_unlock ();
- return NULL;
+ return TRUE;
} else {
/* the thread doing the initialization is blocked on this thread,
but on a lock that has already been freed. It just hasn't got
mono_type_initialization_unlock ();
if (do_initialization) {
- mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, &error);
- if (exc == NULL && !mono_error_ok (&error))
- exc = mono_error_convert_to_exception (&error);
- else
- mono_error_cleanup (&error);
+ MonoException *exc = NULL;
+ mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error);
+ if (exc != NULL && mono_error_ok (error)) {
+ mono_error_set_exception_instance (error, exc);
+ }
/* If the initialization failed, mark the class as unusable. */
/* Avoid infinite loops */
- if (!(exc == NULL ||
+ if (!(mono_error_ok(error) ||
(klass->image == mono_defaults.corlib &&
!strcmp (klass->name_space, "System") &&
!strcmp (klass->name, "TypeInitializationException")))) {
full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
else
full_name = g_strdup (klass->name);
- exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
+
+ MonoException *exc_to_throw = mono_get_exception_type_initialization_checked (full_name, exc, error);
g_free (full_name);
+ return_val_if_nok (error, FALSE);
+ mono_error_set_exception_instance (error, exc_to_throw);
+
+ MonoException *exc_to_store = mono_error_convert_to_exception (error);
+ /* What we really want to do here is clone the error object and store one copy in the
+ * domain's exception hash and use the other one to error out here. */
+ mono_error_set_exception_instance (error, exc_to_store);
/*
* Store the exception object so it could be thrown on subsequent
* accesses.
mono_domain_lock (domain);
if (!domain->type_init_exception_hash)
domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "type initialization exceptions table");
- mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
+ mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_store);
mono_domain_unlock (domain);
}
if (vtable->init_failed) {
/* Either we were the initializing thread or we waited for the initialization */
- if (raise_exception)
- mono_raise_exception (get_type_init_exception_for_vtable (vtable));
- return get_type_init_exception_for_vtable (vtable);
+ mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
+ return FALSE;
}
- return NULL;
+ return TRUE;
}
static
mono_domain_unlock (domain);
}
-static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean raise_on_error);
+static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoError *error);
/**
* mono_class_vtable:
MonoVTable *
mono_class_vtable (MonoDomain *domain, MonoClass *klass)
{
- return mono_class_vtable_full (domain, klass, FALSE);
+ MonoError error;
+ MonoVTable* vtable = mono_class_vtable_full (domain, klass, &error);
+ mono_error_cleanup (&error);
+ return vtable;
}
/**
* mono_class_vtable_full:
* @domain: the application domain
* @class: the class to initialize
- * @raise_on_error if an exception should be raised on failure or not
+ * @error set on failure.
*
* VTables are domain specific because we create domain specific code, and
* they contain the domain specific static class data.
*/
MonoVTable *
-mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, gboolean raise_on_error)
+mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
MonoClassRuntimeInfo *runtime_info;
+ mono_error_init (error);
+
g_assert (klass);
if (mono_class_has_failure (klass)) {
- if (raise_on_error)
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
return NULL;
}
runtime_info = klass->runtime_info;
if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id])
return runtime_info->domain_vtables [domain->domain_id];
- return mono_class_create_runtime_vtable (domain, klass, raise_on_error);
+ return mono_class_create_runtime_vtable (domain, klass, error);
}
/**
}
static MonoVTable *
-mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean raise_on_error)
+mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoError error;
MonoVTable *vt;
MonoClassRuntimeInfo *runtime_info, *old_info;
MonoClassField *field;
gpointer iter;
gpointer *interface_offsets;
+ mono_error_init (error);
+
mono_loader_lock (); /*FIXME mono_class_init acquires it*/
mono_domain_lock (domain);
runtime_info = klass->runtime_info;
if (!mono_class_init (klass) || mono_class_has_failure (klass)) {
mono_domain_unlock (domain);
mono_loader_unlock ();
- if (raise_on_error)
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
return NULL;
}
}
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
mono_domain_unlock (domain);
mono_loader_unlock ();
- if (raise_on_error)
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
return NULL;
}
}
if (mono_class_has_failure (klass)) {
mono_domain_unlock (domain);
mono_loader_unlock ();
- if (raise_on_error)
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
return NULL;
}
cm = klass->vtable [i];
if (cm) {
- vt->vtable [i] = callbacks.create_jit_trampoline (domain, cm, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+ vt->vtable [i] = callbacks.create_jit_trampoline (domain, cm, error);
+ if (!is_ok (error)) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return NULL;
+ }
}
}
}
*/
/* Special case System.MonoType to avoid infinite recursion */
if (klass != mono_defaults.monotype_class) {
- /*FIXME check for OOM*/
- vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, error);
+ if (!is_ok (error)) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return NULL;
+ }
if (mono_object_get_class ((MonoObject *)vt->type) != mono_defaults.monotype_class)
/* This is unregistered in
}
if (klass == mono_defaults.monotype_class) {
- /*FIXME check for OOM*/
- vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, error);
+ if (!is_ok (error)) {
+ mono_domain_unlock (domain);
+ mono_loader_unlock ();
+ return NULL;
+ }
if (mono_object_get_class ((MonoObject *)vt->type) != mono_defaults.monotype_class)
/* This is unregistered in
/* make sure the parent is initialized */
/*FIXME shouldn't this fail the current type?*/
if (klass->parent)
- mono_class_vtable_full (domain, klass->parent, raise_on_error);
+ mono_class_vtable_full (domain, klass->parent, error);
return vt;
}
MonoType *type = mono_field_get_type_checked (field, &error);
if (!mono_error_ok (&error))
- mono_error_raise_exception (&error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
switch (type->type) {
case MONO_TYPE_STRING:
is_static = TRUE;
if (!is_literal) {
- vtable = mono_class_vtable_full (domain, field->parent, TRUE);
- if (!vtable->initialized)
- mono_runtime_class_init (vtable);
+ vtable = mono_class_vtable_full (domain, field->parent, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+ if (!vtable->initialized) {
+ mono_runtime_class_init_full (vtable, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
}
} else {
g_assert (obj);
if (G_UNLIKELY (!o))
mono_error_set_out_of_memory (error, "Could not allocate %i bytes", mono_class_instance_size (klass));
else if (G_UNLIKELY (vtable->klass->has_finalize))
- mono_object_register_finalizer (o);
+ mono_object_register_finalizer (o, error);
return o;
}
if (G_UNLIKELY (!o))
mono_error_set_out_of_memory (error, "Could not allocate %i bytes", vtable->klass->instance_size);
else if (G_UNLIKELY (vtable->klass->has_finalize))
- mono_object_register_finalizer (o);
+ mono_object_register_finalizer (o, error);
return o;
}
if (G_UNLIKELY (!o))
mono_error_set_out_of_memory (error, "Could not allocate %i bytes", vtable->klass->instance_size);
else if (G_UNLIKELY (vtable->klass->has_finalize))
- mono_object_register_finalizer (o);
+ mono_object_register_finalizer (o, error);
return o;
}
mono_gc_wbarrier_object_copy (o, obj);
if (obj->vtable->klass->has_finalize)
- mono_object_register_finalizer (o);
+ mono_object_register_finalizer (o, error);
return o;
}
* Following three lines almost taken from mono_object_new ():
* they need to be kept in sync.
*/
- vtable = mono_class_vtable_full (domain, array_class, TRUE);
+ vtable = mono_class_vtable_full (domain, array_class, error);
+ return_val_if_nok (error, NULL);
+
if (bounds_size)
o = (MonoObject *)mono_gc_alloc_array (vtable, byte_len, len, bounds_size);
else
ac = mono_array_class_get (eclass, 1);
g_assert (ac);
- arr = mono_array_new_specific_checked (mono_class_vtable_full (domain, ac, TRUE), n, &error);
+ MonoVTable *vtable = mono_class_vtable_full (domain, ac, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+ arr = mono_array_new_specific_checked (vtable, n, &error);
mono_error_raise_exception (&error); /* FIXME don't raise here */
return arr;
}
#endif
#endif
- if (klass->has_finalize)
- mono_object_register_finalizer (res);
+ if (klass->has_finalize) {
+ mono_object_register_finalizer (res, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
return res;
}
}
static MonoString*
-mono_string_is_interned_lookup (MonoString *str, int insert)
+mono_string_is_interned_lookup (MonoString *str, int insert, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoError error;
MonoGHashTable *ldstr_table;
MonoString *s, *res;
MonoDomain *domain;
+ mono_error_init (error);
+
domain = ((MonoObject *)str)->vtable->domain;
ldstr_table = domain->ldstr_table;
ldstr_lock ();
if (insert) {
/* Allocate outside the lock */
ldstr_unlock ();
- s = mono_string_get_pinned (str, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ s = mono_string_get_pinned (str, error);
+ return_val_if_nok (error, NULL);
if (s) {
ldstr_lock ();
res = (MonoString *)mono_g_hash_table_lookup (ldstr_table, str);
MonoString*
mono_string_is_interned (MonoString *o)
{
- MONO_REQ_GC_UNSAFE_MODE;
-
- return mono_string_is_interned_lookup (o, FALSE);
+ MonoError error;
+ MonoString *result = mono_string_is_interned_lookup (o, FALSE, &error);
+ /* This function does not fail. */
+ mono_error_assert_ok (&error);
+ return result;
}
/**
*/
MonoString*
mono_string_intern (MonoString *str)
+{
+ MonoError error;
+ MonoString *result = mono_string_intern_checked (str, &error);
+ mono_error_assert_ok (&error);
+ return result;
+}
+
+/**
+ * mono_string_intern_checked:
+ * @o: String to intern
+ * @error: set on error.
+ *
+ * Interns the string passed.
+ * Returns: The interned string. On failure returns NULL and sets @error
+ */
+MonoString*
+mono_string_intern_checked (MonoString *str, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- return mono_string_is_interned_lookup (str, TRUE);
+ mono_error_init (error);
+
+ return mono_string_is_interned_lookup (str, TRUE, error);
}
/**
* Returns: the result object.
*/
MonoObject *
-mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
- MonoObject **exc, MonoArray **out_args)
+mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject **exc, MonoArray **out_args, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoError error;
MonoObject *o;
MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
gpointer pa [4];
+ g_assert (exc);
+
+ mono_error_init (error);
+
/*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
if (!im) {
im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
- if (!im)
- mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+ if (!im) {
+ mono_error_set_generic_error (error, "System", "NotSupportedException", "Linked away.");
+ return NULL;
+ }
real_proxy->vtable->domain->private_invoke_method = im;
}
pa [2] = exc;
pa [3] = out_args;
- if (exc) {
- o = mono_runtime_try_invoke (im, NULL, pa, exc, &error);
- } else {
- o = mono_runtime_invoke_checked (im, NULL, pa, &error);
- }
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ o = mono_runtime_try_invoke (im, NULL, pa, exc, error);
+ return_val_if_nok (error, NULL);
return o;
}
if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
target = tp->rp->unwrapped_server;
} else {
- return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
+ ret = mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+ return ret;
}
}
#endif
mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
g_free (full_name);
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
if (exc) mono_raise_exception ((MonoException *)exc);
mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
g_free (full_name);
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
if (exc) mono_raise_exception ((MonoException *)exc);
mono_array_setref (msg->args, 2, arg);
g_free (full_name);
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
if (exc) mono_raise_exception ((MonoException *)exc);
}
mono_array_setref (msg->args, 2, arg);
g_free (full_name);
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+ mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
if (exc) mono_raise_exception ((MonoException *)exc);
}