/* AOT case */
class->vtable_size = cached_info.vtable_size;
class->has_finalize = cached_info.has_finalize;
+ class->has_finalize_inited = TRUE;
class->ghcimpl = cached_info.ghcimpl;
class->has_cctor = cached_info.has_cctor;
} else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
} else {
class->vtable_size = szarray_vtable_size[slot];
}
+ class->has_finalize_inited = TRUE;
} else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
MonoClass *gklass = class->generic_class->container_class;
/* Generic instance case */
class->ghcimpl = gklass->ghcimpl;
- class->has_finalize = gklass->has_finalize;
+ class->has_finalize = mono_class_has_finalizer (gklass);
+ class->has_finalize_inited = TRUE;
class->has_cctor = gklass->has_cctor;
mono_class_setup_vtable (gklass);
}
*/
- /* Interfaces and valuetypes are not supposed to have finalizers */
- if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
- MonoMethod *cmethod = NULL;
-
- if (class->parent && class->parent->has_finalize) {
- class->has_finalize = 1;
- } else {
- if (class->type_token) {
- cmethod = find_method_in_metadata (class, "Finalize", 0, METHOD_ATTRIBUTE_VIRTUAL);
- } else if (class->parent) {
- /* FIXME: Optimize this */
- mono_class_setup_vtable (class);
- if (class->exception_type || mono_loader_get_last_error ())
- goto leave;
- cmethod = class->vtable [finalize_slot];
- }
-
- if (cmethod) {
- /* Check that this is really the finalizer method */
- mono_class_setup_vtable (class);
- if (class->exception_type || mono_loader_get_last_error ())
- goto leave;
-
- g_assert (class->vtable_size > finalize_slot);
-
- class->has_finalize = 0;
- if (class->parent) {
- cmethod = class->vtable [finalize_slot];
- g_assert (cmethod);
- if (cmethod->is_inflated)
- cmethod = ((MonoMethodInflated*)cmethod)->declaring;
- if (cmethod != default_finalize) {
- class->has_finalize = 1;
- }
- }
- }
- }
- }
-
/* C# doesn't allow interfaces to have cctors */
if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
MonoMethod *cmethod = NULL;
return class->exception_type == MONO_EXCEPTION_NONE;
}
+/*
+ * mono_class_has_finalizer:
+ *
+ * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
+ * process.
+ */
+gboolean
+mono_class_has_finalizer (MonoClass *klass)
+{
+ if (!klass->has_finalize_inited) {
+ MonoClass *class = klass;
+
+ mono_loader_lock ();
+
+ /* Interfaces and valuetypes are not supposed to have finalizers */
+ if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
+ MonoMethod *cmethod = NULL;
+
+ if (class->parent && class->parent->has_finalize) {
+ class->has_finalize = 1;
+ } else {
+ if (class->parent) {
+ /*
+ * Can't search in metadata for a method named Finalize, because that
+ * ignores overrides.
+ */
+ mono_class_setup_vtable (class);
+ if (class->exception_type || mono_loader_get_last_error ())
+ goto leave;
+ cmethod = class->vtable [finalize_slot];
+ }
+
+ if (cmethod) {
+ g_assert (class->vtable_size > finalize_slot);
+
+ class->has_finalize = 0;
+ if (class->parent) {
+ if (cmethod->is_inflated)
+ cmethod = ((MonoMethodInflated*)cmethod)->declaring;
+ if (cmethod != default_finalize) {
+ class->has_finalize = 1;
+ }
+ }
+ }
+ }
+ }
+
+ mono_memory_barrier ();
+ klass->has_finalize_inited = TRUE;
+
+ mono_loader_unlock ();
+ }
+
+ return klass->has_finalize;
+
+ leave:
+ mono_loader_unlock ();
+ return FALSE;
+}
+
gboolean
mono_is_corlib_image (MonoImage *image)
{