There is an additional axis to bridge processing than just if a type is a bridge or not.
It can be processing transparent or opaque.
We didn't make this distinction before and treated all types as transparent.
Opaque types means that bridge processing should stop at them. An opaque bridge, in
addition to that, means it should be reported in.
This change paves the way for bridge graph pruning.
return bridge_callbacks.is_bridge_object (obj);
}
-gboolean
-sgen_is_bridge_class (MonoClass *class)
+MonoGCBridgeObjectKind
+sgen_bridge_class_kind (MonoClass *class)
{
- return bridge_callbacks.is_bridge_class (class);
+ return bridge_callbacks.bridge_class_kind (class);
}
gboolean
static const char *bridge_class;
-static gboolean
-bridge_test_is_bridge_class (MonoClass *class)
+static MonoGCBridgeObjectKind
+bridge_test_bridge_class_kind (MonoClass *class)
{
- return !strcmp (bridge_class, class->name);
+ if (!strcmp (bridge_class, class->name))
+ return GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS;
+ return GC_BRIDGE_TRANSPARENT_CLASS;
}
static gboolean
{
MonoGCBridgeCallbacks callbacks;
callbacks.bridge_version = SGEN_BRIDGE_VERSION;
- callbacks.is_bridge_class = bridge_test_is_bridge_class;
+ callbacks.bridge_class_kind = bridge_test_bridge_class_kind;
callbacks.is_bridge_object = bridge_test_is_bridge_object;
callbacks.cross_references = bridge_class_name[0] == '2' ? bridge_test_cross_reference2 : bridge_test_cross_reference;
mono_gc_register_bridge_callbacks (&callbacks);
MONO_BEGIN_DECLS
enum {
- SGEN_BRIDGE_VERSION = 3
+ SGEN_BRIDGE_VERSION = 4
};
+typedef enum {
+ /* Instances of this class should be scanned when computing the transitive dependency among bridges. E.g. List<object>*/
+ GC_BRIDGE_TRANSPARENT_CLASS,
+ /* Instances of this class should not be scanned when computing the transitive dependency among bridges. E.g. String*/
+ GC_BRIDGE_OPAQUE_CLASS,
+ /* Instances of this class should be bridged and have their dependency computed. */
+ GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS,
+ /* Instances of this class should be bridged but no dependencies should not be calculated. */
+ GC_BRIDGE_OPAQUE_BRIDGE_CLASS,
+} MonoGCBridgeObjectKind;
+
typedef struct {
mono_bool is_alive; /* to be set by the cross reference callback */
int num_objs;
typedef struct {
int bridge_version;
- mono_bool (*is_bridge_class) (MonoClass *class);
+ MonoGCBridgeObjectKind (*bridge_class_kind) (MonoClass *class);
mono_bool (*is_bridge_object) (MonoObject *object);
void (*cross_references) (int num_sccs, MonoGCBridgeSCC **sccs, int num_xrefs, MonoGCBridgeXRef *xrefs);
} MonoGCBridgeCallbacks;
guint
mono_gc_get_vtable_bits (MonoClass *class)
{
- if (sgen_need_bridge_processing () && sgen_is_bridge_class (class))
+ /* FIXME move this to the bridge code */
+ if (!sgen_need_bridge_processing ())
+ return 0;
+ switch (sgen_bridge_class_kind (class)) {
+ case GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS:
+ case GC_BRIDGE_OPAQUE_BRIDGE_CLASS:
return SGEN_GC_BIT_BRIDGE_OBJECT;
+ }
return 0;
}
#include <mono/metadata/sgen-descriptor.h>
#include <mono/metadata/sgen-gray.h>
#include <mono/metadata/sgen-hash-table.h>
+#include <mono/metadata/sgen-bridge.h>
/* The method used to clear the nursery */
/* Clearing at nursery collections is the safest, but has bad interactions with caches.
void sgen_bridge_processing_finish (int generation) MONO_INTERNAL;
void sgen_register_test_bridge_callbacks (const char *bridge_class_name) MONO_INTERNAL;
gboolean sgen_is_bridge_object (MonoObject *obj) MONO_INTERNAL;
-gboolean sgen_is_bridge_class (MonoClass *class) MONO_INTERNAL;
+MonoGCBridgeObjectKind sgen_bridge_class_kind (MonoClass *class) MONO_INTERNAL;
void sgen_mark_bridge_object (MonoObject *obj) MONO_INTERNAL;
void sgen_bridge_register_finalized_object (MonoObject *object) MONO_INTERNAL;
void sgen_bridge_describe_pointer (MonoObject *object) MONO_INTERNAL;