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 8343 2007-08-17 21:39:32Z michi $
38 #include "mm/memory.h"
40 #include "native/llni.h"
42 #include "threads/lock-common.h"
44 #include "vm/builtin.h"
45 #include "vm/exceptions.h"
46 #include "vm/global.h"
47 #include "vm/resolve.h"
49 #include "vm/jit/methodheader.h"
51 #include "vm/jit_interface.h"
53 #include "vmcore/class.h"
54 #include "vmcore/linker.h"
55 #include "vmcore/loader.h"
56 #include "vmcore/method.h"
57 #include "vmcore/options.h"
58 #include "vmcore/suck.h"
61 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
62 #define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
64 #define INLINELOG(code)
68 /* method_load *****************************************************************
70 Loads a method from the class file and fills an existing methodinfo
78 attribute_info attributes[attribute_count];
82 u2 attribute_name_index;
84 u1 info[attribute_length];
87 LineNumberTable_attribute {
88 u2 attribute_name_index;
90 u2 line_number_table_length;
94 } line_number_table[line_number_table_length];
97 *******************************************************************************/
99 bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
108 u2 attribute_name_index;
110 u2 code_attributes_count;
111 u2 code_attribute_name_index;
112 utf *code_attribute_name;
118 LOCK_INIT_OBJECT_LOCK(&(m->header));
120 #if defined(ENABLE_STATISTICS)
125 /* all fields of m have been zeroed in load_class_from_classbuffer */
129 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
134 m->flags = suck_u2(cb);
138 name_index = suck_u2(cb);
140 if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
147 descriptor_index = suck_u2(cb);
149 if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
154 if (!descriptor_pool_add(descpool, u, &argcount))
157 #ifdef ENABLE_VERIFIER
159 if (!is_valid_name_utf(m->name)) {
160 exceptions_throw_classformaterror(c, "Method with invalid name");
164 if (m->name->text[0] == '<' &&
165 m->name != utf_init && m->name != utf_clinit) {
166 exceptions_throw_classformaterror(c, "Method with invalid special name");
170 #endif /* ENABLE_VERIFIER */
172 if (!(m->flags & ACC_STATIC))
173 argcount++; /* count the 'this' argument */
175 #ifdef ENABLE_VERIFIER
177 if (argcount > 255) {
178 exceptions_throw_classformaterror(c, "Too many arguments in signature");
182 /* check flag consistency */
183 if (m->name != utf_clinit) {
184 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
186 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
187 exceptions_throw_classformaterror(c,
188 "Illegal method modifiers: 0x%X",
193 if (m->flags & ACC_ABSTRACT) {
194 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
195 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
196 exceptions_throw_classformaterror(c,
197 "Illegal method modifiers: 0x%X",
203 if (c->flags & ACC_INTERFACE) {
204 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
205 exceptions_throw_classformaterror(c,
206 "Illegal method modifiers: 0x%X",
212 if (m->name == utf_init) {
213 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
214 ACC_NATIVE | ACC_ABSTRACT)) {
215 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
221 #endif /* ENABLE_VERIFIER */
223 /* mark the method as monomorphic until further notice */
225 m->flags |= ACC_METHOD_MONOMORPHIC;
227 /* non-abstract methods have an implementation in this class */
229 if (!(m->flags & ACC_ABSTRACT))
230 m->flags |= ACC_METHOD_IMPLEMENTED;
232 if (!suck_check_classbuffer_size(cb, 2))
235 /* attributes count */
237 attributes_count = suck_u2(cb);
239 for (i = 0; i < attributes_count; i++) {
240 if (!suck_check_classbuffer_size(cb, 2))
243 /* attribute name index */
245 attribute_name_index = suck_u2(cb);
248 class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
250 if (attribute_name == NULL)
253 if (attribute_name == utf_Code) {
256 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
257 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
262 exceptions_throw_classformaterror(c, "Multiple Code attributes");
266 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
270 m->maxstack = suck_u2(cb);
271 m->maxlocals = suck_u2(cb);
273 if (m->maxlocals < argcount) {
274 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
278 if (!suck_check_classbuffer_size(cb, 4))
281 m->jcodelength = suck_u4(cb);
283 if (m->jcodelength == 0) {
284 exceptions_throw_classformaterror(c, "Code of a method has length 0");
288 if (m->jcodelength > 65535) {
289 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
293 if (!suck_check_classbuffer_size(cb, m->jcodelength))
296 m->jcode = MNEW(u1, m->jcodelength);
297 suck_nbytes(m->jcode, cb, m->jcodelength);
299 if (!suck_check_classbuffer_size(cb, 2))
302 m->rawexceptiontablelength = suck_u2(cb);
303 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
306 m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
308 #if defined(ENABLE_STATISTICS)
310 count_vmcode_len += m->jcodelength + 18;
312 m->rawexceptiontablelength * sizeof(raw_exception_entry);
316 for (j = 0; j < m->rawexceptiontablelength; j++) {
318 m->rawexceptiontable[j].startpc = suck_u2(cb);
319 m->rawexceptiontable[j].endpc = suck_u2(cb);
320 m->rawexceptiontable[j].handlerpc = suck_u2(cb);
325 m->rawexceptiontable[j].catchtype.any = NULL;
328 /* the classref is created later */
329 if (!(m->rawexceptiontable[j].catchtype.any =
330 (utf *) class_getconstant(c, idx, CONSTANT_Class)))
335 if (!suck_check_classbuffer_size(cb, 2))
338 /* code attributes count */
340 code_attributes_count = suck_u2(cb);
342 for (k = 0; k < code_attributes_count; k++) {
343 if (!suck_check_classbuffer_size(cb, 2))
346 /* code attribute name index */
348 code_attribute_name_index = suck_u2(cb);
350 code_attribute_name =
351 class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
353 if (code_attribute_name == NULL)
356 /* check which code attribute */
358 if (code_attribute_name == utf_LineNumberTable) {
359 /* LineNumberTable */
361 if (!suck_check_classbuffer_size(cb, 4 + 2))
364 /* attribute length */
368 /* line number table length */
370 m->linenumbercount = suck_u2(cb);
372 if (!suck_check_classbuffer_size(cb,
373 (2 + 2) * m->linenumbercount))
376 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
378 #if defined(ENABLE_STATISTICS)
380 size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
383 for (l = 0; l < m->linenumbercount; l++) {
384 m->linenumbers[l].start_pc = suck_u2(cb);
385 m->linenumbers[l].line_number = suck_u2(cb);
388 #if defined(ENABLE_JAVASE)
389 else if (code_attribute_name == utf_StackMapTable) {
392 if (!stackmap_load_attribute_stackmaptable(cb, m))
397 /* unknown code attribute */
399 if (!loader_skip_attribute_body(cb))
404 else if (attribute_name == utf_Exceptions) {
407 if (m->thrownexceptions != NULL) {
408 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
412 if (!suck_check_classbuffer_size(cb, 4 + 2))
415 /* attribute length */
419 m->thrownexceptionscount = suck_u2(cb);
421 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
424 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
426 for (j = 0; j < m->thrownexceptionscount; j++) {
427 /* the classref is created later */
428 if (!((m->thrownexceptions)[j].any =
429 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
433 #if defined(ENABLE_JAVASE)
434 else if (attribute_name == utf_Signature) {
437 if (!loader_load_attribute_signature(cb, &(m->signature)))
441 #if defined(ENABLE_ANNOTATIONS)
442 else if (attribute_name == utf_RuntimeVisibleAnnotations) {
443 /* RuntimeVisibleAnnotations */
444 if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
447 else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
448 /* RuntimeInvisibleAnnotations */
449 if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
452 else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
453 /* RuntimeVisibleParameterAnnotations */
454 if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
457 else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
458 /* RuntimeInvisibleParameterAnnotations */
459 if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
462 else if (attribute_name == utf_AnnotationDefault) {
463 /* AnnotationDefault */
464 if (!annotation_load_method_attribute_annotationdefault(cb, m))
470 /* unknown attribute */
472 if (!loader_skip_attribute_body(cb))
477 if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
478 exceptions_throw_classformaterror(c, "Missing Code attribute");
482 #if defined(ENABLE_REPLACEMENT)
483 /* initialize the hit countdown field */
485 m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
488 /* everything was ok */
494 /* method_free *****************************************************************
496 Frees all memory that was allocated for this method.
498 *******************************************************************************/
500 void method_free(methodinfo *m)
503 MFREE(m->jcode, u1, m->jcodelength);
505 if (m->rawexceptiontable)
506 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
508 code_free_code_of_method(m);
510 if (m->stubroutine) {
511 if (m->flags & ACC_NATIVE) {
512 removenativestub(m->stubroutine);
515 removecompilerstub(m->stubroutine);
521 /* method_canoverwrite *********************************************************
523 Check if m and old are identical with respect to type and
524 name. This means that old can be overwritten with m.
526 *******************************************************************************/
528 bool method_canoverwrite(methodinfo *m, methodinfo *old)
530 if (m->name != old->name)
533 if (m->descriptor != old->descriptor)
536 if (m->flags & ACC_STATIC)
543 /* method_vftbl_lookup *********************************************************
545 Does a method lookup in the passed virtual function table. This
546 function does exactly the same thing as JIT, but additionally
547 relies on the fact, that the methodinfo pointer is at the first
548 data segment slot (even for compiler stubs).
550 *******************************************************************************/
552 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
556 methodinfo *resm; /* pointer to new resolved method */
558 /* If the method is not an instance method, just return it. */
560 if (m->flags & ACC_STATIC)
565 /* Get the method from the virtual function table. Is this an
568 if (m->class->flags & ACC_INTERFACE) {
569 pmptr = vftbl->interfacetable[-(m->class->index)];
570 mptr = pmptr[(m - m->class->methods)];
573 mptr = vftbl->table[m->vftblindex];
576 /* and now get the codeinfo pointer from the first data segment slot */
578 resm = code_get_methodinfo_for_pv(mptr);
584 /* method_get_parametercount **************************************************
586 Use the descriptor of a method to determine the number of parameters
587 of the method. The this pointer of non-static methods is not counted.
591 *******************************************************************************/
593 int32_t method_get_parametercount(methodinfo *m)
596 int32_t paramcount = 0;
600 /* is the descriptor fully parsed? */
602 if (m->parseddesc->params == NULL) {
603 if (!descriptor_params_from_paramtypes(md, m->flags)) {
608 paramcount = md->paramcount;
610 /* skip `this' pointer */
612 if (!(m->flags & ACC_STATIC)) {
620 /* method_get_parametertypearray ***********************************************
622 Use the descriptor of a method to generate a java.lang.Class array
623 which contains the classes of the parametertypes of the method.
625 This function is called by java.lang.reflect.{Constructor,Method}.
627 *******************************************************************************/
629 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
632 typedesc *paramtypes;
634 java_handle_objectarray_t *oa;
640 /* is the descriptor fully parsed? */
642 if (m->parseddesc->params == NULL)
643 if (!descriptor_params_from_paramtypes(md, m->flags))
646 paramtypes = md->paramtypes;
647 paramcount = md->paramcount;
649 /* skip `this' pointer */
651 if (!(m->flags & ACC_STATIC)) {
656 /* create class-array */
658 oa = builtin_anewarray(paramcount, class_java_lang_Class);
665 for (i = 0; i < paramcount; i++) {
666 if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
669 LLNI_array_direct(oa, i) = (java_object_t *) c;
676 /* method_get_exceptionarray ***************************************************
678 Get the exceptions which can be thrown by a method.
680 *******************************************************************************/
682 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
684 java_handle_objectarray_t *oa;
688 /* create class-array */
690 oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
695 /* iterate over all exceptions and store the class in the array */
697 for (i = 0; i < m->thrownexceptionscount; i++) {
698 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
703 LLNI_array_direct(oa, i) = (java_object_t *) c;
710 /* method_returntype_get *******************************************************
712 Get the return type of the method.
714 *******************************************************************************/
716 classinfo *method_returntype_get(methodinfo *m)
721 td = &(m->parseddesc->returntype);
723 if (!resolve_class_from_typedesc(td, true, false, &c))
730 /* method_count_implementations ************************************************
732 Count the implementations of a method in a class cone (a class and all its
736 m................the method to count
737 c................class at which to start the counting (this class and
738 all its subclasses will be searched)
741 *found...........if found != NULL, *found receives the method
742 implementation that was found. This value is only
743 meaningful if the return value is 1.
746 the number of implementations found
748 *******************************************************************************/
750 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
760 mend = mp + c->methodscount;
762 for (; mp < mend; ++mp) {
763 if (method_canoverwrite(mp, m)) {
771 for (child = c->sub; child != NULL; child = child->nextsub) {
772 count += method_count_implementations(m, child, found);
779 /* method_get_annotations ******************************************************
781 Gets a methods' annotations (or NULL if none).
783 *******************************************************************************/
785 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
787 #if defined(ENABLE_ANNOTATIONS)
790 annotation_bytearray_t *ba;
791 java_handle_bytearray_t *annotations;
794 slot = m - c->methods;
797 if (c->method_annotations != NULL && c->method_annotations->size > slot) {
798 ba = c->method_annotations->data[slot];
801 annotations = builtin_newarray_byte(ba->size);
803 if (annotations != NULL) {
804 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
816 /* method_get_parameterannotations ********************************************
818 Gets a methods' parameter annotations (or NULL if none).
820 *******************************************************************************/
822 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
824 #if defined(ENABLE_ANNOTATIONS)
827 annotation_bytearray_t *ba;
828 java_handle_bytearray_t *parameterAnnotations;
831 slot = m - c->methods;
832 parameterAnnotations = NULL;
834 if (c->method_parameterannotations != NULL &&
835 c->method_parameterannotations->size > slot) {
836 ba = c->method_parameterannotations->data[slot];
839 parameterAnnotations = builtin_newarray_byte(ba->size);
841 if (parameterAnnotations != NULL) {
842 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
847 return parameterAnnotations;
854 /* method_get_annotationdefault ***********************************************
856 Gets a methods' annotation default value (or NULL if none).
858 *******************************************************************************/
860 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
862 #if defined(ENABLE_ANNOTATIONS)
865 annotation_bytearray_t *ba;
866 java_handle_bytearray_t *annotationDefault;
869 slot = m - c->methods;
870 annotationDefault = NULL;
872 if (c->method_annotationdefaults != NULL &&
873 c->method_annotationdefaults->size > slot) {
874 ba = c->method_annotationdefaults->data[slot];
877 annotationDefault = builtin_newarray_byte(ba->size);
879 if (annotationDefault != NULL) {
880 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
885 return annotationDefault;
892 /* method_add_to_worklist ******************************************************
894 Add the method to the given worklist. If the method already occurs in
895 the worklist, the worklist remains unchanged.
897 *******************************************************************************/
899 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
903 for (wi = *wl; wi != NULL; wi = wi->next)
907 wi = NEW(method_worklist);
915 /* method_add_assumption_monomorphic *******************************************
917 Record the assumption that the method is monomorphic.
920 m.................the method
921 caller............the caller making the assumption
923 *******************************************************************************/
925 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
927 method_assumption *as;
929 /* XXX LOCKING FOR THIS FUNCTION? */
931 /* check if we already have registered this assumption */
933 for (as = m->assumptions; as != NULL; as = as->next) {
934 if (as->context == caller)
938 /* register the assumption */
940 as = NEW(method_assumption);
941 as->next = m->assumptions;
942 as->context = caller;
948 /* method_break_assumption_monomorphic *****************************************
950 Break the assumption that this method is monomorphic. All callers that
951 have registered this assumption are added to the worklist.
954 m.................the method
955 wl................worklist where to add invalidated callers
957 *******************************************************************************/
959 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
961 method_assumption *as;
963 /* XXX LOCKING FOR THIS FUNCTION? */
965 for (as = m->assumptions; as != NULL; as = as->next) {
967 printf("ASSUMPTION BROKEN (monomorphism): ");
970 method_println(as->context);
973 method_add_to_worklist(as->context, wl);
978 /* method_printflags ***********************************************************
980 Prints the flags of a method to stdout like.
982 *******************************************************************************/
985 void method_printflags(methodinfo *m)
992 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
993 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
994 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
995 if (m->flags & ACC_STATIC) printf(" STATIC");
996 if (m->flags & ACC_FINAL) printf(" FINAL");
997 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
998 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
999 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
1000 if (m->flags & ACC_NATIVE) printf(" NATIVE");
1001 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
1002 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
1003 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1004 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1006 #endif /* !defined(NDEBUG) */
1009 /* method_print ****************************************************************
1011 Prints a method to stdout like:
1013 java.lang.Object.<init>()V
1015 *******************************************************************************/
1017 #if !defined(NDEBUG)
1018 void method_print(methodinfo *m)
1025 utf_display_printable_ascii_classname(m->class->name);
1027 utf_display_printable_ascii(m->name);
1028 utf_display_printable_ascii(m->descriptor);
1030 method_printflags(m);
1032 #endif /* !defined(NDEBUG) */
1035 /* method_println **************************************************************
1037 Prints a method plus new line to stdout like:
1039 java.lang.Object.<init>()V
1041 *******************************************************************************/
1043 #if !defined(NDEBUG)
1044 void method_println(methodinfo *m)
1046 if (opt_debugcolor) printf("\033[31m"); /* red */
1048 if (opt_debugcolor) printf("\033[m");
1051 #endif /* !defined(NDEBUG) */
1054 /* method_methodref_print ******************************************************
1056 Prints a method reference to stdout.
1058 *******************************************************************************/
1060 #if !defined(NDEBUG)
1061 void method_methodref_print(constant_FMIref *mr)
1064 printf("(constant_FMIref *)NULL");
1068 if (IS_FMIREF_RESOLVED(mr)) {
1069 printf("<method> ");
1070 method_print(mr->p.method);
1073 printf("<methodref> ");
1074 utf_display_printable_ascii_classname(mr->p.classref->name);
1076 utf_display_printable_ascii(mr->name);
1077 utf_display_printable_ascii(mr->descriptor);
1080 #endif /* !defined(NDEBUG) */
1083 /* method_methodref_println ****************************************************
1085 Prints a method reference to stdout, followed by a newline.
1087 *******************************************************************************/
1089 #if !defined(NDEBUG)
1090 void method_methodref_println(constant_FMIref *mr)
1092 method_methodref_print(mr);
1095 #endif /* !defined(NDEBUG) */
1099 * These are local overrides for various environment variables in Emacs.
1100 * Please do not remove this and leave it at the end of the file, where
1101 * Emacs will automagically detect them.
1102 * ---------------------------------------------------------------------
1105 * indent-tabs-mode: t
1109 * vim:noexpandtab:sw=4:ts=4: