f9dc0924e77fa14e44936be839ea374ff66ade46
[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 7573 2007-03-25 18:55:02Z twisti $
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/builtin.h"
40 #include "vm/global.h"
41 #include "vm/resolve.h"
42
43 #include "vm/jit/methodheader.h"
44
45 #include "vm/jit_interface.h"
46
47 #include "vmcore/class.h"
48 #include "vmcore/linker.h"
49 #include "vmcore/loader.h"
50 #include "vmcore/method.h"
51 #include "vmcore/options.h"
52
53
54 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
55 #define INLINELOG(code)  do { if (opt_inline_debug_log) { code } } while (0)
56 #else
57 #define INLINELOG(code)
58 #endif
59
60
61 /* method_free *****************************************************************
62
63    Frees all memory that was allocated for this method.
64
65 *******************************************************************************/
66
67 void method_free(methodinfo *m)
68 {
69         if (m->jcode)
70                 MFREE(m->jcode, u1, m->jcodelength);
71
72         if (m->rawexceptiontable)
73                 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
74
75         code_free_code_of_method(m);
76
77         if (m->stubroutine) {
78                 if (m->flags & ACC_NATIVE) {
79                         removenativestub(m->stubroutine);
80
81                 } else {
82                         removecompilerstub(m->stubroutine);
83                 }
84         }
85 }
86
87
88 /* method_canoverwrite *********************************************************
89
90    Check if m and old are identical with respect to type and
91    name. This means that old can be overwritten with m.
92         
93 *******************************************************************************/
94
95 bool method_canoverwrite(methodinfo *m, methodinfo *old)
96 {
97         if (m->name != old->name)
98                 return false;
99
100         if (m->descriptor != old->descriptor)
101                 return false;
102
103         if (m->flags & ACC_STATIC)
104                 return false;
105
106         return true;
107 }
108
109
110 /* method_vftbl_lookup *********************************************************
111
112    Does a method lookup in the passed virtual function table.  This
113    function does exactly the same thing as JIT, but additionally
114    relies on the fact, that the methodinfo pointer is at the first
115    data segment slot (even for compiler stubs).
116
117 *******************************************************************************/
118
119 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
120 {
121         methodptr   mptr;
122         methodptr  *pmptr;
123         methodinfo *resm;                   /* pointer to new resolved method     */
124
125         /* If the method is not an instance method, just return it. */
126
127         if (m->flags & ACC_STATIC)
128                 return m;
129
130         assert(vftbl);
131
132         /* Get the method from the virtual function table.  Is this an
133            interface method? */
134
135         if (m->class->flags & ACC_INTERFACE) {
136                 pmptr = vftbl->interfacetable[-(m->class->index)];
137                 mptr  = pmptr[(m - m->class->methods)];
138         }
139         else {
140                 mptr = vftbl->table[m->vftblindex];
141         }
142
143         /* and now get the codeinfo pointer from the first data segment slot */
144
145         resm = code_get_methodinfo_for_pv(mptr);
146
147         return resm;
148 }
149
150
151 /* method_get_parametertypearray ***********************************************
152
153    Use the descriptor of a method to generate a java.lang.Class array
154    which contains the classes of the parametertypes of the method.
155
156    This function is called by java.lang.reflect.{Constructor,Method}.
157
158 *******************************************************************************/
159
160 java_objectarray *method_get_parametertypearray(methodinfo *m)
161 {
162         methoddesc       *md;
163         typedesc         *paramtypes;
164         s4                paramcount;
165     java_objectarray *oa;
166         s4                i;
167         classinfo        *c;
168
169         md = m->parseddesc;
170
171         /* is the descriptor fully parsed? */
172
173         if (m->parseddesc->params == NULL)
174                 if (!descriptor_params_from_paramtypes(md, m->flags))
175                         return NULL;
176
177         paramtypes = md->paramtypes;
178         paramcount = md->paramcount;
179
180         /* skip `this' pointer */
181
182         if (!(m->flags & ACC_STATIC)) {
183                 paramtypes++;
184                 paramcount--;
185         }
186
187         /* create class-array */
188
189         oa = builtin_anewarray(paramcount, class_java_lang_Class);
190
191         if (oa == NULL)
192                 return NULL;
193
194     /* get classes */
195
196         for (i = 0; i < paramcount; i++) {
197                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
198                         return NULL;
199
200                 oa->data[i] = (java_objectheader *) c;
201         }
202
203         return oa;
204 }
205
206
207 /* method_get_exceptionarray ***************************************************
208
209    Get the exceptions which can be thrown by a method.
210
211 *******************************************************************************/
212
213 java_objectarray *method_get_exceptionarray(methodinfo *m)
214 {
215         java_objectarray *oa;
216         classinfo        *c;
217         s4                i;
218
219         /* create class-array */
220
221         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
222
223         if (oa == NULL)
224                 return NULL;
225
226         /* iterate over all exceptions and store the class in the array */
227
228         for (i = 0; i < m->thrownexceptionscount; i++) {
229                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
230
231                 if (c == NULL)
232                         return NULL;
233
234                 oa->data[i] = (java_objectheader *) c;
235         }
236
237         return oa;
238 }
239
240
241 /* method_count_implementations ************************************************
242
243    Count the implementations of a method in a class cone (a class and all its
244    subclasses.)
245
246    IN:
247        m................the method to count
248            c................class at which to start the counting (this class and
249                             all its subclasses will be searched)
250
251    OUT:
252        *found...........if found != NULL, *found receives the method
253                             implementation that was found. This value is only
254                                                 meaningful if the return value is 1.
255
256    RETURN VALUE:
257        the number of implementations found
258
259 *******************************************************************************/
260
261 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
262 {
263         s4          count;
264         methodinfo *mp;
265         methodinfo *mend;
266         classinfo  *child;
267
268         count = 0;
269
270         mp = c->methods;
271         mend = mp + c->methodscount;
272
273         for (; mp < mend; ++mp) {
274                 if (method_canoverwrite(mp, m)) {
275                         if (found)
276                                 *found = mp;
277                         count++;
278                         break;
279                 }
280         }
281
282         for (child = c->sub; child != NULL; child = child->nextsub) {
283                 count += method_count_implementations(m, child, found);
284         }
285
286         return count;
287 }
288
289
290 /* method_add_to_worklist ******************************************************
291
292    Add the method to the given worklist. If the method already occurs in
293    the worklist, the worklist remains unchanged.
294
295 *******************************************************************************/
296
297 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
298 {
299         method_worklist *wi;
300
301         for (wi = *wl; wi != NULL; wi = wi->next)
302                 if (wi->m == m)
303                         return;
304
305         wi = NEW(method_worklist);
306         wi->next = *wl;
307         wi->m = m;
308
309         *wl = wi;
310 }
311
312
313 /* method_add_assumption_monomorphic *******************************************
314
315    Record the assumption that the method is monomorphic.
316
317    IN:
318       m.................the method
319           caller............the caller making the assumption
320
321 *******************************************************************************/
322
323 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
324 {
325         method_assumption *as;
326
327         /* XXX LOCKING FOR THIS FUNCTION? */
328
329         /* check if we already have registered this assumption */
330
331         for (as = m->assumptions; as != NULL; as = as->next) {
332                 if (as->context == caller)
333                         return;
334         }
335
336         /* register the assumption */
337
338         as = NEW(method_assumption);
339         as->next = m->assumptions;
340         as->context = caller;
341
342         m->assumptions = as;
343 }
344
345
346 /* method_break_assumption_monomorphic *****************************************
347
348    Break the assumption that this method is monomorphic. All callers that
349    have registered this assumption are added to the worklist.
350
351    IN:
352       m.................the method
353           wl................worklist where to add invalidated callers
354
355 *******************************************************************************/
356
357 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
358 {
359         method_assumption *as;
360
361         /* XXX LOCKING FOR THIS FUNCTION? */
362
363         for (as = m->assumptions; as != NULL; as = as->next) {
364                 INLINELOG(
365                         printf("ASSUMPTION BROKEN (monomorphism): ");
366                         method_print(m);
367                         printf(" in ");
368                         method_println(as->context);
369                 );
370
371                 method_add_to_worklist(as->context, wl);
372         }
373 }
374
375
376 /* method_printflags ***********************************************************
377
378    Prints the flags of a method to stdout like.
379
380 *******************************************************************************/
381
382 #if !defined(NDEBUG)
383 void method_printflags(methodinfo *m)
384 {
385         if (m == NULL) {
386                 printf("NULL");
387                 return;
388         }
389
390         if (m->flags & ACC_PUBLIC)       printf(" PUBLIC");
391         if (m->flags & ACC_PRIVATE)      printf(" PRIVATE");
392         if (m->flags & ACC_PROTECTED)    printf(" PROTECTED");
393         if (m->flags & ACC_STATIC)       printf(" STATIC");
394         if (m->flags & ACC_FINAL)        printf(" FINAL");
395         if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
396         if (m->flags & ACC_VOLATILE)     printf(" VOLATILE");
397         if (m->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
398         if (m->flags & ACC_NATIVE)       printf(" NATIVE");
399         if (m->flags & ACC_INTERFACE)    printf(" INTERFACE");
400         if (m->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
401         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
402         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
403 }
404 #endif /* !defined(NDEBUG) */
405
406
407 /* method_print ****************************************************************
408
409    Prints a method to stdout like:
410
411    java.lang.Object.<init>()V
412
413 *******************************************************************************/
414
415 #if !defined(NDEBUG)
416 void method_print(methodinfo *m)
417 {
418         if (m == NULL) {
419                 printf("NULL");
420                 return;
421         }
422
423         utf_display_printable_ascii_classname(m->class->name);
424         printf(".");
425         utf_display_printable_ascii(m->name);
426         utf_display_printable_ascii(m->descriptor);
427
428         method_printflags(m);
429 }
430 #endif /* !defined(NDEBUG) */
431
432
433 /* method_println **************************************************************
434
435    Prints a method plus new line to stdout like:
436
437    java.lang.Object.<init>()V
438
439 *******************************************************************************/
440
441 #if !defined(NDEBUG)
442 void method_println(methodinfo *m)
443 {
444         if (opt_debugcolor) printf("\033[31m"); /* red */
445         method_print(m);
446         if (opt_debugcolor) printf("\033[m");   
447         printf("\n");
448 }
449 #endif /* !defined(NDEBUG) */
450
451
452 /* method_methodref_print ******************************************************
453
454    Prints a method reference to stdout.
455
456 *******************************************************************************/
457
458 #if !defined(NDEBUG)
459 void method_methodref_print(constant_FMIref *mr)
460 {
461         if (!mr) {
462                 printf("(constant_FMIref *)NULL");
463                 return;
464         }
465
466         if (IS_FMIREF_RESOLVED(mr)) {
467                 printf("<method> ");
468                 method_print(mr->p.method);
469         }
470         else {
471                 printf("<methodref> ");
472                 utf_display_printable_ascii_classname(mr->p.classref->name);
473                 printf(".");
474                 utf_display_printable_ascii(mr->name);
475                 utf_display_printable_ascii(mr->descriptor);
476         }
477 }
478 #endif /* !defined(NDEBUG) */
479
480
481 /* method_methodref_println ****************************************************
482
483    Prints a method reference to stdout, followed by a newline.
484
485 *******************************************************************************/
486
487 #if !defined(NDEBUG)
488 void method_methodref_println(constant_FMIref *mr)
489 {
490         method_methodref_print(mr);
491         printf("\n");
492 }
493 #endif /* !defined(NDEBUG) */
494
495
496 /*
497  * These are local overrides for various environment variables in Emacs.
498  * Please do not remove this and leave it at the end of the file, where
499  * Emacs will automagically detect them.
500  * ---------------------------------------------------------------------
501  * Local variables:
502  * mode: c
503  * indent-tabs-mode: t
504  * c-basic-offset: 4
505  * tab-width: 4
506  * End:
507  * vim:noexpandtab:sw=4:ts=4:
508  */