From vsnyder@math.Jpl.Nasa.Gov  Wed Jan 29 00:25:02 1997
Received: from eis-net-001.jpl.nasa.gov (eis-net-001.jpl.nasa.gov [137.78.57.19]) by dkuug.dk (8.6.12/8.6.12) with ESMTP id AAA03827 for <sc22wg5@dkuug.dk>; Wed, 29 Jan 1997 00:24:58 +0100
Received: from math.Jpl.Nasa.Gov (math.jpl.nasa.gov [137.78.227.106]) by eis-net-001.jpl.nasa.gov (8.7.5/8.7.3) with ESMTP id PAA00439 for <sc22wg5@dkuug.dk>; Tue, 28 Jan 1997 15:24:45 -0800 (PST)
Message-Id: <199701282324.PAA00439@eis-net-001.jpl.nasa.gov>
Received: by math.Jpl.Nasa.Gov
	(1.37.109.15/16.2) id AA081013806; Tue, 28 Jan 1997 15:23:26 -0800
From: Van Snyder <vsnyder@math.Jpl.Nasa.Gov>
Subject: Comments on N1187
To: sc22wg5@dkuug.dk
Date: Tue, 28 Jan 1997 15:23:26 PST
Reply-To: <vsnyder@math.Jpl.Nasa.Gov>
X-Mailer: Elm [revision: 109.14]

Comments on N1187: Requirements for Cleaner and Producer in Fortran 90

A cleaner should be called after the end of a variable's _lifetime_,
not its scope.  There's a difference for SAVEd pointers.

Section II, just below the middle of the page:
  When x = f(y,z) appears, x and f have the same type, and intrinsic
  assignment is used, there appear to be three possibilities:
  1.  The compiler passes the address of the l.h.s. into the function,
      by way of a hidden argument, to be used for the result.
  2.  The compiler creates a temp. variable and passes its address into
      the function, by way of a hidden argument, to be used for the
      result, and then uses intrinsic assignment to copy the result from
      the temp. to the l.h.s.
  3.  The compiler materializes function results by copying their
      values, not by sending the address of the result to the function.

  In all three cases, intrinsic assignment might cause pointer
  assignment into components of x, covering up the previous values
  without checking whether they should be deallocated, causing a memory
  leak.  So it's the _cleaner_ that needs to be run on the l.h.s.

  In the second and third cases, the cleaner needs be run on the
  anonymous temp. variable(s) if the generated code re-uses them.

  In the second and third cases, if pointer components are copied using
  pointer assignment ("shallow copy"), as opposed to allocating new
  space and copying the data ("deep copy"), and then the cleaner is run
  on a temp., the cleaner must be careful _not_ to delete the space --
  this would cause "dangling pointers."  Reference counters in the
  targets could prevent this.

"Task of a Producer..." on page 7:
  In the absence of defined assignment, the discussion for
  pre-assignment should be reconsidered in light of the first remark
  above, concerning section II.  If one insists on using "producers"
  the optimization suggested above would be prohibited.

The argument that one could have a special flag to indicate a function
result, and check that flag in various places to decide to clean up,
doesn't satisfy me.  If the flag isn't correctly managed, then after
x=f(y,z) using intrinsic assignment, x has the flag that says it's a
function result.  So the flag either must be "hidden" and managed by
intrinsic assignment, or users must _always_ write defined assignment
subroutines if derived types have pointer components.  The author of
N1187 suggests that if defined assignment is used for x=f(y,z), the
assignment subroutine could clean up its second argument.  But then the
assignment subroutine might clean up its second argument after w=x as
well.  What if the program still needs x?  The same objection applies
to the suggestion that a function could clean up its arguments when
it's finished, if they have the flags that say they're function
results.

Things get worse if the compiler does common sub-expression elimination.
Suppose you've defined "+" for something like extended precision, or
arithmetic with Taylor's series, or ... (so there are pointer components
in derived type variables), and (a+b) appears twice.  Should the
compiler _not_ do common subexpression elimination involving defined
operators, or should it somehow figure out whether to put the "flags"
onto the temp. result (a+b) in one circumstance and not the other, or ?

There are several related problems that seem to get confounded in N1187:
1.  "Cleaners" or "destructors" are needed so as not to have memory
    leaks when variables (especially anonymous temporaries) have
    pointer components.  They need to be run automatically when
    lifetimes of objects end.
2.  Reference counts are needed so as not to deallocate data when there
    are still pointers to them.  This induces sub-questions:
    2a.  Should intrinsic assignment and deallocation maintain reference
         counters? Or
    2b.  Should one be allowed to define pointer assignment, a natural
         extension of the ability to define intrinsic data assignment?
    2c.  Should DEALLOCATE pay attention to reference counts? Or
    2d.  Should one be allowed to define a type-dependent procedure that
         gets run by the DEALLOCATE statement?  This induces the sub-
         sub-problem:
         2d.1.  How does the deallocation finally get done?  It seems
                one needs an embellishment of the DEALLOCATE statement
                that instructs it to go ahead and deallocate, not to run
                a type-dependent procedure (otherwise a recursion
                without exit results).
3.  Maybe I missed something, but I don't see the value of or need for a
    producer.

I shall further tax your patience after I have read N1188 and N1189.

Best regards to all,
Van Snyder
