* configure.ac (AC_CHECK_HEADERS): Added sys/socket.h.
[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 8123 2007-06-20 23:50:55Z 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/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_returntype_get *******************************************************
242
243    Get the return type of the method.
244
245 *******************************************************************************/
246
247 classinfo *method_returntype_get(methodinfo *m)
248 {
249         typedesc  *td;
250         classinfo *c;
251
252         td = &(m->parseddesc->returntype);
253
254         if (!resolve_class_from_typedesc(td, true, false, &c))
255                 return NULL;
256
257         return c;
258 }
259
260
261 /* method_count_implementations ************************************************
262
263    Count the implementations of a method in a class cone (a class and all its
264    subclasses.)
265
266    IN:
267        m................the method to count
268            c................class at which to start the counting (this class and
269                             all its subclasses will be searched)
270
271    OUT:
272        *found...........if found != NULL, *found receives the method
273                             implementation that was found. This value is only
274                                                 meaningful if the return value is 1.
275
276    RETURN VALUE:
277        the number of implementations found
278
279 *******************************************************************************/
280
281 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
282 {
283         s4          count;
284         methodinfo *mp;
285         methodinfo *mend;
286         classinfo  *child;
287
288         count = 0;
289
290         mp = c->methods;
291         mend = mp + c->methodscount;
292
293         for (; mp < mend; ++mp) {
294                 if (method_canoverwrite(mp, m)) {
295                         if (found)
296                                 *found = mp;
297                         count++;
298                         break;
299                 }
300         }
301
302         for (child = c->sub; child != NULL; child = child->nextsub) {
303                 count += method_count_implementations(m, child, found);
304         }
305
306         return count;
307 }
308
309
310 /* method_add_to_worklist ******************************************************
311
312    Add the method to the given worklist. If the method already occurs in
313    the worklist, the worklist remains unchanged.
314
315 *******************************************************************************/
316
317 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
318 {
319         method_worklist *wi;
320
321         for (wi = *wl; wi != NULL; wi = wi->next)
322                 if (wi->m == m)
323                         return;
324
325         wi = NEW(method_worklist);
326         wi->next = *wl;
327         wi->m = m;
328
329         *wl = wi;
330 }
331
332
333 /* method_add_assumption_monomorphic *******************************************
334
335    Record the assumption that the method is monomorphic.
336
337    IN:
338       m.................the method
339           caller............the caller making the assumption
340
341 *******************************************************************************/
342
343 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
344 {
345         method_assumption *as;
346
347         /* XXX LOCKING FOR THIS FUNCTION? */
348
349         /* check if we already have registered this assumption */
350
351         for (as = m->assumptions; as != NULL; as = as->next) {
352                 if (as->context == caller)
353                         return;
354         }
355
356         /* register the assumption */
357
358         as = NEW(method_assumption);
359         as->next = m->assumptions;
360         as->context = caller;
361
362         m->assumptions = as;
363 }
364
365
366 /* method_break_assumption_monomorphic *****************************************
367
368    Break the assumption that this method is monomorphic. All callers that
369    have registered this assumption are added to the worklist.
370
371    IN:
372       m.................the method
373           wl................worklist where to add invalidated callers
374
375 *******************************************************************************/
376
377 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
378 {
379         method_assumption *as;
380
381         /* XXX LOCKING FOR THIS FUNCTION? */
382
383         for (as = m->assumptions; as != NULL; as = as->next) {
384                 INLINELOG(
385                         printf("ASSUMPTION BROKEN (monomorphism): ");
386                         method_print(m);
387                         printf(" in ");
388                         method_println(as->context);
389                 );
390
391                 method_add_to_worklist(as->context, wl);
392         }
393 }
394
395
396 /* method_printflags ***********************************************************
397
398    Prints the flags of a method to stdout like.
399
400 *******************************************************************************/
401
402 #if !defined(NDEBUG)
403 void method_printflags(methodinfo *m)
404 {
405         if (m == NULL) {
406                 printf("NULL");
407                 return;
408         }
409
410         if (m->flags & ACC_PUBLIC)       printf(" PUBLIC");
411         if (m->flags & ACC_PRIVATE)      printf(" PRIVATE");
412         if (m->flags & ACC_PROTECTED)    printf(" PROTECTED");
413         if (m->flags & ACC_STATIC)       printf(" STATIC");
414         if (m->flags & ACC_FINAL)        printf(" FINAL");
415         if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
416         if (m->flags & ACC_VOLATILE)     printf(" VOLATILE");
417         if (m->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
418         if (m->flags & ACC_NATIVE)       printf(" NATIVE");
419         if (m->flags & ACC_INTERFACE)    printf(" INTERFACE");
420         if (m->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
421         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
422         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
423 }
424 #endif /* !defined(NDEBUG) */
425
426
427 /* method_print ****************************************************************
428
429    Prints a method to stdout like:
430
431    java.lang.Object.<init>()V
432
433 *******************************************************************************/
434
435 #if !defined(NDEBUG)
436 void method_print(methodinfo *m)
437 {
438         if (m == NULL) {
439                 printf("NULL");
440                 return;
441         }
442
443         utf_display_printable_ascii_classname(m->class->name);
444         printf(".");
445         utf_display_printable_ascii(m->name);
446         utf_display_printable_ascii(m->descriptor);
447
448         method_printflags(m);
449 }
450 #endif /* !defined(NDEBUG) */
451
452
453 /* method_println **************************************************************
454
455    Prints a method plus new line to stdout like:
456
457    java.lang.Object.<init>()V
458
459 *******************************************************************************/
460
461 #if !defined(NDEBUG)
462 void method_println(methodinfo *m)
463 {
464         if (opt_debugcolor) printf("\033[31m"); /* red */
465         method_print(m);
466         if (opt_debugcolor) printf("\033[m");   
467         printf("\n");
468 }
469 #endif /* !defined(NDEBUG) */
470
471
472 /* method_methodref_print ******************************************************
473
474    Prints a method reference to stdout.
475
476 *******************************************************************************/
477
478 #if !defined(NDEBUG)
479 void method_methodref_print(constant_FMIref *mr)
480 {
481         if (!mr) {
482                 printf("(constant_FMIref *)NULL");
483                 return;
484         }
485
486         if (IS_FMIREF_RESOLVED(mr)) {
487                 printf("<method> ");
488                 method_print(mr->p.method);
489         }
490         else {
491                 printf("<methodref> ");
492                 utf_display_printable_ascii_classname(mr->p.classref->name);
493                 printf(".");
494                 utf_display_printable_ascii(mr->name);
495                 utf_display_printable_ascii(mr->descriptor);
496         }
497 }
498 #endif /* !defined(NDEBUG) */
499
500
501 /* method_methodref_println ****************************************************
502
503    Prints a method reference to stdout, followed by a newline.
504
505 *******************************************************************************/
506
507 #if !defined(NDEBUG)
508 void method_methodref_println(constant_FMIref *mr)
509 {
510         method_methodref_print(mr);
511         printf("\n");
512 }
513 #endif /* !defined(NDEBUG) */
514
515
516 /*
517  * These are local overrides for various environment variables in Emacs.
518  * Please do not remove this and leave it at the end of the file, where
519  * Emacs will automagically detect them.
520  * ---------------------------------------------------------------------
521  * Local variables:
522  * mode: c
523  * indent-tabs-mode: t
524  * c-basic-offset: 4
525  * tab-width: 4
526  * End:
527  * vim:noexpandtab:sw=4:ts=4:
528  */