diff mbox

[Ada] Strict and relaxed secondary stack management

Message ID 20170427092301.GA124335@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 27, 2017, 9:23 a.m. UTC
This patch modifies the management of secondary stack within transient blocks
by allowing "relaxed management" to be the default. In this mode a block will
not manage the secondary stack if there exists an enclosing scope which already
does that. "Strict management" can be enforced by means of switch -gnatd.s. No
need for a test as Q111-032 already performs all necessary checks.

Tested on x86_64-pc-linux-gnu, committed on trunk

2017-04-27  Hristian Kirtchev  <kirtchev@adacore.com>

	* debug.adb Change the documentation of switch -gnatd.s.
	* exp_ch7.adb (Make_Transient_Block): Transient blocks do not need
	to manage the secondary stack when an enclosing scope already
	performs this functionality (aka relaxed management). Switch
	-gnatd.s may be used to force strict management in which case
	the block will manage the secondary stack unconditionally. Add
	a guard to stop the traversal when encountering a package or a
	subprogram scope.
diff mbox

Patch

Index: exp_ch7.adb
===================================================================
--- exp_ch7.adb	(revision 247295)
+++ exp_ch7.adb	(working copy)
@@ -8275,31 +8275,27 @@ 
 
       function Manages_Sec_Stack (Id : Entity_Id) return Boolean is
       begin
-         --  An exception handler with a choice parameter utilizes a dummy
-         --  block to provide a declarative region. Such a block should not be
-         --  considered because it never manifests in the tree and can never
-         --  release the secondary stack.
+         case Ekind (Id) is
 
-         if Ekind (Id) = E_Block
-           and then Uses_Sec_Stack (Id)
-           and then not Is_Exception_Handler (Id)
-         then
-            return True;
+            --  An exception handler with a choice parameter utilizes a dummy
+            --  block to provide a declarative region. Such a block should not
+            --  be considered because it never manifests in the tree and can
+            --  never release the secondary stack.
 
-         --  Loops are intentionally excluded because they undergo special
-         --  treatment, see Establish_Transient_Scope.
+            when E_Block =>
+               return
+                 Uses_Sec_Stack (Id) and then not Is_Exception_Handler (Id);
 
-         elsif Ekind_In (Id, E_Entry,
-                             E_Entry_Family,
-                             E_Function,
-                             E_Procedure)
-           and then Uses_Sec_Stack (Id)
-         then
-            return True;
+            when E_Entry
+               | E_Entry_Family
+               | E_Function
+               | E_Procedure
+            =>
+               return Uses_Sec_Stack (Id);
 
-         else
-            return False;
-         end if;
+            when others =>
+               return False;
+         end case;
       end Manages_Sec_Stack;
 
       --  Local variables
@@ -8326,14 +8322,11 @@ 
 
          Scop := Scope (Trans_Id);
          while Present (Scop) loop
-            if Scop = Standard_Standard then
-               exit;
 
-            --  The transient block must manage the secondary stack when the
-            --  block appears within a loop in order to reclaim the memory at
-            --  each iteration.
+            --  It should not be possible to reach Standard without hitting one
+            --  of the other cases first unless Standard was manually pushed.
 
-            elsif Ekind (Scop) = E_Loop then
+            if Scop = Standard_Standard then
                exit;
 
             --  The transient block is within a function which returns on the
@@ -8351,15 +8344,36 @@ 
                Set_Uses_Sec_Stack (Trans_Id, False);
                exit;
 
-            --  When requested, the transient block does not need to manage the
-            --  secondary stack when there exists an enclosing block, entry,
-            --  entry family, function, or a procedure which already does that.
+            --  The transient block must manage the secondary stack when the
+            --  block appears within a loop in order to reclaim the memory at
+            --  each iteration.
+
+            elsif Ekind (Scop) = E_Loop then
+               exit;
+
+            --  The transient block does not need to manage the secondary stack
+            --  when there is an enclosing construct which already does that.
             --  This optimization saves on SS_Mark and SS_Release calls but may
             --  allow objects to live a little longer than required.
 
-            elsif Debug_Flag_Dot_S and then Manages_Sec_Stack (Scop) then
+            --  The transient block must manage the secondary stack when switch
+            --  -gnatd.s (strict management) is in effect.
+
+            elsif Manages_Sec_Stack (Scop) and then not Debug_Flag_Dot_S then
                Set_Uses_Sec_Stack (Trans_Id, False);
                exit;
+
+            --  Prevent the search from going too far because transient blocks
+            --  are bounded by packages and subprogram scopes.
+
+            elsif Ekind_In (Scop, E_Entry,
+                                  E_Entry_Family,
+                                  E_Function,
+                                  E_Package,
+                                  E_Procedure,
+                                  E_Subprogram_Body)
+            then
+               exit;
             end if;
 
             Scop := Scope (Scop);
Index: debug.adb
===================================================================
--- debug.adb	(revision 247295)
+++ debug.adb	(working copy)
@@ -109,7 +109,7 @@ 
    --  d.p  Use original Ada 95 semantics for Bit_Order (disable AI95-0133)
    --  d.q  Suppress optimizations on imported 'in'
    --  d.r  Enable OK_To_Reorder_Components in non-variant records
-   --  d.s  Minimize secondary stack Mark and Release calls
+   --  d.s  Strict secondary stack management
    --  d.t  Disable static allocation of library level dispatch tables
    --  d.u  Enable Modify_Tree_For_C (update tree for c)
    --  d.v  Enable OK_To_Reorder_Components in variant records
@@ -572,6 +572,11 @@ 
    --  d.r  Forces the flag OK_To_Reorder_Components to be set in all record
    --       base types that have no discriminants.
 
+   --  d.s  The compiler no longer attempts to optimize the calls to secondary
+   --       stack management routines SS_Mark and SS_Release. As a result, each
+   --       transient block tasked with secondary stack management will fulfill
+   --       its role unconditionally.
+
    --  d.s  The compiler does not generate calls to secondary stack management
    --       routines SS_Mark and SS_Release for a transient block when there is
    --       an enclosing scoping construct which already manages the secondary