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