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