s-stausa.ads (Stack_Analyzer): Remove First_Is_Topmost, redundant with Stack_Grows_Down in System.Parameters.
2007-12-06 Olivier Hainque <hainque@adacore.com> * s-stausa.ads (Stack_Analyzer): Remove First_Is_Topmost, redundant with Stack_Grows_Down in System.Parameters. Rename Array_Address into Stack_Overlay_Address and document that we are using an internal abstraction. (Byte_Size, Unsigned_32_Size): Remove, now useless. (Pattern_Type, Bytes_Per_Pattern): New subtype and constant, to be used consistently throughout the various implementation pieces. * s-stausa.adb (Stack_Slots): New type, abstraction for the stack overlay we are using to fill the stack area with patterns. (Top_Slot_Index_In, Bottom_Slot_Index_In): Operations on Stack_Slots. (Push_Index_Step_For, Pop_Index_Step_For): Likewise. (Fill_Stack, Compute_Result): Use the Stack_Slots abstraction. From-SVN: r130863
This commit is contained in:
parent
90de1450e5
commit
4981ffccd5
|
@ -41,12 +41,141 @@ package body System.Stack_Usage is
|
|||
use System.IO;
|
||||
use Interfaces;
|
||||
|
||||
Index_Str : constant String := "Index";
|
||||
Task_Name_Str : constant String := "Task Name";
|
||||
Stack_Size_Str : constant String := "Stack Size";
|
||||
Actual_Size_Str : constant String := "Stack usage [min - max]";
|
||||
Pattern_Array_Elem_Size : constant Natural :=
|
||||
(Unsigned_32_Size / Byte_Size);
|
||||
-----------------
|
||||
-- Stack_Slots --
|
||||
-----------------
|
||||
|
||||
-- Stackl_Slots is an internal data type to represent a sequence of real
|
||||
-- stack slots initialized with a provided pattern, with operations to
|
||||
-- abstract away the target call stack growth direction.
|
||||
|
||||
type Stack_Slots is array (Integer range <>) of Pattern_Type;
|
||||
for Stack_Slots'Component_Size use Pattern_Type'Object_Size;
|
||||
|
||||
-- We will carefully handle the initializations ourselves and might want
|
||||
-- to remap an initialized overlay later on with an address clause.
|
||||
|
||||
pragma Suppress_Initialization (Stack_Slots);
|
||||
|
||||
-- The abstract Stack_Slots operations all operate over the simple array
|
||||
-- memory model:
|
||||
|
||||
-- memory addresses increasing ---->
|
||||
|
||||
-- Slots('First) Slots('Last)
|
||||
-- | |
|
||||
-- V V
|
||||
-- +------------------------------------------------------------------+
|
||||
-- |####| |####|
|
||||
-- +------------------------------------------------------------------+
|
||||
|
||||
-- What we call Top or Bottom always denotes call chain leaves or entry
|
||||
-- points respectively, and their relative positions in the stack array
|
||||
-- depends on the target stack growth direction:
|
||||
|
||||
-- Stack_Grows_Down
|
||||
|
||||
-- <----- calls push frames towards decreasing addresses
|
||||
|
||||
-- Top(most) Slot Bottom(most) Slot
|
||||
-- | |
|
||||
-- V V
|
||||
-- +------------------------------------------------------------------+
|
||||
-- |####| | leaf frame | ... | entry frame |
|
||||
-- +------------------------------------------------------------------+
|
||||
|
||||
-- Stack_Grows_Up
|
||||
|
||||
-- calls push frames towards increasing addresses ----->
|
||||
|
||||
-- Bottom(most) Slot Top(most) Slot
|
||||
-- | |
|
||||
-- V V
|
||||
-- +------------------------------------------------------------------+
|
||||
-- | entry frame | ... | leaf frame | |####|
|
||||
-- +------------------------------------------------------------------+
|
||||
|
||||
function Top_Slot_Index_In (Stack : Stack_Slots) return Integer;
|
||||
-- Index of the stack Top slot in the Slots array, denoting the latest
|
||||
-- possible slot available to call chain leaves.
|
||||
|
||||
function Bottom_Slot_Index_In (Stack : Stack_Slots) return Integer;
|
||||
-- Index of the stack Bottom slot in the Slots array, denoting the first
|
||||
-- possible slot available to call chain entry points.
|
||||
|
||||
function Push_Index_Step_For (Stack : Stack_Slots) return Integer;
|
||||
-- By how much do we need to update a Slots index to Push a single slot on
|
||||
-- the stack.
|
||||
|
||||
function Pop_Index_Step_For (Stack : Stack_Slots) return Integer;
|
||||
-- By how much do we need to update a Slots index to Pop a single slot off
|
||||
-- the stack.
|
||||
|
||||
pragma Inline_Always (Top_Slot_Index_In);
|
||||
pragma Inline_Always (Bottom_Slot_Index_In);
|
||||
pragma Inline_Always (Push_Index_Step_For);
|
||||
pragma Inline_Always (Pop_Index_Step_For);
|
||||
|
||||
-----------------------
|
||||
-- Top_Slot_Index_In --
|
||||
-----------------------
|
||||
|
||||
function Top_Slot_Index_In (Stack : Stack_Slots) return Integer is
|
||||
begin
|
||||
if System.Parameters.Stack_Grows_Down then
|
||||
return Stack'First;
|
||||
else
|
||||
return Stack'Last;
|
||||
end if;
|
||||
end Top_Slot_Index_In;
|
||||
|
||||
----------------------------
|
||||
-- Bottom_Slot_Index_In --
|
||||
----------------------------
|
||||
|
||||
function Bottom_Slot_Index_In (Stack : Stack_Slots) return Integer is
|
||||
begin
|
||||
if System.Parameters.Stack_Grows_Down then
|
||||
return Stack'Last;
|
||||
else
|
||||
return Stack'First;
|
||||
end if;
|
||||
end Bottom_Slot_Index_In;
|
||||
|
||||
-------------------------
|
||||
-- Push_Index_Step_For --
|
||||
-------------------------
|
||||
|
||||
function Push_Index_Step_For (Stack : Stack_Slots) return Integer is
|
||||
pragma Unreferenced (Stack);
|
||||
begin
|
||||
if System.Parameters.Stack_Grows_Down then
|
||||
return -1;
|
||||
else
|
||||
return +1;
|
||||
end if;
|
||||
end Push_Index_Step_For;
|
||||
|
||||
------------------------
|
||||
-- Pop_Index_Step_For --
|
||||
------------------------
|
||||
|
||||
function Pop_Index_Step_For (Stack : Stack_Slots) return Integer is
|
||||
begin
|
||||
return -Push_Index_Step_For (Stack);
|
||||
end Pop_Index_Step_For;
|
||||
|
||||
-------------------
|
||||
-- Unit Services --
|
||||
-------------------
|
||||
|
||||
-- Now the implementation of the services offered by this unit, on top of
|
||||
-- the Stack_Slots abstraction above.
|
||||
|
||||
Index_Str : constant String := "Index";
|
||||
Task_Name_Str : constant String := "Task Name";
|
||||
Stack_Size_Str : constant String := "Stack Size";
|
||||
Actual_Size_Str : constant String := "Stack usage [min - max]";
|
||||
|
||||
function Get_Usage_Range (Result : Task_Result) return String;
|
||||
-- Return string representing the range of possible result of stack usage
|
||||
|
@ -62,30 +191,6 @@ package body System.Stack_Usage is
|
|||
-- proper layout. They hold the maximum length of the string representing
|
||||
-- the Stack_Size and Actual_Use values.
|
||||
|
||||
function Closer_To_Bottom
|
||||
(A1 : Stack_Address;
|
||||
A2 : Stack_Address) return Boolean;
|
||||
pragma Inline (Closer_To_Bottom);
|
||||
-- Return True if, according to the direction of the stack growth, A1 is
|
||||
-- closer to the bottom than A2. Inlined to reduce the size of the stack
|
||||
-- used by the instrumentation code.
|
||||
|
||||
----------------------
|
||||
-- Closer_To_Bottom --
|
||||
----------------------
|
||||
|
||||
function Closer_To_Bottom
|
||||
(A1 : Stack_Address;
|
||||
A2 : Stack_Address) return Boolean
|
||||
is
|
||||
begin
|
||||
if System.Parameters.Stack_Grows_Down then
|
||||
return A1 > A2;
|
||||
else
|
||||
return A2 > A1;
|
||||
end if;
|
||||
end Closer_To_Bottom;
|
||||
|
||||
----------------
|
||||
-- Initialize --
|
||||
----------------
|
||||
|
@ -154,39 +259,17 @@ package body System.Stack_Usage is
|
|||
-- big, the more an "instrumentation threshold at writing" error is
|
||||
-- likely to happen.
|
||||
|
||||
type Unsigned_32_Arr is
|
||||
array (1 .. Analyzer.Size / Pattern_Array_Elem_Size) of Unsigned_32;
|
||||
for Unsigned_32_Arr'Component_Size use 32;
|
||||
|
||||
package Arr_Addr is
|
||||
new System.Address_To_Access_Conversions (Unsigned_32_Arr);
|
||||
|
||||
Arr : aliased Unsigned_32_Arr;
|
||||
Stack : aliased Stack_Slots (1 .. Analyzer.Size / Bytes_Per_Pattern);
|
||||
|
||||
begin
|
||||
-- Fill the stack with the pattern
|
||||
Stack := (others => Analyzer.Pattern);
|
||||
|
||||
for J in Unsigned_32_Arr'Range loop
|
||||
Arr (J) := Analyzer.Pattern;
|
||||
end loop;
|
||||
Analyzer.Stack_Overlay_Address := Stack'Address;
|
||||
|
||||
-- Initialize the analyzer value
|
||||
|
||||
Analyzer.Array_Address := Arr_Addr.To_Address (Arr'Access);
|
||||
Analyzer.Bottom_Pattern_Mark := To_Stack_Address (Arr (1)'Address);
|
||||
Analyzer.Bottom_Pattern_Mark :=
|
||||
To_Stack_Address (Stack (Bottom_Slot_Index_In (Stack))'Address);
|
||||
Analyzer.Top_Pattern_Mark :=
|
||||
To_Stack_Address (Arr (Unsigned_32_Arr'Last)'Address);
|
||||
|
||||
if
|
||||
Closer_To_Bottom
|
||||
(Analyzer.Top_Pattern_Mark, Analyzer.Bottom_Pattern_Mark)
|
||||
then
|
||||
Analyzer.Bottom_Pattern_Mark := Analyzer.Top_Pattern_Mark;
|
||||
Analyzer.Top_Pattern_Mark := To_Stack_Address (Arr (1)'Address);
|
||||
Analyzer.First_Is_Topmost := True;
|
||||
else
|
||||
Analyzer.First_Is_Topmost := False;
|
||||
end if;
|
||||
To_Stack_Address (Stack (Top_Slot_Index_In (Stack))'Address);
|
||||
|
||||
-- If Arr has been packed, the following assertion must be true (we add
|
||||
-- the size of the element whose address is:
|
||||
|
@ -263,33 +346,35 @@ package body System.Stack_Usage is
|
|||
-- is, the more an "instrumentation threshold at reading" error is
|
||||
-- likely to happen.
|
||||
|
||||
type Unsigned_32_Arr is
|
||||
array (1 .. Analyzer.Size / Pattern_Array_Elem_Size) of Unsigned_32;
|
||||
for Unsigned_32_Arr'Component_Size use 32;
|
||||
|
||||
package Arr_Addr is
|
||||
new System.Address_To_Access_Conversions (Unsigned_32_Arr);
|
||||
|
||||
Arr_Access : Arr_Addr.Object_Pointer;
|
||||
Stack : Stack_Slots (1 .. Analyzer.Size / Bytes_Per_Pattern);
|
||||
for Stack'Address use Analyzer.Stack_Overlay_Address;
|
||||
|
||||
begin
|
||||
Arr_Access := Arr_Addr.To_Pointer (Analyzer.Array_Address);
|
||||
Analyzer.Topmost_Touched_Mark := Analyzer.Bottom_Pattern_Mark;
|
||||
|
||||
-- Look backward from the end of the stack to the beginning. The first
|
||||
-- index not equals to the patterns marks the beginning of the used
|
||||
-- stack.
|
||||
-- Look backward from the topmost possible end of the marked stack to
|
||||
-- the bottom of it. The first index not equals to the patterns marks
|
||||
-- the beginning of the used stack.
|
||||
|
||||
for J in Unsigned_32_Arr'Range loop
|
||||
if Arr_Access (J) /= Analyzer.Pattern then
|
||||
Analyzer.Topmost_Touched_Mark :=
|
||||
To_Stack_Address (Arr_Access (J)'Address);
|
||||
declare
|
||||
Top_Index : constant Integer := Top_Slot_Index_In (Stack);
|
||||
Bottom_Index : constant Integer := Bottom_Slot_Index_In (Stack);
|
||||
Step : constant Integer := Pop_Index_Step_For (Stack);
|
||||
J : Integer;
|
||||
|
||||
if Analyzer.First_Is_Topmost then
|
||||
begin
|
||||
J := Top_Index;
|
||||
loop
|
||||
if Stack (J) /= Analyzer.Pattern then
|
||||
Analyzer.Topmost_Touched_Mark
|
||||
:= To_Stack_Address (Stack (J)'Address);
|
||||
exit;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
exit when J = Bottom_Index;
|
||||
J := J + Step;
|
||||
end loop;
|
||||
end;
|
||||
end Compute_Result;
|
||||
|
||||
---------------------
|
||||
|
@ -303,7 +388,7 @@ package body System.Stack_Usage is
|
|||
Natural'Image (Result.Measure + Result.Overflow_Guard);
|
||||
begin
|
||||
return "[" & Min_Used_Str (2 .. Min_Used_Str'Last) & " -"
|
||||
& Max_Used_Str & "]";
|
||||
& Max_Used_Str & "]";
|
||||
end Get_Usage_Range;
|
||||
|
||||
---------------------
|
||||
|
@ -323,12 +408,15 @@ package body System.Stack_Usage is
|
|||
Result_Id_Blanks : constant
|
||||
String (1 .. Index_Str'Length - Result_Id_Str'Length) :=
|
||||
(others => ' ');
|
||||
|
||||
Stack_Size_Blanks : constant
|
||||
String (1 .. Max_Stack_Size_Len - Stack_Size_Str'Length) :=
|
||||
(others => ' ');
|
||||
|
||||
Actual_Use_Blanks : constant
|
||||
String (1 .. Max_Actual_Use_Len - Actual_Use_Str'Length) :=
|
||||
(others => ' ');
|
||||
|
||||
begin
|
||||
Set_Output (Standard_Error);
|
||||
Put (Result_Id_Blanks & Natural'Image (Result_Id));
|
||||
|
@ -350,9 +438,9 @@ package body System.Stack_Usage is
|
|||
Max_Actual_Use_Result_Id : Natural := Result_Array'First;
|
||||
Max_Stack_Size_Len, Max_Actual_Use_Len : Natural := 0;
|
||||
|
||||
Task_Name_Blanks :
|
||||
constant String (1 .. Task_Name_Length - Task_Name_Str'Length) :=
|
||||
(others => ' ');
|
||||
Task_Name_Blanks : constant
|
||||
String (1 .. Task_Name_Length - Task_Name_Str'Length) :=
|
||||
(others => ' ');
|
||||
|
||||
begin
|
||||
Set_Output (Standard_Error);
|
||||
|
@ -392,10 +480,11 @@ package body System.Stack_Usage is
|
|||
declare
|
||||
Stack_Size_Blanks : constant
|
||||
String (1 .. Max_Stack_Size_Len - Stack_Size_Str'Length) :=
|
||||
(others => ' ');
|
||||
(others => ' ');
|
||||
|
||||
Stack_Usage_Blanks : constant
|
||||
String (1 .. Max_Actual_Use_Len - Actual_Size_Str'Length) :=
|
||||
(others => ' ');
|
||||
(others => ' ');
|
||||
|
||||
begin
|
||||
if Stack_Size_Str'Length > Max_Stack_Size_Len then
|
||||
|
@ -421,9 +510,10 @@ package body System.Stack_Usage is
|
|||
Output_Result
|
||||
(J, Result_Array (J), Max_Stack_Size_Len, Max_Actual_Use_Len);
|
||||
end loop;
|
||||
else
|
||||
-- If there are no result stored, we'll still display the labels
|
||||
|
||||
-- Case of no result stored, still display the labels
|
||||
|
||||
else
|
||||
Put
|
||||
(Index_Str & " | " & Task_Name_Str & Task_Name_Blanks & " | "
|
||||
& Stack_Size_Str & " | " & Actual_Size_Str);
|
||||
|
@ -437,14 +527,15 @@ package body System.Stack_Usage is
|
|||
|
||||
procedure Report_Result (Analyzer : Stack_Analyzer) is
|
||||
Result : constant Task_Result :=
|
||||
(Task_Name => Analyzer.Task_Name,
|
||||
Max_Size => Analyzer.Size + Analyzer.Overflow_Guard,
|
||||
Measure => Stack_Size
|
||||
(Analyzer.Topmost_Touched_Mark,
|
||||
Analyzer.Bottom_Of_Stack),
|
||||
Overflow_Guard => Analyzer.Overflow_Guard -
|
||||
Natural (Analyzer.Bottom_Of_Stack -
|
||||
Analyzer.Bottom_Pattern_Mark));
|
||||
(Task_Name => Analyzer.Task_Name,
|
||||
Max_Size => Analyzer.Size + Analyzer.Overflow_Guard,
|
||||
Measure => Stack_Size
|
||||
(Analyzer.Topmost_Touched_Mark,
|
||||
Analyzer.Bottom_Of_Stack),
|
||||
Overflow_Guard => Analyzer.Overflow_Guard -
|
||||
Natural (Analyzer.Bottom_Of_Stack -
|
||||
Analyzer.Bottom_Pattern_Mark));
|
||||
|
||||
begin
|
||||
if Analyzer.Result_Id in Result_Array'Range then
|
||||
|
||||
|
@ -453,7 +544,6 @@ package body System.Stack_Usage is
|
|||
Result_Array (Analyzer.Result_Id) := Result;
|
||||
|
||||
else
|
||||
|
||||
-- If the result cannot be stored, then we display it right away
|
||||
|
||||
declare
|
||||
|
|
|
@ -41,9 +41,6 @@ package System.Stack_Usage is
|
|||
|
||||
package SSE renames System.Storage_Elements;
|
||||
|
||||
Byte_Size : constant := 8;
|
||||
Unsigned_32_Size : constant := 4 * Byte_Size;
|
||||
|
||||
-- The alignment clause seems dubious, what about architectures where
|
||||
-- the maximum alignment is less than 4???
|
||||
-- Anyway, why not use Interfaces.Unsigned_32???
|
||||
|
@ -270,6 +267,9 @@ private
|
|||
package Unsigned_32_Addr is
|
||||
new System.Address_To_Access_Conversions (Interfaces.Unsigned_32);
|
||||
|
||||
subtype Pattern_Type is Interfaces.Unsigned_32;
|
||||
Bytes_Per_Pattern : constant := Pattern_Type'Object_Size / Storage_Unit;
|
||||
|
||||
type Stack_Analyzer is record
|
||||
Task_Name : String (1 .. Task_Name_Length);
|
||||
-- Name of the task
|
||||
|
@ -277,7 +277,7 @@ private
|
|||
Size : Natural;
|
||||
-- Size of the pattern zone
|
||||
|
||||
Pattern : Interfaces.Unsigned_32;
|
||||
Pattern : Pattern_Type;
|
||||
-- Pattern used to recognize untouched memory
|
||||
|
||||
Bottom_Pattern_Mark : Stack_Address;
|
||||
|
@ -296,13 +296,9 @@ private
|
|||
-- Address of the bottom of the stack, as given by the caller of
|
||||
-- Initialize_Analyzer.
|
||||
|
||||
Array_Address : System.Address;
|
||||
-- Address of the array of Unsigned_32 that represents the pattern zone
|
||||
|
||||
First_Is_Topmost : Boolean;
|
||||
-- Set to true if the first element of the array of Unsigned_32 that
|
||||
-- represents the pattern zone is at the topmost address of the
|
||||
-- pattern zone; false if it is the bottommost address.
|
||||
Stack_Overlay_Address : System.Address;
|
||||
-- Address of the stack abstraction object we overlay over a
|
||||
-- task's real stack, typically a pattern-initialized array.
|
||||
|
||||
Result_Id : Positive;
|
||||
-- Id of the result. If less than value given to gnatbind -u corresponds
|
||||
|
|
Loading…
Reference in New Issue