Retro68/binutils/gprofng/src/Expression.cc
Wolfgang Thaller f485e125c4 binutils 2.39
2022-10-27 20:45:45 +02:00

1282 lines
30 KiB
C++

/* 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;
v = Value (rhs.v);
if (rhs.arg0)
{
arg0 = rhs.arg0->copy ();
if (v.next)
{
assert (arg0 && v.next == &(rhs.arg0->v));
v.next = &(arg0->v);
}
}
if (rhs.arg1)
arg1 = rhs.arg1->copy ();
}
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;
v = Value (rhs->v);
if (rhs->arg0)
{
arg0 = rhs->arg0->copy ();
if (v.next)
{
assert (arg0 && v.next == &(rhs->arg0->v));
v.next = &(arg0->v);
}
}
if (rhs->arg1)
arg1 = rhs->arg1->copy ();
}
Expression &
Expression::operator= (const Expression &rhs)
{
if (this == &rhs)
return *this;
copy (&rhs);
return *this;
}
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;
}