/* Copyright (C) 2021 Free Software Foundation, Inc.
Contributed by Oracle.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#ifndef _HIST_DATA_H
#define _HIST_DATA_H
// A Hist_data object is used to obtain data used for constructing
// a histogram display.
#include <sys/types.h>
#include <vec.h>
#include <Map.h>
#include <HashMap.h>
#include "dbe_structs.h"
#include "Histable.h"
#include "DerivedMetrics.h"
class DbeLine;
class MetricList;
class Hist_data
{
public:
friend class DbeView;
friend class er_print_histogram;
friend class PathTree;
friend class DataSpace;
friend class MemorySpace;
friend class IOActivity;
friend class HeapActivity;
// HistItem contains all the data about a single histogram item.
struct HistItem
{
HistItem (long n);
~HistItem ();
Histable *obj; // info on the object
int type; // annotated src/dis: type
TValue *value; // numeric values
long size;
};
enum Hist_status
{
SUCCESS = 0,
NO_DATA
};
enum Mode
{
ALL,
CALLERS,
CALLEES,
SELF,
MODL,
LAYOUT,
DETAIL
};
enum Sort_order
{
ASCEND,
DESCEND
};
enum Sort_type
{
ALPHA,
VALUE,
AUX
};
Hist_data (MetricList *, Histable::Type, Mode, bool _viewowned = false);
virtual ~Hist_data ();
void dump (char *msg, FILE *f);
Hist_status
get_status (void)
{
return status;
}
// Return the view ownership flag
bool
isViewOwned (void)
{
return viewowned;
}
// Return the total number of items
long size (void);
// Append a new HistItem for the specified Histable
HistItem *append_hist_item (Histable *obj);
void append_hist_item (HistItem *hi);
TValue *get_real_value (TValue *res, int met_index, int row);
TValue *get_value (TValue *res, int met_index, int row);
TValue *get_value (TValue *res, int met_index, HistItem *hi);
void print_row(StringBuilder *sb, int row, Metric::HistMetric *hist_metric,
const char *mark);
void print_content (FILE *out_file, Metric::HistMetric *hist_metric, int limit);
int print_label (FILE *out_file, Metric::HistMetric *hist_metric, int space);
void update_total (Hist_data::HistItem *new_total);
void update_max (Metric::HistMetric *hm_tmp);
void update_legend_width (Metric::HistMetric *hm_tmp);
// Find an existing HistItem
HistItem *find_hist_item (Histable *obj);
// sort the data
void sort (long ind, bool reverse);
// resort the data, if metric sort or direction has changed
void resort (MetricList *mlist);
// compute minima and maxima
void compute_minmax (void);
// fetch() takes a hist item index and returns a ptr to the item
HistItem *fetch (long index);
HistItem *
get_maximums (void)
{
return maximum;
}
HistItem *
get_maximums_inc (void)
{
return maximum_inc;
}
HistItem *
get_minimums (void)
{
return minimum;
}
HistItem *
get_totals (void)
{
return total;
}
Vector<HistItem*> *
get_hist_items (void)
{
return hist_items;
}
void
set_status (Hist_status st)
{
status = st;
}
MetricList *
get_metric_list (void)
{
return metrics;
}
Map<Histable*, int> *
get_callsite_mark ()
{
return callsite_mark;
}
Metric::HistMetric *get_histmetrics ();
void set_threshold (double proportion);
bool above_threshold (HistItem *hi);
double get_percentage (double value, int mindex);
size_t value_maxlen (int mindex); // Return the drawing length
size_t time_len (TValue *value, int clock);
size_t time_maxlen (int mindex, int clock);
size_t name_len (HistItem *item);
size_t name_maxlen ();
HistItem *new_hist_item (Histable *obj, int itype, TValue *value);
HistItem *update_hist_item (HistItem *hi, TValue *value);
Vector<uint64_t> *get_object_indices (Vector<int> *selections);
private:
Metric::HistMetric *hist_metrics;
Vector<HistItem*> *hist_items; // Actual histogram values
HashMap<Histable*, HistItem*>*hi_map; // map: Histable -> HistItem
Map<Histable*, int>*callsite_mark;
Hist_status status;
int nmetrics; // number of metrics
MetricList *metrics;
Histable::Type type;
Sort_order sort_order;
Sort_type sort_type;
int sort_ind;
bool rev_sort; // true if sort is reversed
Mode mode;
HistItem *gprof_item; // used for gprof-style info
Histable *spontaneous;
// Private state variables
HistItem *maximum;
HistItem *minimum;
HistItem *maximum_inc;
HistItem *total;
HistItem *threshold;
// Perform the sort operation with this function
static int sort_compare_all (const void *a, const void *b, const void *arg);
static int sort_compare_dlayout (const void *a, const void *b, const void *arg);
static int sort_compare (HistItem *hi_1, HistItem *hi_2, Sort_type stype,
long ind, Hist_data *hdata);
// Allocate a new structure of dynamic size
HistItem *new_hist_item (Histable *obj);
// Flag indicating whether or not the Hist_data structure
// is owned by a DbeView, which has responsibility for
// deleting it, or not, in which case the last user deletes it.
// XXX this is very ugly, and arises from the inconsistent handling
// XXX of the Hist_data structure in various bits of code.
bool viewowned;
};
// This structure is destined to merge with Hist_data.
// We currently use it to present callstack data such as
// leak and allocation lists.
class DbeInstr;
struct CStack_data
{
struct CStack_item
{
CStack_item (long n);
~CStack_item ();
long count;
int64_t val;
Vector<DbeInstr*> *stack;
TValue *value; // numeric values
};
Vector<CStack_item*> *cstack_items;
CStack_item *total;
CStack_item *new_cstack_item ();
CStack_data (MetricList *);
long
size ()
{
return cstack_items->size ();
}
CStack_item *
fetch (long i)
{
return cstack_items->fetch (i);
}
~CStack_data ()
{
cstack_items->destroy ();
delete cstack_items;
delete total;
}
MetricList *metrics;
};
#endif /* _HIST_DATA_H */