CVS difference for ais/ai-00147.txt

Differences between 1.2 and version 1.3
Log of other versions for file ais/ai-00147.txt

--- ais/ai-00147.txt	1998/10/01 00:24:26	1.2
+++ ais/ai-00147.txt	1999/03/04 20:41:39	1.3
@@ -1,7 +1,7 @@
-!standard 07.06    (21)                               98-09-29  AI95-00147/04
+!standard 07.06    (21)                               99-02-23  AI95-00147/05
 !class binding interpretation 96-06-06
 !status work item 98-04-01
-!status ARG Approved (with changes) 10-1-2  95-11-01
+!status ARG Approved (with changes) 10-1-2  97-11-16
 !status work item 5-1-4  96-10-07
 !status work item 96-06-06
 !status received 96-06-06
@@ -9,34 +9,35 @@
 !difficulty Hard
 !subject Optimization of Controlled Types
 
-!summary 98-09-29
+!summary 99-02-23
 
 7.6(18-21) does not apply to limited controlled types.  Thus, the
-Initialize and Finalize calls will happen as described in other 
+Initialize and Finalize calls will happen as described in other
 paragraphs of the Standard.
 
 For non-limited controlled types, the implementation permission of
 RM-7.6(18-21) is extended as follows:
 
-An implementation is permitted to omit implicit Adjust and Finalize calls
-and associated assignment operations on an object of non-limited controlled
+An implementation is permitted to omit implicit Initialize, Adjust and Finalize
+calls and associated assignment operations on an object of non-limited controlled
 types if
   a) any change to the value of the object performed by these calls or
      assignment operations do not affect the external effect of any
      program execution, and
   b) any execution of the program that executes an Initialize or Adjust
-     call on an object will also later execute a Finalize call on the object
-     and will always do so prior to assigning a new value to the object.
-This permission applies even if the implicit calls produce side-effects
-on other objects.
+     call on an object or initializes the object by an aggregate will
+     also later execute a Finalize call on the object and will always do
+     so prior to assigning a new value to the object.
+This permission applies even if the implicit calls have additional effects.
 
+
 The last sentence of 7.6(21) is amended to include the omission of the
 finalization of the anonymous object (along with the adjustment) and to
 exclude the optimization when there are any access values designating
 the anonymous object as a whole.
 
 
-!question 98-03-21
+!question 99-02-23
 
 RM-7.6(18-21) give implementations permission to eliminate certain calls
 to Adjust and Finalize.  The purpose of these rules is to allow greater
@@ -50,25 +51,23 @@
      null;
   end;                  -- Finalize(X)
 
-Are the calls really needed for an obviously "dead" variable ?  [Yes]
-Would the Finalize call be eliminatable, if X were explicitly 
-initialized ? [Yes]
+Are the calls really needed for an obviously "dead" variable ?  [No]
 
-Second example: 
+Second example:
 
   X: Controlled_Type;        -- Initialize(X)
   begin
-      X := something;        -- Finalize(X); Adjust(X);   
-      X := something_else;   -- Finalize(X); Adjust(X);   
+      X := something;        -- Finalize(X); Adjust(X);
+      X := something_else;   -- Finalize(X); Adjust(X);
       ... X.Comp             -- so that it isn't dead
   end;                       -- Finalize(X);
 
-The comments indicate the implicit calls, already taking advantage of 
+The comments indicate the implicit calls, already taking advantage of
 the Implementation Permission to omit creation, adjustment and finalization
 of a temporary anonymous object. Is it really necessary to mandate
-the execution of the first assignment and its implicit calls, merely for 
+the execution of the first assignment and its implicit calls, merely for
 the sake of potential side-effects of these calls ? [No]
-Do we really have to Initialize and immediately thereafter Finalize X ? [Yes]
+Do we really have to Initialize and immediately thereafter Finalize X ? [No]
 
 
 Third example:
@@ -78,15 +77,15 @@
   declare
       X: Controlled_Type := Init;  -- Adjust(X);
   begin
