diff options
Diffstat (limited to 'gprofng/src/MemorySpace.cc')
-rw-r--r-- | gprofng/src/MemorySpace.cc | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/gprofng/src/MemorySpace.cc b/gprofng/src/MemorySpace.cc new file mode 100644 index 0000000..3f7c78d --- /dev/null +++ b/gprofng/src/MemorySpace.cc @@ -0,0 +1,452 @@ +/* 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. */ + +#include "config.h" +#include <ctype.h> + +#include "util.h" +#include "DbeSession.h" +#include "Application.h" +#include "Experiment.h" +#include "Exp_Layout.h" +#include "MetricList.h" +#include "MemObject.h" +#include "PathTree.h" +#include "DbeView.h" +#include "Metric.h" +#include "MemorySpace.h" +#include "Table.h" +#include "IndexObject.h" + +MemObjType_t::MemObjType_t () +{ + type = -1; + name = NULL; + index_expr = NULL; + machmodel = NULL; + mnemonic = 0; + short_description = NULL; + long_description = NULL; +} + +MemObjType_t::~MemObjType_t () +{ + free (name); + free (index_expr); + free (machmodel); + free (short_description); + free (long_description); +} + +MemorySpace::MemorySpace (DbeView *_dbev, int _mstype) +{ + char *mname; + dbev = _dbev; + phaseIdx = -1; + + // set up the MemoryObject information + objs = new HashMap<uint64_t, MemObj*>; + mstype = _mstype; + msindex_exp = NULL; + msname = NULL; + msindex_exp_str = NULL; + + // find the memory space in the table + MemObjType_t *mot = findMemSpaceByIndex (mstype); + if (mot) + { + msname = dbe_strdup (mot->name); + if (mot->index_expr != NULL) + { + msindex_exp_str = dbe_strdup (mot->index_expr); + msindex_exp = dbeSession->ql_parse (msindex_exp_str); + if (msindex_exp == NULL) + // this was checked when the definition was created + abort (); + } + } + + // create the Total and Unknown objects + mname = dbe_strdup (NTXT ("<Total>")); + total_memobj = createMemObject ((uint64_t) - 2, mname); + mname = dbe_strdup (GTXT ("<Unknown>")); + unk_memobj = createMemObject ((uint64_t) - 1, mname); + hist_data_all = NULL; + selected_mo_index = (uint64_t) - 3; + sel_ind = -1; +} + +MemorySpace::~MemorySpace () +{ + reset (); + delete objs; + free (msname); + free (msindex_exp); + free (msindex_exp_str); +} + +void +MemorySpace::reset () +{ + if (hist_data_all != NULL) + { + delete hist_data_all; + hist_data_all = NULL; + } + // do not clear the selected object's index + // selected_mo_index = (uint64_t)-3; + + // destroy any existing objects, but keep the vector + // Now that we have a hashmap, which has its own vector, + // safe to delete and reallocate + delete objs; + objs = new HashMap<uint64_t, MemObj*>; +} + +// find a memory object by its memory-object index +int +MemorySpace::findMemObject (uint64_t indx) +{ + int index; + Hist_data::HistItem *hi; + if (indx == (uint64_t) - 3) + return -1; + + Vec_loop (Hist_data::HistItem *, hist_data_all->hist_items, index, hi) + { + if (((uint64_t) ((MemObj *) hi->obj)->id) == indx) + return index; + } + // object does not exist; filter change eliminated it, for example + return -1; +} + +// find the object referenced in the packet +MemObj * +MemorySpace::lookupMemObject (Experiment *exp, DataView *packets, long i) +{ + uint64_t idx; + uint64_t va = (uint64_t) packets->getLongValue (PROP_VADDR, i); + if (va == ABS_UNSUPPORTED) + // return NULL, to ignore the record + return NULL; + if (va < ABS_CODE_RANGE) + // The va is not valid, rather, it's an error code + // return the <Unknown> object + return unk_memobj; + + Expression::Context ctx (dbev, exp, packets, i); + idx = msindex_exp->eval (&ctx); + if (idx == (uint64_t) - 1) + return unk_memobj; + + // do a binary search for the memory object + MemObj *res = objs->get (idx); + if (res == NULL) + { + res = createMemObject (idx, NULL); + objs->put (idx, res); + } + else + return res; + + // recompute range + if (idx < idx_min) + idx_min = idx; + if (idx > idx_max) + idx_max = idx; + return res; +} + +MemObj * +MemorySpace::createMemObject (uint64_t index, char *moname) +{ + MemObj *res; + char *name; + if (moname != NULL) + { + res = new MemObj (index, moname); + return res; + } + + // Custom memory objects + // The memory_page_size is defined in the machine model file such + // as ./machinemodels/t4.ermm. + // Most users prefer to look at the hexadecimal version of virtual + // addresses. Display only the hexadecimal version of virtual addresses + // for all machine model views with an exception of virtual page size. + if (dbe_strcmp (msname, NTXT ("Memory_page_size")) == 0) + name = dbe_sprintf (NTXT ("%s 0x%16.16llx (%llu)"), msname, + (long long) index, (unsigned long long) index); + else if (dbe_strcmp (msname, NTXT ("Memory_in_home_lgrp")) == 0) + name = dbe_sprintf (NTXT ("%s: %s"), msname, + index == 1 ? GTXT ("True") : index == 0 ? GTXT ("False") + : GTXT ("<Unknown>")); + else if (dbe_strcmp (msname, NTXT ("Memory_lgrp")) == 0) + name = dbe_sprintf (NTXT ("%s %llu"), msname, (unsigned long long) index); + else + name = dbe_sprintf (NTXT ("%s 0x%16.16llx"), msname, (long long) index); + + res = new MemObj (index, name); + return res; +} + + +static Vector<MemObjType_t*> dyn_memobj_vec; +static Vector<MemObjType_t*> *dyn_memobj = &dyn_memobj_vec; +static Vector<int> *ordlist; + +// Static function to get a vector of custom memory object definitions + +Vector<void*> * +MemorySpace::getMemObjects () +{ + MemObjType_t *mot; + int ii; + int size = dyn_memobj->size (); + Vector<int> *indx = new Vector<int>(size); + Vector<char*> *name = new Vector<char*>(size); + Vector<char> *mnemonic = new Vector<char>(size); + Vector<char*> *formula = new Vector<char*>(size); + Vector<char*> *machmodel = new Vector<char*>(size); + Vector<int> *order = new Vector<int>(size); + Vector<char*> *sdesc = new Vector<char*>(size); + Vector<char*> *ldesc = new Vector<char*>(size); + + if (size > 0) + { + Vec_loop (MemObjType_t *, dyn_memobj, ii, mot) + { + indx->store (ii, mot->type); + order->store (ii, ii); + name->store (ii, dbe_strdup (mot->name)); + formula->store (ii, dbe_strdup (mot->index_expr)); + mnemonic->store (ii, mot->mnemonic); + sdesc->store (ii, mot->short_description == NULL ? NULL + : dbe_strdup (mot->short_description)); + ldesc->store (ii, mot->long_description == NULL ? NULL + : dbe_strdup (mot->long_description)); + if (mot->machmodel == NULL) + machmodel->store (ii, NULL); + else + machmodel->store (ii, dbe_strdup (mot->machmodel)); + } + } + Vector<void*> *res = new Vector<void*>(8); + res->store (0, indx); + res->store (1, name); + res->store (2, mnemonic); + res->store (3, formula); + res->store (4, machmodel); + res->store (5, order); + res->store (6, sdesc); + res->store (7, ldesc); + return (res); +} + +// Static function to set order of memory object tabs +void +MemorySpace::set_MemTabOrder (Vector<int> *orders) +{ + int size = orders->size (); + ordlist = new Vector<int>(size); + for (int i = 0; i < size; i++) + ordlist->store (i, orders->fetch (i)); +} + +// Static function to define a new memory object type +char * +MemorySpace::mobj_define (char *mname, char *mindex_exp, char *_machmodel, + char *short_description, char *long_description) +{ + MemObjType_t *mot; + + if (mname == NULL) + return dbe_strdup (GTXT ("No memory object name has been specified.")); + if (isalpha ((int) (mname[0])) == 0) + return dbe_sprintf (GTXT ("Memory Object type name %s does not begin with an alphabetic character"), + mname); + char *p = mname; + while (*p != 0) + { + if (isalnum ((int) (*p)) == 0 && *p != '_') + return dbe_sprintf (GTXT ("Memory Object type name %s contains a non-alphanumeric character"), + mname); + p++; + } + + mot = findMemSpaceByName (mname); + if (mot != NULL) + { + if (strcmp (mot->index_expr, mindex_exp) == 0) + // It's a redefinition, but the new definition is the same + return NULL; + return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"), + mname); + } + + // make sure the name is not in use + if (dbeSession->findIndexSpaceByName (mname) >= 0) + return dbe_sprintf (GTXT ("Memory/Index Object type name %s is already defined"), + mname); + + if (mindex_exp == NULL || *mindex_exp == 0) + return dbe_strdup (GTXT ("No index-expr has been specified.")); + + // verify that the index expression parses correctly + Expression *e = dbeSession->ql_parse (mindex_exp); + if (e == NULL) + return dbe_sprintf (GTXT ("Memory Object index expression is invalid: %s"), + mindex_exp); + delete e; + + // It's OK, create the new table entry + char *s = dbeSession->indxobj_define (mname, NULL, mindex_exp, + short_description, long_description); + if (s) + return s; + IndexObjType_t *indObj = dbeSession->findIndexSpace (mname); + + mot = new MemObjType_t; + mot->type = indObj->type; + indObj->memObj = mot; + mot->name = dbe_strdup (mname); + mot->index_expr = dbe_strdup (mindex_exp); + mot->mnemonic = MemorySpace::pickMnemonic (mname); + mot->machmodel = dbe_strdup (_machmodel); + mot->short_description = dbe_strdup (short_description); + mot->long_description = dbe_strdup (long_description); + + // add it to the list + dyn_memobj->append (mot); + + // tell the session + if (dbeSession != NULL) + dbeSession->mobj_define (mot); + return NULL; +} + +// Static function to delete a new memory object type + +char * +MemorySpace::mobj_delete (char *mname) +{ + if (mname == NULL) + return dbe_strdup (GTXT ("No memory object name has been specified.\n")); + + // search the dynamic types + for (long idx = 0, sz = VecSize (dyn_memobj); idx < sz; idx++) + { + MemObjType_t *mt = dyn_memobj->get (idx); + if (strcasecmp (mt->name, mname) == 0) + { + // delete it from the vector + mt = dyn_memobj->remove (idx); + delete mt; + dbeSession->removeIndexSpaceByName (mname); + return NULL; + } + } + return dbe_sprintf (GTXT ("Memory object `%s' is not defined.\n"), mname); +} + +// Static function to get a list of memory object names from a machine model + +Vector <char*> * +MemorySpace::getMachineModelMemObjs (char *mname) +{ + Vector <char *> *ret = new Vector <char *> (); + if (mname == NULL) + return ret; + + // search the memory objects + int idx; + MemObjType_t *mt; + Vec_loop (MemObjType_t*, dyn_memobj, idx, mt) + { + if (mt->machmodel != NULL && strcmp (mt->machmodel, mname) == 0) + { + char *n = dbe_strdup (mt->name); + ret->append (n); + } + } + return ret; +} + +char +MemorySpace::pickMnemonic (char *name) +{ + return name[0]; +} + +void +MemorySpace::get_filter_keywords (Vector <void*> *res) +{ + Vector <char*> *kwCategory = (Vector<char*>*) res->fetch (0); + Vector <char*> *kwCategoryI18N = (Vector<char*>*) res->fetch (1); + Vector <char*> *kwDataType = (Vector<char*>*) res->fetch (2); + Vector <char*> *kwKeyword = (Vector<char*>*) res->fetch (3); + Vector <char*> *kwFormula = (Vector<char*>*) res->fetch (4); + Vector <char*> *kwDescription = (Vector<char*>*) res->fetch (5); + Vector <void*> *kwEnumDescs = (Vector<void*>*) res->fetch (6); + + char *vtypeNames[] = VTYPE_TYPE_NAMES; + for (int i = 0, sz = dyn_memobj ? dyn_memobj->size () : 0; i < sz; i++) + { + MemObjType_t *obj = dyn_memobj->fetch (i); + kwCategory->append (dbe_strdup (NTXT ("FK_MEMOBJ"))); + kwCategoryI18N->append (dbe_strdup (GTXT ("Memory Object Definitions"))); + kwDataType->append (dbe_strdup (vtypeNames[TYPE_INT64])); + kwKeyword->append (dbe_strdup (obj->name)); + kwFormula->append (dbe_strdup (obj->index_expr)); + kwDescription->append (NULL); + kwEnumDescs->append (NULL); + } +} + +MemObjType_t * +MemorySpace::findMemSpaceByName (const char *mname) +{ + int idx; + MemObjType_t *mt; + + // search the dynamic types + Vec_loop (MemObjType_t*, dyn_memobj, idx, mt) + { + if (strcasecmp (mt->name, mname) == 0) + return mt; + } + return NULL; +} + +MemObjType_t * +MemorySpace::findMemSpaceByIndex (int index) +{ + int idx; + MemObjType_t *mt; + + // search the dynamic types + Vec_loop (MemObjType_t*, dyn_memobj, idx, mt) + { + if (mt->type == index) + return mt; + } + return NULL; +} |