ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
406 lines
9.8 KiB
C++
406 lines
9.8 KiB
C++
/* Copyright (C) 2021-2024 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 _PATH_TREE_H
|
|
#define _PATH_TREE_H
|
|
|
|
#include <vec.h>
|
|
#include <Map.h>
|
|
|
|
#include "dbe_structs.h"
|
|
#include "Hist_data.h"
|
|
#include "Histable.h"
|
|
#include "Metric.h"
|
|
|
|
typedef enum
|
|
{
|
|
NORMAL = 0, CANCELED
|
|
} PtreePhaseStatus;
|
|
|
|
class PathTree
|
|
{
|
|
public:
|
|
|
|
PathTree (DbeView *_dbev, int _indxtype = -1)
|
|
{
|
|
construct (_dbev, _indxtype, PATHTREE_MAIN);
|
|
}
|
|
|
|
~PathTree ();
|
|
|
|
static void make_deltas (int vtype, TValue *v1, TValue *v2);
|
|
static void make_ratios (int vtype, TValue *v1, TValue *v2);
|
|
|
|
typedef enum
|
|
{
|
|
COMPUTEOPT_NONE = 0,
|
|
COMPUTEOPT_OMP_CALLEE
|
|
} PtreeComputeOption;
|
|
|
|
Hist_data *compute_metrics (MetricList *, Histable::Type,
|
|
Hist_data::Mode, Vector<Histable*>*,
|
|
Histable*, Vector<Histable*>* sel_objs = NULL,
|
|
PtreeComputeOption flag = COMPUTEOPT_NONE);
|
|
// Get aggregated callstack data
|
|
CStack_data *get_cstack_data (MetricList *);
|
|
|
|
Vector<Histable*> *get_clr_instr (Histable *);
|
|
Vector<void*> *get_cle_instr (Histable *, Vector<Histable*>*&);
|
|
|
|
int
|
|
get_status ()
|
|
{
|
|
return status;
|
|
}
|
|
|
|
int
|
|
get_depth ()
|
|
{
|
|
return depth;
|
|
}
|
|
|
|
int
|
|
getStackProp ()
|
|
{
|
|
return stack_prop;
|
|
}
|
|
|
|
typedef long NodeIdx;
|
|
|
|
struct Node
|
|
{
|
|
inline void
|
|
reset ()
|
|
{
|
|
ancestor = 0;
|
|
descendants = NULL;
|
|
instr = NULL;
|
|
funclist = 0;
|
|
}
|
|
|
|
NodeIdx ancestor;
|
|
Vector<NodeIdx> *descendants;
|
|
Histable *instr;
|
|
NodeIdx funclist;
|
|
};
|
|
|
|
static const int CHUNKSZ = 16384;
|
|
|
|
inline Node *
|
|
NODE_IDX (NodeIdx idx)
|
|
{
|
|
return idx ? &chunks[idx / CHUNKSZ][idx % CHUNKSZ] : NULL;
|
|
}
|
|
|
|
// queue for messages (statistics for pathtree processing)
|
|
Emsg *fetch_stats (void); // fetch the queue of comment messages
|
|
void delete_stats (void); // delete the queue of stats messages
|
|
Emsg *fetch_warnings (void); // fetch the queue of warnings messages
|
|
void delete_warnings (void); // delete the queue of warnings messages
|
|
|
|
NodeIdx
|
|
get_func_nodeidx (Function * func)
|
|
{
|
|
return fn_map == NULL ? (NodeIdx) 0 : fn_map->get (func);
|
|
}
|
|
|
|
void print (FILE *);
|
|
void dumpNodes (FILE *, Histable *);
|
|
|
|
// flame charts functions - get values from ftree_internal
|
|
int get_ftree_depth (); // Depth of tree
|
|
Vector<void*>* get_ftree_level (BaseMetric *bm, int dpth);
|
|
Vector<void*>* get_ftree_node_children (BaseMetric *bm, NodeIdx node_idx);
|
|
Vector<Function*>* get_ftree_funcs ();
|
|
Vector<Function*>* get_funcs (); // Unique functions in tree
|
|
|
|
private:
|
|
|
|
enum
|
|
{
|
|
MAX_DESC_HTABLE_SZ = 65535
|
|
};
|
|
|
|
typedef struct hash_node
|
|
{
|
|
NodeIdx nd;
|
|
struct hash_node *next;
|
|
} hash_node_t;
|
|
|
|
int desc_htable_size;
|
|
int desc_htable_nelem;
|
|
hash_node_t **descHT;
|
|
|
|
struct Slot
|
|
{
|
|
int id;
|
|
ValueTag vtype;
|
|
union
|
|
{
|
|
int **mvals;
|
|
int64_t **mvals64;
|
|
};
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
PATHTREE_MAIN = 0,
|
|
PATHTREE_INTERNAL_OMP,
|
|
PATHTREE_INTERNAL_FUNCTREE
|
|
} PathTreeType;
|
|
|
|
DbeView *dbev;
|
|
int indxtype;
|
|
int stack_prop;
|
|
Expression *indx_expr;
|
|
Histable *total_obj;
|
|
Map<Function*, NodeIdx> *fn_map;
|
|
Map<uint64_t, NodeIdx> *pathMap;
|
|
Map<uint64_t, uint64_t> *hideMap;
|
|
int status;
|
|
NodeIdx root_idx;
|
|
Node *root;
|
|
int depth;
|
|
long nodes;
|
|
long dnodes;
|
|
long nchunks;
|
|
Node **chunks;
|
|
int nslots;
|
|
Slot *slots;
|
|
int phaseIdx;
|
|
int nexps;
|
|
Emsgqueue *statsq;
|
|
Emsgqueue *warningq;
|
|
Hist_data *hist_data;
|
|
int percent;
|
|
int ndone;
|
|
Histable **obj_list;
|
|
Node **node_list;
|
|
int *xlate;
|
|
bool cancel_ok;
|
|
PathTreeType pathTreeType;
|
|
PathTree *ptree_internal;
|
|
PathTree *ftree_internal; // function-based pathtree
|
|
bool ftree_needs_update;
|
|
Vector<Vector<NodeIdx>*> *depth_map; // for each depth level, list of nodes
|
|
|
|
void init ();
|
|
void fini ();
|
|
PtreePhaseStatus reset ();
|
|
PtreePhaseStatus add_experiment (int);
|
|
PtreePhaseStatus process_packets (Experiment*, DataView*, int);
|
|
DataView *get_filtered_events (int exp_index, int data_type);
|
|
void construct (DbeView *_dbev, int _indxtype, PathTreeType _pathTreeType);
|
|
|
|
PathTree (DbeView *_dbev, int _indxtype, PathTreeType _pathTreeType)
|
|
{
|
|
construct (_dbev, _indxtype, _pathTreeType);
|
|
}
|
|
|
|
inline int *
|
|
allocate_chunk (int **p, NodeIdx idx)
|
|
{
|
|
int *res = new int[CHUNKSZ];
|
|
for (int i = 0; i < CHUNKSZ; i++)
|
|
res[i] = 0;
|
|
p[idx] = res;
|
|
return res;
|
|
};
|
|
|
|
inline int64_t *
|
|
allocate_chunk (int64_t **p, NodeIdx idx)
|
|
{
|
|
int64_t *res = new int64_t[CHUNKSZ];
|
|
for (int i = 0; i < CHUNKSZ; i++)
|
|
res[i] = 0;
|
|
p[idx] = res;
|
|
return res;
|
|
};
|
|
|
|
inline Node *
|
|
allocate_chunk (Node **p, NodeIdx idx)
|
|
{
|
|
Node *res = new Node[CHUNKSZ];
|
|
for (int i = 0; i < CHUNKSZ; i++)
|
|
res[i].reset ();
|
|
p[idx] = res;
|
|
return res;
|
|
};
|
|
|
|
inline bool
|
|
IS_MVAL_ZERO (Slot& slot, NodeIdx idx)
|
|
{
|
|
if (slot.vtype == VT_LLONG || slot.vtype == VT_ULLONG)
|
|
{
|
|
int64_t *tmp = slot.mvals64[idx / CHUNKSZ];
|
|
return tmp ? tmp[idx % CHUNKSZ] == 0 : true;
|
|
}
|
|
else
|
|
{
|
|
int *tmp = slot.mvals[idx / CHUNKSZ];
|
|
return tmp ? tmp[idx % CHUNKSZ] == 0 : true;
|
|
}
|
|
}
|
|
|
|
inline void
|
|
ASN_METRIC_VAL (TValue& v, Slot& slot, NodeIdx idx)
|
|
{
|
|
if (slot.vtype == VT_LLONG)
|
|
{
|
|
int64_t *tmp = slot.mvals64[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.ll = tmp[idx % CHUNKSZ];
|
|
}
|
|
else if (slot.vtype == VT_ULLONG)
|
|
{
|
|
uint64_t *tmp = (uint64_t *) slot.mvals64[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.ull = tmp[idx % CHUNKSZ];
|
|
}
|
|
else
|
|
{
|
|
int *tmp = slot.mvals[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.i = tmp[idx % CHUNKSZ];
|
|
}
|
|
}
|
|
|
|
inline void
|
|
ADD_METRIC_VAL (TValue& v, Slot& slot, NodeIdx idx)
|
|
{
|
|
if (slot.vtype == VT_LLONG)
|
|
{
|
|
int64_t *tmp = slot.mvals64[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.ll += tmp[idx % CHUNKSZ];
|
|
}
|
|
else if (slot.vtype == VT_ULLONG)
|
|
{
|
|
uint64_t *tmp = (uint64_t *) slot.mvals64[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.ull += tmp[idx % CHUNKSZ];
|
|
}
|
|
else
|
|
{
|
|
int *tmp = slot.mvals[idx / CHUNKSZ];
|
|
if (tmp) v.i += tmp[idx % CHUNKSZ];
|
|
}
|
|
}
|
|
|
|
inline void
|
|
SUB_METRIC_VAL (TValue& v, Slot& slot, NodeIdx idx)
|
|
{
|
|
if (slot.vtype == VT_LLONG)
|
|
{
|
|
int64_t *tmp = slot.mvals64[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.ll -= tmp[idx % CHUNKSZ];
|
|
}
|
|
else if (slot.vtype == VT_ULLONG)
|
|
{
|
|
uint64_t *tmp = (uint64_t *) slot.mvals64[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.ull -= tmp[idx % CHUNKSZ];
|
|
}
|
|
else
|
|
{
|
|
int *tmp = slot.mvals[idx / CHUNKSZ];
|
|
if (tmp)
|
|
v.i -= tmp[idx % CHUNKSZ];
|
|
}
|
|
}
|
|
|
|
inline void
|
|
INCREMENT_METRIC (Slot *slot, NodeIdx idx, int64_t val)
|
|
{
|
|
if (slot->vtype == VT_LLONG)
|
|
{
|
|
int64_t *tmp = slot->mvals64[idx / CHUNKSZ];
|
|
if (tmp == NULL)
|
|
tmp = allocate_chunk (slot->mvals64, idx / CHUNKSZ);
|
|
tmp[idx % CHUNKSZ] += val;
|
|
}
|
|
else if (slot->vtype == VT_ULLONG)
|
|
{
|
|
uint64_t *tmp = (uint64_t *) slot->mvals64[idx / CHUNKSZ];
|
|
if (tmp == NULL)
|
|
tmp = (uint64_t *) allocate_chunk (slot->mvals64, idx / CHUNKSZ);
|
|
tmp[idx % CHUNKSZ] += val;
|
|
}
|
|
else
|
|
{
|
|
int *tmp = slot->mvals[idx / CHUNKSZ];
|
|
if (tmp == NULL)
|
|
tmp = allocate_chunk (slot->mvals, idx / CHUNKSZ);
|
|
tmp[idx % CHUNKSZ] += (int) val;
|
|
}
|
|
}
|
|
|
|
inline Slot *
|
|
SLOT_IDX (int idx)
|
|
{
|
|
if (idx < 0 || idx >= nslots)
|
|
return NULL;
|
|
return &slots[idx];
|
|
}
|
|
|
|
int allocate_slot (int id, ValueTag vtype);
|
|
void allocate_slots (Slot *slots, int nslots);
|
|
int find_slot (int);
|
|
NodeIdx new_Node (NodeIdx, Histable*, bool);
|
|
NodeIdx find_path (Experiment*, DataView*, long);
|
|
NodeIdx find_desc_node (NodeIdx, Histable*, bool);
|
|
NodeIdx find_in_desc_htable (NodeIdx, Histable*, bool);
|
|
Histable *get_hist_obj (Node *, Histable* = NULL);
|
|
Histable *get_hist_func_obj (Node *);
|
|
Histable *get_compare_obj (Histable *obj);
|
|
void get_metrics (NodeIdx, int);
|
|
void get_metrics (Vector<Function*> *, Histable *);
|
|
void get_clr_metrics (Vector<Histable*>*, NodeIdx, int, int);
|
|
void get_clr_metrics (Vector<Histable*>*);
|
|
void get_cle_metrics (Vector<Histable*>*, NodeIdx, int, int, int);
|
|
void get_cle_metrics (Vector<Histable*>*, NodeIdx, int);
|
|
void get_cle_metrics (Vector<Histable*>*);
|
|
void get_self_metrics (Vector<Histable*>*, NodeIdx, bool, int);
|
|
void get_self_metrics (Vector<Histable*>*);
|
|
void get_self_metrics (Histable *, Vector<Function*> *funclist,
|
|
Vector<Histable*>* sel_objs = NULL);
|
|
void get_cstack_list (CStack_data *, NodeIdx, int);
|
|
|
|
// Generate PathTree based on Functions instead of Instructions // Used for flame chart
|
|
void ftree_reset ();
|
|
void ftree_build (PathTree *mstr);
|
|
void ftree_build (PathTree *mstr, NodeIdx mstr_node_idx, NodeIdx local_node_idx);
|
|
void depth_map_build ();
|
|
void depth_map_build (NodeIdx node_idx, int depth);
|
|
Vector<void*>* get_level (BaseMetric *bm, int dpth);
|
|
Vector<void*>* get_nodes (BaseMetric *bm, Vector<NodeIdx> *node_idxs);
|
|
Vector<void*>* get_node_children (BaseMetric *bm, NodeIdx node_idx);
|
|
bool ftree_debug_match_hist_data (Hist_data *data, Hist_data *data_tmp);
|
|
void ftree_dump ();
|
|
|
|
// Debugging functions
|
|
void print (FILE *, PathTree::Node*, int);
|
|
void printn (FILE *);
|
|
int dbg_nodes (PathTree::Node*);
|
|
};
|
|
|
|
#endif /* _PATH_TREE_H */
|