1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Debug
; use Debug
;
28 with Output
; use Output
;
29 with System
; use System
;
31 with System
.Memory
; use System
.Memory
;
33 with Unchecked_Conversion
;
35 pragma Elaborate_All
(Output
);
40 Min
: constant Int
:= Int
(Table_Low_Bound
);
41 -- Subscript of the minimum entry in the currently allocated table
44 -- Number of entries in currently allocated table. The value of zero
45 -- ensures that we initially allocate the table.
47 -----------------------
48 -- Local Subprograms --
49 -----------------------
52 -- Reallocate the existing table according to the current value stored
53 -- in Max. Works correctly to do an initial allocation if the table
56 pragma Warnings
(Off
);
57 -- Turn off warnings. The following unchecked conversions are only used
58 -- internally in this package, and cannot never result in any instances
59 -- of improperly aliased pointers for the client of the package.
61 function To_Address
is new Unchecked_Conversion
(Table_Ptr
, Address
);
62 function To_Pointer
is new Unchecked_Conversion
(Address
, Table_Ptr
);
70 procedure Append
(New_Val
: Table_Component_Type
) is
72 pragma Assert
(not Locked
);
73 Set_Item
(Table_Index_Type
(Last_Val
+ 1), New_Val
);
80 procedure Append_All
(New_Vals
: Table_Type
) is
82 for J
in New_Vals
'Range loop
83 Append
(New_Vals
(J
));
91 procedure Decrement_Last
is
93 Last_Val
:= Last_Val
- 1;
102 Free
(To_Address
(Table
));
111 procedure Increment_Last
is
113 pragma Assert
(not Locked
);
114 Last_Val
:= Last_Val
+ 1;
116 if Last_Val
> Max
then
126 Old_Length
: constant Int
:= Length
;
131 Max
:= Min
+ (Table_Initial
* Table_Factor
) - 1;
132 Length
:= Max
- Min
+ 1;
134 -- If table is same size as before (happens when table is never
135 -- expanded which is a common case), then simply reuse it. Note
136 -- that this also means that an explicit Init call right after
137 -- the implicit one in the package body is harmless.
139 if Old_Length
= Length
then
142 -- Otherwise we can use Reallocate to get a table of the right size.
143 -- Note that Reallocate works fine to allocate a table of the right
144 -- initial size when it is first allocated.
155 function Last
return Table_Index_Type
is
157 return Table_Index_Type
(Last_Val
);
164 procedure Reallocate
is
165 New_Size
: Memory
.size_t
;
166 New_Length
: Long_Long_Integer;
169 if Max
< Last_Val
then
170 pragma Assert
(not Locked
);
172 -- Make sure that we have at least the initial allocation. This
173 -- is needed in cases where a zero length table is written out.
175 Length
:= Int
'Max (Length
, Table_Initial
);
177 -- Now increment table length until it is sufficiently large. Use
178 -- the increment value or 10, which ever is larger (the reason
179 -- for the use of 10 here is to ensure that the table does really
180 -- increase in size (which would not be the case for a table of
181 -- length 10 increased by 3% for instance). Do the intermediate
182 -- calculation in Long_Long_Integer to avoid overflow.
184 while Max
< Last_Val
loop
186 Long_Long_Integer (Length
) *
187 (100 + Long_Long_Integer (Table_Increment
)) / 100;
188 Length
:= Int
'Max (Int
(New_Length
), Length
+ 10);
189 Max
:= Min
+ Length
- 1;
193 Write_Str
("--> Allocating new ");
194 Write_Str
(Table_Name
);
195 Write_Str
(" table, size = ");
196 Write_Int
(Max
- Min
+ 1);
201 -- Do the intermediate calculation in size_t to avoid signed overflow
204 Memory
.size_t
(Max
- Min
+ 1) *
205 (Table_Type
'Component_Size / Storage_Unit
);
208 Table
:= To_Pointer
(Alloc
(New_Size
));
210 elsif New_Size
> 0 then
212 To_Pointer
(Realloc
(Ptr
=> To_Address
(Table
),
216 if Length
/= 0 and then Table
= null then
218 Write_Str
("available memory exhausted");
221 raise Unrecoverable_Error
;
231 Size
: Memory
.size_t
;
234 Length
:= Last_Val
- Int
(Table_Low_Bound
) + 1;
235 Size
:= Memory
.size_t
(Length
) *
236 (Table_Type
'Component_Size / Storage_Unit
);
238 -- If the size of the table exceeds the release threshold then leave
239 -- space to store as many extra elements as 0.1% of the table length.
241 if Release_Threshold
> 0
242 and then Size
> Memory
.size_t
(Release_Threshold
)
244 Extra_Length
:= Length
/ 1000;
245 Length
:= Length
+ Extra_Length
;
246 Max
:= Int
(Table_Low_Bound
) + Length
- 1;
249 Write_Str
("--> Release_Threshold reached (length=");
250 Write_Int
(Int
(Size
));
251 Write_Str
("): leaving room space for ");
252 Write_Int
(Extra_Length
);
253 Write_Str
(" components");
267 procedure Restore
(T
: Saved_Table
) is
269 Free
(To_Address
(Table
));
270 Last_Val
:= T
.Last_Val
;
273 Length
:= Max
- Min
+ 1;
280 function Save
return Saved_Table
is
284 Res
.Last_Val
:= Last_Val
;
299 (Index
: Table_Index_Type
;
300 Item
: Table_Component_Type
)
302 -- If Item is a value within the current allocation, and we are going
303 -- to reallocate, then we must preserve an intermediate copy here
304 -- before calling Increment_Last. Otherwise, if Table_Component_Type
305 -- is passed by reference, we are going to end up copying from
306 -- storage that might have been deallocated from Increment_Last
307 -- calling Reallocate.
309 subtype Allocated_Table_T
is
310 Table_Type
(Table
'First .. Table_Index_Type
(Max
+ 1));
311 -- A constrained table subtype one element larger than the currently
314 Allocated_Table_Address
: constant System
.Address
:=
316 -- Used for address clause below (we can't use non-static expression
317 -- Table.all'Address directly in the clause because some older
318 -- versions of the compiler do not allow it).
320 Allocated_Table
: Allocated_Table_T
;
321 pragma Import
(Ada
, Allocated_Table
);
322 pragma Suppress
(Range_Check
, On
=> Allocated_Table
);
323 for Allocated_Table
'Address use Allocated_Table_Address
;
324 -- Allocated_Table represents the currently allocated array, plus one
325 -- element (the supplementary element is used to have a convenient
326 -- way of computing the address just past the end of the current
327 -- allocation). Range checks are suppressed because this unit
328 -- uses direct calls to System.Memory for allocation, and this can
329 -- yield misaligned storage (and we cannot rely on the bootstrap
330 -- compiler supporting specifically disabling alignment checks, so we
331 -- need to suppress all range checks). It is safe to suppress this
332 -- check here because we know that a (possibly misaligned) object
333 -- of that type does actually exist at that address.
334 -- ??? We should really improve the allocation circuitry here to
335 -- guarantee proper alignment.
337 Need_Realloc
: constant Boolean := Int
(Index
) > Max
;
338 -- True if this operation requires storage reallocation (which may
339 -- involve moving table contents around).
342 -- If we're going to reallocate, check whether Item references an
343 -- element of the currently allocated table.
346 and then Allocated_Table
'Address <= Item
'Address
347 and then Item
'Address <
348 Allocated_Table
(Table_Index_Type
(Max
+ 1))'Address
350 -- If so, save a copy on the stack because Increment_Last will
351 -- reallocate storage and might deallocate the current table.
354 Item_Copy
: constant Table_Component_Type
:= Item
;
357 Table
(Index
) := Item_Copy
;
361 -- Here we know that either we won't reallocate (case of Index <
362 -- Max) or that Item is not in the currently allocated table.
364 if Int
(Index
) > Last_Val
then
368 Table
(Index
) := Item
;
376 procedure Set_Last
(New_Val
: Table_Index_Type
) is
378 pragma Assert
(Int
(New_Val
) <= Last_Val
or else not Locked
);
380 if Int
(New_Val
) < Last_Val
then
381 Last_Val
:= Int
(New_Val
);
384 Last_Val
:= Int
(New_Val
);
386 if Last_Val
> Max
then