-      X1 := X;        -- Finalize(X1); Adjust(X1);   
+      X1 := X;        -- Finalize(X1); Adjust(X1);
   end;                -- Finalize(X);
   ...
 
 Should the declare block not be optimizable to
-  X1 := Init;   -- Finalize(X1); Adjust(X1)		[Yes]
+  X1 := Init;   -- Finalize(X1); Adjust(X1)             [Yes]
 
-or the whole example to 
-  X1: Controlled_Type := Init;  -- Adjust(X1);          [No]
+or the whole example to
+  X1: Controlled_Type := Init;  -- Adjust(X1);          [Yes]
 
 avoiding so many unneeded calls ?
 
@@ -104,7 +103,7 @@
     begin
         return Result;  -- Adjust, Finalize
     end G;
-    
+
     X: Some_Controlled_Type := G;  -- Adjust
 
 Is an implementation allowed to optimize the above by creating the
@@ -122,18 +121,24 @@
 Finalize operation. Is this intended ? [No]
 
 
-!recommendation 98-09-29
+!recommendation 99-02-23
 
-For limited controlled types, the canonical semantics apply.  
+For limited controlled types, the canonical semantics apply.
 
-For non-limited controlled types, matching pairs of Adjust/Finalize may be 
-eliminated by the implementation as follows:
+For non-limited controlled types, matching pairs of Adjust/Finalize
+and Initialize/Finalize calls may be eliminated by the implementation as
+follows:
 
 For an explicit initialization of an object or an assignment to it,
-where the assigned value is not read after the Adjust call and prior
-to the Finalize call for the next assignment to the object or for its
-destruction, the Adjust/Finalize pair of calls (and the value
-assignment) need not be performed.
+where the assigned value is not read after the Adjust call (if any)
+and prior to the Finalize call for the next assignment to the object
+or for its destruction, the Adjust/Finalize pair of calls (and the
+value assignment) need not be performed.
+
+For an implicit Initialize call, where the initialized value is not
+read after the Initialize call and prior to the Finalize call for the
+next assignment to the object or for its destruction, the
+Initialize/Finalize pair of calls need not be performed.
 
 An intermediate recipient object in the flow of a value from a
 source to its final destination, where the value of the intermediate
@@ -153,7 +158,7 @@
 The last sentence of 7.6(21) needs to be amended as stated in the
 !summary.
 
-!discussion 98-09-29
+!discussion 99-02-23
 
 The above examples show that the implicit calls can create a non-trivial
 overhead on the execution even when the existing Implementation Permission
@@ -174,14 +179,14 @@
 
     function F return Some_Controlled_Type is
     begin
-        return (<<<aggregate>>); 
+        return (<<<aggregate>>);
     end F;
 
     function G return Some_Controlled_Type is
     begin
         return F;
     end G;
-    
+
     X: Some_Controlled_Type := G;  -- Adjust
 
 Again, it seems strange that this rewritten version should have
@@ -195,7 +200,7 @@
 to "temporary" named objects.
 
 7.6(18-21) does not allow the elimination of Initialize/Finalize pairs
--- rs, and then only on anonymous objects.
+- -- just Adjust/Finalize pairs, and then only on anonymous objects.
 
 For limited types, this is exactly what we want.  Limited controlled
 types are used, for example, to ensure properly matched calls, such as
@@ -219,8 +224,8 @@
 object; moreover, many Adjust calls may be applied to a value as it
 flows from object to object. By virtue of the existing implementation
 permission, the number of such calls is indeterminate. It is highly
-advisable that users essentially make Finalize an inverse dual to 
-both Initialize and Adjust, and allow for the possibility of an unknown 
+advisable that users essentially make Finalize an inverse dual to
+both Initialize and Adjust, and allow for the possibility of an unknown
 number of Adjust and Finalize calls on the same object.
 Consequently, to preserve a canonical semantics that mandates the
 execution of assignments, even if their only external effect is
