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