* src/vm/jit/codegen-common.cpp (codegen_emit): Fixed support to pass float
[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         if (m->breakpoints)
564                 delete m->breakpoints;
565 }
566
567
568 /* method_canoverwrite *********************************************************
569
570    Check if m and old are identical with respect to type and
571    name. This means that old can be overwritten with m.
572         
573 *******************************************************************************/
574
575 bool method_canoverwrite(methodinfo *m, methodinfo *old)
576 {
577         if (m->name != old->name)
578                 return false;
579
580         if (m->descriptor != old->descriptor)
581                 return false;
582
583         if (m->flags & ACC_STATIC)
584                 return false;
585
586         return true;
587 }
588
589
590 /* method_new_builtin **********************************************************
591
592    Creates a minimal methodinfo structure for builtins. This comes handy
593    when dealing with builtin stubs or stacktraces.
594
595 *******************************************************************************/
596
597 methodinfo *method_new_builtin(builtintable_entry *bte)
598 {
599         methodinfo *m;
600
601         /* allocate the methodinfo structure */
602
603         m = NEW(methodinfo);
604
605         /* initialize methodinfo structure */
606
607         MZERO(m, methodinfo, 1);
608         
609         m->mutex      = new Mutex();
610         m->flags      = ACC_METHOD_BUILTIN;
611         m->parseddesc = bte->md;
612         m->name       = bte->name;
613         m->descriptor = bte->descriptor;
614
615         /* return the newly created methodinfo */
616
617         return m;
618 }
619
620
621 /* method_vftbl_lookup *********************************************************
622
623    Does a method lookup in the passed virtual function table.  This
624    function does exactly the same thing as JIT, but additionally
625    relies on the fact, that the methodinfo pointer is at the first
626    data segment slot (even for compiler stubs).
627
628 *******************************************************************************/
629
630 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
631 {
632         methodptr   mptr;
633         methodptr  *pmptr;
634         methodinfo *resm;                   /* pointer to new resolved method     */
635
636         /* If the method is not an instance method, just return it. */
637
638         if (m->flags & ACC_STATIC)
639                 return m;
640
641         assert(vftbl);
642
643         /* Get the method from the virtual function table.  Is this an
644            interface method? */
645
646         if (m->clazz->flags & ACC_INTERFACE) {
647                 pmptr = vftbl->interfacetable[-(m->clazz->index)];
648                 mptr  = pmptr[(m - m->clazz->methods)];
649         }
650         else {
651                 mptr = vftbl->table[m->vftblindex];
652         }
653
654         /* and now get the codeinfo pointer from the first data segment slot */
655
656         resm = code_get_methodinfo_for_pv(mptr);
657
658         return resm;
659 }
660
661
662 /* method_get_parametercount **************************************************
663
664    Use the descriptor of a method to determine the number of parameters
665    of the method. The this pointer of non-static methods is not counted.
666
667    IN:
668        m........the method of which the parameters should be counted
669
670    RETURN VALUE:
671        The parameter count or -1 on error.
672
673 *******************************************************************************/
674
675 int32_t method_get_parametercount(methodinfo *m)
676 {
677         methoddesc *md;             /* method descriptor of m   */
678         int32_t     paramcount = 0; /* the parameter count of m */
679
680         md = m->parseddesc;
681         
682         /* is the descriptor fully parsed? */
683
684         if (md->params == NULL) {
685                 if (!descriptor_params_from_paramtypes(md, m->flags)) {
686                         return -1;
687                 }
688         }
689
690         paramcount = md->paramcount;
691
692         /* skip `this' pointer */
693
694         if (!(m->flags & ACC_STATIC)) {
695                 --paramcount;
696         }
697
698         return paramcount;
699 }
700
701
702 /* method_get_parametertypearray ***********************************************
703
704    Use the descriptor of a method to generate a java.lang.Class array
705    which contains the classes of the parametertypes of the method.
706
707    This function is called by java.lang.reflect.{Constructor,Method}.
708
709 *******************************************************************************/
710
711 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
712 {
713         methoddesc* md;
714         typedesc*   paramtypes;
715         int32_t     paramcount;
716         int32_t     i;
717         classinfo*  c;
718
719         md = m->parseddesc;
720
721         /* is the descriptor fully parsed? */
722
723         if (m->parseddesc->params == NULL)
724                 if (!descriptor_params_from_paramtypes(md, m->flags))
725                         return NULL;
726
727         paramtypes = md->paramtypes;
728         paramcount = md->paramcount;
729
730         /* skip `this' pointer */
731
732         if (!(m->flags & ACC_STATIC)) {
733                 paramtypes++;
734                 paramcount--;
735         }
736
737         /* create class-array */
738
739         ClassArray ca(paramcount);
740
741         if (ca.is_null())
742                 return NULL;
743
744     /* get classes */
745
746         for (i = 0; i < paramcount; i++) {
747                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
748                         return NULL;
749
750                 ca.set_element(i, c);
751         }
752
753         return ca.get_handle();
754 }
755
756
757 /* method_get_exceptionarray ***************************************************
758
759    Get the exceptions which can be thrown by a method.
760
761 *******************************************************************************/
762
763 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
764 {
765         classinfo* c;
766         s4         i;
767
768         /* create class-array */
769
770         ClassArray ca(m->thrownexceptionscount);
771
772         if (ca.is_null())
773                 return NULL;
774
775         /* iterate over all exceptions and store the class in the array */
776
777         for (i = 0; i < m->thrownexceptionscount; i++) {
778                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
779
780                 if (c == NULL)
781                         return NULL;
782
783                 ca.set_element(i, c);
784         }
785
786         return ca.get_handle();
787 }
788
789
790 /* method_returntype_get *******************************************************
791
792    Get the return type of the method.
793
794 *******************************************************************************/
795
796 classinfo *method_returntype_get(methodinfo *m)
797 {
798         typedesc  *td;
799         classinfo *c;
800
801         td = &(m->parseddesc->returntype);
802
803         if (!resolve_class_from_typedesc(td, true, false, &c))
804                 return NULL;
805
806         return c;
807 }
808
809
810 /* method_count_implementations ************************************************
811
812    Count the implementations of a method in a class cone (a class and all its
813    subclasses.)
814
815    IN:
816        m................the method to count
817            c................class at which to start the counting (this class and
818                             all its subclasses will be searched)
819
820    OUT:
821        *found...........if found != NULL, *found receives the method
822                             implementation that was found. This value is only
823                                                 meaningful if the return value is 1.
824
825    RETURN VALUE:
826        the number of implementations found
827
828 *******************************************************************************/
829
830 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
831 {
832         s4          count;
833         methodinfo *mp;
834         methodinfo *mend;
835         classinfo  *child;
836
837         count = 0;
838
839         mp = c->methods;
840         mend = mp + c->methodscount;
841
842         for (; mp < mend; ++mp) {
843                 if (method_canoverwrite(mp, m)) {
844                         if (found)
845                                 *found = mp;
846                         count++;
847                         break;
848                 }
849         }
850
851         for (child = c->sub; child != NULL; child = child->nextsub) {
852                 count += method_count_implementations(m, child, found);
853         }
854
855         return count;
856 }
857
858
859 /* method_get_annotations ******************************************************
860
861    Get a methods' unparsed annotations in a byte array.
862
863    IN:
864        m........the method of which the annotations should be returned
865
866    RETURN VALUE:
867        The unparsed annotations in a byte array (or NULL if there aren't any).
868
869 *******************************************************************************/
870
871 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
872 {
873 #if defined(ENABLE_ANNOTATIONS)
874         classinfo     *c;                  /* methods' declaring class          */
875         int            slot;               /* methods' slot                     */
876         java_handle_t *method_annotations; /* all methods' unparsed annotations */
877                                            /* of the declaring class            */
878
879         c    = m->clazz;
880         slot = m - c->methods;
881
882         LLNI_classinfo_field_get(c, method_annotations, method_annotations);
883
884         ObjectArray oa((java_handle_objectarray_t*) method_annotations);
885
886         /* the method_annotations array might be shorter then the method
887          * count if the methods above a certain index have no annotations.
888          */     
889         if (method_annotations != NULL && oa.get_length() > slot) {
890                 return (java_handle_bytearray_t*) oa.get_element(slot);
891         } else {
892                 return NULL;
893         }
894 #else
895         return NULL;
896 #endif
897 }
898
899
900 /* method_get_parameterannotations ********************************************
901
902    Get a methods' unparsed parameter annotations in an array of byte
903    arrays.
904
905    IN:
906        m........the method of which the parameter annotations should be
907                     returned
908
909    RETURN VALUE:
910        The unparsed parameter annotations in a byte array (or NULL if
911            there aren't any).
912
913 *******************************************************************************/
914
915 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
916 {
917 #if defined(ENABLE_ANNOTATIONS)
918         classinfo     *c;                           /* methods' declaring class */
919         int            slot;                        /* methods' slot            */
920         java_handle_t *method_parameterannotations; /* all methods' unparsed    */
921                                                     /* parameter annotations of */
922                                                     /* the declaring class      */
923
924         c    = m->clazz;
925         slot = m - c->methods;
926
927         LLNI_classinfo_field_get(
928                 c, method_parameterannotations, method_parameterannotations);
929
930         ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
931
932         /* the method_annotations array might be shorter then the method
933          * count if the methods above a certain index have no annotations.
934          */     
935         if (method_parameterannotations != NULL && oa.get_length() > slot) {
936                 return (java_handle_bytearray_t*) oa.get_element(slot);
937         } else {
938                 return NULL;
939         }
940 #else
941         return NULL;
942 #endif
943 }
944
945
946 /* method_get_annotationdefault ***********************************************
947
948    Get a methods' unparsed annotation default value in a byte array.
949    
950    IN:
951        m........the method of which the annotation default value should be
952                     returned
953
954    RETURN VALUE:
955        The unparsed annotation default value in a byte array (or NULL if
956            there isn't one).
957
958 *******************************************************************************/
959
960 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
961 {
962 #if defined(ENABLE_ANNOTATIONS)
963         classinfo     *c;                         /* methods' declaring class     */
964         int            slot;                      /* methods' slot                */
965         java_handle_t *method_annotationdefaults; /* all methods' unparsed        */
966                                                   /* annotation default values of */
967                                                   /* the declaring class          */
968
969         c    = m->clazz;
970         slot = m - c->methods;
971
972         LLNI_classinfo_field_get(
973                 c, method_annotationdefaults, method_annotationdefaults);
974
975         ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
976
977         /* the method_annotations array might be shorter then the method
978          * count if the methods above a certain index have no annotations.
979          */
980         if (method_annotationdefaults != NULL && oa.get_length() > slot) {
981                 return (java_handle_bytearray_t*) oa.get_element(slot);
982         } else {
983                 return NULL;
984         }
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  */