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