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