Merge pull request #1949 from lewurm/fixtype
[mono.git] / mono / metadata / sgen-client-mono.h
index ae1ebcbab81137f113a96b4899b078296b673b4c..e986ae0c2ed5ba451d3c3b34204e27ae687405fa 100644 (file)
 
 #ifdef SGEN_DEFINE_OBJECT_VTABLE
 
-#include "metadata/sgen-archdep.h"
+#include "sgen/sgen-archdep.h"
 #include "utils/mono-threads.h"
 #include "utils/mono-mmap.h"
+#include "metadata/object-internals.h"
 
 typedef MonoObject GCObject;
-typedef MonoVTable GCVTable;
+typedef MonoVTable* GCVTable;
 
-/* FIXME: This should return a GCVTable* and be a function. */
-#define SGEN_LOAD_VTABLE_UNCHECKED(obj)        ((void*)(((GCObject*)(obj))->vtable))
-
-static inline mword
-sgen_vtable_get_descriptor (GCVTable *vtable)
+static inline GCVTable
+SGEN_LOAD_VTABLE_UNCHECKED (GCObject *obj)
 {
-       return (mword)vtable->gc_descr;
+       return obj->vtable;
 }
 
-static mword /*__attribute__((noinline)) not sure if this hint is a good idea*/
-sgen_client_slow_object_get_size (GCVTable *vtable, GCObject* o)
+static inline SgenDescriptor
+sgen_vtable_get_descriptor (GCVTable vtable)
 {
-       MonoClass *klass = ((MonoVTable*)vtable)->klass;
-
-       /*
-        * We depend on mono_string_length_fast and
-        * mono_array_length_fast not using the object's vtable.
-        */
-       if (klass == mono_defaults.string_class) {
-               return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
-       } else if (klass->rank) {
-               MonoArray *array = (MonoArray*)o;
-               size_t size = sizeof (MonoArray) + klass->sizes.element_size * mono_array_length_fast (array);
-               if (G_UNLIKELY (array->bounds)) {
-                       size += sizeof (mono_array_size_t) - 1;
-                       size &= ~(sizeof (mono_array_size_t) - 1);
-                       size += sizeof (MonoArrayBounds) * klass->rank;
-               }
-               return size;
-       } else {
-               /* from a created object: the class must be inited already */
-               return klass->instance_size;
-       }
-}
-
-/*
- * This function can be called on an object whose first word, the
- * vtable field, is not intact.  This is necessary for the parallel
- * collector.
- */
-static MONO_NEVER_INLINE mword
-sgen_client_par_object_get_size (GCVTable *vtable, GCObject* o)
-{
-       mword descr = sgen_vtable_get_descriptor (vtable);
-       mword type = descr & DESC_TYPE_MASK;
-
-       if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_PTRFREE) {
-               mword size = descr & 0xfff8;
-               SGEN_ASSERT (9, size >= sizeof (MonoObject), "Run length object size to small");
-               return size;
-       } else if (descr == SGEN_DESC_STRING) {
-               return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
-       } else if (type == DESC_TYPE_VECTOR) {
-               int element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE;
-               MonoArray *array = (MonoArray*)o;
-               size_t size = sizeof (MonoArray) + element_size * mono_array_length_fast (array);
-
-               /*
-                * Non-vector arrays with a single dimension whose lower bound is zero are
-                * allocated without bounds.
-                */
-               if ((descr & VECTOR_KIND_ARRAY) && array->bounds) {
-                       size += sizeof (mono_array_size_t) - 1;
-                       size &= ~(sizeof (mono_array_size_t) - 1);
-                       size += sizeof (MonoArrayBounds) * ((MonoVTable*)vtable)->klass->rank;
-               }
-               return size;
-       }
-
-       return sgen_client_slow_object_get_size (vtable, o);
+       return (SgenDescriptor)vtable->gc_descr;
 }
 
 typedef struct _SgenClientThreadInfo SgenClientThreadInfo;
