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