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