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 8315 2007-08-15 22:49:20Z panzi $
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 java_bytearray *method_get_annotations(methodinfo *m)
786 classinfo *c = m->class;
787 int slot = m - c->methods;
788 annotation_bytearray_t *ba = NULL;
789 java_bytearray *annotations = NULL;
791 if (c->method_annotations != NULL && c->method_annotations->size > slot) {
792 ba = c->method_annotations->data[slot];
795 annotations = builtin_newarray_byte(ba->size);
797 if (annotations != NULL) {
798 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
807 /* method_get_parameterannotations ********************************************
809 Gets a methods' parameter annotations (or NULL if none).
811 *******************************************************************************/
813 java_bytearray *method_get_parameterannotations(methodinfo *m)
815 classinfo *c = m->class;
816 int slot = m - c->methods;
817 annotation_bytearray_t *ba = NULL;
818 java_bytearray *parameterAnnotations = NULL;
820 if (c->method_parameterannotations != NULL &&
821 c->method_parameterannotations->size > slot) {
822 ba = c->method_parameterannotations->data[slot];
825 parameterAnnotations = builtin_newarray_byte(ba->size);
827 if (parameterAnnotations != NULL) {
828 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
833 return parameterAnnotations;
837 /* method_get_annotationdefault ***********************************************
839 Gets a methods' annotation default value (or NULL if none).
841 *******************************************************************************/
843 java_bytearray *method_get_annotationdefault(methodinfo *m)
845 classinfo *c = m->class;
846 int slot = m - c->methods;
847 annotation_bytearray_t *ba = NULL;
848 java_bytearray *annotationDefault = NULL;
850 if (c->method_annotationdefaults != NULL &&
851 c->method_annotationdefaults->size > slot) {
852 ba = c->method_annotationdefaults->data[slot];
855 annotationDefault = builtin_newarray_byte(ba->size);
857 if (annotationDefault != NULL) {
858 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
863 return annotationDefault;
868 /* method_add_to_worklist ******************************************************
870 Add the method to the given worklist. If the method already occurs in
871 the worklist, the worklist remains unchanged.
873 *******************************************************************************/
875 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
879 for (wi = *wl; wi != NULL; wi = wi->next)
883 wi = NEW(method_worklist);
891 /* method_add_assumption_monomorphic *******************************************
893 Record the assumption that the method is monomorphic.
896 m.................the method
897 caller............the caller making the assumption
899 *******************************************************************************/
901 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
903 method_assumption *as;
905 /* XXX LOCKING FOR THIS FUNCTION? */
907 /* check if we already have registered this assumption */
909 for (as = m->assumptions; as != NULL; as = as->next) {
910 if (as->context == caller)
914 /* register the assumption */
916 as = NEW(method_assumption);
917 as->next = m->assumptions;
918 as->context = caller;
924 /* method_break_assumption_monomorphic *****************************************
926 Break the assumption that this method is monomorphic. All callers that
927 have registered this assumption are added to the worklist.
930 m.................the method
931 wl................worklist where to add invalidated callers
933 *******************************************************************************/
935 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
937 method_assumption *as;
939 /* XXX LOCKING FOR THIS FUNCTION? */
941 for (as = m->assumptions; as != NULL; as = as->next) {
943 printf("ASSUMPTION BROKEN (monomorphism): ");
946 method_println(as->context);
949 method_add_to_worklist(as->context, wl);
954 /* method_printflags ***********************************************************
956 Prints the flags of a method to stdout like.
958 *******************************************************************************/
961 void method_printflags(methodinfo *m)
968 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
969 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
970 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
971 if (m->flags & ACC_STATIC) printf(" STATIC");
972 if (m->flags & ACC_FINAL) printf(" FINAL");
973 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
974 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
975 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
976 if (m->flags & ACC_NATIVE) printf(" NATIVE");
977 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
978 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
979 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
980 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
982 #endif /* !defined(NDEBUG) */
985 /* method_print ****************************************************************
987 Prints a method to stdout like:
989 java.lang.Object.<init>()V
991 *******************************************************************************/
994 void method_print(methodinfo *m)
1001 utf_display_printable_ascii_classname(m->class->name);
1003 utf_display_printable_ascii(m->name);
1004 utf_display_printable_ascii(m->descriptor);
1006 method_printflags(m);
1008 #endif /* !defined(NDEBUG) */
1011 /* method_println **************************************************************
1013 Prints a method plus new line to stdout like:
1015 java.lang.Object.<init>()V
1017 *******************************************************************************/
1019 #if !defined(NDEBUG)
1020 void method_println(methodinfo *m)
1022 if (opt_debugcolor) printf("\033[31m"); /* red */
1024 if (opt_debugcolor) printf("\033[m");
1027 #endif /* !defined(NDEBUG) */
1030 /* method_methodref_print ******************************************************
1032 Prints a method reference to stdout.
1034 *******************************************************************************/
1036 #if !defined(NDEBUG)
1037 void method_methodref_print(constant_FMIref *mr)
1040 printf("(constant_FMIref *)NULL");
1044 if (IS_FMIREF_RESOLVED(mr)) {
1045 printf("<method> ");
1046 method_print(mr->p.method);
1049 printf("<methodref> ");
1050 utf_display_printable_ascii_classname(mr->p.classref->name);
1052 utf_display_printable_ascii(mr->name);
1053 utf_display_printable_ascii(mr->descriptor);
1056 #endif /* !defined(NDEBUG) */
1059 /* method_methodref_println ****************************************************
1061 Prints a method reference to stdout, followed by a newline.
1063 *******************************************************************************/
1065 #if !defined(NDEBUG)
1066 void method_methodref_println(constant_FMIref *mr)
1068 method_methodref_print(mr);
1071 #endif /* !defined(NDEBUG) */
1075 * These are local overrides for various environment variables in Emacs.
1076 * Please do not remove this and leave it at the end of the file, where
1077 * Emacs will automagically detect them.
1078 * ---------------------------------------------------------------------
1081 * indent-tabs-mode: t
1085 * vim:noexpandtab:sw=4:ts=4: