#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"
static char *
mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error);
+/* Class lazy loading functions */
+static GENERATE_GET_CLASS_WITH_CACHE (pointer, System.Reflection, Pointer)
+static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, System.Runtime.Remoting, RemotingServices)
+static GENERATE_GET_CLASS_WITH_CACHE (unhandled_exception_event_args, System, UnhandledExceptionEventArgs)
+static GENERATE_GET_CLASS_WITH_CACHE (sta_thread_attribute, System, STAThreadAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (activation_services, System.Runtime.Remoting.Activation, ActivationServices)
+
#define ldstr_lock() mono_os_mutex_lock (&ldstr_section)
#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;
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 (method, this_obj, NULL, NULL);
+
+ 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;
- 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_invoke (method, NULL, NULL, (MonoObject **) &exc);
+ 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
return NULL;
}
-static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
-static MonoJumpTrampoline arch_create_jump_trampoline = default_jump_trampoline;
static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
static MonoImtThunkBuilder imt_thunk_builder;
static gboolean always_build_imt_thunks;
return &callbacks;
}
-void
-mono_install_trampoline (MonoTrampoline func)
-{
- arch_create_jit_trampoline = func? func: default_trampoline;
-}
-
-void
-mono_install_jump_trampoline (MonoJumpTrampoline func)
-{
- arch_create_jump_trampoline = func? func: default_jump_trampoline;
-}
-
#ifndef DISABLE_REMOTING
void
mono_install_remoting_trampoline (MonoRemotingTrampoline func)
always_build_imt_thunks = value;
}
-static MonoCompileFunc default_mono_compile_method = NULL;
-
-/**
- * mono_install_compile_method:
- * @func: function to install
- *
- * This is a VM internal routine
- */
-void
-mono_install_compile_method (MonoCompileFunc func)
-{
- default_mono_compile_method = func;
-}
-
/**
* mono_compile_method:
* @method: The method to compile.
gpointer
mono_compile_method (MonoMethod *method)
{
+ gpointer res;
+ MonoError error;
+
MONO_REQ_GC_NEUTRAL_MODE
- if (!default_mono_compile_method) {
+ if (!callbacks.compile_method) {
g_error ("compile method called on uninitialized runtime");
return NULL;
}
- return default_mono_compile_method (method);
+ res = callbacks.compile_method (method, &error);
+ if (!mono_error_ok (&error))
+ mono_error_raise_exception (&error);
+ return res;
}
gpointer
mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
{
- MONO_REQ_GC_NEUTRAL_MODE
+ MonoError error;
+ gpointer res;
+
+ MONO_REQ_GC_NEUTRAL_MODE;
- return arch_create_jump_trampoline (domain, method, add_sync_wrapper);
+ res = callbacks.create_jump_trampoline (domain, method, add_sync_wrapper, &error);
+ if (!mono_error_ok (&error))
+ mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+ return res;
}
gpointer
{
MONO_REQ_GC_NEUTRAL_MODE;
+ MonoError error;
MonoCustomAttrInfo *ainfo;
int i;
- ainfo = mono_custom_attrs_from_field (fklass, field);
+ ainfo = mono_custom_attrs_from_field_checked (fklass, field, &error);
+ mono_error_cleanup (&error); /* FIXME don't swallow the error? */
if (!ainfo)
return FALSE;
for (i = 0; i < ainfo->num_attrs; ++i) {
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 (klass->exception_type) {
- if (raise_on_error)
- mono_raise_exception (mono_class_get_exception_for_failure (klass));
+ if (mono_class_has_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;
mono_loader_unlock ();
return runtime_info->domain_vtables [domain->domain_id];
}
- if (!klass->inited || klass->exception_type) {
- if (!mono_class_init (klass) || klass->exception_type) {
+ if (!klass->inited || mono_class_has_failure (klass)) {
+ 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_init (element_class);
/*mono_class_init can leave the vtable layout to be lazily done and we can't afford this here*/
- if (element_class->exception_type == MONO_EXCEPTION_NONE && !element_class->vtable_size)
+ if (!mono_class_has_failure (element_class) && !element_class->vtable_size)
mono_class_setup_vtable (element_class);
- if (element_class->exception_type != MONO_EXCEPTION_NONE) {
+ if (mono_class_has_failure (element_class)) {
/*Can happen if element_class only got bad after mono_class_setup_vtable*/
- if (klass->exception_type == MONO_EXCEPTION_NONE)
+ if (!mono_class_has_failure (klass))
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;
}
}
/* Initialize klass->has_finalize */
mono_class_has_finalizer (klass);
- if (klass->exception_type) {
+ 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;
}
for (i = 0; i < klass->vtable_size; ++i) {
MonoMethod *cm;
- if ((cm = klass->vtable [i]))
- vt->vtable [i] = arch_create_jit_trampoline (cm);
+ cm = klass->vtable [i];
+ if (cm) {
+ 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;
}
}
static MonoObject*
-dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
{
- g_error ("runtime invoke called on uninitialized runtime");
- return NULL;
-}
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoObject *result = NULL;
+
+ g_assert (callbacks.runtime_invoke);
-static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
+ mono_error_init (error);
+
+ if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+ mono_profiler_method_start_invoke (method);
+
+ MONO_PREPARE_RESET_BLOCKING;
+
+ result = callbacks.runtime_invoke (method, obj, params, exc, error);
+
+ MONO_FINISH_RESET_BLOCKING;
+
+ if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+ mono_profiler_method_end_invoke (method);
+
+ if (!mono_error_ok (error))
+ return NULL;
+
+ return result;
+}
/**
* mono_runtime_invoke:
*/
MonoObject*
mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+{
+ MonoError error;
+ MonoObject *res;
+ if (exc) {
+ res = mono_runtime_try_invoke (method, obj, params, exc, &error);
+ if (*exc == NULL && !mono_error_ok(&error)) {
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ } else
+ mono_error_cleanup (&error);
+ } else {
+ res = mono_runtime_invoke_checked (method, obj, params, &error);
+ mono_error_raise_exception (&error);
+ }
+ return res;
+}
+
+/**
+ * mono_runtime_try_invoke:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @exc: exception information.
+ * @error: set on error
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise.
+ *
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ *
+ * For this function, you must not pass NULL as the exc argument if
+ * you don't want to catch exceptions, use
+ * mono_runtime_invoke_checked(). If an exception is thrown, you
+ * can't use the MonoObject* result from the function.
+ *
+ * If this method cannot be invoked, @error will be set and @exc and
+ * the return value must not be used.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_try_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError* error)
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoObject *result;
+ g_assert (exc != NULL);
if (mono_runtime_get_no_exec ())
g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
- if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
- mono_profiler_method_start_invoke (method);
+ return do_runtime_invoke (method, obj, params, exc, error);
+}
- result = default_mono_runtime_invoke (method, obj, params, exc);
+/**
+ * mono_runtime_invoke_checked:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @error: set on error
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise.
+ *
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ *
+ * If an exception is thrown, you can't use the MonoObject* result
+ * from the function.
+ *
+ * If this method cannot be invoked, @error will be set. If the
+ * method throws an exception (and we're in coop mode) the exception
+ * will be set in @error.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_invoke_checked (MonoMethod *method, void *obj, void **params, MonoError* error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
- if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
- mono_profiler_method_end_invoke (method);
+ if (mono_runtime_get_no_exec ())
+ g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
- return result;
+ return do_runtime_invoke (method, obj, params, NULL, error);
}
/**
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);
gpointer v;
if (!m) {
- MonoClass *ptr_klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Reflection", "Pointer");
+ MonoClass *ptr_klass = mono_class_get_pointer_class ();
m = mono_class_get_method_from_name_flags (ptr_klass, "Box", 2, METHOD_ATTRIBUTE_STATIC);
g_assert (m);
}
args [1] = mono_type_get_object_checked (mono_domain_get (), type, &error);
mono_error_raise_exception (&error); /* FIXME don't raise here */
- return mono_runtime_invoke (m, NULL, args, NULL);
+ o = mono_runtime_invoke_checked (m, NULL, args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+ return o;
}
/* boxed value type */
if (mono_class_is_nullable (klass))
return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
- o = mono_object_new (domain, klass);
+ o = mono_object_new_checked (domain, klass, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
v = ((gchar *) o) + sizeof (MonoObject);
if (is_literal) {
{
MONO_REQ_GC_UNSAFE_MODE;
- default_mono_runtime_invoke (prop->set, obj, params, exc);
+ MonoError error;
+ do_runtime_invoke (prop->set, obj, params, exc, &error);
+ if (exc && *exc == NULL && !mono_error_ok (&error)) {
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ } else {
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
}
/**
{
MONO_REQ_GC_UNSAFE_MODE;
- return default_mono_runtime_invoke (prop->get, obj, params, exc);
+ MonoError error;
+ MonoObject *val = do_runtime_invoke (prop->get, obj, params, exc, &error);
+ if (exc && *exc == NULL && !mono_error_ok (&error)) {
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ } else {
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
+ return val;
}
/*
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+
MonoClass *param_class = klass->cast_class;
mono_class_setup_fields_locking (klass);
g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
if (*(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject))) {
- MonoObject *o = mono_object_new (mono_domain_get (), param_class);
+ MonoObject *o = mono_object_new_checked (mono_domain_get (), param_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
if (param_class->has_references)
mono_gc_wbarrier_value_copy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), 1, param_class);
else
/* This is called at runtime, so avoid the slower search in metadata */
mono_class_setup_methods (klass);
- if (klass->exception_type)
+ if (mono_class_has_failure (klass))
return NULL;
im = mono_class_get_method_from_name (klass, "Invoke", -1);
return im;
/* This is called at runtime, so avoid the slower search in metadata */
mono_class_setup_methods (klass);
- if (klass->exception_type)
+ if (mono_class_has_failure (klass))
return NULL;
im = mono_class_get_method_from_name (klass, "BeginInvoke", -1);
return im;
/* This is called at runtime, so avoid the slower search in metadata */
mono_class_setup_methods (klass);
- if (klass->exception_type)
+ if (mono_class_has_failure (klass))
return NULL;
im = mono_class_get_method_from_name (klass, "EndInvoke", -1);
return im;
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
MonoMethod *im;
MonoClass *klass = delegate->vtable->klass;
+ MonoObject *o;
im = mono_get_delegate_invoke (klass);
if (!im)
g_error ("Could not lookup delegate invoke method for delegate %s", mono_type_get_full_name (klass));
- return mono_runtime_invoke (im, delegate, params, exc);
+ if (exc) {
+ o = mono_runtime_try_invoke (im, delegate, params, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ else
+ mono_error_cleanup (&error);
+ } else {
+ o = mono_runtime_invoke_checked (im, delegate, params, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
+ return o;
}
static char **main_args = NULL;
{
static MonoMethod *serialize_method;
+ MonoError error;
void *params [1];
MonoObject *array;
if (!serialize_method) {
- MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingServices");
+ MonoClass *klass = mono_class_get_remoting_services_class ();
serialize_method = mono_class_get_method_from_name (klass, "SerializeCallData", -1);
}
params [0] = obj;
*exc = NULL;
- array = mono_runtime_invoke (serialize_method, NULL, params, exc);
+
+ array = mono_runtime_try_invoke (serialize_method, NULL, params, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME convert serialize_object to MonoError */
+ else
+ mono_error_cleanup (&error);
+
if (*exc)
*failure = TRUE;
static MonoMethod *deserialize_method;
+ MonoError error;
void *params [1];
MonoObject *result;
if (!deserialize_method) {
- MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingServices");
+ MonoClass *klass = mono_class_get_remoting_services_class ();
deserialize_method = mono_class_get_method_from_name (klass, "DeserializeCallData", -1);
}
if (!deserialize_method) {
params [0] = obj;
*exc = NULL;
- result = mono_runtime_invoke (deserialize_method, NULL, params, exc);
+
+ result = mono_runtime_try_invoke (deserialize_method, NULL, params, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME convert deserialize_object to MonoError */
+ else
+ mono_error_cleanup (&error);
+
if (*exc)
*failure = TRUE;
g_assert (mono_class_is_marshalbyref (obj->vtable->klass));
- real_proxy = (MonoRealProxy*) mono_object_new (domain, mono_defaults.real_proxy_class);
+ real_proxy = (MonoRealProxy*) mono_object_new_checked (domain, mono_defaults.real_proxy_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
reflection_type = mono_type_get_object_checked (domain, &obj->vtable->klass->byval_arg, &error);
mono_error_raise_exception (&error); /* FIXME don't raise here */
MONO_OBJECT_SETREF (real_proxy, unwrapped_server, obj);
*exc = NULL;
- transparent_proxy = (MonoTransparentProxy*) mono_runtime_invoke (get_proxy_method, real_proxy, NULL, exc);
+
+ transparent_proxy = (MonoTransparentProxy*) mono_runtime_try_invoke (get_proxy_method, real_proxy, NULL, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME change make_transparent_proxy outarg to MonoError */
+ else
+ mono_error_cleanup (&error);
if (*exc)
*failure = TRUE;
MonoObject *deserialized = NULL;
gboolean failure = FALSE;
+ g_assert (exc != NULL);
*exc = NULL;
#ifndef DISABLE_REMOTING
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
MonoClass *klass;
gpointer args [2];
MonoMethod *method = NULL;
MonoBoolean is_terminating = TRUE;
MonoObject *obj;
- klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
- g_assert (klass);
-
+ klass = mono_class_get_unhandled_exception_event_args_class ();
mono_class_init (klass);
/* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
args [0] = exc;
args [1] = &is_terminating;
- obj = mono_object_new (mono_domain_get (), klass);
- mono_runtime_invoke (method, obj, args, NULL);
+ obj = mono_object_new_checked (mono_domain_get (), klass, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+ mono_runtime_invoke_checked (method, obj, args, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
return obj;
}
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
MonoDomain *domain;
gpointer pa [1];
int rval;
}
}
- cinfo = mono_custom_attrs_from_method (method);
+ cinfo = mono_custom_attrs_from_method_checked (method, &error);
+ mono_error_cleanup (&error); /* FIXME warn here? */
if (cinfo) {
- static MonoClass *stathread_attribute = NULL;
- if (!stathread_attribute)
- stathread_attribute = mono_class_from_name (mono_defaults.corlib, "System", "STAThreadAttribute");
- has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, stathread_attribute);
+ has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, mono_class_get_sta_thread_attribute_class ());
if (!cinfo->cached)
mono_custom_attrs_free (cinfo);
} else {
/* FIXME: check signature of method */
if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
MonoObject *res;
- res = mono_runtime_invoke (method, NULL, pa, exc);
+ if (exc) {
+ res = mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ else
+ mono_error_cleanup (&error);
+ } else {
+ res = mono_runtime_invoke_checked (method, NULL, pa, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
if (!exc || !*exc)
rval = *(guint32 *)((char *)res + sizeof (MonoObject));
else
mono_environment_exitcode_set (rval);
} else {
- mono_runtime_invoke (method, NULL, pa, exc);
+ if (exc) {
+ mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ else
+ mono_error_cleanup (&error);
+ } else {
+ mono_runtime_invoke_checked (method, NULL, pa, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
if (!exc || !*exc)
rval = 0;
else {
return rval;
}
-/**
- * mono_install_runtime_invoke:
- * @func: Function to install
- *
- * This is a VM internal routine
- */
-void
-mono_install_runtime_invoke (MonoInvokeFunc func)
-{
- default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
-}
-
-
/**
* mono_runtime_invoke_array:
* @method: method to invoke
* respective reference representation.
*
* From unmanaged code you'll usually use the
- * mono_runtime_invoke() variant.
+ * mono_runtime_invoke_checked() variant.
*
* Note that this function doesn't handle virtual methods for
* you, it will exec the exact method you pass: we still need to
has_byref_nullables = TRUE;
} else {
/* MS seems to create the objects if a null is passed in */
- if (!mono_array_get (params, MonoObject*, i))
- mono_array_setref (params, i, mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i])));
+ if (!mono_array_get (params, MonoObject*, i)) {
+ MonoObject *o = mono_object_new_checked (mono_domain_get (), mono_class_from_mono_type (sig->params [i]), &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_array_setref (params, i, o);
+ }
if (t->byref) {
/*
}
if (!obj) {
- obj = mono_object_new (mono_domain_get (), method->klass);
- g_assert (obj); /*maybe we should raise a TLE instead?*/
+ obj = mono_object_new_checked (mono_domain_get (), method->klass, &error);
+ g_assert (obj && mono_error_ok (&error)); /*maybe we should raise a TLE instead?*/ /* FIXME don't swallow error */
#ifndef DISABLE_REMOTING
if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
obj = mono_value_box (mono_domain_get (), method->klass, obj);
}
- mono_runtime_invoke (method, o, pa, exc);
+ if (exc) {
+ mono_runtime_try_invoke (method, o, pa, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ else
+ mono_error_cleanup (&error);
+ } else {
+ mono_runtime_invoke_checked (method, o, pa, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
return (MonoObject *)obj;
} else {
if (mono_class_is_nullable (method->klass)) {
MonoObject *nullable;
/* Convert the unboxed vtype into a Nullable structure */
- nullable = mono_object_new (mono_domain_get (), method->klass);
+ nullable = mono_object_new_checked (mono_domain_get (), method->klass, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
mono_nullable_init ((guint8 *)mono_object_unbox (nullable), mono_value_box (mono_domain_get (), method->klass->cast_class, obj), method->klass);
obj = mono_object_unbox (nullable);
}
/* obj must be already unboxed if needed */
- res = mono_runtime_invoke (method, obj, pa, exc);
+ if (exc) {
+ res = mono_runtime_try_invoke (method, obj, pa, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ else
+ mono_error_cleanup (&error);
+ } else {
+ res = mono_runtime_invoke_checked (method, obj, pa, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
if (sig->ret->type == MONO_TYPE_PTR) {
MonoClass *pointer_class;
* The runtime-invoke wrapper returns a boxed IntPtr, need to
* convert it to a Pointer object.
*/
- pointer_class = mono_class_from_name_cached (mono_defaults.corlib, "System.Reflection", "Pointer");
+ pointer_class = mono_class_get_pointer_class ();
if (!box_method)
box_method = mono_class_get_method_from_name (pointer_class, "Box", -1);
box_args [1] = mono_type_get_object_checked (mono_domain_get (), sig->ret, &error);
mono_error_raise_exception (&error); /* FIXME don't raise here */
- res = mono_runtime_invoke (box_method, NULL, box_args, &box_exc);
- g_assert (!box_exc);
+ res = mono_runtime_try_invoke (box_method, NULL, box_args, &box_exc, &error);
+ g_assert (box_exc == NULL);
+ mono_error_assert_ok (&error);
}
if (has_byref_nullables) {
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoVTable *vtable;
+ MonoError error;
- vtable = mono_class_vtable (domain, klass);
- if (!vtable)
- return NULL;
+ MonoObject * result = mono_object_new_checked (domain, klass, &error);
+
+ mono_error_raise_exception (&error);
+ return result;
+}
+
+MonoObject *
+ves_icall_object_new (MonoDomain *domain, MonoClass *klass)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
MonoError error;
- MonoObject *o = mono_object_new_specific_checked (vtable, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ MonoObject * result = mono_object_new_checked (domain, klass, &error);
+
+ mono_error_raise_exception (&error);
+ return result;
+}
+
+/**
+ * mono_object_new_checked:
+ * @klass: the class of the object that we want to create
+ * @error: set on error
+ *
+ * Returns: a newly created object whose definition is
+ * looked up using @klass. This will not invoke any constructors,
+ * so the consumer of this routine has to invoke any constructors on
+ * its own to initialize the object.
+ *
+ * It returns NULL on failure and sets @error.
+ */
+MonoObject *
+mono_object_new_checked (MonoDomain *domain, MonoClass *klass, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ MonoVTable *vtable;
+
+ vtable = mono_class_vtable (domain, klass);
+ g_assert (vtable); /* FIXME don't swallow the error */
+
+ MonoObject *o = mono_object_new_specific_checked (vtable, error);
return o;
}
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;
}
MonoMethod *im = vtable->domain->create_proxy_for_type_method;
if (im == NULL) {
- MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
+ MonoClass *klass = mono_class_get_activation_services_class ();
if (!klass->inited)
mono_class_init (klass);
if (!mono_error_ok (error))
return NULL;
- o = mono_runtime_invoke (im, NULL, pa, NULL);
- if (o != NULL) return o;
+ o = mono_runtime_invoke_checked (im, NULL, pa, error);
+ if (!mono_error_ok (error))
+ return NULL;
+
+ if (o != NULL)
+ return o;
}
return mono_object_new_alloc_specific_checked (vtable, error);
return o;
}
+/**
+ * mono_object_new_alloc_specific:
+ * @vtable: virtual table for the object.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information. If the class of this object has a
+ * finalizer, then the object will be tracked for finalization.
+ *
+ * This method might raise an exception on errors. Use the
+ * `mono_object_new_fast_checked` method if you want to manually raise
+ * the exception.
+ *
+ * Returns: the allocated object.
+ */
MonoObject *
mono_object_new_alloc_specific (MonoVTable *vtable)
{
return o;
}
+/**
+ * mono_object_new_alloc_specific_checked:
+ * @vtable: virtual table for the object.
+ * @error: holds the error return value.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information. If the class of this object has a
+ * finalizer, then the object will be tracked for finalization.
+ *
+ * If there is not enough memory, the @error parameter will be set
+ * and will contain a user-visible message with the amount of bytes
+ * that were requested.
+ *
+ * Returns: the allocated object, or NULL if there is not enough memory
+ *
+ */
MonoObject *
mono_object_new_alloc_specific_checked (MonoVTable *vtable, MonoError *error)
{
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_object_new_fast:
+ * @vtable: virtual table for the object.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information. The returned object is not tracked
+ * for finalization. If your object implements a finalizer, you should
+ * use `mono_object_new_alloc_specific` instead.
+ *
+ * This method might raise an exception on errors. Use the
+ * `mono_object_new_fast_checked` method if you want to manually raise
+ * the exception.
+ *
+ * Returns: the allocated object.
+ */
MonoObject*
mono_object_new_fast (MonoVTable *vtable)
{
return o;
}
+/**
+ * mono_object_new_fast_checked:
+ * @vtable: virtual table for the object.
+ * @error: holds the error return value.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information. The returned object is not tracked
+ * for finalization. If your object implements a finalizer, you should
+ * use `mono_object_new_alloc_specific_checked` instead.
+ *
+ * If there is not enough memory, the @error parameter will be set
+ * and will contain a user-visible message with the amount of bytes
+ * that were requested.
+ *
+ * Returns: the allocated object, or NULL if there is not enough memory
+ *
+ */
MonoObject*
mono_object_new_fast_checked (MonoVTable *vtable, MonoError *error)
{
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_REQ_GC_UNSAFE_MODE;
MonoError error;
+ MonoObject *result;
MonoClass *klass;
klass = mono_class_get_checked (image, token, &error);
g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
+ result = mono_object_new_checked (domain, klass, &error);
- return mono_object_new (domain, klass);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ return result;
+
}
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;
MONO_REQ_GC_UNSAFE_MODE;
MonoError error;
+ MonoString *res = NULL;
+ res = mono_string_new_utf16_checked (domain, text, len, &error);
+ mono_error_raise_exception (&error);
+
+ return res;
+}
+
+/**
+ * mono_string_new_utf16_checked:
+ * @text: a pointer to an utf16 string
+ * @len: the length of the string
+ * @error: written on error.
+ *
+ * Returns: A newly created string object which contains @text.
+ * On error, returns NULL and sets @error.
+ */
+MonoString *
+mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
MonoString *s;
- s = mono_string_new_size_checked (domain, len, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
-
- memcpy (mono_string_chars (s), text, len * 2);
+ mono_error_init (error);
+
+ s = mono_string_new_size_checked (domain, len, error);
+ if (s != NULL)
+ memcpy (mono_string_chars (s), text, len * 2);
return s;
}
{
MONO_REQ_GC_UNSAFE_MODE;
- GError *error = NULL;
+ MonoError error;
+ GError *eg_error = NULL;
MonoString *o = NULL;
guint16 *ut;
glong items_written;
- ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &error);
+ mono_error_init (&error);
- if (!error)
- o = mono_string_new_utf16 (domain, ut, items_written);
+ ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &eg_error);
+
+ if (!eg_error)
+ o = mono_string_new_utf16_checked (domain, ut, items_written, &error);
else
- g_error_free (error);
+ g_error_free (eg_error);
g_free (ut);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
return o;
}
* @text: a pointer to an utf8 string
*
* Returns: A newly created string object which contains @text.
+ *
+ * This function asserts if it cannot allocate a new string.
+ *
+ * @deprecated Use mono_string_new_checked in new code.
*/
MonoString*
mono_string_new (MonoDomain *domain, const char *text)
+{
+ MonoError error;
+ MonoString *res = NULL;
+ res = mono_string_new_checked (domain, text, &error);
+ mono_error_assert_ok (&error);
+ return res;
+}
+
+/**
+ * mono_string_new_checked:
+ * @text: a pointer to an utf8 string
+ * @merror: set on error
+ *
+ * Returns: A newly created string object which contains @text.
+ * On error returns NULL and sets @merror.
+ */
+MonoString*
+mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *error)
{
MONO_REQ_GC_UNSAFE_MODE;
- GError *error = NULL;
+ GError *eg_error = NULL;
MonoString *o = NULL;
guint16 *ut;
glong items_written;
int l;
+ mono_error_init (error);
+
l = strlen (text);
- ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
+ ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &eg_error);
- if (!error)
- o = mono_string_new_utf16 (domain, ut, items_written);
+ if (!eg_error)
+ o = mono_string_new_utf16_checked (domain, ut, items_written, error);
else
- g_error_free (error);
+ g_error_free (eg_error);
g_free (ut);
+ mono_error_raise_exception (error);
+
/*FIXME g_utf8_get_char, g_utf8_next_char and g_utf8_validate are not part of eglib.*/
#if 0
- MonoError error;
gunichar2 *str;
const gchar *end;
int len;
MonoString *o = NULL;
- if (!g_utf8_validate (text, -1, &end))
- return NULL;
+ if (!g_utf8_validate (text, -1, &end)) {
+ mono_error_set_argument (error, "text", "Not a valid utf8 string");
+ goto leave;
+ }
len = g_utf8_strlen (text, -1);
- o = mono_string_new_size_checked (domain, len, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ o = mono_string_new_size_checked (domain, len, error);
+ if (!o)
+ goto leave;
str = mono_string_chars (o);
while (text < end) {
*str++ = g_utf8_get_char (text);
text = g_utf8_next_char (text);
}
+
+leave:
#endif
return o;
}
}
#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;
}
-/*
+/**
* mono_value_copy:
* @dest: destination pointer
* @src: source pointer
mono_gc_wbarrier_value_copy (dest, src, 1, klass);
}
-/*
+/**
* mono_value_copy_array:
* @dest: destination array
* @dest_idx: index in the @dest array
/**
* mono_object_get_class:
* @obj: object to query
- *
- * Returns: the MonOClass of the object.
+ *
+ * Use this function to obtain the `MonoClass*` for a given `MonoObject`.
+ *
+ * Returns: the MonoClass of the object.
*/
MonoClass*
mono_object_get_class (MonoObject *obj)
mono_error_raise_exception (&error); /* FIXME don't raise here */
pa [1] = obj;
- res = mono_runtime_invoke (im, rp, pa, NULL);
-
+ res = mono_runtime_invoke_checked (im, rp, pa, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
if (*(MonoBoolean *) mono_object_unbox(res)) {
/* Update the vtable of the remote type, so it can safely cast to this new type */
mono_upgrade_remote_class (domain, obj, klass);
}
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);
}
/**
len2 = mono_metadata_decode_blob_size (str, &str);
len2 >>= 1;
- o = mono_string_new_utf16 (domain, (guint16*)str, len2);
+ o = mono_string_new_utf16_checked (domain, (guint16*)str, len2, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
#if G_BYTE_ORDER != G_LITTLE_ENDIAN
{
int i;
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+ MonoString *res = NULL;
MonoDomain *domain = mono_domain_get ();
int len = 0;
while (data [len]) len++;
- return mono_string_new_utf16 (domain, data, len);
+ res = mono_string_new_utf16_checked (domain, data, len, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ return res;
}
/**
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
MonoWaitHandle *res;
gpointer params [1];
static MonoMethod *handle_set;
- res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.manualresetevent_class);
+ res = (MonoWaitHandle *)mono_object_new_checked (domain, mono_defaults.manualresetevent_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
/* Even though this method is virtual, it's safe to invoke directly, since the object type matches. */
if (!handle_set)
handle_set = mono_class_get_property_from_name (mono_defaults.manualresetevent_class, "Handle")->set;
params [0] = &handle;
- mono_runtime_invoke (handle_set, res, params, NULL);
+
+ mono_runtime_invoke_checked (handle_set, res, params, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
return res;
}
{
MONO_REQ_GC_UNSAFE_MODE;
- static MonoClassField *f_os_handle;
- static MonoClassField *f_safe_handle;
+ static MonoClassField *f_safe_handle = NULL;
+ MonoSafeHandle *sh;
- if (!f_os_handle && !f_safe_handle) {
- f_os_handle = mono_class_get_field_from_name (mono_defaults.manualresetevent_class, "os_handle");
- f_safe_handle = mono_class_get_field_from_name (mono_defaults.manualresetevent_class, "safe_wait_handle");
+ if (!f_safe_handle) {
+ f_safe_handle = mono_class_get_field_from_name (mono_defaults.manualresetevent_class, "safeWaitHandle");
+ g_assert (f_safe_handle);
}
- if (f_os_handle) {
- HANDLE retval;
- mono_field_get_value ((MonoObject*)handle, f_os_handle, &retval);
- return retval;
- } else {
- MonoSafeHandle *sh;
- mono_field_get_value ((MonoObject*)handle, f_safe_handle, &sh);
- return sh->handle;
- }
+ mono_field_get_value ((MonoObject*)handle, f_safe_handle, &sh);
+ return sh->handle;
}
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
+ MonoError error;
+ MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new_checked (domain, mono_defaults.asyncresult_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
MonoObject *context = mono_runtime_capture_context (domain);
/* we must capture the execution context from the original thread */
if (context) {
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
MonoAsyncCall *ac;
MonoObject *res;
SetEvent (wait_event);
if (ac->cb_method) {
- /* we swallow the excepton as it is the behavior on .NET */
- MonoObject *exc = NULL;
- mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, &exc);
- if (exc)
- mono_unhandled_exception (exc);
+ mono_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, &error);
+ mono_error_raise_exception (&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;
+ 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;
- return mono_runtime_invoke (im, NULL, pa, exc);
+ o = mono_runtime_try_invoke (im, NULL, pa, exc, error);
+ return_val_if_nok (error, NULL);
+
+ return o;
}
#endif
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_REQ_GC_UNSAFE_MODE;
static MonoMethod *to_string = NULL;
+ MonoError error;
MonoMethod *method;
+ MonoString *s;
void *target = obj;
g_assert (obj);
target = mono_object_unbox (obj);
}
- return (MonoString *) mono_runtime_invoke (method, target, NULL, exc);
+ if (exc) {
+ s = (MonoString *) mono_runtime_try_invoke (method, target, NULL, exc, &error);
+ if (*exc == NULL && !mono_error_ok (&error))
+ *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+ else
+ mono_error_cleanup (&error);
+ } else {
+ s = (MonoString *) mono_runtime_invoke_checked (method, target, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ }
+
+ return s;
}
/**
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+
MonoDomain *domain = mono_domain_get ();
MonoMethodSignature *sig = mono_method_signature (method);
MonoMethodMessage *msg;
int i, count;
- msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
-
+ msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+
if (invoke) {
- mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, invoke, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_message_init (domain, msg, rm, NULL);
count = sig->param_count - 2;
} else {
- mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_message_init (domain, msg, rm, NULL);
count = sig->param_count;
}
{
MONO_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+
static MonoMethod *getter = NULL;
MonoDomain *domain = mono_domain_get ();
MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
field_class = mono_class_from_mono_type (field->type);
- msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
+ msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
out_args = mono_array_new (domain, mono_defaults.object_class, 1);
- mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_message_init (domain, msg, rm, out_args);
full_name = mono_type_get_full_name (klass);
mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
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_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+
static MonoMethod *getter = NULL;
MonoDomain *domain = mono_domain_get ();
MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
gpointer val;
if (field_class->valuetype) {
- res = mono_object_new (domain, field_class);
+ res = mono_object_new_checked (domain, field_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
val = ((gchar *) res) + sizeof (MonoObject);
} else {
val = &res;
mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
}
- msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
+ msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
out_args = mono_array_new (domain, mono_defaults.object_class, 1);
- mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_message_init (domain, msg, rm, out_args);
full_name = mono_type_get_full_name (klass);
mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
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_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+
static MonoMethod *setter = NULL;
MonoDomain *domain = mono_domain_get ();
MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
arg = *((MonoObject **)val);
- msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
- mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
+ msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_message_init (domain, msg, rm, NULL);
full_name = mono_type_get_full_name (klass);
mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
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_REQ_GC_UNSAFE_MODE;
+ MonoError error;
+
static MonoMethod *setter = NULL;
MonoDomain *domain = mono_domain_get ();
MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
}
- msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
- mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
+ msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, &error);
+ mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_message_init (domain, msg, rm, NULL);
full_name = mono_type_get_full_name (klass);
mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
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);
}
* @size: size of the array elements
* @idx: index into the array
*
+ * Use this function to obtain the address for the @idx item on the
+ * @array containing elements of size @size.
+ *
+ * This method performs no bounds checking or type checking.
+ *
* Returns the address of the @idx element in the array.
*/
char*
return res;
}
+#if NEVER_DEFINED
+/*
+ * The following section is purely to declare prototypes and
+ * document the API, as these C files are processed by our
+ * tool
+ */
+
+/**
+ * mono_array_set:
+ * @array: array to alter
+ * @element_type: A C type name, this macro will use the sizeof(type) to determine the element size
+ * @index: index into the array
+ * @value: value to set
+ *
+ * Value Type version: This sets the @index's element of the @array
+ * with elements of size sizeof(type) to the provided @value.
+ *
+ * This macro does not attempt to perform type checking or bounds checking.
+ *
+ * Use this to set value types in a `MonoArray`.
+ */
+void mono_array_set(MonoArray *array, Type element_type, uintptr_t index, Value value)
+{
+}
+
+/**
+ * mono_array_setref:
+ * @array: array to alter
+ * @index: index into the array
+ * @value: value to set
+ *
+ * Reference Type version: This sets the @index's element of the
+ * @array with elements of size sizeof(type) to the provided @value.
+ *
+ * This macro does not attempt to perform type checking or bounds checking.
+ *
+ * Use this to reference types in a `MonoArray`.
+ */
+void mono_array_setref(MonoArray *array, uintptr_t index, MonoObject *object)
+{
+}
+
+/**
+ * mono_array_get:
+ * @array: array on which to operate on
+ * @element_type: C element type (example: MonoString *, int, MonoObject *)
+ * @index: index into the array
+ *
+ * Use this macro to retrieve the @index element of an @array and
+ * extract the value assuming that the elements of the array match
+ * the provided type value.
+ *
+ * This method can be used with both arrays holding value types and
+ * reference types. For reference types, the @type parameter should
+ * be a `MonoObject*` or any subclass of it, like `MonoString*`.
+ *
+ * This macro does not attempt to perform type checking or bounds checking.
+ *
+ * Returns: The element at the @index position in the @array.
+ */
+Type mono_array_get (MonoArray *array, Type element_type, uintptr_t index)
+{
+}
+#endif
+