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