1 /* src/vm/method.cpp - method functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "mm/memory.h"
36 #include "native/llni.h"
38 #include "threads/mutex.hpp"
40 #include "vm/array.hpp"
41 #include "vm/jit/builtin.hpp"
42 #include "vm/class.hpp"
43 #include "vm/exceptions.hpp"
44 #include "vm/global.h"
45 #include "vm/globals.hpp"
46 #include "vm/linker.hpp"
47 #include "vm/loader.hpp"
48 #include "vm/method.hpp"
49 #include "vm/options.h"
50 #include "vm/resolve.hpp"
51 #include "vm/suck.hpp"
55 #include "vm/jit/code.hpp"
56 #include "vm/jit/methodheader.h"
57 #include "vm/jit/stubs.hpp"
60 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
61 #define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
63 #define INLINELOG(code)
66 /* global variables ***********************************************************/
68 methodinfo *method_java_lang_reflect_Method_invoke;
71 #if defined(__cplusplus)
76 /* method_init *****************************************************************
78 Initialize method subsystem.
80 *******************************************************************************/
82 void method_init(void)
84 #if defined(ENABLE_JAVASE)
87 if (class_java_lang_reflect_Method == NULL)
88 vm_abort("method_init: class_java_lang_reflect_Method is NULL");
90 /* Cache java.lang.reflect.Method.invoke() */
92 method_java_lang_reflect_Method_invoke =
93 class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
95 if (method_java_lang_reflect_Method_invoke == NULL)
96 vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
101 /* method_load *****************************************************************
103 Loads a method from the class file and fills an existing methodinfo
111 attribute_info attributes[attribute_count];
115 u2 attribute_name_index;
117 u1 info[attribute_length];
120 LineNumberTable_attribute {
121 u2 attribute_name_index;
123 u2 line_number_table_length;
127 } line_number_table[line_number_table_length];
130 *******************************************************************************/
132 bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
141 u2 attribute_name_index;
143 u2 code_attributes_count;
144 u2 code_attribute_name_index;
145 utf *code_attribute_name;
151 m->mutex = new Mutex();
153 #if defined(ENABLE_STATISTICS)
158 /* all fields of m have been zeroed in load_class_from_classbuffer */
162 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
167 m->flags = suck_u2(cb);
171 name_index = suck_u2(cb);
173 if (!(u = (utf*) class_getconstant(c, name_index, CONSTANT_Utf8)))
180 descriptor_index = suck_u2(cb);
182 if (!(u = (utf*) class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
187 if (!descriptor_pool_add(descpool, u, &argcount))
190 #ifdef ENABLE_VERIFIER
192 if (!is_valid_name_utf(m->name)) {
193 exceptions_throw_classformaterror(c, "Method with invalid name");
197 if (m->name->text[0] == '<' &&
198 m->name != utf_init && m->name != utf_clinit) {
199 exceptions_throw_classformaterror(c, "Method with invalid special name");
203 #endif /* ENABLE_VERIFIER */
205 if (!(m->flags & ACC_STATIC))
206 argcount++; /* count the 'this' argument */
208 #ifdef ENABLE_VERIFIER
210 if (argcount > 255) {
211 exceptions_throw_classformaterror(c, "Too many arguments in signature");
215 /* check flag consistency */
216 if (m->name != utf_clinit) {
217 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
219 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
220 exceptions_throw_classformaterror(c,
221 "Illegal method modifiers: 0x%X",
226 if (m->flags & ACC_ABSTRACT) {
227 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
228 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
229 exceptions_throw_classformaterror(c,
230 "Illegal method modifiers: 0x%X",
236 if (c->flags & ACC_INTERFACE) {
237 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
238 exceptions_throw_classformaterror(c,
239 "Illegal method modifiers: 0x%X",
245 if (m->name == utf_init) {
246 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
247 ACC_NATIVE | ACC_ABSTRACT)) {
248 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
254 #endif /* ENABLE_VERIFIER */
256 /* mark the method as monomorphic until further notice */
258 m->flags |= ACC_METHOD_MONOMORPHIC;
260 /* non-abstract methods have an implementation in this class */
262 if (!(m->flags & ACC_ABSTRACT))
263 m->flags |= ACC_METHOD_IMPLEMENTED;
265 if (!suck_check_classbuffer_size(cb, 2))
268 /* attributes count */
270 attributes_count = suck_u2(cb);
272 for (i = 0; i < attributes_count; i++) {
273 if (!suck_check_classbuffer_size(cb, 2))
276 /* attribute name index */
278 attribute_name_index = suck_u2(cb);
281 (utf*) class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
283 if (attribute_name == NULL)
286 if (attribute_name == utf_Code) {
289 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
290 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
295 exceptions_throw_classformaterror(c, "Multiple Code attributes");
299 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
303 m->maxstack = suck_u2(cb);
304 m->maxlocals = suck_u2(cb);
306 if (m->maxlocals < argcount) {
307 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
311 if (!suck_check_classbuffer_size(cb, 4))
314 m->jcodelength = suck_u4(cb);
316 if (m->jcodelength == 0) {
317 exceptions_throw_classformaterror(c, "Code of a method has length 0");
321 if (m->jcodelength > 65535) {
322 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
326 if (!suck_check_classbuffer_size(cb, m->jcodelength))
329 m->jcode = MNEW(u1, m->jcodelength);
330 suck_nbytes(m->jcode, cb, m->jcodelength);
332 if (!suck_check_classbuffer_size(cb, 2))
335 m->rawexceptiontablelength = suck_u2(cb);
336 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
339 m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
341 #if defined(ENABLE_STATISTICS)
343 count_vmcode_len += m->jcodelength + 18;
345 m->rawexceptiontablelength * sizeof(raw_exception_entry);
349 for (j = 0; j < m->rawexceptiontablelength; j++) {
351 m->rawexceptiontable[j].startpc = suck_u2(cb);
352 m->rawexceptiontable[j].endpc = suck_u2(cb);
353 m->rawexceptiontable[j].handlerpc = suck_u2(cb);
358 m->rawexceptiontable[j].catchtype.any = NULL;
361 /* the classref is created later */
362 if (!(m->rawexceptiontable[j].catchtype.any =
363 (utf *) class_getconstant(c, idx, CONSTANT_Class)))
368 if (!suck_check_classbuffer_size(cb, 2))
371 /* code attributes count */
373 code_attributes_count = suck_u2(cb);
375 for (k = 0; k < code_attributes_count; k++) {
376 if (!suck_check_classbuffer_size(cb, 2))
379 /* code attribute name index */
381 code_attribute_name_index = suck_u2(cb);
383 code_attribute_name =
384 (utf*) class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
386 if (code_attribute_name == NULL)
389 /* check which code attribute */
391 if (code_attribute_name == utf_LineNumberTable) {
392 /* LineNumberTable */
394 if (!suck_check_classbuffer_size(cb, 4 + 2))
397 /* attribute length */
401 /* line number table length */
403 m->linenumbercount = suck_u2(cb);
405 if (!suck_check_classbuffer_size(cb,
406 (2 + 2) * m->linenumbercount))
409 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
411 #if defined(ENABLE_STATISTICS)
413 size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
416 for (l = 0; l < m->linenumbercount; l++) {
417 m->linenumbers[l].start_pc = suck_u2(cb);
418 m->linenumbers[l].line_number = suck_u2(cb);
421 #if defined(ENABLE_JAVASE)
422 else if (code_attribute_name == utf_StackMapTable) {
425 if (!stackmap_load_attribute_stackmaptable(cb, m))
430 /* unknown code attribute */
432 if (!loader_skip_attribute_body(cb))
437 else if (attribute_name == utf_Exceptions) {
440 if (m->thrownexceptions != NULL) {
441 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
445 if (!suck_check_classbuffer_size(cb, 4 + 2))
448 /* attribute length */
452 m->thrownexceptionscount = suck_u2(cb);
454 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
457 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
459 for (j = 0; j < m->thrownexceptionscount; j++) {
460 /* the classref is created later */
461 if (!((m->thrownexceptions)[j].any =
462 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
466 #if defined(ENABLE_JAVASE)
467 else if (attribute_name == utf_Signature) {
470 if (!loader_load_attribute_signature(cb, &(m->signature)))
474 #if defined(ENABLE_ANNOTATIONS)
475 else if (attribute_name == utf_RuntimeVisibleAnnotations) {
476 /* RuntimeVisibleAnnotations */
477 if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
480 else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
481 /* RuntimeInvisibleAnnotations */
482 if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
485 else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
486 /* RuntimeVisibleParameterAnnotations */
487 if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
490 else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
491 /* RuntimeInvisibleParameterAnnotations */
492 if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
495 else if (attribute_name == utf_AnnotationDefault) {
496 /* AnnotationDefault */
497 if (!annotation_load_method_attribute_annotationdefault(cb, m))
503 /* unknown attribute */
505 if (!loader_skip_attribute_body(cb))
510 if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
511 exceptions_throw_classformaterror(c, "Missing Code attribute");
515 #if defined(ENABLE_REPLACEMENT)
516 /* initialize the hit countdown field */
518 m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
521 /* everything was ok */
527 /* method_free *****************************************************************
529 Frees all memory that was allocated for this method.
531 *******************************************************************************/
533 void method_free(methodinfo *m)
539 MFREE(m->jcode, u1, m->jcodelength);
541 if (m->rawexceptiontable)
542 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
544 code_free_code_of_method(m);
546 if (m->stubroutine) {
547 if (m->flags & ACC_NATIVE) {
548 NativeStub::remove(m->stubroutine);
551 CompilerStub::remove(m->stubroutine);
557 /* method_canoverwrite *********************************************************
559 Check if m and old are identical with respect to type and
560 name. This means that old can be overwritten with m.
562 *******************************************************************************/
564 bool method_canoverwrite(methodinfo *m, methodinfo *old)
566 if (m->name != old->name)
569 if (m->descriptor != old->descriptor)
572 if (m->flags & ACC_STATIC)
579 /* method_new_builtin **********************************************************
581 Creates a minimal methodinfo structure for builtins. This comes handy
582 when dealing with builtin stubs or stacktraces.
584 *******************************************************************************/
586 methodinfo *method_new_builtin(builtintable_entry *bte)
590 /* allocate the methodinfo structure */
594 /* initialize methodinfo structure */
596 MZERO(m, methodinfo, 1);
598 m->mutex = new Mutex();
599 m->flags = ACC_METHOD_BUILTIN;
600 m->parseddesc = bte->md;
602 m->descriptor = bte->descriptor;
604 /* return the newly created methodinfo */
610 /* method_vftbl_lookup *********************************************************
612 Does a method lookup in the passed virtual function table. This
613 function does exactly the same thing as JIT, but additionally
614 relies on the fact, that the methodinfo pointer is at the first
615 data segment slot (even for compiler stubs).
617 *******************************************************************************/
619 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
623 methodinfo *resm; /* pointer to new resolved method */
625 /* If the method is not an instance method, just return it. */
627 if (m->flags & ACC_STATIC)
632 /* Get the method from the virtual function table. Is this an
635 if (m->clazz->flags & ACC_INTERFACE) {
636 pmptr = vftbl->interfacetable[-(m->clazz->index)];
637 mptr = pmptr[(m - m->clazz->methods)];
640 mptr = vftbl->table[m->vftblindex];
643 /* and now get the codeinfo pointer from the first data segment slot */
645 resm = code_get_methodinfo_for_pv(mptr);
651 /* method_get_parametercount **************************************************
653 Use the descriptor of a method to determine the number of parameters
654 of the method. The this pointer of non-static methods is not counted.
657 m........the method of which the parameters should be counted
660 The parameter count or -1 on error.
662 *******************************************************************************/
664 int32_t method_get_parametercount(methodinfo *m)
666 methoddesc *md; /* method descriptor of m */
667 int32_t paramcount = 0; /* the parameter count of m */
671 /* is the descriptor fully parsed? */
673 if (md->params == NULL) {
674 if (!descriptor_params_from_paramtypes(md, m->flags)) {
679 paramcount = md->paramcount;
681 /* skip `this' pointer */
683 if (!(m->flags & ACC_STATIC)) {
691 /* method_get_parametertypearray ***********************************************
693 Use the descriptor of a method to generate a java.lang.Class array
694 which contains the classes of the parametertypes of the method.
696 This function is called by java.lang.reflect.{Constructor,Method}.
698 *******************************************************************************/
700 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
703 typedesc *paramtypes;
705 java_handle_objectarray_t *oa;
711 /* is the descriptor fully parsed? */
713 if (m->parseddesc->params == NULL)
714 if (!descriptor_params_from_paramtypes(md, m->flags))
717 paramtypes = md->paramtypes;
718 paramcount = md->paramcount;
720 /* skip `this' pointer */
722 if (!(m->flags & ACC_STATIC)) {
727 /* create class-array */
729 oa = builtin_anewarray(paramcount, class_java_lang_Class);
736 for (i = 0; i < paramcount; i++) {
737 if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
740 LLNI_array_direct(oa, i) = (java_object_t *) c;
747 /* method_get_exceptionarray ***************************************************
749 Get the exceptions which can be thrown by a method.
751 *******************************************************************************/
753 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
755 java_handle_objectarray_t *oa;
759 /* create class-array */
761 oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
766 /* iterate over all exceptions and store the class in the array */
768 for (i = 0; i < m->thrownexceptionscount; i++) {
769 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
774 LLNI_array_direct(oa, i) = (java_object_t *) c;
781 /* method_returntype_get *******************************************************
783 Get the return type of the method.
785 *******************************************************************************/
787 classinfo *method_returntype_get(methodinfo *m)
792 td = &(m->parseddesc->returntype);
794 if (!resolve_class_from_typedesc(td, true, false, &c))
801 /* method_count_implementations ************************************************
803 Count the implementations of a method in a class cone (a class and all its
807 m................the method to count
808 c................class at which to start the counting (this class and
809 all its subclasses will be searched)
812 *found...........if found != NULL, *found receives the method
813 implementation that was found. This value is only
814 meaningful if the return value is 1.
817 the number of implementations found
819 *******************************************************************************/
821 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
831 mend = mp + c->methodscount;
833 for (; mp < mend; ++mp) {
834 if (method_canoverwrite(mp, m)) {
842 for (child = c->sub; child != NULL; child = child->nextsub) {
843 count += method_count_implementations(m, child, found);
850 /* method_get_annotations ******************************************************
852 Get a methods' unparsed annotations in a byte array.
855 m........the method of which the annotations should be returned
858 The unparsed annotations in a byte array (or NULL if there aren't any).
860 *******************************************************************************/
862 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
864 #if defined(ENABLE_ANNOTATIONS)
865 classinfo *c; /* methods' declaring class */
866 int slot; /* methods' slot */
867 java_handle_t *annotations; /* methods' unparsed annotations */
868 java_handle_t *method_annotations; /* all methods' unparsed annotations */
869 /* of the declaring class */
872 slot = m - c->methods;
875 LLNI_classinfo_field_get(c, method_annotations, method_annotations);
877 /* the method_annotations array might be shorter then the method
878 * count if the methods above a certain index have no annotations.
880 if (method_annotations != NULL &&
881 array_length_get(method_annotations) > slot) {
882 annotations = array_objectarray_element_get(
883 (java_handle_objectarray_t*)method_annotations, slot);
886 return (java_handle_bytearray_t*)annotations;
893 /* method_get_parameterannotations ********************************************
895 Get a methods' unparsed parameter annotations in an array of byte
899 m........the method of which the parameter annotations should be
903 The unparsed parameter annotations in a byte array (or NULL if
906 *******************************************************************************/
908 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
910 #if defined(ENABLE_ANNOTATIONS)
911 classinfo *c; /* methods' declaring class */
912 int slot; /* methods' slot */
913 java_handle_t *parameterAnnotations; /* methods' unparsed */
914 /* parameter annotations */
915 java_handle_t *method_parameterannotations; /* all methods' unparsed */
916 /* parameter annotations of */
917 /* the declaring class */
920 slot = m - c->methods;
921 parameterAnnotations = NULL;
923 LLNI_classinfo_field_get(
924 c, method_parameterannotations, method_parameterannotations);
926 /* the method_annotations array might be shorter then the method
927 * count if the methods above a certain index have no annotations.
929 if (method_parameterannotations != NULL &&
930 array_length_get(method_parameterannotations) > slot) {
931 parameterAnnotations = array_objectarray_element_get(
932 (java_handle_objectarray_t*)method_parameterannotations,
936 return (java_handle_bytearray_t*)parameterAnnotations;
943 /* method_get_annotationdefault ***********************************************
945 Get a methods' unparsed annotation default value in a byte array.
948 m........the method of which the annotation default value should be
952 The unparsed annotation default value in a byte array (or NULL if
955 *******************************************************************************/
957 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
959 #if defined(ENABLE_ANNOTATIONS)
960 classinfo *c; /* methods' declaring class */
961 int slot; /* methods' slot */
962 java_handle_t *annotationDefault; /* methods' unparsed */
963 /* annotation default value */
964 java_handle_t *method_annotationdefaults; /* all methods' unparsed */
965 /* annotation default values of */
966 /* the declaring class */
969 slot = m - c->methods;
970 annotationDefault = NULL;
972 LLNI_classinfo_field_get(
973 c, method_annotationdefaults, method_annotationdefaults);
975 /* the method_annotations array might be shorter then the method
976 * count if the methods above a certain index have no annotations.
978 if (method_annotationdefaults != NULL &&
979 array_length_get(method_annotationdefaults) > slot) {
980 annotationDefault = array_objectarray_element_get(
981 (java_handle_objectarray_t*)method_annotationdefaults, slot);
984 return (java_handle_bytearray_t*)annotationDefault;
991 /* method_add_to_worklist ******************************************************
993 Add the method to the given worklist. If the method already occurs in
994 the worklist, the worklist remains unchanged.
996 *******************************************************************************/
998 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
1000 method_worklist *wi;
1002 for (wi = *wl; wi != NULL; wi = wi->next)
1006 wi = NEW(method_worklist);
1014 /* method_add_assumption_monomorphic *******************************************
1016 Record the assumption that the method is monomorphic.
1019 m.................the method
1020 caller............the caller making the assumption
1022 *******************************************************************************/
1024 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
1026 method_assumption *as;
1028 /* XXX LOCKING FOR THIS FUNCTION? */
1030 /* check if we already have registered this assumption */
1032 for (as = m->assumptions; as != NULL; as = as->next) {
1033 if (as->context == caller)
1037 /* register the assumption */
1039 as = NEW(method_assumption);
1040 as->next = m->assumptions;
1041 as->context = caller;
1043 m->assumptions = as;
1046 /* method_break_assumption_monomorphic *****************************************
1048 Break the assumption that this method is monomorphic. All callers that
1049 have registered this assumption are added to the worklist.
1052 m.................the method
1053 wl................worklist where to add invalidated callers
1055 *******************************************************************************/
1057 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1059 method_assumption *as;
1061 /* XXX LOCKING FOR THIS FUNCTION? */
1063 for (as = m->assumptions; as != NULL; as = as->next) {
1065 printf("ASSUMPTION BROKEN (monomorphism): ");
1068 method_println(as->context);
1071 method_add_to_worklist(as->context, wl);
1073 #if defined(ENABLE_TLH) && 0
1075 method_assumption *as2;
1076 as2 = m->assumptions;
1077 m->assumptions = NULL;
1078 method_break_assumption_monomorphic(as->context, wl);
1080 assert(m->assumptions == NULL);
1081 m->assumptions = as2;*/
1087 /* method_printflags ***********************************************************
1089 Prints the flags of a method to stdout like.
1091 *******************************************************************************/
1093 #if !defined(NDEBUG)
1094 void method_printflags(methodinfo *m)
1101 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
1102 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
1103 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
1104 if (m->flags & ACC_STATIC) printf(" STATIC");
1105 if (m->flags & ACC_FINAL) printf(" FINAL");
1106 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
1107 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
1108 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
1109 if (m->flags & ACC_NATIVE) printf(" NATIVE");
1110 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
1111 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
1112 if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
1113 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1114 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1116 #endif /* !defined(NDEBUG) */
1119 /* method_print ****************************************************************
1121 Prints a method to stdout like:
1123 java.lang.Object.<init>()V
1125 *******************************************************************************/
1127 #if !defined(NDEBUG)
1128 void method_print(methodinfo *m)
1135 if (m->clazz != NULL)
1136 utf_display_printable_ascii_classname(m->clazz->name);
1140 utf_display_printable_ascii(m->name);
1141 utf_display_printable_ascii(m->descriptor);
1143 method_printflags(m);
1145 #endif /* !defined(NDEBUG) */
1148 /* method_println **************************************************************
1150 Prints a method plus new line to stdout like:
1152 java.lang.Object.<init>()V
1154 *******************************************************************************/
1156 #if !defined(NDEBUG)
1157 void method_println(methodinfo *m)
1159 if (opt_debugcolor) printf("\033[31m"); /* red */
1161 if (opt_debugcolor) printf("\033[m");
1164 #endif /* !defined(NDEBUG) */
1167 /* method_methodref_print ******************************************************
1169 Prints a method reference to stdout.
1171 *******************************************************************************/
1173 #if !defined(NDEBUG)
1174 void method_methodref_print(constant_FMIref *mr)
1177 printf("(constant_FMIref *)NULL");
1181 if (IS_FMIREF_RESOLVED(mr)) {
1182 printf("<method> ");
1183 method_print(mr->p.method);
1186 printf("<methodref> ");
1187 utf_display_printable_ascii_classname(mr->p.classref->name);
1189 utf_display_printable_ascii(mr->name);
1190 utf_display_printable_ascii(mr->descriptor);
1193 #endif /* !defined(NDEBUG) */
1196 /* method_methodref_println ****************************************************
1198 Prints a method reference to stdout, followed by a newline.
1200 *******************************************************************************/
1202 #if !defined(NDEBUG)
1203 void method_methodref_println(constant_FMIref *mr)
1205 method_methodref_print(mr);
1208 #endif /* !defined(NDEBUG) */
1210 #if defined(__cplusplus)
1215 * These are local overrides for various environment variables in Emacs.
1216 * Please do not remove this and leave it at the end of the file, where
1217 * Emacs will automagically detect them.
1218 * ---------------------------------------------------------------------
1221 * indent-tabs-mode: t
1225 * vim:noexpandtab:sw=4:ts=4: