inlining of parameters fixed
[cacao.git] / src / vm / jit / inline / inline.c
1 /* jit/inline.c - code inliner
2
3 globals moved to structure and passed as parameter
4
5    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
6    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
7    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
8    Institut f. Computersprachen - TU Wien
9
10    This file is part of CACAO.
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2, or (at
15    your option) any later version.
16
17    This program is distributed in the hope that it will be useful, but
18    WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25    02111-1307, USA.
26
27    Contact: cacao@complang.tuwien.ac.at
28
29    Authors: Dieter Thuernbeck
30
31    $Id: inline.c 1750 2004-12-10 23:21:03Z carolyn $
32
33 */
34
35 /*---
36 Inlining initializes an inline structure with values of the method called
37 with. Then it recursively to MAXDEPTH analyzes by parsing the bytecode 
38 looking for methods that meet the critera to be inlined.
39
40 Critera for inlining currently is:
41 Method to be inlined must:
42 - be less than MAXCODESIZE 
43 - only MAXMETHODS can be inlined in 1 method
44
45 -in only STATIC, FINAL, PRIVATE methods can be inlined from method's class
46 -ino (include outsiders) all STATIC, FINAL, PRIVATE methods can be inlined
47         note: PRIVATE is always only in the same class
48 -inv include virtual methods which static analysis (currently only RTA)
49      to only have 1 definition used (INVOKEVIRTUAL/INVOKEINTERFACE)
50      Currently dynamic loading is handled by rerunning with info 
51         (see parseRT). Guards need to be added.
52 -inp  inline parameters - Parameters are analysed if they are
53         readonly, which is used during parsing to generate ICMD_CLEAR_ARGREN
54         and ICMD_CLEAR_ARGREN is in turn used during stack analysis to
55         replace the ISTORE with a NOP so the same local variable is used.
56         Parameters are pushed on the stack, same as normal method 
57         invocation when popped the local variable of calling program is used.
58 -ine  JOWENN <- please add
59 ---*/
60
61 #include <stdio.h>
62 #include <string.h>
63
64 #include "mm/memory.h"
65 #include "toolbox/logging.h"
66 #include "vm/global.h"
67 #include "vm/loader.h"
68 #include "vm/tables.h"
69 #include "vm/options.h"
70 #include "vm/jit/jit.h"
71 #include "vm/jit/parse.h"
72 #include "vm/jit/inline/inline.h"
73 #include "vm/jit/inline/sets.h"
74
75 #undef  INVIRTDEBUG  /* prints if a method was found to be 
76                          a unique virt/interface method  definition */
77 #undef DEBUGi 
78
79 #define METHINFOj(mm) \
80     { \
81         printf("<j%i/l%i/s%i/(p)%i>\t", \
82                 (mm)->jcodelength,(mm)->maxlocals, \
83                 (mm)->maxstack, (mm)->paramcount);  \
84         method_display_w_class(mm); }
85
86 #define METHINFOx(mm) \
87     { \
88         printf("<c%i/m%i/p%i>\t", \
89                 (mm)->class->classUsed,(mm)->methodUsed, (mm)->monoPoly); \
90         method_display_w_class(mm); }
91
92 #define METHINFO(m) \
93   method_display_w_class(m); 
94
95 #define IMETHINFO(m) \
96   utf_display(m->class->name); printf("."); fflush(stdout); \
97   method_display(m); fflush(stdout); \
98   printf("\tm->jcodelength=%i; ",m->jcodelength); fflush(stdout); \
99   printf("m->jcode=%p;\n",m->jcode); fflush(stdout); \
100   printf("\tm->maxlocals=%i; ",m->maxlocals); fflush(stdout); \
101   printf("m->maxstack=%i;\n",m->maxstack); fflush(stdout);
102
103 /* checked functions and macros: LOADCONST code_get OP1 BUILTIN block_insert bound_check ALIGN */
104
105 /* replace jcodelength loops with correct number after main for loop in parse()! */
106
107 #define CLASSINFO(cls) \
108         {       printf("<c%i>\t",cls->classUsed); \
109                 utf_display(cls->name); printf("\n");fflush(stdout);}
110
111 /*-----------------------------------------------------------*/
112 /* just initialize global structure for non-inlining         */
113 /*-----------------------------------------------------------*/
114
115 void inlining_init0(methodinfo *m, t_inlining_globals *inline_env)
116 {
117         /* initialization for normal use in parse */
118         inlining_set_compiler_variables_fun(m, inline_env);
119         inline_env->isinlinedmethod = 0;
120         inline_env->cumjcodelength = m->jcodelength; /* for not inlining */
121
122         inline_env->cummaxstack = m->maxstack; 
123         inline_env->cumextablelength = 0;
124         inline_env->cumlocals = m->maxlocals;
125         inline_env->cummethods = 0; /* co not global or static-used only here? */
126         inline_env->inlining_stack = NULL;
127         inline_env->inlining_rootinfo = NULL;
128 }
129
130
131 /*-----------------------------------------------------------*/
132
133 void inlining_setup(methodinfo *m, t_inlining_globals *inline_env)
134 {
135 /*      t_inlining_globals *inline_env = DNEW(t_inlining_globals); */
136         inlining_init0(m,inline_env);
137
138 /* define in options.h; Used in main.c, jit.c & inline.c */
139 #ifdef INAFTERMAIN
140 if ((utf_new_char("main") == m->name) && (useinliningm)) {
141         useinlining = true;
142         }
143 #endif
144
145 if (useinlining)
146         {
147                 #ifdef DEBUGi
148                 printf("\n-------- Inlining init for: "); fflush(stdout);
149                 IMETHINFO(m)
150                 #endif
151                 
152         inline_env->cumjcodelength = 0;
153         inline_env->inlining_stack = NEW(list);
154         list_init(inline_env->inlining_stack, 
155                   OFFSET(t_inlining_stacknode, linkage));
156         /*------ analyze ------*/
157         inline_env->inlining_rootinfo 
158                 = inlining_analyse_method(m, 0, 0, 0, 0, inline_env);
159                 #ifdef DEBUGi
160                         printf ("\n------------------------------ ");fflush(stdout);
161                         printf ("\nComplete Result of inlining analysis of:");
162                         fflush(stdout);
163                         METHINFOj(m)
164                         print_t_inlining_globals(inline_env); /* init ok */
165                 #endif
166         /*---------------------*/
167 /*
168  if (inline_env->cummethods == 0) {
169          inline_env = DNEW(t_inlining_globals);
170          inlining_init0(m,inline_env);
171          return inline_env;
172  }
173 */
174 #if 0
175                 #ifdef DEBUGi
176   printf("(l,s) (%i,%i) was (%i,%i)\n",
177     m->maxlocals, inline_env->cumlocals,
178     m->maxstack,  inline_env->cummaxstack); fflush(stdout);
179                 #endif
180 /*This looks wrong*/
181 /* OK since other changes were also made, but in parse same stmt still */
182         m->maxlocals = inline_env->cumlocals;   orig not used
183         m->maxstack = inline_env->cummaxstack;  orig global maxstack var!!
184 #endif
185         }
186 }
187
188
189 void inlining_cleanup(t_inlining_globals *inline_env)
190 {
191         FREE(inline_env->inlining_stack, t_inlining_stacknode);
192 }
193
194
195 /*--2 push the compile variables to save the method's environment --*/
196
197 void inlining_push_compiler_variablesT(int opcode, inlining_methodinfo *inlinfo, t_inlining_globals *inline_env)
198 {
199         t_inlining_stacknode *new = NEW(t_inlining_stacknode);
200
201         /**new->opcode = opcode; **/
202         new->method = inline_env->method;
203         new->inlinfo = inlinfo;
204         list_addfirst(inline_env->inlining_stack, new);
205         inline_env->isinlinedmethod++;
206 }
207 /*-- push the compile variables to save the method's environment --*/
208
209 void inlining_push_compiler_variables(int i, int p, int nextp, int opcode,  u2 lineindex,u2 currentline,u2 linepcchange,inlining_methodinfo *inlinfo, t_inlining_globals *inline_env)
210 {
211         t_inlining_stacknode *new = NEW(t_inlining_stacknode);
212
213         new->i = i;
214         new->p = p;
215         new->nextp = nextp;
216         new->opcode = opcode;
217         new->method = inline_env->method;
218         new->lineindex=lineindex;
219         new->currentline=currentline;
220         new->linepcchange=linepcchange;
221         new->inlinfo = inlinfo;
222         list_addfirst(inline_env->inlining_stack, new);
223         inline_env->isinlinedmethod++;
224 }
225
226
227 void inlining_pop_compiler_variables(
228                                     int *i, int *p, int *nextp,
229                                     int *opcode, u2 *lineindex,
230                                     u2 *currentline,u2 *linepcchange,
231                                     inlining_methodinfo **inlinfo,
232                                     t_inlining_globals *inline_env)
233 {
234         t_inlining_stacknode *tmp 
235           = (t_inlining_stacknode *) list_first(inline_env->inlining_stack);
236
237         if (!inline_env->isinlinedmethod) panic("Attempting to pop from inlining stack in toplevel method!\n");
238
239         *i = tmp->i;
240         *p = tmp->p;
241         *nextp = tmp->nextp;
242         *opcode = tmp->opcode;
243
244         *lineindex=tmp->lineindex;
245         *currentline=tmp->currentline;
246         *currentline=tmp->linepcchange;
247
248         *inlinfo = tmp->inlinfo;
249
250         inline_env->method = tmp->method; /*co*/
251         inline_env->class = inline_env->method->class; /*co*/
252         inline_env->jcodelength = inline_env->method->jcodelength; /*co*/
253         inline_env->jcode = inline_env->method->jcode; /*co*/
254
255         list_remove(inline_env->inlining_stack, tmp);
256         FREE(tmp, t_inlining_stacknode);
257         inline_env->isinlinedmethod--;
258 }
259
260
261 void inlining_set_compiler_variables_fun(methodinfo *m,
262                                          t_inlining_globals *inline_env)
263 {
264         inline_env->method = m; 
265         inline_env->class  = m->class; 
266         inline_env->jcode  = m->jcode; 
267         inline_env->jcodelength = m->jcodelength; 
268 }
269
270 /* is_unique_method2 - determines if m is a unique method by looking
271         in subclasses of class that define method m 
272         It counts as it goes. It also saves the method name if found.
273
274  returns count of # methods used up to 2
275                                 (since if 2 used then not unique.)
276                        sets mout to method found 
277                                 (unique in class' heirarchy)
278                        It looks for subclasses with method def'd.
279  Input:
280  * class - where looking for method
281  * m     - original method ptr
282  * mout  - unique method (output) 
283  Output: "cnt" of methods found up to max of 2 (then not unique)
284 */
285
286 int is_unique_method2(classinfo *class, methodinfo *m, methodinfo **mout)
287 {
288 utf* name = m->name;
289 utf* desc = m->descriptor;
290
291 int cnt = 0;  /* number of times method found in USED classes in hierarchy*/
292 classinfo *subs1;          
293
294 if ((m->class == class) && (class->classUsed == USED)) {
295         /* found method in current class, which is used */
296         if (*mout != m) {
297                 cnt++;
298                 *mout = m;
299                 }
300         }
301
302 if ( ((m->flags & ACC_FINAL)  
303 ||    (class->sub == NULL))
304 && (class->classUsed == USED)) {
305         /* if final search no further */
306         if (*mout != m) {
307                 cnt++;
308                 *mout = m;
309                 }
310          return cnt;
311         }
312
313 /* search for the method in its subclasses */
314 for (subs1 = class->sub;subs1 != NULL;subs1 = subs1->nextsub) {
315         methodinfo * sm;
316         classinfo *subs = subs1;           
317         sm = class_resolveclassmethod(subs,name,desc,class,false);
318         if (sm != NULL) {
319                 if ((subs->classUsed == USED) && 
320                     (*mout != sm)) {
321                         *mout = sm;
322                         cnt++;
323                         }
324                 cnt = cnt + is_unique_method2(subs, sm, mout);
325                 /* Not unique if more than 1 def of method in class heir */
326                 if (cnt > 1)
327                         {return cnt;}
328                 }
329
330         }
331 return cnt;
332 }
333
334 /*-----------------------------------------------------------*/
335
336 bool is_unique_interface_method (methodinfo *mi, methodinfo **mout) {
337
338 utf* name = mi->name;
339 utf* desc = mi->descriptor;
340         
341         classSetNode *classImplNode;
342         int icnt = 0;
343
344         for (classImplNode  = mi->class->impldBy;
345              classImplNode != NULL;                     
346              classImplNode  = classImplNode->nextClass) {
347
348                 classinfo * classImplements = classImplNode->classType;
349                 methodinfo *submeth;
350
351                 submeth = class_findmethod(classImplements,name, desc); 
352                 if (submeth != NULL) {
353                         icnt =+ is_unique_method2(
354                                     classImplements,
355                                     submeth,
356                                     mout);
357                         }       
358                 if (icnt > 1) return false;
359                 } /* end for*/
360 if (icnt == 1) return true;
361 else return false;
362
363
364 /*-----------------------------------------------------------*/
365
366 inlining_methodinfo *inlining_analyse_method(methodinfo *m, 
367                                           int level, int gp, 
368                                           int firstlocal, int maxstackdepth,
369                                           t_inlining_globals *inline_env)
370 {
371         inlining_methodinfo *newnode = DNEW(inlining_methodinfo);
372         /*u1 *jcode = m->jcode;*/
373         int jcodelength = m->jcodelength;
374         int p;
375         int nextp;
376         int opcode;
377         int i=0;
378         bool iswide = false, oldiswide;
379         bool *readonly = NULL;
380         int  *label_index = NULL;
381         bool isnotrootlevel = (level > 0);
382         bool isnotleaflevel = (level < INLINING_MAXDEPTH);
383         #ifdef DEBUGi
384                 printf ("\n------------------------------ ");fflush(stdout);
385                 printf ("\nStart of inlining analysis of: ");fflush(stdout);
386                 METHINFOj(m)
387                 if (isnotrootlevel) printf(" isnotrootlevel=T ");
388                 else printf(" isnotrootlevel=F ");
389                 print_t_inlining_globals(inline_env); /* init ok */
390         #endif
391         #undef DEBUGi
392
393         /* if (level == 0) gp = 0; */
394
395         if (isnotrootlevel) {
396                 newnode->readonly = readonly = DMNEW(bool, m->maxlocals); /* FIXME only paramcount entrys necessary - ok FIXED also turned on*/
397
398                 /** for (i = 0; i < m->maxlocals; readonly[i++] = true); **/
399                 for (i = 0; i < m->paramcount; readonly[i++] = true);
400                 /***isnotrootlevel = true; This had turned -inp off **/
401
402         } else {
403                 readonly = NULL;
404         }
405         
406         label_index = DMNEW(int, jcodelength+200);
407
408         newnode->inlinedmethods = DNEW(list);
409         list_init(newnode->inlinedmethods, OFFSET(inlining_methodinfo, linkage));
410
411         newnode->method = m;
412         newnode->level = level;
413         newnode->startgp = gp;
414         newnode->readonly = readonly;
415         newnode->label_index = label_index;
416         newnode->firstlocal = firstlocal;
417         inline_env->cumjcodelength += jcodelength + m->paramcount + 1 + 5;
418
419         if ((firstlocal + m->maxlocals) > inline_env->cumlocals) {
420                 inline_env->cumlocals = firstlocal + m->maxlocals;
421         }
422
423         if ((maxstackdepth + m->maxstack) > inline_env->cummaxstack) {
424                 inline_env->cummaxstack = maxstackdepth + m->maxstack;
425         }
426
427         inline_env->cumextablelength += m->exceptiontablelength;
428    
429
430         for (p = 0; p < jcodelength; gp += (nextp - p), p = nextp) {
431                 opcode = code_get_u1 (p,m);
432                 nextp = p + jcommandsize[opcode];
433                 oldiswide = iswide;
434
435                 /* figure out nextp */
436
437                 switch (opcode) {
438                 case JAVA_ILOAD:
439                 case JAVA_LLOAD:
440                 case JAVA_FLOAD:
441                 case JAVA_DLOAD:
442                 case JAVA_ALOAD: 
443
444                 case JAVA_ISTORE:
445                 case JAVA_LSTORE:
446                 case JAVA_FSTORE:
447                 case JAVA_DSTORE:
448                 case JAVA_ASTORE: 
449
450                 case JAVA_RET:
451                         if (iswide) {
452                                 nextp = p + 3;
453                                 iswide = false;
454                         }
455                         break;
456
457                 case JAVA_IINC:
458                         if (iswide) {
459                                 nextp = p + 5;
460                                 iswide = false;
461                         }
462                         break;
463
464                 case JAVA_WIDE:
465                         iswide = true;
466                         nextp = p + 1;
467                         break;
468
469                 case JAVA_LOOKUPSWITCH:
470                         nextp = ALIGN((p + 1), 4) + 4;
471                         nextp += code_get_u4(nextp,m) * 8 + 4;
472                         break;
473
474                 case JAVA_TABLESWITCH:
475                         nextp = ALIGN((p + 1), 4) + 4;
476                         nextp += (code_get_u4(nextp+4,m) - code_get_u4(nextp,m) + 1) * 4 + 4 +4;
477                         break;
478                 }
479
480                 /* detect readonly variables in inlined methods */
481                 
482                 if (isnotrootlevel) { 
483                         bool iswide = oldiswide;
484                         
485                         switch (opcode) {
486                         case JAVA_ISTORE:
487                         case JAVA_LSTORE:
488                         case JAVA_FSTORE:
489                         case JAVA_DSTORE:
490                         case JAVA_ASTORE: 
491                                 if (!iswide) {
492                                         i = code_get_u1(p + 1,m);
493
494                                 } else {
495                                         i = code_get_u2(p + 1,m);
496                                 }
497                                 readonly[i] = false;
498                                 break;
499
500                         case JAVA_ISTORE_0:
501                         case JAVA_LSTORE_0:
502                         case JAVA_FSTORE_0:
503                         case JAVA_ASTORE_0:
504                                 readonly[0] = false;
505                                 break;
506
507                         case JAVA_ISTORE_1:
508                         case JAVA_LSTORE_1:
509                         case JAVA_FSTORE_1:
510                         case JAVA_ASTORE_1:
511                                 readonly[1] = false;
512                                 break;
513
514                         case JAVA_ISTORE_2:
515                         case JAVA_LSTORE_2:
516                         case JAVA_FSTORE_2:
517                         case JAVA_ASTORE_2:
518                                 readonly[2] = false;
519                                 break;
520
521                         case JAVA_ISTORE_3:
522                         case JAVA_LSTORE_3:
523                         case JAVA_FSTORE_3:
524                         case JAVA_ASTORE_3:
525                                 readonly[3] = false;
526                                 break;
527
528                         case JAVA_IINC:
529                                 if (!iswide) {
530                                         i = code_get_u1(p + 1,m);
531
532                                 } else {
533                                         i = code_get_u2(p + 1,m);
534                                 }
535                                 readonly[i] = false;
536                                 break;
537                         }
538                 }
539
540                 /*              for (i=lastlabel; i<=p; i++) label_index[i] = gp; 
541                                 printf("lastlabel=%d p=%d gp=%d\n",lastlabel, p, gp);
542                 lastlabel = p+1; */
543                 for (i = p; i < nextp; i++) label_index[i] = gp;
544
545                 if (isnotleaflevel) { 
546
547                         switch (opcode) {
548
549                         case JAVA_INVOKEINTERFACE:
550                         case JAVA_INVOKEVIRTUAL:
551                                 if (!inlinevirtuals) 
552                                         break;
553                         
554                         case JAVA_INVOKESPECIAL:
555                         case JAVA_INVOKESTATIC:
556                                 i = code_get_u2(p + 1,m);
557                                 {
558                                         constant_FMIref *imr;
559                                         methodinfo *imi;
560
561                                         methodinfo *mout;
562                                         bool uniqueVirt= false;
563
564
565                                         if (opcode ==JAVA_INVOKEINTERFACE) {
566                                             imr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
567                                             LAZYLOADING(imr->class)
568                                             imi = class_resolveinterfacemethod(
569                                                 imr->class,
570                                                 imr->name,
571                                                 imr->descriptor,
572                                                 m->class,
573                                                 true);
574                                             if (!imi)  /* extra for debug */
575                                                 panic("ExceptionI thrown while parsing bytecode"); /* XXX should be passed on */
576                                            }
577                                         else {
578                                            imr = class_getconstant(m->class, i, CONSTANT_Methodref);
579                                            LAZYLOADING(imr->class)
580                                            imi = class_resolveclassmethod(
581                                                 imr->class,
582                                                 imr->name,
583                                                 imr->descriptor,
584                                                 m->class,
585                                                 true);
586                                             if (!imi) /* extra for debug */
587                                                 panic("Exception0 thrown while parsing bytecode"); /* XXX should be passed on */
588                                             }
589
590                                         if (!imi) /* normal-but never get here now */ 
591                                                 panic("Exception thrown while parsing bytecode"); /* XXX should be passed on */
592
593 /** Inlining has problem currently with typecheck & inlining **/
594 /** Due problem with typecheck & inlining, class checks fail for <init>s **/
595                                         if (utf_new_char("<init>") == imi->name) break; 
596 /****/                                  
597                                         if (opcode == JAVA_INVOKEVIRTUAL) {
598                                                 mout = NULL;
599                                                 /* unique virt meth? then */
600                                                 /*  allow it to be inlined*/
601                                                 if (is_unique_method2(
602                                                          imi->class,
603                                                          imi, 
604                                                          &mout) == 1) {
605                                                   if (mout != NULL) {
606                                                         imi = mout;
607                                                         uniqueVirt=true; 
608 #ifdef INVIRTDEBUG
609                                                         METHINFOx(imi);
610                                                         printf("WAS unique virtual(-iv)\n");fflush(stdout);
611 #endif
612                                                         }
613                                                   } /* end is unique */
614                                                 } /* end INVOKEVIRTUAL */       
615                                         if (opcode == JAVA_INVOKEINTERFACE){
616                                                 mout = NULL; 
617 #ifdef INVIRTDEBUG
618                                                 METHINFOx(imi);
619 #endif
620                                                 if (is_unique_interface_method (
621                                                          imi, 
622                                                          &mout)) {
623                                                      if (mout != NULL) {
624                                                         imi = mout;
625                                                         uniqueVirt=true;
626 #ifdef INVIRTDEBUG
627                                                           METHINFOx(imi);
628                                                           printf("WAS unique interface(-iv)\n");fflush(stdout);
629 #endif
630                                                         }
631                                                         
632                                                      } 
633                                                 } /* end INVOKEINTERFACE */     
634
635                                         if ((inline_env->cummethods < INLINING_MAXMETHODS) &&
636                                                 (!(imi->flags & ACC_NATIVE)) &&  
637                                                 (inlineoutsiders || (m->class == imr->class)) && 
638                                                 (imi->jcodelength < INLINING_MAXCODESIZE) && 
639                                                 (imi->jcodelength > 0) && 
640                                                (((!inlinevirtuals)  || 
641                                                  (uniqueVirt     ))   || 
642                                                 ((opcode != JAVA_INVOKEVIRTUAL) || 
643                                                  (opcode != JAVA_INVOKEINTERFACE)) ) &&
644                                                 (inlineexceptions || (imi->exceptiontablelength == 0))) { /* FIXME: eliminate empty methods? */
645                                                 inlining_methodinfo *tmp;
646                                                 descriptor2types(imi);
647
648                                                 inline_env->cummethods++;
649
650                                                 if (opt_verbose) {
651                                                         char logtext[MAXLOGTEXT];
652                                                         sprintf(logtext, "Going to inline: ");
653                                                         utf_sprint(logtext  +strlen(logtext), imi->class->name);
654                                                         strcpy(logtext + strlen(logtext), ".");
655                                                         utf_sprint(logtext + strlen(logtext), imi->name);
656                                                         utf_sprint(logtext + strlen(logtext), imi->descriptor);
657                                                         log_text(logtext);
658                                                         if ( (!(opcode == JAVA_INVOKEVIRTUAL)) &&
659                                                              (! ( (imi->flags & ACC_STATIC )
660                                                              ||   ((imi->flags & ACC_PRIVATE) && (imi->class == inline_env->class))
661                                                              ||   (imi->flags & ACC_FINAL  ))) )
662                                                            {
663                                                            printf("DEBUG WARNING:PROBABLE INLINE PROBLEM flags not static, private or final for non-virtual inlined method\n"); fflush(stdout);
664                                                            METHINFOx(imi);
665                                                            log_text("PROBABLE INLINE PROBLEM flags not static, private or final for non-virtual inlined method\n See method info after DEBUG WARNING\n");
666                                                            }
667
668                                                 }
669                                                 
670                                                 tmp =inlining_analyse_method(imi, level + 1, gp, firstlocal + m->maxlocals, maxstackdepth + m->maxstack, inline_env);
671                                                 list_addlast(newnode->inlinedmethods, tmp);
672                 #ifdef DEBUGi
673 printf("New node Right after an inline by:");fflush(stdout);
674 METHINFOj(m)
675 print_inlining_methodinfo(newnode);
676 printf("end new node\n"); fflush(stdout);
677                 #endif
678                                                 gp = tmp->stopgp;
679                                                 p = nextp;
680                                         }
681                                 }
682                                 break;
683                         }
684                 }  
685         } /* for */
686         
687         newnode->stopgp = gp;
688         label_index[jcodelength]=gp;
689     return newnode;
690 }
691
692 /* --------------------------------------------------------------------*/
693 /*  print_ functions: check inline structures contain what is expected */
694 /* --------------------------------------------------------------------*/
695 void print_t_inlining_globals (t_inlining_globals *g) 
696 {
697 printf("\n------------\nt_inlining_globals struct for: \n\t");fflush(stdout); 
698 METHINFOj(g->method);
699 printf("\tclass=");fflush(stdout);
700   utf_display(g->class->name);printf("\n");fflush(stdout);
701
702 printf("\tjcodelength=%i; jcode=%p;\n",g->jcodelength, g->jcode);
703
704 if (g->isinlinedmethod==true) {
705   printf("\tisinlinedmethod=true ");fflush(stdout);  
706   }
707 else {
708   printf("\tisinlinedmethod=false");fflush(stdout);  
709   }
710
711 printf("\tcumjcodelength=%i ,cummaxstack=%i ,cumextablelength=%i ",
712  g->cumjcodelength,    g->cummaxstack,  g->cumextablelength);fflush(stdout);
713 printf("\tcumlocals=%i ,cummethods=%i \n",
714  g->cumlocals,    g->cummethods);fflush(stdout);  
715
716 printf("s>s>s> ");fflush(stdout);
717         print_inlining_stack     (g->inlining_stack);
718 printf("i>i>i> "); fflush(stdout);
719         print_inlining_methodinfo(g->inlining_rootinfo);
720 printf("-------------------\n");fflush(stdout);
721 }
722
723 /* --------------------------------------------------------------------*/
724 void print_inlining_stack     ( list                *s)
725 {
726   t_inlining_stacknode *is;
727
728 if (s==NULL) { 
729   printf("\n\tinlining_stack: NULL\n");
730   return;
731   }
732
733 /* print first  element to see if get into stack */
734 printf("\n\tinlining_stack: NOT NULL\n");
735
736 is=list_first(s); 
737 if (is==NULL) { 
738     printf("\n\tinlining_stack = init'd but EMPTY\n");
739     fflush(stdout);
740     return;
741     }
742
743 printf("\n\tinlining_stack: NOT NULL\n");
744
745 for (is=list_first(s); 
746        is!=NULL;
747        is=list_next(s,is)) {
748          printf("\n\ti>--->inlining_stack entry: \n"); fflush(stdout);
749          METHINFOx(is->method);
750          printf("i=%i, p=%i, nextp=%i, opcode=%i;\n",
751                 is->i,is->p,is->nextp,is->opcode);fflush(stdout);
752          print_inlining_methodinfo(is->inlinfo);
753     } /*end for */
754 }
755
756 /* --------------------------------------------------------------------*/
757 void print_inlining_methodinfo( inlining_methodinfo *r) {
758   int i=0;
759   int cnt,cnt2;
760   inlining_methodinfo *im;
761   inlining_methodinfo *im2;
762   bool labellong = false;
763
764 if (r==NULL) { 
765   printf("\n\tinlining_methodinfo: NULL\n");
766   return;
767   }
768 printf("\n\tinlining_methodinfo for:"); fflush(stdout);
769
770 if (r->method != NULL) {
771   utf_display(r->method->class->name); printf("."); fflush(stdout); \
772   method_display(r->method); fflush(stdout); \
773   }
774 else {
775   printf(" NULL!!!!!\n");fflush(stdout);
776   }
777
778 if (r->readonly==NULL) {
779   printf("\treadonly==NULL ");fflush(stdout);  
780   }
781 else {
782   printf("\treadonly=");fflush(stdout);  
783   for (i = 0; i < r->method->maxlocals; i++)  {
784     if (r->readonly[i] == true)
785       printf("[i]=T;");
786     else
787       printf("[i]=F;");
788     fflush(stdout);
789     } 
790   }
791
792 /**printf("\tstartgp=%i; stopgp=%i; firstlocal=%i; label_index=%p;\n", **/
793 printf("\tstartgp=%i; stopgp=%i; firstlocal=%i; label_index=%p;\n",
794           r->startgp, r->stopgp, r->firstlocal, (void *)r->label_index);
795 printf ("label_index[0..%d]->", r->method->jcodelength);
796 if (labellong) {
797 for (i=0; i<r->method->jcodelength; i++) printf ("%d:%d ", i, r->label_index[i]); }
798 else {
799 printf ("%d:%d ", 0, r->label_index[i]);
800 printf ("%d:%d ", 
801   (r->method->jcodelength-1), r->label_index[r->method->jcodelength-1]);
802 }
803
804 printf("\n:::::inlines::::::::::::::::::::\n");
805 if (list_first(r->inlinedmethods) == NULL) {
806         printf("Nothing\n");fflush(stdout);
807         }
808 else {
809         for (im=list_first(r->inlinedmethods),cnt=0; 
810              im!=NULL;
811              im=list_next(r->inlinedmethods,im),cnt++) {
812                 printf("*"); fflush(stdout);
813                 printf("%i:",cnt);
814                 printf("[1L%i] ",im->firstlocal); fflush(stdout);
815                 METHINFOj(im->method)
816                 printf("::::: which inlines::"); fflush(stdout);        
817                 if (list_first(im->inlinedmethods) == NULL) {
818                         printf("Nothing\n");fflush(stdout);
819                         }
820                 else   {
821                         printf("##"); fflush(stdout);
822                         for (im2=list_first(im->inlinedmethods),cnt2=0; 
823                              im2!=NULL;
824                              im2=list_next(im2->inlinedmethods,im2),cnt2++) 
825                                 {
826                                 printf("\t%i::",cnt2); fflush(stdout);
827                                 printf("[1L%i] ",im2->firstlocal); 
828                                         fflush(stdout);
829                                 METHINFOj(im2->method)
830                                 }
831                         printf("\n"); fflush(stdout);
832                         }
833                 } 
834       }
835 }
836
837
838 /*
839  * These are local overrides for various environment variables in Emacs.
840  * Please do not remove this and leave it at the end of the file, where
841  * Emacs will automagically detect them.
842  * ---------------------------------------------------------------------
843  * Local variables:
844  * mode: c
845  * indent-tabs-mode: t
846  * c-basic-offset: 4
847  * tab-width: 4
848  * End:
849  */