From patchwork Mon Aug 29 09:57:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 112005 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id E14AFB6F8F for ; Mon, 29 Aug 2011 19:58:29 +1000 (EST) Received: (qmail 1151 invoked by alias); 29 Aug 2011 09:58:27 -0000 Received: (qmail 1108 invoked by uid 22791); 29 Aug 2011 09:58:09 -0000 X-SWARE-Spam-Status: No, hits=-0.4 required=5.0 tests=AWL, BAYES_50, TW_OC, TW_TM, T_FILL_THIS_FORM_SHORT X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 29 Aug 2011 09:57:37 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 23C822BB04F; Mon, 29 Aug 2011 05:57:36 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id EK8h8ckltrlA; Mon, 29 Aug 2011 05:57:36 -0400 (EDT) Received: from kwai.gnat.com (kwai.gnat.com [205.232.38.4]) by rock.gnat.com (Postfix) with ESMTP id E67FA2BB04C; Mon, 29 Aug 2011 05:57:35 -0400 (EDT) Received: by kwai.gnat.com (Postfix, from userid 4192) id DEC3D3FEE8; Mon, 29 Aug 2011 05:57:35 -0400 (EDT) Date: Mon, 29 Aug 2011 05:57:35 -0400 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Hristian Kirtchev Subject: [Ada] Ada2012-A111 specifying a pool on an allocator Message-ID: <20110829095735.GA21908@adacore.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org See detailed changelog for more details on the implementation of this Ada 2012 AI. Tested on x86_64-pc-linux-gnu, committed on trunk 2011-08-29 Hristian Kirtchev * a-fihema.ads, a-fihema.adb: Unit removed. * a-undesu.ads, a-undesu.adb: New unit implementing Ada.Unchecked_Deallocate_Subpool. * einfo.adb: Remove Associated_Collection from the node usage. Add Finalization_Master to the node usage. (Associated_Collection): Removed. (Finalization_Master): New routine. (Set_Associated_Collection): Removed. (Set_Finalization_Master): New routine. (Write_Field23_Name): Remove Associated_Collection from the output. Add Finalization_Master to the output. * einfo.ads: Remove attribute Associated_Collection and its uses in entities. Add new attribute Finalization_Master along with its uses in entitites. (Associated_Collection): Removed along with its pragma import. (Finalization_Master): New routine along with a pragma import. (Set_Associated_Collection): Removed along with its pragma import. (Set_Finalization_Master): New routine along with a pragma import. * exp_ch3.adb (Expand_Freeze_Array_Type): Replace call to Build_Finalization_Collection with Build_Finalization_Master. (Expand_Freeze_Record_Type): Move the generation of Finalize_Address before the bodies of the predefined routines. Add comment explaining this. Replace call to Build_Finalization_Collection with Build_Finalization_Master. (Freeze_Type): Replace call to Build_Finalization_Collection with Build_Finalization_Master. (Make_Finalize_Address_Body): Comment reformatting. (Make_Predefined_Primitive_Specs): Code reformatting. (Stream_Operation_OK): Update comment mentioning finalization collections. Replace RE_Finalization_Collection with RE_Finalization_Master. * exp_ch4.adb (Complete_Controlled_Allocation): Replace call to Associated_Collection with Finalization_Master. Replace call to Build_Finalization_Collection with Build_Finalization_Master. (Expand_Allocator_Expression): Replace call to Associated_Collection with Finalization_Master. Replace call to Set_Associated_Collection with Set_Finalization_Master. Remove the generation of Set_Finalize_Address_Ptr. (Expand_N_Allocator): Replace call to Associated_Collection with Finalization_Master. Remove the generation of Set_Finalize_Address_Ptr. * exp_ch6.adb (Add_Collection_Actual_To_Build_In_Place_Call): Renamed to Add_Finalization_Master_Actual_To_Build_In_Place_Call. Update the comment on usage. Replace call to Needs_BIP_Collection with Needs_BIP_Finalization_Master Remplace BIP_Collection with BIP_Finalization_Master. Update all comments which mention finalization collections. Replace Associated_Collection with Finalization_Master. Replace Build_Finalization_Collection with Build_Finalization_Master. (BIP_Formal_Suffix): Update BIP_Collection's case. (Build_Heap_Allocator): Update the related comment. Rename local variable Collect to Fin_Mas_Id and update its occurrences. Update comments which mention finalization collections. Replace Set_Associated_Collection with Set_Finalization_Master. (Expand_Call): Update the code which detects a special piece of library code for .NET/JVM. (Make_Build_In_Place_Call_In_Allocator): Replace the call to Add_Collection_Actual_To_Build_In_Place_Call with Add_Finalization_Master_Actual_To_Build_In_Place_Call. Remove the code which generates a call to Make_Set_Finalize_Address_Ptr_Call. (Make_Build_In_Place_Call_In_Anonymous_Context): Replace call to Add_Collection_Actual_To_Build_In_Place_Call with Add_Finalization_Master_Actual_To_Build_In_Place_Call. (Make_Build_In_Place_Call_In_Assignment): Replace call to Add_Collection_Actual_To_Build_In_Place_Call with Add_Finalization_Master_Actual_To_Build_In_Place_Call. (Needs_BIP_Collection): Renamed to Needs_BIP_Finalization_Master. * exp_ch6.ads: Rename BIP_Collection to BIP_Finalization_Master. (Needs_BIP_Collection): Renamed to Needs_BIP_Finalization_Master. * exp_ch7.adb (Build_BIP_Cleanup_Stmts): Update comment on usage. Rename local variable Collect to Fin_Mas_Id and update its occurrences. Replace call to Set_Associated_Collection with Set_Finalization_Master. (Build_Finalization_Collection): Renamed to Build_Finalization_Master. Replace the call to Associated_Collection with Finalization_Master. Rename local variable Coll_Id to Fin_Mas_Id and update its occurrences. Update the way finalization master names are generated. Update the retrieval of the correct access type which will carry the pool and master attributes. (Make_Final_Call): Reimplement the way [Deep_]Finalize is retrieved. (Make_Finalize_Address_Body): Abstract types do not need Finalize_Address. Code reformatting. (Make_Finalize_Address_Stmts): Update comment on usage. (Make_Set_Finalize_Address_Ptr_Call): Removed. (Process_Declarations): Update comments. * exp_ch7.ads (Build_Finalization_Collection): Renamed to Build_Finalization_Master. Update associated comment. (Make_Set_Finalize_Address_Ptr_Call): Removed. * exp_ch13.adb: Update comments which mention finalization collections. (Expand_N_Free_Statement): Replace the call to Associated_Collection with Finalization_Master. * exp_util.adb (Build_Allocate_Deallocate_Proc): Reimplemented to create calls to routines Allocate_Any_Controlled and Deallocate_Any_Controlled. (Find_Finalize_Address): New routine. (Is_Allocate_Deallocate_Proc): Update the RTE entities used in the comparison. (Requires_Cleanup_Actions): Update the comment on freeze node inspection. * exp_util.ads: Remove comment on generated code for Build_Allocate_Deallocate_Proc. The code is now quite complex and it is better to simply look in the body. * freeze.adb (Freeze_All): Update the comment of finalization collections. Replace the call to Associated_Collection with Finalization_Master. Replace the call to Build_Finalization_Collection with Build_Finalization_Master. * impunit.adb: Add a-undesu and s-stposu to the list of units. * Makefile.rtl: Add files a-undesu, s-finmas and s-stposu. Remove file a-fihema. * rtsfind.adb (Get_Unit_Name): Remove the processing for children of Ada.Finalization. Add processing for children of System.Storage_Pools. * rtsfind.ads: Remove the naming of second level children of Ada.Finalization. Remove Ada_Finalization_Heap_Management from the list of units. Remove subtype Ada_Finalization_Child. Remove the following subprogram entities: RE_Allocate RE_Deallocate RE_Finalization_Collection RE_Finalization_Collection_Ptr RE_Set_Finalize_Address_Ptr Add the naming of second level children of System.Storage_Pools. Add System_Finalization_Masters and System_Storage_Pools_Subpools to the list of units. Add subtype System_Storage_Pools_Child. Add the following subprogram entities to System.Finalization_Masters: RE_Finalization_Master RE_Finalization_Master_Ptr Add the following subprogram entities to System.Storage_Pools.Subpools: RE_Allocate_Any_Controlled RE_Deallocate_Any_Controlled RE_Root_Storage_Pool_With_Subpools RE_Root_Subpool RE_Subpool_Handle Move the following subprogram entities from Ada.Finalization.Heap_Management to System.Finalization_Masters: RE_Add_Offset_To_Address RE_Attach RE_Base_Pool RE_Detach * sem_ch3.adb (Access_Type_Declaration): Replace the call to Set_Associated_Collection with Set_Finalization_Master. * sem_ch6.adb (Create_Extra_Formals): Update the way extra formal BIP_Finalization_Master is created. * s-finmas.adb: New unit System.Finalization_Masters. * s-finmas.ads: New unit System.Finalization_Masters. * s-stopoo.ads, s-stopoo.adb: Minor code reformatting. * s-stposu.ads, s-stposu.adb: New unit implementing System.Storage_Pools.Subpools. Index: a-fihema.adb =================================================================== --- a-fihema.adb (revision 178181) +++ a-fihema.adb (working copy) @@ -1,568 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- A D A . F I N A L I Z A T I O N . H E A P _ M A N A G E M E N T -- --- -- --- B o d y -- --- -- --- Copyright (C) 2008-2011, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Ada.Exceptions; use Ada.Exceptions; -with Ada.Unchecked_Conversion; - -with System; use System; -with System.Address_Image; -with System.IO; use System.IO; --- ???with System.OS_Lib; --- Breaks ravenscar runtimes -with System.Soft_Links; use System.Soft_Links; -with System.Storage_Elements; use System.Storage_Elements; -with System.Storage_Pools; use System.Storage_Pools; - -package body Ada.Finalization.Heap_Management is - - Debug : constant Boolean := False; - -- True for debugging printouts. - - Header_Size : constant Storage_Count := Node'Size / Storage_Unit; - -- Size of the header in bytes. Added to Storage_Size requested by - -- Allocate/Deallocate to determine the Storage_Size passed to the - -- underlying pool. - - function Address_To_Node_Ptr is - new Ada.Unchecked_Conversion (Address, Node_Ptr); - - procedure Attach (N : Node_Ptr; L : Node_Ptr); - -- Prepend a node to a list - - procedure Detach (N : Node_Ptr); - -- Unhook a node from an arbitrary list - - procedure Fin_Assert (Condition : Boolean; Message : String); - -- Asserts that the condition is True. Used instead of pragma Assert in - -- delicate places where raising an exception would cause re-invocation of - -- finalization. Instead of raising an exception, aborts the whole process. - - function Is_Empty (Objects : Node_Ptr) return Boolean; - -- True if the Objects list is empty - - ---------------- - -- Fin_Assert -- - ---------------- - - procedure Fin_Assert (Condition : Boolean; Message : String) is - - procedure Fail; - -- Use a separate procedure to make it easy to set a breakpoint here. - - ---------- - -- Fail -- - ---------- - - procedure Fail is - begin - Put_Line ("Heap_Management: Fin_Assert failed: " & Message); - -- ???OS_Lib.OS_Abort; - -- Breaks ravenscar runtimes - end Fail; - - -- Start of processing for Fin_Assert - - begin - if not Condition then - Fail; - end if; - end Fin_Assert; - - --------------------------- - -- Add_Offset_To_Address -- - --------------------------- - - function Add_Offset_To_Address - (Addr : System.Address; - Offset : System.Storage_Elements.Storage_Offset) return System.Address - is - begin - return System.Storage_Elements."+" (Addr, Offset); - end Add_Offset_To_Address; - - -------------- - -- Allocate -- - -------------- - - procedure Allocate - (Collection : in out Finalization_Collection; - Addr : out System.Address; - Storage_Size : System.Storage_Elements.Storage_Count; - Alignment : System.Storage_Elements.Storage_Count; - Needs_Header : Boolean := True) - is - begin - -- Allocation of an object with controlled parts - - if Needs_Header then - - -- Do not allow the allocation of controlled objects while the - -- associated collection is being finalized. - - if Collection.Finalization_Started then - raise Program_Error with "allocation after finalization started"; - end if; - - declare - Header_Offset : Storage_Offset; - N_Addr : Address; - N_Ptr : Node_Ptr; - - begin - -- Offset from the header to the actual object. The header is - -- just in front of the object. There may be padding space before - -- the header. - - if Alignment > Header_Size then - Header_Offset := Alignment; - else - Header_Offset := Header_Size; - end if; - - -- Use the underlying pool to allocate enough space for the object - -- and the list header. The returned address points to the list - -- header. If locking is necessary, it will be done by the - -- underlying pool. - - Allocate - (Collection.Base_Pool.all, - N_Addr, - Storage_Size + Header_Offset, - Alignment); - - -- Map the allocated memory into a Node record. This converts the - -- top of the allocated bits into a list header. - - N_Ptr := Address_To_Node_Ptr - (N_Addr + Header_Offset - Header_Size); - Attach (N_Ptr, Collection.Objects'Unchecked_Access); - - -- Move the address from Prev to the start of the object. This - -- operation effectively hides the list header. - - Addr := N_Addr + Header_Offset; - end; - - -- Allocation of a non-controlled object - - else - Allocate - (Collection.Base_Pool.all, - Addr, - Storage_Size, - Alignment); - end if; - - pragma Assert (Addr mod Alignment = 0); - end Allocate; - - ------------ - -- Attach -- - ------------ - - procedure Attach (N : Node_Ptr; L : Node_Ptr) is - begin - Lock_Task.all; - - L.Next.Prev := N; - N.Next := L.Next; - L.Next := N; - N.Prev := L; - - Unlock_Task.all; - - -- Note: no need to unlock in case of exceptions; the above code cannot - -- raise any. - - end Attach; - - --------------- - -- Base_Pool -- - --------------- - - function Base_Pool - (Collection : Finalization_Collection) return Any_Storage_Pool_Ptr - is - begin - return Collection.Base_Pool; - end Base_Pool; - - ---------------- - -- Deallocate -- - ---------------- - - procedure Deallocate - (Collection : in out Finalization_Collection; - Addr : System.Address; - Storage_Size : System.Storage_Elements.Storage_Count; - Alignment : System.Storage_Elements.Storage_Count; - Has_Header : Boolean := True) - is - pragma Assert (Addr mod Alignment = 0); - begin - -- Deallocation of an object with controlled parts - - if Has_Header then - declare - Header_Offset : Storage_Offset; - N_Addr : Address; - N_Ptr : Node_Ptr; - - begin - -- Offset from the header to the actual object. - - if Alignment > Header_Size then - Header_Offset := Alignment; - else - Header_Offset := Header_Size; - end if; - - -- Converts from the object to the list header - - N_Ptr := Address_To_Node_Ptr (Addr - Header_Size); - Detach (N_Ptr); - - -- Converts the bits preceding the object the block address. - - N_Addr := Addr - Header_Offset; - - -- Use the underlying pool to destroy the object along with the - -- list header. - - Deallocate - (Collection.Base_Pool.all, - N_Addr, - Storage_Size + Header_Size, - Alignment); - end; - - -- Deallocation of a non-controlled object - - else - Deallocate - (Collection.Base_Pool.all, - Addr, - Storage_Size, - Alignment); - end if; - end Deallocate; - - ------------ - -- Detach -- - ------------ - - procedure Detach (N : Node_Ptr) is - begin - pragma Debug (Fin_Assert (N /= null, "Detach null")); - - Lock_Task.all; - - if N.Next = null then - pragma Assert (N.Prev = null); - - else - N.Prev.Next := N.Next; - N.Next.Prev := N.Prev; - N.Next := null; - N.Prev := null; - end if; - - Unlock_Task.all; - - -- Note: no need to unlock in case of exceptions; the above code cannot - -- raise any. - - end Detach; - - -------------- - -- Finalize -- - -------------- - - overriding procedure Finalize - (Collection : in out Finalization_Collection) - is - Ex_Occur : Exception_Occurrence; - Raised : Boolean := False; - - begin - if Debug then - Put_Line ("-->Heap_Management: "); - pcol (Collection); - end if; - - -- Set Finalization_Started to prevent any allocations of objects with - -- controlled parts during finalization. The associated access type is - -- about to go out of scope; Finalization_Started is never again - -- modified. - - if Collection.Finalization_Started then - - -- ???Needed for shared libraries - - return; - end if; - - pragma Debug (Fin_Assert (not Collection.Finalization_Started, - "Finalize: already started")); - Collection.Finalization_Started := True; - - -- For each object in the Objects list, detach it, and finalize it. Note - -- that other tasks can be doing Unchecked_Deallocations at the same - -- time, so we need to beware of race conditions. - - while not Is_Empty (Collection.Objects'Unchecked_Access) loop - - declare - Node : constant Node_Ptr := Collection.Objects.Next; - begin - -- Remove the current node from the list first, in case some other - -- task is simultaneously doing Unchecked_Deallocation on this - -- object. Detach does Lock_Task. Note that we can't Lock_Task - -- during Finalize_Address, because finalization can do pretty - -- much anything. - - Detach (Node); - - -- ??? Kludge: Don't do anything until the proper place to set - -- primitive Finalize_Address has been determined. - - if Collection.Finalize_Address /= null then - declare - Object_Address : constant Address := - Node.all'Address + Header_Size; - -- Get address of object from address of header - - begin - Collection.Finalize_Address (Object_Address); - exception - when Fin_Except : others => - if not Raised then - Raised := True; - Save_Occurrence (Ex_Occur, Fin_Except); - end if; - end; - end if; - end; - end loop; - - if Debug then - Put_Line ("<--Heap_Management: "); - pcol (Collection); - end if; - - -- If the finalization of a particular node raised an exception, reraise - -- it after the remainder of the list has been finalized. - - if Raised then - if Debug then - Put_Line ("Heap_Management: reraised"); - end if; - - Reraise_Occurrence (Ex_Occur); - end if; - end Finalize; - - ---------------- - -- Initialize -- - ---------------- - - overriding procedure Initialize - (Collection : in out Finalization_Collection) - is - begin - -- The dummy head must point to itself in both directions - - Collection.Objects.Next := Collection.Objects'Unchecked_Access; - Collection.Objects.Prev := Collection.Objects'Unchecked_Access; - pragma Assert (Is_Empty (Collection.Objects'Unchecked_Access)); - end Initialize; - - -------------- - -- Is_Empty -- - -------------- - - function Is_Empty (Objects : Node_Ptr) return Boolean is - begin - pragma Debug - (Fin_Assert ((Objects.Next = Objects) = (Objects.Prev = Objects), - "Is_Empty")); - return Objects.Next = Objects; - end Is_Empty; - - ---------- - -- pcol -- - ---------- - - procedure pcol (Collection : Finalization_Collection) is - Head : constant Node_Ptr := Collection.Objects'Unrestricted_Access; - -- "Unrestricted", because we are getting access-to-variable of a - -- constant! Normally worrisome, this is OK for debugging code. - - Head_Seen : Boolean := False; - N_Ptr : Node_Ptr; - - begin - -- Output the basic contents of the collection - - -- Collection: 0x123456789 - -- Base_Pool : null 0x123456789 - -- Fin_Addr : null 0x123456789 - -- Fin_Start : TRUE FALSE - - Put ("Collection: "); - Put_Line (Address_Image (Collection'Address)); - - Put ("Base_Pool : "); - - if Collection.Base_Pool = null then - Put_Line (" null"); - else - Put_Line (Address_Image (Collection.Base_Pool'Address)); - end if; - - Put ("Fin_Addr : "); - - if Collection.Finalize_Address = null then - Put_Line ("null"); - else - Put_Line (Address_Image (Collection.Finalize_Address'Address)); - end if; - - Put ("Fin_Start : "); - Put_Line (Collection.Finalization_Started'Img); - - -- Output all chained elements. The format is the following: - - -- ^ ? null - -- |Header: 0x123456789 (dummy head) - -- | Prev: 0x123456789 - -- | Next: 0x123456789 - -- V - - -- ^ - the current element points back to the correct element - -- ? - the current element points back to an erroneous element - -- n - the current element points back to null - - -- Header - the address of the list header - -- Prev - the address of the list header which the current element - -- - points back to - -- Next - the address of the list header which the current element - -- - points to - -- (dummy head) - present if dummy head - - N_Ptr := Head; - while N_Ptr /= null loop -- Should never be null; we being defensive - Put_Line ("V"); - - -- We see the head initially; we want to exit when we see the head a - -- SECOND time. - - if N_Ptr = Head then - exit when Head_Seen; - - Head_Seen := True; - end if; - - -- The current element is null. This should never happen since the - -- list is circular. - - if N_Ptr.Prev = null then - Put_Line ("null (ERROR)"); - - -- The current element points back to the correct element - - elsif N_Ptr.Prev.Next = N_Ptr then - Put_Line ("^"); - - -- The current element points to an erroneous element - - else - Put_Line ("? (ERROR)"); - end if; - - -- Output the header and fields - - Put ("|Header: "); - Put (Address_Image (N_Ptr.all'Address)); - - -- Detect the dummy head - - if N_Ptr = Head then - Put_Line (" (dummy head)"); - else - Put_Line (""); - end if; - - Put ("| Prev: "); - - if N_Ptr.Prev = null then - Put_Line ("null"); - else - Put_Line (Address_Image (N_Ptr.Prev.all'Address)); - end if; - - Put ("| Next: "); - - if N_Ptr.Next = null then - Put_Line ("null"); - else - Put_Line (Address_Image (N_Ptr.Next.all'Address)); - end if; - - N_Ptr := N_Ptr.Next; - end loop; - end pcol; - - ------------------------------ - -- Set_Finalize_Address_Ptr -- - ------------------------------ - - procedure Set_Finalize_Address_Ptr - (Collection : in out Finalization_Collection; - Proc_Ptr : Finalize_Address_Ptr) - is - begin - Collection.Finalize_Address := Proc_Ptr; - end Set_Finalize_Address_Ptr; - - -------------------------- - -- Set_Storage_Pool_Ptr -- - -------------------------- - - procedure Set_Storage_Pool_Ptr - (Collection : in out Finalization_Collection; - Pool_Ptr : Any_Storage_Pool_Ptr) - is - begin - Collection.Base_Pool := Pool_Ptr; - end Set_Storage_Pool_Ptr; - -end Ada.Finalization.Heap_Management; Index: a-fihema.ads =================================================================== --- a-fihema.ads (revision 178181) +++ a-fihema.ads (working copy) @@ -1,161 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- A D A . F I N A L I Z A T I O N . H E A P _ M A N A G E M E N T -- --- -- --- S p e c -- --- -- --- Copyright (C) 2008-2011, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with System; -with System.Storage_Elements; -with System.Storage_Pools; - -package Ada.Finalization.Heap_Management is - - -- A reference to any derivation of Root_Storage_Pool. Since this type may - -- not be used to allocate objects, its storage size is zero. - - type Any_Storage_Pool_Ptr is - access System.Storage_Pools.Root_Storage_Pool'Class; - for Any_Storage_Pool_Ptr'Storage_Size use 0; - - -- ??? Comment needed on overall mechanism - - type Finalization_Collection is - new Ada.Finalization.Limited_Controlled with private; - - type Finalization_Collection_Ptr is access all Finalization_Collection; - for Finalization_Collection_Ptr'Storage_Size use 0; - - -- A reference used to describe primitive Finalize_Address - - type Finalize_Address_Ptr is access procedure (Obj : System.Address); - - -- Since RTSfind cannot contain names of the form RE_"+", the following - -- routine serves as a wrapper around System.Storage_Elements."+". - - function Add_Offset_To_Address - (Addr : System.Address; - Offset : System.Storage_Elements.Storage_Offset) return System.Address; - - procedure Allocate - (Collection : in out Finalization_Collection; - Addr : out System.Address; - Storage_Size : System.Storage_Elements.Storage_Count; - Alignment : System.Storage_Elements.Storage_Count; - Needs_Header : Boolean := True); - -- Allocate a chunk of memory described by Storage_Size and Alignment on - -- Collection's underlying storage pool. Return the address of the chunk. - -- The routine creates a list header which precedes the chunk of memory if - -- Needs_Header is True. If allocated, the header is attached to the - -- Collection's objects. The interface to this routine is provided by - -- Build_Allocate_Deallocate_Proc. - - function Base_Pool - (Collection : Finalization_Collection) return Any_Storage_Pool_Ptr; - -- Return a reference to the underlying storage pool of Collection - - procedure Deallocate - (Collection : in out Finalization_Collection; - Addr : System.Address; - Storage_Size : System.Storage_Elements.Storage_Count; - Alignment : System.Storage_Elements.Storage_Count; - Has_Header : Boolean := True); - -- Deallocate a chunk of memory described by Storage_Size and Alignment - -- from Collection's underlying storage pool. The beginning of the memory - -- chunk is designated by Addr. The routine detaches and destroys the - -- preceding list header if flag Has_Header is set. The interface to this - -- routine is provided by Build_Allocate_Deallocate_Proc. - - overriding procedure Finalize - (Collection : in out Finalization_Collection); - -- Traverse objects of Collection, invoking Finalize_Address on each one - - overriding procedure Initialize - (Collection : in out Finalization_Collection); - -- Initialize the finalization list to empty - - procedure Set_Finalize_Address_Ptr - (Collection : in out Finalization_Collection; - Proc_Ptr : Finalize_Address_Ptr); - -- Set the finalization address routine of a finalization collection - - procedure Set_Storage_Pool_Ptr - (Collection : in out Finalization_Collection; - Pool_Ptr : Any_Storage_Pool_Ptr); - -- Set the underlying storage pool of a finalization collection - -private - -- Homogeneous collection types - - type Node; - type Node_Ptr is access all Node; - pragma No_Strict_Aliasing (Node_Ptr); - - -- The following record type should really be limited, but we can see the - -- full view of Limited_Controlled, which is NOT limited. Note that default - -- initialization does not happen for this type (the pointers will not be - -- automatically set to null), because of the games we're playing with - -- address arithmetic. Code in the body assumes that the size of - -- this record is a power of 2 to deal with alignment. - - type Node is record - Prev : Node_Ptr; - Next : Node_Ptr; - end record; - - type Finalization_Collection is - new Ada.Finalization.Limited_Controlled with - record - Base_Pool : Any_Storage_Pool_Ptr; - -- All objects and node headers are allocated on this underlying pool; - -- the collection is simply a wrapper around it. - - Objects : aliased Node; - -- The head of a doubly linked list containing all allocated objects - -- with controlled parts that still exist (Unchecked_Deallocation has - -- not been done on them). - - Finalize_Address : Finalize_Address_Ptr; - -- A reference to a routine that finalizes an object denoted by its - -- address. The collection must be homogeneous since the same routine - -- will be invoked for every allocated object when the pool is - -- finalized. - - Finalization_Started : Boolean := False; - pragma Atomic (Finalization_Started); - -- When the finalization of a collection takes place, any allocations of - -- objects with controlled or protected parts on the same collection are - -- prohibited and the action must raise Program_Error. This needs to be - -- atomic, because it is accessed without Lock_Task/Unlock_Task. See - -- RM-4.8(10.2/2). - end record; - - procedure pcol (Collection : Finalization_Collection); - -- Output the contents of a collection in a readable form. Intended for - -- debugging purposes. - -end Ada.Finalization.Heap_Management; Index: sem_ch3.adb =================================================================== --- sem_ch3.adb (revision 178161) +++ sem_ch3.adb (working copy) @@ -1353,7 +1353,7 @@ Set_Has_Task (T, False); Set_Has_Controlled_Component (T, False); - -- Initialize Associated_Collection explicitly to Empty, to avoid + -- Initialize field Finalization_Master explicitly to Empty, to avoid -- problems where an incomplete view of this entity has been previously -- established by a limited with and an overlaid version of this field -- (Stored_Constraint) was initialized for the incomplete view. @@ -1361,10 +1361,10 @@ -- This reset is performed in most cases except where the access type -- has been created for the purposes of allocating or deallocating a -- build-in-place object. Such access types have explicitly set pools - -- and collections. + -- and finalization masters. if No (Associated_Storage_Pool (T)) then - Set_Associated_Collection (T, Empty); + Set_Finalization_Master (T, Empty); end if; -- Ada 2005 (AI-231): Propagate the null-excluding and access-constant Index: impunit.adb =================================================================== --- impunit.adb (revision 178155) +++ impunit.adb (working copy) @@ -111,6 +111,7 @@ "a-titest", -- Ada.Text_IO.Text_Streams "a-unccon", -- Ada.Unchecked_Conversion "a-uncdea", -- Ada.Unchecked_Deallocation + "a-undesu", -- Ada.Unchecked_Deallocate_Subpool "a-witeio", -- Ada.Wide_Text_IO "a-wtcoio", -- Ada.Wide_Text_IO.Complex_IO "a-wtedit", -- Ada.Wide_Text_IO.Editing @@ -339,6 +340,7 @@ "s-rpc ", -- System.Rpc "s-stoele", -- System.Storage_Elements "s-stopoo", -- System.Storage_Pools + "s-stposu", -- System.Storage_Pools.Subpools -------------------------------------- -- GNAT Defined Additions to System -- Index: exp_ch7.adb =================================================================== --- exp_ch7.adb (revision 178155) +++ exp_ch7.adb (working copy) @@ -431,8 +431,8 @@ -- whether the inner logic should be dictated by state counters. function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id; - -- Subsidiary to Make_Finalize_Address_Body and Make_Deep_Array_Body. - -- Generate the following statements: + -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and + -- Make_Deep_Record_Body. Generate the following statements: -- -- declare -- type Acc_Typ is access all Typ; @@ -797,11 +797,11 @@ Parameter_Associations => Actuals))))); end Build_Exception_Handler; - ----------------------------------- - -- Build_Finalization_Collection -- - ----------------------------------- + ------------------------------- + -- Build_Finalization_Master -- + ------------------------------- - procedure Build_Finalization_Collection + procedure Build_Finalization_Master (Typ : Entity_Id; Ins_Node : Node_Id := Empty; Encl_Scope : Entity_Id := Empty) @@ -837,7 +837,7 @@ return False; end In_Deallocation_Instance; - -- Start of processing for Build_Finalization_Collection + -- Start of processing for Build_Finalization_Master begin -- Certain run-time configurations and targets do not provide support @@ -847,16 +847,13 @@ return; -- Various machinery such as freezing may have already created a - -- collection. + -- finalization master. - elsif Present (Associated_Collection (Typ)) then + elsif Present (Finalization_Master (Typ)) then return; -- Do not process types that return on the secondary stack - -- ??? The need for a secondary stack should be revisited and perhaps - -- changed. - elsif Present (Associated_Storage_Pool (Typ)) and then Is_RTE (Associated_Storage_Pool (Typ), RE_SS_Pool) then @@ -875,7 +872,7 @@ return; -- Ignore the general use of anonymous access types unless the context - -- requires a collection. + -- requires a finalization master. elsif Ekind (Typ) = E_Anonymous_Access_Type and then No (Ins_Node) @@ -883,7 +880,7 @@ return; -- Do not process non-library access types when restriction No_Nested_ - -- Finalization is in effect since collections are controlled objects. + -- Finalization is in effect since masters are controlled objects. elsif Restriction_Active (No_Nested_Finalization) and then not Is_Library_Level_Entity (Typ) @@ -901,87 +898,85 @@ end if; declare - Loc : constant Source_Ptr := Sloc (Typ); - Actions : constant List_Id := New_List; - Coll_Id : Entity_Id; - Pool_Id : Entity_Id; + Loc : constant Source_Ptr := Sloc (Typ); + Actions : constant List_Id := New_List; + Fin_Mas_Id : Entity_Id; + Pool_Id : Entity_Id; + Ptr_Typ : Entity_Id := Typ; begin + -- Access subtypes must use the storage pool of their base type + + if Ekind (Ptr_Typ) = E_Access_Subtype then + Ptr_Typ := Base_Type (Ptr_Typ); + end if; + -- Generate: - -- Fnn : Finalization_Collection; + -- Fnn : aliased Finalization_Master; - -- Source access types use fixed names for their collections since - -- the collection is inserted only once in the same source unit and - -- there is no possible name overlap. Internally-generated access - -- types on the other hand use temporaries as collection names due - -- to possible name collisions. + -- Source access types use fixed master names since the master is + -- inserted in the same source unit only once. The only exception to + -- this are instances using the same access type as generic actual. - if Comes_From_Source (Typ) then - Coll_Id := + if Comes_From_Source (Ptr_Typ) + and then not Inside_A_Generic + then + Fin_Mas_Id := Make_Defining_Identifier (Loc, - Chars => New_External_Name (Chars (Typ), "FC")); + Chars => New_External_Name (Chars (Ptr_Typ), "FM")); + + -- Internally generated access types use temporaries as their names + -- due to possible collision with identical names coming from other + -- packages. + else - Coll_Id := Make_Temporary (Loc, 'F'); + Fin_Mas_Id := Make_Temporary (Loc, 'F'); end if; Append_To (Actions, Make_Object_Declaration (Loc, - Defining_Identifier => Coll_Id, + Defining_Identifier => Fin_Mas_Id, + Aliased_Present => True, Object_Definition => - New_Reference_To (RTE (RE_Finalization_Collection), Loc))); + New_Reference_To (RTE (RE_Finalization_Master), Loc))); -- Storage pool selection and attribute decoration of the generated - -- collection. Since .NET/JVM compilers do not support pools, this - -- step is skipped. + -- master. Since .NET/JVM compilers do not support pools, this step + -- is skipped. if VM_Target = No_VM then -- If the access type has a user-defined pool, use it as the base -- storage medium for the finalization pool. - if Present (Associated_Storage_Pool (Typ)) then - Pool_Id := Associated_Storage_Pool (Typ); + if Present (Associated_Storage_Pool (Ptr_Typ)) then + Pool_Id := Associated_Storage_Pool (Ptr_Typ); - -- Access subtypes must use the storage pool of their base type - - elsif Ekind (Typ) = E_Access_Subtype then - declare - Base_Typ : constant Entity_Id := Base_Type (Typ); - - begin - if No (Associated_Storage_Pool (Base_Typ)) then - Pool_Id := Get_Global_Pool_For_Access_Type (Base_Typ); - Set_Associated_Storage_Pool (Base_Typ, Pool_Id); - else - Pool_Id := Associated_Storage_Pool (Base_Typ); - end if; - end; - -- The default choice is the global pool else - Pool_Id := Get_Global_Pool_For_Access_Type (Typ); - Set_Associated_Storage_Pool (Typ, Pool_Id); + Pool_Id := Get_Global_Pool_For_Access_Type (Ptr_Typ); + Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id); end if; -- Generate: - -- Set_Storage_Pool_Ptr (Fnn, Pool_Id'Unchecked_Access); + -- Set_Base_Pool (Fnn, Pool_Id'Unchecked_Access); Append_To (Actions, Make_Procedure_Call_Statement (Loc, Name => - New_Reference_To (RTE (RE_Set_Storage_Pool_Ptr), Loc), + New_Reference_To (RTE (RE_Set_Base_Pool), Loc), Parameter_Associations => New_List ( - New_Reference_To (Coll_Id, Loc), + New_Reference_To (Fin_Mas_Id, Loc), Make_Attribute_Reference (Loc, Prefix => New_Reference_To (Pool_Id, Loc), Attribute_Name => Name_Unrestricted_Access)))); end if; - Set_Associated_Collection (Typ, Coll_Id); + Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id); - -- A finalization collection created for an anonymous access type - -- must be inserted before a context-dependent node. + -- A finalization master created for an anonymous access type must be + -- inserted before a context-dependent node. if Present (Ins_Node) then Push_Scope (Encl_Scope); @@ -1024,12 +1019,12 @@ Append_Freeze_Actions (Typ, Actions); -- If there's a pool created locally for the access type, then we - -- need to ensure that the collection gets created after the pool - -- object, because otherwise we can have a forward reference, so - -- we force the collection actions to be inserted and analyzed after - -- the pool entity. Note that both the access type and its designated - -- type may have already been frozen and had their freezing actions - -- analyzed at this point. (This seems a little unclean.???) + -- need to ensure that the master gets created after the pool object, + -- because otherwise we can have a forward reference, so we force the + -- master actions to be inserted and analyzed after the pool entity. + -- Note that both the access type and its designated type may have + -- already been frozen and had their freezing actions analyzed at + -- this point. (This seems a little unclean.???) elsif VM_Target = No_VM and then Scope (Pool_Id) = Scope (Typ) @@ -1040,7 +1035,7 @@ Insert_Actions (Parent (Typ), Actions); end if; end; - end Build_Finalization_Collection; + end Build_Finalization_Master; --------------------- -- Build_Finalizer -- @@ -1933,15 +1928,15 @@ end if; -- Inspect the freeze node of an access-to-controlled type and - -- look for a delayed finalization collection. This case arises - -- when the freeze actions are inserted at a later time than the + -- look for a delayed finalization master. This case arises when + -- the freeze actions are inserted at a later time than the -- expansion of the context. Since Build_Finalizer is never called - -- on a single construct twice, the collection will be ultimately + -- on a single construct twice, the master will be ultimately -- left out and never finalized. This is also needed for freeze -- actions of designated types themselves, since in some cases the - -- finalization collection is associated with a designated type's + -- finalization master is associated with a designated type's -- freeze node rather than that of the access type (see handling - -- for freeze actions in Build_Finalization_Collection). + -- for freeze actions in Build_Finalization_Master). elsif Nkind (Decl) = N_Freeze_Entity and then Present (Actions (Decl)) @@ -1958,12 +1953,12 @@ -- Freeze nodes are considered to be identical to packages -- and blocks in terms of nesting. The difference is that - -- a finalization collection created inside the freeze node - -- is at the same nesting level as the node itself. + -- a finalization master created inside the freeze node is + -- at the same nesting level as the node itself. Process_Declarations (Actions (Decl), Preprocess); - -- The freeze node contains a finalization collection + -- The freeze node contains a finalization master if Preprocess and then Top_Level @@ -2086,11 +2081,12 @@ -- following cleanup code: -- -- if BIPallocfrom > Secondary_Stack'Pos - -- and then BIPcollection /= null + -- and then BIPfinalizationmaster /= null -- then -- declare -- type Ptr_Typ is access Obj_Typ; - -- for Ptr_Typ'Storage_Pool use Base_Pool (BIPcollection); + -- for Ptr_Typ'Storage_Pool + -- use Base_Pool (BIPfinalizationmaster); -- -- begin -- Free (Ptr_Typ (Temp)); @@ -2118,12 +2114,13 @@ function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id is - Collect : constant Entity_Id := - Build_In_Place_Formal (Func_Id, BIP_Collection); - Decls : constant List_Id := New_List; - Obj_Typ : constant Entity_Id := Etype (Func_Id); - Temp_Id : constant Entity_Id := - Entity (Prefix (Name (Parent (Obj_Id)))); + Decls : constant List_Id := New_List; + Fin_Mas_Id : constant Entity_Id := + Build_In_Place_Formal + (Func_Id, BIP_Finalization_Master); + Obj_Typ : constant Entity_Id := Etype (Func_Id); + Temp_Id : constant Entity_Id := + Entity (Prefix (Name (Parent (Obj_Id)))); Cond : Node_Id; Free_Blk : Node_Id; @@ -2133,7 +2130,7 @@ begin -- Generate: - -- Pool_Id renames Base_Pool (BIPcollection.all).all; + -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all; Pool_Id := Make_Temporary (Loc, 'P'); @@ -2150,10 +2147,10 @@ New_Reference_To (RTE (RE_Base_Pool), Loc), Parameter_Associations => New_List ( Make_Explicit_Dereference (Loc, - Prefix => New_Reference_To (Collect, Loc))))))); + Prefix => New_Reference_To (Fin_Mas_Id, Loc))))))); -- Create an access type which uses the storage pool of the - -- caller's collection. + -- caller's finalization master. -- Generate: -- type Ptr_Typ is access Obj_Typ; @@ -2167,11 +2164,11 @@ Make_Access_To_Object_Definition (Loc, Subtype_Indication => New_Reference_To (Obj_Typ, Loc)))); - -- Perform minor decoration in order to set the collection and the + -- Perform minor decoration in order to set the master and the -- storage pool attributes. Set_Ekind (Ptr_Typ, E_Access_Type); - Set_Associated_Collection (Ptr_Typ, Collect); + Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id); Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id); -- Create an explicit free statement. Note that the free uses the @@ -2203,18 +2200,18 @@ Statements => New_List (Free_Stmt))); -- Generate: - -- if BIPcollection /= null then + -- if BIPfinalizationmaster /= null then Cond := Make_Op_Ne (Loc, - Left_Opnd => New_Reference_To (Collect, Loc), + Left_Opnd => New_Reference_To (Fin_Mas_Id, Loc), Right_Opnd => Make_Null (Loc)); -- For constrained or tagged results escalate the condition to -- include the allocation format. Generate: -- -- if BIPallocform > Secondary_Stack'Pos - -- and then BIPcollection /= null + -- and then BIPfinalizationmaster /= null -- then if not Is_Constrained (Obj_Typ) @@ -2590,11 +2587,13 @@ -- If we are dealing with a return object of a build-in-place -- function, generate the following cleanup statements: -- - -- if BIPallocfrom > Secondary_Stack'Pos then + -- if BIPallocfrom > Secondary_Stack'Pos + -- and then BIPfinalizationmaster /= null + -- then -- declare -- type Ptr_Typ is access Obj_Typ; -- for Ptr_Typ'Storage_Pool use - -- Base_Pool (BIPcollection.all).all; + -- Base_Pool (BIPfinalizationmaster.all).all; -- -- begin -- Free (Ptr_Typ (Temp)); @@ -2602,17 +2601,15 @@ -- end if; -- -- The generated code effectively detaches the temporary from the - -- caller finalization chain and deallocates the object. This is + -- caller finalization master and deallocates the object. This is -- disabled on .NET/JVM because pools are not supported. - -- H505-021 This needs to be revisited on .NET/JVM - if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then declare Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id); begin if Is_Build_In_Place_Function (Func_Id) - and then Needs_BIP_Collection (Func_Id) + and then Needs_BIP_Finalization_Master (Func_Id) then Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id)); end if; @@ -4632,7 +4629,7 @@ Name => New_Reference_To (RTE (RE_Attach), Loc), Parameter_Associations => New_List ( - New_Reference_To (Associated_Collection (Ptr_Typ), Loc), + New_Reference_To (Finalization_Master (Ptr_Typ), Loc), Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref))); end Make_Attach_Call; @@ -6849,17 +6846,16 @@ Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize); end if; - -- For types that are both controlled and have controlled components, - -- generate a call to Deep_Finalize. + -- Derivations from [Limited_]Controlled - elsif Is_Controlled (Utyp) - and then Has_Controlled_Component (Utyp) - then - Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize); + elsif Is_Controlled (Utyp) then + if Has_Controlled_Component (Utyp) then + Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize); + else + Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case)); + end if; - -- For types that are not controlled themselves, but contain controlled - -- components or can be extended by types with controlled components, - -- create a call to Deep_Finalize. + -- Class-wide types, interfaces and types with controlled components elsif Is_Class_Wide_Type (Typ) or else Is_Interface (Typ) @@ -6871,11 +6867,13 @@ Fin_Id := TSS (Utyp, TSS_Deep_Finalize); end if; - -- For types that are derived from Controlled and do not have controlled - -- components, build a call to Finalize. + -- Tagged types + elsif Is_Tagged_Type (Utyp) then + Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize); + else - Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case)); + raise Program_Error; end if; if Present (Fin_Id) then @@ -6927,6 +6925,9 @@ -------------------------------- procedure Make_Finalize_Address_Body (Typ : Entity_Id) is + Loc : constant Source_Ptr := Sloc (Typ); + Proc_Id : Entity_Id; + begin -- Nothing to do if the type is not controlled or it already has a -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not @@ -6934,6 +6935,7 @@ -- do not need the Finalize_Address primitive. if not Needs_Finalization (Typ) + or else Is_Abstract_Type (Typ) or else Present (TSS (Typ, TSS_Finalize_Address)) or else (Is_Class_Wide_Type (Typ) @@ -6943,48 +6945,42 @@ return; end if; - declare - Loc : constant Source_Ptr := Sloc (Typ); - Proc_Id : Entity_Id; + Proc_Id := + Make_Defining_Identifier (Loc, + Make_TSS_Name (Typ, TSS_Finalize_Address)); - begin - Proc_Id := - Make_Defining_Identifier (Loc, - Make_TSS_Name (Typ, TSS_Finalize_Address)); + -- Generate: + -- procedure FD (V : System.Address) is + -- begin + -- declare + -- type Pnn is access all Typ; + -- for Pnn'Storage_Size use 0; + -- begin + -- [Deep_]Finalize (Pnn (V).all); + -- end; + -- end TypFD; - -- Generate: - -- procedure TypFD (V : System.Address) is - -- begin - -- declare - -- type Pnn is access all Typ; - -- for Pnn'Storage_Size use 0; - -- begin - -- [Deep_]Finalize (Pnn (V).all); - -- end; - -- end TypFD; + Discard_Node ( + Make_Subprogram_Body (Loc, + Specification => + Make_Procedure_Specification (Loc, + Defining_Unit_Name => Proc_Id, - Discard_Node ( - Make_Subprogram_Body (Loc, - Specification => - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Proc_Id, + Parameter_Specifications => New_List ( + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_V), + Parameter_Type => + New_Reference_To (RTE (RE_Address), Loc)))), - Parameter_Specifications => New_List ( - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_V), - Parameter_Type => - New_Reference_To (RTE (RE_Address), Loc)))), + Declarations => No_List, - Declarations => No_List, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => + Make_Finalize_Address_Stmts (Typ)))); - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => - Make_Finalize_Address_Stmts (Typ)))); - - Set_TSS (Typ, Proc_Id); - end; + Set_TSS (Typ, Proc_Id); end Make_Finalize_Address_Body; --------------------------------- @@ -7415,86 +7411,6 @@ Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True))); end Make_Local_Deep_Finalize; - ---------------------------------------- - -- Make_Set_Finalize_Address_Ptr_Call -- - ---------------------------------------- - - function Make_Set_Finalize_Address_Ptr_Call - (Loc : Source_Ptr; - Typ : Entity_Id; - Ptr_Typ : Entity_Id) return Node_Id - is - Desig_Typ : constant Entity_Id := - Available_View (Designated_Type (Ptr_Typ)); - Utyp : Entity_Id; - - begin - -- If the context is a class-wide allocator, we use the class-wide type - -- to obtain the proper Finalize_Address routine. - - if Is_Class_Wide_Type (Desig_Typ) then - Utyp := Desig_Typ; - - else - Utyp := Typ; - - if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then - Utyp := Full_View (Utyp); - end if; - - if Is_Concurrent_Type (Utyp) then - Utyp := Corresponding_Record_Type (Utyp); - end if; - end if; - - Utyp := Underlying_Type (Base_Type (Utyp)); - - -- Deal with non-tagged derivation of private views. If the parent is - -- now known to be protected, the finalization routine is the one - -- defined on the corresponding record of the ancestor (corresponding - -- records do not automatically inherit operations, but maybe they - -- should???) - - if Is_Untagged_Derivation (Typ) then - if Is_Protected_Type (Typ) then - Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ))); - else - Utyp := Underlying_Type (Root_Type (Base_Type (Typ))); - - if Is_Protected_Type (Utyp) then - Utyp := Corresponding_Record_Type (Utyp); - end if; - end if; - end if; - - -- If the underlying_type is a subtype, we are dealing with the - -- completion of a private type. We need to access the base type and - -- generate a conversion to it. - - if Utyp /= Base_Type (Utyp) then - pragma Assert (Is_Private_Type (Typ)); - - Utyp := Base_Type (Utyp); - end if; - - -- Generate: - -- Set_Finalize_Address_Ptr - -- (FC, FD'Unrestricted_Access); - - return - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Set_Finalize_Address_Ptr), Loc), - - Parameter_Associations => New_List ( - New_Reference_To (Associated_Collection (Ptr_Typ), Loc), - - Make_Attribute_Reference (Loc, - Prefix => - New_Reference_To (TSS (Utyp, TSS_Finalize_Address), Loc), - Attribute_Name => Name_Unrestricted_Access))); - end Make_Set_Finalize_Address_Ptr_Call; - -------------------------- -- Make_Transient_Block -- -------------------------- Index: exp_ch7.ads =================================================================== --- exp_ch7.ads (revision 178155) +++ exp_ch7.ads (working copy) @@ -40,15 +40,15 @@ -- Create the procedures Deep_Initialize, Deep_Adjust and Deep_Finalize -- that take care of finalization management at run-time. - procedure Build_Finalization_Collection + procedure Build_Finalization_Master (Typ : Entity_Id; Ins_Node : Node_Id := Empty; Encl_Scope : Entity_Id := Empty); - -- Build a finalization collection for an access type. The designated type - -- may not necessarely be controlled or need finalization actions. The - -- routine creates a wrapper around a user-defined storage pool or the - -- general storage pool for access types. Ins_Nod and Encl_Scope are used - -- in conjunction with anonymous access types. Ins_Node designates the + -- Build a finalization master for an access type. The designated type may + -- not necessarely be controlled or need finalization actions. The routine + -- creates a wrapper around a user-defined storage pool or the general + -- storage pool for access types. Ins_Nod and Encl_Scope are used in + -- conjunction with anonymous access types. Ins_Node designates the -- insertion point before which the collection should be added. Encl_Scope -- is the scope of the context, either the enclosing record or the scope -- of the related function. @@ -173,18 +173,6 @@ -- Create a special version of Deep_Finalize with identifier Nam. The -- routine has state information and can parform partial finalization. - function Make_Set_Finalize_Address_Ptr_Call - (Loc : Source_Ptr; - Typ : Entity_Id; - Ptr_Typ : Entity_Id) return Node_Id; - -- Generate the following call: - -- - -- Set_Finalize_Address_Ptr (FC, FD'Unrestricted_Access); - -- - -- where Finalize_Address is the corresponding TSS primitive of type Typ - -- and Ptr_Typ is the access type of the related allocation. Loc is the - -- source location of the related allocator. - -------------------------------------------- -- Task and Protected Object finalization -- -------------------------------------------- Index: exp_util.adb =================================================================== --- exp_util.adb (revision 178182) +++ exp_util.adb (working copy) @@ -332,6 +332,9 @@ Desig_Typ : constant Entity_Id := Available_View (Designated_Type (Ptr_Typ)); + function Find_Finalize_Address (Typ : Entity_Id) return Entity_Id; + -- Locate TSS primitive Finalize_Address in type Typ + function Find_Object (E : Node_Id) return Node_Id; -- Given an arbitrary expression of an allocator, try to find an object -- reference in it, otherwise return the original expression. @@ -340,6 +343,57 @@ -- Determine whether subprogram Subp denotes a custom allocate or -- deallocate. + --------------------------- + -- Find_Finalize_Address -- + --------------------------- + + function Find_Finalize_Address (Typ : Entity_Id) return Entity_Id is + Utyp : Entity_Id := Typ; + + begin + if Is_Private_Type (Utyp) + and then Present (Full_View (Utyp)) + then + Utyp := Full_View (Utyp); + end if; + + if Is_Concurrent_Type (Utyp) then + Utyp := Corresponding_Record_Type (Utyp); + end if; + + Utyp := Underlying_Type (Base_Type (Utyp)); + + -- Deal with non-tagged derivation of private views. If the parent is + -- now known to be protected, the finalization routine is the one + -- defined on the corresponding record of the ancestor (corresponding + -- records do not automatically inherit operations, but maybe they + -- should???) + + if Is_Untagged_Derivation (Typ) then + if Is_Protected_Type (Typ) then + Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ))); + else + Utyp := Underlying_Type (Root_Type (Base_Type (Typ))); + + if Is_Protected_Type (Utyp) then + Utyp := Corresponding_Record_Type (Utyp); + end if; + end if; + end if; + + -- If the underlying_type is a subtype, we are dealing with the + -- completion of a private type. We need to access the base type and + -- generate a conversion to it. + + if Utyp /= Base_Type (Utyp) then + pragma Assert (Is_Private_Type (Typ)); + + Utyp := Base_Type (Utyp); + end if; + + return TSS (Utyp, TSS_Finalize_Address); + end Find_Finalize_Address; + ----------------- -- Find_Object -- ----------------- @@ -375,8 +429,7 @@ function Is_Allocate_Deallocate_Proc (Subp : Entity_Id) return Boolean is begin -- Look for a subprogram body with only one statement which is a - -- call to one of the Allocate / Deallocate routines in package - -- Ada.Finalization.Heap_Management. + -- call to Allocate_Any_Controlled / Deallocate_Any_Controlled. if Ekind (Subp) = E_Procedure and then Nkind (Parent (Parent (Subp))) = N_Subprogram_Body @@ -394,8 +447,8 @@ Proc := Entity (Name (First (Statements (HSS)))); return - Is_RTE (Proc, RE_Allocate) - or else Is_RTE (Proc, RE_Deallocate); + Is_RTE (Proc, RE_Allocate_Any_Controlled) + or else Is_RTE (Proc, RE_Deallocate_Any_Controlled); end if; end; end if; @@ -430,137 +483,191 @@ Size_Id : constant Entity_Id := Make_Temporary (Loc, 'S'); Actuals : List_Id; - Collect_Act : Node_Id; - Collect_Id : Entity_Id; - Collect_Typ : Entity_Id; + Fin_Addr_Id : Entity_Id; + Fin_Mas_Act : Node_Id; + Fin_Mas_Id : Entity_Id; + Fin_Mas_Typ : Entity_Id; Proc_To_Call : Entity_Id; begin - -- When dealing with an access subtype, use the collection of the - -- base type. + -- When dealing with an access subtype, always use the base type + -- since it carries all the attributes. if Ekind (Ptr_Typ) = E_Access_Subtype then - Collect_Typ := Base_Type (Ptr_Typ); + Fin_Mas_Typ := Base_Type (Ptr_Typ); else - Collect_Typ := Ptr_Typ; + Fin_Mas_Typ := Ptr_Typ; end if; - Collect_Id := Associated_Collection (Collect_Typ); - Collect_Act := New_Reference_To (Collect_Id, Loc); + Actuals := New_List; - -- Handle the case where the collection is actually a pointer to a - -- collection. This case arises in build-in-place functions. + -- Step 1: Construct all the actuals for the call to library routine + -- Allocate_Any_Controlled / Deallocate_Any_Controlled. - if Is_Access_Type (Etype (Collect_Id)) then - Collect_Act := - Make_Explicit_Dereference (Loc, - Prefix => Collect_Act); - end if; + -- a) Storage pool - -- Create the actuals for the call to Allocate / Deallocate + Append_To (Actuals, + New_Reference_To (Associated_Storage_Pool (Fin_Mas_Typ), Loc)); - Actuals := New_List ( - Collect_Act, - New_Reference_To (Addr_Id, Loc), - New_Reference_To (Size_Id, Loc), - New_Reference_To (Alig_Id, Loc)); + if Is_Allocate then - -- Generate a run-time check to determine whether a class-wide object - -- is truly controlled. + -- b) Subpool - if Is_Class_Wide_Type (Desig_Typ) - or else Is_Generic_Actual_Type (Desig_Typ) - then - declare - Flag_Id : constant Entity_Id := Make_Temporary (Loc, 'F'); - Flag_Expr : Node_Id; - Param : Node_Id; - Temp : Node_Id; + if Present (Subpool_Handle_Name (Expr)) then + Append_To (Actuals, + New_Reference_To (Entity (Subpool_Handle_Name (Expr)), Loc)); + else + Append_To (Actuals, Make_Null (Loc)); + end if; - begin - if Is_Allocate then - Temp := Find_Object (Expression (Expr)); + -- c) Finalization master + + if Needs_Finalization (Desig_Typ) then + Fin_Mas_Id := Finalization_Master (Fin_Mas_Typ); + Fin_Mas_Act := New_Reference_To (Fin_Mas_Id, Loc); + + -- Handle the case where the master is actually a pointer to a + -- master. This case arises in build-in-place functions. + + if Is_Access_Type (Etype (Fin_Mas_Id)) then + Append_To (Actuals, Fin_Mas_Act); else - Temp := Expr; + Append_To (Actuals, + Make_Attribute_Reference (Loc, + Prefix => Fin_Mas_Act, + Attribute_Name => Name_Unrestricted_Access)); end if; + else + Append_To (Actuals, Make_Null (Loc)); + end if; - -- Processing for generic actuals + -- d) Finalize_Address - if Is_Generic_Actual_Type (Desig_Typ) then - Flag_Expr := - New_Reference_To (Boolean_Literals - (Needs_Finalization (Base_Type (Desig_Typ))), Loc); + Fin_Addr_Id := Find_Finalize_Address (Desig_Typ); - -- Processing for subtype indications + if Present (Fin_Addr_Id) then + Append_To (Actuals, + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Fin_Addr_Id, Loc), + Attribute_Name => Name_Unrestricted_Access)); + else + Append_To (Actuals, Make_Null (Loc)); + end if; + end if; - elsif Nkind (Temp) in N_Has_Entity - and then Is_Type (Entity (Temp)) - then - Flag_Expr := - New_Reference_To (Boolean_Literals - (Needs_Finalization (Entity (Temp))), Loc); + -- e) Address + -- f) Storage_Size + -- g) Alignment - -- Generate a runtime check to test the controlled state of an - -- object for the purposes of allocation / deallocation. + Append_To (Actuals, New_Reference_To (Addr_Id, Loc)); + Append_To (Actuals, New_Reference_To (Size_Id, Loc)); + Append_To (Actuals, New_Reference_To (Alig_Id, Loc)); - else - -- The following case arises when allocating through an - -- interface class-wide type, generate: - -- - -- Temp.all + -- h) Is_Controlled - if Is_RTE (Etype (Temp), RE_Tag_Ptr) then - Param := - Make_Explicit_Dereference (Loc, - Prefix => - Relocate_Node (Temp)); + -- Generate a run-time check to determine whether a class-wide object + -- is truly controlled. - -- Generate: - -- Temp'Tag + if Needs_Finalization (Desig_Typ) then + if Is_Class_Wide_Type (Desig_Typ) + or else Is_Generic_Actual_Type (Desig_Typ) + then + declare + Flag_Id : constant Entity_Id := Make_Temporary (Loc, 'F'); + Flag_Expr : Node_Id; + Param : Node_Id; + Temp : Node_Id; + begin + if Is_Allocate then + Temp := Find_Object (Expression (Expr)); else - Param := - Make_Attribute_Reference (Loc, - Prefix => - Relocate_Node (Temp), - Attribute_Name => Name_Tag); + Temp := Expr; end if; - -- Generate: - -- Needs_Finalization (Param) + -- Processing for generic actuals - Flag_Expr := - Make_Function_Call (Loc, - Name => - New_Reference_To (RTE (RE_Needs_Finalization), Loc), - Parameter_Associations => New_List (Param)); - end if; + if Is_Generic_Actual_Type (Desig_Typ) then + Flag_Expr := + New_Reference_To (Boolean_Literals + (Needs_Finalization (Base_Type (Desig_Typ))), Loc); - -- Create the temporary which represents the finalization state - -- of the expression. Generate: - -- - -- F : constant Boolean := ; + -- Processing for subtype indications - Insert_Action (N, - Make_Object_Declaration (Loc, - Defining_Identifier => Flag_Id, - Constant_Present => True, - Object_Definition => - New_Reference_To (Standard_Boolean, Loc), - Expression => Flag_Expr)); + elsif Nkind (Temp) in N_Has_Entity + and then Is_Type (Entity (Temp)) + then + Flag_Expr := + New_Reference_To (Boolean_Literals + (Needs_Finalization (Entity (Temp))), Loc); - -- The flag acts as the fifth actual + -- Generate a runtime check to test the controlled state of + -- an object for the purposes of allocation / deallocation. - Append_To (Actuals, New_Reference_To (Flag_Id, Loc)); - end; + else + -- The following case arises when allocating through an + -- interface class-wide type, generate: + -- + -- Temp.all + + if Is_RTE (Etype (Temp), RE_Tag_Ptr) then + Param := + Make_Explicit_Dereference (Loc, + Prefix => + Relocate_Node (Temp)); + + -- Generate: + -- Temp'Tag + + else + Param := + Make_Attribute_Reference (Loc, + Prefix => + Relocate_Node (Temp), + Attribute_Name => Name_Tag); + end if; + + -- Generate: + -- Needs_Finalization () + + Flag_Expr := + Make_Function_Call (Loc, + Name => + New_Reference_To (RTE (RE_Needs_Finalization), Loc), + Parameter_Associations => New_List (Param)); + end if; + + -- Create the temporary which represents the finalization + -- state of the expression. Generate: + -- + -- F : constant Boolean := ; + + Insert_Action (N, + Make_Object_Declaration (Loc, + Defining_Identifier => Flag_Id, + Constant_Present => True, + Object_Definition => + New_Reference_To (Standard_Boolean, Loc), + Expression => Flag_Expr)); + + -- The flag acts as the last actual + + Append_To (Actuals, New_Reference_To (Flag_Id, Loc)); + end; + end if; + else + Append_To (Actuals, New_Reference_To (Standard_False, Loc)); end if; + -- Step 2: Build a wrapper Allocate / Deallocate which internally + -- calls Allocate_Any_Controlled / Deallocate_Any_Controlled. + -- Select the proper routine to call if Is_Allocate then - Proc_To_Call := RTE (RE_Allocate); + Proc_To_Call := RTE (RE_Allocate_Any_Controlled); else - Proc_To_Call := RTE (RE_Deallocate); + Proc_To_Call := RTE (RE_Deallocate_Any_Controlled); end if; -- Create a custom Allocate / Deallocate routine which has identical @@ -611,10 +718,6 @@ Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List ( - - -- Allocate / Deallocate - -- (, A, S, L[, F]); - Make_Procedure_Call_Statement (Loc, Name => New_Reference_To (Proc_To_Call, Loc), @@ -3752,7 +3855,7 @@ and then Nkind (Rel_Node) /= N_Simple_Return_Statement -- Do not consider transient objects allocated on the heap since they - -- are attached to a finalization collection. + -- are attached to a finalization master. and then not Is_Allocated (Obj_Id) @@ -6431,16 +6534,16 @@ return True; end if; - -- Inspect the freeze node of an access-to-controlled type and - -- look for a delayed finalization collection. This case arises - -- when the freeze actions are inserted at a later time than the - -- expansion of the context. Since Build_Finalizer is never called - -- on a single construct twice, the collection will be ultimately - -- left out and never finalized. This is also needed for freeze - -- actions of designated types themselves, since in some cases the - -- finalization collection is associated with a designated type's - -- freeze node rather than that of the access type (see handling - -- for freeze actions in Build_Finalization_Collection). + -- Inspect the freeze node of an access-to-controlled type and look + -- for a delayed finalization master. This case arises when the + -- freeze actions are inserted at a later time than the expansion of + -- the context. Since Build_Finalizer is never called on a single + -- construct twice, the master will be ultimately left out and never + -- finalized. This is also needed for freeze actions of designated + -- types themselves, since in some cases the finalization master is + -- associated with a designated type's freeze node rather than that + -- of the access type (see handling for freeze actions in + -- Build_Finalization_Master). elsif Nkind (Decl) = N_Freeze_Entity and then Present (Actions (Decl)) @@ -6451,9 +6554,9 @@ and then not Is_Access_Subprogram_Type (Typ) and then Needs_Finalization (Available_View (Designated_Type (Typ)))) - or else - (Is_Type (Typ) - and then Needs_Finalization (Typ))) + or else + (Is_Type (Typ) + and then Needs_Finalization (Typ))) and then Requires_Cleanup_Actions (Actions (Decl), For_Package, Nested_Constructs) then Index: exp_util.ads =================================================================== --- exp_util.ads (revision 178155) +++ exp_util.ads (working copy) @@ -202,21 +202,7 @@ -- allocation, N is the declaration of the temporary variable which -- represents the expression of the original allocator node, otherwise N -- must be a free statement. If flag Is_Allocate is set, the generated - -- routine is allocate, deallocate otherwise. The generated routine is: - -- - -- F : constant Boolean := -- CW case - -- Ada.Tags.Needs_Finalization ('Tag); -- CW case - -- - -- procedure Allocate / Deallocate - -- (P : Storage_Pool; - -- A : [out] Address; -- out is present for Allocate - -- S : Storage_Count; - -- L : Storage_Count) - -- is - -- begin - -- Allocate / Deallocate - -- (, A, S, L, [Needs_Header => F]); - -- end Allocate; + -- routine is allocate, deallocate otherwise. function Build_Runtime_Call (Loc : Source_Ptr; RE : RE_Id) return Node_Id; -- Build an N_Procedure_Call_Statement calling the given runtime entity. Index: einfo.adb =================================================================== --- einfo.adb (revision 178156) +++ einfo.adb (working copy) @@ -195,11 +195,11 @@ -- Scope_Depth_Value Uint22 -- Shared_Var_Procs_Instance Node22 - -- Associated_Collection Node23 -- CR_Discriminant Node23 -- Entry_Cancel_Parameter Node23 -- Enum_Pos_To_Rep Node23 -- Extra_Constrained Node23 + -- Finalization_Master Node23 -- Generic_Renamings Elist23 -- Inner_Instances Elist23 -- Limited_View Node23 @@ -612,12 +612,6 @@ return Uint14 (Id); end Alignment; - function Associated_Collection (Id : E) return E is - begin - pragma Assert (Is_Access_Type (Id)); - return Node23 (Id); - end Associated_Collection; - function Associated_Formal_Package (Id : E) return E is begin pragma Assert (Ekind (Id) = E_Package); @@ -1075,6 +1069,12 @@ return Flag229 (Base_Type (Id)); end Can_Use_Internal_Rep; + function Finalization_Master (Id : E) return E is + begin + pragma Assert (Is_Access_Type (Id)); + return Node23 (Root_Type (Id)); + end Finalization_Master; + function Finalize_Storage_Only (Id : E) return B is begin pragma Assert (Is_Type (Id)); @@ -3051,12 +3051,6 @@ Set_Elist16 (Id, V); end Set_Access_Disp_Table; - procedure Set_Associated_Collection (Id : E; V : E) is - begin - pragma Assert (Is_Access_Type (Id)); - Set_Node23 (Id, V); - end Set_Associated_Collection; - procedure Set_Associated_Formal_Package (Id : E; V : E) is begin Set_Node12 (Id, V); @@ -3544,6 +3538,12 @@ Set_Flag229 (Id, V); end Set_Can_Use_Internal_Rep; + procedure Set_Finalization_Master (Id : E; V : E) is + begin + pragma Assert (Is_Access_Type (Id) and then Is_Base_Type (Id)); + Set_Node23 (Id, V); + end Set_Finalization_Master; + procedure Set_Finalize_Storage_Only (Id : E; V : B := True) is begin pragma Assert (Is_Type (Id) and then Is_Base_Type (Id)); @@ -6941,16 +6941,8 @@ if Ekind (T) = E_Class_Wide_Type then return Etype (T); - elsif Ekind (T) = E_Class_Wide_Subtype then - return Etype (Base_Type (T)); + -- Other cases - -- ??? T comes from Base_Type, how can it be a subtype? - -- Also Base_Type is supposed to be idempotent, so either way - -- this is equivalent to "return Etype (T)" and should be merged - -- with the E_Class_Wide_Type case. - - -- All other cases - else loop Etyp := Etype (T); @@ -8459,9 +8451,6 @@ procedure Write_Field23_Name (Id : Entity_Id) is begin case Ekind (Id) is - when Access_Kind => - Write_Str ("Associated_Collection"); - when E_Discriminant => Write_Str ("CR_Discriminant"); @@ -8475,6 +8464,9 @@ E_Variable => Write_Str ("Extra_Constrained"); + when Access_Kind => + Write_Str ("Finalization_Master"); + when E_Generic_Function | E_Generic_Package | E_Generic_Procedure => Index: einfo.ads =================================================================== --- einfo.ads (revision 178182) +++ einfo.ads (working copy) @@ -427,12 +427,6 @@ -- definition clause with an (obsolescent) mod clause is converted -- into an attribute definition clause for this purpose. --- Associated_Collection (Node23) --- Present in non-subprogram access type entities. Contains the entity of --- the finalization collection on which dynamically allocated objects --- referenced by the access type are stored. Empty when the access type --- cannot reference a controlled object. - -- Associated_Formal_Package (Node12) -- Present in packages that are the actuals of formal_packages. Points -- to the entity in the declaration for the formal package. @@ -1144,6 +1138,13 @@ -- must be retrieved through the entity designed by this field instead of -- being computed. +-- Finalization_Master (Node23) [root type only] +-- Present in access-to-controlled or access-to-class-wide types. The +-- field contains the entity of the finalization master which handles +-- dynamically allocated controlled objects referenced by the access +-- type. Empty for access-to-subprogram types. Empty for access types +-- whose designated type does not need finalization actions. + -- Finalize_Storage_Only (Flag158) [base type only] -- Present in all types. Set on direct controlled types to which a -- valid Finalize_Storage_Only pragma applies. This flag is also set on @@ -4943,7 +4944,7 @@ -- Master_Id (Node17) -- Directly_Designated_Type (Node20) -- Associated_Storage_Pool (Node22) (base type only) - -- Associated_Collection (Node23) (base type only) + -- Finalization_Master (Node23) (base type only) -- Has_Pragma_Controlled (Flag27) (base type only) -- Has_Storage_Size_Clause (Flag23) (base type only) -- Is_Access_Constant (Flag69) @@ -4971,7 +4972,7 @@ -- E_Anonymous_Access_Type -- Storage_Size_Variable (Node15) ??? is this needed ??? -- Directly_Designated_Type (Node20) - -- Associated_Collection (Node23) + -- Finalization_Master (Node23) -- (plus type attributes) -- E_Array_Type @@ -5278,7 +5279,7 @@ -- Master_Id (Node17) -- Directly_Designated_Type (Node20) -- Associated_Storage_Pool (Node22) (root type only) - -- Associated_Collection (Node23) + -- Finalization_Master (Node23) (root type only) -- (plus type attributes) -- E_Generic_In_Parameter @@ -5974,7 +5975,6 @@ function Address_Taken (Id : E) return B; function Alias (Id : E) return E; function Alignment (Id : E) return U; - function Associated_Collection (Id : E) return E; function Associated_Formal_Package (Id : E) return E; function Associated_Node_For_Itype (Id : E) return N; function Associated_Storage_Pool (Id : E) return E; @@ -6050,6 +6050,7 @@ function Extra_Formal (Id : E) return E; function Extra_Formals (Id : E) return E; function Can_Use_Internal_Rep (Id : E) return B; + function Finalization_Master (Id : E) return E; function Finalize_Storage_Only (Id : E) return B; function Finalizer (Id : E) return E; function First_Entity (Id : E) return E; @@ -6563,7 +6564,6 @@ procedure Set_Address_Taken (Id : E; V : B := True); procedure Set_Alias (Id : E; V : E); procedure Set_Alignment (Id : E; V : U); - procedure Set_Associated_Collection (Id : E; V : E); procedure Set_Associated_Formal_Package (Id : E; V : E); procedure Set_Associated_Node_For_Itype (Id : E; V : N); procedure Set_Associated_Storage_Pool (Id : E; V : E); @@ -6637,6 +6637,7 @@ procedure Set_Extra_Formal (Id : E; V : E); procedure Set_Extra_Formals (Id : E; V : E); procedure Set_Can_Use_Internal_Rep (Id : E; V : B := True); + procedure Set_Finalization_Master (Id : E; V : E); procedure Set_Finalize_Storage_Only (Id : E; V : B := True); procedure Set_Finalizer (Id : E; V : E); procedure Set_First_Entity (Id : E; V : E); @@ -7259,7 +7260,6 @@ pragma Inline (Address_Taken); pragma Inline (Alias); pragma Inline (Alignment); - pragma Inline (Associated_Collection); pragma Inline (Associated_Formal_Package); pragma Inline (Associated_Node_For_Itype); pragma Inline (Associated_Storage_Pool); @@ -7335,6 +7335,7 @@ pragma Inline (Extra_Formal); pragma Inline (Extra_Formals); pragma Inline (Can_Use_Internal_Rep); + pragma Inline (Finalization_Master); pragma Inline (Finalizer); pragma Inline (First_Entity); pragma Inline (First_Exit_Statement); @@ -7703,7 +7704,6 @@ pragma Inline (Set_Address_Taken); pragma Inline (Set_Alias); pragma Inline (Set_Alignment); - pragma Inline (Set_Associated_Collection); pragma Inline (Set_Associated_Formal_Package); pragma Inline (Set_Associated_Node_For_Itype); pragma Inline (Set_Associated_Storage_Pool); @@ -7778,6 +7778,7 @@ pragma Inline (Set_Extra_Formal); pragma Inline (Set_Extra_Formals); pragma Inline (Set_Can_Use_Internal_Rep); + pragma Inline (Set_Finalization_Master); pragma Inline (Set_Finalizer); pragma Inline (Set_First_Entity); pragma Inline (Set_First_Exit_Statement); Index: rtsfind.adb =================================================================== --- rtsfind.adb (revision 178155) +++ rtsfind.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2010, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2011, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -293,9 +293,6 @@ elsif U_Id in Ada_Dispatching_Child then Name_Buffer (16) := '.'; - elsif U_Id in Ada_Finalization_Child then - Name_Buffer (17) := '.'; - elsif U_Id in Ada_Interrupts_Child then Name_Buffer (15) := '.'; @@ -324,6 +321,10 @@ elsif U_Id in System_Child then Name_Buffer (7) := '.'; + if U_Id in System_Storage_Pools_Child then + Name_Buffer (21) := '.'; + end if; + if U_Id in System_Strings_Child then Name_Buffer (15) := '.'; end if; Index: rtsfind.ads =================================================================== --- rtsfind.ads (revision 178176) +++ rtsfind.ads (working copy) @@ -48,9 +48,6 @@ -- eventually, packages implementing delays will be found relative to -- the package that declares the time type. - -- Names of the form Ada_Finalization_xxx are second level children of - -- Ada.Finalization. - -- Names of the form Ada_Interrupts_xxx are second level children of -- Ada.Interrupts. This is needed for Ada.Interrupts.Names which is used -- by pragma Interrupt_State. @@ -80,6 +77,9 @@ -- name is System.xxx. For example, the name System_Str_Concat refers to -- package System.Str_Concat. + -- Names of the form System_Storage_Pools_xxx are second level children + -- of the package System.Storage_Pools. + -- Names of the form System_Strings_xxx are second level children of the -- package System.Strings. @@ -140,10 +140,6 @@ Ada_Dispatching_EDF, - -- Children of Ada.Finalization - - Ada_Finalization_Heap_Management, - -- Children of Ada.Interrupts Ada_Interrupts_Names, @@ -249,6 +245,7 @@ System_Fat_VAX_D_Float, System_Fat_VAX_F_Float, System_Fat_VAX_G_Float, + System_Finalization_Masters, System_Finalization_Root, System_Fore, System_Img_Bool, @@ -374,6 +371,10 @@ System_WWd_Enum, System_WWd_Wchar, + -- Children of System.Storage_Pools + + System_Storage_Pools_Subpools, + -- Children of System.Strings System_Strings_Stream_Ops, @@ -403,10 +404,6 @@ range Ada_Dispatching_EDF .. Ada_Dispatching_EDF; -- Range of values for children of Ada.Dispatching - subtype Ada_Finalization_Child is Ada_Child range - Ada_Finalization_Heap_Management .. Ada_Finalization_Heap_Management; - -- Range of values for children of Ada.Finalization - subtype Ada_Interrupts_Child is Ada_Child range Ada_Interrupts_Names .. Ada_Interrupts_Names; -- Range of values for children of Ada.Interrupts @@ -443,6 +440,9 @@ range System_Address_Image .. System_Tasking_Stages; -- Range of values for children or grandchildren of System + subtype System_Storage_Pools_Child is RTU_Id + range System_Storage_Pools_Subpools .. System_Storage_Pools_Subpools; + subtype System_Strings_Child is RTU_Id range System_Strings_Stream_Ops .. System_Strings_Stream_Ops; @@ -521,17 +521,6 @@ RE_Reraise_Occurrence_No_Defer, -- Ada.Exceptions RE_Save_Occurrence, -- Ada.Exceptions - RE_Add_Offset_To_Address, -- Ada.Finalization.Heap_Management - RE_Allocate, -- Ada.Finalization.Heap_Management - RE_Attach, -- Ada.Finalization.Heap_Management - RE_Base_Pool, -- Ada.Finalization.Heap_Management - RE_Deallocate, -- Ada.Finalization.Heap_Management - RE_Detach, -- Ada.Finalization.Heap_Management - RE_Finalization_Collection, -- Ada.Finalization.Heap_Management - RE_Finalization_Collection_Ptr, -- Ada.Finalization.Heap_Management - RE_Set_Finalize_Address_Ptr, -- Ada.Finalization.Heap_Management - RE_Set_Storage_Pool_Ptr, -- Ada.Finalization.Heap_Management - RE_Interrupt_ID, -- Ada.Interrupts RE_Is_Reserved, -- Ada.Interrupts RE_Is_Attached, -- Ada.Interrupts @@ -805,6 +794,14 @@ RE_Attr_VAX_G_Float, -- System.Fat_VAX_G_Float RE_Fat_VAX_G, -- System.Fat_VAX_G_Float + RE_Add_Offset_To_Address, -- System.Finalization_Masters + RE_Attach, -- System.Finalization_Masters + RE_Base_Pool, -- System.Finalization_Masters + RE_Detach, -- System.Finalization_Masters + RE_Finalization_Master, -- System.Finalization_Masters + RE_Finalization_Master_Ptr, -- System.Finalization_Masters + RE_Set_Base_Pool, -- System.Finalization_Masters + RE_Root_Controlled, -- System.Finalization_Root RE_Root_Controlled_Ptr, -- System.Finalization_Root @@ -1327,10 +1324,16 @@ RE_Storage_Offset, -- System.Storage_Elements RE_To_Address, -- System.Storage_Elements + RE_Allocate_Any, -- System.Storage_Pools + RE_Deallocate_Any, -- System.Storage_Pools RE_Root_Storage_Pool, -- System.Storage_Pools - RE_Allocate_Any, -- System.Storage_Pools, - RE_Deallocate_Any, -- System.Storage_Pools, + RE_Allocate_Any_Controlled, -- System.Storage_Pools.Subpools + RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools + RE_Root_Storage_Pool_With_Subpools, -- System.Storage_Pools.Subpools + RE_Root_Subpool, -- System.Storage_Pools.Subpools + RE_Subpool_Handle, -- System.Storage_Pools.Subpools + RE_I_AD, -- System.Stream_Attributes RE_I_AS, -- System.Stream_Attributes RE_I_B, -- System.Stream_Attributes @@ -1704,17 +1707,6 @@ RE_Reraise_Occurrence_No_Defer => Ada_Exceptions, RE_Save_Occurrence => Ada_Exceptions, - RE_Add_Offset_To_Address => Ada_Finalization_Heap_Management, - RE_Allocate => Ada_Finalization_Heap_Management, - RE_Attach => Ada_Finalization_Heap_Management, - RE_Base_Pool => Ada_Finalization_Heap_Management, - RE_Deallocate => Ada_Finalization_Heap_Management, - RE_Detach => Ada_Finalization_Heap_Management, - RE_Finalization_Collection => Ada_Finalization_Heap_Management, - RE_Finalization_Collection_Ptr => Ada_Finalization_Heap_Management, - RE_Set_Finalize_Address_Ptr => Ada_Finalization_Heap_Management, - RE_Set_Storage_Pool_Ptr => Ada_Finalization_Heap_Management, - RE_Interrupt_ID => Ada_Interrupts, RE_Is_Reserved => Ada_Interrupts, RE_Is_Attached => Ada_Interrupts, @@ -1988,6 +1980,14 @@ RE_Attr_VAX_G_Float => System_Fat_VAX_G_Float, RE_Fat_VAX_G => System_Fat_VAX_G_Float, + RE_Add_Offset_To_Address => System_Finalization_Masters, + RE_Attach => System_Finalization_Masters, + RE_Base_Pool => System_Finalization_Masters, + RE_Detach => System_Finalization_Masters, + RE_Finalization_Master => System_Finalization_Masters, + RE_Finalization_Master_Ptr => System_Finalization_Masters, + RE_Set_Base_Pool => System_Finalization_Masters, + RE_Root_Controlled => System_Finalization_Root, RE_Root_Controlled_Ptr => System_Finalization_Root, @@ -2510,10 +2510,16 @@ RE_Storage_Offset => System_Storage_Elements, RE_To_Address => System_Storage_Elements, - RE_Root_Storage_Pool => System_Storage_Pools, RE_Allocate_Any => System_Storage_Pools, RE_Deallocate_Any => System_Storage_Pools, + RE_Root_Storage_Pool => System_Storage_Pools, + RE_Allocate_Any_Controlled => System_Storage_Pools_Subpools, + RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools, + RE_Root_Storage_Pool_With_Subpools => System_Storage_Pools_Subpools, + RE_Root_Subpool => System_Storage_Pools_Subpools, + RE_Subpool_Handle => System_Storage_Pools_Subpools, + RE_I_AD => System_Stream_Attributes, RE_I_AS => System_Stream_Attributes, RE_I_B => System_Stream_Attributes, Index: freeze.adb =================================================================== --- freeze.adb (revision 178160) +++ freeze.adb (working copy) @@ -1432,27 +1432,27 @@ end loop; end; - -- We add finalization collections to access types whose designated - -- types require finalization. This is normally done when freezing - -- the type, but this misses recursive type definitions where the - -- later members of the recursion introduce controlled components - -- (such as can happen when incomplete types are involved), as well - -- cases where a component type is private and the controlled full - -- type occurs after the access type is frozen. Cases that don't - -- need a finalization collection are generic formal types (the - -- actual type will have it) and types with Java and CIL conventions, - -- since those are used for API bindings. (Are there any other cases - -- that should be excluded here???) + -- We add finalization masters to access types whose designated types + -- require finalization. This is normally done when freezing the + -- type, but this misses recursive type definitions where the later + -- members of the recursion introduce controlled components (such as + -- can happen when incomplete types are involved), as well cases + -- where a component type is private and the controlled full type + -- occurs after the access type is frozen. Cases that don't need a + -- finalization master are generic formal types (the actual type will + -- have it) and types with Java and CIL conventions, since those are + -- used for API bindings. (Are there any other cases that should be + -- excluded here???) elsif Is_Access_Type (E) and then Comes_From_Source (E) and then not Is_Generic_Type (E) and then Needs_Finalization (Designated_Type (E)) - and then No (Associated_Collection (E)) + and then No (Finalization_Master (E)) and then Convention (Designated_Type (E)) /= Convention_Java and then Convention (Designated_Type (E)) /= Convention_CIL then - Build_Finalization_Collection (E); + Build_Finalization_Master (E); end if; Next_Entity (E); @@ -2029,7 +2029,7 @@ Next_Entity (Comp); end loop; - -- Deal with Bit_Order aspect specifying a non-default bit order + -- Deal with pragma Bit_Order setting non-standard bit order if Reverse_Bit_Order (Rec) and then Base_Type (Rec) = Rec then if not Placed_Component then Index: s-stposu.adb =================================================================== --- s-stposu.adb (revision 0) +++ s-stposu.adb (revision 0) @@ -0,0 +1,473 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . S T O R A G E _ P O O L S . S U B P O O L S -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. The copyright notice above, and the license provisions that follow -- +-- apply solely to the contents of the part following the private keyword. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with Ada.Exceptions; use Ada.Exceptions; +with Ada.Unchecked_Deallocation; + +with System.Finalization_Masters; use System.Finalization_Masters; +with System.Soft_Links; use System.Soft_Links; +with System.Storage_Elements; use System.Storage_Elements; + +package body System.Storage_Pools.Subpools is + + procedure Attach (N : not null SP_Node_Ptr; L : not null SP_Node_Ptr); + -- Attach a subpool node to a pool + + procedure Free is new Ada.Unchecked_Deallocation (SP_Node, SP_Node_Ptr); + + procedure Detach (N : not null SP_Node_Ptr); + -- Unhook a subpool node from an arbitrary subpool list + + -------------- + -- Allocate -- + -------------- + + overriding procedure Allocate + (Pool : in out Root_Storage_Pool_With_Subpools; + Storage_Address : out System.Address; + Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count) + is + begin + -- ??? The use of Allocate is very dangerous as it does not handle + -- controlled objects properly. Perhaps we should provide an + -- implementation which raises Program_Error instead. + + -- Dispatch to the user-defined implementations of Allocate_From_Subpool + -- and Default_Subpool_For_Pool. + + Allocate_From_Subpool + (Root_Storage_Pool_With_Subpools'Class (Pool), + Storage_Address, + Size_In_Storage_Elements, + Alignment, + Default_Subpool_For_Pool + (Root_Storage_Pool_With_Subpools'Class (Pool))); + end Allocate; + + ----------------------------- + -- Allocate_Any_Controlled -- + ----------------------------- + + procedure Allocate_Any_Controlled + (Pool : in out Root_Storage_Pool'Class; + Context_Subpool : Subpool_Handle := null; + Context_Master : Finalization_Masters.Finalization_Master_Ptr := null; + Fin_Address : Finalization_Masters.Finalize_Address_Ptr := null; + Addr : out System.Address; + Storage_Size : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count; + Is_Controlled : Boolean := True) + is + -- ??? This membership test gives the wrong result when Pool has + -- subpools. + + Is_Subpool_Allocation : constant Boolean := + Pool in Root_Storage_Pool_With_Subpools; + + Master : Finalization_Master_Ptr := null; + N_Addr : Address; + N_Ptr : FM_Node_Ptr; + N_Size : Storage_Count; + Subpool : Subpool_Handle := null; + + begin + -- Step 1: Pool-related runtime checks + + -- Allocation on a pool_with_subpools. In this scenario there is a + -- master for each subpool. + + if Is_Subpool_Allocation then + + -- Case of an allocation without a Subpool_Handle. Dispatch to the + -- implementation of Default_Subpool_For_Pool. + + if Context_Subpool = null then + Subpool := + Default_Subpool_For_Pool + (Root_Storage_Pool_With_Subpools'Class (Pool)); + + -- Ensure proper ownership + + if Subpool.Owner /= + Root_Storage_Pool_With_Subpools'Class (Pool)'Unchecked_Access + then + raise Program_Error with "incorrect owner of default subpool"; + end if; + + -- Allocation with a Subpool_Handle + + else + Subpool := Context_Subpool; + + -- Ensure proper ownership + + if Subpool.Owner /= + Root_Storage_Pool_With_Subpools'Class (Pool)'Unchecked_Access + then + raise Program_Error with "incorrect owner of subpool"; + end if; + end if; + + Master := Subpool.Master'Unchecked_Access; + + -- Allocation on a simple pool. In this scenario there is a master for + -- each access-to-controlled type. No context subpool should be present. + + else + + -- If the master is missing, then the expansion of the access type + -- failed to create one. This is a serious error. + + if Context_Master = null then + raise Program_Error with "missing master in pool allocation"; + + -- If a subpool is present, then this is the result of erroneous + -- allocator expansion. This is not a serious error, but it should + -- still be detected. + + elsif Context_Subpool /= null then + raise Program_Error with "subpool not required in pool allocation"; + end if; + + Master := Context_Master; + end if; + + -- Step 2: Master-related runtime checks + + -- Allocation of a descendant from [Limited_]Controlled, a class-wide + -- object or a record with controlled components. + + if Is_Controlled then + + -- Do not allow the allocation of controlled objects while the + -- associated master is being finalized. + + if Master.Finalization_Started then + raise Program_Error with "allocation after finalization started"; + end if; + + -- The size must acount for the hidden header preceding the object + + N_Size := Storage_Size + Header_Size; + + -- Non-controlled allocation + + else + N_Size := Storage_Size; + end if; + + -- Step 3: Allocation of object + + -- For descendants of Root_Storage_Pool_With_Subpools, dispatch to the + -- implementation of Allocate_From_Subpool. + + if Is_Subpool_Allocation then + Allocate_From_Subpool + (Root_Storage_Pool_With_Subpools'Class (Pool), + N_Addr, N_Size, Alignment, Subpool); + + -- For descendants of Root_Storage_Pool, dispatch to the implementation + -- of Allocate. + + else + Allocate (Pool, N_Addr, N_Size, Alignment); + end if; + + -- Step 4: Attachment + + if Is_Controlled then + + -- Map the allocated memory into a FM_Node record. This converts the + -- top of the allocated bits into a list header. + + N_Ptr := Address_To_FM_Node_Ptr (N_Addr); + + -- Check whether primitive Finalize_Address is available. If it is + -- not, then either the expansion of the designated type failed or + -- the expansion of the allocator failed. This is a serious error. + + if Fin_Address = null then + raise Program_Error + with "primitive Finalize_Address not available"; + end if; + + N_Ptr.Finalize_Address := Fin_Address; + + -- Prepend the allocated object to the finalization master + + Attach (N_Ptr, Master.Objects'Unchecked_Access); + + -- Move the address from the hidden list header to the start of the + -- object. This operation effectively hides the list header. + + Addr := N_Addr + Header_Offset; + else + Addr := N_Addr; + end if; + end Allocate_Any_Controlled; + + ------------ + -- Attach -- + ------------ + + procedure Attach (N : not null SP_Node_Ptr; L : not null SP_Node_Ptr) is + begin + Lock_Task.all; + + L.Next.Prev := N; + N.Next := L.Next; + L.Next := N; + N.Prev := L; + + Unlock_Task.all; + + -- Note: No need to unlock in case of an exception because the above + -- code can never raise one. + end Attach; + + ------------------------------- + -- Deallocate_Any_Controlled -- + ------------------------------- + + procedure Deallocate_Any_Controlled + (Pool : in out Root_Storage_Pool'Class; + Addr : System.Address; + Storage_Size : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count; + Is_Controlled : Boolean := True) + is + N_Addr : Address; + N_Ptr : FM_Node_Ptr; + N_Size : Storage_Count; + + begin + -- Step 1: Detachment + + if Is_Controlled then + + -- Move the address from the object to the beginning of the list + -- header. + + N_Addr := Addr - Header_Offset; + + -- Convert the bits preceding the object into a list header + + N_Ptr := Address_To_FM_Node_Ptr (N_Addr); + + -- Detach the object from the related finalization master. This + -- action does not need to know the prior context used during + -- allocation. + + Detach (N_Ptr); + + -- The size of the deallocated object must include the size of the + -- hidden list header. + + N_Size := Storage_Size + Header_Size; + else + N_Addr := Addr; + N_Size := Storage_Size; + end if; + + -- Step 2: Deallocation + + -- Dispatch to the proper implementation of Deallocate. This action + -- covers both Root_Storage_Pool and Root_Storage_Pool_With_Subpools + -- implementations. + + Deallocate (Pool, N_Addr, N_Size, Alignment); + end Deallocate_Any_Controlled; + + ------------ + -- Detach -- + ------------ + + procedure Detach (N : not null SP_Node_Ptr) is + begin + -- N must be attached to some list + + pragma Assert (N.Next /= null and then N.Prev /= null); + + Lock_Task.all; + + N.Prev.Next := N.Next; + N.Next.Prev := N.Prev; + + Unlock_Task.all; + + -- Note: No need to unlock in case of an exception because the above + -- code can never raise one. + end Detach; + + -------------- + -- Finalize -- + -------------- + + overriding procedure Finalize + (Pool : in out Root_Storage_Pool_With_Subpools) + is + Curr_Ptr : SP_Node_Ptr; + Ex_Occur : Exception_Occurrence; + Next_Ptr : SP_Node_Ptr; + Raised : Boolean := False; + + begin + -- Uninitialized pools do not have subpools and do not contain objects + -- of any kind. + + if not Pool.Initialized then + return; + end if; + + -- It is possible for multiple tasks to cause the finalization of a + -- common pool. Allow only one task to finalize the contents. + + if Pool.Finalization_Started then + return; + end if; + + -- Lock the pool to prevent the creation of additional subpools while + -- the available ones are finalized. The pool remains locked because + -- either it is about to be deallocated or the associated access type + -- is about to go out of scope. + + Pool.Finalization_Started := True; + + -- Skip the dummy head + + Curr_Ptr := Pool.Subpools.Next; + while Curr_Ptr /= Pool.Subpools'Unchecked_Access loop + Next_Ptr := Curr_Ptr.Next; + + -- Remove the subpool node from the subpool list + + Detach (Curr_Ptr); + + -- Finalize the current subpool + + begin + Finalize_Subpool (Curr_Ptr.Subpool); + + exception + when Fin_Occur : others => + if not Raised then + Raised := True; + Save_Occurrence (Ex_Occur, Fin_Occur); + end if; + end; + + -- Since subpool nodes are not allocated on the owner pool, they must + -- be explicitly destroyed. + + Free (Curr_Ptr); + + Curr_Ptr := Next_Ptr; + end loop; + + -- If the finalization of a particular master failed, reraise the + -- exception now. + + if Raised then + Reraise_Occurrence (Ex_Occur); + end if; + end Finalize; + + ---------------------- + -- Finalize_Subpool -- + ---------------------- + + procedure Finalize_Subpool (Subpool : not null Subpool_Handle) is + begin + Finalize (Subpool.Master); + end Finalize_Subpool; + + --------------------- + -- Pool_Of_Subpool -- + --------------------- + + function Pool_Of_Subpool (Subpool : not null Subpool_Handle) + return access Root_Storage_Pool_With_Subpools'Class is + begin + return Subpool.Owner; + end Pool_Of_Subpool; + + ------------------------- + -- Set_Pool_Of_Subpool -- + ------------------------- + + procedure Set_Pool_Of_Subpool + (Subpool : not null Subpool_Handle; + Pool : in out Root_Storage_Pool_With_Subpools'Class) + is + N_Ptr : SP_Node_Ptr; + + begin + if not Pool.Initialized then + + -- The dummy head must point to itself in both directions + + Pool.Subpools.Next := Pool.Subpools'Unchecked_Access; + Pool.Subpools.Prev := Pool.Subpools'Unchecked_Access; + Pool.Initialized := True; + end if; + + -- If the subpool is already owned, raise Program_Error. This is a + -- direct violation of the RM rules. + + if Subpool.Owner /= null then + raise Program_Error with "subpool already belongs to a pool"; + end if; + + -- Prevent the creation of a new subpool while the owner is being + -- finalized. This is a serious error. + + if Pool.Finalization_Started then + raise Program_Error + with "subpool creation after finalization started"; + end if; + + -- Create a subpool node, decorate it and associate it with the subpool + -- list of Pool. + + N_Ptr := new SP_Node; + + Subpool.Owner := Pool'Unchecked_Access; + N_Ptr.Subpool := Subpool; + + Attach (N_Ptr, Pool.Subpools'Unchecked_Access); + end Set_Pool_Of_Subpool; + +end System.Storage_Pools.Subpools; Index: s-stposu.ads =================================================================== --- s-stposu.ads (revision 0) +++ s-stposu.ads (revision 0) @@ -0,0 +1,255 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . S T O R A G E _ P O O L S . S U B P O O L S -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. The copyright notice above, and the license provisions that follow -- +-- apply solely to the contents of the part following the private keyword. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with System.Finalization_Masters; +with System.Storage_Elements; + +package System.Storage_Pools.Subpools is + pragma Preelaborate (System.Storage_Pools.Subpools); + + type Root_Storage_Pool_With_Subpools is abstract + new Root_Storage_Pool with private; + -- The base for all implementations of Storage_Pool_With_Subpools. This + -- type is Limited_Controlled by derivation. To use subpools, an access + -- type must be associated with an implementation descending from type + -- Root_Storage_Pool_With_Subpools. + + type Root_Subpool is abstract tagged limited private; + -- The base for all implementations of Subpool. Objects of this type are + -- managed by the pool_with_subpools. + + type Subpool_Handle is access all Root_Subpool'Class; + for Subpool_Handle'Storage_Size use 0; + -- Since subpools are limited types by definition, a handle is instead used + -- to manage subpool abstractions. + + overriding procedure Allocate + (Pool : in out Root_Storage_Pool_With_Subpools; + Storage_Address : out System.Address; + Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count); + -- Allocate an object described by Size_In_Storage_Elements and Alignment + -- on the default subpool of Pool. + + procedure Allocate_From_Subpool + (Pool : in out Root_Storage_Pool_With_Subpools; + Storage_Address : out System.Address; + Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count; + Subpool : not null Subpool_Handle) + is abstract; + + -- ??? This precondition causes errors in simple tests, disabled for now + +-- with Pre'Class => Pool_Of_Subpool (Subpool) = Pool'Access; + -- This routine requires implementation. Allocate an object described by + -- Size_In_Storage_Elements and Alignment on a subpool. + + function Create_Subpool + (Pool : in out Root_Storage_Pool_With_Subpools; + Storage_Size : Storage_Elements.Storage_Count := + Storage_Elements.Storage_Count'Last) + return not null Subpool_Handle + is abstract; + -- This routine requires implementation. Create a subpool within the given + -- pool_with_subpools. + + overriding procedure Deallocate + (Pool : in out Root_Storage_Pool_With_Subpools; + Storage_Address : System.Address; + Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count) + is null; + + procedure Deallocate_Subpool + (Pool : in out Root_Storage_Pool_With_Subpools; + Subpool : in out Subpool_Handle) + is abstract; + + -- ??? This precondition causes errors in simple tests, disabled for now + +-- with Pre'Class => Pool_Of_Subpool (Subpool) = Pool'Access; + -- This routine requires implementation. Reclaim the storage a particular + -- subpool occupies in a pool_with_subpools. This routine is called by + -- Ada.Unchecked_Deallocate_Subpool. + + function Default_Subpool_For_Pool + (Pool : Root_Storage_Pool_With_Subpools) + return not null Subpool_Handle + is abstract; + -- This routine requires implementation. Returns a common subpool used for + -- allocations without Subpool_Handle_name in the allocator. + + function Pool_Of_Subpool + (Subpool : not null Subpool_Handle) + return access Root_Storage_Pool_With_Subpools'Class; + -- Return the owner of the subpool + + procedure Set_Pool_Of_Subpool + (Subpool : not null Subpool_Handle; + Pool : in out Root_Storage_Pool_With_Subpools'Class); + -- Set the owner of the subpool. This is intended to be called from + -- Create_Subpool or similar subpool constructors. Raises Program_Error + -- if the subpool already belongs to a pool. + +private + -- Model + -- Pool_With_Subpools + -- +----> +---------------------+ <----+ + -- | +---------- Subpools | | + -- | | +---------------------+ | + -- | | : User data : | + -- | | '.....................' | + -- | | | + -- | | SP_Node SP_Node | + -- | +-> +-------+ +-------+ | + -- | | Prev <-----> Prev | | + -- | +-------+ +-------+ | + -- | | Next <---->| Next | | + -- | +-------+ +-------+ | + -- | +----Subpool| |Subpool----+ | + -- | | +-------+ +-------+ | | + -- | | | | + -- | | Subpool Subpool | | + -- | +-> +-------+ +-------+ <-+ | + -- +------- Owner | | Owner -------+ + -- +-------+ +-------+ + -- +------------------- Master| | Master---------------+ + -- | +-------+ +-------+ | + -- | : User : : User : | + -- | : Data : : Data : | + -- | '.......' '.......' | + -- | | + -- | Heap | + -- .. | ..................................................... | .. + -- : | | : + -- : | Object Object Object Object | : + -- : +-> +------+ +------+ +------+ +------+ <-+ : + -- : | Prev <--> Prev <--> Prev | | Prev | : + -- : +------+ +------+ +------+ +------+ : + -- : | Next <--> Next <--> Next | | Next | : + -- : +------+ +------+ +------+ +------+ : + -- : | FA | | FA | | FA | | FA | : + -- : +------+ +------+ +------+ +------+ : + -- : : : : : : : : : : + -- : : : : : : : : : : + -- : '......' '......' '......' '......' : + -- : : + -- '.............................................................' + + -- Subpool list types. Each pool_with_subpools contains a list of subpools. + + type SP_Node; + type SP_Node_Ptr is access all SP_Node; + + type SP_Node is record + Prev : SP_Node_Ptr := null; + Next : SP_Node_Ptr := null; + Subpool : Subpool_Handle := null; + end record; + + -- Root_Storage_Pool_With_Subpools internal structure + + type Root_Storage_Pool_With_Subpools is abstract + new Root_Storage_Pool with + record + Initialized : Boolean := False; + pragma Atomic (Initialized); + -- Even though this type is derived from Limited_Controlled, overriding + -- Initialize would have no effect since the type is abstract. Routine + -- Set_Pool_Of_Subpool is tasked with the initialization of a pool with + -- subpools because it has to be called at some point. This flag is used + -- to prevent the resetting of the subpool chain. + + Subpools : aliased SP_Node; + -- A doubly linked list of subpools + + Finalization_Started : Boolean := False; + pragma Atomic (Finalization_Started); + -- A flag which prevents the creation of new subpools while the master + -- pool is being finalized. The flag needs to be atomic because it is + -- accessed without Lock_Task / Unlock_Task. + end record; + + type Any_Storage_Pool_With_Subpools_Ptr + is access all Root_Storage_Pool_With_Subpools'Class; + for Any_Storage_Pool_With_Subpools_Ptr'Storage_Size use 0; + + -- A subpool is an abstraction layer which sits on top of a pool. It + -- contains links to all controlled objects allocated on a particular + -- subpool. + + type Root_Subpool is abstract tagged limited record + Owner : Any_Storage_Pool_With_Subpools_Ptr := null; + -- A reference to the master pool_with_subpools + + Master : aliased System.Finalization_Masters.Finalization_Master; + -- A collection of controlled objects + end record; + + -- ??? Once Storage_Pools.Allocate_Any is removed, this should be renamed + -- to Allocate_Any. + + procedure Allocate_Any_Controlled + (Pool : in out Root_Storage_Pool'Class; + Context_Subpool : Subpool_Handle := null; + Context_Master : Finalization_Masters.Finalization_Master_Ptr := null; + Fin_Address : Finalization_Masters.Finalize_Address_Ptr := null; + Addr : out System.Address; + Storage_Size : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count; + Is_Controlled : Boolean := True); + -- Compiler interface. This version of Allocate handles all possible cases, + -- either on a pool or a pool_with_subpools. + + procedure Deallocate_Any_Controlled + (Pool : in out Root_Storage_Pool'Class; + Addr : System.Address; + Storage_Size : System.Storage_Elements.Storage_Count; + Alignment : System.Storage_Elements.Storage_Count; + Is_Controlled : Boolean := True); + -- Compiler interface. This version of Deallocate handles all possible + -- cases, either from a pool or a pool_with_subpools. + + overriding procedure Finalize + (Pool : in out Root_Storage_Pool_With_Subpools); + -- Iterate over all subpools of Pool, detach them one by one and finalize + -- their masters. This action first detaches a controlled object from a + -- particular master, then invokes its Finalize_Address primitive. + + procedure Finalize_Subpool (Subpool : not null Subpool_Handle); + -- Finalize the master of a subpool + +end System.Storage_Pools.Subpools; Index: a-undesu.adb =================================================================== --- a-undesu.adb (revision 0) +++ a-undesu.adb (revision 0) @@ -0,0 +1,36 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- A D A . U N C H E C K E D _ D E A L L O C A T E _ S U B P O O L -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. In accordance with the copyright of that document, you can freely -- +-- copy and modify this specification, provided that if you redistribute a -- +-- modified version, any changes that you have made are clearly indicated. -- +-- -- +------------------------------------------------------------------------------ + +-- ??? What is the header version here, see a-uncdea.adb. No GPL? + +with System.Storage_Pools.Subpools; use System.Storage_Pools.Subpools; + +procedure Ada.Unchecked_Deallocate_Subpool + (Subpool : in out System.Storage_Pools.Subpools.Subpool_Handle) +is +begin + -- Finalize all controlled objects allocated on the input subpool + + -- ??? It is awkward to create a child of Storage_Pools.Subpools for the + -- sole purpose of exporting Finalize_Subpool. + +-- Finalize_Subpool (Subpool); + + -- Dispatch to the user-defined implementation of Deallocate_Subpool + + Deallocate_Subpool (Pool_Of_Subpool (Subpool).all, Subpool); +end Ada.Unchecked_Deallocate_Subpool; Index: a-undesu.ads =================================================================== --- a-undesu.ads (revision 0) +++ a-undesu.ads (revision 0) @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- A D A . U N C H E C K E D _ D E A L L O C A T E _ S U B P O O L -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. In accordance with the copyright of that document, you can freely -- +-- copy and modify this specification, provided that if you redistribute a -- +-- modified version, any changes that you have made are clearly indicated. -- +-- -- +------------------------------------------------------------------------------ + +-- ??? What is the header version here, see a-uncdea.ads. No GPL? + +with System.Storage_Pools.Subpools; + +procedure Ada.Unchecked_Deallocate_Subpool + (Subpool : in out System.Storage_Pools.Subpools.Subpool_Handle); Index: exp_ch4.adb =================================================================== --- exp_ch4.adb (revision 178163) +++ exp_ch4.adb (working copy) @@ -444,12 +444,15 @@ return; end if; + -- ??? Now that finalization masters act as heterogeneous lists, it + -- might be worthed to revisit the global master approach. + -- Processing for anonymous access-to-controlled types. These access - -- types receive a special collection which appears on the declarations - -- of the enclosing semantic unit. + -- types receive a special finalization master which appears in the + -- declarations of the enclosing semantic unit. if Ekind (Ptr_Typ) = E_Anonymous_Access_Type - and then No (Associated_Collection (Ptr_Typ)) + and then No (Finalization_Master (Ptr_Typ)) and then (not Restriction_Active (No_Nested_Finalization) or else Is_Library_Level_Entity (Ptr_Typ)) @@ -466,7 +469,7 @@ Scop := Corresponding_Spec (Parent (Parent (Parent (Scop)))); end if; - Build_Finalization_Collection + Build_Finalization_Master (Typ => Ptr_Typ, Ins_Node => First_Declaration_Of_Current_Unit, Encl_Scope => Scop); @@ -481,7 +484,7 @@ -- Since the temporary object reuses the original allocator, generate a -- custom Allocate routine for the temporary. - if Present (Associated_Collection (Ptr_Typ)) then + if Present (Finalization_Master (Ptr_Typ)) then Build_Allocate_Deallocate_Proc (N => Temp_Decl, Is_Allocate => True); @@ -858,14 +861,14 @@ Complete_Controlled_Allocation (Temp_Decl); Convert_Aggr_In_Allocator (N, Temp_Decl, Exp); - -- Attach the object to the associated finalization collection. + -- Attach the object to the associated finalization master. -- This is done manually on .NET/JVM since those compilers do -- no support pools and can't benefit from internally generated -- Allocate / Deallocate procedures. if VM_Target /= No_VM and then Is_Controlled (DesigT) - and then Present (Associated_Collection (PtrT)) + and then Present (Finalization_Master (PtrT)) then Insert_Action (N, Make_Attach_Call ( @@ -888,14 +891,14 @@ Insert_Action (N, Temp_Decl); Complete_Controlled_Allocation (Temp_Decl); - -- Attach the object to the associated finalization collection. + -- Attach the object to the associated finalization master. -- This is done manually on .NET/JVM since those compilers do -- no support pools and can't benefit from internally generated -- Allocate / Deallocate procedures. if VM_Target /= No_VM and then Is_Controlled (DesigT) - and then Present (Associated_Collection (PtrT)) + and then Present (Finalization_Master (PtrT)) then Insert_Action (N, Make_Attach_Call ( @@ -931,8 +934,7 @@ -- Inherit the allocation-related attributes from the original -- access type. - Set_Associated_Collection (Def_Id, - Associated_Collection (PtrT)); + Set_Finalization_Master (Def_Id, Finalization_Master (PtrT)); Set_Associated_Storage_Pool (Def_Id, Associated_Storage_Pool (PtrT)); @@ -1083,25 +1085,6 @@ Prefix => New_Reference_To (Temp, Loc))), Typ => T)); end if; - - -- Generate: - -- Set_Finalize_Address_Ptr - -- (Collection, 'Unrestricted_Access) - - -- Since .NET/JVM compilers do not support address arithmetic, - -- this call is skipped. The same is done for CodePeer because - -- Finalize_Address is never generated. - - if VM_Target = No_VM - and then not CodePeer_Mode - and then Present (Associated_Collection (PtrT)) - then - Insert_Action (N, - Make_Set_Finalize_Address_Ptr_Call - (Loc => Loc, - Typ => T, - Ptr_Typ => PtrT)); - end if; end if; Rewrite (N, New_Reference_To (Temp, Loc)); @@ -1139,14 +1122,14 @@ Complete_Controlled_Allocation (Temp_Decl); Convert_Aggr_In_Allocator (N, Temp_Decl, Exp); - -- Attach the object to the associated finalization collection. This - -- is done manually on .NET/JVM since those compilers do no support + -- Attach the object to the associated finalization master. Thisis + -- done manually on .NET/JVM since those compilers do no support -- pools and cannot benefit from internally generated Allocate and -- Deallocate procedures. if VM_Target /= No_VM and then Is_Controlled (DesigT) - and then Present (Associated_Collection (PtrT)) + and then Present (Finalization_Master (PtrT)) then Insert_Action (N, Make_Attach_Call @@ -3564,7 +3547,7 @@ -- do not support pools, this step is skipped. if VM_Target = No_VM - and then Present (Associated_Collection (PtrT)) + and then Present (Finalization_Master (PtrT)) then Build_Allocate_Deallocate_Proc (N => Parent (N), @@ -3858,39 +3841,22 @@ (Obj_Ref => New_Copy_Tree (Init_Arg1), Typ => T)); - if Present (Associated_Collection (PtrT)) then + -- Special processing for .NET/JVM, the allocated object is + -- attached to the finalization master. Generate: - -- Special processing for .NET/JVM, the allocated object - -- is attached to the finalization collection. Generate: + -- Attach (FM, Root_Controlled_Ptr (Init_Arg1)); - -- Attach (FC, Root_Controlled_Ptr (Init_Arg1)); + -- Types derived from [Limited_]Controlled are the only + -- ones considered since they have fields Prev and Next. - -- Types derived from [Limited_]Controlled are the only - -- ones considered since they have fields Prev and Next. - - if VM_Target /= No_VM then - if Is_Controlled (T) then - Insert_Action (N, - Make_Attach_Call - (Obj_Ref => New_Copy_Tree (Init_Arg1), - Ptr_Typ => PtrT)); - end if; - - -- Default case, generate: - - -- Set_Finalize_Address_Ptr - -- (Pool, 'Unrestricted_Access) - - -- Do not generate the above for CodePeer compilations - -- because Finalize_Address is never built. - - elsif not CodePeer_Mode then - Insert_Action (N, - Make_Set_Finalize_Address_Ptr_Call - (Loc => Loc, - Typ => T, - Ptr_Typ => PtrT)); - end if; + if VM_Target /= No_VM + and then Present (Finalization_Master (PtrT)) + and then Is_Controlled (T) + then + Insert_Action (N, + Make_Attach_Call + (Obj_Ref => New_Copy_Tree (Init_Arg1), + Ptr_Typ => PtrT)); end if; end if; Index: s-stopoo.adb =================================================================== --- s-stopoo.adb (revision 178155) +++ s-stopoo.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 2009 Free Software Foundation, Inc. -- +-- Copyright (C) 2009-2011, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -37,13 +37,12 @@ procedure Allocate_Any (Pool : in out Root_Storage_Pool'Class; - Storage_Address : out Address; + Storage_Address : out System.Address; Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count) is begin - Allocate - (Pool, Storage_Address, Size_In_Storage_Elements, Alignment); + Allocate (Pool, Storage_Address, Size_In_Storage_Elements, Alignment); end Allocate_Any; -------------------- @@ -52,12 +51,12 @@ procedure Deallocate_Any (Pool : in out Root_Storage_Pool'Class; - Storage_Address : Address; + Storage_Address : System.Address; Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count) is begin - Deallocate - (Pool, Storage_Address, Size_In_Storage_Elements, Alignment); + Deallocate (Pool, Storage_Address, Size_In_Storage_Elements, Alignment); end Deallocate_Any; + end System.Storage_Pools; Index: s-stopoo.ads =================================================================== --- s-stopoo.ads (revision 178155) +++ s-stopoo.ads (working copy) @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2009, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2011, Free Software Foundation, Inc. -- -- -- -- This specification is derived from the Ada Reference Manual for use with -- -- GNAT. The copyright notice above, and the license provisions that follow -- @@ -44,14 +44,14 @@ procedure Allocate (Pool : in out Root_Storage_Pool; - Storage_Address : out Address; + Storage_Address : out System.Address; Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count) is abstract; procedure Deallocate (Pool : in out Root_Storage_Pool; - Storage_Address : Address; + Storage_Address : System.Address; Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count) is abstract; @@ -62,6 +62,13 @@ is abstract; private + type Root_Storage_Pool is abstract + new Ada.Finalization.Limited_Controlled with null record; + + -- ??? Are these two still needed? It might be possible to use Subpools. + -- Allocate_Any_Controlled / Deallocate_Any_Controlled for non-controlled + -- objects. + -- The following two procedures support the use of class-wide pool -- objects in storage pools. When a local type is given a class-wide -- storage pool, allocation and deallocation for the type must dispatch @@ -71,16 +78,14 @@ procedure Allocate_Any (Pool : in out Root_Storage_Pool'Class; - Storage_Address : out Address; + Storage_Address : out System.Address; Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count); procedure Deallocate_Any (Pool : in out Root_Storage_Pool'Class; - Storage_Address : Address; + Storage_Address : System.Address; Size_In_Storage_Elements : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count); - type Root_Storage_Pool is abstract - new Ada.Finalization.Limited_Controlled with null record; end System.Storage_Pools; Index: exp_ch6.adb =================================================================== --- exp_ch6.adb (revision 178155) +++ exp_ch6.adb (working copy) @@ -110,14 +110,14 @@ -- Adds Extra_Actual as a named parameter association for the formal -- Extra_Formal in Subprogram_Call. - procedure Add_Collection_Actual_To_Build_In_Place_Call + procedure Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call : Node_Id; Func_Id : Entity_Id; Ptr_Typ : Entity_Id := Empty); -- Ada 2005 (AI-318-02): If the result type of a build-in-place call needs -- finalization actions, add an actual parameter which is a pointer to the - -- finalization collection of the caller. If Ptr_Typ is left Empty, this - -- will result in an automatic "null" value for the actual. + -- finalization master of the caller. If Ptr_Typ is left Empty, this will + -- result in an automatic "null" value for the actual. procedure Add_Task_Actuals_To_Build_In_Place_Call (Function_Call : Node_Id; @@ -340,30 +340,30 @@ (Function_Call, Alloc_Form_Formal, Alloc_Form_Actual); end Add_Alloc_Form_Actual_To_Build_In_Place_Call; - -------------------------------------------------- - -- Add_Collection_Actual_To_Build_In_Place_Call -- - -------------------------------------------------- + ----------------------------------------------------------- + -- Add_Finalization_Master_Actual_To_Build_In_Place_Call -- + ----------------------------------------------------------- - procedure Add_Collection_Actual_To_Build_In_Place_Call + procedure Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call : Node_Id; Func_Id : Entity_Id; Ptr_Typ : Entity_Id := Empty) is begin - if not Needs_BIP_Collection (Func_Id) then + if not Needs_BIP_Finalization_Master (Func_Id) then return; end if; declare Formal : constant Entity_Id := - Build_In_Place_Formal (Func_Id, BIP_Collection); + Build_In_Place_Formal (Func_Id, BIP_Finalization_Master); Loc : constant Source_Ptr := Sloc (Func_Call); Actual : Node_Id; Desig_Typ : Entity_Id; begin - -- Case where the context does not require an actual collection + -- Case where the context does not require an actual master if No (Ptr_Typ) then Actual := Make_Null (Loc); @@ -372,9 +372,9 @@ Desig_Typ := Directly_Designated_Type (Ptr_Typ); -- Check for a library-level access type whose designated type has - -- supressed finalization. Such an access types lack a collection. + -- supressed finalization. Such an access types lack a master. -- Pass a null actual to the callee in order to signal a missing - -- collection. + -- master. if Is_Library_Level_Entity (Ptr_Typ) and then Finalize_Storage_Only (Desig_Typ) @@ -385,28 +385,28 @@ elsif Needs_Finalization (Desig_Typ) then - -- The general mechanism of creating finalization collections - -- for anonymous access types is disabled by default, otherwise - -- collections will pop all over the place. Such types use - -- context-specific collections. + -- The general mechanism of creating finalization masters for + -- anonymous access types is disabled by default, otherwise + -- finalization masters will pop all over the place. Such types + -- use context-specific masters. if Ekind (Ptr_Typ) = E_Anonymous_Access_Type - and then No (Associated_Collection (Ptr_Typ)) + and then No (Finalization_Master (Ptr_Typ)) then - Build_Finalization_Collection + Build_Finalization_Master (Typ => Ptr_Typ, Ins_Node => Associated_Node_For_Itype (Ptr_Typ), Encl_Scope => Scope (Ptr_Typ)); end if; - -- Access-to-controlled types should always have a collection + -- Access-to-controlled types should always have a master - pragma Assert (Present (Associated_Collection (Ptr_Typ))); + pragma Assert (Present (Finalization_Master (Ptr_Typ))); Actual := Make_Attribute_Reference (Loc, Prefix => - New_Reference_To (Associated_Collection (Ptr_Typ), Loc), + New_Reference_To (Finalization_Master (Ptr_Typ), Loc), Attribute_Name => Name_Unrestricted_Access); -- Tagged types @@ -423,7 +423,7 @@ Add_Extra_Actual_To_Call (Func_Call, Formal, Actual); end; - end Add_Collection_Actual_To_Build_In_Place_Call; + end Add_Finalization_Master_Actual_To_Build_In_Place_Call; ------------------------------ -- Add_Extra_Actual_To_Call -- @@ -559,15 +559,15 @@ function BIP_Formal_Suffix (Kind : BIP_Formal_Kind) return String is begin case Kind is - when BIP_Alloc_Form => + when BIP_Alloc_Form => return "BIPalloc"; - when BIP_Collection => - return "BIPcollection"; - when BIP_Master => + when BIP_Finalization_Master => + return "BIPfinalizationmaster"; + when BIP_Master => return "BIPmaster"; - when BIP_Activation_Chain => + when BIP_Activation_Chain => return "BIPactivationchain"; - when BIP_Object_Access => + when BIP_Object_Access => return "BIPaccess"; end case; end BIP_Formal_Suffix; @@ -2105,10 +2105,10 @@ end if; end if; - -- Detect the following code in Ada.Finalization.Heap_Management only - -- on .NET/JVM targets: + -- Detect the following code in System.Finalization_Masters only on + -- .NET/JVM targets: -- - -- procedure Finalize (Collection : in out Finalization_Collection) is + -- procedure Finalize (Master : in out Finalization_Master) is -- begin -- . . . -- begin @@ -2124,7 +2124,7 @@ and then Ekind (Scope (Curr_S)) = E_Procedure and then Chars (Scope (Curr_S)) = Name_Finalize and then Etype (First_Formal (Scope (Curr_S))) = - RTE (RE_Finalization_Collection) + RTE (RE_Finalization_Master) then declare Deep_Fin : constant Entity_Id := @@ -4393,20 +4393,20 @@ Ret_Typ : Entity_Id; Alloc_Expr : Node_Id) return Node_Id; -- Create the statements necessary to allocate a return object on the - -- caller's collection. The collection is available through implicit - -- parameter BIPcollection. + -- caller's master. The master is available through implicit parameter + -- BIPfinalizationmaster. -- - -- if BIPcollection /= null then + -- if BIPfinalizationmaster /= null then -- declare -- type Ptr_Typ is access Ret_Typ; -- for Ptr_Typ'Storage_Pool use - -- Base_Pool (BIPcollection.all).all; + -- Base_Pool (BIPfinalizationmaster.all).all; -- Local : Ptr_Typ; -- -- begin -- procedure Allocate (...) is -- begin - -- Ada.Finalization.Heap_Management.Allocate (...); + -- System.Storage_Pools.Subpools.Allocate_Any (...); -- end Allocate; -- -- Local := ; @@ -4439,17 +4439,18 @@ is begin -- Processing for build-in-place object allocation. This is disabled - -- on .NET/JVM because pools are not supported. + -- on .NET/JVM because the targets do not support pools. if VM_Target = No_VM and then Is_Build_In_Place_Function (Func_Id) and then Needs_Finalization (Ret_Typ) then declare - Collect : constant Entity_Id := - Build_In_Place_Formal (Func_Id, BIP_Collection); - Decls : constant List_Id := New_List; - Stmts : constant List_Id := New_List; + Decls : constant List_Id := New_List; + Fin_Mas_Id : constant Entity_Id := + Build_In_Place_Formal + (Func_Id, BIP_Finalization_Master); + Stmts : constant List_Id := New_List; Local_Id : Entity_Id; Pool_Id : Entity_Id; @@ -4457,7 +4458,7 @@ begin -- Generate: - -- Pool_Id renames Base_Pool (BIPcollection.all).all; + -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all; Pool_Id := Make_Temporary (Loc, 'P'); @@ -4474,11 +4475,12 @@ New_Reference_To (RTE (RE_Base_Pool), Loc), Parameter_Associations => New_List ( Make_Explicit_Dereference (Loc, - Prefix => New_Reference_To (Collect, Loc))))))); + Prefix => + New_Reference_To (Fin_Mas_Id, Loc))))))); -- Create an access type which uses the storage pool of the - -- caller's collection. This additional type is necessary - -- because the collection cannot be associated with the type + -- caller's master. This additional type is necessary because + -- the finalization master cannot be associated with the type -- of the temporary. Otherwise the secondary stack allocation -- will fail. @@ -4495,11 +4497,11 @@ Subtype_Indication => New_Reference_To (Ret_Typ, Loc)))); - -- Perform minor decoration in order to set the collection and - -- the storage pool attributes. + -- Perform minor decoration in order to set the master and the + -- storage pool attributes. Set_Ekind (Ptr_Typ, E_Access_Type); - Set_Associated_Collection (Ptr_Typ, Collect); + Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id); Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id); -- Create the temporary, generate: @@ -4534,12 +4536,12 @@ New_Reference_To (Local_Id, Loc)))); -- Wrap the allocation in a block. This is further conditioned - -- by checking the caller collection at runtime. A null value - -- indicates a non-existent collection, most likely due to a - -- Finalize_Storage_Only allocation. + -- by checking the caller finalization master at runtime. A + -- null value indicates a non-existent master, most likely due + -- to a Finalize_Storage_Only allocation. -- Generate: - -- if BIPcollection /= null then + -- if BIPfinalizationmaster /= null then -- declare -- -- begin @@ -4551,7 +4553,7 @@ Make_If_Statement (Loc, Condition => Make_Op_Ne (Loc, - Left_Opnd => New_Reference_To (Collect, Loc), + Left_Opnd => New_Reference_To (Fin_Mas_Id, Loc), Right_Opnd => Make_Null (Loc)), Then_Statements => New_List ( @@ -7110,7 +7112,7 @@ Add_Alloc_Form_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Alloc_Form => Caller_Allocation); - Add_Collection_Actual_To_Build_In_Place_Call + Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Acc_Type); Add_Task_Actuals_To_Build_In_Place_Call @@ -7144,7 +7146,7 @@ Add_Alloc_Form_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Alloc_Form => Global_Heap); - Add_Collection_Actual_To_Build_In_Place_Call + Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Acc_Type); Add_Task_Actuals_To_Build_In_Place_Call @@ -7157,33 +7159,6 @@ (Func_Call, Function_Id, Return_Object => Empty); end if; - -- If the build-in-place function call returns a controlled object, the - -- finalization collection will require a reference to routine Finalize_ - -- Address of the designated type. Setting this attribute is done in the - -- same manner to expansion of allocators. - - if Needs_Finalization (Result_Subt) then - - -- Controlled types with supressed finalization do not need to - -- associate the address of their Finalize_Address primitives with a - -- collection since they do not need a collection to begin with. - - if Is_Library_Level_Entity (Acc_Type) - and then Finalize_Storage_Only (Result_Subt) - then - null; - - -- Do not generate the call to Make_Set_Finalize_Address_Ptr for - -- CodePeer compilations because Finalize_Address is never built. - - elsif not CodePeer_Mode then - Insert_Action (Allocator, - Make_Set_Finalize_Address_Ptr_Call (Loc, - Typ => Etype (Function_Id), - Ptr_Typ => Acc_Type)); - end if; - end if; - -- Finally, replace the allocator node with a reference to the result -- of the function call itself (which will effectively be an access -- to the object created by the allocator). @@ -7310,7 +7285,7 @@ Add_Alloc_Form_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Alloc_Form => Caller_Allocation); - Add_Collection_Actual_To_Build_In_Place_Call + Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call, Function_Id); Add_Task_Actuals_To_Build_In_Place_Call @@ -7334,7 +7309,7 @@ Add_Alloc_Form_Actual_To_Build_In_Place_Call (Func_Call, Function_Id, Alloc_Form => Secondary_Stack); - Add_Collection_Actual_To_Build_In_Place_Call + Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call, Function_Id); Add_Task_Actuals_To_Build_In_Place_Call @@ -7412,7 +7387,7 @@ Add_Alloc_Form_Actual_To_Build_In_Place_Call (Func_Call, Func_Id, Alloc_Form => Caller_Allocation); - Add_Collection_Actual_To_Build_In_Place_Call + Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call, Func_Id); Add_Task_Actuals_To_Build_In_Place_Call @@ -7625,7 +7600,7 @@ Establish_Transient_Scope (Object_Decl, Sec_Stack => True); end if; - Add_Collection_Actual_To_Build_In_Place_Call + Add_Finalization_Master_Actual_To_Build_In_Place_Call (Func_Call, Function_Id); if Nkind (Parent (Object_Decl)) = N_Extended_Return_Statement @@ -7773,11 +7748,13 @@ end if; end Make_Build_In_Place_Call_In_Object_Declaration; - -------------------------- - -- Needs_BIP_Collection -- - -------------------------- + ----------------------------------- + -- Needs_BIP_Finalization_Master -- + ----------------------------------- - function Needs_BIP_Collection (Func_Id : Entity_Id) return Boolean is + function Needs_BIP_Finalization_Master + (Func_Id : Entity_Id) return Boolean + is pragma Assert (Is_Build_In_Place_Function (Func_Id)); Func_Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id)); @@ -7785,6 +7762,6 @@ return not Restriction_Active (No_Finalization) and then Needs_Finalization (Func_Typ); - end Needs_BIP_Collection; + end Needs_BIP_Finalization_Master; end Exp_Ch6; Index: exp_ch6.ads =================================================================== --- exp_ch6.ads (revision 178155) +++ exp_ch6.ads (working copy) @@ -68,9 +68,9 @@ -- caller or callee, and if the callee, whether to use the secondary -- stack or the heap. See Create_Extra_Formals. - BIP_Collection, + BIP_Finalization_Master, -- Present if result type needs finalization. Pointer to caller's - -- finalization collection. + -- finalization master. BIP_Master, -- Present if result type contains tasks. Master associated with @@ -163,8 +163,8 @@ -- for which Is_Build_In_Place_Call is True, or an N_Qualified_Expression -- node applied to such a function call. - function Needs_BIP_Collection (Func_Id : Entity_Id) return Boolean; + function Needs_BIP_Finalization_Master (Func_Id : Entity_Id) return Boolean; -- Ada 2005 (AI-318-02): Return True if the function needs a finalization - -- collection implicit parameter. + -- master implicit parameter. end Exp_Ch6; Index: exp_ch13.adb =================================================================== --- exp_ch13.adb (revision 178155) +++ exp_ch13.adb (working copy) @@ -230,7 +230,7 @@ return; end if; - -- Use the base type to perform the collection check + -- Use the base type to perform the check for finalization master Typ := Etype (Expr); @@ -248,10 +248,10 @@ -- Do not create a custom Deallocate when freeing an object with -- suppressed finalization. In such cases the object is never attached - -- to a collection, so it does not need to be detached. Use a regular - -- free statement instead. + -- to a master, so it does not need to be detached. Use a regular free + -- statement instead. - if No (Associated_Collection (Typ)) then + if No (Finalization_Master (Typ)) then return; end if; Index: sem_ch6.adb =================================================================== --- sem_ch6.adb (revision 178165) +++ sem_ch6.adb (working copy) @@ -6080,14 +6080,13 @@ end if; -- In the case of functions whose result type needs finalization, - -- add an extra formal of type Ada.Finalization.Heap_Management. - -- Finalization_Collection_Ptr. + -- add an extra formal which represents the finalization master. - if Needs_BIP_Collection (E) then + if Needs_BIP_Finalization_Master (E) then Discard := Add_Extra_Formal - (E, RTE (RE_Finalization_Collection_Ptr), - E, BIP_Formal_Suffix (BIP_Collection)); + (E, RTE (RE_Finalization_Master_Ptr), + E, BIP_Formal_Suffix (BIP_Finalization_Master)); end if; -- If the result type contains tasks, we have two extra formals: Index: Makefile.rtl =================================================================== --- Makefile.rtl (revision 178155) +++ Makefile.rtl (working copy) @@ -154,7 +154,6 @@ a-envvar$(objext) \ a-except$(objext) \ a-exctra$(objext) \ - a-fihema$(objext) \ a-finali$(objext) \ a-flteio$(objext) \ a-fwteio$(objext) \ @@ -290,6 +289,7 @@ a-tiunio$(objext) \ a-unccon$(objext) \ a-uncdea$(objext) \ + a-undesu$(objext) \ a-wichha$(objext) \ a-wichun$(objext) \ a-widcha$(objext) \ @@ -495,6 +495,7 @@ s-ficobl$(objext) \ s-fileio$(objext) \ s-filofl$(objext) \ + s-finmas$(objext) \ s-finroo$(objext) \ s-fishfl$(objext) \ s-flocon$(objext) \ @@ -611,6 +612,7 @@ s-stchop$(objext) \ s-stoele$(objext) \ s-stopoo$(objext) \ + s-stposu$(objext) \ s-stratt$(objext) \ s-strhas$(objext) \ s-string$(objext) \ Index: s-finmas.adb =================================================================== --- s-finmas.adb (revision 0) +++ s-finmas.adb (revision 0) @@ -0,0 +1,214 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . F I N A L I Z A T I O N _ M A S T E R S -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with Ada.Exceptions; use Ada.Exceptions; + +with System.Soft_Links; use System.Soft_Links; +with System.Storage_Elements; use System.Storage_Elements; + +package body System.Finalization_Masters is + + --------------------------- + -- Add_Offset_To_Address -- + --------------------------- + + function Add_Offset_To_Address + (Addr : System.Address; + Offset : System.Storage_Elements.Storage_Offset) return System.Address + is + begin + return System.Storage_Elements."+" (Addr, Offset); + end Add_Offset_To_Address; + + ------------ + -- Attach -- + ------------ + + procedure Attach (N : not null FM_Node_Ptr; L : not null FM_Node_Ptr) is + begin + Lock_Task.all; + + L.Next.Prev := N; + N.Next := L.Next; + L.Next := N; + N.Prev := L; + + Unlock_Task.all; + + -- Note: No need to unlock in case of an exception because the above + -- code can never raise one. + end Attach; + + --------------- + -- Base_Pool -- + --------------- + + function Base_Pool + (Master : Finalization_Master) return Any_Storage_Pool_Ptr + is + begin + return Master.Base_Pool; + end Base_Pool; + + ------------ + -- Detach -- + ------------ + + procedure Detach (N : not null FM_Node_Ptr) is + begin + -- N must be attached to some list + + pragma Assert (N.Next /= null and then N.Prev /= null); + + Lock_Task.all; + + N.Prev.Next := N.Next; + N.Next.Prev := N.Prev; + + Unlock_Task.all; + + -- Note: No need to unlock in case of an exception because the above + -- code can never raise one. + end Detach; + + -------------- + -- Finalize -- + -------------- + + overriding procedure Finalize (Master : in out Finalization_Master) is + Curr_Ptr : FM_Node_Ptr; + Ex_Occur : Exception_Occurrence; + Obj_Addr : Address; + Raised : Boolean := False; + + begin + -- It is possible for multiple tasks to cause the finalization of the + -- same master. Let only one task finalize the objects. + + if Master.Finalization_Started then + return; + end if; + + -- Lock the master to prevent any allocations while the objects are + -- being finalized. The master remains locked because either the master + -- is explicitly deallocated or the associated access type is about to + -- go out of scope. + + Master.Finalization_Started := True; + + -- Skip the dummy head + + Curr_Ptr := Master.Objects.Next; + while Curr_Ptr /= Master.Objects'Unchecked_Access loop + begin + -- If primitive Finalize_Address is not set, then the expansion of + -- the designated type or that of the allocator failed. This is a + -- serious error. + + -- Note: The Program_Error must be raised from the same block as + -- the finalization call. If Finalize_Address is not present for + -- a particular object, this should not stop the finalization of + -- the remaining objects. + + if Curr_Ptr.Finalize_Address = null then + raise Program_Error + with "primitive Finalize_Address not available"; + + -- Skip the list header in order to offer proper object layout for + -- finalization and call Finalize_Address. + + else + Obj_Addr := Curr_Ptr.all'Address + Header_Offset; + Curr_Ptr.Finalize_Address (Obj_Addr); + end if; + + exception + when Fin_Occur : others => + if not Raised then + Raised := True; + Save_Occurrence (Ex_Occur, Fin_Occur); + end if; + end; + + Curr_Ptr := Curr_Ptr.Next; + end loop; + + -- If the finalization of a particular object failed or Finalize_Address + -- was not set, reraise the exception now. + + if Raised then + Reraise_Occurrence (Ex_Occur); + end if; + end Finalize; + + ----------------- + -- Header_Size -- + ----------------- + + function Header_Size return System.Storage_Elements.Storage_Count is + begin + return FM_Node'Size / Storage_Unit; + end Header_Size; + + ------------------- + -- Header_Offset -- + ------------------- + + function Header_Offset return System.Storage_Elements.Storage_Offset is + begin + return FM_Node'Size / Storage_Unit; + end Header_Offset; + + ---------------- + -- Initialize -- + ---------------- + + overriding procedure Initialize (Master : in out Finalization_Master) is + begin + -- The dummy head must point to itself in both directions + + Master.Objects.Next := Master.Objects'Unchecked_Access; + Master.Objects.Prev := Master.Objects'Unchecked_Access; + end Initialize; + + ------------------- + -- Set_Base_Pool -- + ------------------- + + procedure Set_Base_Pool + (Master : in out Finalization_Master; + Pool_Ptr : Any_Storage_Pool_Ptr) + is + begin + Master.Base_Pool := Pool_Ptr; + end Set_Base_Pool; + +end System.Finalization_Masters; Index: s-finmas.ads =================================================================== --- s-finmas.ads (revision 0) +++ s-finmas.ads (revision 0) @@ -0,0 +1,135 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . F I N A L I Z A T I O N _ M A S T E R S -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with Ada.Finalization; +with Ada.Unchecked_Conversion; + +with System.Storage_Elements; +with System.Storage_Pools; + +package System.Finalization_Masters is + pragma Preelaborate (System.Finalization_Masters); + + -- A reference to primitive Finalize_Address. The expander generates an + -- implementation of this procedure for each controlled and class-wide + -- type. Since controlled objects are simply viewed as addresses once + -- allocated through a master, Finalize_Address provides a backward + -- indirection from an address to a type-specific context. + + type Finalize_Address_Ptr is access procedure (Obj : System.Address); + + -- Heterogeneous collection type structure. The implementation allows for + -- finalizable objects of different base types to be serviced by the same + -- master. + + type FM_Node; + type FM_Node_Ptr is access all FM_Node; + + type FM_Node is record + Prev : FM_Node_Ptr := null; + Next : FM_Node_Ptr := null; + Finalize_Address : Finalize_Address_Ptr := null; + end record; + + -- A reference to any derivation from Root_Storage_Pool. Since this type + -- may not be used to allocate objects, its storage size is zero. + + type Any_Storage_Pool_Ptr is + access System.Storage_Pools.Root_Storage_Pool'Class; + for Any_Storage_Pool_Ptr'Storage_Size use 0; + + -- Finalization master type structure. A unique master is associated with + -- each access-to-controlled or access-to-class-wide type. Masters also act + -- as components of subpools. + + type Finalization_Master is + new Ada.Finalization.Limited_Controlled with + record + Base_Pool : Any_Storage_Pool_Ptr := null; + -- A reference to the pool which this finalization master services. This + -- field is used in conjunction with the build-in-place machinery. + + Objects : aliased FM_Node; + -- A doubly linked list which contains the headers of all controlled + -- objects allocated in a [sub]pool. + + Finalization_Started : Boolean := False; + pragma Atomic (Finalization_Started); + -- A flag used to detect allocations which occur during the finalization + -- of a master. The allocations must raise Program_Error. This scenario + -- may arise in a multitask environment. The flag is atomic because it + -- is accessed without Lock_Task / Unlock_Task. + end record; + + type Finalization_Master_Ptr is access all Finalization_Master; + for Finalization_Master_Ptr'Storage_Size use 0; + + -- Since RTSfind cannot contain names of the form RE_"+", the following + -- routine serves as a wrapper around System.Storage_Elements."+". + + function Add_Offset_To_Address + (Addr : System.Address; + Offset : System.Storage_Elements.Storage_Offset) return System.Address; + + function Address_To_FM_Node_Ptr is + new Ada.Unchecked_Conversion (Address, FM_Node_Ptr); + + procedure Attach (N : not null FM_Node_Ptr; L : not null FM_Node_Ptr); + -- Prepend a node to a specific finalization master + + function Base_Pool + (Master : Finalization_Master) return Any_Storage_Pool_Ptr; + -- Return a reference to the underlying storage pool on which the master + -- operates. + + procedure Detach (N : not null FM_Node_Ptr); + -- Remove a node from an arbitrary finalization master + + overriding procedure Finalize (Master : in out Finalization_Master); + -- Lock the master to prevent allocations during finalization. Iterate over + -- the list of allocated controlled objects, finalizing each one by calling + -- its specific Finalize_Address. In the end, deallocate the dummy head. + + function Header_Size return System.Storage_Elements.Storage_Count; + -- Return the size of type FM_Node as Storage_Count + + function Header_Offset return System.Storage_Elements.Storage_Offset; + -- Return the size of type FM_Node as Storage_Offset + + overriding procedure Initialize (Master : in out Finalization_Master); + -- Initialize the dummy head of a finalization master + + procedure Set_Base_Pool + (Master : in out Finalization_Master; + Pool_Ptr : Any_Storage_Pool_Ptr); + -- Set the underlying pool of a finalization master + +end System.Finalization_Masters; Index: exp_ch3.adb =================================================================== --- exp_ch3.adb (revision 178176) +++ exp_ch3.adb (working copy) @@ -5482,12 +5482,13 @@ Build_Slice_Assignment (Typ); end if; - -- ??? This may not be necessary after all + -- ??? Now that masters acts as heterogeneous lists, it might be + -- worthed to revisit the global master approach. elsif Ekind (Comp_Typ) = E_Anonymous_Access_Type and then Needs_Finalization (Directly_Designated_Type (Comp_Typ)) then - Build_Finalization_Collection (Comp_Typ); + Build_Finalization_Master (Comp_Typ); end if; end if; @@ -5581,8 +5582,8 @@ return; end if; - -- Generate the body of Finalize_Address. This routine is accessible - -- through the TSS mechanism. + -- Create the body of TSS primitive Finalize_Address. This automatically + -- sets the TSS entry for the class-wide type. Make_Finalize_Address_Body (Typ); end Expand_Freeze_Class_Wide_Type; @@ -6310,13 +6311,17 @@ -- compiling a CPP tagged type. elsif not Restriction_Active (No_Dispatching_Calls) then - Predef_List := Predefined_Primitive_Bodies (Def_Id, Renamed_Eq); - Append_Freeze_Actions (Def_Id, Predef_List); - -- Create the body of Finalize_Address, a helper routine used in - -- conjunction with controlled objects on the heap. + -- Create the body of TSS primitive Finalize_Address. This must + -- be done before the bodies of all predefined primitives are + -- created. If Def_Id is limited, Stream_Input and Streap_Read + -- may produce build-in-place allocations and for that the + -- expander needs Finalize_Address. Make_Finalize_Address_Body (Def_Id); + + Predef_List := Predefined_Primitive_Bodies (Def_Id, Renamed_Eq); + Append_Freeze_Actions (Def_Id, Predef_List); end if; -- Ada 2005 (AI-391): If any wrappers were created for nonoverridden @@ -6364,7 +6369,7 @@ and then Directly_Designated_Type (Comp_Typ) /= Def_Id then - Build_Finalization_Collection + Build_Finalization_Master (Typ => Comp_Typ, Ins_Node => Parent (Def_Id), Encl_Scope => Scope (Def_Id)); @@ -6652,7 +6657,7 @@ and then not Is_Frozen (Desig_Type) and then Needs_Finalization (Component_Type (Desig_Type))) then - Build_Finalization_Collection (Def_Id); + Build_Finalization_Master (Def_Id); end if; end; @@ -8399,7 +8404,7 @@ end if; -- All tagged types receive their own Deep_Adjust and Deep_Finalize - -- regardless of whether they are controlled or contain controlled + -- regardless of whether they are controlled or may contain controlled -- components. -- Do not generate the routines if finalization is disabled @@ -8414,12 +8419,10 @@ else if not Is_Limited_Type (Tag_Typ) then - Append_To (Res, - Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Adjust)); + Append_To (Res, Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Adjust)); end if; - Append_To (Res, - Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize)); + Append_To (Res, Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize)); end if; Predef_List := Res; @@ -9028,9 +9031,9 @@ -- to be (implicitly) inherited in that case because it can lead to a VM -- exception. - -- Do not generate stream routines for type Finalization_Collection - -- because collection may never appear in types and therefore cannot be - -- read or written. + -- Do not generate stream routines for type Finalization_Master because + -- a master may never appear in types and therefore cannot be read or + -- written. return (not Is_Limited_Type (Typ) @@ -9053,7 +9056,7 @@ and then RTE_Available (RE_Tag) and then No (Type_Without_Stream_Operation (Typ)) and then RTE_Available (RE_Root_Stream_Type) - and then not Is_RTE (Typ, RE_Finalization_Collection); + and then not Is_RTE (Typ, RE_Finalization_Master); end Stream_Operation_OK; end Exp_Ch3;