1 /* src/vmcore/method.c - method functions
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: method.c 8295 2007-08-11 17:57:24Z michi $
38 #include "mm/memory.h"
40 #include "threads/lock-common.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/global.h"
45 #include "vm/resolve.h"
47 #include "vm/jit/methodheader.h"
49 #include "vm/jit_interface.h"
51 #include "vmcore/class.h"
52 #include "vmcore/linker.h"
53 #include "vmcore/loader.h"
54 #include "vmcore/method.h"
55 #include "vmcore/options.h"
56 #include "vmcore/suck.h"
59 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
60 #define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
62 #define INLINELOG(code)
66 /* method_load *****************************************************************
68 Loads a method from the class file and fills an existing methodinfo
76 attribute_info attributes[attribute_count];
80 u2 attribute_name_index;
82 u1 info[attribute_length];
85 LineNumberTable_attribute {
86 u2 attribute_name_index;
88 u2 line_number_table_length;
92 } line_number_table[line_number_table_length];
95 *******************************************************************************/
97 bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
106 u2 attribute_name_index;
108 u2 code_attributes_count;
109 u2 code_attribute_name_index;
110 utf *code_attribute_name;
116 LOCK_INIT_OBJECT_LOCK(&(m->header));
118 #if defined(ENABLE_STATISTICS)
123 /* all fields of m have been zeroed in load_class_from_classbuffer */
127 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
132 m->flags = suck_u2(cb);
136 name_index = suck_u2(cb);
138 if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
145 descriptor_index = suck_u2(cb);
147 if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
152 if (!descriptor_pool_add(descpool, u, &argcount))
155 #ifdef ENABLE_VERIFIER
157 if (!is_valid_name_utf(m->name)) {
158 exceptions_throw_classformaterror(c, "Method with invalid name");
162 if (m->name->text[0] == '<' &&
163 m->name != utf_init && m->name != utf_clinit) {
164 exceptions_throw_classformaterror(c, "Method with invalid special name");
168 #endif /* ENABLE_VERIFIER */
170 if (!(m->flags & ACC_STATIC))
171 argcount++; /* count the 'this' argument */
173 #ifdef ENABLE_VERIFIER
175 if (argcount > 255) {
176 exceptions_throw_classformaterror(c, "Too many arguments in signature");
180 /* check flag consistency */
181 if (m->name != utf_clinit) {
182 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
184 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
185 exceptions_throw_classformaterror(c,
186 "Illegal method modifiers: 0x%X",
191 if (m->flags & ACC_ABSTRACT) {
192 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
193 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
194 exceptions_throw_classformaterror(c,
195 "Illegal method modifiers: 0x%X",
201 if (c->flags & ACC_INTERFACE) {
202 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
203 exceptions_throw_classformaterror(c,
204 "Illegal method modifiers: 0x%X",
210 if (m->name == utf_init) {
211 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
212 ACC_NATIVE | ACC_ABSTRACT)) {
213 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
219 #endif /* ENABLE_VERIFIER */
221 /* mark the method as monomorphic until further notice */
223 m->flags |= ACC_METHOD_MONOMORPHIC;
225 /* non-abstract methods have an implementation in this class */
227 if (!(m->flags & ACC_ABSTRACT))
228 m->flags |= ACC_METHOD_IMPLEMENTED;
230 if (!suck_check_classbuffer_size(cb, 2))
233 /* attributes count */
235 attributes_count = suck_u2(cb);
237 for (i = 0; i < attributes_count; i++) {
238 if (!suck_check_classbuffer_size(cb, 2))
241 /* attribute name index */
243 attribute_name_index = suck_u2(cb);
246 class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
248 if (attribute_name == NULL)
251 if (attribute_name == utf_Code) {
254 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
255 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
260 exceptions_throw_classformaterror(c, "Multiple Code attributes");
264 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
268 m->maxstack = suck_u2(cb);
269 m->maxlocals = suck_u2(cb);
271 if (m->maxlocals < argcount) {
272 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
276 if (!suck_check_classbuffer_size(cb, 4))
279 m->jcodelength = suck_u4(cb);
281 if (m->jcodelength == 0) {
282 exceptions_throw_classformaterror(c, "Code of a method has length 0");
286 if (m->jcodelength > 65535) {
287 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
291 if (!suck_check_classbuffer_size(cb, m->jcodelength))
294 m->jcode = MNEW(u1, m->jcodelength);
295 suck_nbytes(m->jcode, cb, m->jcodelength);
297 if (!suck_check_classbuffer_size(cb, 2))
300 m->rawexceptiontablelength = suck_u2(cb);
301 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
304 m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
306 #if defined(ENABLE_STATISTICS)
308 count_vmcode_len += m->jcodelength + 18;
310 m->rawexceptiontablelength * sizeof(raw_exception_entry);
314 for (j = 0; j < m->rawexceptiontablelength; j++) {
316 m->rawexceptiontable[j].startpc = suck_u2(cb);
317 m->rawexceptiontable[j].endpc = suck_u2(cb);
318 m->rawexceptiontable[j].handlerpc = suck_u2(cb);
323 m->rawexceptiontable[j].catchtype.any = NULL;
326 /* the classref is created later */
327 if (!(m->rawexceptiontable[j].catchtype.any =
328 (utf *) class_getconstant(c, idx, CONSTANT_Class)))
333 if (!suck_check_classbuffer_size(cb, 2))
336 /* code attributes count */
338 code_attributes_count = suck_u2(cb);
340 for (k = 0; k < code_attributes_count; k++) {
341 if (!suck_check_classbuffer_size(cb, 2))
344 /* code attribute name index */
346 code_attribute_name_index = suck_u2(cb);
348 code_attribute_name =
349 class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
351 if (code_attribute_name == NULL)
354 /* check which code attribute */
356 if (code_attribute_name == utf_LineNumberTable) {
357 /* LineNumberTable */
359 if (!suck_check_classbuffer_size(cb, 4 + 2))
362 /* attribute length */
366 /* line number table length */
368 m->linenumbercount = suck_u2(cb);
370 if (!suck_check_classbuffer_size(cb,
371 (2 + 2) * m->linenumbercount))
374 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
376 #if defined(ENABLE_STATISTICS)
378 size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
381 for (l = 0; l < m->linenumbercount; l++) {
382 m->linenumbers[l].start_pc = suck_u2(cb);
383 m->linenumbers[l].line_number = suck_u2(cb);
386 #if defined(ENABLE_JAVASE)
387 else if (code_attribute_name == utf_StackMapTable) {
390 if (!stackmap_load_attribute_stackmaptable(cb, m))
395 /* unknown code attribute */
397 if (!loader_skip_attribute_body(cb))
402 else if (attribute_name == utf_Exceptions) {
405 if (m->thrownexceptions != NULL) {
406 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
410 if (!suck_check_classbuffer_size(cb, 4 + 2))
413 /* attribute length */
417 m->thrownexceptionscount = suck_u2(cb);
419 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
422 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
424 for (j = 0; j < m->thrownexceptionscount; j++) {
425 /* the classref is created later */
426 if (!((m->thrownexceptions)[j].any =
427 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
431 #if defined(ENABLE_JAVASE)
432 else if (attribute_name == utf_Signature) {
435 if (!loader_load_attribute_signature(cb, &(m->signature)))
439 #if defined(ENABLE_ANNOTATIONS)
440 else if (attribute_name == utf_RuntimeVisibleAnnotations) {
441 /* RuntimeVisibleAnnotations */
442 if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
445 else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
446 /* RuntimeInvisibleAnnotations */
447 if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
450 else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
451 /* RuntimeVisibleParameterAnnotations */
452 if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
455 else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
456 /* RuntimeInvisibleParameterAnnotations */
457 if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
460 else if (attribute_name == utf_AnnotationDefault) {
461 /* AnnotationDefault */
462 if (!annotation_load_method_attribute_annotationdefault(cb, m))
468 /* unknown attribute */
470 if (!loader_skip_attribute_body(cb))
475 if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
476 exceptions_throw_classformaterror(c, "Missing Code attribute");
480 #if defined(ENABLE_REPLACEMENT)
481 /* initialize the hit countdown field */
483 m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
486 /* everything was ok */
492 /* method_free *****************************************************************
494 Frees all memory that was allocated for this method.
496 *******************************************************************************/
498 void method_free(methodinfo *m)
501 MFREE(m->jcode, u1, m->jcodelength);
503 if (m->rawexceptiontable)
504 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
506 code_free_code_of_method(m);
508 if (m->stubroutine) {
509 if (m->flags & ACC_NATIVE) {
510 removenativestub(m->stubroutine);
513 removecompilerstub(m->stubroutine);
519 /* method_canoverwrite *********************************************************
521 Check if m and old are identical with respect to type and
522 name. This means that old can be overwritten with m.
524 *******************************************************************************/
526 bool method_canoverwrite(methodinfo *m, methodinfo *old)
528 if (m->name != old->name)
531 if (m->descriptor != old->descriptor)
534 if (m->flags & ACC_STATIC)
541 /* method_vftbl_lookup *********************************************************
543 Does a method lookup in the passed virtual function table. This
544 function does exactly the same thing as JIT, but additionally
545 relies on the fact, that the methodinfo pointer is at the first
546 data segment slot (even for compiler stubs).
548 *******************************************************************************/
550 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
554 methodinfo *resm; /* pointer to new resolved method */
556 /* If the method is not an instance method, just return it. */
558 if (m->flags & ACC_STATIC)
563 /* Get the method from the virtual function table. Is this an
566 if (m->class->flags & ACC_INTERFACE) {
567 pmptr = vftbl->interfacetable[-(m->class->index)];
568 mptr = pmptr[(m - m->class->methods)];
571 mptr = vftbl->table[m->vftblindex];
574 /* and now get the codeinfo pointer from the first data segment slot */
576 resm = code_get_methodinfo_for_pv(mptr);
582 /* method_get_parametercount **************************************************
584 Use the descriptor of a method to determine the number of parameters
585 of the method. The this pointer of non-static methods is not counted.
589 *******************************************************************************/
591 int32_t method_get_parametercount(methodinfo *m)
594 int32_t paramcount = 0;
598 /* is the descriptor fully parsed? */
600 if (m->parseddesc->params == NULL) {
601 if (!descriptor_params_from_paramtypes(md, m->flags)) {
606 paramcount = md->paramcount;
608 /* skip `this' pointer */
610 if (!(m->flags & ACC_STATIC)) {
618 /* method_get_parametertypearray ***********************************************
620 Use the descriptor of a method to generate a java.lang.Class array
621 which contains the classes of the parametertypes of the method.
623 This function is called by java.lang.reflect.{Constructor,Method}.
625 *******************************************************************************/
627 java_objectarray *method_get_parametertypearray(methodinfo *m)
630 typedesc *paramtypes;
632 java_objectarray *oa;
638 /* is the descriptor fully parsed? */
640 if (m->parseddesc->params == NULL)
641 if (!descriptor_params_from_paramtypes(md, m->flags))
644 paramtypes = md->paramtypes;
645 paramcount = md->paramcount;
647 /* skip `this' pointer */
649 if (!(m->flags & ACC_STATIC)) {
654 /* create class-array */
656 oa = builtin_anewarray(paramcount, class_java_lang_Class);
663 for (i = 0; i < paramcount; i++) {
664 if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
674 /* method_get_exceptionarray ***************************************************
676 Get the exceptions which can be thrown by a method.
678 *******************************************************************************/
680 java_objectarray *method_get_exceptionarray(methodinfo *m)
682 java_objectarray *oa;
686 /* create class-array */
688 oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
693 /* iterate over all exceptions and store the class in the array */
695 for (i = 0; i < m->thrownexceptionscount; i++) {
696 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
708 /* method_returntype_get *******************************************************
710 Get the return type of the method.
712 *******************************************************************************/
714 classinfo *method_returntype_get(methodinfo *m)
719 td = &(m->parseddesc->returntype);
721 if (!resolve_class_from_typedesc(td, true, false, &c))
728 /* method_count_implementations ************************************************
730 Count the implementations of a method in a class cone (a class and all its
734 m................the method to count
735 c................class at which to start the counting (this class and
736 all its subclasses will be searched)
739 *found...........if found != NULL, *found receives the method
740 implementation that was found. This value is only
741 meaningful if the return value is 1.
744 the number of implementations found
746 *******************************************************************************/
748 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
758 mend = mp + c->methodscount;
760 for (; mp < mend; ++mp) {
761 if (method_canoverwrite(mp, m)) {
769 for (child = c->sub; child != NULL; child = child->nextsub) {
770 count += method_count_implementations(m, child, found);
777 #if defined(ENABLE_ANNOTATIONS)
778 /* method_get_annotations ******************************************************
780 Gets a methods' annotations (or NULL if none).
782 *******************************************************************************/
784 annotation_bytearray_t *method_get_annotations(methodinfo *m)
786 classinfo *c = m->class;
787 int slot = m - c->methods;
789 if (c->method_annotations != NULL && c->method_annotations->size > slot) {
790 return c->method_annotations->data[slot];
797 /* method_get_parameterannotations ********************************************
799 Gets a methods' parameter annotations (or NULL if none).
801 *******************************************************************************/
803 annotation_bytearray_t *method_get_parameterannotations(methodinfo *m)
805 classinfo *c = m->class;
806 int slot = m - c->methods;
808 if (c->method_parameterannotations != NULL &&
809 c->method_parameterannotations->size > slot) {
810 return c->method_parameterannotations->data[slot];
817 /* method_get_annotationdefault ***********************************************
819 Gets a methods' annotation default value (or NULL if none).
821 *******************************************************************************/
823 annotation_bytearray_t *method_get_annotationdefault(methodinfo *m)
825 classinfo *c = m->class;
826 int slot = m - c->methods;
828 if (c->method_annotationdefaults != NULL &&
829 c->method_annotationdefaults->size > slot) {
830 return c->method_annotationdefaults->data[slot];
838 /* method_add_to_worklist ******************************************************
840 Add the method to the given worklist. If the method already occurs in
841 the worklist, the worklist remains unchanged.
843 *******************************************************************************/
845 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
849 for (wi = *wl; wi != NULL; wi = wi->next)
853 wi = NEW(method_worklist);
861 /* method_add_assumption_monomorphic *******************************************
863 Record the assumption that the method is monomorphic.
866 m.................the method
867 caller............the caller making the assumption
869 *******************************************************************************/
871 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
873 method_assumption *as;
875 /* XXX LOCKING FOR THIS FUNCTION? */
877 /* check if we already have registered this assumption */
879 for (as = m->assumptions; as != NULL; as = as->next) {
880 if (as->context == caller)
884 /* register the assumption */
886 as = NEW(method_assumption);
887 as->next = m->assumptions;
888 as->context = caller;
894 /* method_break_assumption_monomorphic *****************************************
896 Break the assumption that this method is monomorphic. All callers that
897 have registered this assumption are added to the worklist.
900 m.................the method
901 wl................worklist where to add invalidated callers
903 *******************************************************************************/
905 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
907 method_assumption *as;
909 /* XXX LOCKING FOR THIS FUNCTION? */
911 for (as = m->assumptions; as != NULL; as = as->next) {
913 printf("ASSUMPTION BROKEN (monomorphism): ");
916 method_println(as->context);
919 method_add_to_worklist(as->context, wl);
924 /* method_printflags ***********************************************************
926 Prints the flags of a method to stdout like.
928 *******************************************************************************/
931 void method_printflags(methodinfo *m)
938 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
939 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
940 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
941 if (m->flags & ACC_STATIC) printf(" STATIC");
942 if (m->flags & ACC_FINAL) printf(" FINAL");
943 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
944 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
945 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
946 if (m->flags & ACC_NATIVE) printf(" NATIVE");
947 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
948 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
949 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
950 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
952 #endif /* !defined(NDEBUG) */
955 /* method_print ****************************************************************
957 Prints a method to stdout like:
959 java.lang.Object.<init>()V
961 *******************************************************************************/
964 void method_print(methodinfo *m)
971 utf_display_printable_ascii_classname(m->class->name);
973 utf_display_printable_ascii(m->name);
974 utf_display_printable_ascii(m->descriptor);
976 method_printflags(m);
978 #endif /* !defined(NDEBUG) */
981 /* method_println **************************************************************
983 Prints a method plus new line to stdout like:
985 java.lang.Object.<init>()V
987 *******************************************************************************/
990 void method_println(methodinfo *m)
992 if (opt_debugcolor) printf("\033[31m"); /* red */
994 if (opt_debugcolor) printf("\033[m");
997 #endif /* !defined(NDEBUG) */
1000 /* method_methodref_print ******************************************************
1002 Prints a method reference to stdout.
1004 *******************************************************************************/
1006 #if !defined(NDEBUG)
1007 void method_methodref_print(constant_FMIref *mr)
1010 printf("(constant_FMIref *)NULL");
1014 if (IS_FMIREF_RESOLVED(mr)) {
1015 printf("<method> ");
1016 method_print(mr->p.method);
1019 printf("<methodref> ");
1020 utf_display_printable_ascii_classname(mr->p.classref->name);
1022 utf_display_printable_ascii(mr->name);
1023 utf_display_printable_ascii(mr->descriptor);
1026 #endif /* !defined(NDEBUG) */
1029 /* method_methodref_println ****************************************************
1031 Prints a method reference to stdout, followed by a newline.
1033 *******************************************************************************/
1035 #if !defined(NDEBUG)
1036 void method_methodref_println(constant_FMIref *mr)
1038 method_methodref_print(mr);
1041 #endif /* !defined(NDEBUG) */
1045 * These are local overrides for various environment variables in Emacs.
1046 * Please do not remove this and leave it at the end of the file, where
1047 * Emacs will automagically detect them.
1048 * ---------------------------------------------------------------------
1051 * indent-tabs-mode: t
1055 * vim:noexpandtab:sw=4:ts=4: