* src/vm/options.h, src/vm/method.c, src/vm/jit/inline/inline.c,
[cacao.git] / src / vm / method.c
1 /* src/vm/method.c - method functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Reinhard Grafl
28
29    Changes: Andreas Krall
30             Roman Obermaiser
31             Mark Probst
32             Edwin Steiner
33             Christian Thalinger
34
35    $Id: method.c 7228 2007-01-19 01:13:48Z edwin $
36
37 */
38
39
40 #include "config.h"
41
42 #include <assert.h>
43 #include <stdio.h>
44
45 #include "vm/types.h"
46
47 #include "mm/memory.h"
48 #include "vm/class.h"
49 #include "vm/global.h"
50 #include "vm/linker.h"
51 #include "vm/loader.h"
52 #include "vm/method.h"
53 #include "vm/options.h"
54 #include "vm/jit/methodheader.h"
55
56
57 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
58 #define INLINELOG(code)  do { if (opt_inline_debug_log) { code } } while (0)
59 #else
60 #define INLINELOG(code)
61 #endif
62
63
64 /* method_free *****************************************************************
65
66    Frees all memory that was allocated for this method.
67
68 *******************************************************************************/
69
70 void method_free(methodinfo *m)
71 {
72         if (m->jcode)
73                 MFREE(m->jcode, u1, m->jcodelength);
74
75         if (m->rawexceptiontable)
76                 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
77
78         code_free_code_of_method(m);
79
80         if (m->stubroutine) {
81                 if (m->flags & ACC_NATIVE) {
82                         removenativestub(m->stubroutine);
83
84                 } else {
85                         removecompilerstub(m->stubroutine);
86                 }
87         }
88 }
89
90
91 /* method_canoverwrite *********************************************************
92
93    Check if m and old are identical with respect to type and
94    name. This means that old can be overwritten with m.
95         
96 *******************************************************************************/
97
98 bool method_canoverwrite(methodinfo *m, methodinfo *old)
99 {
100         if (m->name != old->name)
101                 return false;
102
103         if (m->descriptor != old->descriptor)
104                 return false;
105
106         if (m->flags & ACC_STATIC)
107                 return false;
108
109         return true;
110 }
111
112
113 /* method_vftbl_lookup *********************************************************
114
115    Does a method lookup in the passed virtual function table.  This
116    function does exactly the same thing as JIT, but additionally
117    relies on the fact, that the methodinfo pointer is at the first
118    data segment slot (even for compiler stubs).
119
120 *******************************************************************************/
121
122 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
123 {
124         methodptr   mptr;
125         methodptr  *pmptr;
126         methodinfo *resm;                   /* pointer to new resolved method     */
127         codeinfo   *code;
128
129         /* If the method is not an instance method, just return it. */
130
131         if (m->flags & ACC_STATIC)
132                 return m;
133
134         assert(vftbl);
135
136         /* Get the method from the virtual function table.  Is this an
137            interface method? */
138
139         if (m->class->flags & ACC_INTERFACE) {
140                 pmptr = vftbl->interfacetable[-(m->class->index)];
141                 mptr  = pmptr[(m - m->class->methods)];
142         }
143         else {
144                 mptr = vftbl->table[m->vftblindex];
145         }
146
147         /* and now get the codeinfo pointer from the first data segment slot */
148
149         code = *((codeinfo **) (mptr + CodeinfoPointer));
150
151         resm = code->m;
152
153         return resm;
154 }
155
156
157 /* method_count_implementations ************************************************
158
159    Count the implementations of a method in a class cone (a class and all its
160    subclasses.)
161
162    IN:
163        m................the method to count
164            c................class at which to start the counting (this class and
165                             all its subclasses will be searched)
166
167    OUT:
168        *found...........if found != NULL, *found receives the method
169                             implementation that was found. This value is only
170                                                 meaningful if the return value is 1.
171
172    RETURN VALUE:
173        the number of implementations found
174
175 *******************************************************************************/
176
177 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
178 {
179         s4          count;
180         methodinfo *mp;
181         methodinfo *mend;
182         classinfo  *child;
183
184         count = 0;
185
186         mp = c->methods;
187         mend = mp + c->methodscount;
188
189         for (; mp < mend; ++mp) {
190                 if (method_canoverwrite(mp, m)) {
191                         if (found)
192                                 *found = mp;
193                         count++;
194                         break;
195                 }
196         }
197
198         for (child = c->sub; child != NULL; child = child->nextsub) {
199                 count += method_count_implementations(m, child, found);
200         }
201
202         return count;
203 }
204
205
206 /* method_add_to_worklist ******************************************************
207
208    Add the method to the given worklist. If the method already occurs in
209    the worklist, the worklist remains unchanged.
210
211 *******************************************************************************/
212
213 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
214 {
215         method_worklist *wi;
216
217         for (wi = *wl; wi != NULL; wi = wi->next)
218                 if (wi->m == m)
219                         return;
220
221         wi = NEW(method_worklist);
222         wi->next = *wl;
223         wi->m = m;
224
225         *wl = wi;
226 }
227
228
229 /* method_add_assumption_monomorphic *******************************************
230
231    Record the assumption that the method is monomorphic.
232
233    IN:
234       m.................the method
235           caller............the caller making the assumption
236
237 *******************************************************************************/
238
239 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
240 {
241         method_assumption *as;
242
243         /* XXX LOCKING FOR THIS FUNCTION? */
244
245         /* check if we already have registered this assumption */
246
247         for (as = m->assumptions; as != NULL; as = as->next) {
248                 if (as->context == caller)
249                         return;
250         }
251
252         /* register the assumption */
253
254         as = NEW(method_assumption);
255         as->next = m->assumptions;
256         as->context = caller;
257
258         m->assumptions = as;
259 }
260
261
262 /* method_break_assumption_monomorphic *****************************************
263
264    Break the assumption that this method is monomorphic. All callers that
265    have registered this assumption are added to the worklist.
266
267    IN:
268       m.................the method
269           wl................worklist where to add invalidated callers
270
271 *******************************************************************************/
272
273 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
274 {
275         method_assumption *as;
276
277         /* XXX LOCKING FOR THIS FUNCTION? */
278
279         for (as = m->assumptions; as != NULL; as = as->next) {
280                 INLINELOG(
281                         printf("ASSUMPTION BROKEN (monomorphism): ");
282                         method_print(m);
283                         printf(" in ");
284                         method_println(as->context);
285                 );
286
287                 method_add_to_worklist(as->context, wl);
288         }
289 }
290
291
292 /* method_printflags ***********************************************************
293
294    Prints the flags of a method to stdout like.
295
296 *******************************************************************************/
297
298 #if !defined(NDEBUG)
299 void method_printflags(methodinfo *m)
300 {
301         if (m == NULL) {
302                 printf("NULL");
303                 return;
304         }
305
306         if (m->flags & ACC_PUBLIC)       printf(" PUBLIC");
307         if (m->flags & ACC_PRIVATE)      printf(" PRIVATE");
308         if (m->flags & ACC_PROTECTED)    printf(" PROTECTED");
309         if (m->flags & ACC_STATIC)       printf(" STATIC");
310         if (m->flags & ACC_FINAL)        printf(" FINAL");
311         if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
312         if (m->flags & ACC_VOLATILE)     printf(" VOLATILE");
313         if (m->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
314         if (m->flags & ACC_NATIVE)       printf(" NATIVE");
315         if (m->flags & ACC_INTERFACE)    printf(" INTERFACE");
316         if (m->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
317         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
318         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
319 }
320 #endif /* !defined(NDEBUG) */
321
322
323 /* method_print ****************************************************************
324
325    Prints a method to stdout like:
326
327    java.lang.Object.<init>()V
328
329 *******************************************************************************/
330
331 #if !defined(NDEBUG)
332 void method_print(methodinfo *m)
333 {
334         if (m == NULL) {
335                 printf("NULL");
336                 return;
337         }
338
339         utf_display_printable_ascii_classname(m->class->name);
340         printf(".");
341         utf_display_printable_ascii(m->name);
342         utf_display_printable_ascii(m->descriptor);
343
344         method_printflags(m);
345 }
346 #endif /* !defined(NDEBUG) */
347
348
349 /* method_println **************************************************************
350
351    Prints a method plus new line to stdout like:
352
353    java.lang.Object.<init>()V
354
355 *******************************************************************************/
356
357 #if !defined(NDEBUG)
358 void method_println(methodinfo *m)
359 {
360         if (opt_debugcolor) printf("\033[31m"); /* red */
361         method_print(m);
362         if (opt_debugcolor) printf("\033[m");   
363         printf("\n");
364 }
365 #endif /* !defined(NDEBUG) */
366
367
368 /* method_methodref_print ******************************************************
369
370    Prints a method reference to stdout.
371
372 *******************************************************************************/
373
374 #if !defined(NDEBUG)
375 void method_methodref_print(constant_FMIref *mr)
376 {
377         if (!mr) {
378                 printf("(constant_FMIref *)NULL");
379                 return;
380         }
381
382         if (IS_FMIREF_RESOLVED(mr)) {
383                 printf("<method> ");
384                 method_print(mr->p.method);
385         }
386         else {
387                 printf("<methodref> ");
388                 utf_display_printable_ascii_classname(mr->p.classref->name);
389                 printf(".");
390                 utf_display_printable_ascii(mr->name);
391                 utf_display_printable_ascii(mr->descriptor);
392         }
393 }
394 #endif /* !defined(NDEBUG) */
395
396
397 /* method_methodref_println ****************************************************
398
399    Prints a method reference to stdout, followed by a newline.
400
401 *******************************************************************************/
402
403 #if !defined(NDEBUG)
404 void method_methodref_println(constant_FMIref *mr)
405 {
406         method_methodref_print(mr);
407         printf("\n");
408 }
409 #endif /* !defined(NDEBUG) */
410
411
412 /*
413  * These are local overrides for various environment variables in Emacs.
414  * Please do not remove this and leave it at the end of the file, where
415  * Emacs will automagically detect them.
416  * ---------------------------------------------------------------------
417  * Local variables:
418  * mode: c
419  * indent-tabs-mode: t
420  * c-basic-offset: 4
421  * tab-width: 4
422  * End:
423  * vim:noexpandtab:sw=4:ts=4:
424  */