1 static void descriptor2types (methodinfo *m);
21 } inlining_methodinfo;
26 // saved static compiler variables
30 // restored through method
36 // descriptor never used
37 // maxstack used outside of main for loop
38 // maxlocals never used
40 // exceptiontablelength
41 // raw_extable used outside of main for loop
42 // mreturntype used outside of main for loop
43 // mparamcount used outside of main for loop
44 // mparamtypes used outside of main for loop
46 //local variables used in parse()
48 int i; /* temporary for different uses (counters) */
49 int p; /* java instruction counter */
50 int nextp; /* start of next java instruction */
51 int opcode; /* java opcode */
53 inlining_methodinfo *inlinfo;
55 /* list *patchlist; */
56 } t_inlining_stacknode;
58 // checked functions and macros: LOADCONST code_get OP1 BUILTIN block_insert bound_check ALIGN
60 // replace jcodelength loops with correct number after main for loop in parse()!
62 static list *inlining_stack;
63 //static list *inlining_patchlist;
64 static bool isinlinedmethod;
65 static int cumjcodelength; /* cumulative immediate intruction length */
67 static int cummaxstack;
68 static int cumextablelength;
69 static int cummethods;
70 static inlining_methodinfo *inlining_rootinfo;
73 void inlining_push_compiler_variables(int i, int p, int nextp, int opcode, inlining_methodinfo* inlinfo);
74 void inlining_pop_compiler_variables(int *i, int *p, int *nextp, int *opcode, inlining_methodinfo** inlinfo);
75 void inlining_init(void);
76 inlining_methodinfo *inlining_analyse_method(methodinfo *m, int level, int gp, int firstlocal, int maxstackdepth);
78 #define inlining_save_compiler_variables() inlining_push_compiler_variables(i,p,nextp,opcode,inlinfo)
79 #define inlining_restore_compiler_variables() inlining_pop_compiler_variables(&i,&p,&nextp,&opcode,&inlinfo)
80 #define inlining_set_compiler_variables(i) p=nextp=0; inlining_set_compiler_variables_fun(i->method); inlinfo=i;
81 #define INLINING_MAXDEPTH 1
82 #define INLINING_MAXCODESIZE 32
83 #define INLINING_MAXMETHODS 8
85 void inlining_init(void)
87 inlining_stack = NULL;
88 // inlining_patchlist = NULL;
96 inlining_stack = NEW(list);
97 list_init(inlining_stack, OFFSET(t_inlining_stacknode, linkage));
99 inlining_rootinfo = inlining_analyse_method(method, 0, 0, 0, 0);
100 maxlocals = cumlocals;
101 maxstack = cummaxstack;
104 void inlining_cleanup(void)
106 FREE(inlining_stack, t_inlining_stacknode);
109 void inlining_push_compiler_variables(int i, int p, int nextp, int opcode, inlining_methodinfo *inlinfo)
111 t_inlining_stacknode *new = NEW(t_inlining_stacknode);
116 new->opcode = opcode;
117 new->method = method;
118 // new->patchlist = inlining_patchlist;
119 new->inlinfo = inlinfo;
121 list_addfirst(inlining_stack, new);
125 void inlining_pop_compiler_variables(int *i, int *p, int *nextp, int *opcode, inlining_methodinfo **inlinfo)
127 t_inlining_stacknode *tmp = (t_inlining_stacknode *) list_first(inlining_stack);
129 if (!isinlinedmethod) panic("Attempting to pop from inlining stack in toplevel method!\n");
134 *opcode = tmp->opcode;
135 *inlinfo = tmp->inlinfo;
137 method = tmp->method;
138 class = method->class;
139 jcodelength = method->jcodelength;
140 jcode = method->jcode;
141 // inlining_patchlist = tmp->patchlist;
143 list_remove(inlining_stack, tmp);
144 FREE(tmp, t_inlining_stacknode);
148 void inlining_set_compiler_variables_fun(methodinfo *m)
152 jcodelength = m->jcodelength;
155 // inlining_patchlist = DNEW(list);
156 // list_init(inlining_patchlist, OFFSET(t_patchlistnode, linkage));
159 /*void inlining_addpatch(instruction *iptr)
161 t_patchlistnode *patch = DNEW(t_patchlistnode);
163 list_addlast(inlining_patchlist, patch);
167 classinfo *first_occurence(classinfo* class, utf* name, utf* desc) {
168 classinfo *first = class;
170 for (; class->super != NULL ; class = class->super) {
171 if (class_findmethod(class->super, name, desc) != NULL) {
172 first = class->super;
178 bool is_unique_rec(classinfo *class, methodinfo *m, utf* name, utf* desc) {
179 methodinfo *tmp = class_findmethod(class, name, desc);
180 if ((tmp != NULL) && (tmp != m))
183 for (; class != NULL; class = class->nextsub) {
184 if ((class->sub != NULL) && !is_unique_rec(class->sub, m, name, desc)) {
191 bool is_unique_method(classinfo *class, methodinfo *m, utf* name, utf* desc) {
192 classinfo *firstclass;
194 /* sprintf (logtext, "First occurence of: ");
195 utf_sprint (logtext+strlen(logtext), m->class->name);
196 strcpy (logtext+strlen(logtext), ".");
197 utf_sprint (logtext+strlen(logtext), m->name);
198 utf_sprint (logtext+strlen(logtext), m->descriptor);
201 firstclass = first_occurence(class, name, desc);
203 /* sprintf (logtext, "\nis in class:");
204 utf_sprint (logtext+strlen(logtext), firstclass->name);
207 if (firstclass != class) return false;
209 return is_unique_rec(class, m, name, desc);
213 inlining_methodinfo *inlining_analyse_method(methodinfo *m, int level, int gp, int firstlocal, int maxstackdepth)
215 inlining_methodinfo *newnode = DNEW(inlining_methodinfo);
216 u1 *jcode = m->jcode;
217 int jcodelength = m->jcodelength;
221 int i, lastlabel = 0;
222 bool iswide = false, oldiswide;
223 bool *readonly = NULL;
224 int *label_index = NULL;
225 bool isnotrootlevel = (level > 0);
226 bool isnotleaflevel = (level < INLINING_MAXDEPTH);
228 // if (level == 0) gp = 0;
230 sprintf (logtext, "Performing inlining analysis of: ");
231 utf_sprint (logtext+strlen(logtext), m->class->name);
232 strcpy (logtext+strlen(logtext), ".");
233 utf_sprint (logtext+strlen(logtext), m->name);
234 utf_sprint (logtext+strlen(logtext), m->descriptor);
237 if (isnotrootlevel) {
238 newnode->readonly = readonly = DMNEW(bool, m->maxlocals); //FIXME only paramcount entrys necessary
239 for (i = 0; i < m->maxlocals; readonly[i++] = true);
240 isnotrootlevel = true;
245 label_index = DMNEW(int, jcodelength);
247 newnode->inlinedmethods = DNEW(list);
248 list_init(newnode->inlinedmethods, OFFSET(inlining_methodinfo, linkage));
251 newnode->startgp = gp;
252 newnode->readonly = readonly;
253 newnode->label_index = label_index;
254 newnode->firstlocal = firstlocal;
255 cumjcodelength += jcodelength + m->paramcount + 1 + 5;
256 if ((firstlocal + m->maxlocals) > cumlocals) cumlocals = firstlocal + m->maxlocals;
257 if ((maxstackdepth + m->maxstack) > cummaxstack) cummaxstack = maxstackdepth + m->maxstack;
258 cumextablelength += m->exceptiontablelength;
261 for (p = 0; p < jcodelength; gp += (nextp - p), p = nextp) {
262 opcode = code_get_u1 (p);
263 nextp = p + jcommandsize[opcode];
266 /* figure out nextp */
284 if (iswide) { nextp = p + 3; iswide = false; }
288 if (iswide) { nextp = p + 5; iswide = false; }
296 case JAVA_LOOKUPSWITCH:
297 nextp = ALIGN((p + 1), 4) + 4;
298 nextp += code_get_u4(nextp) * 8 + 4;
301 case JAVA_TABLESWITCH:
302 nextp = ALIGN((p + 1), 4) + 4;
303 nextp += (code_get_u4(nextp+4) - code_get_u4(nextp) + 1) * 4 + 4;
307 /* detect readonly variables in inlined methods */
309 if (isnotrootlevel) {
310 bool iswide = oldiswide;
320 i = code_get_u1(p+1);
322 i = code_get_u2(p+1);
358 i = code_get_u1(p + 1);
361 i = code_get_u2(p + 1);
370 /* for (i=lastlabel; i<=p; i++) label_index[i] = gp;
371 // printf("lastlabel=%d p=%d gp=%d\n",lastlabel, p, gp);
373 for (i=p; i < nextp; i++) label_index[i] = gp;
375 if (isnotleaflevel) {
378 case JAVA_INVOKEVIRTUAL:
379 if (!inlinevirtuals) break;
380 case JAVA_INVOKESTATIC:
381 i = code_get_u2(p + 1);
383 constant_FMIref *imr;
386 imr = class_getconstant (m->class, i, CONSTANT_Methodref);
387 imi = class_findmethod (imr->class, imr->name, imr->descriptor);
389 if (opcode == JAVA_INVOKEVIRTUAL)
391 if (!is_unique_method(imi->class, imi, imr->name ,imr->descriptor))
395 if ( (cummethods < INLINING_MAXMETHODS) &&
396 (! (imi->flags & ACC_NATIVE)) &&
397 ( !inlineoutsiders || (class == imr->class)) &&
398 (imi->jcodelength < INLINING_MAXCODESIZE) &&
399 (imi->jcodelength > 0) &&
400 (!inlineexceptions || (imi->exceptiontablelength == 0)) ) //FIXME: eliminate empty methods?
402 inlining_methodinfo *tmp;
403 descriptor2types(imi);
407 /* sprintf (logtext, "Going to inline: ");
408 utf_sprint (logtext+strlen(logtext), imi->class->name);
409 strcpy (logtext+strlen(logtext), ".");
410 utf_sprint (logtext+strlen(logtext), imi->name);
411 utf_sprint (logtext+strlen(logtext), imi->descriptor);
414 tmp = inlining_analyse_method(imi, level+1, gp, firstlocal + m->maxlocals, maxstackdepth + m->maxstack);
415 list_addlast(newnode->inlinedmethods, tmp);
427 newnode->stopgp = gp;
430 sprintf (logtext, "Result of inlining analysis of: ");
431 utf_sprint (logtext+strlen(logtext), m->class->name);
432 strcpy (logtext+strlen(logtext), ".");
433 utf_sprint (logtext+strlen(logtext), m->name);
434 utf_sprint (logtext+strlen(logtext), m->descriptor);
436 sprintf (logtext, "label_index[0..%d]->", jcodelength);
437 for (i=0; i<jcodelength; i++) sprintf (logtext, "%d:%d ", i, label_index[i]);
438 sprintf(logtext,"stopgp : %d\n",newnode->stopgp); */
444 * These are local overrides for various environment variables in Emacs.
445 * Please do not remove this and leave it at the end of the file, where
446 * Emacs will automagically detect them.
447 * ---------------------------------------------------------------------
450 * indent-tabs-mode: t