@@ -121,6 +62,13 @@ struct _SgenClientThreadInfo {
        */
        gboolean gc_disabled;
 
+#ifdef SGEN_POSIX_STW
+       /* This is -1 until the first suspend. */
+       int signal;
+       /* FIXME: kill this, we only use signals on systems that have rt-posix, which doesn't have issues with duplicates. */
+       unsigned int stop_count; /* to catch duplicate signals. */
+#endif
+
        gpointer runtime_data;
 
        void *stack_end;
@@ -142,6 +90,8 @@ struct _SgenClientThreadInfo {
 #include "utils/mono-counters.h"
 #include "utils/mono-logger-internal.h"
 #include "utils/mono-time.h"
+#include "utils/mono-semaphore.h"
+#include "metadata/sgen-bridge-internal.h"
 
 extern void mono_sgen_register_moved_object (void *obj, void *destination);
 extern void mono_sgen_gc_event_moves (void);
@@ -153,11 +103,78 @@ enum {
        INTERNAL_MEM_MAX
 };
 
+static inline mword
+sgen_mono_array_size (GCVTable vtable, MonoArray *array, mword *bounds_size, mword descr)
+{
+       mword size, size_without_bounds;
+       int element_size;
+
+       if ((descr & DESC_TYPE_MASK) == DESC_TYPE_VECTOR)
+               element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE;
+       else
+               element_size = vtable->klass->sizes.element_size;
+
+       size_without_bounds = size = sizeof (MonoArray) + element_size * mono_array_length_fast (array);
+
+       if (G_UNLIKELY (array->bounds)) {
+               size += sizeof (mono_array_size_t) - 1;
+               size &= ~(sizeof (mono_array_size_t) - 1);
+               size += sizeof (MonoArrayBounds) * vtable->klass->rank;
+       }
+
+       if (bounds_size)
+               *bounds_size = size - size_without_bounds;
+       return size;
+}
+
 #define SGEN_CLIENT_OBJECT_HEADER_SIZE         (sizeof (GCObject))
 #define SGEN_CLIENT_MINIMUM_OBJECT_SIZE                SGEN_CLIENT_OBJECT_HEADER_SIZE
 
+static mword /*__attribute__((noinline)) not sure if this hint is a good idea*/
+sgen_client_slow_object_get_size (GCVTable vtable, GCObject* o)
+{
+       MonoClass *klass = ((MonoVTable*)vtable)->klass;
+
+       /*
+        * We depend on mono_string_length_fast and
+        * mono_array_length_fast not using the object's vtable.
+        */
+       if (klass == mono_defaults.string_class) {
+               return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
+       } else if (klass->rank) {
+               return sgen_mono_array_size (vtable, (MonoArray*)o, NULL, 0);
+       } else {
+               /* from a created object: the class must be inited already */
+               return klass->instance_size;
+       }
+}
+
+/*
+ * This function can be called on an object whose first word, the
+ * vtable field, is not intact.  This is necessary for the parallel
+ * collector.
+ */
+static MONO_NEVER_INLINE mword
+sgen_client_par_object_get_size (GCVTable vtable, GCObject* o)
+{
+       SgenDescriptor descr = sgen_vtable_get_descriptor (vtable);
+       mword type = descr & DESC_TYPE_MASK;
+
+       if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_PTRFREE) {
+               mword size = descr & 0xfff8;
+               SGEN_ASSERT (9, size >= sizeof (MonoObject), "Run length object size to small");
+               return size;
+       } else if (descr == SGEN_DESC_STRING) {
+               return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2;
+       } else if (type == DESC_TYPE_VECTOR) {
+               return sgen_mono_array_size (vtable, (MonoArray*)o, NULL, descr);
+       }
+
+       return sgen_client_slow_object_get_size (vtable, o);
+}
+
 static MONO_ALWAYS_INLINE size_t G_GNUC_UNUSED
-sgen_client_array_element_size (GCVTable *gc_vtable)
+sgen_client_array_element_size (GCVTable gc_vtable)
 {
        MonoVTable *vt = (MonoVTable*)gc_vtable;
        return mono_array_element_size (vt->klass);
@@ -181,22 +198,15 @@ sgen_client_object_is_array_fill (GCObject *o)
        return ((MonoObject*)o)->synchronisation == GINT_TO_POINTER (-1);
 }
 
-/* FIXME: Why do we even need this?  Can't we get it from the descriptor? */
-static gboolean G_GNUC_UNUSED
-sgen_client_vtable_has_references (GCVTable *vt)
-{
-       return ((MonoVTable*)vt)->klass->has_references;
-}
-
 static MONO_ALWAYS_INLINE void G_GNUC_UNUSED
-sgen_client_pre_copy_checks (char *destination, GCVTable *gc_vtable, void *obj, mword objsize)
+sgen_client_pre_copy_checks (char *destination, GCVTable gc_vtable, void *obj, mword objsize)
 {
        MonoVTable *vt = (MonoVTable*)gc_vtable;
        SGEN_ASSERT (9, vt->klass->inited, "vtable %p for class %s:%s was not initialized", vt, vt->klass->name_space, vt->klass->name);
 }
 
 static MONO_ALWAYS_INLINE void G_GNUC_UNUSED
-sgen_client_update_copied_object (char *destination, GCVTable *gc_vtable, void *obj, mword objsize)
+sgen_client_update_copied_object (char *destination, GCVTable gc_vtable, void *obj, mword objsize)
 {
        MonoVTable *vt = (MonoVTable*)gc_vtable;
        if (G_UNLIKELY (vt->rank && ((MonoArray*)obj)->bounds)) {
@@ -239,13 +249,55 @@ sgen_client_object_has_critical_finalizer (GCObject *obj)
        if (!mono_defaults.critical_finalizer_object)
                return FALSE;
 
-       class = ((MonoVTable*)SGEN_LOAD_VTABLE (obj))->klass;
+       class = SGEN_LOAD_VTABLE (obj)->klass;
 
        return mono_class_has_parent_fast (class, mono_defaults.critical_finalizer_object);
 }
 
-const char* sgen_client_vtable_get_namespace (GCVTable *vtable);
-const char* sgen_client_vtable_get_name (GCVTable *vtable);
+const char* sgen_client_vtable_get_namespace (GCVTable vtable);
+const char* sgen_client_vtable_get_name (GCVTable vtable);
+
+static gboolean G_GNUC_UNUSED
+sgen_client_bridge_need_processing (void)
+{
+       return sgen_need_bridge_processing ();
+}
+
+static void G_GNUC_UNUSED
+sgen_client_bridge_reset_data (void)
+{
+       sgen_bridge_reset_data ();
+}
+
+static void G_GNUC_UNUSED
+sgen_client_bridge_processing_stw_step (void)
+{
+       sgen_bridge_processing_stw_step ();
+}
+
+static void G_GNUC_UNUSED
+sgen_client_bridge_wait_for_processing (void)
+{
+       mono_gc_wait_for_bridge_processing ();
+}
+
+static void G_GNUC_UNUSED
+sgen_client_bridge_processing_finish (int generation)
+{
+       sgen_bridge_processing_finish (generation);
+}
+
+static gboolean G_GNUC_UNUSED
+sgen_client_bridge_is_bridge_object (GCObject *obj)
+{
+       return sgen_is_bridge_object (obj);
+}
+
+static void G_GNUC_UNUSED
+sgen_client_bridge_register_finalized_object (GCObject *object)
+{
+       sgen_bridge_register_finalized_object (object);
+}
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_collection_requested (int generation, size_t requested_size, gboolean force)
@@ -259,6 +311,13 @@ sgen_client_binary_protocol_collection_begin (int minor_gc_count, int generation
        MONO_GC_BEGIN (generation);
 
        mono_profiler_gc_event (MONO_GC_EVENT_START, generation);
+
+#ifndef DISABLE_PERFCOUNTERS
+       if (generation == GENERATION_NURSERY)
+               mono_perfcounters->gc_collections0++;
+       else
+               mono_perfcounters->gc_collections1++;
+#endif
 }
 
 static void G_GNUC_UNUSED
@@ -300,7 +359,7 @@ sgen_client_binary_protocol_sweep_end (int generation, int full_sweep)
 }
 
 static void G_GNUC_UNUSED
-sgen_client_binary_protocol_world_stopping (int generation, long long timestamp)
+sgen_client_binary_protocol_world_stopping (int generation, long long timestamp, gpointer thread)
 {
        MONO_GC_WORLD_STOP_BEGIN ();
 
@@ -331,6 +390,21 @@ sgen_client_binary_protocol_world_restarted (int generation, long long timestamp
        mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD, generation);
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_block_alloc (gpointer addr, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_block_free (gpointer addr, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_block_set_state (gpointer addr, size_t size, int old, int new)
+{
+}
+
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_mark_start (int generation)
 {
@@ -377,23 +451,38 @@ mono_binary_protocol_alloc_generic (gpointer obj, gpointer vtable, size_t size,
 }
 
 static void G_GNUC_UNUSED
-sgen_client_binary_protocol_alloc (gpointer obj, gpointer vtable, size_t size)
+sgen_client_binary_protocol_alloc (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
 {
        mono_binary_protocol_alloc_generic (obj, vtable, size, FALSE);
 }
 
 static void G_GNUC_UNUSED
-sgen_client_binary_protocol_alloc_pinned (gpointer obj, gpointer vtable, size_t size)
+sgen_client_binary_protocol_alloc_pinned (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
 {
        mono_binary_protocol_alloc_generic (obj, vtable, size, TRUE);
 }
 
 static void G_GNUC_UNUSED
-sgen_client_binary_protocol_alloc_degraded (gpointer obj, gpointer vtable, size_t size)
+sgen_client_binary_protocol_alloc_degraded (gpointer obj, gpointer vtable, size_t size, gpointer provenance)
 {
        MONO_GC_MAJOR_OBJ_ALLOC_DEGRADED ((mword)obj, size, sgen_client_vtable_get_namespace (vtable), sgen_client_vtable_get_name (vtable));
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_card_scan (gpointer start, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_pin_stage (gpointer addr_ptr, gpointer addr)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_cement_stage (gpointer addr)
+{
+}
+
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_pin (gpointer obj, gpointer vtable, size_t size)
 {
@@ -407,6 +496,36 @@ sgen_client_binary_protocol_pin (gpointer obj, gpointer vtable, size_t size)
 #endif
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_mark (gpointer obj, gpointer vtable, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_scan_begin (gpointer obj, gpointer vtable, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_scan_vtype_begin (gpointer obj, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_scan_process_reference (gpointer obj, gpointer ptr, gpointer value)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_scan_stack (gpointer thread, gpointer stack_start, gpointer stack_end, int skip_reason)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_wbarrier (gpointer ptr, gpointer value, gpointer value_vtable)
+{
+}
+
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_cement (gpointer ptr, gpointer vtable, size_t size)
 {
@@ -442,11 +561,26 @@ sgen_client_binary_protocol_global_remset (gpointer ptr, gpointer value, gpointe
 }
 
 static void G_GNUC_UNUSED
-sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolean track, gboolean staged)
+sgen_client_binary_protocol_ptr_update (gpointer ptr, gpointer old_value, gpointer new_value, gpointer vtable, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_cleanup (gpointer ptr, gpointer vtable, size_t size)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_dislink_add (gpointer link, gpointer obj, gboolean track)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolean track)
 {
 #ifdef ENABLE_DTRACE
        if (MONO_GC_WEAK_UPDATE_ENABLED ()) {
-               GCVTable *vt = obj ? (GCVTable*)SGEN_LOAD_VTABLE (obj) : NULL;
+               GCVTable vt = obj ? SGEN_LOAD_VTABLE (obj) : NULL;
                MONO_GC_WEAK_UPDATE ((mword)link,
                                (mword)obj,
                                obj ? (mword)sgen_safe_object_get_size (obj) : (mword)0,
@@ -457,6 +591,11 @@ sgen_client_binary_protocol_dislink_update (gpointer link, gpointer obj, gboolea
 #endif
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_dislink_remove (gpointer link, gboolean track)
+{
+}
+
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_empty (gpointer start, size_t size)
 {
@@ -506,15 +645,27 @@ sgen_client_binary_protocol_domain_unload_end (gpointer domain)
 {
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_gray_enqueue (gpointer queue, gpointer cursor, gpointer value)
+{
+}
+
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_gray_dequeue (gpointer queue, gpointer cursor, gpointer value)
+{
+}
+
 int sgen_thread_handshake (BOOL suspend);
 gboolean sgen_suspend_thread (SgenThreadInfo *info);
 gboolean sgen_resume_thread (SgenThreadInfo *info);
 void sgen_wait_for_suspend_ack (int count);
 
 #ifdef HAVE_KW_THREAD
+extern __thread SgenThreadInfo *sgen_thread_info;
 #define TLAB_ACCESS_INIT
 #define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
 #else
+extern MonoNativeTlsKey thread_info_key;
 #define TLAB_ACCESS_INIT       SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
 #define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
 #endif
@@ -539,6 +690,22 @@ void sgen_wait_for_suspend_ack (int count);
 
 #define SGEN_TV_DECLARE(name) gint64 name
 #define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks ()
-#define SGEN_TV_ELAPSED(start,end) (int)((end-start))
+#define SGEN_TV_ELAPSED(start,end) ((long)(end-start))
+
+typedef MonoSemType SgenSemaphore;
+
+#define SGEN_SEMAPHORE_INIT(sem,initial)       MONO_SEM_INIT ((sem), (initial))
+#define SGEN_SEMAPHORE_POST(sem)               MONO_SEM_POST ((sem))
+#define SGEN_SEMAPHORE_WAIT(sem)               MONO_SEM_WAIT ((sem))
+
+gboolean sgen_has_critical_method (void);
+gboolean sgen_is_critical_method (MonoMethod *method);
+
+void sgen_set_use_managed_allocator (gboolean flag);
+gboolean sgen_is_managed_allocator (MonoMethod *method);
+gboolean sgen_has_managed_allocator (void);
+
+void sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type);
+void sgen_null_links_for_domain (MonoDomain *domain);
 
 #endif