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