GNU header update.
[cacao.git] / src / vm / jit / parse.c
1 /* vm/jit/parse.c - parser for JavaVM to intermediate code translation
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Author: Andreas Krall
28
29    Changes: Carolyn Oates
30             Edwin Steiner
31             Joseph Wenninger
32
33    $Id: parse.c 1735 2004-12-07 14:33:27Z twisti $
34
35 */
36
37
38 #include <string.h>
39
40 #include "config.h"
41 #include "types.h"
42 #include "mm/memory.h"
43 #include "native/native.h"
44 #include "toolbox/logging.h"
45 #include "vm/builtin.h"
46 #include "vm/exceptions.h"
47 #include "vm/global.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/statistics.h"
51 #include "vm/tables.h"
52 #include "vm/jit/jit.h"
53 #include "vm/jit/parse.h"
54 #include "vm/jit/inline/parseRT.h"
55 #include "vm/jit/inline/inline.h"
56 #include "vm/jit/loop/loop.h"
57
58
59 #define METHINFO(mm) \
60         { \
61                 printf("PARSE method name ="); \
62                 utf_display(mm->class->name); \
63                 printf("."); \
64                 method_display(mm); \
65                 fflush(stdout); \
66         }
67 #define DEBUGMETH(mm) \
68 if (DEBUG4 == true) \
69         { \
70                 printf("PARSE method name ="); \
71                 utf_display(mm->class->name); \
72                 printf("."); \
73                 method_display(mm); \
74                 fflush(stdout); \
75         }
76
77 #define SHOWOPCODE \
78 if (DEBUG4 == true) {printf("Parse p=%i<%i<   opcode=<%i> %s\n", \
79                            p, m->jcodelength,opcode,opcode_names[opcode]);}
80 bool DEBUG = false;
81 bool DEBUG2 = false;
82 bool DEBUG3 = false;
83 bool DEBUG4 = false;  /*opcodes*/
84
85 /*INLINING*/
86 #define debug_writebranch if (DEBUG2==true) printf("op:: %s i: %d label_index[i]: %d label_index=0x%x\n",opcode_names[opcode], i, label_index[i], label_index);
87 #define debug_writebranch1
88
89
90 /* function descriptor2typesL ***************************************************
91
92         decodes a already checked method descriptor. The parameter count, the
93         return type and the argument types are stored in the passed methodinfo.
94         gets and saves classptr for object ref.s
95
96 *******************************************************************************/                
97
98 classSetNode *descriptor2typesL(methodinfo *m)
99 {
100         int debugInfo = 0;
101         int i;
102         u1 *types, *tptr;
103         int pcount, c;
104         char *utf_ptr;
105         classinfo** classtypes;
106         char *class; 
107         char *desc;
108         classSetNode *p=NULL;
109         if (debugInfo >= 1) {
110                 printf("In descriptor2typesL >>>\t"); fflush(stdout);
111                 utf_display(m->class->name); printf(".");
112                 method_display(m);fflush(stdout);
113         }
114
115         pcount = 0;
116         desc =       MNEW (char, 256); 
117         types = DMNEW (u1, m->descriptor->blength); 
118         classtypes = MNEW (classinfo*, m->descriptor->blength+1);
119         m->returnclass = NULL;
120         tptr = types;
121         if (!(m->flags & ACC_STATIC)) {
122                 *tptr++ = TYPE_ADR;
123                 if (debugInfo >= 1) {
124                         printf("param #0 (this?) method class =");utf_display(m->class->name);printf("\n");
125                 }
126                 classtypes[pcount] = m->class;
127                 p = addClassCone(p,  m->class);
128                 pcount++;
129         }
130
131         utf_ptr = m->descriptor->text + 1;
132         strcpy (desc,utf_ptr);
133    
134         while ((c = *desc++) != ')') {
135                 pcount++;
136                 switch (c) {
137                 case 'B':
138                 case 'C':
139                 case 'I':
140                 case 'S':
141                 case 'Z':  *tptr++ = TYPE_INT;
142                         break;
143                 case 'J':  *tptr++ = TYPE_LNG;
144                         break;
145                 case 'F':  *tptr++ = TYPE_FLT;
146                         break;
147                 case 'D':  *tptr++ = TYPE_DBL;
148                         break;
149                 case 'L':  *tptr++ = TYPE_ADR;
150                         /* get class string */
151                         class = strtok(desc,";");
152                         desc = strtok(NULL,"\0");
153                         /* get/save classinfo ptr */
154                         classtypes[pcount-1] = class_get(utf_new_char(class));
155                         p = addClassCone(p,  class_get(utf_new_char(class)));
156                         if (debugInfo >= 1) {
157                                 printf("LParam#%i 's class type is: %s\n",pcount-1,class);fflush(stdout);
158                                 printf("Lclasstypes[%i]=",pcount-1);fflush(stdout);
159                                 utf_display(classtypes[pcount-1]->name);
160                         }
161                         break;
162                 case '[':  *tptr++ = TYPE_ADR;
163                         while (c == '[')
164                                 c = *desc++;
165                         /* get class string */
166                         if (c == 'L') {
167                                 class = strtok(desc,";");
168                                 desc = strtok(NULL,"\0");
169                                 /* get/save classinfo ptr */
170                                 classtypes[pcount-1] = class_get(utf_new_char(class));
171                                 p= addClassCone(p,  class_get(utf_new_char(class)));
172                                 if (debugInfo >= 1) {
173                                         printf("[Param#%i 's class type is: %s\n",pcount-1,class);
174                                         printf("[classtypes[%i]=",pcount-1);fflush(stdout);
175                                         utf_display(classtypes[pcount-1]->name);
176                                         printf("\n");
177                                 }
178                         }
179                         else
180                                 classtypes[pcount-1] = NULL;
181                         break;
182                 default:   
183                         panic("Ill formed methodtype-descriptor");
184                 }
185         }
186
187         /* compute return type */
188         switch (*desc++) {
189         case 'B':
190         case 'C':
191         case 'I':
192         case 'S':
193         case 'Z':  m->returntype = TYPE_INT;
194                 break;
195         case 'J':  m->returntype = TYPE_LNG;
196                 break;
197         case 'F':  m->returntype = TYPE_FLT;
198                 break;
199         case 'D':  m->returntype = TYPE_DBL;
200                 break;
201         case '[':
202                 m->returntype = TYPE_ADR;
203                 c = *desc;
204                 while (c == '[')
205                         c = *desc++;
206                 if (c != 'L') break;
207                 *(desc++);
208                            
209         case 'L':  
210                 m->returntype = TYPE_ADR;
211                           
212                 /* get class string */
213                 class = strtok(desc,";");
214                 m->returnclass = class_get(utf_new_char(class));
215                 if (m->returnclass == NULL) {
216                         printf("class=%s :\t",class);
217                         panic ("return class not found");
218                 }
219                 break;
220         case 'V':  m->returntype = TYPE_VOID;
221                 break;
222
223         default:   panic("Ill formed methodtype-descriptor-ReturnType");
224         }
225
226         m->paramcount = pcount;
227         m->paramtypes = types;
228         m->paramclass = classtypes;
229
230         if (debugInfo >=1) {
231                 if (pcount > 0) {
232                         for (i=0; i< m->paramcount; i++) {
233                         if ((m->paramtypes[i] == TYPE_ADR) && (m->paramclass[i] != NULL)) {
234                                         printf("Param #%i is:\t",i);
235                                         utf_display(m->paramclass[i]->name);
236                                         printf("\n");
237                                 }
238                         }
239                 }
240                 if ((m->returntype == TYPE_ADR) && (m->returnclass != NULL)) { 
241                         printf("\tReturn Type is:\t"); fflush(stdout);
242                         utf_display(m->returnclass->name);
243                         printf("\n");
244                 }
245
246                 printf("params2types: START  results in a set \n");
247                 printf("param2types: A Set size=%i=\n",sizeOfSet(p));
248                 printSet(p);
249         }
250
251         return p;
252 }
253
254
255
256 /* function descriptor2types ***************************************************
257
258         decodes a already checked method descriptor. The parameter count, the
259         return type and the argument types are stored in the passed methodinfo.
260
261 *******************************************************************************/                
262
263 void descriptor2types(methodinfo *m)
264 {
265         u1 *types, *tptr;
266         int pcount, c;
267         char *utf_ptr;
268         pcount = 0;
269         types = DMNEW(u1, m->descriptor->blength); 
270         
271         tptr = types;
272         if (!(m->flags & ACC_STATIC)) {
273                 *tptr++ = TYPE_ADR;
274                 pcount++;
275         }
276
277         utf_ptr = m->descriptor->text + 1;
278    
279         while ((c = *utf_ptr++) != ')') {
280                 pcount++;
281                 switch (c) {
282                 case 'B':
283                 case 'C':
284                 case 'I':
285                 case 'S':
286                 case 'Z':
287                         *tptr++ = TYPE_INT;
288                         break;
289                 case 'J':
290                         *tptr++ = TYPE_LNG;
291                         break;
292                 case 'F':
293                         *tptr++ = TYPE_FLT;
294                         break;
295                 case 'D':
296                         *tptr++ = TYPE_DBL;
297                         break;
298                 case 'L':
299                         *tptr++ = TYPE_ADR;
300                         while (*utf_ptr++ != ';');
301                         break;
302                 case '[':
303                         *tptr++ = TYPE_ADR;
304                         while (c == '[')
305                                 c = *utf_ptr++;
306                         if (c == 'L')
307                                 while (*utf_ptr++ != ';') /* skip */;
308                         break;
309                 default:
310                         panic("Ill formed methodtype-descriptor");
311                 }
312         }
313
314         /* compute return type */
315
316         switch (*utf_ptr++) {
317         case 'B':
318         case 'C':
319         case 'I':
320         case 'S':
321         case 'Z':
322                 m->returntype = TYPE_INT;
323                 break;
324         case 'J':
325                 m->returntype = TYPE_LNG;
326                 break;
327         case 'F':
328                 m->returntype = TYPE_FLT;
329                 break;
330         case 'D':
331                 m->returntype = TYPE_DBL;
332                 break;
333         case '[':
334         case 'L':
335                 m->returntype = TYPE_ADR;
336                 break;
337         case 'V':
338                 m->returntype = TYPE_VOID;
339                 break;
340         default:
341                 panic("Ill formed methodtype-descriptor");
342         }
343
344         m->paramcount = pcount;
345         m->paramtypes = types;
346 }
347
348
349
350 /*******************************************************************************
351
352         function 'parse' scans the JavaVM code and generates intermediate code
353
354         During parsing the block index table is used to store at bit pos 0
355         a flag which marks basic block starts and at position 1 to 31 the
356         intermediate instruction index. After parsing the block index table
357         is scanned, for marked positions a block is generated and the block
358         number is stored in the block index table.
359
360 *******************************************************************************/
361
362 static exceptiontable* fillextable(methodinfo *m, 
363                 exceptiontable* extable, exceptiontable *raw_extable, 
364                 int exceptiontablelength, 
365                 int *label_index, int *block_count, 
366                 t_inlining_globals *inline_env)
367 {
368         int b_count, i, p, src, insertBlock;
369         
370         if (exceptiontablelength == 0) 
371                 return extable;
372
373         
374         /*if (m->exceptiontablelength > 0) {
375           DEBUGMETH(m);
376           printf("m->exceptiontablelength=%i\n",m->exceptiontablelength);
377           panic("exceptiontablelength > 0");
378           }*/
379
380         b_count = *block_count;
381
382         for (src = exceptiontablelength-1; src >=0; src--) {
383                 /* printf("Excepiont table index: %d\n",i); */
384                 p = raw_extable[src].startpc;
385                 if (label_index != NULL) p = label_index[p];
386                 extable->startpc = p;
387                 bound_check(p);
388                 block_insert(p);
389                 
390 /*** if (DEBUG==true){printf("---------------------block_inserted:b_count=%i m->basicblockindex[(p=%i)]=%i=%p\n",b_count,p,m->basicblockindex[(p)],m->basicblockindex[(p)]); 
391   fflush(stdout); } ***/   
392                 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
393                 if (p <= raw_extable[src].startpc)
394                         panic("Invalid exception handler range");
395
396                 if (p >inline_env->method->jcodelength) {
397                         panic("Invalid exception handler end is after code end");
398                 }
399                 if (p<inline_env->method->jcodelength) insertBlock=1; else insertBlock=0;
400                 /*if (label_index !=NULL) printf("%s:translating endpc:%ld to %ld, label_index:%p\n",m->name->text,p,label_index[p],label_index); else
401                         printf("%s:fillextab: endpc:%ld\n",m->name->text,p);*/
402                 if (label_index != NULL) p = label_index[p];
403                 extable->endpc = p;
404                 bound_check1(p);
405                 /*if (p < inline_env->method->jcodelength) {
406                         block_insert(p); }*/
407                 if (insertBlock) block_insert(p);
408
409                 p = raw_extable[src].handlerpc;
410                 if (label_index != NULL) p = label_index[p];
411                 extable->handlerpc = p;
412                 bound_check(p);
413                 block_insert(p);
414
415                 extable->catchtype  = raw_extable[src].catchtype;
416                 extable->next = NULL;
417                 extable->down = &extable[1];
418                 extable--;
419         }
420
421         *block_count = b_count;
422         return extable; /*&extable[i];*/  /* return the next free xtable* */
423 }
424
425
426
427 methodinfo *parse(methodinfo *m, codegendata *cd, t_inlining_globals *inline_env)
428 {
429         int  p;                     /* java instruction counter           */
430         int  nextp;                 /* start of next java instruction     */
431         int  opcode;                /* java opcode                        */
432         int  i;                     /* temporary for different uses (ctrs)*/
433         int  ipc = 0;               /* intermediate instruction counter   */
434         int  b_count = 0;           /* basic block counter                */
435         int  s_count = 0;           /* stack element counter              */
436         bool blockend = false;      /* true if basic block end has been reached   */
437         bool iswide = false;        /* true if last instruction was a wide*/
438         instruction *iptr;          /* current ptr into instruction array */
439         int gp;                     /* global java instruction counter    */
440                                     /* inlining info for current method   */
441
442         inlining_methodinfo *inlinfo = inline_env->inlining_rootinfo;
443         inlining_methodinfo *tmpinlinf;
444         int nextgp = -1;            /* start of next method to be inlined */
445         int *label_index = NULL;    /* label redirection table            */
446         int firstlocal = 0;         /* first local variable of method     */
447         exceptiontable* nextex;     /* points next free entry in extable  */
448         u1 *instructionstart;       /* 1 for pcs which are valid instr. starts    */
449
450         u2 lineindex = 0;
451         u2 currentline = 0;
452         u2 linepcchange = 0;
453
454         u2 skipBasicBlockChange;
455
456 if (DEBUG4==true) {printf("\nPARSING: "); fflush(stdout);
457 DEBUGMETH(m);
458 }
459 if (opt_rt) {
460   if (m->methodUsed != USED) {
461     if (opt_verbose) {
462       printf(" rta missed: "); fflush(stdout);
463       METHINFO(m);
464       }
465     if ( (rtMissed = fopen("rtMissed", "a")) == NULL) {
466       printf("CACAO - rtMissed file: cant open file to write append \n");
467       }
468     else {
469       utf_fprint(rtMissed,m->class->name); 
470        fprintf(rtMissed," "); fflush(rtMissed);
471       utf_fprint(rtMissed,m->name);
472        fprintf(rtMissed," "); fflush(rtMissed);
473       utf_fprint(rtMissed,m->descriptor); 
474        fprintf(rtMissed,"\n"); fflush(rtMissed);
475       fclose(rtMissed);
476       }
477    } 
478 }
479         /* INLINING */
480
481         if (useinlining) {
482                 label_index = inlinfo->label_index;
483                 m->maxstack = inline_env->cummaxstack;
484                 /*JOWENN m->exceptiontablelength = inline_env->cumextablelength;*/
485                 tmpinlinf = (inlining_methodinfo*) 
486                                 list_first(inlinfo->inlinedmethods);
487                 if (tmpinlinf != NULL) nextgp = tmpinlinf->startgp;
488         }
489
490 /**** static analysis has to be called before inlining
491         which has to be called before reg_set
492         which has to be called before parse (or ???)
493         will check if method being parsed was analysed here
494         ****/ 
495         if (opt_xta && opt_verbose) { 
496                 /**RT_jit_parse(m);**/
497                 printf("XTA requested, not available\n");
498                 }
499         if (opt_vta && opt_verbose)  
500                     printf("VTA requested, not yet implemented\n");
501
502         /* allocate instruction array and block index table */
503         
504         /* 1 additional for end ipc * # cum inline methods*/
505         
506         m->basicblockindex = DMNEW(s4, inline_env->cumjcodelength + inline_env->cummethods);
507         memset(m->basicblockindex, 0, sizeof(s4) * (inline_env->cumjcodelength + inline_env->cummethods));
508
509         instructionstart = DMNEW(u1, inline_env->cumjcodelength + inline_env->cummethods);
510         memset(instructionstart, 0, sizeof(u1) * (inline_env->cumjcodelength + inline_env->cummethods));
511
512         /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
513         /* additional MONITOREXITS are reached by branches which are 3 bytes */
514         
515         iptr = m->instructions = DMNEW(instruction, inline_env->cumjcodelength + 5);
516
517         /* Zero the intermediate instructions array so we don't have any
518          * invalid pointers in it if we cannot finish analyse_stack(). */
519
520         memset(iptr, 0, sizeof(instruction) * (inline_env->cumjcodelength + 5));
521         
522         /* compute branch targets of exception table */
523         /*
524 if (m->exceptiontable == NULL) {
525   printf("m->exceptiontable=NULL\n");fflush(stdout);
526   }
527 else {
528   printf("m->exceptiontable != NULL\n");fflush(stdout);
529   }
530 printf("m->exceptiontablelength=%i, inline_env->method->exceptiontablelength=%i,inline_env->cumextablelength=%i\n",
531 m->exceptiontablelength, inline_env->method->exceptiontablelength,inline_env->cumextablelength);
532         */
533         /*
534 if (m->exceptiontablelength > 0)
535         m->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1); 
536         */
537
538         nextex = fillextable(m, 
539           &(cd->exceptiontable[cd->exceptiontablelength-1]), m->exceptiontable, m->exceptiontablelength, 
540           label_index, &b_count, inline_env);
541         s_count = 1 + m->exceptiontablelength; /* initialize stack element counter   */
542
543 #if defined(USE_THREADS)
544         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
545                 m->isleafmethod = false;
546                 inline_env->method->isleafmethod = false;
547         }                       
548 #endif
549
550         /* scan all java instructions */
551         currentline = 0;
552         linepcchange = 0;
553
554         if (m->linenumbercount == 0) {
555                 lineindex = 0;
556
557         } else {
558                 linepcchange = m->linenumbers[0].start_pc;
559         }
560
561         skipBasicBlockChange=0;
562         for (p = 0, gp = 0; p < inline_env->method->jcodelength; gp += (nextp - p), p = nextp) {
563           
564                 /* DEBUG */      if (DEBUG==true) printf("----- p:%d gp:%d\n",p,gp);
565
566                 /* mark this position as a valid instruction start */
567                 if (!iswide) {
568                         instructionstart[gp] = 1;
569                         /*log_text("new start of instruction");*/
570                         if (linepcchange==p) {
571                                 if (inline_env->method->linenumbercount > lineindex) {
572                                         currentline = inline_env->method->linenumbers[lineindex].line_number;
573                                         lineindex++;
574                                         if (lineindex < inline_env->method->linenumbercount)
575                                                 linepcchange = inline_env->method->linenumbers[lineindex].start_pc;
576                                         /*printf("Line number changed to: %ld\n",currentline);*/
577                                 }
578                         }
579                 }
580
581                 /*INLINING*/
582                 if ((useinlining) && (gp == nextgp)) {
583                         u1 *tptr;
584                         bool *readonly = NULL;
585                         int argBlockIdx=0;
586
587                         block_insert(gp);               /* JJJJJJJJJJ */
588                         blockend=false;
589                         instructionstart[gp] = 1;
590                         m->basicblockindex[gp] |= (ipc << 1);  /*FIXME: necessary ? */
591
592                         opcode = code_get_u1(p,inline_env->method);
593                         nextp = p += jcommandsize[opcode];
594                         if (nextp > inline_env->method->jcodelength)
595                                 panic("Unexpected end of bytecode");
596                         tmpinlinf = list_first(inlinfo->inlinedmethods);
597                         firstlocal = tmpinlinf->firstlocal;
598                         label_index = tmpinlinf->label_index;
599                         readonly = tmpinlinf->readonly;
600
601                         for (i=0,tptr=tmpinlinf->method->paramtypes;i<tmpinlinf->method->paramcount;i++,tptr++) {
602                                 if ( ((*tptr)==TYPE_LNG) ||
603                                   ((*tptr)==TYPE_DBL) )
604                                         argBlockIdx+=2;
605                                 else
606                                         argBlockIdx++;
607                         }
608
609                         for (i = 0, tptr = tmpinlinf->method->paramtypes + tmpinlinf->method->paramcount - 1; i < tmpinlinf->method->paramcount; i++, tptr--) {
610                                 int op;
611
612                                 if ((i == 0) && inlineparamopt) {
613                                         OP1(ICMD_CLEAR_ARGREN, firstlocal);
614                                 }
615
616                                 if (!inlineparamopt || !readonly[i]) {
617                                         op = ICMD_ISTORE;
618
619                                 } else {
620                                         op = ICMD_READONLY_ARG;
621                                 }
622
623                                 op += *tptr;
624                                 if ( ((*tptr)==TYPE_LNG) ||
625                                   ((*tptr)==TYPE_DBL) )
626                                         argBlockIdx-=2;
627                                 else
628                                         argBlockIdx--;
629
630                                 OP1(op, firstlocal + argBlockIdx);
631                                 /* OP1(op, firstlocal + tmpinlinf->method->paramcount - 1 - i); */
632                                 /* printf("inline argument load operation for local: %ld\n",firstlocal + tmpinlinf->method->paramcount - 1 - i); */
633                         }
634                         skipBasicBlockChange=1;
635 if (DEBUG==true) {
636 printf("BEFORE SAVE: "); fflush(stdout);
637 DEBUGMETH(inline_env->method);
638 }
639                         inlining_save_compiler_variables();
640 if (DEBUG==true) {
641 printf("AFTER SAVE: "); fflush(stdout);
642 DEBUGMETH(inline_env->method);
643 }
644                         inlining_set_compiler_variables(tmpinlinf);
645 if (DEBUG==true) {
646 printf("AFTER SET :: "); fflush(stdout);
647 DEBUGMETH(inline_env->method);
648 }
649                         if (DEBUG) {
650                                 printf("\n.......Parsing (inlined): ");
651                                 DEBUGMETH(m);
652                                 DEBUGMETH(inline_env->method);
653                         }
654
655
656                         OP1(ICMD_INLINE_START,tmpinlinf->level);
657
658                         if (inlinfo->inlinedmethods == NULL) {
659                                 gp = -1;
660                         } else {
661                                 tmpinlinf = list_first(inlinfo->inlinedmethods);
662                                 nextgp = (tmpinlinf != NULL) ? tmpinlinf->startgp : -1;
663                         }
664                         if (inline_env->method->exceptiontablelength > 0) 
665                           nextex = fillextable(m, nextex, 
666                             inline_env->method->exceptiontable, inline_env->method->exceptiontablelength, 
667                             label_index, &b_count, inline_env);
668                         continue;
669                 }
670           
671                 opcode = code_get_u1(p,inline_env->method);            /* fetch op code  */
672          if (DEBUG==true) 
673                 {
674                         printf("Parse p=%i<%i<%i<   opcode=<%i> %s\n",
675                            p, gp, inline_env->jcodelength, opcode, opcode_names[opcode]);
676                         if (label_index)
677                                 printf("label_index[%d]=%d\n",p,label_index[p]);
678                 }
679          /*
680 printf("basicblockindex[gp=%i]=%i=%p ipc=%i=%p shifted ipc=%i=%p\n",
681 gp,m->basicblockindex[gp],m->basicblockindex[gp],ipc,ipc,(ipc<<1),(ipc<<1));
682 fflush(stdout);
683          */
684                 if (!skipBasicBlockChange) {
685                         m->basicblockindex[gp] |= (ipc << 1); /*store intermed cnt*/
686                 } else skipBasicBlockChange=0;
687                 /*
688 printf("basicblockindex[gp=%i]=%i=%p \n",
689 gp,m->basicblockindex[gp],m->basicblockindex[gp]);
690 fflush(stdout);
691                 */
692
693                 if (blockend) {
694                         block_insert(gp);               /* start new block                */
695                         blockend = false;
696                         /*printf("blockend was set: new blockcount: %ld at:%ld\n",b_count,gp);*/
697                 }
698
699                 nextp = p + jcommandsize[opcode];   /* compute next instruction start */
700                 if (nextp > inline_env->method->jcodelength)
701                         panic("Unexpected end of bytecode");
702                 s_count += stackreq[opcode];            /* compute stack element count    */
703 SHOWOPCODE
704                 switch (opcode) {
705                 case JAVA_NOP:
706                         break;
707
708                         /* pushing constants onto the stack p */
709
710                 case JAVA_BIPUSH:
711                         LOADCONST_I(code_get_s1(p+1,inline_env->method));
712                         break;
713
714                 case JAVA_SIPUSH:
715                         LOADCONST_I(code_get_s2(p+1,inline_env->method));
716                         break;
717
718                 case JAVA_LDC1:
719                         i = code_get_u1(p+1,inline_env->method);
720
721                         goto pushconstantitem;
722                 case JAVA_LDC2:
723                 case JAVA_LDC2W:
724                         i = code_get_u2(p + 1,inline_env->method);
725
726                 pushconstantitem:
727
728                         if (i >= inline_env->method->class->cpcount) 
729                                 panic ("Attempt to access constant outside range");
730
731                         switch (inline_env->method->class->cptags[i]) {
732                         case CONSTANT_Integer:
733                                 LOADCONST_I(((constant_integer *) (inline_env->method->class->cpinfos[i]))->value);
734                                 break;
735                         case CONSTANT_Long:
736                                 LOADCONST_L(((constant_long *) (inline_env->method->class->cpinfos[i]))->value);
737                                 break;
738                         case CONSTANT_Float:
739                                 LOADCONST_F(((constant_float *) (inline_env->method->class->cpinfos[i]))->value);
740                                 break;
741                         case CONSTANT_Double:
742                                 LOADCONST_D(((constant_double *) (inline_env->method->class->cpinfos[i]))->value);
743                                 break;
744                         case CONSTANT_String:
745                                 LOADCONST_A(literalstring_new((utf *) (inline_env->method->class->cpinfos[i])));
746                                 break;
747                         default: panic("Invalid constant type to push");
748                         }
749                         break;
750
751                 case JAVA_ACONST_NULL:
752                         LOADCONST_A(NULL);
753                         break;
754
755                 case JAVA_ICONST_M1:
756                 case JAVA_ICONST_0:
757                 case JAVA_ICONST_1:
758                 case JAVA_ICONST_2:
759                 case JAVA_ICONST_3:
760                 case JAVA_ICONST_4:
761                 case JAVA_ICONST_5:
762                         LOADCONST_I(opcode - JAVA_ICONST_0);
763                         break;
764
765                 case JAVA_LCONST_0:
766                 case JAVA_LCONST_1:
767                         LOADCONST_L(opcode - JAVA_LCONST_0);
768                         break;
769
770                 case JAVA_FCONST_0:
771                 case JAVA_FCONST_1:
772                 case JAVA_FCONST_2:
773                         LOADCONST_F(opcode - JAVA_FCONST_0);
774                         break;
775
776                 case JAVA_DCONST_0:
777                 case JAVA_DCONST_1:
778                         LOADCONST_D(opcode - JAVA_DCONST_0);
779                         break;
780
781                         /* loading variables onto the stack */
782
783                 case JAVA_ILOAD:
784                 case JAVA_LLOAD:
785                 case JAVA_FLOAD:
786                 case JAVA_DLOAD:
787                 case JAVA_ALOAD:
788                         if (!iswide) {
789                                 i = code_get_u1(p + 1,inline_env->method);
790                         } else {
791                                 i = code_get_u2(p + 1,inline_env->method);
792                                 nextp = p + 3;
793                                 iswide = false;
794                         }
795                         OP1LOAD(opcode, i + firstlocal);
796                         break;
797
798                 case JAVA_ILOAD_0:
799                 case JAVA_ILOAD_1:
800                 case JAVA_ILOAD_2:
801                 case JAVA_ILOAD_3:
802                         OP1LOAD(ICMD_ILOAD, opcode - JAVA_ILOAD_0 + firstlocal);
803                         break;
804
805                 case JAVA_LLOAD_0:
806                 case JAVA_LLOAD_1:
807                 case JAVA_LLOAD_2:
808                 case JAVA_LLOAD_3:
809                         OP1LOAD(ICMD_LLOAD, opcode - JAVA_LLOAD_0 + firstlocal);
810                         break;
811
812                 case JAVA_FLOAD_0:
813                 case JAVA_FLOAD_1:
814                 case JAVA_FLOAD_2:
815                 case JAVA_FLOAD_3:
816                         OP1LOAD(ICMD_FLOAD, opcode - JAVA_FLOAD_0 + firstlocal);
817                         break;
818
819                 case JAVA_DLOAD_0:
820                 case JAVA_DLOAD_1:
821                 case JAVA_DLOAD_2:
822                 case JAVA_DLOAD_3:
823                         OP1LOAD(ICMD_DLOAD, opcode - JAVA_DLOAD_0 + firstlocal);
824                         break;
825
826                 case JAVA_ALOAD_0:
827                 case JAVA_ALOAD_1:
828                 case JAVA_ALOAD_2:
829                 case JAVA_ALOAD_3:
830                         OP1LOAD(ICMD_ALOAD, opcode - JAVA_ALOAD_0 + firstlocal);
831                         break;
832
833                         /* storing stack values into local variables */
834
835                 case JAVA_ISTORE:
836                 case JAVA_LSTORE:
837                 case JAVA_FSTORE:
838                 case JAVA_DSTORE:
839                 case JAVA_ASTORE:
840                         if (!iswide) {
841                                 i = code_get_u1(p + 1,inline_env->method);
842                         } else {
843                                 i = code_get_u2(p + 1,inline_env->method);
844                                 iswide = false;
845                                 nextp = p + 3;
846                         }
847                         OP1STORE(opcode, i + firstlocal);
848                         break;
849
850                 case JAVA_ISTORE_0:
851                 case JAVA_ISTORE_1:
852                 case JAVA_ISTORE_2:
853                 case JAVA_ISTORE_3:
854                         OP1STORE(ICMD_ISTORE, opcode - JAVA_ISTORE_0 + firstlocal);
855                         break;
856
857                 case JAVA_LSTORE_0:
858                 case JAVA_LSTORE_1:
859                 case JAVA_LSTORE_2:
860                 case JAVA_LSTORE_3:
861                         OP1STORE(ICMD_LSTORE, opcode - JAVA_LSTORE_0 + firstlocal);
862                         break;
863
864                 case JAVA_FSTORE_0:
865                 case JAVA_FSTORE_1:
866                 case JAVA_FSTORE_2:
867                 case JAVA_FSTORE_3:
868                         OP1STORE(ICMD_FSTORE, opcode - JAVA_FSTORE_0 + firstlocal);
869                         break;
870
871                 case JAVA_DSTORE_0:
872                 case JAVA_DSTORE_1:
873                 case JAVA_DSTORE_2:
874                 case JAVA_DSTORE_3:
875                         OP1STORE(ICMD_DSTORE, opcode - JAVA_DSTORE_0 + firstlocal);
876                         break;
877
878                 case JAVA_ASTORE_0:
879                 case JAVA_ASTORE_1:
880                 case JAVA_ASTORE_2:
881                 case JAVA_ASTORE_3:
882                         OP1STORE(ICMD_ASTORE, opcode - JAVA_ASTORE_0 + firstlocal);
883                         break;
884
885                 case JAVA_IINC:
886                         {
887                                 int v;
888                                 
889                                 if (!iswide) {
890                                         i = code_get_u1(p + 1,inline_env->method);
891                                         v = code_get_s1(p + 2,inline_env->method);
892
893                                 } else {
894                                         i = code_get_u2(p + 1,inline_env->method);
895                                         v = code_get_s2(p + 3,inline_env->method);
896                                         iswide = false;
897                                         nextp = p + 5;
898                                 }
899                                 INDEX_ONEWORD(i + firstlocal);
900                                 OP2I(opcode, i + firstlocal, v);
901                         }
902                         break;
903
904                         /* wider index for loading, storing and incrementing */
905
906                 case JAVA_WIDE:
907                         iswide = true;
908                         nextp = p + 1;
909                         break;
910
911                         /* managing arrays ************************************************/
912
913                 case JAVA_NEWARRAY:
914                         OP(ICMD_CHECKASIZE);
915                         switch (code_get_s1(p + 1,inline_env->method)) {
916                         case 4:
917                                 BUILTIN1(BUILTIN_newarray_boolean, TYPE_ADR,currentline);
918                                 break;
919                         case 5:
920                                 BUILTIN1(BUILTIN_newarray_char, TYPE_ADR,currentline);
921                                 break;
922                         case 6:
923                                 BUILTIN1(BUILTIN_newarray_float, TYPE_ADR,currentline);
924                                 break;
925                         case 7:
926                                 BUILTIN1(BUILTIN_newarray_double, TYPE_ADR,currentline);
927                                 break;
928                         case 8:
929                                 BUILTIN1(BUILTIN_newarray_byte, TYPE_ADR,currentline);
930                                 break;
931                         case 9:
932                                 BUILTIN1(BUILTIN_newarray_short, TYPE_ADR,currentline);
933                                 break;
934                         case 10:
935                                 BUILTIN1(BUILTIN_newarray_int, TYPE_ADR,currentline);
936                                 break;
937                         case 11:
938                                 BUILTIN1(BUILTIN_newarray_long, TYPE_ADR,currentline);
939                                 break;
940                         default: panic("Invalid array-type to create");
941                         }
942                         OP(ICMD_CHECKEXCEPTION);
943                         break;
944
945                 case JAVA_ANEWARRAY:
946                         OP(ICMD_CHECKASIZE);
947                         i = code_get_u2(p + 1,inline_env->method);
948                         {
949                                 classinfo *component =
950                                         (classinfo *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
951
952                                 if (!class_load(component))
953                                         return NULL;
954
955                                 if (!class_link(component))
956                                         return NULL;
957
958                                 LOADCONST_A_BUILTIN(class_array_of(component)->vftbl);
959 /*                              LOADCONST_A_BUILTIN(component); */
960                                 s_count++;
961                                 BUILTIN2(BUILTIN_newarray, TYPE_ADR, currentline);
962                         }
963                         OP(ICMD_CHECKEXCEPTION);
964                         break;
965
966                 case JAVA_MULTIANEWARRAY:
967                         inline_env->method->isleafmethod = false;
968                         i = code_get_u2(p + 1,inline_env->method);
969                         {
970                                 vftbl_t *arrayvftbl;
971                                 s4 v = code_get_u1(p + 3,inline_env->method);
972
973                                 
974 /*                              vftbl *arrayvftbl = */
975 /*                                      ((classinfo *) class_getconstant(class, i, CONSTANT_Class))->vftbl; */
976 /*                              OP2A(opcode, v, arrayvftbl,currentline); */
977
978                                 
979                                 classinfo *component =
980                                         (classinfo *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
981
982                                 if (!class_load(component))
983                                         return NULL;
984
985                                 if (!class_link(component))
986                                         return NULL;
987
988                                 arrayvftbl = component->vftbl;
989                                 OP2A(opcode, v, arrayvftbl, currentline);
990
991 /*                              classinfo *arrayclass = */
992 /*                                      (classinfo *) class_getconstant(class, i, CONSTANT_Class); */
993 /*                              OP2A(opcode, v, arrayclass, currentline); */
994                         }
995                         break;
996
997                 case JAVA_IFEQ:
998                 case JAVA_IFLT:
999                 case JAVA_IFLE:
1000                 case JAVA_IFNE:
1001                 case JAVA_IFGT:
1002                 case JAVA_IFGE:
1003                 case JAVA_IFNULL:
1004                 case JAVA_IFNONNULL:
1005                 case JAVA_IF_ICMPEQ:
1006                 case JAVA_IF_ICMPNE:
1007                 case JAVA_IF_ICMPLT:
1008                 case JAVA_IF_ICMPGT:
1009                 case JAVA_IF_ICMPLE:
1010                 case JAVA_IF_ICMPGE:
1011                 case JAVA_IF_ACMPEQ:
1012                 case JAVA_IF_ACMPNE:
1013                 case JAVA_GOTO:
1014                 case JAVA_JSR:
1015                         i = p + code_get_s2(p + 1,inline_env->method);
1016                         if (useinlining) { 
1017                                 debug_writebranch;
1018                                 i = label_index[i];
1019                         }
1020                         bound_check(i);
1021                         block_insert(i);
1022                         blockend = true;
1023                         OP1(opcode, i);
1024                         break;
1025                 case JAVA_GOTO_W:
1026                 case JAVA_JSR_W:
1027                         i = p + code_get_s4(p + 1,inline_env->method);
1028                         if (useinlining) { 
1029                                 debug_writebranch;
1030                                 i = label_index[i];
1031                         }
1032                         bound_check(i);
1033                         /*printf("B6 JSR_W\t"); fflush(stdout);*/
1034                         block_insert(i);
1035                         blockend = true;
1036                         OP1(opcode, i);
1037                         break;
1038
1039                 case JAVA_RET:
1040                         if (!iswide) {
1041                                 i = code_get_u1(p + 1,inline_env->method);
1042                         } else {
1043                                 i = code_get_u2(p + 1,inline_env->method);
1044                                 nextp = p + 3;
1045                                 iswide = false;
1046                         }
1047                         blockend = true;
1048                                 
1049                         /*
1050                           if (inline_env->isinlinedmethod) {
1051                           OP1(ICMD_GOTO, inlinfo->stopgp);
1052                           break;
1053                           }*/
1054
1055                         OP1LOAD(opcode, i + firstlocal);
1056                         break;
1057
1058                 case JAVA_IRETURN:
1059                 case JAVA_LRETURN:
1060                 case JAVA_FRETURN:
1061                 case JAVA_DRETURN:
1062                 case JAVA_ARETURN:
1063                 case JAVA_RETURN:
1064                         if (inline_env->isinlinedmethod) {
1065                                 /*                                      if (p==m->jcodelength-1) {*/ /* return is at end of inlined method */
1066                                 /*                                              OP(ICMD_NOP); */
1067                                 /*                                              break; */
1068                                 /*                                      } */
1069                                 if (nextp>inline_env->method->jcodelength-1) {
1070                                         /* OP1(ICMD_GOTO, inlinfo->stopgp);
1071                                            OP(ICMD_NOP);
1072                                            OP(ICMD_NOP);
1073                                         */
1074                                         blockend=true;
1075                                         break;
1076                                 } /* JJJJJJJ */
1077                                 blockend = true;
1078                                 OP1(ICMD_GOTO, inlinfo->stopgp);
1079                                 break;
1080                         }
1081
1082                         blockend = true;
1083                         OP(opcode);
1084                         break;
1085
1086                 case JAVA_ATHROW:
1087                         blockend = true;
1088                         OP(opcode);
1089                         break;
1090                                 
1091
1092                         /* table jumps ********************************/
1093
1094                 case JAVA_LOOKUPSWITCH:
1095                         {
1096                                 s4 num, j;
1097                                 s4 *tablep;
1098                                 s4 prevvalue;
1099
1100                                 blockend = true;
1101                                 nextp = ALIGN((p + 1), 4);
1102                                 if (nextp + 8 > inline_env->method->jcodelength)
1103                                         panic("Unexpected end of bytecode");
1104                                 if (!useinlining) {
1105                                         tablep = (s4 *) (inline_env->method->jcode + nextp);
1106
1107                                 } else {
1108                                         num = code_get_u4(nextp + 4,inline_env->method);
1109                                         tablep = DMNEW(s4, num * 2 + 2);
1110                                 }
1111
1112                                 OP2A(opcode, 0, tablep,currentline);
1113
1114                                 /* default target */
1115
1116                                 j =  p + code_get_s4(nextp,inline_env->method);
1117                                 if (useinlining) 
1118                                         j = label_index[j];
1119                                 *tablep = j;     /* restore for little endian */
1120                                 tablep++;
1121                                 nextp += 4;
1122                                 bound_check(j);
1123                                 block_insert(j);
1124
1125                                 /* number of pairs */
1126
1127                                 num = code_get_u4(nextp,inline_env->method);
1128                                 *tablep = num;
1129                                 tablep++;
1130                                 nextp += 4;
1131
1132                                 if (nextp + 8*(num) > inline_env->method->jcodelength)
1133                                         panic("Unexpected end of bytecode");
1134
1135                                 for (i = 0; i < num; i++) {
1136                                         /* value */
1137
1138                                         j = code_get_s4(nextp,inline_env->method);
1139                                         *tablep = j; /* restore for little endian */
1140                                         tablep++;
1141                                         nextp += 4;
1142
1143                                         /* check if the lookup table is sorted correctly */
1144                                         
1145                                         if (i && (j <= prevvalue))
1146                                                 panic("invalid LOOKUPSWITCH: table not sorted");
1147                                         prevvalue = j;
1148
1149                                         /* target */
1150
1151                                         j = p + code_get_s4(nextp,inline_env->method);
1152                                         if (useinlining)
1153                                                 j = label_index[j];
1154                                         *tablep = j; /* restore for little endian */
1155                                         tablep++;
1156                                         nextp += 4;
1157                                         bound_check(j);
1158                                         block_insert(j);
1159                                 }
1160
1161                                 break;
1162                         }
1163
1164
1165                 case JAVA_TABLESWITCH:
1166                         {
1167                                 s4 num, j;
1168                                 s4 *tablep;
1169
1170                                 blockend = true;
1171                                 nextp = ALIGN((p + 1), 4);
1172                                 if (nextp + 12 > inline_env->method->jcodelength)
1173                                         panic("Unexpected end of bytecode");
1174                                 if (!useinlining) {
1175                                         tablep = (s4 *) (inline_env->method->jcode + nextp);
1176
1177                                 } else {
1178                                         num = code_get_u4(nextp + 8,inline_env->method) - code_get_u4(nextp + 4,inline_env->method);
1179                                         tablep = DMNEW(s4, num + 1 + 3);
1180                                 }
1181
1182                                 OP2A(opcode, 0, tablep,currentline);
1183
1184                                 /* default target */
1185
1186                                 j = p + code_get_s4(nextp,inline_env->method);
1187                                 if (useinlining)
1188                                         j = label_index[j];
1189                                 *tablep = j;     /* restore for little endian */
1190                                 tablep++;
1191                                 nextp += 4;
1192                                 bound_check(j);
1193                                 block_insert(j);
1194
1195                                 /* lower bound */
1196
1197                                 j = code_get_s4(nextp,inline_env->method);
1198                                 *tablep = j;     /* restore for little endian */
1199                                 tablep++;
1200                                 nextp += 4;
1201
1202                                 /* upper bound */
1203
1204                                 num = code_get_s4(nextp,inline_env->method);
1205                                 *tablep = num;   /* restore for little endian */
1206                                 tablep++;
1207                                 nextp += 4;
1208
1209                                 num -= j;  /* difference of upper - lower */
1210                                 if (num < 0)
1211                                         panic("invalid TABLESWITCH: upper bound < lower bound");
1212
1213                                 if (nextp + 4*(num+1) > inline_env->method->jcodelength)
1214                                         panic("Unexpected end of bytecode");
1215
1216                                 for (i = 0; i <= num; i++) {
1217                                         j = p + code_get_s4(nextp,inline_env->method);
1218                                         if (useinlining) {
1219                                                 /*printf("TABLESWITCH: j before mapping=%ld\n",j);*/
1220                                                 j = label_index[j];
1221                                         }
1222                                         *tablep = j; /* restore for little endian */
1223                                         tablep++;
1224                                         nextp += 4;
1225                                         bound_check(j);
1226                                         block_insert(j);
1227                                         /*printf("TABLESWITCH: block_insert(%ld)\n",j);*/
1228                                 }
1229
1230                                 break;
1231                         }
1232
1233
1234                         /* load and store of object fields *******************/
1235
1236                 case JAVA_AASTORE:
1237                         BUILTIN3(BUILTIN_aastore, TYPE_VOID, currentline);
1238                         break;
1239
1240                 case JAVA_PUTSTATIC:
1241                 case JAVA_GETSTATIC:
1242                         i = code_get_u2(p + 1,inline_env->method);
1243                         {
1244                                 constant_FMIref *fr;
1245                                 fieldinfo *fi;
1246
1247                                 fr = class_getconstant(inline_env->method->class, i, CONSTANT_Fieldref);
1248
1249                                 if (!class_load(fr->class))
1250                                         return NULL;
1251
1252                                 if (!class_link(fr->class))
1253                                         return NULL;
1254
1255                                 fi = class_resolvefield(fr->class,
1256                                                                                 fr->name,
1257                                                                                 fr->descriptor,
1258                                                                                 inline_env->method->class,
1259                                                                                 true);
1260
1261                                 if (!fi)
1262                                         return NULL;
1263
1264                                 OP2A(opcode, fi->type, fi, currentline);
1265                                 if (!fi->class->initialized) {
1266                                         inline_env->method->isleafmethod = false;
1267                                 }
1268                         }
1269                         break;
1270
1271                 case JAVA_PUTFIELD:
1272                 case JAVA_GETFIELD:
1273                         i = code_get_u2(p + 1,inline_env->method);
1274                         {
1275                                 constant_FMIref *fr;
1276                                 fieldinfo *fi;
1277
1278                                 fr = class_getconstant(inline_env->method->class, i, CONSTANT_Fieldref);
1279
1280                                 if (!class_load(fr->class))
1281                                         return NULL;
1282
1283                                 if (!class_link(fr->class))
1284                                         return NULL;
1285
1286                                 fi = class_resolvefield(fr->class,
1287                                                                                 fr->name,
1288                                                                                 fr->descriptor,
1289                                                                                 inline_env->method->class,
1290                                                                                 true);
1291
1292                                 if (!fi)
1293                                         return NULL;
1294
1295                                 OP2A(opcode, fi->type, fi, currentline);
1296                         }
1297                         break;
1298
1299
1300                         /* method invocation *****/
1301
1302                 case JAVA_INVOKESTATIC:
1303                         i = code_get_u2(p + 1,inline_env->method);
1304                         {
1305                                 constant_FMIref *mr;
1306                                 methodinfo *mi;
1307                                 
1308                                 inline_env->method->isleafmethod = false;
1309
1310                                 mr = class_getconstant(inline_env->method->class, i, CONSTANT_Methodref);
1311
1312                                 if (!class_load(mr->class))
1313                                         return NULL;
1314
1315                                 if (!class_link(mr->class))
1316                                         return NULL;
1317
1318                                 mi = class_resolveclassmethod(mr->class,
1319                                                                                           mr->name,
1320                                                                                           mr->descriptor,
1321                                                                                           inline_env->method->class,
1322                                                                                           true);
1323
1324                                 if (!mi)
1325                                         return NULL;
1326
1327 if (DEBUG4==true) { 
1328         method_display_w_class(mi); 
1329         printf("\tINVOKE STATIC\n");
1330         fflush(stdout);}
1331
1332                                 if (!(mi->flags & ACC_STATIC)) {
1333                                         *exceptionptr =
1334                                                 new_exception(string_java_lang_IncompatibleClassChangeError);
1335                                         return NULL;
1336                                 }
1337
1338                                 descriptor2types(mi);
1339                                 OP2A(opcode, mi->paramcount, mi, currentline);
1340                         }
1341                         break;
1342
1343                 case JAVA_INVOKESPECIAL:
1344                 case JAVA_INVOKEVIRTUAL:
1345                         i = code_get_u2(p + 1,inline_env->method);
1346                         {
1347                                 constant_FMIref *mr;
1348                                 methodinfo *mi;
1349
1350                                 inline_env->method->isleafmethod = false;
1351
1352                                 mr = class_getconstant(inline_env->method->class, i, CONSTANT_Methodref);
1353
1354                                 if (!class_load(mr->class))
1355                                         return NULL;
1356
1357                                 if (!class_link(mr->class))
1358                                         return NULL;
1359
1360                                 mi = class_resolveclassmethod(mr->class,
1361                                                                                           mr->name,
1362                                                                                           mr->descriptor,
1363                                                                                           inline_env->method->class,
1364                                                                                           true);
1365
1366                                 if (!mi)
1367                                         return NULL;
1368
1369 if (DEBUG4==true) { 
1370         method_display_w_class(mi); 
1371         printf("\tINVOKE SPEC/VIRT\n");
1372         fflush(stdout);}
1373
1374                                 if (mi->flags & ACC_STATIC) {
1375                                         *exceptionptr =
1376                                                 new_exception(string_java_lang_IncompatibleClassChangeError);
1377                                         return NULL;
1378                                 }
1379
1380                                 descriptor2types(mi);
1381                                 OP2A(opcode, mi->paramcount, mi, currentline);
1382                         }
1383                         break;
1384
1385                 case JAVA_INVOKEINTERFACE:
1386                         i = code_get_u2(p + 1,inline_env->method);
1387                         {
1388                                 constant_FMIref *mr;
1389                                 methodinfo *mi;
1390                                 
1391                                 inline_env->method->isleafmethod = false;
1392
1393                                 mr = class_getconstant(inline_env->method->class, i, CONSTANT_InterfaceMethodref);
1394
1395                                 if (!class_load(mr->class))
1396                                         return NULL;
1397
1398                                 if (!class_link(mr->class))
1399                                         return NULL;
1400
1401                                 mi = class_resolveinterfacemethod(mr->class,
1402                                                                                                   mr->name,
1403                                                                                                   mr->descriptor,
1404                                                                                                   inline_env->method->class,
1405                                                                                                   true);
1406                                 if (!mi)
1407                                         return NULL;
1408
1409                                 if (mi->flags & ACC_STATIC) {
1410                                         *exceptionptr =
1411                                                 new_exception(string_java_lang_IncompatibleClassChangeError);
1412                                         return NULL;
1413                                 }
1414
1415 if (DEBUG4==true) { 
1416         method_display_w_class(mi); 
1417         printf("\tINVOKE INTERFACE\n");
1418         fflush(stdout);}
1419                                 descriptor2types(mi);
1420                                 OP2A(opcode, mi->paramcount, mi, currentline);
1421                         }
1422                         break;
1423
1424                         /* miscellaneous object operations *******/
1425
1426                 case JAVA_NEW:
1427                         i = code_get_u2(p + 1,inline_env->method);
1428                         LOADCONST_A_BUILTIN(class_getconstant(inline_env->method->class, i, CONSTANT_Class));
1429                         s_count++;
1430                         BUILTIN1(BUILTIN_new, TYPE_ADR, currentline);
1431                         OP(ICMD_CHECKEXCEPTION);
1432                         break;
1433
1434                 case JAVA_CHECKCAST:
1435                         i = code_get_u2(p + 1,inline_env->method);
1436                         {
1437                                 classinfo *cls =
1438                                         (classinfo *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
1439
1440                                 if (!cls->loaded)
1441                                         if (!class_load(cls))
1442                                                 return NULL;
1443
1444                                 if (!cls->linked)
1445                                         if (!class_link(cls))
1446                                                 return NULL;
1447
1448                                 if (cls->vftbl->arraydesc) {
1449                                         /* array type cast-check */
1450                                         LOADCONST_A_BUILTIN(cls->vftbl);
1451                                         s_count++;
1452                                         BUILTIN2(BUILTIN_checkarraycast, TYPE_ADR,currentline);
1453
1454                                 } else { /* object type cast-check */
1455                                         /*
1456                                           +                                               LOADCONST_A_BUILTIN(class_getconstant(class, i, CONSTANT_Class));
1457                                           +                                               s_count++;
1458                                           +                                               BUILTIN2(BUILTIN_checkcast, TYPE_ADR,currentline);
1459                                           +                                             */
1460                                         OP2A(opcode, 1, cls, currentline);
1461                                 }
1462                         }
1463                         break;
1464
1465                 case JAVA_INSTANCEOF:
1466                         i = code_get_u2(p + 1,inline_env->method);
1467                         {
1468                                 classinfo *cls =
1469                                         (classinfo *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
1470
1471                                 if (!cls->loaded)
1472                                         if (!class_load(cls))
1473                                                 return NULL;
1474
1475                                 if (!cls->linked)
1476                                         if (!class_link(cls))
1477                                                 return NULL;
1478
1479                                 if (cls->vftbl->arraydesc) {
1480                                         /* array type cast-check */
1481                                         LOADCONST_A_BUILTIN(cls->vftbl);
1482                                         s_count++;
1483                                         BUILTIN2(BUILTIN_arrayinstanceof, TYPE_INT, currentline);
1484                                 }
1485                                 else { /* object type cast-check */
1486                                         /*
1487                                           LOADCONST_A_BUILTIN(class_getconstant(class, i, CONSTANT_Class));
1488                                           s_count++;
1489                                           BUILTIN2(BUILTIN_instanceof, TYPE_INT,currentline);
1490                                           +                                             */
1491                                         OP2A(opcode, 1, cls, currentline);
1492                                 }
1493                         }
1494                         break;
1495
1496                 case JAVA_MONITORENTER:
1497 #if defined(USE_THREADS)
1498                         if (checksync) {
1499                                 BUILTIN1(BUILTIN_monitorenter, TYPE_VOID,currentline);
1500                         } else
1501 #endif
1502                                 {
1503                                         OP(ICMD_NULLCHECKPOP);
1504                                 }
1505                         break;
1506
1507                 case JAVA_MONITOREXIT:
1508 #if defined(USE_THREADS)
1509                         if (checksync) {
1510                                 BUILTIN1(BUILTIN_monitorexit, TYPE_VOID,currentline);
1511                                 OP(ICMD_CHECKEXCEPTION);
1512                         } else
1513 #endif
1514                                 {
1515                                         OP(ICMD_POP);
1516                                 }
1517                         break;
1518
1519                         /* any other basic operation **************************************/
1520
1521                 case JAVA_IDIV:
1522                         OP(opcode);
1523                         break;
1524
1525                 case JAVA_IREM:
1526                         OP(opcode);
1527                         break;
1528
1529                 case JAVA_LDIV:
1530                         OP(opcode);
1531                         break;
1532
1533                 case JAVA_LREM:
1534                         OP(opcode);
1535                         break;
1536
1537                 case JAVA_FREM:
1538 #if defined(__I386__)
1539                         OP(opcode);
1540 #else
1541                         BUILTIN2(BUILTIN_frem, TYPE_FLOAT,currentline);
1542 #endif
1543                         break;
1544
1545                 case JAVA_DREM:
1546 #if defined(__I386__)
1547                         OP(opcode);
1548 #else
1549                         BUILTIN2(BUILTIN_drem, TYPE_DOUBLE,currentline);
1550 #endif
1551                         break;
1552
1553                 case JAVA_F2I:
1554 #if defined(__ALPHA__)
1555                         if (!opt_noieee) {
1556                                 BUILTIN1(BUILTIN_f2i, TYPE_INT,currentline);
1557                         } else
1558 #endif
1559                                 {
1560                                         OP(opcode);
1561                                 }
1562                         break;
1563
1564                 case JAVA_F2L:
1565 #if defined(__ALPHA__)
1566                         if (!opt_noieee) {
1567                                 BUILTIN1(BUILTIN_f2l, TYPE_LONG,currentline);
1568                         } else 
1569 #endif
1570                                 {
1571                                         OP(opcode);
1572                                 }
1573                         break;
1574
1575                 case JAVA_D2I:
1576 #if defined(__ALPHA__)
1577                         if (!opt_noieee) {
1578                                 BUILTIN1(BUILTIN_d2i, TYPE_INT,currentline);
1579                         } else
1580 #endif
1581                                 {
1582                                         OP(opcode);
1583                                 }
1584                         break;
1585
1586                 case JAVA_D2L:
1587 #if defined(__ALPHA__)
1588                         if (!opt_noieee) {
1589                                 BUILTIN1(BUILTIN_d2l, TYPE_LONG,currentline);
1590                         } else
1591 #endif
1592                                 {
1593                                         OP(opcode);
1594                                 }
1595                         break;
1596
1597                 case JAVA_BREAKPOINT:
1598                         *exceptionptr =
1599                                 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
1600                         return NULL;
1601
1602                 case 204: /* unused opcode */
1603                 case 205:
1604                 case 206:
1605                 case 207:
1606                 case 208:
1607                 case 209:
1608                 case 210:
1609                 case 211:
1610                 case 212:
1611                 case 213:
1612                 case 214:
1613                 case 215:
1614                 case 216:
1615                 case 217:
1616                 case 218:
1617                 case 219:
1618                 case 220:
1619                 case 221:
1620                 case 222:
1621                 case 223:
1622                 case 224:
1623                 case 225:
1624                 case 226:
1625                 case 227:
1626                 case 228:
1627                 case 229:
1628                 case 230:
1629                 case 231:
1630                 case 232:
1631                 case 233:
1632                 case 234:
1633                 case 235:
1634                 case 236:
1635                 case 237:
1636                 case 238:
1637                 case 239:
1638                 case 240:
1639                 case 241:
1640                 case 242:
1641                 case 243:
1642                 case 244:
1643                 case 245:
1644                 case 246:
1645                 case 247:
1646                 case 248:
1647                 case 249:
1648                 case 250:
1649                 case 251:
1650                 case 252:
1651                 case 253:
1652                 case 254:
1653                 case 255:
1654                         printf("Illegal opcode %d at instr %d\n", opcode, ipc);
1655                         panic("Illegal opcode encountered");
1656                         break;
1657
1658                 default:
1659                         OP(opcode);
1660                         break;
1661                                 
1662                 } /* end switch */
1663
1664                 /* If WIDE was used correctly, iswide should have been reset by now. */
1665                 if (iswide && opcode != JAVA_WIDE)
1666                         panic("Illegal instruction: WIDE before incompatible opcode");
1667                 
1668                 /* INLINING */
1669                   
1670                 /* if (inline_env->isinlinedmethod && p == inline_env->method->jcodelength - 1) { */ /* end of an inlined method */
1671                 if (inline_env->isinlinedmethod && (nextp >= inline_env->method->jcodelength) ) { /* end of an inlined method */
1672                         /*                printf("setting gp from %d to %d\n",gp, inlinfo->stopgp); */
1673                         gp = inlinfo->stopgp; 
1674                         inlining_restore_compiler_variables();
1675                         OP(ICMD_INLINE_END);
1676 /*label_index = inlinfo->label_index;*/
1677
1678 if (DEBUG==true) {
1679 printf("AFTER RESTORE : "); fflush(stdout);
1680 DEBUGMETH(inline_env->method);
1681 }
1682                         list_remove(inlinfo->inlinedmethods, list_first(inlinfo->inlinedmethods));
1683                         if (inlinfo->inlinedmethods == NULL) { /* JJJJ */
1684                                 nextgp = -1;
1685                         } else {
1686                                 tmpinlinf = list_first(inlinfo->inlinedmethods);
1687                                 nextgp = (tmpinlinf != NULL) ? tmpinlinf->startgp : -1;
1688                         }
1689                         /*                printf("nextpgp: %d\n", nextgp); */
1690                         label_index=inlinfo->label_index;
1691                         firstlocal = inlinfo->firstlocal;
1692                 }
1693
1694         } /* end for */
1695
1696
1697         if (p != m->jcodelength) {
1698                 printf("p (%d) != m->jcodelength (%d)\n",p,m->jcodelength);
1699                 panic("Command-sequence crosses code-boundary");
1700         }
1701         if (!blockend) {
1702                 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1703                 return NULL;
1704         }
1705
1706         /* adjust block count if target 0 is not first intermediate instruction */
1707
1708         if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
1709                 b_count++;
1710
1711         /* copy local to method variables */
1712
1713         m->instructioncount = ipc;
1714         m->basicblockcount = b_count;
1715         m->stackcount = s_count + m->basicblockcount * m->maxstack;
1716
1717         /* allocate stack table */
1718
1719         m->stack = DMNEW(stackelement, m->stackcount);
1720
1721         {
1722                 basicblock *bptr;
1723
1724                 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1);    /* one more for end ipc */
1725
1726                 b_count = 0;
1727                 m->c_debug_nr = 0;
1728         
1729                 /* additional block if target 0 is not first intermediate instruction */
1730
1731                 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
1732                         bptr->iinstr = m->instructions;
1733                         bptr->mpc = -1;
1734                         bptr->flags = -1;
1735                         bptr->type = BBTYPE_STD;
1736                         bptr->branchrefs = NULL;
1737                         bptr->pre_count = 0;
1738                         bptr->debug_nr = m->c_debug_nr++;
1739                         bptr++;
1740                         b_count++;
1741                         (bptr - 1)->next = bptr;
1742                 }
1743
1744                 /* allocate blocks */
1745
1746                 for (p = 0; p < inline_env->cumjcodelength; p++) { 
1747                 /* for (p = 0; p < m->jcodelength; p++) { */
1748                         if (m->basicblockindex[p] & 1) {
1749                                 /* check if this block starts at the beginning of an instruction */
1750                                 if (!instructionstart[p]) {
1751                                         printf("Basic Block beginn: %d\n",p);
1752                                         panic("Branch into middle of instruction");
1753                                 }
1754                                 /* allocate the block */
1755                                 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
1756                                 bptr->debug_nr = m->c_debug_nr++;
1757                                 if (b_count != 0)
1758                                         (bptr - 1)->icount = bptr->iinstr - (bptr - 1)->iinstr;
1759                                 bptr->mpc = -1;
1760                                 bptr->flags = -1;
1761                                 bptr->lflags = 0;
1762                                 bptr->type = BBTYPE_STD;
1763                                 bptr->branchrefs = NULL;
1764                                 m->basicblockindex[p] = b_count;
1765                                 bptr->pre_count = 0;
1766                                 bptr++;
1767                                 b_count++;
1768                                 (bptr - 1)->next = bptr;
1769                         }
1770                 }
1771
1772                 /* allocate additional block at end */
1773
1774                 bptr->instack = bptr->outstack = NULL;
1775                 bptr->indepth = bptr->outdepth = 0;
1776                 bptr->iinstr = NULL;
1777                 (bptr - 1)->icount = (m->instructions + m->instructioncount) - (bptr - 1)->iinstr;
1778                 bptr->icount = 0;
1779                 bptr->mpc = -1;
1780                 bptr->flags = -1;
1781                 bptr->lflags = 0;
1782                 bptr->type = BBTYPE_STD;
1783                 bptr->branchrefs = NULL;
1784                 bptr->pre_count = 0;
1785                 bptr->debug_nr = m->c_debug_nr++;
1786                 (bptr - 1)->next = bptr;
1787                 bptr->next = NULL;
1788
1789                 if (cd->exceptiontablelength > 0) {
1790                         cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1791                 }
1792                 
1793                 for (i = 0; i < cd->exceptiontablelength; ++i) {
1794                         p = cd->exceptiontable[i].startpc;
1795                         cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1796
1797                         p = cd->exceptiontable[i].endpc;
1798                         cd->exceptiontable[i].end = (p == inline_env->method->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1799
1800                         p = cd->exceptiontable[i].handlerpc;
1801                         cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1802             }
1803         }
1804         
1805         if (useinlining) inlining_cleanup(inline_env);
1806
1807         /* just return methodinfo* to signal everything was ok */
1808
1809         return m;
1810 }
1811
1812
1813 /*
1814  * These are local overrides for various environment variables in Emacs.
1815  * Please do not remove this and leave it at the end of the file, where
1816  * Emacs will automagically detect them.
1817  * ---------------------------------------------------------------------
1818  * Local variables:
1819  * mode: c
1820  * indent-tabs-mode: t
1821  * c-basic-offset: 4
1822  * tab-width: 4
1823  * End:
1824  */