diff options
Diffstat (limited to 'gprofng/src/Expression.cc')
-rw-r--r-- | gprofng/src/Expression.cc | 1279 |
1 files changed, 1279 insertions, 0 deletions
diff --git a/gprofng/src/Expression.cc b/gprofng/src/Expression.cc new file mode 100644 index 0000000..49c94a8 --- /dev/null +++ b/gprofng/src/Expression.cc @@ -0,0 +1,1279 @@ +/* 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 <assert.h> +#include "CallStack.h" +#include "DbeSession.h" +#include "DbeView.h" +#include "DataObject.h" +#include "Exp_Layout.h" +#include "Experiment.h" +#include "Module.h" +#include "LoadObject.h" +#include "Expression.h" +#include "Function.h" +#include "Histable.h" +#include "Sample.h" +#include "Table.h" + +////////////////////////////////////////////////////////// +// class Expression::Context + +static const uint64_t INDXOBJ_EXPGRID_SHIFT = 60; +static const uint64_t INDXOBJ_EXPID_SHIFT = 32; + +Expression::Context::Context (DbeView *_dbev, Experiment *_exp) +{ + dbev = _dbev; + exp = _exp; + dview = NULL; + eventId = 0; +} + +Expression::Context::Context (DbeView *_dbev, Experiment *_exp, + DataView *_dview, long _eventId) +{ + dbev = _dbev; + exp = _exp; + dview = _dview; + eventId = _eventId; +} + +////////////////////////////////////////////////////////// +// class Expression +Expression::Expression (OpCode _op, uint64_t _v) +{ + op = _op; + v = Value (_v); + arg0 = NULL; + arg1 = NULL; +} + +Expression::Expression (OpCode _op, const Expression *_arg0, + const Expression *_arg1) +{ + op = _op; + v = Value (); + arg0 = NULL; + arg1 = NULL; + if (_arg0) + arg0 = _arg0->copy (); + if (_arg1) + arg1 = _arg1->copy (); +} + +Expression::~Expression () +{ + delete arg0; + delete arg1; +} + +Expression::Expression (const Expression &rhs) +{ + op = rhs.op; + arg0 = NULL; + arg1 = NULL; + if (rhs.arg0) + arg0 = rhs.arg0->copy (); + if (rhs.arg1) + arg1 = rhs.arg1->copy (); + v = Value (rhs.v); + fixupValues (); +} + +Expression::Expression (const Expression *rhs) +{ + arg0 = NULL; + arg1 = NULL; + copy (rhs); +} + +void +Expression::copy (const Expression *rhs) +{ + op = rhs->op; + delete arg0; + delete arg1; + arg0 = NULL; + arg1 = NULL; + if (rhs->arg0) + arg0 = rhs->arg0->copy (); + if (rhs->arg1) + arg1 = rhs->arg1->copy (); + v = Value (rhs->v); + fixupValues (); +} + +Expression & +Expression::operator= (const Expression &rhs) +{ + if (this == &rhs) + return *this; + copy (&rhs); + return *this; +} + +void +Expression::fixupValues () +{ + if (v.next) + { + assert (arg0 && v.next == &(arg0->v)); + v.next = &(arg0->v); + } +} + +bool +Expression::getVal (int propId, Context *ctx) +{ + v.val = 0; + v.next = NULL; + int origPropId = propId; + switch (propId) + { + default: + { + if (!ctx->dview) + return false; + PropDescr *propDscr = ctx->dview->getProp (propId); + if (!propDscr) + return false; + switch (propDscr->vtype) + { + case TYPE_INT32: + v.val = ctx->dview->getIntValue (propId, ctx->eventId); + break; + case TYPE_UINT32: + v.val = (uint32_t) ctx->dview->getIntValue (propId, ctx->eventId); //prevent sign extension + break; + case TYPE_INT64: + case TYPE_UINT64: + v.val = ctx->dview->getLongValue (propId, ctx->eventId); + break; + case TYPE_OBJ: + // YM: not sure if we should allow this + v.val = (long long) ctx->dview->getObjValue (propId, ctx->eventId); + break; + case TYPE_STRING: + case TYPE_DOUBLE: + default: + return false; // Weird, programming error? + } + break; + } + case PROP_FREQ_MHZ: + if (ctx->exp && ctx->exp->clock) + v.val = ctx->exp->clock; + else + return false; + break; + case PROP_PID: + if (ctx->exp == NULL) + return false; + v.val = ctx->exp->getPID (); + break; + case PROP_EXPID: + if (ctx->exp == NULL) + return false; + v.val = ctx->exp->getUserExpId (); + break; + case PROP_EXPID_CMP: + if (ctx->exp == NULL) + return false; + else + { + Experiment *exp = ctx->exp; + if (ctx->dbev && ctx->dbev->comparingExperiments ()) + exp = (Experiment *) exp->get_compare_obj (); + v.val = exp->getUserExpId (); + } + break; + case PROP_EXPGRID: + if (ctx->exp == NULL) + return false; + v.val = ctx->exp->groupId; + break; + case PROP_NTICK_USEC: + if (ctx->exp == NULL) + return false; + if (ctx->dview && ctx->dview->getProp (PROP_NTICK)) + v.val = ctx->dview->getIntValue (PROP_NTICK, ctx->eventId) + * ctx->exp->get_params ()->ptimer_usec; + else + return false; + break; + case PROP_ATSTAMP: + case PROP_ETSTAMP: + if (ctx->exp == NULL) + return false; + if (ctx->dview && ctx->dview->getProp (PROP_TSTAMP)) + v.val = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); + else + return false; + if (propId == PROP_ATSTAMP) + break; // absolute time, no adjustments + // propId==PROP_ETSTAMP + // calculate relative time from start of this experiment + v.val -= ctx->exp->getStartTime (); + break; + case PROP_TSTAMP: + case PROP_TSTAMP_LO: + case PROP_TSTAMP_HI: + { + if (ctx->exp == NULL) + return false; + if (!(ctx->dview && ctx->dview->getProp (PROP_TSTAMP))) + return false; + hrtime_t tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); + // compute relative time from start of founder experiment + v.val = tstamp - ctx->exp->getStartTime () + + ctx->exp->getRelativeStartTime (); + if (propId == PROP_TSTAMP) + break; + if (ctx->dview->getProp (PROP_EVT_TIME)) + { + hrtime_t delta = ctx->dview->getLongValue (PROP_EVT_TIME, ctx->eventId); + if (propId == PROP_TSTAMP_LO) + { + if (delta > 0) + { // positive delta means TSTAMP is at end + // TSTAMP_LO = TSTAMP-delta + v.val -= delta; + break; + } + break; + } + else + { // PROP_TSTAMP_HI + if (delta < 0) + { // negative delta means TSTAMP is at start + // TSTAMP_HI = TSTAMP+(-delta) + v.val -= delta; + break; + } + break; + } + } + else if (ctx->dview->getProp (PROP_TSTAMP2)) + { + if (propId == PROP_TSTAMP_HI) + { + hrtime_t tstamp2 = ctx->dview->getLongValue (PROP_TSTAMP2, + ctx->eventId); + if (tstamp2 == 0) + break; // if not initialized, event does not have duration + if (tstamp2 == MAX_TIME) + tstamp2 = ctx->exp->getLastEvent (); + hrtime_t delta = tstamp2 - tstamp; + if (delta >= 0) + { + v.val += delta; + break; + } + break; // weird, delta should not be negative + } + break; // PROP_TSTAMP_LO, no modification needed + } + break; // should never be hit + } + case PROP_IOHEAPBYTES: + { + propId = PROP_IONBYTE; + if (ctx->dview == NULL) + return false; + if (!ctx->dview->getProp (propId)) + { // has property? + propId = PROP_HSIZE; + if (!ctx->dview->getProp (propId)) + return false; + } + v.val = ctx->dview->getLongValue (propId, ctx->eventId); + break; + } + case PROP_SAMPLE_MAP: + { + if (ctx->exp == NULL) + return false; + if (ctx->dview == NULL) + return false; + if (ctx->dview->getProp (PROP_SAMPLE)) + v.val = ctx->dview->getIntValue (PROP_SAMPLE, ctx->eventId); + else + { // does not have property, convert to time. + uint64_t tstamp; + tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); + Sample *sample = ctx->exp->map_event_to_Sample (tstamp); + v.val = sample ? sample->get_number () : -1; + } + break; + } + case PROP_GCEVENT_MAP: + { + if (ctx->exp == NULL) + return false; + if (ctx->dview == NULL) + return false; + if (ctx->dview->getProp (PROP_GCEVENT)) + v.val = ctx->dview->getIntValue (PROP_GCEVENT, ctx->eventId); + else + { // does not have property, convert to time. + uint64_t tstamp; + tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); + GCEvent *gcevent = ctx->exp->map_event_to_GCEvent (tstamp); + v.val = gcevent ? gcevent->id : 0; + } + break; + } + case PROP_LEAF: + { + if (ctx->dview == NULL) + return false; + VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER; + int prop_id; + if (vmode == VMODE_MACHINE) + prop_id = PROP_MSTACK; + else if (vmode == VMODE_EXPERT) + prop_id = PROP_XSTACK; + else + prop_id = PROP_USTACK; + if (!ctx->dview->getProp (prop_id)) + return false; + Histable *obj = CallStack::getStackPC (ctx->dview->getObjValue (prop_id, ctx->eventId), 0); + Function *func = (Function*) obj->convertto (Histable::FUNCTION); + v.val = func->id; // LEAF + break; + } + case PROP_STACKID: + { + VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER; + if (vmode == VMODE_MACHINE) + propId = PROP_MSTACK; + else if (vmode == VMODE_EXPERT) + propId = PROP_XSTACK; + else + propId = PROP_USTACK; + if (ctx->dview == NULL) + return false; + if (!ctx->dview->getProp (propId)) + return false; + v.val = (long) ctx->dview->getObjValue (propId, ctx->eventId); + break; + } + case PROP_STACKL: + case PROP_STACKI: + case PROP_STACK: + { + VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER; + if (vmode == VMODE_MACHINE) + propId = PROP_MSTACK; + else if (vmode == VMODE_EXPERT) + propId = PROP_XSTACK; + else + propId = PROP_USTACK; + } + // no break; + case PROP_MSTACKL: + case PROP_XSTACKL: + case PROP_USTACKL: + case PROP_MSTACKI: + case PROP_XSTACKI: + case PROP_USTACKI: + switch (propId) + { + case PROP_MSTACKL: + case PROP_MSTACKI: + propId = PROP_MSTACK; + break; + case PROP_XSTACKL: + case PROP_XSTACKI: + propId = PROP_XSTACK; + break; + case PROP_USTACKL: + case PROP_USTACKI: + propId = PROP_USTACK; + break; + default: + break; + } + // no break; + case PROP_MSTACK: + case PROP_XSTACK: + case PROP_USTACK: + { + if (ctx->dview == NULL) + return false; + if (!ctx->dview->getProp (propId)) + return false; + bool hide_mode = !ctx->dbev->isShowAll () + || ctx->dbev->isFilterHideMode (); + Expression *cur = this; + for (CallStackNode *stack = (CallStackNode *) + ctx->dview->getObjValue (propId, ctx->eventId); + stack; stack = stack->get_ancestor ()) + { + Histable *hist = stack->get_instr (); + if (origPropId == PROP_STACK || origPropId == PROP_MSTACK + || origPropId == PROP_XSTACK || origPropId == PROP_USTACK) + { + cur->v.val = hist->convertto (Histable::FUNCTION)->id; + cur->v.fn = cur->v.val; + } + else if (origPropId == PROP_STACKL || origPropId == PROP_MSTACKL + || origPropId == PROP_XSTACKL || origPropId == PROP_USTACKL) + { + cur->v.val = hist->convertto (Histable::LINE)->id; + if (hide_mode) + cur->v.fn = hist->convertto (Histable::FUNCTION)->id; + else + cur->v.fn = 0; + } + else if (origPropId == PROP_STACKI || origPropId == PROP_MSTACKI + || origPropId == PROP_XSTACKI || origPropId == PROP_USTACKI) + { + cur->v.val = hist->convertto (Histable::INSTR)->id; + if (hide_mode) + cur->v.fn = hist->convertto (Histable::FUNCTION)->id; + else + cur->v.fn = 0; + } + if (cur->arg1 == NULL) + cur->arg1 = new Expression (OP_NONE, (uint64_t) 0); + if (stack->get_ancestor () == NULL) + { + if (origPropId == PROP_STACKL || origPropId == PROP_MSTACKL + || origPropId == PROP_XSTACKL || origPropId == PROP_USTACKL + || origPropId == PROP_STACKI || origPropId == PROP_MSTACKI + || origPropId == PROP_XSTACKI || origPropId == PROP_USTACKI) + { + cur->v.next = NULL; + continue; + } + } + cur->v.next = &cur->arg1->v; + cur = cur->arg1; + } + if (origPropId == PROP_STACK || origPropId == PROP_MSTACK + || origPropId == PROP_XSTACK || origPropId == PROP_USTACK) + { + cur->v.val = dbeSession->get_Total_Function ()->id; + cur->v.fn = cur->v.val; + cur->v.next = NULL; + } + break; + } + case PROP_DOBJ: + { + if (ctx->dview == NULL) + return false; + if (!ctx->dview->getProp (PROP_DOBJ)) + return false; + DataObject *dobj = (DataObject*) + ctx->dview->getObjValue (PROP_DOBJ, ctx->eventId); + if (dobj != NULL) + { + Expression *cur = this; + for (;;) + { + cur->v.val = dobj->id; + dobj = dobj->parent; + if (dobj == NULL) + break; + if (cur->arg1 == NULL) + cur->arg1 = new Expression (OP_NONE, (uint64_t) 0); + cur->v.next = &cur->arg1->v; + cur = cur->arg1; + } + cur->v.next = NULL; + } + break; + } + case PROP_CPRID: + case PROP_TSKID: + { + if (ctx->dview == NULL) + return false; + if (!ctx->dview->getProp (propId)) + return false; + CallStackNode *ompstack = (CallStackNode *) + ctx->dview->getObjValue (propId, ctx->eventId); + Histable *hobj = ompstack->get_instr (); + if (hobj != NULL) + v.val = hobj->id; + break; + } + case PROP_JTHREAD: + { + if (ctx->exp == NULL) + return false; + if (ctx->dview == NULL) + return false; + if (!ctx->dview->getProp (propId)) + return false; + uint64_t tstamp; + tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId); + uint32_t thrid; + uint64_t jthr_id = 0; + thrid = ctx->dview->getIntValue (PROP_THRID, ctx->eventId); + JThread *jthread = ctx->exp->map_pckt_to_Jthread (thrid, tstamp); + if (jthread != JTHREAD_NONE && jthread != JTHREAD_DEFAULT) + { + jthr_id = jthread->jthr_id; + uint64_t grid = ctx->exp->groupId; + uint64_t expid = ctx->exp->getUserExpId (); + v.val = (grid << INDXOBJ_EXPGRID_SHIFT) | + (expid << INDXOBJ_EXPID_SHIFT) | jthr_id; + } + break; + } + } + return true; +} + +bool +Expression::bEval (Context *ctx) +{ + uint64_t v0, v1; + switch (op) + { + case OP_DEG: + if (!arg1->bEval (ctx)) + return false; + if (arg1->v.val < 0) + { + v.val = 0; + return true; + } + if (!arg0->bEval (ctx)) + { + return false; + } + v0 = arg0->v.val; + v1 = arg1->v.val; + for (v.val = 1; v1 > 0; v1--) + v.val *= v0; + return true; + case OP_MUL: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val * arg1->v.val; + return true; + } + return false; + case OP_DIV: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v1 = arg1->v.val; + v.val = (v1 == 0) ? 0 : (arg0->v.val / v1); + return true; + } + return false; + case OP_REM: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v1 = arg1->v.val; + v.val = (v1 == 0) ? 0 : (arg0->v.val % v1); + return true; + } + return false; + case OP_ADD: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val + arg1->v.val; + // DBFIXME LIBRARY VISIBILITY + // hack to pass v.fn value to new expression for leaf filters USTACK+0 + v.fn = arg0->v.fn + arg1->v.fn; + return true; + } + return false; + case OP_MINUS: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val - arg1->v.val; + return true; + } + return false; + case OP_LS: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val << arg1->v.val; + return true; + } + return false; + case OP_RS: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val >> arg1->v.val; + return true; + } + return false; + case OP_LT: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val < arg1->v.val ? 1 : 0; + return true; + } + return false; + case OP_LE: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val <= arg1->v.val ? 1 : 0; + return true; + } + return false; + case OP_GT: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val > arg1->v.val ? 1 : 0; + return true; + } + return false; + case OP_GE: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val >= arg1->v.val ? 1 : 0; + return true; + } + return false; + case OP_EQ: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val == arg1->v.val ? 1 : 0; + return true; + } + return false; + case OP_NE: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val != arg1->v.val ? 1 : 0; + return true; + } + return false; + case OP_BITAND: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val & arg1->v.val; + return true; + } + return false; + case OP_BITXOR: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val ^ arg1->v.val; + return true; + } + return false; + case OP_BITOR: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v.val = arg0->v.val | arg1->v.val; + return true; + } + return false; + case OP_AND: + if (arg0->bEval (ctx)) + { + if (arg0->v.val == 0) + { + v.val = 0; + return true; + } + if (arg1->bEval (ctx)) + { + v.val = arg1->v.val == 0 ? 0 : 1; + return true; + } + return false; + } + if (arg1->bEval (ctx) && arg1->v.val == 0) + { + v.val = 0; + return true; + } + return false; + case OP_OR: + if (arg0->bEval (ctx)) + { + if (arg0->v.val != 0) + { + v.val = 1; + return true; + } + if (arg1->bEval (ctx)) + { + v.val = arg1->v.val == 0 ? 0 : 1; + return true; + } + return false; + } + if (arg1->bEval (ctx) && arg1->v.val != 0) + { + v.val = 1; + return true; + } + return false; + case OP_NEQV: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v0 = arg0->v.val; + v1 = arg1->v.val; + v.val = (v0 == 0 && v1 != 0) || (v0 != 0 && v1 == 0) ? 1 : 0; + return true; + } + return false; + case OP_EQV: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + v0 = arg0->v.val; + v1 = arg1->v.val; + v.val = (v0 == 0 && v1 == 0) || (v0 != 0 && v1 != 0) ? 1 : 0; + return true; + } + return false; + case OP_QWE: + if (arg0->bEval (ctx)) + { + if (arg0->v.val != 0) + { + if (arg1->arg0->bEval (ctx)) + { + v.val = arg1->arg0->v.val; + return true; + } + } + else + { + if (arg1->arg1->bEval (ctx)) + { + v.val = arg1->arg1->v.val; + return true; + } + } + } + return false; + case OP_COMMA: + if (arg0->bEval (ctx)) + { + v.next = &arg0->v; + if (arg1->bEval (ctx)) + { + v.val = arg1->v.val; + return true; + } + } + return false; + case OP_IN: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + for (Value *s = &arg0->v; s; s = s->next) + { + bool found = false; + for (Value *t = &arg1->v; t; t = t->next) + { + if (t->val == s->val) + { + found = true; + break; + } + } + if (!found) + { + v.val = 0; + return true; + } + } + v.val = 1; + return true; + } + return false; + case OP_SOMEIN: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + for (Value *s = &arg0->v; s; s = s->next) + { + for (Value *t = &arg1->v; t; t = t->next) + { + if (t->val == s->val) + { + v.val = 1; + return true; + } + } + } + v.val = 0; + return true; + } + return false; + case OP_ORDRIN: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + for (Value *t0 = &arg1->v; t0; t0 = t0->next) + { + bool found = true; + for (Value *s = &arg0->v, *t = t0; s; s = s->next, t = t->next) + { + if (t == NULL || t->val != s->val) + { + found = false; + break; + } + } + if (found) + { + v.val = 1; + return true; + } + } + v.val = 0; + return true; + } + return false; + // LIBRARY_VISIBILITY + case OP_LIBRARY_IN: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + for (Value *s = &arg0->v; s; s = s->next) + { + bool found = false; + uint64_t objId = s->val; + Histable *obj = dbeSession->findObjectById (objId); + bool libraryFound = false; + Function *fn; + if (obj != NULL && obj->get_type () == Histable::FUNCTION) + { + fn = (Function *) obj; + if (fn->isHideFunc) + // this belongss to a loadobject in hide/library mode + libraryFound = true; + } + + if (libraryFound) + { + uint64_t lo_id = fn->module->loadobject->id; + for (Value *t = &arg1->v; t; t = t->next) + { + uint64_t t_id = t->fn; + Histable *obj2 = dbeSession->findObjectById (t_id); + if (obj2 != NULL + && obj2->get_type () == Histable::FUNCTION) + { + Function *func2 = (Function *) obj2; + uint64_t lo_id2 = func2->module->loadobject->id; + if (lo_id2 == lo_id) + { + found = true; + break; + } + } + } + } + else + { + // Not a loadobject + for (Value *t = &arg1->v; t; t = t->next) + { + if (t->val == s->val) + { + found = true; + break; + } + } + } + if (!found) + { + v.val = 0; + return true; + } + } + v.val = 1; + return true; + } + return false; + case OP_LIBRARY_SOMEIN: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + for (Value *s = &arg0->v; s; s = s->next) + { + uint64_t objId = s->val; + Histable *obj = dbeSession->findObjectById (objId); + bool libraryFound = false; + Function *fn; + if (obj != NULL && obj->get_type () == Histable::FUNCTION) + { + fn = (Function *) obj; + if (fn->isHideFunc) + // this belongs to a loadobject in hide/library mode + libraryFound = true; + } + + if (libraryFound) + { + uint64_t lo_id = fn->module->loadobject->id; + for (Value *t = &arg1->v; t; t = t->next) + { + uint64_t t_id = t->fn; + Histable *obj2 = dbeSession->findObjectById (t_id); + if (obj2 != NULL && obj2->get_type () == Histable::FUNCTION) + { + Function *func2 = (Function *) obj2; + uint64_t lo_id2 = func2->module->loadobject->id; + if (lo_id2 == lo_id) + { + v.val = 1; + return true; + } + } + } + } + else + { + for (Value *t = &arg1->v; t; t = t->next) + if (t->val == s->val) + { + v.val = 1; + return true; + } + } + } + v.val = 0; + return true; + } + return false; + case OP_LIBRARY_ORDRIN: + if (arg0->bEval (ctx) && arg1->bEval (ctx)) + { + for (Value *t0 = &arg1->v; t0; t0 = t0->next) + { + bool found = true; + Value *t = t0; + for (Value *s = &arg0->v; s; s = s->next) + { + // start comparing s->val with t->val + // if matches move on to s->next and t->next + uint64_t objId = s->val; + Histable *obj = dbeSession->findObjectById (objId); + bool libraryFound = false; + Function *fn; + if (obj != NULL && obj->get_type () == Histable::FUNCTION) + { + fn = (Function *) obj; + if (fn->isHideFunc) + libraryFound = true; + } + if (libraryFound) + { + // s->val is from a loadobject + // check if t->val is a func whose loadobject matches s->val + uint64_t lo_id = fn->module->loadobject->id; + uint64_t t_id = t->fn; + Histable *obj2 = dbeSession->findObjectById (t_id); + if (obj2 != NULL + && obj2->get_type () == Histable::FUNCTION) + { + Function *func2 = (Function *) obj2; + uint64_t lo_id2 = func2->module->loadobject->id; + if (lo_id2 != lo_id) + { + // no match + found = false; + break; + } + else + { + // t->val is a func whose loadobject matches s->val + while (t != NULL && lo_id2 == lo_id) + { + // skip frames with same load object + t = t->next; + t_id = t->fn; + obj2 = dbeSession->findObjectById (t_id); + if (obj2 != NULL + && obj2->get_type () == Histable::FUNCTION) + { + func2 = (Function *) obj2; + lo_id2 = func2->module->loadobject->id; + } + } + } + } + } + else + { + if (t == NULL || t->val != s->val) + { + found = false; + break; + } + t = t->next; + } + } + if (found) + { + v.val = 1; + return true; + } + } + v.val = 0; + return true; + } + return false; + case OP_BITNOT: + if (arg0->bEval (ctx)) + { + v.val = ~arg0->v.val; + return true; + } + return false; + case OP_NOT: + if (arg0->bEval (ctx)) + { + v.val = !arg0->v.val; + return true; + } + return false; + case OP_NUM: + return true; + case OP_NAME: + if (ctx && arg0->bEval (ctx) && getVal ((int) arg0->v.val, ctx)) + return true; + return false; + case OP_FUNC: + // FNAME is completely processed by pEval for now + v.val = 0; + return true; + case OP_HASPROP: + if (!ctx || !ctx->dview) + return false; // can't be resolved (occurs during pEval() ) + else if (arg0->op != OP_NAME || !arg0->arg0) + return false; // weird, wrong arg type + else + { + int propId = (int) arg0->arg0->v.val; + if (ctx->dview->getProp (propId)) + v.val = 1; + else + v.val = 0; + return true; + } + case OP_FILE: + // FILENAME is completely processed by pEval for now + v.val = 0; + return true; + case OP_JAVA: + //JGROUP & JPARENT is completely processed by pEval for now + v.val = 0; + return true; + case OP_COLON: + return false; // OK for arg1 of OP_QWE + default: +#ifdef IPC_LOG + fprintf (stderr, "INTERNAL ERROR: Expression::eval op=%d\n", op); +#endif + return false; + } + return false; +} + +Expression * +Expression::pEval (Context *ctx) // partial evaluation (dview may be NULL) +{ + Expression *res = NULL; + switch (op) + { + case OP_FUNC: + { + Vector<Histable*> *objs = NULL; + if (arg0->v.val == FUNC_FNAME) + { + Histable::NameFormat nfmt = ctx ? ctx->dbev->get_name_format () : Histable::NA; + objs = (Vector<Histable*>*)dbeSession->match_func_names ((char*) arg1->v.val, nfmt); + } + else if (arg0->v.val == FUNC_DNAME) + objs = (Vector<Histable*>*)dbeSession->match_dobj_names ((char*) arg1->v.val); + Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0); + res = cur; + int i = objs ? objs->size () - 1 : -1; + for (; i >= 0; i--) + { + cur->v.val = objs->fetch (i)->id; + if (i == 0) + break; + cur->arg0 = new Expression (OP_NONE, (uint64_t) 0); + cur->v.next = &cur->arg0->v; + cur = cur->arg0; + } + cur->v.next = NULL; + if (objs) + delete objs; + break; + } + case OP_JAVA: + { + Vector<JThread*> *objs = NULL; + Vector<uint64_t> *grids = NULL; + Vector<uint64_t> *expids = NULL; + if (arg0->v.val == JAVA_JGROUP) + objs = dbeSession->match_java_threads ((char*) arg1->v.val, 0, grids, + expids); + else if (arg0->v.val == JAVA_JPARENT) + objs = dbeSession->match_java_threads ((char*) arg1->v.val, 1, grids, + expids); + Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0); + res = cur; + int i = objs ? objs->size () - 1 : -1; + for (; i >= 0; i--) + { + uint64_t jthr_id = 0; + JThread *jthread = (JThread *) (objs->fetch (i)); + jthr_id = jthread->jthr_id; + uint64_t grid = grids->fetch (i); + uint64_t expid = expids->fetch (i); + cur->v.val = (grid << INDXOBJ_EXPGRID_SHIFT) | + (expid << INDXOBJ_EXPID_SHIFT) | jthr_id; + if (i == 0) + break; + cur->arg0 = new Expression (OP_NONE, (uint64_t) 0); + cur->v.next = &cur->arg0->v; + cur = cur->arg0; + } + cur->v.next = NULL; + delete objs; + delete grids; + delete expids; + break; + } + case OP_FILE: + { + Vector<Histable*> *objs = NULL; + Histable::NameFormat nfmt = ctx ? ctx->dbev->get_name_format () : Histable::NA; + if (ctx) + objs = (Vector<Histable*>*)dbeSession->match_file_names ((char*) arg1->v.val, nfmt); + Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0); + res = cur; + int i = objs ? objs->size () - 1 : -1; + for (; i >= 0; i--) + { + cur->v.val = objs->fetch (i)->id; + if (i == 0) + break; + cur->arg0 = new Expression (OP_NONE, (uint64_t) 0); + cur->v.next = &cur->arg0->v; + cur = cur->arg0; + } + cur->v.next = NULL; + if (objs) + delete objs; + break; + } + case OP_NUM: + case OP_COMMA: + res = copy (); + break; + case OP_IN: + case OP_SOMEIN: + case OP_ORDRIN: + { + // LIBRARY_VISIBILITY: + // Evaluate the arg0 of OP_IN, OP_SOMEIN, OP_ORDRIN to see if it has any library/loadobject + // Change it to OP_LIBRARY_IN, OP_LIBRARY_SOMEIN or OP_LIBRARY_ORDRIN respectively + if (dbeSession->is_lib_visibility_used () && (arg0->hasLoadObject () + || arg1->hasLoadObject ())) + { + OpCode new_op; + switch (op) + { + case OP_IN: + new_op = OP_LIBRARY_IN; + break; + case OP_SOMEIN: + new_op = OP_LIBRARY_SOMEIN; + break; + case OP_ORDRIN: + new_op = OP_LIBRARY_ORDRIN; + break; + default: + new_op = op; // Should never reach here + break; + } + if (arg1->hasLoadObject ()) + res = new Expression (new_op, arg1 ? arg1->pEval (ctx) : NULL, + arg0 ? arg0->pEval (ctx) : NULL); + else + res = new Expression (new_op, arg0 ? arg0->pEval (ctx) : NULL, + arg1 ? arg1->pEval (ctx) : NULL); + res->v = v; + ctx->dbev->setFilterHideMode (); + return res; + } + } + // no break; if no loadobjects found fall thru to the default case + default: + if (bEval (ctx)) + { + res = new Expression (OP_NUM, v.val); + break; + } + res = new Expression (op, arg0 ? arg0->pEval (ctx) : NULL, + arg1 ? arg1->pEval (ctx) : NULL); + res->v = v; + break; + } + return res; +} + +bool +Expression::verifyObjectInExpr (Histable *obj) +{ + uint64_t id = ((uint64_t) obj->id); + if (op == OP_NUM && v.val == id) + return true; + bool inArg0 = false; + bool inArg1 = false; + if (arg0 != NULL) + inArg0 = arg0->verifyObjectInExpr (obj); + if (inArg0) + return true; + if (arg1 != NULL) + inArg1 = arg1->verifyObjectInExpr (obj); + if (inArg1) + return true; + return false; +} + +bool +Expression::hasLoadObject () +{ + if (op == OP_NUM) + { + uint64_t id = v.val; + Histable *obj = dbeSession->findObjectById (id); + if (obj != NULL && obj->get_type () == Histable::FUNCTION) + { + Function *func = (Function *) obj; + if (func->isHideFunc) + return true; + } + } + if (arg0 && arg0->hasLoadObject ()) + return true; + if (arg1 && arg1->hasLoadObject ()) + return true; + return false; +} |