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