xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/src/Expression.cc (revision dd75ac5b443e967e26b4d18cc8cd5eb98512bfbf)
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "config.h"
22 #include <assert.h>
23 #include "CallStack.h"
24 #include "DbeSession.h"
25 #include "DbeView.h"
26 #include "DataObject.h"
27 #include "Exp_Layout.h"
28 #include "Experiment.h"
29 #include "Module.h"
30 #include "LoadObject.h"
31 #include "Expression.h"
32 #include "Function.h"
33 #include "Histable.h"
34 #include "Sample.h"
35 #include "Table.h"
36 
37 //////////////////////////////////////////////////////////
38 //  class Expression::Context
39 
40 static const uint64_t INDXOBJ_EXPGRID_SHIFT = 60;
41 static const uint64_t INDXOBJ_EXPID_SHIFT   = 32;
42 
43 Expression::Context::Context (DbeView *_dbev, Experiment *_exp)
44 {
45   dbev = _dbev;
46   exp = _exp;
47   dview = NULL;
48   eventId = 0;
49 }
50 
51 Expression::Context::Context (DbeView *_dbev, Experiment *_exp,
52 			      DataView *_dview, long _eventId)
53 {
54   dbev = _dbev;
55   exp = _exp;
56   dview = _dview;
57   eventId = _eventId;
58 }
59 
60 //////////////////////////////////////////////////////////
61 //  class Expression
62 Expression::Expression (OpCode _op, uint64_t _v)
63 {
64   op = _op;
65   v = Value (_v);
66   arg0 = NULL;
67   arg1 = NULL;
68 }
69 
70 Expression::Expression (OpCode _op, const Expression *_arg0,
71 			const Expression *_arg1)
72 {
73   op = _op;
74   v = Value ();
75   arg0 = NULL;
76   arg1 = NULL;
77   if (_arg0)
78     arg0 = _arg0->copy ();
79   if (_arg1)
80     arg1 = _arg1->copy ();
81 }
82 
83 Expression::~Expression ()
84 {
85   delete arg0;
86   delete arg1;
87 }
88 
89 Expression::Expression (const Expression &rhs)
90 {
91   op = rhs.op;
92   arg0 = NULL;
93   arg1 = NULL;
94   v = Value (rhs.v);
95   if (rhs.arg0)
96     {
97       arg0 = rhs.arg0->copy ();
98       if (v.next)
99 	{
100 	  assert (arg0 && v.next == &(rhs.arg0->v));
101 	  v.next = &(arg0->v);
102 	}
103     }
104   if (rhs.arg1)
105     arg1 = rhs.arg1->copy ();
106 }
107 
108 Expression::Expression (const Expression *rhs)
109 {
110   arg0 = NULL;
111   arg1 = NULL;
112   copy (rhs);
113 }
114 
115 void
116 Expression::copy (const Expression *rhs)
117 {
118   op = rhs->op;
119   delete arg0;
120   delete arg1;
121   arg0 = NULL;
122   arg1 = NULL;
123   v = Value (rhs->v);
124   if (rhs->arg0)
125     {
126       arg0 = rhs->arg0->copy ();
127       if (v.next)
128 	{
129 	  assert (arg0 && v.next == &(rhs->arg0->v));
130 	  v.next = &(arg0->v);
131 	}
132     }
133   if (rhs->arg1)
134     arg1 = rhs->arg1->copy ();
135 }
136 
137 Expression &
138 Expression::operator= (const Expression &rhs)
139 {
140   if (this == &rhs)
141     return *this;
142   copy (&rhs);
143   return *this;
144 }
145 
146 bool
147 Expression::getVal (int propId, Context *ctx)
148 {
149   v.val = 0;
150   v.next = NULL;
151   int origPropId = propId;
152   switch (propId)
153     {
154     default:
155       {
156 	if (!ctx->dview)
157 	  return false;
158 	PropDescr *propDscr = ctx->dview->getProp (propId);
159 	if (!propDscr)
160 	  return false;
161 	switch (propDscr->vtype)
162 	  {
163 	  case TYPE_INT32:
164 	    v.val = ctx->dview->getIntValue (propId, ctx->eventId);
165 	    break;
166 	  case TYPE_UINT32:
167 	    v.val = (uint32_t) ctx->dview->getIntValue (propId, ctx->eventId); //prevent sign extension
168 	    break;
169 	  case TYPE_INT64:
170 	  case TYPE_UINT64:
171 	    v.val = ctx->dview->getLongValue (propId, ctx->eventId);
172 	    break;
173 	  case TYPE_OBJ:
174 	    // YM: not sure if we should allow this
175 	    v.val = (long long) ctx->dview->getObjValue (propId, ctx->eventId);
176 	    break;
177 	  case TYPE_STRING:
178 	  case TYPE_DOUBLE:
179 	  default:
180 	    return false; // Weird, programming error?
181 	  }
182 	break;
183       }
184     case PROP_FREQ_MHZ:
185       if (ctx->exp && ctx->exp->clock)
186 	v.val = ctx->exp->clock;
187       else
188 	return false;
189       break;
190     case PROP_PID:
191       if (ctx->exp == NULL)
192 	return false;
193       v.val = ctx->exp->getPID ();
194       break;
195     case PROP_EXPID:
196       if (ctx->exp == NULL)
197 	return false;
198       v.val = ctx->exp->getUserExpId ();
199       break;
200     case PROP_EXPID_CMP:
201       if (ctx->exp == NULL)
202 	return false;
203       else
204 	{
205 	  Experiment *exp = ctx->exp;
206 	  if (ctx->dbev && ctx->dbev->comparingExperiments ())
207 	    exp = (Experiment *) exp->get_compare_obj ();
208 	  v.val = exp->getUserExpId ();
209 	}
210       break;
211     case PROP_EXPGRID:
212       if (ctx->exp == NULL)
213 	return false;
214       v.val = ctx->exp->groupId;
215       break;
216     case PROP_NTICK_USEC:
217       if (ctx->exp == NULL)
218 	return false;
219       if (ctx->dview && ctx->dview->getProp (PROP_NTICK))
220 	v.val = ctx->dview->getIntValue (PROP_NTICK, ctx->eventId)
221 		* ctx->exp->get_params ()->ptimer_usec;
222       else
223 	return false;
224       break;
225     case PROP_ATSTAMP:
226     case PROP_ETSTAMP:
227       if (ctx->exp == NULL)
228 	return false;
229       if (ctx->dview && ctx->dview->getProp (PROP_TSTAMP))
230 	v.val = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId);
231       else
232 	return false;
233       if (propId == PROP_ATSTAMP)
234 	break; // absolute time, no adjustments
235       // propId==PROP_ETSTAMP
236       // calculate relative time from start of this experiment
237       v.val -= ctx->exp->getStartTime ();
238       break;
239     case PROP_TSTAMP:
240     case PROP_TSTAMP_LO:
241     case PROP_TSTAMP_HI:
242       {
243 	if (ctx->exp == NULL)
244 	  return false;
245 	if (!(ctx->dview && ctx->dview->getProp (PROP_TSTAMP)))
246 	  return false;
247 	hrtime_t tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId);
248 	// compute relative time from start of founder experiment
249 	v.val = tstamp - ctx->exp->getStartTime ()
250 		+ ctx->exp->getRelativeStartTime ();
251 	if (propId == PROP_TSTAMP)
252 	  break;
253 	if (ctx->dview->getProp (PROP_EVT_TIME))
254 	  {
255 	    hrtime_t delta = ctx->dview->getLongValue (PROP_EVT_TIME, ctx->eventId);
256 	    if (propId == PROP_TSTAMP_LO)
257 	      {
258 		if (delta > 0)
259 		  { // positive delta means TSTAMP is at end
260 		    // TSTAMP_LO = TSTAMP-delta
261 		    v.val -= delta;
262 		    break;
263 		  }
264 		break;
265 	      }
266 	    else
267 	      { // PROP_TSTAMP_HI
268 		if (delta < 0)
269 		  { // negative delta means TSTAMP is at start
270 		    // TSTAMP_HI = TSTAMP+(-delta)
271 		    v.val -= delta;
272 		    break;
273 		  }
274 		break;
275 	      }
276 	  }
277 	else if (ctx->dview->getProp (PROP_TSTAMP2))
278 	  {
279 	    if (propId == PROP_TSTAMP_HI)
280 	      {
281 		hrtime_t tstamp2 = ctx->dview->getLongValue (PROP_TSTAMP2,
282 							     ctx->eventId);
283 		if (tstamp2 == 0)
284 		  break; // if not initialized, event does not have duration
285 		if (tstamp2 == MAX_TIME)
286 		  tstamp2 = ctx->exp->getLastEvent ();
287 		hrtime_t delta = tstamp2 - tstamp;
288 		if (delta >= 0)
289 		  {
290 		    v.val += delta;
291 		    break;
292 		  }
293 		break; // weird, delta should not be negative
294 	      }
295 	    break; // PROP_TSTAMP_LO, no modification needed
296 	  }
297 	break; // should never be hit
298       }
299     case PROP_IOHEAPBYTES:
300       {
301 	propId = PROP_IONBYTE;
302 	if (ctx->dview == NULL)
303 	  return false;
304 	if (!ctx->dview->getProp (propId))
305 	  { // has property?
306 	    propId = PROP_HSIZE;
307 	    if (!ctx->dview->getProp (propId))
308 	      return false;
309 	  }
310 	v.val = ctx->dview->getLongValue (propId, ctx->eventId);
311 	break;
312       }
313     case PROP_SAMPLE_MAP:
314       {
315 	if (ctx->exp == NULL)
316 	  return false;
317 	if (ctx->dview == NULL)
318 	  return false;
319 	if (ctx->dview->getProp (PROP_SAMPLE))
320 	  v.val = ctx->dview->getIntValue (PROP_SAMPLE, ctx->eventId);
321 	else
322 	  { // does not have property, convert to time.
323 	    uint64_t tstamp;
324 	    tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId);
325 	    Sample *sample = ctx->exp->map_event_to_Sample (tstamp);
326 	    v.val = sample ? sample->get_number () : -1;
327 	  }
328 	break;
329       }
330     case PROP_GCEVENT_MAP:
331       {
332 	if (ctx->exp == NULL)
333 	  return false;
334 	if (ctx->dview == NULL)
335 	  return false;
336 	if (ctx->dview->getProp (PROP_GCEVENT))
337 	  v.val = ctx->dview->getIntValue (PROP_GCEVENT, ctx->eventId);
338 	else
339 	  { // does not have property, convert to time.
340 	    uint64_t tstamp;
341 	    tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId);
342 	    GCEvent *gcevent = ctx->exp->map_event_to_GCEvent (tstamp);
343 	    v.val = gcevent ? gcevent->id : 0;
344 	  }
345 	break;
346       }
347     case PROP_LEAF:
348       {
349 	if (ctx->dview == NULL)
350 	  return false;
351 	VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER;
352 	int prop_id;
353 	if (vmode == VMODE_MACHINE)
354 	  prop_id = PROP_MSTACK;
355 	else if (vmode == VMODE_EXPERT)
356 	  prop_id = PROP_XSTACK;
357 	else
358 	  prop_id = PROP_USTACK;
359 	if (!ctx->dview->getProp (prop_id))
360 	  return false;
361 	Histable *obj = CallStack::getStackPC (ctx->dview->getObjValue (prop_id, ctx->eventId), 0);
362 	Function *func = (Function*) obj->convertto (Histable::FUNCTION);
363 	v.val = func->id; // LEAF
364 	break;
365       }
366     case PROP_STACKID:
367       {
368 	VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER;
369 	if (vmode == VMODE_MACHINE)
370 	  propId = PROP_MSTACK;
371 	else if (vmode == VMODE_EXPERT)
372 	  propId = PROP_XSTACK;
373 	else
374 	  propId = PROP_USTACK;
375 	if (ctx->dview == NULL)
376 	  return false;
377 	if (!ctx->dview->getProp (propId))
378 	  return false;
379 	v.val = (long) ctx->dview->getObjValue (propId, ctx->eventId);
380 	break;
381       }
382     case PROP_STACKL:
383     case PROP_STACKI:
384     case PROP_STACK:
385       {
386 	VMode vmode = ctx->dbev ? ctx->dbev->get_view_mode () : VMODE_USER;
387 	if (vmode == VMODE_MACHINE)
388 	  propId = PROP_MSTACK;
389 	else if (vmode == VMODE_EXPERT)
390 	  propId = PROP_XSTACK;
391 	else
392 	  propId = PROP_USTACK;
393       }
394       // no break;
395     case PROP_MSTACKL:
396     case PROP_XSTACKL:
397     case PROP_USTACKL:
398     case PROP_MSTACKI:
399     case PROP_XSTACKI:
400     case PROP_USTACKI:
401       switch (propId)
402 	{
403 	case PROP_MSTACKL:
404 	case PROP_MSTACKI:
405 	  propId = PROP_MSTACK;
406 	  break;
407 	case PROP_XSTACKL:
408 	case PROP_XSTACKI:
409 	  propId = PROP_XSTACK;
410 	  break;
411 	case PROP_USTACKL:
412 	case PROP_USTACKI:
413 	  propId = PROP_USTACK;
414 	  break;
415 	default:
416 	  break;
417 	}
418       // no break;
419     case PROP_MSTACK:
420     case PROP_XSTACK:
421     case PROP_USTACK:
422       {
423 	if (ctx->dview == NULL)
424 	  return false;
425 	if (!ctx->dview->getProp (propId))
426 	  return false;
427 	bool hide_mode = !ctx->dbev->isShowAll ()
428 		|| ctx->dbev->isFilterHideMode ();
429 	Expression *cur = this;
430 	for (CallStackNode *stack = (CallStackNode *)
431 		ctx->dview->getObjValue (propId, ctx->eventId);
432 		stack; stack = stack->get_ancestor ())
433 	  {
434 	    Histable *hist = stack->get_instr ();
435 	    if (origPropId == PROP_STACK || origPropId == PROP_MSTACK
436 		|| origPropId == PROP_XSTACK || origPropId == PROP_USTACK)
437 	      {
438 		cur->v.val = hist->convertto (Histable::FUNCTION)->id;
439 		cur->v.fn = cur->v.val;
440 	      }
441 	    else if (origPropId == PROP_STACKL || origPropId == PROP_MSTACKL
442 		    || origPropId == PROP_XSTACKL || origPropId == PROP_USTACKL)
443 	      {
444 		cur->v.val = hist->convertto (Histable::LINE)->id;
445 		if (hide_mode)
446 		  cur->v.fn = hist->convertto (Histable::FUNCTION)->id;
447 		else
448 		  cur->v.fn = 0;
449 	      }
450 	    else if (origPropId == PROP_STACKI || origPropId == PROP_MSTACKI
451 		    || origPropId == PROP_XSTACKI || origPropId == PROP_USTACKI)
452 	      {
453 		cur->v.val = hist->convertto (Histable::INSTR)->id;
454 		if (hide_mode)
455 		  cur->v.fn = hist->convertto (Histable::FUNCTION)->id;
456 		else
457 		  cur->v.fn = 0;
458 	      }
459 	    if (cur->arg1 == NULL)
460 	      cur->arg1 = new Expression (OP_NONE, (uint64_t) 0);
461 	    if (stack->get_ancestor () == NULL)
462 	      {
463 		if (origPropId == PROP_STACKL || origPropId == PROP_MSTACKL
464 		    || origPropId == PROP_XSTACKL || origPropId == PROP_USTACKL
465 		    || origPropId == PROP_STACKI || origPropId == PROP_MSTACKI
466 		    || origPropId == PROP_XSTACKI || origPropId == PROP_USTACKI)
467 		  {
468 		    cur->v.next = NULL;
469 		    continue;
470 		  }
471 	      }
472 	    cur->v.next = &cur->arg1->v;
473 	    cur = cur->arg1;
474 	  }
475 	if (origPropId == PROP_STACK || origPropId == PROP_MSTACK
476 	    || origPropId == PROP_XSTACK || origPropId == PROP_USTACK)
477 	  {
478 	    cur->v.val = dbeSession->get_Total_Function ()->id;
479 	    cur->v.fn = cur->v.val;
480 	    cur->v.next = NULL;
481 	  }
482 	break;
483       }
484     case PROP_DOBJ:
485       {
486 	if (ctx->dview == NULL)
487 	  return false;
488 	if (!ctx->dview->getProp (PROP_DOBJ))
489 	  return false;
490 	DataObject *dobj = (DataObject*)
491 		ctx->dview->getObjValue (PROP_DOBJ, ctx->eventId);
492 	if (dobj != NULL)
493 	  {
494 	    Expression *cur = this;
495 	    for (;;)
496 	      {
497 		cur->v.val = dobj->id;
498 		dobj = dobj->parent;
499 		if (dobj == NULL)
500 		  break;
501 		if (cur->arg1 == NULL)
502 		  cur->arg1 = new Expression (OP_NONE, (uint64_t) 0);
503 		cur->v.next = &cur->arg1->v;
504 		cur = cur->arg1;
505 	      }
506 	    cur->v.next = NULL;
507 	  }
508 	break;
509       }
510     case PROP_CPRID:
511     case PROP_TSKID:
512       {
513 	if (ctx->dview == NULL)
514 	  return false;
515 	if (!ctx->dview->getProp (propId))
516 	  return false;
517 	CallStackNode *ompstack = (CallStackNode *)
518 		ctx->dview->getObjValue (propId, ctx->eventId);
519 	Histable *hobj = ompstack->get_instr ();
520 	if (hobj != NULL)
521 	  v.val = hobj->id;
522 	break;
523       }
524     case PROP_JTHREAD:
525       {
526 	if (ctx->exp == NULL)
527 	  return false;
528 	if (ctx->dview == NULL)
529 	  return false;
530 	if (!ctx->dview->getProp (propId))
531 	  return false;
532 	uint64_t tstamp;
533 	tstamp = ctx->dview->getLongValue (PROP_TSTAMP, ctx->eventId);
534 	uint32_t thrid;
535 	uint64_t jthr_id = 0;
536 	thrid = ctx->dview->getIntValue (PROP_THRID, ctx->eventId);
537 	JThread *jthread = ctx->exp->map_pckt_to_Jthread (thrid, tstamp);
538 	if (jthread != JTHREAD_NONE && jthread != JTHREAD_DEFAULT)
539 	  {
540 	    jthr_id = jthread->jthr_id;
541 	    uint64_t grid = ctx->exp->groupId;
542 	    uint64_t expid = ctx->exp->getUserExpId ();
543 	    v.val = (grid << INDXOBJ_EXPGRID_SHIFT) |
544 		    (expid << INDXOBJ_EXPID_SHIFT) | jthr_id;
545 	  }
546 	break;
547       }
548     }
549   return true;
550 }
551 
552 bool
553 Expression::bEval (Context *ctx)
554 {
555   uint64_t v0, v1;
556   switch (op)
557     {
558     case OP_DEG:
559       if (!arg1->bEval (ctx))
560 	return false;
561       if (arg1->v.val < 0)
562 	{
563 	  v.val = 0;
564 	  return true;
565 	}
566       if (!arg0->bEval (ctx))
567 	{
568 	  return false;
569 	}
570       v0 = arg0->v.val;
571       v1 = arg1->v.val;
572       for (v.val = 1; v1 > 0; v1--)
573 	v.val *= v0;
574       return true;
575     case OP_MUL:
576       if (arg0->bEval (ctx) && arg1->bEval (ctx))
577 	{
578 	  v.val = arg0->v.val * arg1->v.val;
579 	  return true;
580 	}
581       return false;
582     case OP_DIV:
583       if (arg0->bEval (ctx) && arg1->bEval (ctx))
584 	{
585 	  v1 = arg1->v.val;
586 	  v.val = (v1 == 0) ? 0 : (arg0->v.val / v1);
587 	  return true;
588 	}
589       return false;
590     case OP_REM:
591       if (arg0->bEval (ctx) && arg1->bEval (ctx))
592 	{
593 	  v1 = arg1->v.val;
594 	  v.val = (v1 == 0) ? 0 : (arg0->v.val % v1);
595 	  return true;
596 	}
597       return false;
598     case OP_ADD:
599       if (arg0->bEval (ctx) && arg1->bEval (ctx))
600 	{
601 	  v.val = arg0->v.val + arg1->v.val;
602 	  // DBFIXME LIBRARY VISIBILITY
603 	  // hack to pass v.fn value to new expression for leaf filters USTACK+0
604 	  v.fn = arg0->v.fn + arg1->v.fn;
605 	  return true;
606 	}
607       return false;
608     case OP_MINUS:
609       if (arg0->bEval (ctx) && arg1->bEval (ctx))
610 	{
611 	  v.val = arg0->v.val - arg1->v.val;
612 	  return true;
613 	}
614       return false;
615     case OP_LS:
616       if (arg0->bEval (ctx) && arg1->bEval (ctx))
617 	{
618 	  v.val = arg0->v.val << arg1->v.val;
619 	  return true;
620 	}
621       return false;
622     case OP_RS:
623       if (arg0->bEval (ctx) && arg1->bEval (ctx))
624 	{
625 	  v.val = arg0->v.val >> arg1->v.val;
626 	  return true;
627 	}
628       return false;
629     case OP_LT:
630       if (arg0->bEval (ctx) && arg1->bEval (ctx))
631 	{
632 	  v.val = arg0->v.val < arg1->v.val ? 1 : 0;
633 	  return true;
634 	}
635       return false;
636     case OP_LE:
637       if (arg0->bEval (ctx) && arg1->bEval (ctx))
638 	{
639 	  v.val = arg0->v.val <= arg1->v.val ? 1 : 0;
640 	  return true;
641 	}
642       return false;
643     case OP_GT:
644       if (arg0->bEval (ctx) && arg1->bEval (ctx))
645 	{
646 	  v.val = arg0->v.val > arg1->v.val ? 1 : 0;
647 	  return true;
648 	}
649       return false;
650     case OP_GE:
651       if (arg0->bEval (ctx) && arg1->bEval (ctx))
652 	{
653 	  v.val = arg0->v.val >= arg1->v.val ? 1 : 0;
654 	  return true;
655 	}
656       return false;
657     case OP_EQ:
658       if (arg0->bEval (ctx) && arg1->bEval (ctx))
659 	{
660 	  v.val = arg0->v.val == arg1->v.val ? 1 : 0;
661 	  return true;
662 	}
663       return false;
664     case OP_NE:
665       if (arg0->bEval (ctx) && arg1->bEval (ctx))
666 	{
667 	  v.val = arg0->v.val != arg1->v.val ? 1 : 0;
668 	  return true;
669 	}
670       return false;
671     case OP_BITAND:
672       if (arg0->bEval (ctx) && arg1->bEval (ctx))
673 	{
674 	  v.val = arg0->v.val & arg1->v.val;
675 	  return true;
676 	}
677       return false;
678     case OP_BITXOR:
679       if (arg0->bEval (ctx) && arg1->bEval (ctx))
680 	{
681 	  v.val = arg0->v.val ^ arg1->v.val;
682 	  return true;
683 	}
684       return false;
685     case OP_BITOR:
686       if (arg0->bEval (ctx) && arg1->bEval (ctx))
687 	{
688 	  v.val = arg0->v.val | arg1->v.val;
689 	  return true;
690 	}
691       return false;
692     case OP_AND:
693       if (arg0->bEval (ctx))
694 	{
695 	  if (arg0->v.val == 0)
696 	    {
697 	      v.val = 0;
698 	      return true;
699 	    }
700 	  if (arg1->bEval (ctx))
701 	    {
702 	      v.val = arg1->v.val == 0 ? 0 : 1;
703 	      return true;
704 	    }
705 	  return false;
706 	}
707       if (arg1->bEval (ctx) && arg1->v.val == 0)
708 	{
709 	  v.val = 0;
710 	  return true;
711 	}
712       return false;
713     case OP_OR:
714       if (arg0->bEval (ctx))
715 	{
716 	  if (arg0->v.val != 0)
717 	    {
718 	      v.val = 1;
719 	      return true;
720 	    }
721 	  if (arg1->bEval (ctx))
722 	    {
723 	      v.val = arg1->v.val == 0 ? 0 : 1;
724 	      return true;
725 	    }
726 	  return false;
727 	}
728       if (arg1->bEval (ctx) && arg1->v.val != 0)
729 	{
730 	  v.val = 1;
731 	  return true;
732 	}
733       return false;
734     case OP_NEQV:
735       if (arg0->bEval (ctx) && arg1->bEval (ctx))
736 	{
737 	  v0 = arg0->v.val;
738 	  v1 = arg1->v.val;
739 	  v.val = (v0 == 0 && v1 != 0) || (v0 != 0 && v1 == 0) ? 1 : 0;
740 	  return true;
741 	}
742       return false;
743     case OP_EQV:
744       if (arg0->bEval (ctx) && arg1->bEval (ctx))
745 	{
746 	  v0 = arg0->v.val;
747 	  v1 = arg1->v.val;
748 	  v.val = (v0 == 0 && v1 == 0) || (v0 != 0 && v1 != 0) ? 1 : 0;
749 	  return true;
750 	}
751       return false;
752     case OP_QWE:
753       if (arg0->bEval (ctx))
754 	{
755 	  if (arg0->v.val != 0)
756 	    {
757 	      if (arg1->arg0->bEval (ctx))
758 		{
759 		  v.val = arg1->arg0->v.val;
760 		  return true;
761 		}
762 	    }
763 	  else
764 	    {
765 	      if (arg1->arg1->bEval (ctx))
766 		{
767 		  v.val = arg1->arg1->v.val;
768 		  return true;
769 		}
770 	    }
771 	}
772       return false;
773     case OP_COMMA:
774       if (arg0->bEval (ctx))
775 	{
776 	  v.next = &arg0->v;
777 	  if (arg1->bEval (ctx))
778 	    {
779 	      v.val = arg1->v.val;
780 	      return true;
781 	    }
782 	}
783       return false;
784     case OP_IN:
785       if (arg0->bEval (ctx) && arg1->bEval (ctx))
786 	{
787 	  for (Value *s = &arg0->v; s; s = s->next)
788 	    {
789 	      bool found = false;
790 	      for (Value *t = &arg1->v; t; t = t->next)
791 		{
792 		  if (t->val == s->val)
793 		    {
794 		      found = true;
795 		      break;
796 		    }
797 		}
798 	      if (!found)
799 		{
800 		  v.val = 0;
801 		  return true;
802 		}
803 	    }
804 	  v.val = 1;
805 	  return true;
806 	}
807       return false;
808     case OP_SOMEIN:
809       if (arg0->bEval (ctx) && arg1->bEval (ctx))
810 	{
811 	  for (Value *s = &arg0->v; s; s = s->next)
812 	    {
813 	      for (Value *t = &arg1->v; t; t = t->next)
814 		{
815 		  if (t->val == s->val)
816 		    {
817 		      v.val = 1;
818 		      return true;
819 		    }
820 		}
821 	    }
822 	  v.val = 0;
823 	  return true;
824 	}
825       return false;
826     case OP_ORDRIN:
827       if (arg0->bEval (ctx) && arg1->bEval (ctx))
828 	{
829 	  for (Value *t0 = &arg1->v; t0; t0 = t0->next)
830 	    {
831 	      bool found = true;
832 	      for (Value *s = &arg0->v, *t = t0; s; s = s->next, t = t->next)
833 		{
834 		  if (t == NULL || t->val != s->val)
835 		    {
836 		      found = false;
837 		      break;
838 		    }
839 		}
840 	      if (found)
841 		{
842 		  v.val = 1;
843 		  return true;
844 		}
845 	    }
846 	  v.val = 0;
847 	  return true;
848 	}
849       return false;
850       // LIBRARY_VISIBILITY
851     case OP_LIBRARY_IN:
852       if (arg0->bEval (ctx) && arg1->bEval (ctx))
853 	{
854 	  for (Value *s = &arg0->v; s; s = s->next)
855 	    {
856 	      bool found = false;
857 	      uint64_t objId = s->val;
858 	      Histable *obj = dbeSession->findObjectById (objId);
859 	      bool libraryFound = false;
860 	      Function *fn;
861 	      if (obj != NULL && obj->get_type () == Histable::FUNCTION)
862 		{
863 		  fn = (Function *) obj;
864 		  if (fn->isHideFunc)
865 		    // this belongss to a loadobject in hide/library mode
866 		    libraryFound = true;
867 		}
868 
869 	      if (libraryFound)
870 		{
871 		  uint64_t lo_id = fn->module->loadobject->id;
872 		  for (Value *t = &arg1->v; t; t = t->next)
873 		    {
874 		      uint64_t t_id = t->fn;
875 		      Histable *obj2 = dbeSession->findObjectById (t_id);
876 		      if (obj2 != NULL
877 			  && obj2->get_type () == Histable::FUNCTION)
878 			{
879 			  Function *func2 = (Function *) obj2;
880 			  uint64_t lo_id2 = func2->module->loadobject->id;
881 			  if (lo_id2 == lo_id)
882 			    {
883 			      found = true;
884 			      break;
885 			    }
886 			}
887 		    }
888 		}
889 	      else
890 		{
891 		  // Not a loadobject
892 		  for (Value *t = &arg1->v; t; t = t->next)
893 		    {
894 		      if (t->val == s->val)
895 			{
896 			  found = true;
897 			  break;
898 			}
899 		    }
900 		}
901 	      if (!found)
902 		{
903 		  v.val = 0;
904 		  return true;
905 		}
906 	    }
907 	  v.val = 1;
908 	  return true;
909 	}
910       return false;
911     case OP_LIBRARY_SOMEIN:
912       if (arg0->bEval (ctx) && arg1->bEval (ctx))
913 	{
914 	  for (Value *s = &arg0->v; s; s = s->next)
915 	    {
916 	      uint64_t objId = s->val;
917 	      Histable *obj = dbeSession->findObjectById (objId);
918 	      bool libraryFound = false;
919 	      Function *fn;
920 	      if (obj != NULL && obj->get_type () == Histable::FUNCTION)
921 		{
922 		  fn = (Function *) obj;
923 		  if (fn->isHideFunc)
924 		    // this belongs to a loadobject in hide/library mode
925 		    libraryFound = true;
926 		}
927 
928 	      if (libraryFound)
929 		{
930 		  uint64_t lo_id = fn->module->loadobject->id;
931 		  for (Value *t = &arg1->v; t; t = t->next)
932 		    {
933 		      uint64_t t_id = t->fn;
934 		      Histable *obj2 = dbeSession->findObjectById (t_id);
935 		      if (obj2 != NULL && obj2->get_type () == Histable::FUNCTION)
936 			{
937 			  Function *func2 = (Function *) obj2;
938 			  uint64_t lo_id2 = func2->module->loadobject->id;
939 			  if (lo_id2 == lo_id)
940 			    {
941 			      v.val = 1;
942 			      return true;
943 			    }
944 			}
945 		    }
946 		}
947 	      else
948 		{
949 		  for (Value *t = &arg1->v; t; t = t->next)
950 		    if (t->val == s->val)
951 		      {
952 			v.val = 1;
953 			return true;
954 		      }
955 		}
956 	    }
957 	  v.val = 0;
958 	  return true;
959 	}
960       return false;
961     case OP_LIBRARY_ORDRIN:
962       if (arg0->bEval (ctx) && arg1->bEval (ctx))
963 	{
964 	  for (Value *t0 = &arg1->v; t0; t0 = t0->next)
965 	    {
966 	      bool found = true;
967 	      Value *t = t0;
968 	      for (Value *s = &arg0->v; s; s = s->next)
969 		{
970 		  // start comparing s->val with t->val
971 		  // if matches move on to s->next and t->next
972 		  uint64_t objId = s->val;
973 		  Histable *obj = dbeSession->findObjectById (objId);
974 		  bool libraryFound = false;
975 		  Function *fn;
976 		  if (obj != NULL && obj->get_type () == Histable::FUNCTION)
977 		    {
978 		      fn = (Function *) obj;
979 		      if (fn->isHideFunc)
980 			libraryFound = true;
981 		    }
982 		  if (libraryFound)
983 		    {
984 		      // s->val is from a loadobject
985 		      // check if t->val is a func whose loadobject matches s->val
986 		      uint64_t lo_id = fn->module->loadobject->id;
987 		      uint64_t t_id = t->fn;
988 		      Histable *obj2 = dbeSession->findObjectById (t_id);
989 		      if (obj2 != NULL
990 			  && obj2->get_type () == Histable::FUNCTION)
991 			{
992 			  Function *func2 = (Function *) obj2;
993 			  uint64_t lo_id2 = func2->module->loadobject->id;
994 			  if (lo_id2 != lo_id)
995 			    {
996 			      // no match
997 			      found = false;
998 			      break;
999 			    }
1000 			  else
1001 			    {
1002 			      // t->val is a func whose loadobject matches s->val
1003 			      while (t != NULL && lo_id2 == lo_id)
1004 				{
1005 				  // skip frames with same load object
1006 				  t = t->next;
1007 				  t_id = t->fn;
1008 				  obj2 = dbeSession->findObjectById (t_id);
1009 				  if (obj2 != NULL
1010 				      && obj2->get_type () == Histable::FUNCTION)
1011 				    {
1012 				      func2 = (Function *) obj2;
1013 				      lo_id2 = func2->module->loadobject->id;
1014 				    }
1015 				}
1016 			    }
1017 			}
1018 		    }
1019 		  else
1020 		    {
1021 		      if (t == NULL || t->val != s->val)
1022 			{
1023 			  found = false;
1024 			  break;
1025 			}
1026 		      t = t->next;
1027 		    }
1028 		}
1029 	      if (found)
1030 		{
1031 		  v.val = 1;
1032 		  return true;
1033 		}
1034 	    }
1035 	  v.val = 0;
1036 	  return true;
1037 	}
1038       return false;
1039     case OP_BITNOT:
1040       if (arg0->bEval (ctx))
1041 	{
1042 	  v.val = ~arg0->v.val;
1043 	  return true;
1044 	}
1045       return false;
1046     case OP_NOT:
1047       if (arg0->bEval (ctx))
1048 	{
1049 	  v.val = !arg0->v.val;
1050 	  return true;
1051 	}
1052       return false;
1053     case OP_NUM:
1054       return true;
1055     case OP_NAME:
1056       if (ctx && arg0->bEval (ctx) && getVal ((int) arg0->v.val, ctx))
1057 	return true;
1058       return false;
1059     case OP_FUNC:
1060       // FNAME is completely processed by pEval for now
1061       v.val = 0;
1062       return true;
1063     case OP_HASPROP:
1064       if (!ctx || !ctx->dview)
1065 	return false; // can't be resolved (occurs during pEval() )
1066       else if (arg0->op != OP_NAME || !arg0->arg0)
1067 	return false; // weird, wrong arg type
1068       else
1069 	{
1070 	  int propId = (int) arg0->arg0->v.val;
1071 	  if (ctx->dview->getProp (propId))
1072 	    v.val = 1;
1073 	  else
1074 	    v.val = 0;
1075 	  return true;
1076 	}
1077     case OP_FILE:
1078       // FILENAME is completely processed by pEval for now
1079       v.val = 0;
1080       return true;
1081     case OP_JAVA:
1082       //JGROUP & JPARENT is completely processed by pEval for now
1083       v.val = 0;
1084       return true;
1085     case OP_COLON:
1086       return false; // OK for arg1 of OP_QWE
1087     default:
1088 #ifdef IPC_LOG
1089       fprintf (stderr, "INTERNAL ERROR: Expression::eval op=%d\n", op);
1090 #endif
1091       return false;
1092     }
1093   return false;
1094 }
1095 
1096 Expression *
1097 Expression::pEval (Context *ctx) // partial evaluation (dview may be NULL)
1098 {
1099   Expression *res = NULL;
1100   switch (op)
1101     {
1102     case OP_FUNC:
1103       {
1104 	Vector<Histable*> *objs = NULL;
1105 	if (arg0->v.val == FUNC_FNAME)
1106 	  {
1107 	    Histable::NameFormat nfmt = ctx ? ctx->dbev->get_name_format () : Histable::NA;
1108 	    objs = (Vector<Histable*>*)dbeSession->match_func_names ((char*) arg1->v.val, nfmt);
1109 	  }
1110 	else if (arg0->v.val == FUNC_DNAME)
1111 	  objs = (Vector<Histable*>*)dbeSession->match_dobj_names ((char*) arg1->v.val);
1112 	Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0);
1113 	res = cur;
1114 	int i = objs ? objs->size () - 1 : -1;
1115 	for (; i >= 0; i--)
1116 	  {
1117 	    cur->v.val = objs->fetch (i)->id;
1118 	    if (i == 0)
1119 	      break;
1120 	    cur->arg0 = new Expression (OP_NONE, (uint64_t) 0);
1121 	    cur->v.next = &cur->arg0->v;
1122 	    cur = cur->arg0;
1123 	  }
1124 	cur->v.next = NULL;
1125 	if (objs)
1126 	  delete objs;
1127 	break;
1128       }
1129     case OP_JAVA:
1130       {
1131 	Vector<JThread*> *objs = NULL;
1132 	Vector<uint64_t> *grids = NULL;
1133 	Vector<uint64_t> *expids = NULL;
1134 	if (arg0->v.val == JAVA_JGROUP)
1135 	  objs = dbeSession->match_java_threads ((char*) arg1->v.val, 0, grids,
1136 						 expids);
1137 	else if (arg0->v.val == JAVA_JPARENT)
1138 	  objs = dbeSession->match_java_threads ((char*) arg1->v.val, 1, grids,
1139 						 expids);
1140 	Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0);
1141 	res = cur;
1142 	int i = objs ? objs->size () - 1 : -1;
1143 	for (; i >= 0; i--)
1144 	  {
1145 	    uint64_t jthr_id = 0;
1146 	    JThread *jthread = (JThread *) (objs->fetch (i));
1147 	    jthr_id = jthread->jthr_id;
1148 	    uint64_t grid = grids->fetch (i);
1149 	    uint64_t expid = expids->fetch (i);
1150 	    cur->v.val = (grid << INDXOBJ_EXPGRID_SHIFT) |
1151 		    (expid << INDXOBJ_EXPID_SHIFT) | jthr_id;
1152 	    if (i == 0)
1153 	      break;
1154 	    cur->arg0 = new Expression (OP_NONE, (uint64_t) 0);
1155 	    cur->v.next = &cur->arg0->v;
1156 	    cur = cur->arg0;
1157 	  }
1158 	cur->v.next = NULL;
1159 	delete objs;
1160 	delete grids;
1161 	delete expids;
1162 	break;
1163       }
1164     case OP_FILE:
1165       {
1166 	Vector<Histable*> *objs = NULL;
1167 	Histable::NameFormat nfmt = ctx ? ctx->dbev->get_name_format () : Histable::NA;
1168 	if (ctx)
1169 	  objs = (Vector<Histable*>*)dbeSession->match_file_names ((char*) arg1->v.val, nfmt);
1170 	Expression *cur = new Expression (Expression::OP_NUM, (uint64_t) 0);
1171 	res = cur;
1172 	int i = objs ? objs->size () - 1 : -1;
1173 	for (; i >= 0; i--)
1174 	  {
1175 	    cur->v.val = objs->fetch (i)->id;
1176 	    if (i == 0)
1177 	      break;
1178 	    cur->arg0 = new Expression (OP_NONE, (uint64_t) 0);
1179 	    cur->v.next = &cur->arg0->v;
1180 	    cur = cur->arg0;
1181 	  }
1182 	cur->v.next = NULL;
1183 	if (objs)
1184 	  delete objs;
1185 	break;
1186       }
1187     case OP_NUM:
1188     case OP_COMMA:
1189       res = copy ();
1190       break;
1191     case OP_IN:
1192     case OP_SOMEIN:
1193     case OP_ORDRIN:
1194       {
1195 	// LIBRARY_VISIBILITY:
1196 	// Evaluate the arg0 of OP_IN, OP_SOMEIN, OP_ORDRIN to see if it has any library/loadobject
1197 	// Change it to OP_LIBRARY_IN, OP_LIBRARY_SOMEIN or OP_LIBRARY_ORDRIN respectively
1198 	if (dbeSession->is_lib_visibility_used () && (arg0->hasLoadObject ()
1199 						     || arg1->hasLoadObject ()))
1200 	  {
1201 	    OpCode new_op;
1202 	    switch (op)
1203 	      {
1204 	      case OP_IN:
1205 		new_op = OP_LIBRARY_IN;
1206 		break;
1207 	      case OP_SOMEIN:
1208 		new_op = OP_LIBRARY_SOMEIN;
1209 		break;
1210 	      case OP_ORDRIN:
1211 		new_op = OP_LIBRARY_ORDRIN;
1212 		break;
1213 	      default:
1214 		new_op = op; // Should never reach here
1215 		break;
1216 	      }
1217 	    if (arg1->hasLoadObject ())
1218 	      res = new Expression (new_op, arg1 ? arg1->pEval (ctx) : NULL,
1219 				    arg0 ? arg0->pEval (ctx) : NULL);
1220 	    else
1221 	      res = new Expression (new_op, arg0 ? arg0->pEval (ctx) : NULL,
1222 				    arg1 ? arg1->pEval (ctx) : NULL);
1223 	    res->v = v;
1224 	    ctx->dbev->setFilterHideMode ();
1225 	    return res;
1226 	  }
1227       }
1228       // no break; if no loadobjects found fall thru to the default case
1229     default:
1230       if (bEval (ctx))
1231 	{
1232 	  res = new Expression (OP_NUM, v.val);
1233 	  break;
1234 	}
1235       res = new Expression (op, arg0 ? arg0->pEval (ctx) : NULL,
1236 			    arg1 ? arg1->pEval (ctx) : NULL);
1237       res->v = v;
1238       break;
1239     }
1240   return res;
1241 }
1242 
1243 bool
1244 Expression::verifyObjectInExpr (Histable *obj)
1245 {
1246   uint64_t id = ((uint64_t) obj->id);
1247   if (op == OP_NUM && v.val == id)
1248     return true;
1249   bool inArg0 = false;
1250   bool inArg1 = false;
1251   if (arg0 != NULL)
1252     inArg0 = arg0->verifyObjectInExpr (obj);
1253   if (inArg0)
1254     return true;
1255   if (arg1 != NULL)
1256     inArg1 = arg1->verifyObjectInExpr (obj);
1257   if (inArg1)
1258     return true;
1259   return false;
1260 }
1261 
1262 bool
1263 Expression::hasLoadObject ()
1264 {
1265   if (op == OP_NUM)
1266     {
1267       uint64_t id = v.val;
1268       Histable *obj = dbeSession->findObjectById (id);
1269       if (obj != NULL && obj->get_type () == Histable::FUNCTION)
1270 	{
1271 	  Function *func = (Function *) obj;
1272 	  if (func->isHideFunc)
1273 	    return true;
1274 	}
1275     }
1276   if (arg0 && arg0->hasLoadObject ())
1277     return true;
1278   if (arg1 && arg1->hasLoadObject ())
1279     return true;
1280   return false;
1281 }
1282