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