1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- G N A T . D E B U G _ P O O L S --
10 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
23 -- As a special exception, if other files instantiate generics from this --
24 -- unit, or you link this unit with other files to produce an executable, --
25 -- this unit does not by itself cause the resulting executable to be --
26 -- covered by the GNU General Public License. This exception does not --
27 -- however invalidate any other reasons why the executable file might be --
28 -- covered by the GNU Public License. --
30 -- GNAT was originally developed by the GNAT team at New York University. --
31 -- Extensive contributions were provided by Ada Core Technologies Inc. --
33 ------------------------------------------------------------------------------
35 with Unchecked_Conversion
;
39 pragma Elaborate_All
(GNAT
.HTable
);
41 package body GNAT
.Debug_Pools
is
44 use System
.Storage_Elements
;
46 -- Definition of a H-table storing the status of each storage chunck
49 type State
is (Not_Allocated
, Deallocated
, Allocated
);
51 type Header
is range 1 .. 1023;
52 function H
(F
: Address
) return Header
;
54 package Table
is new GNAT
.HTable
.Simple_HTable
(
57 No_Element
=> Not_Allocated
,
67 (Pool
: in out Debug_Pool
;
68 Storage_Address
: out Address
;
69 Size_In_Storage_Elements
: Storage_Count
;
70 Alignment
: Storage_Count
)
72 pragma Warnings
(Off
, Alignment
);
75 Storage_Address
:= Alloc
(size_t
(Size_In_Storage_Elements
));
77 if Storage_Address
= Null_Address
then
80 Table
.Set
(Storage_Address
, Allocated
);
81 Pool
.Allocated
:= Pool
.Allocated
+ Size_In_Storage_Elements
;
83 if Pool
.Allocated
- Pool
.Deallocated
> Pool
.High_Water
then
84 Pool
.High_Water
:= Pool
.Allocated
- Pool
.Deallocated
;
94 (Pool
: in out Debug_Pool
;
95 Storage_Address
: Address
;
96 Size_In_Storage_Elements
: Storage_Count
;
97 Alignment
: Storage_Count
)
99 pragma Warnings
(Off
, Alignment
);
101 procedure Free
(Address
: System
.Address
; Siz
: Storage_Count
);
102 -- Fake free, that resets all the deallocated storage to "DEADBEEF"
104 procedure Free
(Address
: System
.Address
; Siz
: Storage_Count
) is
105 DB1
: constant Integer := 16#DEAD#
;
106 DB2
: constant Integer := 16#BEEF#
;
108 type Dead_Memory
is array (1 .. Siz
/ 4) of Integer;
109 type Mem_Ptr
is access all Dead_Memory
;
112 new Unchecked_Conversion
(System
.Address
, Mem_Ptr
);
117 J
:= Dead_Memory
'First;
118 while J
< Dead_Memory
'Last loop
119 From_Ptr
(Address
) (J
) := DB1
;
120 From_Ptr
(Address
) (J
+ 1) := DB2
;
124 if J
= Dead_Memory
'Last then
125 From_Ptr
(Address
) (J
) := DB1
;
129 S
: State
:= Table
.Get
(Storage_Address
);
131 -- Start of processing for Deallocate
135 when Not_Allocated
=>
136 raise Freeing_Not_Allocated_Storage
;
139 raise Freeing_Deallocated_Storage
;
142 Free
(Storage_Address
, Size_In_Storage_Elements
);
143 Table
.Set
(Storage_Address
, Deallocated
);
144 Pool
.Deallocated
:= Pool
.Deallocated
+ Size_In_Storage_Elements
;
152 procedure Dereference
153 (Pool
: in out Debug_Pool
;
154 Storage_Address
: Address
;
155 Size_In_Storage_Elements
: Storage_Count
;
156 Alignment
: Storage_Count
)
158 pragma Warnings
(Off
, Pool
);
159 pragma Warnings
(Off
, Size_In_Storage_Elements
);
160 pragma Warnings
(Off
, Alignment
);
162 S
: State
:= Table
.Get
(Storage_Address
);
163 Max_Dim
: constant := 3;
168 -- If this is not a known address, maybe it is because is is an
169 -- unconstained array. In which case, the bounds have used the
170 -- 2 first words (per dimension) of the allocated spot.
172 while S
= Not_Allocated
and then Dim
<= Max_Dim
loop
173 S
:= Table
.Get
(Storage_Address
- Storage_Offset
(Dim
* 2 * 4));
178 when Not_Allocated
=>
179 raise Accessing_Not_Allocated_Storage
;
182 raise Accessing_Deallocated_Storage
;
193 function H
(F
: Address
) return Header
is
196 Header
(1 + (To_Integer
(F
) mod Integer_Address
(Header
'Last)));
203 procedure Print_Info
(Pool
: Debug_Pool
) is
204 use System
.Storage_Elements
;
207 Put_Line
("Debug Pool info:");
208 Put_Line
(" Total allocated bytes : "
209 & Storage_Offset
'Image (Pool
.Allocated
));
211 Put_Line
(" Total deallocated bytes : "
212 & Storage_Offset
'Image (Pool
.Deallocated
));
214 Put_Line
(" Current Water Mark: "
215 & Storage_Offset
'Image (Pool
.Allocated
- Pool
.Deallocated
));
217 Put_Line
(" High Water Mark: "
218 & Storage_Offset
'Image (Pool
.High_Water
));
226 function Storage_Size
(Pool
: Debug_Pool
) return Storage_Count
is
227 pragma Warnings
(Off
, Pool
);
230 return Storage_Count
'Last;
233 end GNAT
.Debug_Pools
;