+2008-01-05 Zoltan Varga <vargaz@gmail.com>
+
+ * object.c (mono_array_full_copy): Fix detection of whenever to use a write
+ barrier.
+ (mono_array_clone_in_domain): Ditto.
+ (mono_array_clone_in_domain): Ditto.
+
+ * threads.c (start_wrapper): Register the thread start argument as a GC root.
+ (cache_culture): Use a write barrier.
+
+ * icall.c (ves_icall_System_Array_SetValueImpl): Call a write barrier.
+ (ves_icall_get_property_info): Ditto.
+
+ * object.h (MONO_STRUCT_SETREF): New macro.
+
+ * class-internals.h (MonoStats): Add some GC statistics.
+
+ * boehm-gc.c null-gc.c: Define mono_gc_deregister_root ().
+
2008-01-04 Andreas Faerber <andreas.faerber@web.de>
* exception.c (mono_exception_from_name_two_strings):
return TRUE;
}
+void
+mono_gc_deregister_root (char* addr)
+{
+ /* FIXME: No size info */
+ GC_remove_roots (addr, addr + sizeof (gpointer));
+}
+
void
mono_gc_weak_link_add (void **link_addr, MonoObject *obj)
{
gulong generics_sharable_methods;
gulong generics_unsharable_methods;
gulong generics_shared_methods;
+ gulong minor_gc_count;
+ gulong major_gc_count;
+ gulong minor_gc_time_usecs;
+ gulong major_gc_time_usecs;
gboolean enabled;
} MonoStats;
if (!ec->valuetype) {
if (!mono_object_isinst (value, ec))
INVALID_CAST;
- *ea = (gpointer)value;
+ mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
return;
}
if (mono_object_isinst (value, ec)) {
+ // FIXME: Add membarrier
memcpy (ea, (char *)value + sizeof (MonoObject), esize);
return;
}
MONO_ARCH_SAVE_REGS;
if ((req_info & PInfo_ReflectedType) != 0)
- info->parent = mono_type_get_object (domain, &property->klass->byval_arg);
+ MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
else if ((req_info & PInfo_DeclaringType) != 0)
- info->parent = mono_type_get_object (domain, &property->property->parent->byval_arg);
+ MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
if ((req_info & PInfo_Name) != 0)
- info->name = mono_string_new (domain, property->property->name);
+ MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
if ((req_info & PInfo_Attributes) != 0)
info->attrs = property->property->attrs;
if ((req_info & PInfo_GetMethod) != 0)
- info->get = property->property->get ?
- mono_method_get_object (domain, property->property->get, property->klass): NULL;
+ MONO_STRUCT_SETREF (info, get, property->property->get ?
+ mono_method_get_object (domain, property->property->get, property->klass): NULL);
if ((req_info & PInfo_SetMethod) != 0)
- info->set = property->property->set ?
- mono_method_get_object (domain, property->property->set, property->klass): NULL;
+ MONO_STRUCT_SETREF (info, set, property->property->set ?
+ mono_method_get_object (domain, property->property->set, property->klass): NULL);
/*
* There may be other methods defined for properties, though, it seems they are not exposed
* in the reflection API
return TRUE;
}
+void
+mono_gc_deregister_root (char* addr)
+{
+}
+
void
mono_gc_weak_link_add (void **link_addr, MonoObject *obj)
{
g_assert (size == mono_array_length (dest));
size *= mono_array_element_size (klass);
#ifdef HAVE_SGEN_GC
- if (klass->valuetype) {
- if (klass->has_references)
+ if (klass->element_class->valuetype) {
+ if (klass->element_class->has_references)
mono_value_copy_array (dest, 0, src, mono_array_length (src));
else
memcpy (&dest->vector, &src->vector, size);
size *= mono_array_element_size (klass);
#ifdef HAVE_SGEN_GC
- if (klass->valuetype) {
- if (klass->has_references)
+ if (klass->element_class->valuetype) {
+ if (klass->element_class->has_references)
mono_value_copy_array (o, 0, array, mono_array_length (array));
else
memcpy (&o->vector, &array->vector, size);
}
o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
#ifdef HAVE_SGEN_GC
- if (klass->valuetype) {
- if (klass->has_references)
+ if (klass->element_class->valuetype) {
+ if (klass->element_class->has_references)
mono_value_copy_array (o, 0, array, mono_array_length (array));
else
memcpy (&o->vector, &array->vector, size);
/*(obj)->fieldname = (value);*/ \
} while (0)
+/* This should be used if 's' can reside on the heap */
+#define MONO_STRUCT_SETREF(s,field,value) do { \
+ mono_gc_wbarrier_generic_store (&((s)->field), (MonoObject*)(value)); \
+ } while (0)
+
#define mono_array_length(array) ((array)->max_length)
#define mono_array_addr(array,type,index) ((type*)(gpointer) mono_array_addr_with_size (array, sizeof (type), index))
#define mono_array_addr_with_size(array,size,index) ( ((char*)(array)->vector) + (size) * (index) )
*/
ReleaseSemaphore (thread->start_notify, 1, NULL);
}
-
+
+ MONO_GC_UNREGISTER_ROOT (start_info->start_arg);
g_free (start_info);
thread_adjust_static_data (thread);
start_info->obj = thread;
start_info->domain = domain;
start_info->start_arg = arg;
+
+ /*
+ * The argument may be an object reference, and there is no ref to keep it alive
+ * when the new thread is started but not yet registered with the collector.
+ */
+ MONO_GC_REGISTER_ROOT (start_info->start_arg);
/* Create suspended, so we can do some housekeeping before the thread
* starts
THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
if (thread_handle == NULL) {
/* The thread couldn't be created, so throw an exception */
+ MONO_GC_UNREGISTER_ROOT (start_info->start_arg);
+ g_free (start_info);
mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
return;
}
EnterCriticalSection (this->synch_cs);
if (!this->cached_culture_info)
- this->cached_culture_info = mono_array_new (mono_object_domain (this), mono_defaults.object_class, NUM_CACHED_CULTURES * 2);
+ MONO_OBJECT_SETREF (this, cached_culture_info, mono_array_new (mono_object_domain (this), mono_defaults.object_class, NUM_CACHED_CULTURES * 2));
for (i = start_idx; i < start_idx + NUM_CACHED_CULTURES; ++i) {
obj = mono_array_get (this->cached_culture_info, MonoObject*, i);