* src/vm/jit/i386/darwin/md-os.c (md_replace_executionstate_read):
[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/array.h"
43 #include "vm/builtin.h"
44 #include "vm/exceptions.h"
45 #include "vm/global.h"
46 #include "vm/resolve.h"
47
48 #include "vm/jit/code.h"
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_TraceInlining) { 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_new_builtin **********************************************************
544
545    Creates a minimal methodinfo structure for builtins. This comes handy
546    when dealing with builtin stubs or stacktraces.
547
548 *******************************************************************************/
549
550 methodinfo *method_new_builtin(builtintable_entry *bte)
551 {
552         methodinfo *m;
553
554         /* allocate the methodinfo structure */
555
556         m = NEW(methodinfo);
557
558         /* initialize methodinfo structure */
559
560         MZERO(m, methodinfo, 1);
561         LOCK_INIT_OBJECT_LOCK(&(m->header));
562
563         m->flags      = ACC_METHOD_BUILTIN;
564         m->parseddesc = bte->md;
565         m->name       = bte->name;
566         m->descriptor = bte->descriptor;
567
568         /* return the newly created methodinfo */
569
570         return m;
571 }
572
573
574 /* method_vftbl_lookup *********************************************************
575
576    Does a method lookup in the passed virtual function table.  This
577    function does exactly the same thing as JIT, but additionally
578    relies on the fact, that the methodinfo pointer is at the first
579    data segment slot (even for compiler stubs).
580
581 *******************************************************************************/
582
583 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
584 {
585         methodptr   mptr;
586         methodptr  *pmptr;
587         methodinfo *resm;                   /* pointer to new resolved method     */
588
589         /* If the method is not an instance method, just return it. */
590
591         if (m->flags & ACC_STATIC)
592                 return m;
593
594         assert(vftbl);
595
596         /* Get the method from the virtual function table.  Is this an
597            interface method? */
598
599         if (m->class->flags & ACC_INTERFACE) {
600                 pmptr = vftbl->interfacetable[-(m->class->index)];
601                 mptr  = pmptr[(m - m->class->methods)];
602         }
603         else {
604                 mptr = vftbl->table[m->vftblindex];
605         }
606
607         /* and now get the codeinfo pointer from the first data segment slot */
608
609         resm = code_get_methodinfo_for_pv(mptr);
610
611         return resm;
612 }
613
614
615 /* method_get_parametercount **************************************************
616
617    Use the descriptor of a method to determine the number of parameters
618    of the method. The this pointer of non-static methods is not counted.
619
620    IN:
621        m........the method of which the parameters should be counted
622
623    RETURN VALUE:
624        The parameter count or -1 on error.
625
626 *******************************************************************************/
627
628 int32_t method_get_parametercount(methodinfo *m)
629 {
630         methoddesc *md;             /* method descriptor of m   */
631         int32_t     paramcount = 0; /* the parameter count of m */
632
633         md = m->parseddesc;
634         
635         /* is the descriptor fully parsed? */
636
637         if (md->params == NULL) {
638                 if (!descriptor_params_from_paramtypes(md, m->flags)) {
639                         return -1;
640                 }
641         }
642
643         paramcount = md->paramcount;
644
645         /* skip `this' pointer */
646
647         if (!(m->flags & ACC_STATIC)) {
648                 --paramcount;
649         }
650
651         return paramcount;
652 }
653
654
655 /* method_get_parametertypearray ***********************************************
656
657    Use the descriptor of a method to generate a java.lang.Class array
658    which contains the classes of the parametertypes of the method.
659
660    This function is called by java.lang.reflect.{Constructor,Method}.
661
662 *******************************************************************************/
663
664 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
665 {
666         methoddesc                *md;
667         typedesc                  *paramtypes;
668         int32_t                    paramcount;
669         java_handle_objectarray_t *oa;
670         int32_t                    i;
671         classinfo                 *c;
672
673         md = m->parseddesc;
674
675         /* is the descriptor fully parsed? */
676
677         if (m->parseddesc->params == NULL)
678                 if (!descriptor_params_from_paramtypes(md, m->flags))
679                         return NULL;
680
681         paramtypes = md->paramtypes;
682         paramcount = md->paramcount;
683
684         /* skip `this' pointer */
685
686         if (!(m->flags & ACC_STATIC)) {
687                 paramtypes++;
688                 paramcount--;
689         }
690
691         /* create class-array */
692
693         oa = builtin_anewarray(paramcount, class_java_lang_Class);
694
695         if (oa == NULL)
696                 return NULL;
697
698     /* get classes */
699
700         for (i = 0; i < paramcount; i++) {
701                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
702                         return NULL;
703
704                 LLNI_array_direct(oa, i) = (java_object_t *) c;
705         }
706
707         return oa;
708 }
709
710
711 /* method_get_exceptionarray ***************************************************
712
713    Get the exceptions which can be thrown by a method.
714
715 *******************************************************************************/
716
717 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
718 {
719         java_handle_objectarray_t *oa;
720         classinfo                 *c;
721         s4                         i;
722
723         /* create class-array */
724
725         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
726
727         if (oa == NULL)
728                 return NULL;
729
730         /* iterate over all exceptions and store the class in the array */
731
732         for (i = 0; i < m->thrownexceptionscount; i++) {
733                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
734
735                 if (c == NULL)
736                         return NULL;
737
738                 LLNI_array_direct(oa, i) = (java_object_t *) c;
739         }
740
741         return oa;
742 }
743
744
745 /* method_returntype_get *******************************************************
746
747    Get the return type of the method.
748
749 *******************************************************************************/
750
751 classinfo *method_returntype_get(methodinfo *m)
752 {
753         typedesc  *td;
754         classinfo *c;
755
756         td = &(m->parseddesc->returntype);
757
758         if (!resolve_class_from_typedesc(td, true, false, &c))
759                 return NULL;
760
761         return c;
762 }
763
764
765 /* method_count_implementations ************************************************
766
767    Count the implementations of a method in a class cone (a class and all its
768    subclasses.)
769
770    IN:
771        m................the method to count
772            c................class at which to start the counting (this class and
773                             all its subclasses will be searched)
774
775    OUT:
776        *found...........if found != NULL, *found receives the method
777                             implementation that was found. This value is only
778                                                 meaningful if the return value is 1.
779
780    RETURN VALUE:
781        the number of implementations found
782
783 *******************************************************************************/
784
785 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
786 {
787         s4          count;
788         methodinfo *mp;
789         methodinfo *mend;
790         classinfo  *child;
791
792         count = 0;
793
794         mp = c->methods;
795         mend = mp + c->methodscount;
796
797         for (; mp < mend; ++mp) {
798                 if (method_canoverwrite(mp, m)) {
799                         if (found)
800                                 *found = mp;
801                         count++;
802                         break;
803                 }
804         }
805
806         for (child = c->sub; child != NULL; child = child->nextsub) {
807                 count += method_count_implementations(m, child, found);
808         }
809
810         return count;
811 }
812
813
814 /* method_get_annotations ******************************************************
815
816    Get a methods' unparsed annotations in a byte array.
817
818    IN:
819        m........the method of which the annotations should be returned
820
821    RETURN VALUE:
822        The unparsed annotations in a byte array (or NULL if there aren't any).
823
824 *******************************************************************************/
825
826 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
827 {
828 #if defined(ENABLE_ANNOTATIONS)
829         classinfo     *c;                  /* methods' declaring class          */
830         int            slot;               /* methods' slot                     */
831         java_handle_t *annotations;        /* methods' unparsed annotations     */
832         java_handle_t *method_annotations; /* all methods' unparsed annotations */
833                                            /* of the declaring class            */
834
835         c           = m->class;
836         slot        = m - c->methods;
837         annotations = NULL;
838
839         LLNI_classinfo_field_get(c, method_annotations, method_annotations);
840
841         /* the method_annotations array might be shorter then the method
842          * count if the methods above a certain index have no annotations.
843          */     
844         if (method_annotations != NULL &&
845                 array_length_get(method_annotations) > slot) {
846                 annotations = array_objectarray_element_get(
847                         (java_handle_objectarray_t*)method_annotations, slot);
848         }
849         
850         return (java_handle_bytearray_t*)annotations;
851 #else
852         return NULL;
853 #endif
854 }
855
856
857 /* method_get_parameterannotations ********************************************
858
859    Get a methods' unparsed parameter annotations in an array of byte
860    arrays.
861
862    IN:
863        m........the method of which the parameter annotations should be
864                     returned
865
866    RETURN VALUE:
867        The unparsed parameter annotations in a byte array (or NULL if
868            there aren't any).
869
870 *******************************************************************************/
871
872 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
873 {
874 #if defined(ENABLE_ANNOTATIONS)
875         classinfo     *c;                           /* methods' declaring class */
876         int            slot;                        /* methods' slot            */
877         java_handle_t *parameterAnnotations;        /* methods' unparsed        */
878                                                     /* parameter annotations    */
879         java_handle_t *method_parameterannotations; /* all methods' unparsed    */
880                                                     /* parameter annotations of */
881                                                     /* the declaring class      */
882
883         c                    = m->class;
884         slot                 = m - c->methods;
885         parameterAnnotations = NULL;
886
887         LLNI_classinfo_field_get(
888                 c, method_parameterannotations, method_parameterannotations);
889
890         /* the method_annotations array might be shorter then the method
891          * count if the methods above a certain index have no annotations.
892          */     
893         if (method_parameterannotations != NULL &&
894                 array_length_get(method_parameterannotations) > slot) {
895                 parameterAnnotations = array_objectarray_element_get(
896                                 (java_handle_objectarray_t*)method_parameterannotations,
897                                 slot);
898         }
899         
900         return (java_handle_bytearray_t*)parameterAnnotations;
901 #else
902         return NULL;
903 #endif
904 }
905
906
907 /* method_get_annotationdefault ***********************************************
908
909    Get a methods' unparsed annotation default value in a byte array.
910    
911    IN:
912        m........the method of which the annotation default value should be
913                     returned
914
915    RETURN VALUE:
916        The unparsed annotation default value in a byte array (or NULL if
917            there isn't one).
918
919 *******************************************************************************/
920
921 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
922 {
923 #if defined(ENABLE_ANNOTATIONS)
924         classinfo     *c;                         /* methods' declaring class     */
925         int            slot;                      /* methods' slot                */
926         java_handle_t *annotationDefault;         /* methods' unparsed            */
927                                                   /* annotation default value     */
928         java_handle_t *method_annotationdefaults; /* all methods' unparsed        */
929                                                   /* annotation default values of */
930                                                   /* the declaring class          */
931
932         c                 = m->class;
933         slot              = m - c->methods;
934         annotationDefault = NULL;
935
936         LLNI_classinfo_field_get(
937                 c, method_annotationdefaults, method_annotationdefaults);
938
939         /* the method_annotations array might be shorter then the method
940          * count if the methods above a certain index have no annotations.
941          */     
942         if (method_annotationdefaults != NULL &&
943                 array_length_get(method_annotationdefaults) > slot) {
944                 annotationDefault = array_objectarray_element_get(
945                                 (java_handle_objectarray_t*)method_annotationdefaults, slot);
946         }
947         
948         return (java_handle_bytearray_t*)annotationDefault;
949 #else
950         return NULL;
951 #endif
952 }
953
954
955 /* method_add_to_worklist ******************************************************
956
957    Add the method to the given worklist. If the method already occurs in
958    the worklist, the worklist remains unchanged.
959
960 *******************************************************************************/
961
962 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
963 {
964         method_worklist *wi;
965
966         for (wi = *wl; wi != NULL; wi = wi->next)
967                 if (wi->m == m)
968                         return;
969
970         wi = NEW(method_worklist);
971         wi->next = *wl;
972         wi->m = m;
973
974         *wl = wi;
975 }
976
977
978 /* method_add_assumption_monomorphic *******************************************
979
980    Record the assumption that the method is monomorphic.
981
982    IN:
983       m.................the method
984           caller............the caller making the assumption
985
986 *******************************************************************************/
987
988 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
989 {
990         method_assumption *as;
991
992         /* XXX LOCKING FOR THIS FUNCTION? */
993
994         /* check if we already have registered this assumption */
995
996         for (as = m->assumptions; as != NULL; as = as->next) {
997                 if (as->context == caller)
998                         return;
999         }
1000
1001         /* register the assumption */
1002
1003         as = NEW(method_assumption);
1004         as->next = m->assumptions;
1005         as->context = caller;
1006
1007         m->assumptions = as;
1008 }
1009
1010
1011 /* method_break_assumption_monomorphic *****************************************
1012
1013    Break the assumption that this method is monomorphic. All callers that
1014    have registered this assumption are added to the worklist.
1015
1016    IN:
1017       m.................the method
1018           wl................worklist where to add invalidated callers
1019
1020 *******************************************************************************/
1021
1022 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1023 {
1024         method_assumption *as;
1025
1026         /* XXX LOCKING FOR THIS FUNCTION? */
1027
1028         for (as = m->assumptions; as != NULL; as = as->next) {
1029                 INLINELOG(
1030                         printf("ASSUMPTION BROKEN (monomorphism): ");
1031                         method_print(m);
1032                         printf(" in ");
1033                         method_println(as->context);
1034                 );
1035
1036                 method_add_to_worklist(as->context, wl);
1037         }
1038 }
1039
1040
1041 /* method_printflags ***********************************************************
1042
1043    Prints the flags of a method to stdout like.
1044
1045 *******************************************************************************/
1046
1047 #if !defined(NDEBUG)
1048 void method_printflags(methodinfo *m)
1049 {
1050         if (m == NULL) {
1051                 printf("NULL");
1052                 return;
1053         }
1054
1055         if (m->flags & ACC_PUBLIC)             printf(" PUBLIC");
1056         if (m->flags & ACC_PRIVATE)            printf(" PRIVATE");
1057         if (m->flags & ACC_PROTECTED)          printf(" PROTECTED");
1058         if (m->flags & ACC_STATIC)             printf(" STATIC");
1059         if (m->flags & ACC_FINAL)              printf(" FINAL");
1060         if (m->flags & ACC_SYNCHRONIZED)       printf(" SYNCHRONIZED");
1061         if (m->flags & ACC_VOLATILE)           printf(" VOLATILE");
1062         if (m->flags & ACC_TRANSIENT)          printf(" TRANSIENT");
1063         if (m->flags & ACC_NATIVE)             printf(" NATIVE");
1064         if (m->flags & ACC_INTERFACE)          printf(" INTERFACE");
1065         if (m->flags & ACC_ABSTRACT)           printf(" ABSTRACT");
1066         if (m->flags & ACC_METHOD_BUILTIN)     printf(" (builtin)");
1067         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1068         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1069 }
1070 #endif /* !defined(NDEBUG) */
1071
1072
1073 /* method_print ****************************************************************
1074
1075    Prints a method to stdout like:
1076
1077    java.lang.Object.<init>()V
1078
1079 *******************************************************************************/
1080
1081 #if !defined(NDEBUG)
1082 void method_print(methodinfo *m)
1083 {
1084         if (m == NULL) {
1085                 printf("NULL");
1086                 return;
1087         }
1088
1089         if (m->class != NULL)
1090                 utf_display_printable_ascii_classname(m->class->name);
1091         else
1092                 printf("NULL");
1093         printf(".");
1094         utf_display_printable_ascii(m->name);
1095         utf_display_printable_ascii(m->descriptor);
1096
1097         method_printflags(m);
1098 }
1099 #endif /* !defined(NDEBUG) */
1100
1101
1102 /* method_println **************************************************************
1103
1104    Prints a method plus new line to stdout like:
1105
1106    java.lang.Object.<init>()V
1107
1108 *******************************************************************************/
1109
1110 #if !defined(NDEBUG)
1111 void method_println(methodinfo *m)
1112 {
1113         if (opt_debugcolor) printf("\033[31m"); /* red */
1114         method_print(m);
1115         if (opt_debugcolor) printf("\033[m");   
1116         printf("\n");
1117 }
1118 #endif /* !defined(NDEBUG) */
1119
1120
1121 /* method_methodref_print ******************************************************
1122
1123    Prints a method reference to stdout.
1124
1125 *******************************************************************************/
1126
1127 #if !defined(NDEBUG)
1128 void method_methodref_print(constant_FMIref *mr)
1129 {
1130         if (!mr) {
1131                 printf("(constant_FMIref *)NULL");
1132                 return;
1133         }
1134
1135         if (IS_FMIREF_RESOLVED(mr)) {
1136                 printf("<method> ");
1137                 method_print(mr->p.method);
1138         }
1139         else {
1140                 printf("<methodref> ");
1141                 utf_display_printable_ascii_classname(mr->p.classref->name);
1142                 printf(".");
1143                 utf_display_printable_ascii(mr->name);
1144                 utf_display_printable_ascii(mr->descriptor);
1145         }
1146 }
1147 #endif /* !defined(NDEBUG) */
1148
1149
1150 /* method_methodref_println ****************************************************
1151
1152    Prints a method reference to stdout, followed by a newline.
1153
1154 *******************************************************************************/
1155
1156 #if !defined(NDEBUG)
1157 void method_methodref_println(constant_FMIref *mr)
1158 {
1159         method_methodref_print(mr);
1160         printf("\n");
1161 }
1162 #endif /* !defined(NDEBUG) */
1163
1164
1165 /*
1166  * These are local overrides for various environment variables in Emacs.
1167  * Please do not remove this and leave it at the end of the file, where
1168  * Emacs will automagically detect them.
1169  * ---------------------------------------------------------------------
1170  * Local variables:
1171  * mode: c
1172  * indent-tabs-mode: t
1173  * c-basic-offset: 4
1174  * tab-width: 4
1175  * End:
1176  * vim:noexpandtab:sw=4:ts=4:
1177  */