Version 1.7 of ai05s/ai05-0193-1.txt
!standard 13.11(16) 10-06-06 AI05-0193-1/03
!standard 13.11(21)
!standard 13.11.1 (0)
!standard 13.11.1 (1)
!standard 13.11.1 (2)
!standard 13.11.1 (3)
!class amendment 09-11-03
!status Amendment 201Z 09-11-30
!status WG9 Approved 10-06-18
!status ARG Approved 10-0-1 09-11-08
!status work item 09-11-03
!status received 09-06-16
!priority Low
!difficulty Easy
!qualifier Omission
!subject Alignment of allocators
!summary
Ada implementations may request more strictly aligned data for allocators. In
addition, the attribute Max_Alignment_For_Allocation is added.
!problem
In the case of an allocator of access type whose Storage_Pool is user-defined,
RM 13.11(16) completely specifies the value of the Alignment parameter passed in
the associated call to Allocate.
This may be inappropriate in some cases. If an Ada implementation chooses to
allocate space for additional (typically contiguous) data, the alignment
requirements of this additional data may be stricter than the specified
Alignment value. In this case, the implementation should have the freedom to
pass in an Alignment value that reflects this requirement.
Consider the following example:
type T is access String;
for T'Storage_Pool use ... ;
X : T := new String'("abc");
In the case of an access type whose designated subtype is an unconstrained array
subtype, some implementations prepend contiguous dope information to the
allocated array. String'Alignment is typically 1. If the dope information
contains values of the array type's index type(s), then the alignment
requirement of this dope information might reasonably be that of the most
strictly aligned index type. The given example might be easier to implement if
the implementation were allowed to pass Integer'Alignment instead of
String'Alignment as the Alignment parameter in the call to Allocate associated
with the allocator.
As another example, consider the case of an implementation which (for whatever
reason - finalization or deallocation) chooses to maintain a linked list of the
allocated objects associated with an access type. Suppose further that the
implementation chooses to implement this by prepending contiguous linkage fields
to each allocated object. If the language definition requires passing in an
Alignment value less than System.Address'Alignment, this requirement can be
inconvenient.
As a third example, consider the case of an allocated coextension which has a
stricter alignment requirement than that of the access-discriminant-bearing
"owner" type.
The Max_Size_In_Storage_Elements attribute was designed to cope with all of these
issues as they relate to the value of the Size_In_Storage_Elements parameter
value that is passed to Allocate. An analogous attribute is needed for the
Alignment parameter.
!proposal
(see wording)
!wording
In the Implementation Requirements added by AI05-0107-1 (which replaces
paragraph 13.11(16)), replace
The Alignment parameter is D'Alignment if D is a specific type,
and otherwise is the alignment of the specific type identified by
the tag of the object being created.
with
The Alignment parameter is at least D'Alignment if D is a specific
type, and otherwise is at least the alignment of the specific type
identified by the tag of the object being created. The Alignment
parameter is no more than D'Max_Alignment_For_Allocation.
Completely replace 13.11.1 with
13.11.1 Storage Allocation Attributes
The Max_Size_In_Storage_Elements and Max_Alignment_For_Allocation
attributes may be useful in writing user-defined pool types.
Static Semantics
For every subtype S, the following attributes are defined:
S'Max_Size_In_Storage_Elements
Denotes the maximum value for Size_In_Storage_Elements that
could be requested by the implementation via Allocate for an
access type whose designated subtype is S. The value of this
attribute is of type universal_integer.
S'Max_Alignment_For_Allocation
Denotes the maximum value for Alignment that could be requested
by the implementation via Allocate for an access type whose
designated subtype is S. The value of this attribute is of type
universal_integer.
For a type with access discriminants, if the implementation
allocates space for a coextension in the same pool as that of the
object having the access discriminant, then these attributes account
for any calls on Allocate that could be performed to provide space for
such coextensions.
Update Annex K accordingly. [This is done automatically; we generally don't
mention changes to Annex K, L, M, P, and Q unless they don't appear anywhere
else. - ED.]
!discussion
We mention the lower bound on the value of the Alignment parameter mainly to explain
the purpose of the Alignment parameter. We could have used vaguer wording like that
used for the Size_In_Storage_Elements parameter:
The Size_In_Storage_Elements parameter indicates the number of
storage elements to be allocated, and is no more than
D'Max_Size_In_Storage_Elements, where D is the designated subtype.
But such wording would have the effect of eliminating any requirements on the parameter
(in particular those discussed in AI05-0116-1), and that is not intended by this AI.
The phrase "associated with these discriminants" is intended to include the case
of a coextension of a coextension.
!corrigendum 13.11(21)
@Comment{A partial change intended to force a conflict; the real text is found
in the conflict file. This only changes 13.11(21.5/3).}
Replace the paragraph:
For one of the calls of Allocate described above, P (equivalent to T'Storage_Pool)
is passed as the Pool parameter. The Size_In_Storage_Elements parameter indicates the
number of storage elements to be allocated, and is no more than
D'Max_Size_In_Storage_Elements, where D is the designated subtype of T.
The Alignment parameter is D'Alignment if D is a specific
type, and otherwise is the alignment of the specific type identified by
the tag of the object being created. The result returned in the Storage_Address parameter
is used as the address of the allocated storage, which is a contiguous block of memory
of Size_In_Storage_Elements storage elements. Any exception propagated
by Allocate is propagated by the construct that contained the call.
by:
For one of the calls of Allocate described above, P (equivalent to T'Storage_Pool)
is passed as the Pool parameter. The Size_In_Storage_Elements parameter indicates the
number of storage elements to be allocated, and is no more than
D'Max_Size_In_Storage_Elements, where D is the designated subtype of T.
The Alignment parameter is at least D'Alignment if D is a specific
type, and otherwise is at least the alignment of the specific type identified by
the tag of the object being created. The Alignment parameter is no more than
D'Max_Alignment_For_Allocation. The result returned in the Storage_Address parameter
is used as the address of the allocated storage, which is a contiguous block of memory
of Size_In_Storage_Elements storage elements. Any exception propagated
by Allocate is propagated by the construct that contained the call.
!corrigendum 13.11.1(0)
Replace the paragraph:
The Max_Size_In_Storage_Elements Attribute
by:
Storage Allocation Attributes
!corrigendum 13.11.1(1)
Replace the paragraph:
The Max_Size_In_Storage_Units attribute is useful in writing user-defined
pool types.
by:
The Max_Size_In_Storage_Units and Max_Alignment_For_Allocation
attributes may be useful in writing user-defined pool types.
!corrigendum 13.11.1(2)
Replace the paragraph:
For every subtype S, the following attribute is defined:
by:
For every subtype S, the following attributes are defined:
!corrigendum 13.11.1(3)
Replace the paragraph:
- S'Max_Size_In_Storage_Elements
-
Denotes the maximum value for Size_In_Storage_Elements that could be
requested by the implementation via Allocate for an access type whose
designated subtype is S. For a type with access discriminants, if the
implementation allocates space for a coextension in the same pool as
that of the object having the access discriminant, then this accounts
for any calls on Allocate that could be performed to provide space for
such coextensions. The value of this attribute is of type universal_integer.
by:
- S'Max_Size_In_Storage_Elements
-
Denotes the maximum value for Size_In_Storage_Elements that could be
requested by the implementation via Allocate for an access type whose
designated subtype is S. The value of this attribute is of type
universal_integer.
- S'Max_Alignment_For_Allocation
-
Denotes the maximum value for Alignment that could be requested
by the implementation via Allocate for an access type whose
designated subtype is S. The value of this attribute is of type
universal_integer.
For a type with access discriminants, if the implementation
allocates space for a coextension in the same pool as that of the
object having the access discriminant, then these attributes account
for any calls on Allocate that could be performed to provide space for
such coextensions.
!ACATS test
Create an ACATS C-Test to test the new attribute.
!appendix
From: Steve Baird
Sent: Tuesday, June 16, 2009 6:09 AM
[Posted version /01 of this AI. - ED]
****************************************************************
From: Tucker Taft
Sent: Tuesday, June 16, 2009 7:09 AM
I agree with this problem and your proposed solution.
I see no need for specifying a minimum alignment, since it is trivial to round
up to a greater alignment. On the other hand, if a storage allocator is
suddenly handed a bigger alignment than it was prepared for, that could be a
real pain, so I agree with defining an attribute that specifies the max. It
might also be nice to have a value in package Standard that specifies the
maximum value that this attribute would ever have, so that simple allocators can
simply return everything with that maximum alignment, and ignore the alignment
parameter completely.
****************************************************************
From: Bob Duff
Sent: Tuesday, June 16, 2009 9:50 AM
> It might also be nice to have
> a value in package Standard that specifies the maximum
^^^^^^^^
Maybe you mean package System?
> value that this attribute would ever have, so that simple allocators
> can simply return everything with that maximum alignment, and ignore
> the alignment parameter completely.
GNAT supports crazy stuff like:
for T'Alignment use 2**25;
so such a "simple allocator" would not be useful in GNAT. Doesn't mean such a
constant shouldn't exist in the language.
Maybe we want (instead or in addition) the max alignment the impl will pass to
an allocator when there are no user-specified Alignment clauses.
Which might not be quite the same as the max alignment of any type chosen by
default (but that might be useful, too).
****************************************************************
From: Tucker Taft
Sent: Tuesday, June 16, 2009 10:32 AM
>> It might also be nice to have
>> a value in package Standard that specifies the maximum
> ^^^^^^^^
> Maybe you mean package System?
Yes, I meant System.
>> value that this attribute would ever have, so that simple allocators
>> can simply return everything with that maximum alignment, and ignore
>> the alignment parameter completely.
>
> GNAT supports crazy stuff like:
>
> for T'Alignment use 2**25;
Really? I could imagine it accepting something like that for a library-level
object's alignment, but for a type that seems very hard to support.
> so such a "simple allocator" would not be useful in GNAT. Doesn't
> mean such a constant shouldn't exist in the language.
>
> Maybe we want (instead or in addition) the max alignment the impl will
> pass to an allocator when there are no user-specified Alignment clauses.
Yes, I suppose that would be more useful.
It would also be useful to have a maximum supported alignment for user-specified
*subtype* alignment clauses (and perhaps for objects as well).
> Which might not be quite the same as the max alignment of any type
> chosen by default (but that might be useful, too).
Yes, that too. Sounds like a nice little collection of alignment limits.
****************************************************************
From: Robert Dewar
Sent: Wednesday, June 17, 2009 5:36 AM
> Really? I could imagine it accepting something like that for a
> library-level object's alignment, but for a type that seems very hard
> to support.
No, you just allocate extra and waste some space. We have to have this
cirrcuitry anyway to meet existing rules of the language, e.g. when the storage
allocator/stack max alignment does not match. So it is no extra work to trigger
it in silly cases.
****************************************************************
From: Bob Duff
Sent: Wednesday, June 17, 2009 3:11 PM
> > for T'Alignment use 2**25;
> Really?
Yup. ;-)
>...I could imagine it accepting something like that for a
>library-level object's alignment, but for a type that seems very hard
>to support.
Well, having been involved in some bug fixing in this area, I guess I'd have to
agree with "hard". Not terribly efficient, either.
****************************************************************
Questions? Ask the ACAA Technical Agent