* src/vm/global.h (java_handle_t): Added typedef.
[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 8295 2007-08-11 17:57:24Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <stdio.h>
35
36 #include "vm/types.h"
37
38 #include "mm/memory.h"
39
40 #include "threads/lock-common.h"
41
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/global.h"
45 #include "vm/resolve.h"
46
47 #include "vm/jit/methodheader.h"
48
49 #include "vm/jit_interface.h"
50
51 #include "vmcore/class.h"
52 #include "vmcore/linker.h"
53 #include "vmcore/loader.h"
54 #include "vmcore/method.h"
55 #include "vmcore/options.h"
56 #include "vmcore/suck.h"
57
58
59 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
60 #define INLINELOG(code)  do { if (opt_inline_debug_log) { code } } while (0)
61 #else
62 #define INLINELOG(code)
63 #endif
64
65
66 /* method_load *****************************************************************
67
68    Loads a method from the class file and fills an existing methodinfo
69    structure.
70
71    method_info {
72        u2 access_flags;
73            u2 name_index;
74            u2 descriptor_index;
75            u2 attributes_count;
76            attribute_info attributes[attribute_count];
77    }
78
79    attribute_info {
80        u2 attribute_name_index;
81            u4 attribute_length;
82            u1 info[attribute_length];
83    }
84
85    LineNumberTable_attribute {
86        u2 attribute_name_index;
87            u4 attribute_length;
88            u2 line_number_table_length;
89            {
90                u2 start_pc;
91                    u2 line_number;
92            } line_number_table[line_number_table_length];
93    }
94
95 *******************************************************************************/
96
97 bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
98 {
99         classinfo *c;
100         int argcount;
101         s4         i, j, k, l;
102         utf       *u;
103         u2         name_index;
104         u2         descriptor_index;
105         u2         attributes_count;
106         u2         attribute_name_index;
107         utf       *attribute_name;
108         u2         code_attributes_count;
109         u2         code_attribute_name_index;
110         utf       *code_attribute_name;
111
112         /* get classinfo */
113
114         c = cb->class;
115
116         LOCK_INIT_OBJECT_LOCK(&(m->header));
117
118 #if defined(ENABLE_STATISTICS)
119         if (opt_stat)
120                 count_all_methods++;
121 #endif
122
123         /* all fields of m have been zeroed in load_class_from_classbuffer */
124
125         m->class = c;
126         
127         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
128                 return false;
129
130         /* access flags */
131
132         m->flags = suck_u2(cb);
133
134         /* name */
135
136         name_index = suck_u2(cb);
137
138         if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
139                 return false;
140
141         m->name = u;
142
143         /* descriptor */
144
145         descriptor_index = suck_u2(cb);
146
147         if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
148                 return false;
149
150         m->descriptor = u;
151
152         if (!descriptor_pool_add(descpool, u, &argcount))
153                 return false;
154
155 #ifdef ENABLE_VERIFIER
156         if (opt_verify) {
157                 if (!is_valid_name_utf(m->name)) {
158                         exceptions_throw_classformaterror(c, "Method with invalid name");
159                         return false;
160                 }
161
162                 if (m->name->text[0] == '<' &&
163                         m->name != utf_init && m->name != utf_clinit) {
164                         exceptions_throw_classformaterror(c, "Method with invalid special name");
165                         return false;
166                 }
167         }
168 #endif /* ENABLE_VERIFIER */
169         
170         if (!(m->flags & ACC_STATIC))
171                 argcount++; /* count the 'this' argument */
172
173 #ifdef ENABLE_VERIFIER
174         if (opt_verify) {
175                 if (argcount > 255) {
176                         exceptions_throw_classformaterror(c, "Too many arguments in signature");
177                         return false;
178                 }
179
180                 /* check flag consistency */
181                 if (m->name != utf_clinit) {
182                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
183
184                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
185                                 exceptions_throw_classformaterror(c,
186                                                                                                   "Illegal method modifiers: 0x%X",
187                                                                                                   m->flags);
188                                 return false;
189                         }
190
191                         if (m->flags & ACC_ABSTRACT) {
192                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
193                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
194                                         exceptions_throw_classformaterror(c,
195                                                                                                           "Illegal method modifiers: 0x%X",
196                                                                                                           m->flags);
197                                         return false;
198                                 }
199                         }
200
201                         if (c->flags & ACC_INTERFACE) {
202                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
203                                         exceptions_throw_classformaterror(c,
204                                                                                                           "Illegal method modifiers: 0x%X",
205                                                                                                           m->flags);
206                                         return false;
207                                 }
208                         }
209
210                         if (m->name == utf_init) {
211                                 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
212                                                                 ACC_NATIVE | ACC_ABSTRACT)) {
213                                         exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
214                                         return false;
215                                 }
216                         }
217                 }
218         }
219 #endif /* ENABLE_VERIFIER */
220
221         /* mark the method as monomorphic until further notice */
222
223         m->flags |= ACC_METHOD_MONOMORPHIC;
224
225         /* non-abstract methods have an implementation in this class */
226
227         if (!(m->flags & ACC_ABSTRACT))
228                 m->flags |= ACC_METHOD_IMPLEMENTED;
229                 
230         if (!suck_check_classbuffer_size(cb, 2))
231                 return false;
232
233         /* attributes count */
234
235         attributes_count = suck_u2(cb);
236
237         for (i = 0; i < attributes_count; i++) {
238                 if (!suck_check_classbuffer_size(cb, 2))
239                         return false;
240
241                 /* attribute name index */
242
243                 attribute_name_index = suck_u2(cb);
244
245                 attribute_name =
246                         class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
247
248                 if (attribute_name == NULL)
249                         return false;
250
251                 if (attribute_name == utf_Code) {
252                         /* Code */
253
254                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
255                                 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
256                                 return false;
257                         }
258                         
259                         if (m->jcode) {
260                                 exceptions_throw_classformaterror(c, "Multiple Code attributes");
261                                 return false;
262                         }
263
264                         if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
265                                 return false;
266
267                         suck_u4(cb);
268                         m->maxstack = suck_u2(cb);
269                         m->maxlocals = suck_u2(cb);
270
271                         if (m->maxlocals < argcount) {
272                                 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
273                                 return false;
274                         }
275                         
276                         if (!suck_check_classbuffer_size(cb, 4))
277                                 return false;
278
279                         m->jcodelength = suck_u4(cb);
280
281                         if (m->jcodelength == 0) {
282                                 exceptions_throw_classformaterror(c, "Code of a method has length 0");
283                                 return false;
284                         }
285                         
286                         if (m->jcodelength > 65535) {
287                                 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
288                                 return false;
289                         }
290
291                         if (!suck_check_classbuffer_size(cb, m->jcodelength))
292                                 return false;
293
294                         m->jcode = MNEW(u1, m->jcodelength);
295                         suck_nbytes(m->jcode, cb, m->jcodelength);
296
297                         if (!suck_check_classbuffer_size(cb, 2))
298                                 return false;
299
300                         m->rawexceptiontablelength = suck_u2(cb);
301                         if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
302                                 return false;
303
304                         m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
305
306 #if defined(ENABLE_STATISTICS)
307                         if (opt_stat) {
308                                 count_vmcode_len += m->jcodelength + 18;
309                                 count_extable_len +=
310                                         m->rawexceptiontablelength * sizeof(raw_exception_entry);
311                         }
312 #endif
313
314                         for (j = 0; j < m->rawexceptiontablelength; j++) {
315                                 u4 idx;
316                                 m->rawexceptiontable[j].startpc   = suck_u2(cb);
317                                 m->rawexceptiontable[j].endpc     = suck_u2(cb);
318                                 m->rawexceptiontable[j].handlerpc = suck_u2(cb);
319
320                                 idx = suck_u2(cb);
321
322                                 if (!idx) {
323                                         m->rawexceptiontable[j].catchtype.any = NULL;
324                                 }
325                                 else {
326                                         /* the classref is created later */
327                                         if (!(m->rawexceptiontable[j].catchtype.any =
328                                                   (utf *) class_getconstant(c, idx, CONSTANT_Class)))
329                                                 return false;
330                                 }
331                         }
332
333                         if (!suck_check_classbuffer_size(cb, 2))
334                                 return false;
335
336                         /* code attributes count */
337
338                         code_attributes_count = suck_u2(cb);
339
340                         for (k = 0; k < code_attributes_count; k++) {
341                                 if (!suck_check_classbuffer_size(cb, 2))
342                                         return false;
343
344                                 /* code attribute name index */
345
346                                 code_attribute_name_index = suck_u2(cb);
347
348                                 code_attribute_name =
349                                         class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
350
351                                 if (code_attribute_name == NULL)
352                                         return false;
353
354                                 /* check which code attribute */
355
356                                 if (code_attribute_name == utf_LineNumberTable) {
357                                         /* LineNumberTable */
358
359                                         if (!suck_check_classbuffer_size(cb, 4 + 2))
360                                                 return false;
361
362                                         /* attribute length */
363
364                                         (void) suck_u4(cb);
365
366                                         /* line number table length */
367
368                                         m->linenumbercount = suck_u2(cb);
369
370                                         if (!suck_check_classbuffer_size(cb,
371                                                                                                 (2 + 2) * m->linenumbercount))
372                                                 return false;
373
374                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
375
376 #if defined(ENABLE_STATISTICS)
377                                         if (opt_stat)
378                                                 size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
379 #endif
380                                         
381                                         for (l = 0; l < m->linenumbercount; l++) {
382                                                 m->linenumbers[l].start_pc    = suck_u2(cb);
383                                                 m->linenumbers[l].line_number = suck_u2(cb);
384                                         }
385                                 }
386 #if defined(ENABLE_JAVASE)
387                                 else if (code_attribute_name == utf_StackMapTable) {
388                                         /* StackTableMap */
389
390                                         if (!stackmap_load_attribute_stackmaptable(cb, m))
391                                                 return false;
392                                 }
393 #endif
394                                 else {
395                                         /* unknown code attribute */
396
397                                         if (!loader_skip_attribute_body(cb))
398                                                 return false;
399                                 }
400                         }
401                 }
402                 else if (attribute_name == utf_Exceptions) {
403                         /* Exceptions */
404
405                         if (m->thrownexceptions != NULL) {
406                                 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
407                                 return false;
408                         }
409
410                         if (!suck_check_classbuffer_size(cb, 4 + 2))
411                                 return false;
412
413                         /* attribute length */
414
415                         (void) suck_u4(cb);
416
417                         m->thrownexceptionscount = suck_u2(cb);
418
419                         if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
420                                 return false;
421
422                         m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
423
424                         for (j = 0; j < m->thrownexceptionscount; j++) {
425                                 /* the classref is created later */
426                                 if (!((m->thrownexceptions)[j].any =
427                                           (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
428                                         return false;
429                         }
430                 }
431 #if defined(ENABLE_JAVASE)
432                 else if (attribute_name == utf_Signature) {
433                         /* Signature */
434
435                         if (!loader_load_attribute_signature(cb, &(m->signature)))
436                                 return false;
437                 }
438
439 #if defined(ENABLE_ANNOTATIONS)
440                 else if (attribute_name == utf_RuntimeVisibleAnnotations) {
441                         /* RuntimeVisibleAnnotations */
442                         if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
443                                 return false;
444                 }
445                 else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
446                         /* RuntimeInvisibleAnnotations */
447                         if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
448                                 return false;
449                 }
450                 else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
451                         /* RuntimeVisibleParameterAnnotations */
452                         if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
453                                 return false;
454                 }
455                 else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
456                         /* RuntimeInvisibleParameterAnnotations */
457                         if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
458                                 return false;
459                 }
460                 else if (attribute_name == utf_AnnotationDefault) {
461                         /* AnnotationDefault */
462                         if (!annotation_load_method_attribute_annotationdefault(cb, m))
463                                 return false;
464                 }
465 #endif
466 #endif
467                 else {
468                         /* unknown attribute */
469
470                         if (!loader_skip_attribute_body(cb))
471                                 return false;
472                 }
473         }
474
475         if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
476                 exceptions_throw_classformaterror(c, "Missing Code attribute");
477                 return false;
478         }
479
480 #if defined(ENABLE_REPLACEMENT)
481         /* initialize the hit countdown field */
482
483         m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
484 #endif
485
486         /* everything was ok */
487
488         return true;
489 }
490
491
492 /* method_free *****************************************************************
493
494    Frees all memory that was allocated for this method.
495
496 *******************************************************************************/
497
498 void method_free(methodinfo *m)
499 {
500         if (m->jcode)
501                 MFREE(m->jcode, u1, m->jcodelength);
502
503         if (m->rawexceptiontable)
504                 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
505
506         code_free_code_of_method(m);
507
508         if (m->stubroutine) {
509                 if (m->flags & ACC_NATIVE) {
510                         removenativestub(m->stubroutine);
511
512                 } else {
513                         removecompilerstub(m->stubroutine);
514                 }
515         }
516 }
517
518
519 /* method_canoverwrite *********************************************************
520
521    Check if m and old are identical with respect to type and
522    name. This means that old can be overwritten with m.
523         
524 *******************************************************************************/
525
526 bool method_canoverwrite(methodinfo *m, methodinfo *old)
527 {
528         if (m->name != old->name)
529                 return false;
530
531         if (m->descriptor != old->descriptor)
532                 return false;
533
534         if (m->flags & ACC_STATIC)
535                 return false;
536
537         return true;
538 }
539
540
541 /* method_vftbl_lookup *********************************************************
542
543    Does a method lookup in the passed virtual function table.  This
544    function does exactly the same thing as JIT, but additionally
545    relies on the fact, that the methodinfo pointer is at the first
546    data segment slot (even for compiler stubs).
547
548 *******************************************************************************/
549
550 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
551 {
552         methodptr   mptr;
553         methodptr  *pmptr;
554         methodinfo *resm;                   /* pointer to new resolved method     */
555
556         /* If the method is not an instance method, just return it. */
557
558         if (m->flags & ACC_STATIC)
559                 return m;
560
561         assert(vftbl);
562
563         /* Get the method from the virtual function table.  Is this an
564            interface method? */
565
566         if (m->class->flags & ACC_INTERFACE) {
567                 pmptr = vftbl->interfacetable[-(m->class->index)];
568                 mptr  = pmptr[(m - m->class->methods)];
569         }
570         else {
571                 mptr = vftbl->table[m->vftblindex];
572         }
573
574         /* and now get the codeinfo pointer from the first data segment slot */
575
576         resm = code_get_methodinfo_for_pv(mptr);
577
578         return resm;
579 }
580
581
582 /* method_get_parametercount **************************************************
583
584    Use the descriptor of a method to determine the number of parameters
585    of the method. The this pointer of non-static methods is not counted.
586
587    Returns -1 on error.
588
589 *******************************************************************************/
590
591 int32_t method_get_parametercount(methodinfo *m)
592 {
593         methoddesc *md;
594         int32_t     paramcount = 0;
595
596         md = m->parseddesc;
597         
598         /* is the descriptor fully parsed? */
599
600         if (m->parseddesc->params == NULL) {
601                 if (!descriptor_params_from_paramtypes(md, m->flags)) {
602                         return -1;
603                 }
604         }
605
606         paramcount = md->paramcount;
607
608         /* skip `this' pointer */
609
610         if (!(m->flags & ACC_STATIC)) {
611                 --paramcount;
612         }
613
614         return paramcount;
615 }
616
617
618 /* method_get_parametertypearray ***********************************************
619
620    Use the descriptor of a method to generate a java.lang.Class array
621    which contains the classes of the parametertypes of the method.
622
623    This function is called by java.lang.reflect.{Constructor,Method}.
624
625 *******************************************************************************/
626
627 java_objectarray *method_get_parametertypearray(methodinfo *m)
628 {
629         methoddesc       *md;
630         typedesc         *paramtypes;
631         int32_t           paramcount;
632         java_objectarray *oa;
633         int32_t           i;
634         classinfo        *c;
635
636         md = m->parseddesc;
637
638         /* is the descriptor fully parsed? */
639
640         if (m->parseddesc->params == NULL)
641                 if (!descriptor_params_from_paramtypes(md, m->flags))
642                         return NULL;
643
644         paramtypes = md->paramtypes;
645         paramcount = md->paramcount;
646
647         /* skip `this' pointer */
648
649         if (!(m->flags & ACC_STATIC)) {
650                 paramtypes++;
651                 paramcount--;
652         }
653
654         /* create class-array */
655
656         oa = builtin_anewarray(paramcount, class_java_lang_Class);
657
658         if (oa == NULL)
659                 return NULL;
660
661     /* get classes */
662
663         for (i = 0; i < paramcount; i++) {
664                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
665                         return NULL;
666
667                 oa->data[i] = c;
668         }
669
670         return oa;
671 }
672
673
674 /* method_get_exceptionarray ***************************************************
675
676    Get the exceptions which can be thrown by a method.
677
678 *******************************************************************************/
679
680 java_objectarray *method_get_exceptionarray(methodinfo *m)
681 {
682         java_objectarray *oa;
683         classinfo        *c;
684         s4                i;
685
686         /* create class-array */
687
688         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
689
690         if (oa == NULL)
691                 return NULL;
692
693         /* iterate over all exceptions and store the class in the array */
694
695         for (i = 0; i < m->thrownexceptionscount; i++) {
696                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
697
698                 if (c == NULL)
699                         return NULL;
700
701                 oa->data[i] = c;
702         }
703
704         return oa;
705 }
706
707
708 /* method_returntype_get *******************************************************
709
710    Get the return type of the method.
711
712 *******************************************************************************/
713
714 classinfo *method_returntype_get(methodinfo *m)
715 {
716         typedesc  *td;
717         classinfo *c;
718
719         td = &(m->parseddesc->returntype);
720
721         if (!resolve_class_from_typedesc(td, true, false, &c))
722                 return NULL;
723
724         return c;
725 }
726
727
728 /* method_count_implementations ************************************************
729
730    Count the implementations of a method in a class cone (a class and all its
731    subclasses.)
732
733    IN:
734        m................the method to count
735            c................class at which to start the counting (this class and
736                             all its subclasses will be searched)
737
738    OUT:
739        *found...........if found != NULL, *found receives the method
740                             implementation that was found. This value is only
741                                                 meaningful if the return value is 1.
742
743    RETURN VALUE:
744        the number of implementations found
745
746 *******************************************************************************/
747
748 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
749 {
750         s4          count;
751         methodinfo *mp;
752         methodinfo *mend;
753         classinfo  *child;
754
755         count = 0;
756
757         mp = c->methods;
758         mend = mp + c->methodscount;
759
760         for (; mp < mend; ++mp) {
761                 if (method_canoverwrite(mp, m)) {
762                         if (found)
763                                 *found = mp;
764                         count++;
765                         break;
766                 }
767         }
768
769         for (child = c->sub; child != NULL; child = child->nextsub) {
770                 count += method_count_implementations(m, child, found);
771         }
772
773         return count;
774 }
775
776
777 #if defined(ENABLE_ANNOTATIONS)
778 /* method_get_annotations ******************************************************
779
780    Gets a methods' annotations (or NULL if none).
781
782 *******************************************************************************/
783
784 annotation_bytearray_t *method_get_annotations(methodinfo *m)
785 {
786         classinfo *c = m->class;
787         int slot = m - c->methods;
788
789         if (c->method_annotations != NULL && c->method_annotations->size > slot) {
790                 return c->method_annotations->data[slot];
791         }
792
793         return NULL;
794 }
795
796
797 /* method_get_parameterannotations ********************************************
798
799    Gets a methods' parameter annotations (or NULL if none).
800
801 *******************************************************************************/
802
803 annotation_bytearray_t *method_get_parameterannotations(methodinfo *m)
804 {
805         classinfo *c = m->class;
806         int slot = m - c->methods;
807
808         if (c->method_parameterannotations != NULL &&
809                 c->method_parameterannotations->size > slot) {
810                 return c->method_parameterannotations->data[slot];
811         }
812
813         return NULL;
814 }
815
816
817 /* method_get_annotationdefault ***********************************************
818
819    Gets a methods' annotation default value (or NULL if none).
820
821 *******************************************************************************/
822
823 annotation_bytearray_t *method_get_annotationdefault(methodinfo *m)
824 {
825         classinfo *c = m->class;
826         int slot = m - c->methods;
827
828         if (c->method_annotationdefaults != NULL &&
829                 c->method_annotationdefaults->size > slot) {
830                 return c->method_annotationdefaults->data[slot];
831         }
832
833         return NULL;
834 }
835 #endif
836
837
838 /* method_add_to_worklist ******************************************************
839
840    Add the method to the given worklist. If the method already occurs in
841    the worklist, the worklist remains unchanged.
842
843 *******************************************************************************/
844
845 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
846 {
847         method_worklist *wi;
848
849         for (wi = *wl; wi != NULL; wi = wi->next)
850                 if (wi->m == m)
851                         return;
852
853         wi = NEW(method_worklist);
854         wi->next = *wl;
855         wi->m = m;
856
857         *wl = wi;
858 }
859
860
861 /* method_add_assumption_monomorphic *******************************************
862
863    Record the assumption that the method is monomorphic.
864
865    IN:
866       m.................the method
867           caller............the caller making the assumption
868
869 *******************************************************************************/
870
871 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
872 {
873         method_assumption *as;
874
875         /* XXX LOCKING FOR THIS FUNCTION? */
876
877         /* check if we already have registered this assumption */
878
879         for (as = m->assumptions; as != NULL; as = as->next) {
880                 if (as->context == caller)
881                         return;
882         }
883
884         /* register the assumption */
885
886         as = NEW(method_assumption);
887         as->next = m->assumptions;
888         as->context = caller;
889
890         m->assumptions = as;
891 }
892
893
894 /* method_break_assumption_monomorphic *****************************************
895
896    Break the assumption that this method is monomorphic. All callers that
897    have registered this assumption are added to the worklist.
898
899    IN:
900       m.................the method
901           wl................worklist where to add invalidated callers
902
903 *******************************************************************************/
904
905 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
906 {
907         method_assumption *as;
908
909         /* XXX LOCKING FOR THIS FUNCTION? */
910
911         for (as = m->assumptions; as != NULL; as = as->next) {
912                 INLINELOG(
913                         printf("ASSUMPTION BROKEN (monomorphism): ");
914                         method_print(m);
915                         printf(" in ");
916                         method_println(as->context);
917                 );
918
919                 method_add_to_worklist(as->context, wl);
920         }
921 }
922
923
924 /* method_printflags ***********************************************************
925
926    Prints the flags of a method to stdout like.
927
928 *******************************************************************************/
929
930 #if !defined(NDEBUG)
931 void method_printflags(methodinfo *m)
932 {
933         if (m == NULL) {
934                 printf("NULL");
935                 return;
936         }
937
938         if (m->flags & ACC_PUBLIC)       printf(" PUBLIC");
939         if (m->flags & ACC_PRIVATE)      printf(" PRIVATE");
940         if (m->flags & ACC_PROTECTED)    printf(" PROTECTED");
941         if (m->flags & ACC_STATIC)       printf(" STATIC");
942         if (m->flags & ACC_FINAL)        printf(" FINAL");
943         if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
944         if (m->flags & ACC_VOLATILE)     printf(" VOLATILE");
945         if (m->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
946         if (m->flags & ACC_NATIVE)       printf(" NATIVE");
947         if (m->flags & ACC_INTERFACE)    printf(" INTERFACE");
948         if (m->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
949         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
950         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
951 }
952 #endif /* !defined(NDEBUG) */
953
954
955 /* method_print ****************************************************************
956
957    Prints a method to stdout like:
958
959    java.lang.Object.<init>()V
960
961 *******************************************************************************/
962
963 #if !defined(NDEBUG)
964 void method_print(methodinfo *m)
965 {
966         if (m == NULL) {
967                 printf("NULL");
968                 return;
969         }
970
971         utf_display_printable_ascii_classname(m->class->name);
972         printf(".");
973         utf_display_printable_ascii(m->name);
974         utf_display_printable_ascii(m->descriptor);
975
976         method_printflags(m);
977 }
978 #endif /* !defined(NDEBUG) */
979
980
981 /* method_println **************************************************************
982
983    Prints a method plus new line to stdout like:
984
985    java.lang.Object.<init>()V
986
987 *******************************************************************************/
988
989 #if !defined(NDEBUG)
990 void method_println(methodinfo *m)
991 {
992         if (opt_debugcolor) printf("\033[31m"); /* red */
993         method_print(m);
994         if (opt_debugcolor) printf("\033[m");   
995         printf("\n");
996 }
997 #endif /* !defined(NDEBUG) */
998
999
1000 /* method_methodref_print ******************************************************
1001
1002    Prints a method reference to stdout.
1003
1004 *******************************************************************************/
1005
1006 #if !defined(NDEBUG)
1007 void method_methodref_print(constant_FMIref *mr)
1008 {
1009         if (!mr) {
1010                 printf("(constant_FMIref *)NULL");
1011                 return;
1012         }
1013
1014         if (IS_FMIREF_RESOLVED(mr)) {
1015                 printf("<method> ");
1016                 method_print(mr->p.method);
1017         }
1018         else {
1019                 printf("<methodref> ");
1020                 utf_display_printable_ascii_classname(mr->p.classref->name);
1021                 printf(".");
1022                 utf_display_printable_ascii(mr->name);
1023                 utf_display_printable_ascii(mr->descriptor);
1024         }
1025 }
1026 #endif /* !defined(NDEBUG) */
1027
1028
1029 /* method_methodref_println ****************************************************
1030
1031    Prints a method reference to stdout, followed by a newline.
1032
1033 *******************************************************************************/
1034
1035 #if !defined(NDEBUG)
1036 void method_methodref_println(constant_FMIref *mr)
1037 {
1038         method_methodref_print(mr);
1039         printf("\n");
1040 }
1041 #endif /* !defined(NDEBUG) */
1042
1043
1044 /*
1045  * These are local overrides for various environment variables in Emacs.
1046  * Please do not remove this and leave it at the end of the file, where
1047  * Emacs will automagically detect them.
1048  * ---------------------------------------------------------------------
1049  * Local variables:
1050  * mode: c
1051  * indent-tabs-mode: t
1052  * c-basic-offset: 4
1053  * tab-width: 4
1054  * End:
1055  * vim:noexpandtab:sw=4:ts=4:
1056  */