a0a647d13bc07b54d42393a97c169003bcd4e354
[cacao.git] / src / vm / jit / loop / tracing.c
1 /* vm/jit/loop/tracing.c - trace functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christopher Kruegel
28
29    Contains the functions which create a trace. A trace is a
30    structure, that contains the source of the arguments of a given
31    instruction. For more details see function tracing(basicblock, int,
32    int) below.
33
34    $Id: tracing.c 1621 2004-11-30 13:06:55Z twisti $
35
36 */
37
38
39 /*  #include <stdio.h> */
40
41 #include "mm/memory.h"
42 #include "vm/jit/loop/loop.h"
43 #include "vm/jit/loop/tracing.h"
44
45
46 /*      Test function -> will be removed in final release
47 */
48 void printTraceResult(struct Trace *p)
49 {
50         printf("TRACE: ");
51
52         switch (p->type) {
53         case TRACE_UNKNOWN:
54                 printf("\tUnknown");
55                 break;
56         case TRACE_ICONST:
57                 printf("\tconst - %d", p->constant);
58                 break;
59         case TRACE_ALENGTH:
60                 printf("\tarray - (%d)%d - %d", p->neg, p->var, p->constant);
61                 break;
62         case TRACE_IVAR:
63                 printf("\tivar - (%d)%d - %d", p->neg, p->var, p->constant);
64                 break;
65         case TRACE_AVAR:
66                 printf("\tavar - %d", p->var);
67                 break;
68                 }
69         
70         printf("\n");
71 }
72
73     
74 /*      A function that creates a new trace structure and initializes its values
75 */
76 Trace* create_trace(int type, int var, int constant, int nr)
77 {
78         Trace *t;
79
80         t = DNEW(Trace);
81
82         t->type = type;
83
84         t->neg = 1;
85         t->var = var;
86         t->nr = nr;
87
88         t->constant = constant;
89
90         return t;
91 }
92
93
94 /*      When the function tracing(...) encounters an add instruction during its 
95         backward scan over the instructions, it trys to identify the source of the
96         arguments of this add function. The following function performs this task.
97 */
98 Trace* add(Trace* a, Trace* b)
99 {
100         switch (a->type) {                      /* check the first argument of add. when it             */
101         case TRACE_UNKNOWN:                     /* is unknown or array-address, return unknown  */
102         case TRACE_AVAR:
103                 return create_trace(TRACE_UNKNOWN, -1, 0, 0);
104
105         case TRACE_ICONST:                      /* when it is constant, check second argument   */
106                 switch (b->type) {
107                 case TRACE_IVAR:                        /* when second argument is a variable value */
108                 case TRACE_ALENGTH:                     /* or array length, just add the constant       */
109                         a->type = b->type;
110                         a->var  = b->var;
111                         a->neg  = b->neg;
112                         a->constant += b->constant;
113                         break;
114                 case TRACE_UNKNOWN:                     /* when unknown/array ref. return unknown       */
115                 case TRACE_AVAR:
116                       return create_trace(TRACE_UNKNOWN, -1, 0, 0);
117             case TRACE_ICONST:                  /* when both are constant, just add them        */
118                         a->constant += b->constant;
119                         break;
120                         }
121                 break;
122
123         case TRACE_IVAR:                        /* when it is a variable value or array length, */
124         case TRACE_ALENGTH:                     /* check second argument                                                */
125                 switch (b->type) {
126                 case TRACE_IVAR:                        /* when it is not a constant return unknown     */
127                 case TRACE_ALENGTH:
128                 case TRACE_UNKNOWN:
129                 case TRACE_AVAR:
130                         return create_trace(TRACE_UNKNOWN, -1, 0, 0);
131                 case TRACE_ICONST:                      /* when it is a constant, just add it           */
132                         a->constant += b->constant;
133                         break;
134                         }
135                 break;
136                 }
137
138         return a;
139 }
140
141
142 /*      When the function tracing(...) encounters a neg instruction during its 
143         backward scan over the instructions, it trys to identify the source of the
144         argument of this neg function. The following function performs this task.
145 */
146 Trace* negate(Trace* a)
147 {
148         switch (a->type) {                              /* check argument type                                          */
149         case TRACE_IVAR:                                /* when it is variable/array length value       */
150         case TRACE_ALENGTH:                                     
151                 a->neg = -(a->neg);                             /* invert negate flag                                   */
152                 a->constant = -(a->constant);   /* and negate constant                                  */
153                 break;
154         
155         case TRACE_ICONST:                              /* when it is a constant, negate it                     */
156                 a->constant = -(a->constant);
157                 break;
158
159         default:
160                 a->type = TRACE_UNKNOWN;        /* else return unknown                                          */
161                 break;
162                 }
163
164   return a;
165 }
166
167
168 /*      When the function tracing(...) encounters a sub instruction during its backward
169         scan over the instructions, it trys to identify the source of the arguments of
170         this sub function. The following function performs this task, by applaying the
171         negate function on the second argument and then adds the values.
172 */
173 Trace* sub(Trace* a, Trace* b)
174 {
175         Trace *c = negate(b);
176         return add(a, c);
177 }
178
179
180 /*      When the function tracing(...) encounters an array length instruction during
181         its backward scan over the instructions, it trys to identify the source of 
182         the argument ofthis array length function. The following function performs 
183         this task.
184 */
185 Trace* array_length(Trace* a)
186 {
187         if (a->type == TRACE_AVAR)      /* if argument is an array ref., mark the type  */
188                 a->type = TRACE_ALENGTH;        /* as array length of this array reference      */
189         else
190                 a->type = TRACE_UNKNOWN;        /* else it's unknown                                    */
191
192         return a;
193 }
194
195
196 /* tracing *********************************************************************
197
198    This function is used to identify the types of operands of an intermediate
199    code instruction. It is needed by functions, that analyze array accesses. If
200    something is stored into or loaded from an array, we have to find out,
201    which array really has been accessed. When a compare instruction is
202    encountered at a loop header, the type of its operands have to be detected
203    to construct dynamic bounds for some variables in the loop. This function
204    returns a struct Trace (see loop.h for more details about this structure).
205    block is the basic block to be examined, index holds the offset of the
206    examined instruction in this block. The arguments are retrieved by using
207    the stack structure, the compilation process sets up. During the backwards
208    scan of the code, it is possible, that other instructions temporary put or
209    get values from the stack and hide the value, we are interested in below
210    them. The value temp counts the number of values on the stack, the are
211    located beyond the target value.
212
213 *******************************************************************************/
214
215 Trace* tracing(basicblock *block, int index, int temp)
216 {
217         int args, retval;
218         instruction *ip;
219         methodinfo *m;
220
221         if (index >= 0) {
222                 ip = block->iinstr+index;
223
224 /*      printf("TRACING with %d %d %d\n", index, temp, ip->opc);
225 */
226                 switch (ip->opc) {
227                 
228                 /* nop, nullcheckpop                                                                                                    */
229                 case ICMD_NOP:                          /* ...  ==> ...                                                         */
230                         return tracing(block, index-1, temp);
231                         break;
232       
233                 case ICMD_NULLCHECKPOP:         /* ..., objectref  ==> ...                                      */
234                         return tracing(block, index-1, temp+1);
235                         break;
236
237                 /* Constants                                                                                                                    */
238                 case ICMD_LCONST:                               
239                 case ICMD_DCONST:
240                 case ICMD_FCONST:
241                 case ICMD_ACONST:
242                         if (temp > 0)                           
243                                 return tracing(block, index-1, temp-1);         
244                         else
245                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
246                         break;                                          
247
248                 case ICMD_ICONST:
249                         if (temp > 0)           /* if the target argument is not on top                 */
250                                 return tracing(block, index-1, temp-1); /* look further                 */
251                         else
252                                 return create_trace(TRACE_ICONST, -1, ip->val.i, index);
253                         break;                          /* else, return the value, found at this instr. */
254
255                 /* Load/Store                                                                                                                   */
256         case ICMD_LLOAD:                
257                 case ICMD_DLOAD:    
258                 case ICMD_FLOAD:
259                         if (temp > 0)
260                                 return tracing(block, index-1, temp-1);
261                         else
262                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
263                         break;
264     
265                 case ICMD_ILOAD:
266                         if (temp > 0)
267                                 return tracing(block, index-1, temp-1);
268                     else
269                                 return create_trace(TRACE_IVAR, ip->op1, 0, index);
270                         break;
271
272                 case ICMD_ALOAD:    
273                         if (temp > 0)
274                                 return tracing(block, index-1, temp-1);
275                         else
276                                 return create_trace(TRACE_AVAR, ip->op1, 0, index);                     
277                         break;
278                 
279                 case ICMD_LSTORE:    
280                 case ICMD_DSTORE:    
281                 case ICMD_FSTORE:
282                 case ICMD_ISTORE:
283                 case ICMD_ASTORE:    
284                         return tracing(block, index-1, temp+1);
285                         break;
286         
287
288                 /* pop/dup/swap                                                                                                                 */
289                 case ICMD_POP:      
290                         return tracing(block, index-1, temp+1);
291                         break;
292      
293                 case ICMD_POP2:  
294                         return tracing(block, index-1, temp+2);
295                         break;
296
297                 case ICMD_DUP:
298                         if (temp > 0)
299                                 return tracing(block, index-1, temp-1);
300                         else
301                                 return tracing(block, index-1, temp);
302                         break;
303
304                 case ICMD_DUP_X1:                       /* ..., a, b ==> ..., b, a, b                           */
305                         switch (temp) {
306                         case 0:                                 /* when looking for top or third element,       */
307                         case 2:                                 /* just return top element                                      */
308                                 return tracing(block, index-1, 0);
309                         case 1:
310                                 return tracing(block, index-1, 1);
311                         default:
312                                 return tracing(block, index-1, temp-1);
313                                 }
314                         break;
315
316                 case ICMD_DUP2:                         /* ..., a, b ==> ..., a, b, a, b                        */
317                         switch (temp) { 
318                         case 0:                                 /* when looking for top or third element        */
319                         case 2:                                 /* just return top element                                      */
320                                 return tracing(block, index-1, 0);
321                         case 1:                                 /* when looking for second or fourth element*/
322                         case 3:                                 /* just return second element                           */
323                                 return tracing(block, index-1, 1);
324                         default:
325                                 return tracing(block, index-1, temp-2);
326                                 }
327                         break;
328
329                 case ICMD_DUP2_X1:                      /* ..., a, b, c ==> ..., b, c, a, b, c          */
330                         switch (temp) {
331                         case 0:
332                         case 3:
333                                 return tracing(block, index-1, 0);
334                         case 1:
335                         case 4:
336                                 return tracing(block, index-1, 1);
337                         case 2:
338                                 return tracing(block, index-1, 2);
339                         default:
340                                 return tracing(block, index-1, temp-2);
341                                 }
342                         break;
343
344                 case ICMD_DUP_X2:                       /* ..., a, b, c ==> ..., c, a, b, c                     */
345                         switch (temp) {    
346                         case 0:
347                         case 3:
348                                 return tracing(block, index-1, 0);
349                         case 1:
350                         case 4:
351                                 return tracing(block, index-1, 1);
352                         case 2:
353                                 return tracing(block, index-1, 2);
354                         default:
355                                 return tracing(block, index-1, temp-2);
356                                 }
357                         break;
358
359                 case ICMD_DUP2_X2:                      /* .., a, b, c, d ==> ..., c, d, a, b, c, d     */
360                         switch (temp) {
361                         case 0:
362                         case 4:
363                                 return tracing(block, index-1, 0);
364                         case 1:
365                         case 5:
366                                 return tracing(block, index-1, 1);
367                         case 2:
368                                 return tracing(block, index-1, 2);
369                         case 3:
370                                 return tracing(block, index-1, 3);
371                         default:
372                                 return tracing(block, index-1, temp-2);
373                                 }
374                         break;
375
376                 case ICMD_SWAP:                         /* ..., a, b ==> ..., b, a                                      */
377                         switch (temp) {
378                         case 0:
379                                 return tracing(block, index-1, 1);
380                         case 1:
381                                 return tracing(block, index-1, 0);
382                         default:
383                                 return tracing(block, index-1, temp);
384                                 }
385                         break;
386       
387                 /* Interger operations                                                                                                  */
388             case ICMD_INEG:                             /* ..., value  ==> ..., - value                         */
389                         if (temp > 0)
390                                 return tracing(block, index-1, temp);
391                         else                                    /* if an inter neg. operation is found,         */
392                                                                         /* invokethe negate function                            */
393                                 return negate(tracing(block, index-1, temp));
394                         break;
395
396                 case ICMD_LNEG:                         /* ..., value  ==> ..., - value                         */
397                 case ICMD_I2L:                          /* ..., value  ==> ..., value                           */
398                 case ICMD_L2I:                          /* ..., value  ==> ..., value                           */
399                 case ICMD_INT2BYTE:                     /* ..., value  ==> ..., value                           */
400                 case ICMD_INT2CHAR:                     /* ..., value  ==> ..., value                           */
401                 case ICMD_INT2SHORT:            /* ..., value  ==> ..., value                           */
402                         if (temp > 0)
403                                 return tracing(block, index-1, temp);
404                         else
405                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
406                         break;
407
408                 case ICMD_IADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
409                         if (temp > 0)
410                                 return tracing(block, index-1, temp+1);
411                         else                                    /* when add is encountered, invoke add func     */
412                                 return add(tracing(block, index-1, 0), tracing(block, index-1, 1));
413                         break;
414
415                 case ICMD_IADDCONST:            /* ..., value  ==> ..., value + constant        */
416                         if (temp > 0)
417                                 return tracing(block, index-1, temp);
418                         else                                    /* when a constant is added, create a           */
419                                                                         /* constant-trace and use add function          */
420                                 return add(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, ip->val.i, index));
421                         break;
422
423                 case ICMD_ISUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
424                         if (temp > 0)
425                                 return tracing(block, index-1, temp+1);
426                         else                                    /* use sub function for sub instructions        */
427                                 return sub(tracing(block, index-1, 1), tracing(block, index-1, 0));
428                         break;
429
430                 case ICMD_ISUBCONST:            /* ..., value  ==> ..., value + constant        */
431                         if (temp > 0)
432                                 return tracing(block, index-1, temp);
433                         else
434                                 return sub(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, ip->val.i, index));
435                         break;
436
437                 case ICMD_LADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
438                 case ICMD_LSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
439                 case ICMD_IMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
440                 case ICMD_LMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
441                 case ICMD_ISHL:                         /* ..., val1, val2  ==> ..., val1 << val2       */
442                 case ICMD_ISHR:                         /* ..., val1, val2  ==> ..., val1 >> val2       */
443                 case ICMD_IUSHR:                        /* ..., val1, val2  ==> ..., val1 >>> val2      */
444                 case ICMD_LSHL:                         /* ..., val1, val2  ==> ..., val1 << val2       */
445                 case ICMD_LSHR:                         /* ..., val1, val2  ==> ..., val1 >> val2       */
446                 case ICMD_LUSHR:                        /* ..., val1, val2  ==> ..., val1 >>> val2      */
447                 case ICMD_IAND:                         /* ..., val1, val2  ==> ..., val1 & val2        */
448                 case ICMD_LAND:  
449                 case ICMD_IOR:                          /* ..., val1, val2  ==> ..., val1 | val2        */
450                 case ICMD_LOR:
451                 case ICMD_IXOR:                         /* ..., val1, val2  ==> ..., val1 ^ val2        */
452                 case ICMD_LXOR:
453                         if (temp > 0)
454                                 return tracing(block, index-1, temp+1);
455                         else
456                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
457                         break;
458      
459                 case ICMD_LADDCONST:            /* ..., value  ==> ..., value + constant        */
460                 case ICMD_LSUBCONST:            /* ..., value  ==> ..., value - constant        */
461                 case ICMD_IMULCONST:            /* ..., value  ==> ..., value * constant        */
462                 case ICMD_LMULCONST:            /* ..., value  ==> ..., value * constant        */
463                 case ICMD_IDIVPOW2:                     /* ..., value  ==> ..., value << constant       */
464                 case ICMD_LDIVPOW2:                     /* val.i = constant                                                     */
465                 case ICMD_ISHLCONST:            /* ..., value  ==> ..., value << constant       */
466                 case ICMD_ISHRCONST:            /* ..., value  ==> ..., value >> constant       */
467                 case ICMD_IUSHRCONST:           /* ..., value  ==> ..., value >>> constant      */
468                 case ICMD_LSHLCONST:            /* ..., value  ==> ..., value << constant       */
469                 case ICMD_LSHRCONST:            /* ..., value  ==> ..., value >> constant       */
470                 case ICMD_LUSHRCONST:           /* ..., value  ==> ..., value >>> constant      */
471                 case ICMD_IANDCONST:            /* ..., value  ==> ..., value & constant        */
472                 case ICMD_IREMPOW2:                     /* ..., value  ==> ..., value % constant        */
473                 case ICMD_LANDCONST:            /* ..., value  ==> ..., value & constant        */
474                 case ICMD_LREMPOW2:                     /* ..., value  ==> ..., value % constant        */
475                 case ICMD_IORCONST:                     /* ..., value  ==> ..., value | constant        */
476                 case ICMD_LORCONST:                     /* ..., value  ==> ..., value | constant        */  
477                 case ICMD_IXORCONST:            /* ..., value  ==> ..., value ^ constant        */
478                 case ICMD_LXORCONST:            /* ..., value  ==> ..., value ^ constant        */
479                 case ICMD_LCMP:                         /* ..., val1, val2  ==> ..., val1 cmp val2      */
480                         if (temp > 0)
481                                 return tracing(block, index-1, temp);
482                         else
483                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
484                         break;
485
486                 case ICMD_IINC:                         /* ..., value  ==> ..., value + constant        */
487                         return tracing(block, index-1, temp);
488                         break;
489
490
491                 /* floating operations                                                                                                  */
492                 case ICMD_FADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
493                 case ICMD_DADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
494                 case ICMD_FSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
495                 case ICMD_DSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
496                 case ICMD_FMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
497                 case ICMD_DMUL:                         /* ..., val1, val2  ==> ..., val1 *** val2      */
498                 case ICMD_FDIV:                         /* ..., val1, val2  ==> ..., val1 / val2        */
499                 case ICMD_DDIV:                         /* ..., val1, val2  ==> ..., val1 / val2        */
500                 case ICMD_FREM:                         /* ..., val1, val2  ==> ..., val1 % val2        */
501                 case ICMD_DREM:                         /* ..., val1, val2  ==> ..., val1 % val2        */
502                 case ICMD_FCMPL:                        /* .., val1, val2  ==> ..., val1 fcmpl val2     */
503                 case ICMD_DCMPL:
504                 case ICMD_FCMPG:                        /* .., val1, val2  ==> ..., val1 fcmpg val2     */
505                 case ICMD_DCMPG:
506                         if (temp > 0)
507                                 return tracing(block, index-1, temp+1);
508                         else
509                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
510                         break;
511
512                 case ICMD_FNEG:                         /* ..., value  ==> ..., - value                         */
513                 case ICMD_DNEG:                         /* ..., value  ==> ..., - value                         */  
514                 case ICMD_I2F:                          /* ..., value  ==> ..., (float) value           */
515                 case ICMD_L2F:
516                 case ICMD_I2D:                          /* ..., value  ==> ..., (double) value          */
517                 case ICMD_L2D:
518                 case ICMD_F2I:                          /* ..., value  ==> ..., (int) value                     */
519                 case ICMD_D2I:
520                 case ICMD_F2L:                          /* ..., value  ==> ..., (long) value            */
521                 case ICMD_D2L:  
522                 case ICMD_F2D:                          /* ..., value  ==> ..., (double) value          */
523                 case ICMD_D2F:                          /* ..., value  ==> ..., (double) value          */
524                         if (temp > 0)
525                                 return tracing(block, index-1, temp);
526                         else
527                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
528                         break;
529    
530                 /* memory operations                                                                                                    */
531                  case ICMD_ARRAYLENGTH:         /* ..., arrayref  ==> ..., length                       */
532                         if (temp > 0)
533                                 return tracing(block, index-1, temp);
534                         else
535                                 return array_length(tracing(block, index-1, 0));
536                         break;
537
538                 case ICMD_AALOAD:                       /* ..., arrayref, index  ==> ..., value         */
539                 case ICMD_LALOAD:                       /* ..., arrayref, index  ==> ..., value         */  
540                 case ICMD_IALOAD:                       /* ..., arrayref, index  ==> ..., value         */
541                 case ICMD_FALOAD:                       /* ..., arrayref, index  ==> ..., value         */
542                 case ICMD_DALOAD:                       /* ..., arrayref, index  ==> ..., value         */
543                 case ICMD_CALOAD:                       /* ..., arrayref, index  ==> ..., value         */
544                 case ICMD_SALOAD:                       /* ..., arrayref, index  ==> ..., value         */
545                 case ICMD_BALOAD:                       /* ..., arrayref, index  ==> ..., value         */
546                         if (temp > 0)           
547                                 return tracing(block, index-1, temp+1);
548                         else
549                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
550                         break;
551
552                 case ICMD_AASTORE:                      /* ..., arrayref, index, value  ==> ...         */
553                 case ICMD_LASTORE:                      /* ..., arrayref, index, value  ==> ...         */
554                 case ICMD_IASTORE:                      /* ..., arrayref, index, value  ==> ...         */
555                 case ICMD_FASTORE:                      /* ..., arrayref, index, value  ==> ...         */
556                 case ICMD_DASTORE:                      /* ..., arrayref, index, value  ==> ...         */
557                 case ICMD_CASTORE:                      /* ..., arrayref, index, value  ==> ...         */
558                 case ICMD_SASTORE:                      /* ..., arrayref, index, value  ==> ...         */
559                 case ICMD_BASTORE:                      /* ..., arrayref, index, value  ==> ...         */
560                         return tracing(block, index-1, temp+3);
561                         break;
562  
563                 case ICMD_PUTSTATIC:            /* ..., value  ==> ...                                          */
564                 case ICMD_PUTFIELD:                     /* ..., value  ==> ...                                          */
565                         return tracing(block, index-1, temp+1);
566                         break;
567  
568                 case ICMD_GETSTATIC:            /* ...  ==> ..., value                                          */
569                 case ICMD_GETFIELD:                     /* ...  ==> ..., value                                          */
570                         if (temp > 0)
571                                 return tracing(block, index-1, temp-1);
572                         else
573                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
574                         break;
575
576
577                 /* branch: should not be encountered, but function calls possible               */
578                 case ICMD_INVOKESTATIC:         /* ..., [arg1, [arg2 ...]] ==> ...                      */
579                         m = ip->val.a;                  /* get method pointer and                                       */
580                         args = ip->op1;                 /* number of arguments                                          */
581                         if (m->returntype != TYPE_VOID)
582                                 retval = 1;                     /* if function returns a value, it is on        */
583                         else                                    /* top of stack                                                         */
584                                 retval = 0;
585       
586                         if (temp > 0)                   /* temp is increased by number of arguments     */
587                                                                         /* less a possible result value                         */
588                                 return tracing(block, index-1, temp+(args-retval));
589                         else
590                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
591                         break;
592
593                 case ICMD_INVOKESPECIAL:        /* ..., objectref, [arg1, [arg2 ...]] ==> .     */
594                 case ICMD_INVOKEVIRTUAL:        /* ..., objectref, [arg1, [arg2 ...]] ==> .     */
595                 case ICMD_INVOKEINTERFACE:      /* ..., objectref, [arg1, [arg2 ...]] ==> . */
596                         m = ip->val.a;
597                         args = ip->op1; 
598                         if (m->returntype != TYPE_VOID)
599                                 retval = 1;
600                         else
601                                 retval = 0;
602                         
603                         if (temp > 0)                   /* same as above but add 1 for object ref       */
604                                 return tracing(block, index-1, temp+(args-retval+1));
605                         else
606                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
607                         break;
608  
609                 /* special                                                                                                                              */  
610                 case ICMD_INSTANCEOF:           /* ..., objectref ==> ..., intresult            */
611                 case ICMD_CHECKCAST:            /* ..., objectref ==> ..., objectref            */
612                         if (temp > 0)
613                                 return tracing(block, index-1, temp);
614                         else
615                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
616                         break;
617       
618                 case ICMD_MULTIANEWARRAY:       /* ..., cnt1, [cnt2, ...] ==> ..., arrayref     */
619                                                                         /* op1 = dimension                                                      */ 
620
621                         if (temp > 0)                   /* temp increased by number of dimensions       */
622                                                                         /* minus one for array ref                                      */
623                                 return tracing(block, index-1, temp+(ip->op1 - 1));
624                         else
625                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
626                         break;
627        
628                 case ICMD_BUILTIN3:                     /* ..., arg1, arg2, arg3 ==> ...                        */
629                         if (ip->op1 != TYPE_VOID)
630                                 retval = 1;
631                         else
632                                 retval = 0;
633       
634                         if (temp > 0)                   /* increase temp by 3 minus possible return     */
635                                                                         /* value                                                                        */
636                                 return tracing(block, index-1, temp+(3-retval));
637                         else
638                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
639                         break;
640
641                 case ICMD_BUILTIN2:                     /* ..., arg1, arg2 ==> ...                                      */
642                         if (ip->op1 != TYPE_VOID)
643                                 retval = 1;
644                         else
645                                 retval = 0;
646                         if (temp > 0)
647                                 return tracing(block, index-1, temp+(2-retval));
648                         else
649                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
650                         break;
651
652                 case ICMD_BUILTIN1:     /* ..., arg1 ==> ...                                                    */
653                         if (ip->op1 != TYPE_VOID)
654                                 retval = 1;
655                         else
656                                 retval = 0;
657                         if (temp > 0)
658                                 return tracing(block, index-1, temp+(1-retval));
659                         else
660                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
661                         break;
662
663                 /* others                                                                                                                               */
664                 default:
665                         return create_trace(TRACE_UNKNOWN, -1, 0, index);
666                         }       /* switch       */
667                 }               /* if           */
668         else
669                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
670 }
671
672
673 /*
674  * These are local overrides for various environment variables in Emacs.
675  * Please do not remove this and leave it at the end of the file, where
676  * Emacs will automagically detect them.
677  * ---------------------------------------------------------------------
678  * Local variables:
679  * mode: c
680  * indent-tabs-mode: t
681  * c-basic-offset: 4
682  * tab-width: 4
683  * End:
684  */