@@ -229,9 +234,10 @@
 
 Conversely, it does make sense to weaken the canonical semantics for
 the benefit of important optimizations. We can do so by extending the
-permissions of 7.6(18-21) to Adjust/Finalize pairs for non-limited
-types in such a way that the practical effect is merely more uncertainty
-over an already uncertain number of call pairs.
+permissions of 7.6(18-21) to Initialize/Finalize pairs and to
+Adjust/Finalize pairs for non-limited types in such a way that the
+practical effect is merely more uncertainty over an already uncertain
+number of call pairs.
 
 Note also that it is the assignment *operation* that is abort
 deferred, not the assignment_statement.  Thus, it is possible under
@@ -252,17 +258,26 @@
 guarantee that any program execution that executes an Initialize or
 Adjust call on an object also executes a Finalize on the object.
 
-Eliminating Initialize/Finalize pairs might seem interesting, but the
-guaranteed "once-only" semantics of Initialize calls distinguishes
-them from Adjust calls. Initialize calls with side-effects should
-therefore not be eliminatable. This also guarantees that users relying
-on Initialize effects on non-limited controlled types in analogy to
-limited controlled types cannot be surprised by optimizations.
-
-Consequently, in the absence of an explicit initialization, the
-Initialize/Finalize pair will be preserved.  With an explicit
-initialization, the resulting Adjust/Finalize pair can however be
-eliminated by the proposed permissions.
+Eliminating Initialize/Finalize pairs is obviously interesting, when a
+variable is declared, but never used. Or, the more likely case, other
+optimizations have found such use to be unnecessary. Equally
+interesting are Adjust/Finalize pairs for an initialized variable that
+is never used.
+
+Consider also, for example, if the user had written
+   "Result: Some_Controlled_Type;
+   ... Result := F;"
+above, instead of "Result: Some_Controlled_Type := F;".
+
+Canonical semantics would then cause a pair of Initialize/Finalize
+calls on Result, followed by an Adjust call, while the original
+program caused only the Adjust call.  A semantics that makes these two
+alternatives significantly different, is surely a surprise to many
+users. Permission to eliminate the Initialize/Finalize pair creates at
+least the possibility that the two alternatives might result in the same
+behavior (and acts as minor additional incentive to the programmer to
+make Initialize and Finalize an "inverse" pair to get identical
+semantics from both alternatives).
 
 The optimizations argued for are restricted to those cases where, at
 Ada source level, an initialization or assignment occurs, but the
@@ -279,9 +294,9 @@
 
   X: Controlled_Type;
   begin
-      X := something;   -- Adjust(X);   
+      X := something;   -- Adjust(X);
       if P then
-         X := then_something;   -- Finalize(X); Adjust(X);   
+         X := then_something;   -- Finalize(X); Adjust(X);
       else
          X := else_something;   -- Finalize(X); Adjust(X);
          ... X.Comp             -- so that it isn't dead
@@ -290,11 +305,11 @@
 
 We would like to eliminate the first Adjust call and BOTH Finalize
 calls.  As a group, they constitute the matching pairs. We cannot
-always eliminate single pairs.  It is fairly easy to do in a compiler, 
+always eliminate single pairs.  It is fairly easy to do in a compiler,
 but hard to describe in these terms in a language definition.
 
-The words in the !summary therefore capture the bounds of the 
-optimization by its externally visible effects. 
+The words in the !summary therefore capture the bounds of the
+optimization by its externally visible effects.
 
 Finally, the !question raises an issue with the last sentence of
 7.6(21), which indeed is seriously incomplete.  The sentence needs to
@@ -330,17 +345,17 @@
 
 Consider further an assignment to such variable with no subsequent use of
 the variable prior to completion of the master. Is it legitimate to omit the
-Finalize/Adjust pair of calls along with the value transfer, which would 
+Finalize/Adjust pair of calls along with the value transfer, which would
 normally implement such an assignment ?
 
