This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Get libffi closures to cope with SELinux execmem/execmod


On Mon, 5 Feb 2007, Alexandre Oliva wrote:

> > - It doesn't fit well with the GCs original design.  It feels like a
> > hack on the interface, even more so than the Java finalization
> > extension.
>
> I agree.  That's why I've been hinting that, instead of adding a new
> finalization type, we should modify the non-Java finalization types
> such that they enforce the original property even in Java mode.
>
> I haven't been able to think of any case in which it could possibly be
> useful for a finalizer to want to run only if no other finalizers with
> normal semantics reach it, even if other finalizers with Java
> semantics do.

I'm unconvinced of this point, but there probably is a variant of this
solution that could also work.

To see why I'm not convinced, assume I have some object A with a bunch of
reference fields, but only field f is needed by the finalizer.

Case 1:
If I'm careful and using normal (ordered) finalization semantics, I
would separate A into two objects A and A' where A' contains (possibly
a copy of) f and none of the other reference fields, A points to A',
and only A' is finalizaton-enabled, something like

A   ->   A'    ->  ...
       final.  f

That way I avoid spurious finalization cycles.

Case 2:
If I'm using Java (unordered) finalization for A, there is no reason to do
this, and I just make A finalizable.  (To avoid premature finalization,
I would probably put a copy of f in some permanent data structure, but that
doesn't matter here.)

Now assume A has another field f2 that (possibly indirectly) points to a
(ordered) non-Java-finalizable object B.  Assume for the case of argument
that it points back to A since B and Bs finalizer needs A.  I claim:

In case 1:  B can be finalized since it's not reachable from a
finalization-enabled object, A will probably become unreachable in the
next cycle, and A' will then be finalized.  I'm fine, as expected.

In case 2:  B is reachable from A, and the author of A had no reason to
avoid that, since unordered finalization is used.  But now if I let
that inhibit finalization of B, I have a finalization cycle, and neither
can get finalized.  That seems wrong.

I think the more general solution you suggest works only because the
normally finalizable resources in question are known not to refer to
Java objects, and hence the above situation can't arise.  It's needed
because we can't can't trust the Java code to do the right thing.
(And it probably couldn't anyway because not all the relevant references
are visible at the Java level.)  But if we had a C program mixing
finalization types, I think you'd want the other treatment.

I think the solution below incurs a slight risk of breaking something,
if e.g. Mono relied on the current behavior someplace.  But I could
also live with the variant in which this was a global (initialization
time) option, and the code below were wrapped in a suitable conditional.
The GC already has some such options.

Otherwise, the original patch seems fine.

Hans

>
> What I have in mind is something like this (untested) patch.  How do
> you feel about it?
>
>
> Index: finalize.c
> ===================================================================
> --- finalize.c	(revision 121196)
> +++ finalize.c	(working copy)
> @@ -2,6 +2,7 @@
>   * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
>   * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
>   * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
> + * Copyright (C) 2007 Free Software Foundation, Inc
>
>   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
>   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
> @@ -637,10 +638,43 @@
>    	if (!GC_is_marked(real_ptr)) {
>    	    if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
>    	        GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
> +		GC_set_mark_bit(real_ptr);
>    	    }
> -  	    GC_set_mark_bit(real_ptr);
>    	}
>        }
> +
> +      /* now revive finalize-when-unreachable objects reachable from
> +	 other finalizable objects */
> +      curr_fo = GC_finalize_now;
> +      prev_fo = 0;
> +      while (curr_fo != 0) {
> +	next_fo = fo_next(curr_fo);
> +	if (curr_fo -> fo_mark_proc != GC_null_finalize_mark_proc) {
> +	  real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
> +	  if (!GC_is_marked(real_ptr)) {
> +	      GC_set_mark_bit(real_ptr);
> +	  } else {
> +	      if (prev_fo == 0)
> +		GC_finalize_now = next_fo;
> +	      else
> +		fo_set_next(prev_fo, next_fo);
> +
> +              curr_fo -> fo_hidden_base =
> +              		(word) HIDE_POINTER(curr_fo -> fo_hidden_base);
> +              GC_words_finalized -=
> +                 	ALIGNED_WORDS(curr_fo -> fo_object_size)
> +              		+ ALIGNED_WORDS(sizeof(struct finalizable_object));
> +
> +	      i = HASH2(real_ptr, log_fo_table_size);
> +	      fo_set_next (curr_fo, fo_head[i]);
> +	      GC_fo_entries++;
> +	      fo_head[i] = curr_fo;
> +	      curr_fo = prev_fo;
> +	  }
> +	}
> +	prev_fo = curr_fo;
> +	curr_fo = next_fo;
> +      }
>    }
>
>    /* Remove dangling disappearing links. */
>
>
> --
> Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
> FSF Latin America Board Member         http://www.fsfla.org/
> Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
> Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]