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
40static const uint64_t INDXOBJ_EXPGRID_SHIFT = 60;
41static const uint64_t INDXOBJ_EXPID_SHIFT   = 32;
42
43Expression::Context::Context (DbeView *_dbev, Experiment *_exp)
44{
45  dbev = _dbev;
46  exp = _exp;
47  dview = NULL;
48  eventId = 0;
49}
50
51Expression::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
62Expression::Expression (OpCode _op, uint64_t _v)
63{
64  op = _op;
65  v = Value (_v);
66  arg0 = NULL;
67  arg1 = NULL;
68}
69
70Expression::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
83Expression::~Expression ()
84{
85  delete arg0;
86  delete arg1;
87}
88
89Expression::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
108Expression::Expression (const Expression *rhs)
109{
110  arg0 = NULL;
111  arg1 = NULL;
112  copy (rhs);
113}
114
115void
116Expression::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
137Expression &
138Expression::operator= (const Expression &rhs)
139{
140  if (this == &rhs)
141    return *this;
142  copy (&rhs);
143  return *this;
144}
145
146bool
147Expression::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
552bool
553Expression::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
1096Expression *
1097Expression::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
1243bool
1244Expression::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
1262bool
1263Expression::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