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
36 #include "mm/memory.h"
38 #include "native/llni.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_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
630 typedesc *paramtypes;
632 java_handle_objectarray_t *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))
667 LLNI_array_direct(oa, i) = (java_object_t *) c;
674 /* method_get_exceptionarray ***************************************************
676 Get the exceptions which can be thrown by a method.
678 *******************************************************************************/
680 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
682 java_handle_objectarray_t *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);
701 LLNI_array_direct(oa, i) = (java_object_t *) c;
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 /* method_get_annotations ******************************************************
779 Gets a methods' annotations (or NULL if none).
781 *******************************************************************************/
783 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
785 #if defined(ENABLE_ANNOTATIONS)
788 annotation_bytearray_t *ba;
789 java_handle_bytearray_t *annotations;
792 slot = m - c->methods;
795 if (c->method_annotations != NULL && c->method_annotations->size > slot) {
796 ba = c->method_annotations->data[slot];
799 annotations = builtin_newarray_byte(ba->size);
801 if (annotations != NULL) {
802 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
814 /* method_get_parameterannotations ********************************************
816 Gets a methods' parameter annotations (or NULL if none).
818 *******************************************************************************/
820 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
822 #if defined(ENABLE_ANNOTATIONS)
825 annotation_bytearray_t *ba;
826 java_handle_bytearray_t *parameterAnnotations;
829 slot = m - c->methods;
830 parameterAnnotations = NULL;
832 if (c->method_parameterannotations != NULL &&
833 c->method_parameterannotations->size > slot) {
834 ba = c->method_parameterannotations->data[slot];
837 parameterAnnotations = builtin_newarray_byte(ba->size);
839 if (parameterAnnotations != NULL) {
840 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
845 return parameterAnnotations;
852 /* method_get_annotationdefault ***********************************************
854 Gets a methods' annotation default value (or NULL if none).
856 *******************************************************************************/
858 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
860 #if defined(ENABLE_ANNOTATIONS)
863 annotation_bytearray_t *ba;
864 java_handle_bytearray_t *annotationDefault;
867 slot = m - c->methods;
868 annotationDefault = NULL;
870 if (c->method_annotationdefaults != NULL &&
871 c->method_annotationdefaults->size > slot) {
872 ba = c->method_annotationdefaults->data[slot];
875 annotationDefault = builtin_newarray_byte(ba->size);
877 if (annotationDefault != NULL) {
878 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
883 return annotationDefault;
890 /* method_add_to_worklist ******************************************************
892 Add the method to the given worklist. If the method already occurs in
893 the worklist, the worklist remains unchanged.
895 *******************************************************************************/
897 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
901 for (wi = *wl; wi != NULL; wi = wi->next)
905 wi = NEW(method_worklist);
913 /* method_add_assumption_monomorphic *******************************************
915 Record the assumption that the method is monomorphic.
918 m.................the method
919 caller............the caller making the assumption
921 *******************************************************************************/
923 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
925 method_assumption *as;
927 /* XXX LOCKING FOR THIS FUNCTION? */
929 /* check if we already have registered this assumption */
931 for (as = m->assumptions; as != NULL; as = as->next) {
932 if (as->context == caller)
936 /* register the assumption */
938 as = NEW(method_assumption);
939 as->next = m->assumptions;
940 as->context = caller;
946 /* method_break_assumption_monomorphic *****************************************
948 Break the assumption that this method is monomorphic. All callers that
949 have registered this assumption are added to the worklist.
952 m.................the method
953 wl................worklist where to add invalidated callers
955 *******************************************************************************/
957 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
959 method_assumption *as;
961 /* XXX LOCKING FOR THIS FUNCTION? */
963 for (as = m->assumptions; as != NULL; as = as->next) {
965 printf("ASSUMPTION BROKEN (monomorphism): ");
968 method_println(as->context);
971 method_add_to_worklist(as->context, wl);
976 /* method_printflags ***********************************************************
978 Prints the flags of a method to stdout like.
980 *******************************************************************************/
983 void method_printflags(methodinfo *m)
990 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
991 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
992 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
993 if (m->flags & ACC_STATIC) printf(" STATIC");
994 if (m->flags & ACC_FINAL) printf(" FINAL");
995 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
996 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
997 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
998 if (m->flags & ACC_NATIVE) printf(" NATIVE");
999 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
1000 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
1001 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1002 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1004 #endif /* !defined(NDEBUG) */
1007 /* method_print ****************************************************************
1009 Prints a method to stdout like:
1011 java.lang.Object.<init>()V
1013 *******************************************************************************/
1015 #if !defined(NDEBUG)
1016 void method_print(methodinfo *m)
1023 utf_display_printable_ascii_classname(m->class->name);
1025 utf_display_printable_ascii(m->name);
1026 utf_display_printable_ascii(m->descriptor);
1028 method_printflags(m);
1030 #endif /* !defined(NDEBUG) */
1033 /* method_println **************************************************************
1035 Prints a method plus new line to stdout like:
1037 java.lang.Object.<init>()V
1039 *******************************************************************************/
1041 #if !defined(NDEBUG)
1042 void method_println(methodinfo *m)
1044 if (opt_debugcolor) printf("\033[31m"); /* red */
1046 if (opt_debugcolor) printf("\033[m");
1049 #endif /* !defined(NDEBUG) */
1052 /* method_methodref_print ******************************************************
1054 Prints a method reference to stdout.
1056 *******************************************************************************/
1058 #if !defined(NDEBUG)
1059 void method_methodref_print(constant_FMIref *mr)
1062 printf("(constant_FMIref *)NULL");
1066 if (IS_FMIREF_RESOLVED(mr)) {
1067 printf("<method> ");
1068 method_print(mr->p.method);
1071 printf("<methodref> ");
1072 utf_display_printable_ascii_classname(mr->p.classref->name);
1074 utf_display_printable_ascii(mr->name);
1075 utf_display_printable_ascii(mr->descriptor);
1078 #endif /* !defined(NDEBUG) */
1081 /* method_methodref_println ****************************************************
1083 Prints a method reference to stdout, followed by a newline.
1085 *******************************************************************************/
1087 #if !defined(NDEBUG)
1088 void method_methodref_println(constant_FMIref *mr)
1090 method_methodref_print(mr);
1093 #endif /* !defined(NDEBUG) */
1097 * These are local overrides for various environment variables in Emacs.
1098 * Please do not remove this and leave it at the end of the file, where
1099 * Emacs will automagically detect them.
1100 * ---------------------------------------------------------------------
1103 * indent-tabs-mode: t
1107 * vim:noexpandtab:sw=4:ts=4: