/* Main thread */
static MonoThread *main_thread;
+/* Functions supplied by the runtime */
+static MonoRuntimeCallbacks callbacks;
+
/**
* mono_thread_set_main:
* @thread: thread to set as the main thread
#error "MONO_IMT_SIZE cannot be larger than 32"
#endif
+void
+mono_install_callbacks (MonoRuntimeCallbacks *cbs)
+{
+ memcpy (&callbacks, cbs, sizeof (*cbs));
+}
+
void
mono_install_trampoline (MonoTrampoline func)
{
if (field->type->byref)
break;
+ if (static_fields && field->offset == -1)
+ /* special static */
+ continue;
+
pos = field->offset / sizeof (gpointer);
pos += offset;
return mono_string_new_size (mono_domain_get (), length);
}
-static void
+void
mono_class_compute_gc_descriptor (MonoClass *class)
{
int max_set = 0;
MonoImtBuilderEntry* entry = imt_builder [i];
while (entry != NULL) {
MonoImtBuilderEntry* next = entry->next;
- free (entry);
+ g_free (entry);
entry = next;
}
}
static int num_added = 0;
GenericVirtualCase *gvc, *list;
+ MonoImtBuilderEntry *entries;
+ int i;
+ GPtrArray *sorted;
mono_domain_lock (domain);
if (!domain->generic_virtual_cases)
if (++gvc->count == THUNK_THRESHOLD) {
gpointer *old_thunk = *vtable_slot;
- /* Force the rebuild of the thunk at the next call */
if ((gpointer)vtable_slot < (gpointer)vtable)
+ /* Force the rebuild of the thunk at the next call */
*vtable_slot = imt_trampoline;
- else
- *vtable_slot = vtable_trampoline;
+ else {
+ entries = get_generic_virtual_entries (domain, vtable_slot);
+
+ sorted = imt_sort_slot_entries (entries);
+
+ *vtable_slot = imt_thunk_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len,
+ vtable_trampoline);
+
+ while (entries) {
+ MonoImtBuilderEntry *next = entries->next;
+ g_free (entries);
+ entries = next;
+ }
+
+ for (i = 0; i < sorted->len; ++i)
+ g_free (g_ptr_array_index (sorted, i));
+ g_ptr_array_free (sorted, TRUE);
+ }
if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
invalidate_generic_virtual_thunk (domain, old_thunk);
bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
/*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
- statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set? max_set + 1: 0);
+ statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set + 1);
vt->data = mono_gc_alloc_fixed (class_size, statics_gc_descr);
mono_domain_add_class_static_data (domain, class, vt->data, NULL);
if (bitmap != default_bitmap)
if (!domain->special_static_fields)
domain->special_static_fields = g_hash_table_new (NULL, NULL);
g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
+ /*
+ * This marks the field as special static to speed up the
+ * checks in mono_field_static_get/set_value ().
+ */
+ field->offset = -1;
continue;
}
}
for (i = 0; i < class->vtable_size; ++i) {
MonoMethod *cm;
- if ((cm = class->vtable [i])) {
- if (mono_method_signature (cm)->generic_param_count)
- /* FIXME: Why is this needed ? */
- vt->vtable [i] = cm;
- else
- vt->vtable [i] = vtable_trampoline? vtable_trampoline: arch_create_jit_trampoline (cm);
- }
+ if ((cm = class->vtable [i]))
+ vt->vtable [i] = vtable_trampoline? vtable_trampoline: arch_create_jit_trampoline (cm);
}
}
g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
/* you cant set a constant! */
g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
-
- dest = (char*)vt->data + field->offset;
+
+ if (field->offset == -1) {
+ /* Special static */
+ gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ dest = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
+ } else {
+ dest = (char*)vt->data + field->offset;
+ }
set_value (field->type, dest, value, FALSE);
}
return;
}
- src = (char*)vt->data + field->offset;
+ if (field->offset == -1) {
+ /* Special static */
+ gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
+ } else {
+ src = (char*)vt->data + field->offset;
+ }
set_value (field->type, value, src, TRUE);
}
* will point into the next function in the executable, not this one.
*/
- if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class)
- MONO_OBJECT_SETREF (mono_thread_current (), abort_exc, ex);
+ if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class) {
+ MonoThread *thread = mono_thread_current ();
+ g_assert (ex->object.vtable->domain == mono_domain_get ());
+ MONO_OBJECT_SETREF (thread, abort_exc, ex);
+ }
ex_handler (ex);
}
}
}
+
+static MonoObject*
+mono_runtime_capture_context (MonoDomain *domain)
+{
+ RuntimeInvokeFunction runtime_invoke;
+
+ if (!domain->capture_context_runtime_invoke || !domain->capture_context_method) {
+ MonoMethod *method = mono_get_context_capture_method ();
+ MonoMethod *wrapper;
+ if (!method)
+ return NULL;
+ wrapper = mono_marshal_get_runtime_invoke (method, FALSE);
+ domain->capture_context_runtime_invoke = mono_compile_method (wrapper);
+ domain->capture_context_method = mono_compile_method (method);
+ }
+
+ runtime_invoke = domain->capture_context_runtime_invoke;
+
+ return runtime_invoke (NULL, NULL, NULL, domain->capture_context_method);
+}
/**
* mono_async_result_new:
* @domain:domain where the object will be created.
mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
{
MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
- MonoMethod *method = mono_get_context_capture_method ();
-
+ MonoObject *context = mono_runtime_capture_context (domain);
/* we must capture the execution context from the original thread */
- if (method) {
- MONO_OBJECT_SETREF (res, execution_context, mono_runtime_invoke (method, NULL, NULL, NULL));
+ if (context) {
+ MONO_OBJECT_SETREF (res, execution_context, context);
/* note: result may be null if the flow is suppressed */
}
* mono_create_ftnptr:
*
* Given a function address, create a function descriptor for it.
- * This is only needed on IA64 and PPC64.
+ * This is only needed on some platforms.
*/
gpointer
mono_create_ftnptr (MonoDomain *domain, gpointer addr)
{
-#ifdef __ia64__
- gpointer *desc;
-
- desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer));
-
- desc [0] = addr;
- desc [1] = NULL;
-
- return desc;
-#elif defined(__ppc64__) || defined(__powerpc64__)
- gpointer *desc;
-
- desc = mono_domain_code_reserve (domain, 3 * sizeof (gpointer));
-
- desc [0] = addr;
- desc [1] = NULL;
- desc [2] = NULL;
-
- return desc;
-#else
- return addr;
-#endif
+ return callbacks.create_ftnptr (domain, addr);
}
/*
* mono_get_addr_from_ftnptr:
*
* Given a pointer to a function descriptor, return the function address.
- * This is only needed on IA64 and PPC64.
+ * This is only needed on some platforms.
*/
gpointer
mono_get_addr_from_ftnptr (gpointer descr)
{
-#if defined(__ia64__) || defined(__ppc64__) || defined(__powerpc64__)
- return *(gpointer*)descr;
-#else
- return descr;
-#endif
+ return callbacks.get_addr_from_ftnptr (descr);
}
#if 0