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 /* Ignore flags for class initializer according to section 4.6
206 of "The Java Virtual Machine Specification, 2nd Edition" (see PR125). */
208 if (m->name == utf_clinit) {
209 m->flags &= ACC_STRICT;
210 m->flags |= ACC_STATIC;
213 if (!(m->flags & ACC_STATIC))
214 argcount++; /* count the 'this' argument */
216 #ifdef ENABLE_VERIFIER
218 if (argcount > 255) {
219 exceptions_throw_classformaterror(c, "Too many arguments in signature");
223 /* check flag consistency */
224 if (m->name != utf_clinit) {
225 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
227 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
228 exceptions_throw_classformaterror(c,
229 "Illegal method modifiers: 0x%X",
234 if (m->flags & ACC_ABSTRACT) {
235 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
236 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
237 exceptions_throw_classformaterror(c,
238 "Illegal method modifiers: 0x%X",
244 if (c->flags & ACC_INTERFACE) {
245 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
246 exceptions_throw_classformaterror(c,
247 "Illegal method modifiers: 0x%X",
253 if (m->name == utf_init) {
254 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
255 ACC_NATIVE | ACC_ABSTRACT)) {
256 exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
262 #endif /* ENABLE_VERIFIER */
264 /* mark the method as monomorphic until further notice */
266 m->flags |= ACC_METHOD_MONOMORPHIC;
268 /* non-abstract methods have an implementation in this class */
270 if (!(m->flags & ACC_ABSTRACT))
271 m->flags |= ACC_METHOD_IMPLEMENTED;
273 if (!suck_check_classbuffer_size(cb, 2))
276 /* attributes count */
278 attributes_count = suck_u2(cb);
280 for (i = 0; i < attributes_count; i++) {
281 if (!suck_check_classbuffer_size(cb, 2))
284 /* attribute name index */
286 attribute_name_index = suck_u2(cb);
289 (utf*) class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
291 if (attribute_name == NULL)
294 if (attribute_name == utf_Code) {
297 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
298 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
303 exceptions_throw_classformaterror(c, "Multiple Code attributes");
307 if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
311 m->maxstack = suck_u2(cb);
312 m->maxlocals = suck_u2(cb);
314 if (m->maxlocals < argcount) {
315 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
319 if (!suck_check_classbuffer_size(cb, 4))
322 m->jcodelength = suck_u4(cb);
324 if (m->jcodelength == 0) {
325 exceptions_throw_classformaterror(c, "Code of a method has length 0");
329 if (m->jcodelength > 65535) {
330 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
334 if (!suck_check_classbuffer_size(cb, m->jcodelength))
337 m->jcode = MNEW(u1, m->jcodelength);
338 suck_nbytes(m->jcode, cb, m->jcodelength);
340 if (!suck_check_classbuffer_size(cb, 2))
343 m->rawexceptiontablelength = suck_u2(cb);
344 if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
347 m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
349 #if defined(ENABLE_STATISTICS)
351 count_vmcode_len += m->jcodelength + 18;
353 m->rawexceptiontablelength * sizeof(raw_exception_entry);
357 for (j = 0; j < m->rawexceptiontablelength; j++) {
359 m->rawexceptiontable[j].startpc = suck_u2(cb);
360 m->rawexceptiontable[j].endpc = suck_u2(cb);
361 m->rawexceptiontable[j].handlerpc = suck_u2(cb);
366 m->rawexceptiontable[j].catchtype.any = NULL;
369 /* the classref is created later */
370 if (!(m->rawexceptiontable[j].catchtype.any =
371 (utf *) class_getconstant(c, idx, CONSTANT_Class)))
376 if (!suck_check_classbuffer_size(cb, 2))
379 /* code attributes count */
381 code_attributes_count = suck_u2(cb);
383 for (k = 0; k < code_attributes_count; k++) {
384 if (!suck_check_classbuffer_size(cb, 2))
387 /* code attribute name index */
389 code_attribute_name_index = suck_u2(cb);
391 code_attribute_name =
392 (utf*) class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
394 if (code_attribute_name == NULL)
397 /* check which code attribute */
399 if (code_attribute_name == utf_LineNumberTable) {
400 /* LineNumberTable */
402 if (!suck_check_classbuffer_size(cb, 4 + 2))
405 /* attribute length */
409 /* line number table length */
411 m->linenumbercount = suck_u2(cb);
413 if (!suck_check_classbuffer_size(cb,
414 (2 + 2) * m->linenumbercount))
417 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
419 #if defined(ENABLE_STATISTICS)
421 size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
424 for (l = 0; l < m->linenumbercount; l++) {
425 m->linenumbers[l].start_pc = suck_u2(cb);
426 m->linenumbers[l].line_number = suck_u2(cb);
429 #if defined(ENABLE_JAVASE)
430 else if (code_attribute_name == utf_StackMapTable) {
433 if (!stackmap_load_attribute_stackmaptable(cb, m))
438 /* unknown code attribute */
440 if (!loader_skip_attribute_body(cb))
445 else if (attribute_name == utf_Exceptions) {
448 if (m->thrownexceptions != NULL) {
449 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
453 if (!suck_check_classbuffer_size(cb, 4 + 2))
456 /* attribute length */
460 m->thrownexceptionscount = suck_u2(cb);
462 if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
465 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
467 for (j = 0; j < m->thrownexceptionscount; j++) {
468 /* the classref is created later */
469 if (!((m->thrownexceptions)[j].any =
470 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
474 #if defined(ENABLE_JAVASE)
475 else if (attribute_name == utf_Signature) {
478 if (!loader_load_attribute_signature(cb, &(m->signature)))
482 #if defined(ENABLE_ANNOTATIONS)
483 else if (attribute_name == utf_RuntimeVisibleAnnotations) {
484 /* RuntimeVisibleAnnotations */
485 if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
488 else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
489 /* RuntimeInvisibleAnnotations */
490 if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
493 else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
494 /* RuntimeVisibleParameterAnnotations */
495 if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
498 else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
499 /* RuntimeInvisibleParameterAnnotations */
500 if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
503 else if (attribute_name == utf_AnnotationDefault) {
504 /* AnnotationDefault */
505 if (!annotation_load_method_attribute_annotationdefault(cb, m))
511 /* unknown attribute */
513 if (!loader_skip_attribute_body(cb))
518 if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
519 exceptions_throw_classformaterror(c, "Missing Code attribute");
523 #if defined(ENABLE_REPLACEMENT)
524 /* initialize the hit countdown field */
526 m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
529 /* everything was ok */
535 /* method_free *****************************************************************
537 Frees all memory that was allocated for this method.
539 *******************************************************************************/
541 void method_free(methodinfo *m)
547 MFREE(m->jcode, u1, m->jcodelength);
549 if (m->rawexceptiontable)
550 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
552 code_free_code_of_method(m);
554 if (m->stubroutine) {
555 if (m->flags & ACC_NATIVE) {
556 NativeStub::remove(m->stubroutine);
559 CompilerStub::remove(m->stubroutine);
564 delete m->breakpoints;
568 /* method_canoverwrite *********************************************************
570 Check if m and old are identical with respect to type and
571 name. This means that old can be overwritten with m.
573 *******************************************************************************/
575 bool method_canoverwrite(methodinfo *m, methodinfo *old)
577 if (m->name != old->name)
580 if (m->descriptor != old->descriptor)
583 if (m->flags & ACC_STATIC)
590 /* method_new_builtin **********************************************************
592 Creates a minimal methodinfo structure for builtins. This comes handy
593 when dealing with builtin stubs or stacktraces.
595 *******************************************************************************/
597 methodinfo *method_new_builtin(builtintable_entry *bte)
601 /* allocate the methodinfo structure */
605 /* initialize methodinfo structure */
607 MZERO(m, methodinfo, 1);
609 m->mutex = new Mutex();
610 m->flags = ACC_METHOD_BUILTIN;
611 m->parseddesc = bte->md;
613 m->descriptor = bte->descriptor;
615 /* return the newly created methodinfo */
621 /* method_vftbl_lookup *********************************************************
623 Does a method lookup in the passed virtual function table. This
624 function does exactly the same thing as JIT, but additionally
625 relies on the fact, that the methodinfo pointer is at the first
626 data segment slot (even for compiler stubs).
628 *******************************************************************************/
630 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
634 methodinfo *resm; /* pointer to new resolved method */
636 /* If the method is not an instance method, just return it. */
638 if (m->flags & ACC_STATIC)
643 /* Get the method from the virtual function table. Is this an
646 if (m->clazz->flags & ACC_INTERFACE) {
647 pmptr = vftbl->interfacetable[-(m->clazz->index)];
648 mptr = pmptr[(m - m->clazz->methods)];
651 mptr = vftbl->table[m->vftblindex];
654 /* and now get the codeinfo pointer from the first data segment slot */
656 resm = code_get_methodinfo_for_pv(mptr);
662 /* method_get_parametercount **************************************************
664 Use the descriptor of a method to determine the number of parameters
665 of the method. The this pointer of non-static methods is not counted.
668 m........the method of which the parameters should be counted
671 The parameter count or -1 on error.
673 *******************************************************************************/
675 int32_t method_get_parametercount(methodinfo *m)
677 methoddesc *md; /* method descriptor of m */
678 int32_t paramcount = 0; /* the parameter count of m */
682 /* is the descriptor fully parsed? */
684 if (md->params == NULL) {
685 if (!descriptor_params_from_paramtypes(md, m->flags)) {
690 paramcount = md->paramcount;
692 /* skip `this' pointer */
694 if (!(m->flags & ACC_STATIC)) {
702 /* method_get_parametertypearray ***********************************************
704 Use the descriptor of a method to generate a java.lang.Class array
705 which contains the classes of the parametertypes of the method.
707 This function is called by java.lang.reflect.{Constructor,Method}.
709 *******************************************************************************/
711 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
714 typedesc* paramtypes;
721 /* is the descriptor fully parsed? */
723 if (m->parseddesc->params == NULL)
724 if (!descriptor_params_from_paramtypes(md, m->flags))
727 paramtypes = md->paramtypes;
728 paramcount = md->paramcount;
730 /* skip `this' pointer */
732 if (!(m->flags & ACC_STATIC)) {
737 /* create class-array */
739 ClassArray ca(paramcount);
746 for (i = 0; i < paramcount; i++) {
747 if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
750 ca.set_element(i, c);
753 return ca.get_handle();
757 /* method_get_exceptionarray ***************************************************
759 Get the exceptions which can be thrown by a method.
761 *******************************************************************************/
763 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
768 /* create class-array */
770 ClassArray ca(m->thrownexceptionscount);
775 /* iterate over all exceptions and store the class in the array */
777 for (i = 0; i < m->thrownexceptionscount; i++) {
778 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
783 ca.set_element(i, c);
786 return ca.get_handle();
790 /* method_returntype_get *******************************************************
792 Get the return type of the method.
794 *******************************************************************************/
796 classinfo *method_returntype_get(methodinfo *m)
801 td = &(m->parseddesc->returntype);
803 if (!resolve_class_from_typedesc(td, true, false, &c))
810 /* method_count_implementations ************************************************
812 Count the implementations of a method in a class cone (a class and all its
816 m................the method to count
817 c................class at which to start the counting (this class and
818 all its subclasses will be searched)
821 *found...........if found != NULL, *found receives the method
822 implementation that was found. This value is only
823 meaningful if the return value is 1.
826 the number of implementations found
828 *******************************************************************************/
830 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
840 mend = mp + c->methodscount;
842 for (; mp < mend; ++mp) {
843 if (method_canoverwrite(mp, m)) {
851 for (child = c->sub; child != NULL; child = child->nextsub) {
852 count += method_count_implementations(m, child, found);
859 /* method_get_annotations ******************************************************
861 Get a methods' unparsed annotations in a byte array.
864 m........the method of which the annotations should be returned
867 The unparsed annotations in a byte array (or NULL if there aren't any).
869 *******************************************************************************/
871 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
873 #if defined(ENABLE_ANNOTATIONS)
874 classinfo *c; /* methods' declaring class */
875 int slot; /* methods' slot */
876 java_handle_t *method_annotations; /* all methods' unparsed annotations */
877 /* of the declaring class */
880 slot = m - c->methods;
882 LLNI_classinfo_field_get(c, method_annotations, method_annotations);
884 ObjectArray oa((java_handle_objectarray_t*) method_annotations);
886 /* the method_annotations array might be shorter then the method
887 * count if the methods above a certain index have no annotations.
889 if (method_annotations != NULL && oa.get_length() > slot) {
890 return (java_handle_bytearray_t*) oa.get_element(slot);
900 /* method_get_parameterannotations ********************************************
902 Get a methods' unparsed parameter annotations in an array of byte
906 m........the method of which the parameter annotations should be
910 The unparsed parameter annotations in a byte array (or NULL if
913 *******************************************************************************/
915 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
917 #if defined(ENABLE_ANNOTATIONS)
918 classinfo *c; /* methods' declaring class */
919 int slot; /* methods' slot */
920 java_handle_t *method_parameterannotations; /* all methods' unparsed */
921 /* parameter annotations of */
922 /* the declaring class */
925 slot = m - c->methods;
927 LLNI_classinfo_field_get(
928 c, method_parameterannotations, method_parameterannotations);
930 ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
932 /* the method_annotations array might be shorter then the method
933 * count if the methods above a certain index have no annotations.
935 if (method_parameterannotations != NULL && oa.get_length() > slot) {
936 return (java_handle_bytearray_t*) oa.get_element(slot);
946 /* method_get_annotationdefault ***********************************************
948 Get a methods' unparsed annotation default value in a byte array.
951 m........the method of which the annotation default value should be
955 The unparsed annotation default value in a byte array (or NULL if
958 *******************************************************************************/
960 java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
962 #if defined(ENABLE_ANNOTATIONS)
963 classinfo *c; /* methods' declaring class */
964 int slot; /* methods' slot */
965 java_handle_t *method_annotationdefaults; /* all methods' unparsed */
966 /* annotation default values of */
967 /* the declaring class */
970 slot = m - c->methods;
972 LLNI_classinfo_field_get(
973 c, method_annotationdefaults, method_annotationdefaults);
975 ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
977 /* the method_annotations array might be shorter then the method
978 * count if the methods above a certain index have no annotations.
980 if (method_annotationdefaults != NULL && oa.get_length() > slot) {
981 return (java_handle_bytearray_t*) oa.get_element(slot);
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: