* src/vm/linker.c (inline_debug_log): Added variable reference.
[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 5975 2006-11-12 15:33:16Z 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 extern bool inline_debug_log;
59 #define INLINELOG(code)  do { if (inline_debug_log) { code } } while (0)
60 #else
61 #define INLINELOG(code)
62 #endif
63
64
65 /* method_free *****************************************************************
66
67    Frees all memory that was allocated for this method.
68
69 *******************************************************************************/
70
71 void method_free(methodinfo *m)
72 {
73         if (m->jcode)
74                 MFREE(m->jcode, u1, m->jcodelength);
75
76         if (m->rawexceptiontable)
77                 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
78
79         code_free_code_of_method(m);
80
81         if (m->stubroutine) {
82                 if (m->flags & ACC_NATIVE) {
83                         removenativestub(m->stubroutine);
84
85                 } else {
86                         removecompilerstub(m->stubroutine);
87                 }
88         }
89 }
90
91
92 /* method_canoverwrite *********************************************************
93
94    Check if m and old are identical with respect to type and
95    name. This means that old can be overwritten with m.
96         
97 *******************************************************************************/
98
99 bool method_canoverwrite(methodinfo *m, methodinfo *old)
100 {
101         if (m->name != old->name)
102                 return false;
103
104         if (m->descriptor != old->descriptor)
105                 return false;
106
107         if (m->flags & ACC_STATIC)
108                 return false;
109
110         return true;
111 }
112
113
114 /* method_vftbl_lookup *********************************************************
115
116    Does a method lookup in the passed virtual function table.  This
117    function does exactly the same thing as JIT, but additionally
118    relies on the fact, that the methodinfo pointer is at the first
119    data segment slot (even for compiler stubs).
120
121 *******************************************************************************/
122
123 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
124 {
125         methodptr   mptr;
126         methodptr  *pmptr;
127         methodinfo *resm;                   /* pointer to new resolved method     */
128         codeinfo   *code;
129
130         /* If the method is not an instance method, just return it. */
131
132         if (m->flags & ACC_STATIC)
133                 return m;
134
135         assert(vftbl);
136
137         /* Get the method from the virtual function table.  Is this an
138            interface method? */
139
140         if (m->class->flags & ACC_INTERFACE) {
141                 pmptr = vftbl->interfacetable[-(m->class->index)];
142                 mptr  = pmptr[(m - m->class->methods)];
143         }
144         else {
145                 mptr = vftbl->table[m->vftblindex];
146         }
147
148         /* and now get the codeinfo pointer from the first data segment slot */
149
150         code = *((codeinfo **) (mptr + CodeinfoPointer));
151
152         resm = code->m;
153
154         return resm;
155 }
156
157
158 /* method_add_to_worklist ******************************************************
159
160    Add the method to the given worklist. If the method already occurs in
161    the worklist, the worklist remains unchanged.
162
163 *******************************************************************************/
164
165 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
166 {
167         method_worklist *wi;
168
169         for (wi = *wl; wi != NULL; wi = wi->next)
170                 if (wi->m == m)
171                         return;
172
173         wi = NEW(method_worklist);
174         wi->next = *wl;
175         wi->m = m;
176
177         *wl = wi;
178 }
179
180
181 /* method_add_assumption_monomorphic *******************************************
182
183    Record the assumption that the method is monomorphic.
184
185    IN:
186       m.................the method
187           caller............the caller making the assumption
188
189 *******************************************************************************/
190
191 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
192 {
193         method_assumption *as;
194
195         /* XXX LOCKING FOR THIS FUNCTION? */
196
197         /* check if we already have registered this assumption */
198
199         for (as = m->assumptions; as != NULL; as = as->next) {
200                 if (as->context == caller)
201                         return;
202         }
203
204         /* register the assumption */
205
206         as = NEW(method_assumption);
207         as->next = m->assumptions;
208         as->context = caller;
209
210         m->assumptions = as;
211 }
212
213
214 /* method_break_assumption_monomorphic *****************************************
215
216    Break the assumption that this method is monomorphic. All callers that
217    have registered this assumption are added to the worklist.
218
219    IN:
220       m.................the method
221           wl................worklist where to add invalidated callers
222
223 *******************************************************************************/
224
225 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
226 {
227         method_assumption *as;
228
229         /* XXX LOCKING FOR THIS FUNCTION? */
230
231         for (as = m->assumptions; as != NULL; as = as->next) {
232                 INLINELOG(
233                         printf("ASSUMPTION BROKEN (monomorphism): ");
234                         method_print(m);
235                         printf(" in ");
236                         method_println(as->context);
237                 );
238
239                 method_add_to_worklist(as->context, wl);
240         }
241 }
242
243
244 /* method_printflags ***********************************************************
245
246    Prints the flags of a method to stdout like.
247
248 *******************************************************************************/
249
250 #if !defined(NDEBUG)
251 void method_printflags(methodinfo *m)
252 {
253         if (m == NULL) {
254                 printf("NULL");
255                 return;
256         }
257
258         if (m->flags & ACC_PUBLIC)       printf(" PUBLIC");
259         if (m->flags & ACC_PRIVATE)      printf(" PRIVATE");
260         if (m->flags & ACC_PROTECTED)    printf(" PROTECTED");
261         if (m->flags & ACC_STATIC)       printf(" STATIC");
262         if (m->flags & ACC_FINAL)        printf(" FINAL");
263         if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
264         if (m->flags & ACC_VOLATILE)     printf(" VOLATILE");
265         if (m->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
266         if (m->flags & ACC_NATIVE)       printf(" NATIVE");
267         if (m->flags & ACC_INTERFACE)    printf(" INTERFACE");
268         if (m->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
269 }
270 #endif /* !defined(NDEBUG) */
271
272
273 /* method_print ****************************************************************
274
275    Prints a method to stdout like:
276
277    java.lang.Object.<init>()V
278
279 *******************************************************************************/
280
281 #if !defined(NDEBUG)
282 void method_print(methodinfo *m)
283 {
284         if (m == NULL) {
285                 printf("NULL");
286                 return;
287         }
288
289         utf_display_printable_ascii_classname(m->class->name);
290         printf(".");
291         utf_display_printable_ascii(m->name);
292         utf_display_printable_ascii(m->descriptor);
293
294         method_printflags(m);
295 }
296 #endif /* !defined(NDEBUG) */
297
298
299 /* method_println **************************************************************
300
301    Prints a method plus new line to stdout like:
302
303    java.lang.Object.<init>()V
304
305 *******************************************************************************/
306
307 #if !defined(NDEBUG)
308 void method_println(methodinfo *m)
309 {
310         if (opt_debugcolor) printf("\033[31m"); /* red */
311         method_print(m);
312         if (opt_debugcolor) printf("\033[m");   
313         printf("\n");
314 }
315 #endif /* !defined(NDEBUG) */
316
317
318 /* method_methodref_print ******************************************************
319
320    Prints a method reference to stdout.
321
322 *******************************************************************************/
323
324 #if !defined(NDEBUG)
325 void method_methodref_print(constant_FMIref *mr)
326 {
327         if (!mr) {
328                 printf("(constant_FMIref *)NULL");
329                 return;
330         }
331
332         if (IS_FMIREF_RESOLVED(mr)) {
333                 printf("<method> ");
334                 method_print(mr->p.method);
335         }
336         else {
337                 printf("<methodref> ");
338                 utf_display_printable_ascii_classname(mr->p.classref->name);
339                 printf(".");
340                 utf_display_printable_ascii(mr->name);
341                 utf_display_printable_ascii(mr->descriptor);
342         }
343 }
344 #endif /* !defined(NDEBUG) */
345
346
347 /* method_methodref_println ****************************************************
348
349    Prints a method reference to stdout, followed by a newline.
350
351 *******************************************************************************/
352
353 #if !defined(NDEBUG)
354 void method_methodref_println(constant_FMIref *mr)
355 {
356         method_methodref_print(mr);
357         printf("\n");
358 }
359 #endif /* !defined(NDEBUG) */
360
361
362 /*
363  * These are local overrides for various environment variables in Emacs.
364  * Please do not remove this and leave it at the end of the file, where
365  * Emacs will automagically detect them.
366  * ---------------------------------------------------------------------
367  * Local variables:
368  * mode: c
369  * indent-tabs-mode: t
370  * c-basic-offset: 4
371  * tab-width: 4
372  * End:
373  * vim:noexpandtab:sw=4:ts=4:
374  */