-Put differently: Can dead code and dead variable elimination disregard 
+Put differently: Can dead code and dead variable elimination disregard
 the effects of such implicit calls in determining whether an object or
 assignment is needed at all ?
 
 In the spirit of 7.6(21), which makes the exact number of such calls
 implementation-defined, anyhow, one might assume that such liberty causes
 little damage, while being quite important for further reducing the number of
-such (unneeded) calls and enabling other optimizations. 
+such (unneeded) calls and enabling other optimizations.
 
 
 ****************************************************************
@@ -409,12 +424,12 @@
 
 > Consider further an assignment to such variable with no subsequent use of
 > the variable prior to completion of the master. Is it legitimate to omit the
-> Finalize/Adjust pair of calls along with the value transfer, which would 
+> Finalize/Adjust pair of calls along with the value transfer, which would
 > normally implement such an assignment ?
 
 Hmm.  Maybe.
 
-> Put differently: Can dead code and dead variable elimination disregard 
+> Put differently: Can dead code and dead variable elimination disregard
 > the effects of such implicit calls in determining whether an object or
 > assignment is needed at all ?
 
@@ -423,11 +438,11 @@
 > In the spirit of 7.6(21), which makes the exact number of such calls
 > implementation-defined, anyhow, one might assume that such liberty causes
 > little damage, while being quite important for further reducing the number of
-> such (unneeded) calls and enabling other optimizations. 
+> such (unneeded) calls and enabling other optimizations.
 
 True, but certainly not for limited types.
 
-- Bob
+- - Bob
 
 
 ****************************************************************
@@ -554,7 +569,7 @@
 "interpreted" otherwise by the ARG, the only permissions to play games
 apply to Adjust/Finalize pairs, and not Initialize/Finalize pairs.
 
-- Bob
+- - Bob
 
 ****************************************************************
 
@@ -624,6 +639,53 @@
 
 > [Note: ACVC-test C980003 wants to know to check abort-deferral of
 > assignments in general.]
+
+- -Tuck
+
+****************************************************************
+
+From: 	Tucker Taft
+Sent: 	Tuesday, March 02, 1999 9:55 PM
+Subject: 	Re: AI-00147 revised
+
+> An implementation is permitted to omit implicit Initialize, Adjust and Finalize
+> calls and associated assignment operations on an object of non-limited controlled
+> types if
+>   a) any change to the value of the object performed by these calls or
+>      assignment operations do not affect the external effect of any
+>      program execution, and
+
+I don't find this wording very understandable.  You explain things
+better later.  The presumption is that after a Finalize, there
+is no reference to the value anyway.  So all we care about is that
+between the return from Initialize/Adjust, and the call to Finalize,
+the value of the object is not used.  Another way to put it is that
+if the Initialize is omitted, then the value is undefined until the
+next copy/Adjust (if any), and the Initialize can be omitted only
+if the content of this undefined value does not affect the
+external interactions of the program up to that next Adjust.  This is
+similar to the permission in 11.6(5) to omit raising an exception upon a
+check failure.  The raise may be omitted only if the content of the
+undefined value wouldn't alter the external interactions.
+
+The key point is that the compiler does *not* need to look "inside" the
+Initialize, Adjust, or Finalize routine to make this determination.
+All it needs to notice is whether the content of the object is referenced
+(in an externally significant way) between the initial Initialize/Adjust
+call and the matching Finalize.
+
+>   b) any execution of the program that executes an Initialize or Adjust
+>      call on an object or initializes the object by an aggregate will
+>      also later execute a Finalize call on the object and will always do
+>      so prior to assigning a new value to the object.
+
+I also have trouble with this wording.  You are implying that an
+initialize/finalize can be omitted *if* (a) and (b), but I think rather
+you want to say that "if" (a) is true, and that *after* removing the pair,
+(b) must still be true.  (b) is certainly true *before* you omit the pair,
+which seems to be all that the word "if" is requiring.
+
+> ...
 
 -Tuck
 

Questions? Ask the ACAA Technical Agent