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.hpp"
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;
710 /* is the descriptor fully parsed? */
712 if (m->parseddesc->params == NULL)
713 if (!descriptor_params_from_paramtypes(md, m->flags))
716 paramtypes = md->paramtypes;
717 paramcount = md->paramcount;
719 /* skip `this' pointer */
721 if (!(m->flags & ACC_STATIC)) {
726 /* create class-array */
728 ClassArray ca(paramcount);
735 for (i = 0; i < paramcount; i++) {
736 if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
739 ca.set_element(i, c);
742 return ca.get_handle();
746 /* method_get_exceptionarray ***************************************************
748 Get the exceptions which can be thrown by a method.
750 *******************************************************************************/
752 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
757 /* create class-array */
759 ClassArray ca(m->thrownexceptionscount);
764 /* iterate over all exceptions and store the class in the array */
766 for (i = 0; i < m->thrownexceptionscount; i++) {
767 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
772 ca.set_element(i, c);
775 return ca.get_handle();
779 /* method_returntype_get *******************************************************
781 Get the return type of the method.
783 *******************************************************************************/
785 classinfo *method_returntype_get(methodinfo *m)
790 td = &(m->parseddesc->returntype);
792 if (!resolve_class_from_typedesc(td, true, false, &c))
799 /* method_count_implementations ************************************************
801 Count the implementations of a method in a class cone (a class and all its
805 m................the method to count
806 c................class at which to start the counting (this class and
807 all its subclasses will be searched)
810 *found...........if found != NULL, *found receives the method
811 implementation that was found. This value is only
812 meaningful if the return value is 1.
815 the number of implementations found
817 *******************************************************************************/
819 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
829 mend = mp + c->methodscount;
831 for (; mp < mend; ++mp) {
832 if (method_canoverwrite(mp, m)) {
840 for (child = c->sub; child != NULL; child = child->nextsub) {
841 count += method_count_implementations(m, child, found);
848 /* method_get_annotations ******************************************************
850 Get a methods' unparsed annotations in a byte array.
853 m........the method of which the annotations should be returned
856 The unparsed annotations in a byte array (or NULL if there aren't any).
858 *******************************************************************************/
860 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
862 #if defined(ENABLE_ANNOTATIONS)
863 classinfo *c; /* methods' declaring class */
864 int slot; /* methods' slot */
865 java_handle_t *method_annotations; /* all methods' unparsed annotations */
866 /* of the declaring class */
869 slot = m - c->methods;
871 LLNI_classinfo_field_get(c, method_annotations, method_annotations);
873 ObjectArray oa((java_handle_objectarray_t*) method_annotations);
875 /* the method_annotations array might be shorter then the method
876 * count if the methods above a certain index have no annotations.
878 if (method_annotations != NULL && oa.get_length() > slot) {
879 return (java_handle_bytearray_t*) oa.get_element(slot);
889 /* method_get_parameterannotations ********************************************
891 Get a methods' unparsed parameter annotations in an array of byte
895 m........the method of which the parameter annotations should be
899 The unparsed parameter annotations in a byte array (or NULL if
902 *******************************************************************************/
904 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
906 #if defined(ENABLE_ANNOTATIONS)
907 classinfo *c; /* methods' declaring class */
908 int slot; /* methods' slot */
909 java_handle_t *method_parameterannotations; /* all methods' unparsed */
910 /* parameter annotations of */
911 /* the declaring class */
914 slot = m - c->methods;
916 LLNI_classinfo_field_get(
917 c, method_parameterannotations, method_parameterannotations);
919 ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
921 /* the method_annotations array might be shorter then the method
922 * count if the methods above a certain index have no annotations.
924 if (method_parameterannotations != NULL && oa.get_length() > slot) {
925 return (java_handle_bytearray_t*) oa.get_element(slot);
935 /* method_get_annotationdefault ***********************************************
937 Get a methods' unparsed annotation default value in a byte array.
940 m........the method of which the annotation default value should be
944 The unparsed annotation default value in a byte array (or NULL if
947 *******************************************************************************/
949 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
951 #if defined(ENABLE_ANNOTATIONS)
952 classinfo *c; /* methods' declaring class */
953 int slot; /* methods' slot */
954 java_handle_t *method_annotationdefaults; /* all methods' unparsed */
955 /* annotation default values of */
956 /* the declaring class */
959 slot = m - c->methods;
961 LLNI_classinfo_field_get(
962 c, method_annotationdefaults, method_annotationdefaults);
964 ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
966 /* the method_annotations array might be shorter then the method
967 * count if the methods above a certain index have no annotations.
969 if (method_annotationdefaults != NULL && oa.get_length() > slot) {
970 return (java_handle_bytearray_t*) oa.get_element(slot);
980 /* method_add_to_worklist ******************************************************
982 Add the method to the given worklist. If the method already occurs in
983 the worklist, the worklist remains unchanged.
985 *******************************************************************************/
987 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
991 for (wi = *wl; wi != NULL; wi = wi->next)
995 wi = NEW(method_worklist);
1003 /* method_add_assumption_monomorphic *******************************************
1005 Record the assumption that the method is monomorphic.
1008 m.................the method
1009 caller............the caller making the assumption
1011 *******************************************************************************/
1013 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
1015 method_assumption *as;
1017 /* XXX LOCKING FOR THIS FUNCTION? */
1019 /* check if we already have registered this assumption */
1021 for (as = m->assumptions; as != NULL; as = as->next) {
1022 if (as->context == caller)
1026 /* register the assumption */
1028 as = NEW(method_assumption);
1029 as->next = m->assumptions;
1030 as->context = caller;
1032 m->assumptions = as;
1035 /* method_break_assumption_monomorphic *****************************************
1037 Break the assumption that this method is monomorphic. All callers that
1038 have registered this assumption are added to the worklist.
1041 m.................the method
1042 wl................worklist where to add invalidated callers
1044 *******************************************************************************/
1046 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1048 method_assumption *as;
1050 /* XXX LOCKING FOR THIS FUNCTION? */
1052 for (as = m->assumptions; as != NULL; as = as->next) {
1054 printf("ASSUMPTION BROKEN (monomorphism): ");
1057 method_println(as->context);
1060 method_add_to_worklist(as->context, wl);
1062 #if defined(ENABLE_TLH) && 0
1064 method_assumption *as2;
1065 as2 = m->assumptions;
1066 m->assumptions = NULL;
1067 method_break_assumption_monomorphic(as->context, wl);
1069 assert(m->assumptions == NULL);
1070 m->assumptions = as2;*/
1076 /* method_printflags ***********************************************************
1078 Prints the flags of a method to stdout like.
1080 *******************************************************************************/
1082 #if !defined(NDEBUG)
1083 void method_printflags(methodinfo *m)
1090 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
1091 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
1092 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
1093 if (m->flags & ACC_STATIC) printf(" STATIC");
1094 if (m->flags & ACC_FINAL) printf(" FINAL");
1095 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
1096 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
1097 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
1098 if (m->flags & ACC_NATIVE) printf(" NATIVE");
1099 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
1100 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
1101 if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
1102 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1103 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1105 #endif /* !defined(NDEBUG) */
1108 /* method_print ****************************************************************
1110 Prints a method to stdout like:
1112 java.lang.Object.<init>()V
1114 *******************************************************************************/
1116 #if !defined(NDEBUG)
1117 void method_print(methodinfo *m)
1124 if (m->clazz != NULL)
1125 utf_display_printable_ascii_classname(m->clazz->name);
1129 utf_display_printable_ascii(m->name);
1130 utf_display_printable_ascii(m->descriptor);
1132 method_printflags(m);
1134 #endif /* !defined(NDEBUG) */
1137 /* method_println **************************************************************
1139 Prints a method plus new line to stdout like:
1141 java.lang.Object.<init>()V
1143 *******************************************************************************/
1145 #if !defined(NDEBUG)
1146 void method_println(methodinfo *m)
1148 if (opt_debugcolor) printf("\033[31m"); /* red */
1150 if (opt_debugcolor) printf("\033[m");
1153 #endif /* !defined(NDEBUG) */
1156 /* method_methodref_print ******************************************************
1158 Prints a method reference to stdout.
1160 *******************************************************************************/
1162 #if !defined(NDEBUG)
1163 void method_methodref_print(constant_FMIref *mr)
1166 printf("(constant_FMIref *)NULL");
1170 if (IS_FMIREF_RESOLVED(mr)) {
1171 printf("<method> ");
1172 method_print(mr->p.method);
1175 printf("<methodref> ");
1176 utf_display_printable_ascii_classname(mr->p.classref->name);
1178 utf_display_printable_ascii(mr->name);
1179 utf_display_printable_ascii(mr->descriptor);
1182 #endif /* !defined(NDEBUG) */
1185 /* method_methodref_println ****************************************************
1187 Prints a method reference to stdout, followed by a newline.
1189 *******************************************************************************/
1191 #if !defined(NDEBUG)
1192 void method_methodref_println(constant_FMIref *mr)
1194 method_methodref_print(mr);
1197 #endif /* !defined(NDEBUG) */
1199 #if defined(__cplusplus)
1204 * These are local overrides for various environment variables in Emacs.
1205 * Please do not remove this and leave it at the end of the file, where
1206 * Emacs will automagically detect them.
1207 * ---------------------------------------------------------------------
1210 * indent-tabs-mode: t
1214 * vim:noexpandtab:sw=4:ts=4: