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