73050f0b319940d7e4111433621ad7834c7f0369
[cacao.git] / src / vm / jit / loop / tracing.c
1 /* vm/jit/loop/tracing.c - trace functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
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 4862 2006-04-30 15:58:53Z edwin $
35
36 */
37
38
39 #include "mm/memory.h"
40 #include "vm/builtin.h"
41 #include "vm/resolve.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         instruction        *iptr;
218         methodinfo         *m;
219         builtintable_entry *bte;
220         methoddesc         *md;
221         s4                  args;
222         s4                  retval;
223
224         if (index >= 0) {
225                 iptr = block->iinstr + index;
226
227                 switch (iptr->opc) {
228                 
229                 /* nop, nullcheckpop                                                  */
230                 case ICMD_NOP:              /* ...  ==> ...                           */
231                         return tracing(block, index - 1, temp);
232                         break;
233       
234                 case ICMD_CHECKNULL:        /* ..., objectref  ==> ..., objectref     */
235                         return tracing(block, index-1, temp);
236                         break;
237
238                 /* Constants                                                          */
239                 case ICMD_LCONST:                               
240                 case ICMD_DCONST:
241                 case ICMD_FCONST:
242                 case ICMD_ACONST:
243                         if (temp > 0)                           
244                                 return tracing(block, index - 1, temp - 1);
245                         else
246                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
247                         break;                                          
248
249                 case ICMD_ICONST:
250                         if (temp > 0)           /* if the target argument is not on top                 */
251                                 return tracing(block, index-1, temp-1); /* look further                 */
252                         else
253                                 return create_trace(TRACE_ICONST, -1, iptr->val.i, index);
254                         break;                          /* else, return the value, found at this instr. */
255
256                 /* Load/Store                                                                                                                   */
257         case ICMD_LLOAD:                
258                 case ICMD_DLOAD:    
259                 case ICMD_FLOAD:
260                         if (temp > 0)
261                                 return tracing(block, index-1, temp-1);
262                         else
263                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
264                         break;
265     
266                 case ICMD_ILOAD:
267                         if (temp > 0)
268                                 return tracing(block, index-1, temp-1);
269                     else
270                                 return create_trace(TRACE_IVAR, iptr->op1, 0, index);
271                         break;
272
273                 case ICMD_ALOAD:    
274                         if (temp > 0)
275                                 return tracing(block, index-1, temp-1);
276                         else
277                                 return create_trace(TRACE_AVAR, iptr->op1, 0, index);                   
278                         break;
279                 
280                 case ICMD_LSTORE:    
281                 case ICMD_DSTORE:    
282                 case ICMD_FSTORE:
283                 case ICMD_ISTORE:
284                 case ICMD_ASTORE:    
285                         return tracing(block, index-1, temp+1);
286                         break;
287         
288
289                 /* pop/dup/swap                                                                                                                 */
290                 case ICMD_POP:      
291                         return tracing(block, index-1, temp+1);
292                         break;
293      
294                 case ICMD_POP2:  
295                         return tracing(block, index-1, temp+2);
296                         break;
297
298                 case ICMD_DUP:
299                         if (temp > 0)
300                                 return tracing(block, index-1, temp-1);
301                         else
302                                 return tracing(block, index-1, temp);
303                         break;
304
305                 case ICMD_DUP_X1:                       /* ..., a, b ==> ..., b, a, b                           */
306                         switch (temp) {
307                         case 0:                                 /* when looking for top or third element,       */
308                         case 2:                                 /* just return top element                                      */
309                                 return tracing(block, index-1, 0);
310                         case 1:
311                                 return tracing(block, index-1, 1);
312                         default:
313                                 return tracing(block, index-1, temp-1);
314                                 }
315                         break;
316
317                 case ICMD_DUP2:                         /* ..., a, b ==> ..., a, b, a, b                        */
318                         switch (temp) { 
319                         case 0:                                 /* when looking for top or third element        */
320                         case 2:                                 /* just return top element                                      */
321                                 return tracing(block, index-1, 0);
322                         case 1:                                 /* when looking for second or fourth element*/
323                         case 3:                                 /* just return second element                           */
324                                 return tracing(block, index-1, 1);
325                         default:
326                                 return tracing(block, index-1, temp-2);
327                                 }
328                         break;
329
330                 case ICMD_DUP2_X1:                      /* ..., a, b, c ==> ..., b, c, a, b, c          */
331                         switch (temp) {
332                         case 0:
333                         case 3:
334                                 return tracing(block, index-1, 0);
335                         case 1:
336                         case 4:
337                                 return tracing(block, index-1, 1);
338                         case 2:
339                                 return tracing(block, index-1, 2);
340                         default:
341                                 return tracing(block, index-1, temp-2);
342                                 }
343                         break;
344
345                 case ICMD_DUP_X2:                       /* ..., a, b, c ==> ..., c, a, b, c                     */
346                         switch (temp) {    
347                         case 0:
348                         case 3:
349                                 return tracing(block, index-1, 0);
350                         case 1:
351                         case 4:
352                                 return tracing(block, index-1, 1);
353                         case 2:
354                                 return tracing(block, index-1, 2);
355                         default:
356                                 return tracing(block, index-1, temp-2);
357                                 }
358                         break;
359
360                 case ICMD_DUP2_X2:                      /* .., a, b, c, d ==> ..., c, d, a, b, c, d     */
361                         switch (temp) {
362                         case 0:
363                         case 4:
364                                 return tracing(block, index-1, 0);
365                         case 1:
366                         case 5:
367                                 return tracing(block, index-1, 1);
368                         case 2:
369                                 return tracing(block, index-1, 2);
370                         case 3:
371                                 return tracing(block, index-1, 3);
372                         default:
373                                 return tracing(block, index-1, temp-2);
374                                 }
375                         break;
376
377                 case ICMD_SWAP:                         /* ..., a, b ==> ..., b, a                                      */
378                         switch (temp) {
379                         case 0:
380                                 return tracing(block, index-1, 1);
381                         case 1:
382                                 return tracing(block, index-1, 0);
383                         default:
384                                 return tracing(block, index-1, temp);
385                                 }
386                         break;
387       
388                 /* Interger operations                                                                                                  */
389             case ICMD_INEG:                             /* ..., value  ==> ..., - value                         */
390                         if (temp > 0)
391                                 return tracing(block, index-1, temp);
392                         else                                    /* if an inter neg. operation is found,         */
393                                                                         /* invokethe negate function                            */
394                                 return negate(tracing(block, index-1, temp));
395                         break;
396
397                 case ICMD_LNEG:                         /* ..., value  ==> ..., - value                         */
398                 case ICMD_I2L:                          /* ..., value  ==> ..., value                           */
399                 case ICMD_L2I:                          /* ..., value  ==> ..., value                           */
400                 case ICMD_INT2BYTE:                     /* ..., value  ==> ..., value                           */
401                 case ICMD_INT2CHAR:                     /* ..., value  ==> ..., value                           */
402                 case ICMD_INT2SHORT:            /* ..., value  ==> ..., value                           */
403                         if (temp > 0)
404                                 return tracing(block, index-1, temp);
405                         else
406                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
407                         break;
408
409                 case ICMD_IADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
410                         if (temp > 0)
411                                 return tracing(block, index-1, temp+1);
412                         else                                    /* when add is encountered, invoke add func     */
413                                 return add(tracing(block, index-1, 0), tracing(block, index-1, 1));
414                         break;
415
416                 case ICMD_IADDCONST:            /* ..., value  ==> ..., value + constant        */
417                         if (temp > 0)
418                                 return tracing(block, index-1, temp);
419                         else                                    /* when a constant is added, create a           */
420                                                                         /* constant-trace and use add function          */
421                                 return add(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, iptr->val.i, index));
422                         break;
423
424                 case ICMD_ISUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
425                         if (temp > 0)
426                                 return tracing(block, index-1, temp+1);
427                         else                                    /* use sub function for sub instructions        */
428                                 return sub(tracing(block, index-1, 1), tracing(block, index-1, 0));
429                         break;
430
431                 case ICMD_ISUBCONST:            /* ..., value  ==> ..., value + constant        */
432                         if (temp > 0)
433                                 return tracing(block, index-1, temp);
434                         else
435                                 return sub(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, iptr->val.i, index));
436                         break;
437
438                 case ICMD_LADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
439                 case ICMD_LSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
440                 case ICMD_IMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
441                 case ICMD_LMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
442                 case ICMD_ISHL:                         /* ..., val1, val2  ==> ..., val1 << val2       */
443                 case ICMD_ISHR:                         /* ..., val1, val2  ==> ..., val1 >> val2       */
444                 case ICMD_IUSHR:                        /* ..., val1, val2  ==> ..., val1 >>> val2      */
445                 case ICMD_LSHL:                         /* ..., val1, val2  ==> ..., val1 << val2       */
446                 case ICMD_LSHR:                         /* ..., val1, val2  ==> ..., val1 >> val2       */
447                 case ICMD_LUSHR:                        /* ..., val1, val2  ==> ..., val1 >>> val2      */
448                 case ICMD_IAND:                         /* ..., val1, val2  ==> ..., val1 & val2        */
449                 case ICMD_LAND:  
450                 case ICMD_IOR:                          /* ..., val1, val2  ==> ..., val1 | val2        */
451                 case ICMD_LOR:
452                 case ICMD_IXOR:                         /* ..., val1, val2  ==> ..., val1 ^ val2        */
453                 case ICMD_LXOR:
454                         if (temp > 0)
455                                 return tracing(block, index-1, temp+1);
456                         else
457                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
458                         break;
459      
460                 case ICMD_LADDCONST:            /* ..., value  ==> ..., value + constant        */
461                 case ICMD_LSUBCONST:            /* ..., value  ==> ..., value - constant        */
462                 case ICMD_IMULCONST:            /* ..., value  ==> ..., value * constant        */
463                 case ICMD_LMULCONST:            /* ..., value  ==> ..., value * constant        */
464                 case ICMD_IDIVPOW2:                     /* ..., value  ==> ..., value << constant       */
465                 case ICMD_LDIVPOW2:                     /* val.i = constant                                                     */
466                 case ICMD_ISHLCONST:            /* ..., value  ==> ..., value << constant       */
467                 case ICMD_ISHRCONST:            /* ..., value  ==> ..., value >> constant       */
468                 case ICMD_IUSHRCONST:           /* ..., value  ==> ..., value >>> constant      */
469                 case ICMD_LSHLCONST:            /* ..., value  ==> ..., value << constant       */
470                 case ICMD_LSHRCONST:            /* ..., value  ==> ..., value >> constant       */
471                 case ICMD_LUSHRCONST:           /* ..., value  ==> ..., value >>> constant      */
472                 case ICMD_IANDCONST:            /* ..., value  ==> ..., value & constant        */
473                 case ICMD_IREMPOW2:                     /* ..., value  ==> ..., value % constant        */
474                 case ICMD_LANDCONST:            /* ..., value  ==> ..., value & constant        */
475                 case ICMD_LREMPOW2:                     /* ..., value  ==> ..., value % constant        */
476                 case ICMD_IORCONST:                     /* ..., value  ==> ..., value | constant        */
477                 case ICMD_LORCONST:                     /* ..., value  ==> ..., value | constant        */  
478                 case ICMD_IXORCONST:            /* ..., value  ==> ..., value ^ constant        */
479                 case ICMD_LXORCONST:            /* ..., value  ==> ..., value ^ constant        */
480                 case ICMD_LCMP:                         /* ..., val1, val2  ==> ..., val1 cmp val2      */
481                         if (temp > 0)
482                                 return tracing(block, index-1, temp);
483                         else
484                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
485                         break;
486
487                 case ICMD_IINC:                         /* ..., value  ==> ..., value + constant        */
488                         return tracing(block, index-1, temp);
489                         break;
490
491
492                 /* floating operations                                                                                                  */
493                 case ICMD_FADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
494                 case ICMD_DADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
495                 case ICMD_FSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
496                 case ICMD_DSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
497                 case ICMD_FMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
498                 case ICMD_DMUL:                         /* ..., val1, val2  ==> ..., val1 *** val2      */
499                 case ICMD_FDIV:                         /* ..., val1, val2  ==> ..., val1 / val2        */
500                 case ICMD_DDIV:                         /* ..., val1, val2  ==> ..., val1 / val2        */
501                 case ICMD_FREM:                         /* ..., val1, val2  ==> ..., val1 % val2        */
502                 case ICMD_DREM:                         /* ..., val1, val2  ==> ..., val1 % val2        */
503                 case ICMD_FCMPL:                        /* .., val1, val2  ==> ..., val1 fcmpl val2     */
504                 case ICMD_DCMPL:
505                 case ICMD_FCMPG:                        /* .., val1, val2  ==> ..., val1 fcmpg val2     */
506                 case ICMD_DCMPG:
507                         if (temp > 0)
508                                 return tracing(block, index-1, temp+1);
509                         else
510                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
511                         break;
512
513                 case ICMD_FNEG:                         /* ..., value  ==> ..., - value                         */
514                 case ICMD_DNEG:                         /* ..., value  ==> ..., - value                         */  
515                 case ICMD_I2F:                          /* ..., value  ==> ..., (float) value           */
516                 case ICMD_L2F:
517                 case ICMD_I2D:                          /* ..., value  ==> ..., (double) value          */
518                 case ICMD_L2D:
519                 case ICMD_F2I:                          /* ..., value  ==> ..., (int) value                     */
520                 case ICMD_D2I:
521                 case ICMD_F2L:                          /* ..., value  ==> ..., (long) value            */
522                 case ICMD_D2L:  
523                 case ICMD_F2D:                          /* ..., value  ==> ..., (double) value          */
524                 case ICMD_D2F:                          /* ..., value  ==> ..., (double) value          */
525                         if (temp > 0)
526                                 return tracing(block, index-1, temp);
527                         else
528                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
529                         break;
530    
531                 /* memory operations                                                                                                    */
532                  case ICMD_ARRAYLENGTH:         /* ..., arrayref  ==> ..., length                       */
533                         if (temp > 0)
534                                 return tracing(block, index-1, temp);
535                         else
536                                 return array_length(tracing(block, index-1, 0));
537                         break;
538
539                 case ICMD_AALOAD:                       /* ..., arrayref, index  ==> ..., value         */
540                 case ICMD_LALOAD:                       /* ..., arrayref, index  ==> ..., value         */  
541                 case ICMD_IALOAD:                       /* ..., arrayref, index  ==> ..., value         */
542                 case ICMD_FALOAD:                       /* ..., arrayref, index  ==> ..., value         */
543                 case ICMD_DALOAD:                       /* ..., arrayref, index  ==> ..., value         */
544                 case ICMD_CALOAD:                       /* ..., arrayref, index  ==> ..., value         */
545                 case ICMD_SALOAD:                       /* ..., arrayref, index  ==> ..., value         */
546                 case ICMD_BALOAD:                       /* ..., arrayref, index  ==> ..., value         */
547                         if (temp > 0)           
548                                 return tracing(block, index-1, temp+1);
549                         else
550                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
551                         break;
552
553                 case ICMD_AASTORE:                      /* ..., arrayref, index, value  ==> ...         */
554                 case ICMD_LASTORE:                      /* ..., arrayref, index, value  ==> ...         */
555                 case ICMD_IASTORE:                      /* ..., arrayref, index, value  ==> ...         */
556                 case ICMD_FASTORE:                      /* ..., arrayref, index, value  ==> ...         */
557                 case ICMD_DASTORE:                      /* ..., arrayref, index, value  ==> ...         */
558                 case ICMD_CASTORE:                      /* ..., arrayref, index, value  ==> ...         */
559                 case ICMD_SASTORE:                      /* ..., arrayref, index, value  ==> ...         */
560                 case ICMD_BASTORE:                      /* ..., arrayref, index, value  ==> ...         */
561                         return tracing(block, index-1, temp+3);
562                         break;
563  
564                 case ICMD_PUTSTATIC:        /* ..., value  ==> ...                    */
565                 case ICMD_PUTFIELD:         /* ..., value  ==> ...                    */
566                         return tracing(block, index - 1, temp + 1);
567                         break;
568  
569                 case ICMD_GETSTATIC:        /* ...  ==> ..., value                    */
570                 case ICMD_GETFIELD:         /* ...  ==> ..., value                    */
571                         if (temp > 0)
572                                 return tracing(block, index-1, temp - 1);
573                         else
574                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
575                         break;
576
577
578                 /* branch: should not be encountered, but function calls possible     */
579
580                 case ICMD_INVOKESTATIC:     /* ..., [arg1, [arg2 ...]] ==> ...        */
581                 case ICMD_INVOKESPECIAL:    /* ..., objectref, [arg1, [arg2 ...]] ==> . */
582                 case ICMD_INVOKEVIRTUAL:
583                 case ICMD_INVOKEINTERFACE:
584                         INSTRUCTION_GET_METHODDESC(iptr,md);
585
586                         args = md->paramcount;  /* number of arguments                    */
587
588                         if (md->returntype.type != TYPE_VOID)
589                                 retval = 1;         /* if function returns a value, it is on  */
590                         else                    /* top of stack                           */
591                                 retval = 0;
592       
593                         if (temp > 0)           /* temp is increased by number of         */
594                                                 /* arguments a possible result value      */
595                                 return tracing(block, index - 1, temp + (args - retval));
596                         else
597                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
598                         break;
599
600
601                 /* special                                                            */
602
603                 case ICMD_INSTANCEOF:       /* ..., objectref ==> ..., intresult      */
604                 case ICMD_CHECKCAST:        /* ..., objectref ==> ..., objectref      */
605                         if (temp > 0)
606                                 return tracing(block, index-1, temp);
607                         else
608                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
609                         break;
610       
611                 case ICMD_MULTIANEWARRAY:       /* ..., cnt1, [cnt2, ...] ==> ..., arrayref     */
612                                                                         /* op1 = dimension                        */
613
614                         if (temp > 0)           /* temp increased by number of dimensions */
615                                                                         /* minus one for array ref                */
616                                 return tracing(block, index - 1, temp + (iptr->op1 - 1));
617                         else
618                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
619                         break;
620        
621                 case ICMD_BUILTIN:         /* ..., [arg1, [arg2 ...]] ==> ...         */
622                         bte = iptr->val.a;
623                         md = bte->md;
624                         args = md->paramcount;
625                         if (md->returntype.type != TYPE_VOID)
626                                 retval = 1;
627                         else
628                                 retval = 0;
629       
630                         if (temp > 0)           /* temp is increased by number of         */
631                                                 /* arguments less a possible result value */
632                                 return tracing(block, index - 1, temp + (args - retval));
633                         else
634                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
635                         break;
636
637
638                 /* others                                                             */
639
640                 default:
641                         return create_trace(TRACE_UNKNOWN, -1, 0, index);
642                         }       /* switch       */
643                 }               /* if           */
644
645         else
646                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
647 }
648
649
650 /*
651  * These are local overrides for various environment variables in Emacs.
652  * Please do not remove this and leave it at the end of the file, where
653  * Emacs will automagically detect them.
654  * ---------------------------------------------------------------------
655  * Local variables:
656  * mode: c
657  * indent-tabs-mode: t
658  * c-basic-offset: 4
659  * tab-width: 4
660  * End:
661  */