Merge from subtype.
[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.h"
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         java_handle_objectarray_t *oa;
706         int32_t                    i;
707         classinfo                 *c;
708
709         md = m->parseddesc;
710
711         /* is the descriptor fully parsed? */
712
713         if (m->parseddesc->params == NULL)
714                 if (!descriptor_params_from_paramtypes(md, m->flags))
715                         return NULL;
716
717         paramtypes = md->paramtypes;
718         paramcount = md->paramcount;
719
720         /* skip `this' pointer */
721
722         if (!(m->flags & ACC_STATIC)) {
723                 paramtypes++;
724                 paramcount--;
725         }
726
727         /* create class-array */
728
729         oa = builtin_anewarray(paramcount, class_java_lang_Class);
730
731         if (oa == NULL)
732                 return NULL;
733
734     /* get classes */
735
736         for (i = 0; i < paramcount; i++) {
737                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
738                         return NULL;
739
740                 LLNI_array_direct(oa, i) = (java_object_t *) c;
741         }
742
743         return oa;
744 }
745
746
747 /* method_get_exceptionarray ***************************************************
748
749    Get the exceptions which can be thrown by a method.
750
751 *******************************************************************************/
752
753 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
754 {
755         java_handle_objectarray_t *oa;
756         classinfo                 *c;
757         s4                         i;
758
759         /* create class-array */
760
761         oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
762
763         if (oa == NULL)
764                 return NULL;
765
766         /* iterate over all exceptions and store the class in the array */
767
768         for (i = 0; i < m->thrownexceptionscount; i++) {
769                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
770
771                 if (c == NULL)
772                         return NULL;
773
774                 LLNI_array_direct(oa, i) = (java_object_t *) c;
775         }
776
777         return oa;
778 }
779
780
781 /* method_returntype_get *******************************************************
782
783    Get the return type of the method.
784
785 *******************************************************************************/
786
787 classinfo *method_returntype_get(methodinfo *m)
788 {
789         typedesc  *td;
790         classinfo *c;
791
792         td = &(m->parseddesc->returntype);
793
794         if (!resolve_class_from_typedesc(td, true, false, &c))
795                 return NULL;
796
797         return c;
798 }
799
800
801 /* method_count_implementations ************************************************
802
803    Count the implementations of a method in a class cone (a class and all its
804    subclasses.)
805
806    IN:
807        m................the method to count
808            c................class at which to start the counting (this class and
809                             all its subclasses will be searched)
810
811    OUT:
812        *found...........if found != NULL, *found receives the method
813                             implementation that was found. This value is only
814                                                 meaningful if the return value is 1.
815
816    RETURN VALUE:
817        the number of implementations found
818
819 *******************************************************************************/
820
821 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
822 {
823         s4          count;
824         methodinfo *mp;
825         methodinfo *mend;
826         classinfo  *child;
827
828         count = 0;
829
830         mp = c->methods;
831         mend = mp + c->methodscount;
832
833         for (; mp < mend; ++mp) {
834                 if (method_canoverwrite(mp, m)) {
835                         if (found)
836                                 *found = mp;
837                         count++;
838                         break;
839                 }
840         }
841
842         for (child = c->sub; child != NULL; child = child->nextsub) {
843                 count += method_count_implementations(m, child, found);
844         }
845
846         return count;
847 }
848
849
850 /* method_get_annotations ******************************************************
851
852    Get a methods' unparsed annotations in a byte array.
853
854    IN:
855        m........the method of which the annotations should be returned
856
857    RETURN VALUE:
858        The unparsed annotations in a byte array (or NULL if there aren't any).
859
860 *******************************************************************************/
861
862 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
863 {
864 #if defined(ENABLE_ANNOTATIONS)
865         classinfo     *c;                  /* methods' declaring class          */
866         int            slot;               /* methods' slot                     */
867         java_handle_t *annotations;        /* methods' unparsed annotations     */
868         java_handle_t *method_annotations; /* all methods' unparsed annotations */
869                                            /* of the declaring class            */
870
871         c           = m->clazz;
872         slot        = m - c->methods;
873         annotations = NULL;
874
875         LLNI_classinfo_field_get(c, method_annotations, method_annotations);
876
877         /* the method_annotations array might be shorter then the method
878          * count if the methods above a certain index have no annotations.
879          */     
880         if (method_annotations != NULL &&
881                 array_length_get(method_annotations) > slot) {
882                 annotations = array_objectarray_element_get(
883                         (java_handle_objectarray_t*)method_annotations, slot);
884         }
885         
886         return (java_handle_bytearray_t*)annotations;
887 #else
888         return NULL;
889 #endif
890 }
891
892
893 /* method_get_parameterannotations ********************************************
894
895    Get a methods' unparsed parameter annotations in an array of byte
896    arrays.
897
898    IN:
899        m........the method of which the parameter annotations should be
900                     returned
901
902    RETURN VALUE:
903        The unparsed parameter annotations in a byte array (or NULL if
904            there aren't any).
905
906 *******************************************************************************/
907
908 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
909 {
910 #if defined(ENABLE_ANNOTATIONS)
911         classinfo     *c;                           /* methods' declaring class */
912         int            slot;                        /* methods' slot            */
913         java_handle_t *parameterAnnotations;        /* methods' unparsed        */
914                                                     /* parameter annotations    */
915         java_handle_t *method_parameterannotations; /* all methods' unparsed    */
916                                                     /* parameter annotations of */
917                                                     /* the declaring class      */
918
919         c                    = m->clazz;
920         slot                 = m - c->methods;
921         parameterAnnotations = NULL;
922
923         LLNI_classinfo_field_get(
924                 c, method_parameterannotations, method_parameterannotations);
925
926         /* the method_annotations array might be shorter then the method
927          * count if the methods above a certain index have no annotations.
928          */     
929         if (method_parameterannotations != NULL &&
930                 array_length_get(method_parameterannotations) > slot) {
931                 parameterAnnotations = array_objectarray_element_get(
932                                 (java_handle_objectarray_t*)method_parameterannotations,
933                                 slot);
934         }
935         
936         return (java_handle_bytearray_t*)parameterAnnotations;
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 *annotationDefault;         /* methods' unparsed            */
963                                                   /* annotation default value     */
964         java_handle_t *method_annotationdefaults; /* all methods' unparsed        */
965                                                   /* annotation default values of */
966                                                   /* the declaring class          */
967
968         c                 = m->clazz;
969         slot              = m - c->methods;
970         annotationDefault = NULL;
971
972         LLNI_classinfo_field_get(
973                 c, method_annotationdefaults, method_annotationdefaults);
974
975         /* the method_annotations array might be shorter then the method
976          * count if the methods above a certain index have no annotations.
977          */     
978         if (method_annotationdefaults != NULL &&
979                 array_length_get(method_annotationdefaults) > slot) {
980                 annotationDefault = array_objectarray_element_get(
981                                 (java_handle_objectarray_t*)method_annotationdefaults, slot);
982         }
983         
984         return (java_handle_bytearray_t*)annotationDefault;
985 #else
986         return NULL;
987 #endif
988 }
989
990
991 /* method_add_to_worklist ******************************************************
992
993    Add the method to the given worklist. If the method already occurs in
994    the worklist, the worklist remains unchanged.
995
996 *******************************************************************************/
997
998 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
999 {
1000         method_worklist *wi;
1001
1002         for (wi = *wl; wi != NULL; wi = wi->next)
1003                 if (wi->m == m)
1004                         return;
1005
1006         wi = NEW(method_worklist);
1007         wi->next = *wl;
1008         wi->m = m;
1009
1010         *wl = wi;
1011 }
1012
1013
1014 /* method_add_assumption_monomorphic *******************************************
1015
1016    Record the assumption that the method is monomorphic.
1017
1018    IN:
1019       m.................the method
1020           caller............the caller making the assumption
1021
1022 *******************************************************************************/
1023
1024 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
1025 {
1026         method_assumption *as;
1027
1028         /* XXX LOCKING FOR THIS FUNCTION? */
1029
1030         /* check if we already have registered this assumption */
1031
1032         for (as = m->assumptions; as != NULL; as = as->next) {
1033                 if (as->context == caller)
1034                         return;
1035         }
1036
1037         /* register the assumption */
1038
1039         as = NEW(method_assumption);
1040         as->next = m->assumptions;
1041         as->context = caller;
1042
1043         m->assumptions = as;
1044 }
1045
1046 /* method_break_assumption_monomorphic *****************************************
1047
1048    Break the assumption that this method is monomorphic. All callers that
1049    have registered this assumption are added to the worklist.
1050
1051    IN:
1052       m.................the method
1053           wl................worklist where to add invalidated callers
1054
1055 *******************************************************************************/
1056
1057 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1058 {
1059         method_assumption *as;
1060
1061         /* XXX LOCKING FOR THIS FUNCTION? */
1062
1063         for (as = m->assumptions; as != NULL; as = as->next) {
1064                 INLINELOG(
1065                         printf("ASSUMPTION BROKEN (monomorphism): ");
1066                         method_print(m);
1067                         printf(" in ");
1068                         method_println(as->context);
1069                 );
1070
1071                 method_add_to_worklist(as->context, wl);
1072
1073 #if defined(ENABLE_TLH) && 0
1074                 /* XXX hack */
1075                 method_assumption *as2;
1076                 as2 = m->assumptions;
1077                 m->assumptions = NULL;
1078                 method_break_assumption_monomorphic(as->context, wl);
1079                 /*
1080                 assert(m->assumptions == NULL);
1081                 m->assumptions = as2;*/
1082 #endif
1083
1084         }
1085 }
1086
1087 /* method_printflags ***********************************************************
1088
1089    Prints the flags of a method to stdout like.
1090
1091 *******************************************************************************/
1092
1093 #if !defined(NDEBUG)
1094 void method_printflags(methodinfo *m)
1095 {
1096         if (m == NULL) {
1097                 printf("NULL");
1098                 return;
1099         }
1100
1101         if (m->flags & ACC_PUBLIC)             printf(" PUBLIC");
1102         if (m->flags & ACC_PRIVATE)            printf(" PRIVATE");
1103         if (m->flags & ACC_PROTECTED)          printf(" PROTECTED");
1104         if (m->flags & ACC_STATIC)             printf(" STATIC");
1105         if (m->flags & ACC_FINAL)              printf(" FINAL");
1106         if (m->flags & ACC_SYNCHRONIZED)       printf(" SYNCHRONIZED");
1107         if (m->flags & ACC_VOLATILE)           printf(" VOLATILE");
1108         if (m->flags & ACC_TRANSIENT)          printf(" TRANSIENT");
1109         if (m->flags & ACC_NATIVE)             printf(" NATIVE");
1110         if (m->flags & ACC_INTERFACE)          printf(" INTERFACE");
1111         if (m->flags & ACC_ABSTRACT)           printf(" ABSTRACT");
1112         if (m->flags & ACC_METHOD_BUILTIN)     printf(" (builtin)");
1113         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1114         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1115 }
1116 #endif /* !defined(NDEBUG) */
1117
1118
1119 /* method_print ****************************************************************
1120
1121    Prints a method to stdout like:
1122
1123    java.lang.Object.<init>()V
1124
1125 *******************************************************************************/
1126
1127 #if !defined(NDEBUG)
1128 void method_print(methodinfo *m)
1129 {
1130         if (m == NULL) {
1131                 printf("NULL");
1132                 return;
1133         }
1134
1135         if (m->clazz != NULL)
1136                 utf_display_printable_ascii_classname(m->clazz->name);
1137         else
1138                 printf("NULL");
1139         printf(".");
1140         utf_display_printable_ascii(m->name);
1141         utf_display_printable_ascii(m->descriptor);
1142
1143         method_printflags(m);
1144 }
1145 #endif /* !defined(NDEBUG) */
1146
1147
1148 /* method_println **************************************************************
1149
1150    Prints a method plus new line to stdout like:
1151
1152    java.lang.Object.<init>()V
1153
1154 *******************************************************************************/
1155
1156 #if !defined(NDEBUG)
1157 void method_println(methodinfo *m)
1158 {
1159         if (opt_debugcolor) printf("\033[31m"); /* red */
1160         method_print(m);
1161         if (opt_debugcolor) printf("\033[m");   
1162         printf("\n");
1163 }
1164 #endif /* !defined(NDEBUG) */
1165
1166
1167 /* method_methodref_print ******************************************************
1168
1169    Prints a method reference to stdout.
1170
1171 *******************************************************************************/
1172
1173 #if !defined(NDEBUG)
1174 void method_methodref_print(constant_FMIref *mr)
1175 {
1176         if (!mr) {
1177                 printf("(constant_FMIref *)NULL");
1178                 return;
1179         }
1180
1181         if (IS_FMIREF_RESOLVED(mr)) {
1182                 printf("<method> ");
1183                 method_print(mr->p.method);
1184         }
1185         else {
1186                 printf("<methodref> ");
1187                 utf_display_printable_ascii_classname(mr->p.classref->name);
1188                 printf(".");
1189                 utf_display_printable_ascii(mr->name);
1190                 utf_display_printable_ascii(mr->descriptor);
1191         }
1192 }
1193 #endif /* !defined(NDEBUG) */
1194
1195
1196 /* method_methodref_println ****************************************************
1197
1198    Prints a method reference to stdout, followed by a newline.
1199
1200 *******************************************************************************/
1201
1202 #if !defined(NDEBUG)
1203 void method_methodref_println(constant_FMIref *mr)
1204 {
1205         method_methodref_print(mr);
1206         printf("\n");
1207 }
1208 #endif /* !defined(NDEBUG) */
1209
1210 #if defined(__cplusplus)
1211 }
1212 #endif
1213
1214 /*
1215  * These are local overrides for various environment variables in Emacs.
1216  * Please do not remove this and leave it at the end of the file, where
1217  * Emacs will automagically detect them.
1218  * ---------------------------------------------------------------------
1219  * Local variables:
1220  * mode: c++
1221  * indent-tabs-mode: t
1222  * c-basic-offset: 4
1223  * tab-width: 4
1224  * End:
1225  * vim:noexpandtab:sw=4:ts=4:
1226  */