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