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