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);
565 /* method_canoverwrite *********************************************************
567 Check if m and old are identical with respect to type and
568 name. This means that old can be overwritten with m.
570 *******************************************************************************/
572 bool method_canoverwrite(methodinfo *m, methodinfo *old)
574 if (m->name != old->name)
577 if (m->descriptor != old->descriptor)
580 if (m->flags & ACC_STATIC)
587 /* method_new_builtin **********************************************************
589 Creates a minimal methodinfo structure for builtins. This comes handy
590 when dealing with builtin stubs or stacktraces.
592 *******************************************************************************/
594 methodinfo *method_new_builtin(builtintable_entry *bte)
598 /* allocate the methodinfo structure */
602 /* initialize methodinfo structure */
604 MZERO(m, methodinfo, 1);
606 m->mutex = new Mutex();
607 m->flags = ACC_METHOD_BUILTIN;
608 m->parseddesc = bte->md;
610 m->descriptor = bte->descriptor;
612 /* return the newly created methodinfo */
618 /* method_vftbl_lookup *********************************************************
620 Does a method lookup in the passed virtual function table. This
621 function does exactly the same thing as JIT, but additionally
622 relies on the fact, that the methodinfo pointer is at the first
623 data segment slot (even for compiler stubs).
625 *******************************************************************************/
627 methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
631 methodinfo *resm; /* pointer to new resolved method */
633 /* If the method is not an instance method, just return it. */
635 if (m->flags & ACC_STATIC)
640 /* Get the method from the virtual function table. Is this an
643 if (m->clazz->flags & ACC_INTERFACE) {
644 pmptr = vftbl->interfacetable[-(m->clazz->index)];
645 mptr = pmptr[(m - m->clazz->methods)];
648 mptr = vftbl->table[m->vftblindex];
651 /* and now get the codeinfo pointer from the first data segment slot */
653 resm = code_get_methodinfo_for_pv(mptr);
659 /* method_get_parametercount **************************************************
661 Use the descriptor of a method to determine the number of parameters
662 of the method. The this pointer of non-static methods is not counted.
665 m........the method of which the parameters should be counted
668 The parameter count or -1 on error.
670 *******************************************************************************/
672 int32_t method_get_parametercount(methodinfo *m)
674 methoddesc *md; /* method descriptor of m */
675 int32_t paramcount = 0; /* the parameter count of m */
679 /* is the descriptor fully parsed? */
681 if (md->params == NULL) {
682 if (!descriptor_params_from_paramtypes(md, m->flags)) {
687 paramcount = md->paramcount;
689 /* skip `this' pointer */
691 if (!(m->flags & ACC_STATIC)) {
699 /* method_get_parametertypearray ***********************************************
701 Use the descriptor of a method to generate a java.lang.Class array
702 which contains the classes of the parametertypes of the method.
704 This function is called by java.lang.reflect.{Constructor,Method}.
706 *******************************************************************************/
708 java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
711 typedesc* paramtypes;
718 /* is the descriptor fully parsed? */
720 if (m->parseddesc->params == NULL)
721 if (!descriptor_params_from_paramtypes(md, m->flags))
724 paramtypes = md->paramtypes;
725 paramcount = md->paramcount;
727 /* skip `this' pointer */
729 if (!(m->flags & ACC_STATIC)) {
734 /* create class-array */
736 ClassArray ca(paramcount);
743 for (i = 0; i < paramcount; i++) {
744 if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
747 ca.set_element(i, c);
750 return ca.get_handle();
754 /* method_get_exceptionarray ***************************************************
756 Get the exceptions which can be thrown by a method.
758 *******************************************************************************/
760 java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
765 /* create class-array */
767 ClassArray ca(m->thrownexceptionscount);
772 /* iterate over all exceptions and store the class in the array */
774 for (i = 0; i < m->thrownexceptionscount; i++) {
775 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
780 ca.set_element(i, c);
783 return ca.get_handle();
787 /* method_returntype_get *******************************************************
789 Get the return type of the method.
791 *******************************************************************************/
793 classinfo *method_returntype_get(methodinfo *m)
798 td = &(m->parseddesc->returntype);
800 if (!resolve_class_from_typedesc(td, true, false, &c))
807 /* method_count_implementations ************************************************
809 Count the implementations of a method in a class cone (a class and all its
813 m................the method to count
814 c................class at which to start the counting (this class and
815 all its subclasses will be searched)
818 *found...........if found != NULL, *found receives the method
819 implementation that was found. This value is only
820 meaningful if the return value is 1.
823 the number of implementations found
825 *******************************************************************************/
827 s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
837 mend = mp + c->methodscount;
839 for (; mp < mend; ++mp) {
840 if (method_canoverwrite(mp, m)) {
848 for (child = c->sub; child != NULL; child = child->nextsub) {
849 count += method_count_implementations(m, child, found);
856 /* method_get_annotations ******************************************************
858 Get a methods' unparsed annotations in a byte array.
861 m........the method of which the annotations should be returned
864 The unparsed annotations in a byte array (or NULL if there aren't any).
866 *******************************************************************************/
868 java_handle_bytearray_t *method_get_annotations(methodinfo *m)
870 #if defined(ENABLE_ANNOTATIONS)
871 classinfo *c; /* methods' declaring class */
872 int slot; /* methods' slot */
873 java_handle_t *method_annotations; /* all methods' unparsed annotations */
874 /* of the declaring class */
877 slot = m - c->methods;
879 LLNI_classinfo_field_get(c, method_annotations, method_annotations);
881 ObjectArray oa((java_handle_objectarray_t*) method_annotations);
883 /* the method_annotations array might be shorter then the method
884 * count if the methods above a certain index have no annotations.
886 if (method_annotations != NULL && oa.get_length() > slot) {
887 return (java_handle_bytearray_t*) oa.get_element(slot);
897 /* method_get_parameterannotations ********************************************
899 Get a methods' unparsed parameter annotations in an array of byte
903 m........the method of which the parameter annotations should be
907 The unparsed parameter annotations in a byte array (or NULL if
910 *******************************************************************************/
912 java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
914 #if defined(ENABLE_ANNOTATIONS)
915 classinfo *c; /* methods' declaring class */
916 int slot; /* methods' slot */
917 java_handle_t *method_parameterannotations; /* all methods' unparsed */
918 /* parameter annotations of */
919 /* the declaring class */
922 slot = m - c->methods;
924 LLNI_classinfo_field_get(
925 c, method_parameterannotations, method_parameterannotations);
927 ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
929 /* the method_annotations array might be shorter then the method
930 * count if the methods above a certain index have no annotations.
932 if (method_parameterannotations != NULL && oa.get_length() > slot) {
933 return (java_handle_bytearray_t*) oa.get_element(slot);
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 *method_annotationdefaults; /* all methods' unparsed */
963 /* annotation default values of */
964 /* the declaring class */
967 slot = m - c->methods;
969 LLNI_classinfo_field_get(
970 c, method_annotationdefaults, method_annotationdefaults);
972 ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
974 /* the method_annotations array might be shorter then the method
975 * count if the methods above a certain index have no annotations.
977 if (method_annotationdefaults != NULL && oa.get_length() > slot) {
978 return (java_handle_bytearray_t*) oa.get_element(slot);
988 /* method_add_to_worklist ******************************************************
990 Add the method to the given worklist. If the method already occurs in
991 the worklist, the worklist remains unchanged.
993 *******************************************************************************/
995 static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
999 for (wi = *wl; wi != NULL; wi = wi->next)
1003 wi = NEW(method_worklist);
1011 /* method_add_assumption_monomorphic *******************************************
1013 Record the assumption that the method is monomorphic.
1016 m.................the method
1017 caller............the caller making the assumption
1019 *******************************************************************************/
1021 void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
1023 method_assumption *as;
1025 /* XXX LOCKING FOR THIS FUNCTION? */
1027 /* check if we already have registered this assumption */
1029 for (as = m->assumptions; as != NULL; as = as->next) {
1030 if (as->context == caller)
1034 /* register the assumption */
1036 as = NEW(method_assumption);
1037 as->next = m->assumptions;
1038 as->context = caller;
1040 m->assumptions = as;
1043 /* method_break_assumption_monomorphic *****************************************
1045 Break the assumption that this method is monomorphic. All callers that
1046 have registered this assumption are added to the worklist.
1049 m.................the method
1050 wl................worklist where to add invalidated callers
1052 *******************************************************************************/
1054 void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
1056 method_assumption *as;
1058 /* XXX LOCKING FOR THIS FUNCTION? */
1060 for (as = m->assumptions; as != NULL; as = as->next) {
1062 printf("ASSUMPTION BROKEN (monomorphism): ");
1065 method_println(as->context);
1068 method_add_to_worklist(as->context, wl);
1070 #if defined(ENABLE_TLH) && 0
1072 method_assumption *as2;
1073 as2 = m->assumptions;
1074 m->assumptions = NULL;
1075 method_break_assumption_monomorphic(as->context, wl);
1077 assert(m->assumptions == NULL);
1078 m->assumptions = as2;*/
1084 /* method_printflags ***********************************************************
1086 Prints the flags of a method to stdout like.
1088 *******************************************************************************/
1090 #if !defined(NDEBUG)
1091 void method_printflags(methodinfo *m)
1098 if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
1099 if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
1100 if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
1101 if (m->flags & ACC_STATIC) printf(" STATIC");
1102 if (m->flags & ACC_FINAL) printf(" FINAL");
1103 if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
1104 if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
1105 if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
1106 if (m->flags & ACC_NATIVE) printf(" NATIVE");
1107 if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
1108 if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
1109 if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
1110 if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
1111 if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
1113 #endif /* !defined(NDEBUG) */
1116 /* method_print ****************************************************************
1118 Prints a method to stdout like:
1120 java.lang.Object.<init>()V
1122 *******************************************************************************/
1124 #if !defined(NDEBUG)
1125 void method_print(methodinfo *m)
1132 if (m->clazz != NULL)
1133 utf_display_printable_ascii_classname(m->clazz->name);
1137 utf_display_printable_ascii(m->name);
1138 utf_display_printable_ascii(m->descriptor);
1140 method_printflags(m);
1142 #endif /* !defined(NDEBUG) */
1145 /* method_println **************************************************************
1147 Prints a method plus new line to stdout like:
1149 java.lang.Object.<init>()V
1151 *******************************************************************************/
1153 #if !defined(NDEBUG)
1154 void method_println(methodinfo *m)
1156 if (opt_debugcolor) printf("\033[31m"); /* red */
1158 if (opt_debugcolor) printf("\033[m");
1161 #endif /* !defined(NDEBUG) */
1164 /* method_methodref_print ******************************************************
1166 Prints a method reference to stdout.
1168 *******************************************************************************/
1170 #if !defined(NDEBUG)
1171 void method_methodref_print(constant_FMIref *mr)
1174 printf("(constant_FMIref *)NULL");
1178 if (IS_FMIREF_RESOLVED(mr)) {
1179 printf("<method> ");
1180 method_print(mr->p.method);
1183 printf("<methodref> ");
1184 utf_display_printable_ascii_classname(mr->p.classref->name);
1186 utf_display_printable_ascii(mr->name);
1187 utf_display_printable_ascii(mr->descriptor);
1190 #endif /* !defined(NDEBUG) */
1193 /* method_methodref_println ****************************************************
1195 Prints a method reference to stdout, followed by a newline.
1197 *******************************************************************************/
1199 #if !defined(NDEBUG)
1200 void method_methodref_println(constant_FMIref *mr)
1202 method_methodref_print(mr);
1205 #endif /* !defined(NDEBUG) */
1207 #if defined(__cplusplus)
1212 * These are local overrides for various environment variables in Emacs.
1213 * Please do not remove this and leave it at the end of the file, where
1214 * Emacs will automagically detect them.
1215 * ---------------------------------------------------------------------
1218 * indent-tabs-mode: t
1222 * vim:noexpandtab:sw=4:ts=4: