* src/vm/jit/replace.c: Only recompile if necessary. Count
[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 5992 2006-11-15 22:46:10Z 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         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
270         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
271 }
272 #endif /* !defined(NDEBUG) */
273
274
275 /* method_print ****************************************************************
276
277    Prints a method to stdout like:
278
279    java.lang.Object.<init>()V
280
281 *******************************************************************************/
282
283 #if !defined(NDEBUG)
284 void method_print(methodinfo *m)
285 {
286         if (m == NULL) {
287                 printf("NULL");
288                 return;
289         }
290
291         utf_display_printable_ascii_classname(m->class->name);
292         printf(".");
293         utf_display_printable_ascii(m->name);
294         utf_display_printable_ascii(m->descriptor);
295
296         method_printflags(m);
297 }
298 #endif /* !defined(NDEBUG) */
299
300
301 /* method_println **************************************************************
302
303    Prints a method plus new line to stdout like:
304
305    java.lang.Object.<init>()V
306
307 *******************************************************************************/
308
309 #if !defined(NDEBUG)
310 void method_println(methodinfo *m)
311 {
312         if (opt_debugcolor) printf("\033[31m"); /* red */
313         method_print(m);
314         if (opt_debugcolor) printf("\033[m");   
315         printf("\n");
316 }
317 #endif /* !defined(NDEBUG) */
318
319
320 /* method_methodref_print ******************************************************
321
322    Prints a method reference to stdout.
323
324 *******************************************************************************/
325
326 #if !defined(NDEBUG)
327 void method_methodref_print(constant_FMIref *mr)
328 {
329         if (!mr) {
330                 printf("(constant_FMIref *)NULL");
331                 return;
332         }
333
334         if (IS_FMIREF_RESOLVED(mr)) {
335                 printf("<method> ");
336                 method_print(mr->p.method);
337         }
338         else {
339                 printf("<methodref> ");
340                 utf_display_printable_ascii_classname(mr->p.classref->name);
341                 printf(".");
342                 utf_display_printable_ascii(mr->name);
343                 utf_display_printable_ascii(mr->descriptor);
344         }
345 }
346 #endif /* !defined(NDEBUG) */
347
348
349 /* method_methodref_println ****************************************************
350
351    Prints a method reference to stdout, followed by a newline.
352
353 *******************************************************************************/
354
355 #if !defined(NDEBUG)
356 void method_methodref_println(constant_FMIref *mr)
357 {
358         method_methodref_print(mr);
359         printf("\n");
360 }
361 #endif /* !defined(NDEBUG) */
362
363
364 /*
365  * These are local overrides for various environment variables in Emacs.
366  * Please do not remove this and leave it at the end of the file, where
367  * Emacs will automagically detect them.
368  * ---------------------------------------------------------------------
369  * Local variables:
370  * mode: c
371  * indent-tabs-mode: t
372  * c-basic-offset: 4
373  * tab-width: 4
374  * End:
375  * vim:noexpandtab:sw=4:ts=4:
376  */