* src/native/vm/reflect.c
[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 8315 2007-08-15 22:49:20Z panzi $
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 java_bytearray *method_get_annotations(methodinfo *m)
785 {
786         classinfo              *c           = m->class;
787         int                     slot        = m - c->methods;
788         annotation_bytearray_t *ba          = NULL;
789         java_bytearray         *annotations = NULL;
790         
791         if (c->method_annotations != NULL && c->method_annotations->size > slot) {
792                 ba = c->method_annotations->data[slot];
793                 
794                 if (ba != NULL) {
795                         annotations = builtin_newarray_byte(ba->size);
796                         
797                         if (annotations != NULL) {
798                                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
799                         }
800                 }
801         }
802         
803         return annotations;
804 }
805
806
807 /* method_get_parameterannotations ********************************************
808
809    Gets a methods' parameter annotations (or NULL if none).
810
811 *******************************************************************************/
812
813 java_bytearray *method_get_parameterannotations(methodinfo *m)
814 {
815         classinfo              *c                    = m->class;
816         int                     slot                 = m - c->methods;
817         annotation_bytearray_t *ba                   = NULL;
818         java_bytearray         *parameterAnnotations = NULL;
819
820         if (c->method_parameterannotations != NULL &&
821                 c->method_parameterannotations->size > slot) {
822                 ba = c->method_parameterannotations->data[slot];
823                 
824                 if (ba != NULL) {
825                         parameterAnnotations = builtin_newarray_byte(ba->size);
826                         
827                         if (parameterAnnotations != NULL) {
828                                 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
829                         }
830                 }
831         }
832         
833         return parameterAnnotations;
834 }
835
836
837 /* method_get_annotationdefault ***********************************************
838
839    Gets a methods' annotation default value (or NULL if none).
840
841 *******************************************************************************/
842
843 java_bytearray *method_get_annotationdefault(methodinfo *m)
844 {
845         classinfo              *c                 = m->class;
846         int                     slot              = m - c->methods;
847         annotation_bytearray_t *ba                = NULL;
848         java_bytearray         *annotationDefault = NULL;
849
850         if (c->method_annotationdefaults != NULL &&
851                 c->method_annotationdefaults->size > slot) {
852                 ba = c->method_annotationdefaults->data[slot];
853                 
854                 if (ba != NULL) {
855                         annotationDefault = builtin_newarray_byte(ba->size);
856                         
857                         if (annotationDefault != NULL) {
858                                 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
859                         }
860                 }
861         }
862         
863         return annotationDefault;
864 }
865 #endif
866
867
868 /* method_add_to_worklist ******************************************************
869
870    Add the method to the given worklist. If the method already occurs in
871    the worklist, the worklist remains unchanged.
872
873 *******************************************************************************/
874
875 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
876 {
877         method_worklist *wi;
878
879         for (wi = *wl; wi != NULL; wi = wi->next)
880                 if (wi->m == m)
881                         return;
882
883         wi = NEW(method_worklist);
884         wi->next = *wl;
885         wi->m = m;
886
887         *wl = wi;
888 }
889
890
891 /* method_add_assumption_monomorphic *******************************************
892
893    Record the assumption that the method is monomorphic.
894
895    IN:
896       m.................the method
897           caller............the caller making the assumption
898
899 *******************************************************************************/
900
901 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
902 {
903         method_assumption *as;
904
905         /* XXX LOCKING FOR THIS FUNCTION? */
906
907         /* check if we already have registered this assumption */
908
909         for (as = m->assumptions; as != NULL; as = as->next) {
910                 if (as->context == caller)
911                         return;
912         }
913
914         /* register the assumption */
915
916         as = NEW(method_assumption);
917         as->next = m->assumptions;
918         as->context = caller;
919
920         m->assumptions = as;
921 }
922
923
924 /* method_break_assumption_monomorphic *****************************************
925
926    Break the assumption that this method is monomorphic. All callers that
927    have registered this assumption are added to the worklist.
928
929    IN:
930       m.................the method
931           wl................worklist where to add invalidated callers
932
933 *******************************************************************************/
934
935 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
936 {
937         method_assumption *as;
938
939         /* XXX LOCKING FOR THIS FUNCTION? */
940
941         for (as = m->assumptions; as != NULL; as = as->next) {
942                 INLINELOG(
943                         printf("ASSUMPTION BROKEN (monomorphism): ");
944                         method_print(m);
945                         printf(" in ");
946                         method_println(as->context);
947                 );
948
949                 method_add_to_worklist(as->context, wl);
950         }
951 }
952
953
954 /* method_printflags ***********************************************************
955
956    Prints the flags of a method to stdout like.
957
958 *******************************************************************************/
959
960 #if !defined(NDEBUG)
961 void method_printflags(methodinfo *m)
962 {
963         if (m == NULL) {
964                 printf("NULL");
965                 return;
966         }
967
968         if (m->flags & ACC_PUBLIC)       printf(" PUBLIC");
969         if (m->flags & ACC_PRIVATE)      printf(" PRIVATE");
970         if (m->flags & ACC_PROTECTED)    printf(" PROTECTED");
971         if (m->flags & ACC_STATIC)       printf(" STATIC");
972         if (m->flags & ACC_FINAL)        printf(" FINAL");
973         if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
974         if (m->flags & ACC_VOLATILE)     printf(" VOLATILE");
975         if (m->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
976         if (m->flags & ACC_NATIVE)       printf(" NATIVE");
977         if (m->flags & ACC_INTERFACE)    printf(" INTERFACE");
978         if (m->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
979         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
980         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
981 }
982 #endif /* !defined(NDEBUG) */
983
984
985 /* method_print ****************************************************************
986
987    Prints a method to stdout like:
988
989    java.lang.Object.<init>()V
990
991 *******************************************************************************/
992
993 #if !defined(NDEBUG)
994 void method_print(methodinfo *m)
995 {
996         if (m == NULL) {
997                 printf("NULL");
998                 return;
999         }
1000
1001         utf_display_printable_ascii_classname(m->class->name);
1002         printf(".");
1003         utf_display_printable_ascii(m->name);
1004         utf_display_printable_ascii(m->descriptor);
1005
1006         method_printflags(m);
1007 }
1008 #endif /* !defined(NDEBUG) */
1009
1010
1011 /* method_println **************************************************************
1012
1013    Prints a method plus new line to stdout like:
1014
1015    java.lang.Object.<init>()V
1016
1017 *******************************************************************************/
1018
1019 #if !defined(NDEBUG)
1020 void method_println(methodinfo *m)
1021 {
1022         if (opt_debugcolor) printf("\033[31m"); /* red */
1023         method_print(m);
1024         if (opt_debugcolor) printf("\033[m");   
1025         printf("\n");
1026 }
1027 #endif /* !defined(NDEBUG) */
1028
1029
1030 /* method_methodref_print ******************************************************
1031
1032    Prints a method reference to stdout.
1033
1034 *******************************************************************************/
1035
1036 #if !defined(NDEBUG)
1037 void method_methodref_print(constant_FMIref *mr)
1038 {
1039         if (!mr) {
1040                 printf("(constant_FMIref *)NULL");
1041                 return;
1042         }
1043
1044         if (IS_FMIREF_RESOLVED(mr)) {
1045                 printf("<method> ");
1046                 method_print(mr->p.method);
1047         }
1048         else {
1049                 printf("<methodref> ");
1050                 utf_display_printable_ascii_classname(mr->p.classref->name);
1051                 printf(".");
1052                 utf_display_printable_ascii(mr->name);
1053                 utf_display_printable_ascii(mr->descriptor);
1054         }
1055 }
1056 #endif /* !defined(NDEBUG) */
1057
1058
1059 /* method_methodref_println ****************************************************
1060
1061    Prints a method reference to stdout, followed by a newline.
1062
1063 *******************************************************************************/
1064
1065 #if !defined(NDEBUG)
1066 void method_methodref_println(constant_FMIref *mr)
1067 {
1068         method_methodref_print(mr);
1069         printf("\n");
1070 }
1071 #endif /* !defined(NDEBUG) */
1072
1073
1074 /*
1075  * These are local overrides for various environment variables in Emacs.
1076  * Please do not remove this and leave it at the end of the file, where
1077  * Emacs will automagically detect them.
1078  * ---------------------------------------------------------------------
1079  * Local variables:
1080  * mode: c
1081  * indent-tabs-mode: t
1082  * c-basic-offset: 4
1083  * tab-width: 4
1084  * End:
1085  * vim:noexpandtab:sw=4:ts=4:
1086  */