* src/vm/method.cpp (method_load): Loads LocalVariableTable attribute.
[cacao.git] / src / vm / method.cpp
1 /* src/vm/method.cpp - method functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdio.h>
31
32 #include "vm/types.h"
33
34 #include "mm/memory.hpp"
35
36 #include "native/llni.h"
37
38 #include "threads/mutex.hpp"
39
40 #include "vm/array.hpp"
41 #include "vm/jit/builtin.hpp"
42 #include "vm/class.hpp"
43 #include "vm/exceptions.hpp"
44 #include "vm/global.h"
45 #include "vm/globals.hpp"
46 #include "vm/linker.hpp"
47 #include "vm/loader.hpp"
48 #include "vm/method.hpp"
49 #include "vm/options.h"
50 #include "vm/resolve.hpp"
51 #include "vm/suck.hpp"
52 #include "vm/utf8.h"
53 #include "vm/vm.hpp"
54
55 #include "vm/jit/code.hpp"
56 #include "vm/jit/methodheader.h"
57 #include "vm/jit/stubs.hpp"
58
59
60 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
61 #define INLINELOG(code)  do { if (opt_TraceInlining) { code } } while (0)
62 #else
63 #define INLINELOG(code)
64 #endif
65
66 /* global variables ***********************************************************/
67
68 methodinfo *method_java_lang_reflect_Method_invoke;
69
70
71 #if defined(__cplusplus)
72 extern "C" {
73 #endif
74
75
76 /* method_init *****************************************************************
77
78    Initialize method subsystem.
79
80 *******************************************************************************/
81
82 void method_init(void)
83 {
84 #if defined(ENABLE_JAVASE)
85         /* Sanity check. */
86
87         if (class_java_lang_reflect_Method == NULL)
88                 vm_abort("method_init: class_java_lang_reflect_Method is NULL");
89
90         /* Cache java.lang.reflect.Method.invoke() */
91
92         method_java_lang_reflect_Method_invoke =
93                 class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
94
95         if (method_java_lang_reflect_Method_invoke == NULL)
96                 vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
97 #endif
98 }
99
100
101 /* method_load *****************************************************************
102
103    Loads a method from the class file and fills an existing methodinfo
104    structure.
105
106    method_info {
107        u2 access_flags;
108            u2 name_index;
109            u2 descriptor_index;
110            u2 attributes_count;
111            attribute_info attributes[attribute_count];
112    }
113
114    attribute_info {
115        u2 attribute_name_index;
116            u4 attribute_length;
117            u1 info[attribute_length];
118    }
119
120    LineNumberTable_attribute {
121        u2 attribute_name_index;
122            u4 attribute_length;
123            u2 line_number_table_length;
124            {
125                u2 start_pc;
126                    u2 line_number;
127            } line_number_table[line_number_table_length];
128    }
129
130    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 or -1 on error.
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                 if (!descriptor_params_from_paramtypes(md, m->flags)) {
740                         return -1;
741                 }
742         }
743
744         paramcount = md->paramcount;
745
746         /* skip `this' pointer */
747
748         if (!(m->flags & ACC_STATIC)) {
749                 --paramcount;
750         }
751
752         return paramcount;
753 }
754
755
756 /* method_get_parametertypearray ***********************************************
757
758    Use the descriptor of a method to generate a java.lang.Class array
759    which contains the classes of the parametertypes of the method.
760
761    This function is called by java.lang.reflect.{Constructor,Method}.
762
763 *******************************************************************************/
764
765 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
766 {
767         methoddesc* md;
768         typedesc*   paramtypes;
769         int32_t     paramcount;
770         int32_t     i;
771         classinfo*  c;
772
773         md = m->parseddesc;
774
775         /* is the descriptor fully parsed? */
776
777         if (m->parseddesc->params == NULL)
778                 if (!descriptor_params_from_paramtypes(md, m->flags))
779                         return NULL;
780
781         paramtypes = md->paramtypes;
782         paramcount = md->paramcount;
783
784         /* skip `this' pointer */
785
786         if (!(m->flags & ACC_STATIC)) {
787                 paramtypes++;
788                 paramcount--;
789         }
790
791         /* create class-array */
792
793         ClassArray ca(paramcount);
794
795         if (ca.is_null())
796                 return NULL;
797
798     /* get classes */
799
800         for (i = 0; i < paramcount; i++) {
801                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
802                         return NULL;
803
804                 ca.set_element(i, c);
805         }
806
807         return ca.get_handle();
808 }
809
810
811 /* method_get_exceptionarray ***************************************************
812
813    Get the exceptions which can be thrown by a method.
814
815 *******************************************************************************/
816
817 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
818 {
819         classinfo* c;
820         s4         i;
821
822         /* create class-array */
823
824         ClassArray ca(m->thrownexceptionscount);
825
826         if (ca.is_null())
827                 return NULL;
828
829         /* iterate over all exceptions and store the class in the array */
830
831         for (i = 0; i < m->thrownexceptionscount; i++) {
832                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
833
834                 if (c == NULL)
835                         return NULL;
836
837                 ca.set_element(i, c);
838         }
839
840         return ca.get_handle();
841 }
842
843
844 /* method_returntype_get *******************************************************
845
846    Get the return type of the method.
847
848 *******************************************************************************/
849
850 classinfo *method_returntype_get(methodinfo *m)
851 {
852         typedesc  *td;
853         classinfo *c;
854
855         td = &(m->parseddesc->returntype);
856
857         if (!resolve_class_from_typedesc(td, true, false, &c))
858                 return NULL;
859
860         return c;
861 }
862
863
864 /* method_count_implementations ************************************************
865
866    Count the implementations of a method in a class cone (a class and all its
867    subclasses.)
868
869    IN:
870        m................the method to count
871            c................class at which to start the counting (this class and
872                             all its subclasses will be searched)
873
874    OUT:
875        *found...........if found != NULL, *found receives the method
876                             implementation that was found. This value is only
877                                                 meaningful if the return value is 1.
878
879    RETURN VALUE:
880        the number of implementations found
881
882 *******************************************************************************/
883
884 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
885 {
886         s4          count;
887         methodinfo *mp;
888         methodinfo *mend;
889         classinfo  *child;
890
891         count = 0;
892
893         mp = c->methods;
894         mend = mp + c->methodscount;
895
896         for (; mp < mend; ++mp) {
897                 if (method_canoverwrite(mp, m)) {
898                         if (found)
899                                 *found = mp;
900                         count++;
901                         break;
902                 }
903         }
904
905         for (child = c->sub; child != NULL; child = child->nextsub) {
906                 count += method_count_implementations(m, child, found);
907         }
908
909         return count;
910 }
911
912
913 /* method_get_annotations ******************************************************
914
915    Get a methods' unparsed annotations in a byte array.
916
917    IN:
918        m........the method of which the annotations should be returned
919
920    RETURN VALUE:
921        The unparsed annotations in a byte array (or NULL if there aren't any).
922
923 *******************************************************************************/
924
925 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
926 {
927 #if defined(ENABLE_ANNOTATIONS)
928         classinfo     *c;                  /* methods' declaring class          */
929         int            slot;               /* methods' slot                     */
930         java_handle_t *method_annotations; /* all methods' unparsed annotations */
931                                            /* of the declaring class            */
932
933         c    = m->clazz;
934         slot = m - c->methods;
935
936         LLNI_classinfo_field_get(c, method_annotations, method_annotations);
937
938         ObjectArray oa((java_handle_objectarray_t*) method_annotations);
939
940         /* the method_annotations array might be shorter then the method
941          * count if the methods above a certain index have no annotations.
942          */     
943         if (method_annotations != NULL && oa.get_length() > slot) {
944                 return (java_handle_bytearray_t*) oa.get_element(slot);
945         } else {
946                 return NULL;
947         }
948 #else
949         return NULL;
950 #endif
951 }
952
953
954 /* method_get_parameterannotations ********************************************
955
956    Get a methods' unparsed parameter annotations in an array of byte
957    arrays.
958
959    IN:
960        m........the method of which the parameter annotations should be
961                     returned
962
963    RETURN VALUE:
964        The unparsed parameter annotations in a byte array (or NULL if
965            there aren't any).
966
967 *******************************************************************************/
968
969 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
970 {
971 #if defined(ENABLE_ANNOTATIONS)
972         classinfo     *c;                           /* methods' declaring class */
973         int            slot;                        /* methods' slot            */
974         java_handle_t *method_parameterannotations; /* all methods' unparsed    */
975                                                     /* parameter annotations of */
976                                                     /* the declaring class      */
977
978         c    = m->clazz;
979         slot = m - c->methods;
980
981         LLNI_classinfo_field_get(
982                 c, method_parameterannotations, method_parameterannotations);
983
984         ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
985
986         /* the method_annotations array might be shorter then the method
987          * count if the methods above a certain index have no annotations.
988          */     
989         if (method_parameterannotations != NULL && oa.get_length() > slot) {
990                 return (java_handle_bytearray_t*) oa.get_element(slot);
991         } else {
992                 return NULL;
993         }
994 #else
995         return NULL;
996 #endif
997 }
998
999
1000 /* method_get_annotationdefault ***********************************************
1001
1002    Get a methods' unparsed annotation default value in a byte array.
1003    
1004    IN:
1005        m........the method of which the annotation default value should be
1006                     returned
1007
1008    RETURN VALUE:
1009        The unparsed annotation default value in a byte array (or NULL if
1010            there isn't one).
1011
1012 *******************************************************************************/
1013
1014 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
1015 {
1016 #if defined(ENABLE_ANNOTATIONS)
1017         classinfo     *c;                         /* methods' declaring class     */
1018         int            slot;                      /* methods' slot                */
1019         java_handle_t *method_annotationdefaults; /* all methods' unparsed        */
1020                                                   /* annotation default values of */
1021                                                   /* the declaring class          */
1022
1023         c    = m->clazz;
1024         slot = m - c->methods;
1025
1026         LLNI_classinfo_field_get(
1027                 c, method_annotationdefaults, method_annotationdefaults);
1028
1029         ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
1030
1031         /* the method_annotations array might be shorter then the method
1032          * count if the methods above a certain index have no annotations.
1033          */
1034         if (method_annotationdefaults != NULL && oa.get_length() > slot) {
1035                 return (java_handle_bytearray_t*) oa.get_element(slot);
1036         } else {
1037                 return NULL;
1038         }
1039 #else
1040         return NULL;
1041 #endif
1042 }
1043
1044
1045 /* method_add_to_worklist ******************************************************
1046
1047    Add the method to the given worklist. If the method already occurs in
1048    the worklist, the worklist remains unchanged.
1049
1050 *******************************************************************************/
1051
1052 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
1053 {
1054         method_worklist *wi;
1055
1056         for (wi = *wl; wi != NULL; wi = wi->next)
1057                 if (wi->m == m)
1058                         return;
1059
1060         wi = NEW(method_worklist);
1061         wi->next = *wl;
1062         wi->m = m;
1063
1064         *wl = wi;
1065 }
1066
1067
1068 /* method_add_assumption_monomorphic *******************************************
1069
1070    Record the assumption that the method is monomorphic.
1071
1072    IN:
1073       m.................the method
1074           caller............the caller making the assumption
1075
1076 *******************************************************************************/
1077
1078 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
1079 {
1080         method_assumption *as;
1081
1082         /* XXX LOCKING FOR THIS FUNCTION? */
1083
1084         /* check if we already have registered this assumption */
1085
1086         for (as = m->assumptions; as != NULL; as = as->next) {
1087                 if (as->context == caller)
1088                         return;
1089         }
1090
1091         /* register the assumption */
1092
1093         as = NEW(method_assumption);
1094         as->next = m->assumptions;
1095         as->context = caller;
1096
1097         m->assumptions = as;
1098 }
1099
1100 /* method_break_assumption_monomorphic *****************************************
1101
1102    Break the assumption that this method is monomorphic. All callers that
1103    have registered this assumption are added to the worklist.
1104
1105    IN:
1106       m.................the method
1107           wl................worklist where to add invalidated callers
1108
1109 *******************************************************************************/
1110
1111 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1112 {
1113         method_assumption *as;
1114
1115         /* XXX LOCKING FOR THIS FUNCTION? */
1116
1117         for (as = m->assumptions; as != NULL; as = as->next) {
1118                 INLINELOG(
1119                         printf("ASSUMPTION BROKEN (monomorphism): ");
1120                         method_print(m);
1121                         printf(" in ");
1122                         method_println(as->context);
1123                 );
1124
1125                 method_add_to_worklist(as->context, wl);
1126
1127 #if defined(ENABLE_TLH) && 0
1128                 /* XXX hack */
1129                 method_assumption *as2;
1130                 as2 = m->assumptions;
1131                 m->assumptions = NULL;
1132                 method_break_assumption_monomorphic(as->context, wl);
1133                 /*
1134                 assert(m->assumptions == NULL);
1135                 m->assumptions = as2;*/
1136 #endif
1137
1138         }
1139 }
1140
1141 /* method_printflags ***********************************************************
1142
1143    Prints the flags of a method to stdout like.
1144
1145 *******************************************************************************/
1146
1147 #if !defined(NDEBUG)
1148 void method_printflags(methodinfo *m)
1149 {
1150         if (m == NULL) {
1151                 printf("NULL");
1152                 return;
1153         }
1154
1155         if (m->flags & ACC_PUBLIC)             printf(" PUBLIC");
1156         if (m->flags & ACC_PRIVATE)            printf(" PRIVATE");
1157         if (m->flags & ACC_PROTECTED)          printf(" PROTECTED");
1158         if (m->flags & ACC_STATIC)             printf(" STATIC");
1159         if (m->flags & ACC_FINAL)              printf(" FINAL");
1160         if (m->flags & ACC_SYNCHRONIZED)       printf(" SYNCHRONIZED");
1161         if (m->flags & ACC_VOLATILE)           printf(" VOLATILE");
1162         if (m->flags & ACC_TRANSIENT)          printf(" TRANSIENT");
1163         if (m->flags & ACC_NATIVE)             printf(" NATIVE");
1164         if (m->flags & ACC_INTERFACE)          printf(" INTERFACE");
1165         if (m->flags & ACC_ABSTRACT)           printf(" ABSTRACT");
1166         if (m->flags & ACC_METHOD_BUILTIN)     printf(" (builtin)");
1167         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1168         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1169 }
1170 #endif /* !defined(NDEBUG) */
1171
1172
1173 /* method_print ****************************************************************
1174
1175    Prints a method to stdout like:
1176
1177    java.lang.Object.<init>()V
1178
1179 *******************************************************************************/
1180
1181 #if !defined(NDEBUG)
1182 void method_print(methodinfo *m)
1183 {
1184         if (m == NULL) {
1185                 printf("NULL");
1186                 return;
1187         }
1188
1189         if (m->clazz != NULL)
1190                 utf_display_printable_ascii_classname(m->clazz->name);
1191         else
1192                 printf("NULL");
1193         printf(".");
1194         utf_display_printable_ascii(m->name);
1195         utf_display_printable_ascii(m->descriptor);
1196
1197         method_printflags(m);
1198 }
1199 #endif /* !defined(NDEBUG) */
1200
1201
1202 /* method_println **************************************************************
1203
1204    Prints a method plus new line to stdout like:
1205
1206    java.lang.Object.<init>()V
1207
1208 *******************************************************************************/
1209
1210 #if !defined(NDEBUG)
1211 void method_println(methodinfo *m)
1212 {
1213         if (opt_debugcolor) printf("\033[31m"); /* red */
1214         method_print(m);
1215         if (opt_debugcolor) printf("\033[m");   
1216         printf("\n");
1217 }
1218 #endif /* !defined(NDEBUG) */
1219
1220
1221 /* method_methodref_print ******************************************************
1222
1223    Prints a method reference to stdout.
1224
1225 *******************************************************************************/
1226
1227 #if !defined(NDEBUG)
1228 void method_methodref_print(constant_FMIref *mr)
1229 {
1230         if (!mr) {
1231                 printf("(constant_FMIref *)NULL");
1232                 return;
1233         }
1234
1235         if (IS_FMIREF_RESOLVED(mr)) {
1236                 printf("<method> ");
1237                 method_print(mr->p.method);
1238         }
1239         else {
1240                 printf("<methodref> ");
1241                 utf_display_printable_ascii_classname(mr->p.classref->name);
1242                 printf(".");
1243                 utf_display_printable_ascii(mr->name);
1244                 utf_display_printable_ascii(mr->descriptor);
1245         }
1246 }
1247 #endif /* !defined(NDEBUG) */
1248
1249
1250 /* method_methodref_println ****************************************************
1251
1252    Prints a method reference to stdout, followed by a newline.
1253
1254 *******************************************************************************/
1255
1256 #if !defined(NDEBUG)
1257 void method_methodref_println(constant_FMIref *mr)
1258 {
1259         method_methodref_print(mr);
1260         printf("\n");
1261 }
1262 #endif /* !defined(NDEBUG) */
1263
1264 #if defined(__cplusplus)
1265 }
1266 #endif
1267
1268 /*
1269  * These are local overrides for various environment variables in Emacs.
1270  * Please do not remove this and leave it at the end of the file, where
1271  * Emacs will automagically detect them.
1272  * ---------------------------------------------------------------------
1273  * Local variables:
1274  * mode: c++
1275  * indent-tabs-mode: t
1276  * c-basic-offset: 4
1277  * tab-width: 4
1278  * End:
1279  * vim:noexpandtab:sw=4:ts=4:
1280  */