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