LCOV - code coverage report
Current view: top level - vm - method.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 214 398 53.8 %
Date: 2017-07-14 10:03:36 Functions: 15 25 60.0 %

          Line data    Source code
       1             : /* src/vm/method.cpp - method functions
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       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.
      12             : 
      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.
      17             : 
      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
      21             :    02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : 
      26             : #include "vm/method.hpp"
      27             : #include "config.h"                     // for ENABLE_ANNOTATIONS, etc
      28             : 
      29             : #include <cassert>                      // for assert
      30             : #include <cstdio>                       // for printf
      31             : #include <stdint.h>                     // for int32_t
      32             : 
      33             : #include "mm/memory.hpp"
      34             : 
      35             : #include "native/llni.hpp"
      36             : 
      37             : #include "threads/mutex.hpp"            // for Mutex
      38             : 
      39             : #include "vm/annotation.hpp"
      40             : #include "vm/array.hpp"                 // for ObjectArray, ClassArray
      41             : #include "vm/breakpoint.hpp"            // for BreakpointTable
      42             : #include "vm/class.hpp"                 // for classinfo, etc
      43             : #include "vm/descriptor.hpp"
      44             : #include "vm/exceptions.hpp"
      45             : #include "vm/global.hpp"                // for java_handle_bytearray_t, etc
      46             : #include "vm/globals.hpp"
      47             : #include "vm/linker.hpp"
      48             : #include "vm/loader.hpp"                // for loader_skip_attribute_body, etc
      49             : #include "vm/options.hpp"               // for opt_debugcolor, opt_verify, etc
      50             : #include "vm/references.hpp"            // for classref_or_classinfo, etc
      51             : #include "vm/resolve.hpp"               // for resolve_class_from_typedesc, etc
      52             : #include "vm/stackmap.hpp"
      53             : #include "vm/statistics.hpp"
      54             : #include "vm/suck.hpp"                  // for suck_u2, etc
      55             : #include "vm/types.hpp"                 // for s4, u2, u1, u4
      56             : #include "vm/utf8.hpp"                  // for Utf8String, etc
      57             : #include "vm/vftbl.hpp"                 // for vftbl_t
      58             : #include "vm/vm.hpp"                    // for vm_abort
      59             : 
      60             : #include "vm/jit/builtin.hpp"           // for builtintable_entry
      61             : #include "vm/jit/code.hpp"              // for code_free_code_of_method, etc
      62             : #include "vm/jit/methodheader.hpp"
      63             : #include "vm/jit/stubs.hpp"             // for CompilerStub, NativeStub
      64             : 
      65             : using namespace cacao;
      66             : 
      67             : 
      68             : #if !defined(NDEBUG) && defined(ENABLE_INLINING)
      69             : #define INLINELOG(code)  do { if (opt_TraceInlining) { code } } while (0)
      70             : #else
      71             : #define INLINELOG(code)
      72             : #endif
      73             : 
      74             : 
      75             : STAT_REGISTER_VAR(int,count_all_methods,0,"all methods","Number of loaded Methods")
      76             : 
      77             : STAT_DECLARE_GROUP(info_struct_stat)
      78             : STAT_REGISTER_GROUP_VAR(int,size_lineinfo,0,"size lineinfo","lineinfo",info_struct_stat) // sizeof(lineinfo)?
      79             : 
      80             : STAT_DECLARE_GROUP(memory_stat)
      81             : STAT_REGISTER_SUM_SUBGROUP(table_stat,"info structs","info struct usage",memory_stat)
      82             : STAT_REGISTER_GROUP_VAR(int,count_extable_len,0,"extable len","exception tables",table_stat)
      83             : STAT_REGISTER_GROUP_VAR_EXTERN(int,size_linenumbertable,0,"size linenumbertable","size of linenumber tables",table_stat)
      84             : STAT_REGISTER_GROUP_VAR_EXTERN(int,count_linenumbertable,0,"count linenumbertable","number of linenumber tables",table_stat)
      85             : STAT_REGISTER_GROUP_VAR_EXTERN(int,size_patchref,0,"patchref","patcher references",table_stat)
      86             : 
      87             : STAT_DECLARE_VAR(int,count_vmcode_len,0)
      88             : /* global variables ***********************************************************/
      89             : 
      90             : methodinfo *method_java_lang_reflect_Method_invoke;
      91             : 
      92             : 
      93             : /* method_init *****************************************************************
      94             : 
      95             :    Initialize method subsystem.
      96             : 
      97             : *******************************************************************************/
      98             : 
      99         163 : void method_init(void)
     100             : {
     101             : #if defined(ENABLE_JAVASE)
     102             :         /* Sanity check. */
     103             : 
     104         163 :         if (class_java_lang_reflect_Method == NULL)
     105           0 :                 vm_abort("method_init: class_java_lang_reflect_Method is NULL");
     106             : 
     107             :         /* Cache java.lang.reflect.Method.invoke() */
     108             : 
     109             :         method_java_lang_reflect_Method_invoke =
     110         163 :                 class_findmethod(class_java_lang_reflect_Method, utf8::invoke, NULL);
     111             : 
     112         163 :         if (method_java_lang_reflect_Method_invoke == NULL)
     113           0 :                 vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
     114             : #endif
     115         163 : }
     116             : 
     117             : 
     118             : /* method_load *****************************************************************
     119             : 
     120             :    Loads a method from the class file and fills an existing methodinfo
     121             :    structure.
     122             : 
     123             :    method_info {
     124             :        u2 access_flags;
     125             :            u2 name_index;
     126             :            u2 descriptor_index;
     127             :            u2 attributes_count;
     128             :            attribute_info attributes[attribute_count];
     129             :    }
     130             : 
     131             :    attribute_info {
     132             :        u2 attribute_name_index;
     133             :            u4 attribute_length;
     134             :            u1 info[attribute_length];
     135             :    }
     136             : 
     137             :    LineNumberTable_attribute {
     138             :        u2 attribute_name_index;
     139             :            u4 attribute_length;
     140             :            u2 line_number_table_length;
     141             :            {
     142             :                u2 start_pc;
     143             :                    u2 line_number;
     144             :            } line_number_table[line_number_table_length];
     145             :    }
     146             : 
     147             :    LocalVariableTable_attribute {
     148             :        u2 attribute_name_index;
     149             :        u4 attribute_length;
     150             :        u2 local_variable_table_length;
     151             :        {
     152             :            u2 start_pc;
     153             :            u2 length;
     154             :            u2 name_index;
     155             :            u2 descriptor_index;
     156             :            u2 index;
     157             :        } local_variable_table[local_variable_table_length];
     158             :    }
     159             : 
     160             : *******************************************************************************/
     161             : 
     162      469928 : bool method_load(ClassBuffer& cb, methodinfo *m, DescriptorPool& descpool)
     163             : {
     164             :         int argcount;
     165             :         s4         i, j, k, l;
     166      469928 :         Utf8String u;
     167             :         u2         name_index;
     168             :         u2         descriptor_index;
     169             :         u2         attributes_count;
     170             :         u2         attribute_name_index;
     171      469928 :         Utf8String attribute_name;
     172             :         u2         code_attributes_count;
     173             :         u2         code_attribute_name_index;
     174      469928 :         Utf8String code_attribute_name;
     175             : 
     176             :         /* get classinfo */
     177             : 
     178      469928 :         classinfo *c = cb.get_class();
     179             : 
     180      469928 :         m->mutex = new Mutex();
     181             : 
     182             :         STATISTICS(count_all_methods++);
     183             : 
     184             :         /* all fields of m have been zeroed in load_class_from_classbuffer */
     185             : 
     186      469928 :         m->clazz = c;
     187             : 
     188      469928 :         if (!cb.check_size(2 + 2 + 2))
     189           0 :                 return false;
     190             : 
     191             :         /* access flags */
     192             : 
     193      469928 :         m->flags = cb.read_u2();
     194             : 
     195             :         /* name */
     196             : 
     197      469928 :         name_index = cb.read_u2();
     198             : 
     199      469928 :         if (!(u = (utf*) class_getconstant(c, name_index, CONSTANT_Utf8)))
     200           0 :                 return false;
     201             : 
     202      469928 :         m->name = u;
     203             : 
     204             :         /* descriptor */
     205             : 
     206      469928 :         descriptor_index = cb.read_u2();
     207             : 
     208      469928 :         if (!(u = (utf*) class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
     209           0 :                 return false;
     210             : 
     211      469928 :         m->descriptor = u;
     212             : 
     213      469928 :         if ((argcount = descpool.add_method(u)) == -1)
     214           0 :                 return false;
     215             : 
     216             : #ifdef ENABLE_VERIFIER
     217      469928 :         if (opt_verify) {
     218      469928 :                 if (!Utf8String(m->name).is_valid_name()) {
     219           0 :                         exceptions_throw_classformaterror(c, "Method with invalid name");
     220           0 :                         return false;
     221             :                 }
     222             : 
     223      469928 :                 if (m->name[0] == '<' &&
     224             :                         m->name != utf8::init && m->name != utf8::clinit) {
     225           0 :                         exceptions_throw_classformaterror(c, "Method with invalid special name");
     226           0 :                         return false;
     227             :                 }
     228             :         }
     229             : #endif /* ENABLE_VERIFIER */
     230             : 
     231             :         /* Ignore flags for class initializer according to section 4.6
     232             :            of "The Java Virtual Machine Specification, 2nd Edition" (see PR125). */
     233             : 
     234      469928 :         if (m->name == utf8::clinit) {
     235        9149 :                 m->flags &= ACC_STRICT;
     236        9149 :                 m->flags |= ACC_STATIC;
     237             :         }
     238             : 
     239      469928 :         if (!(m->flags & ACC_STATIC))
     240      361561 :                 argcount++; /* count the 'this' argument */
     241             : 
     242             : #ifdef ENABLE_VERIFIER
     243      469928 :         if (opt_verify) {
     244      469928 :                 if (argcount > 255) {
     245           0 :                         exceptions_throw_classformaterror(c, "Too many arguments in signature");
     246           0 :                         return false;
     247             :                 }
     248             : 
     249             :                 /* check flag consistency */
     250      469928 :                 if (m->name != utf8::clinit) {
     251      460779 :                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
     252             : 
     253      460779 :                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
     254             :                                 exceptions_throw_classformaterror(c,
     255             :                                                                                                   "Illegal method modifiers: 0x%X",
     256           0 :                                                                                                   m->flags);
     257           0 :                                 return false;
     258             :                         }
     259             : 
     260      460779 :                         if (m->flags & ACC_ABSTRACT) {
     261       41898 :                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
     262             :                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
     263             :                                         exceptions_throw_classformaterror(c,
     264             :                                                                                                           "Illegal method modifiers: 0x%X",
     265           0 :                                                                                                           m->flags);
     266           0 :                                         return false;
     267             :                                 }
     268             :                         }
     269             : 
     270      460779 :                         if (c->flags & ACC_INTERFACE) {
     271       24254 :                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
     272             :                                         exceptions_throw_classformaterror(c,
     273             :                                                                                                           "Illegal method modifiers: 0x%X",
     274           0 :                                                                                                           m->flags);
     275           0 :                                         return false;
     276             :                                 }
     277             :                         }
     278             : 
     279      460779 :                         if (m->name == utf8::init) {
     280       50954 :                                 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
     281             :                                                                 ACC_NATIVE | ACC_ABSTRACT)) {
     282           0 :                                         exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
     283           0 :                                         return false;
     284             :                                 }
     285             :                         }
     286             :                 }
     287             :         }
     288             : #endif /* ENABLE_VERIFIER */
     289             : 
     290             :         /* mark the method as monomorphic until further notice */
     291             : 
     292      469928 :         m->flags |= ACC_METHOD_MONOMORPHIC;
     293             : 
     294             :         /* non-abstract methods have an implementation in this class */
     295             : 
     296      469928 :         if (!(m->flags & ACC_ABSTRACT))
     297      428030 :                 m->flags |= ACC_METHOD_IMPLEMENTED;
     298             :                 
     299      469928 :         if (!cb.check_size(2))
     300           0 :                 return false;
     301             : 
     302             :         /* attributes count */
     303             : 
     304      469928 :         attributes_count = cb.read_u2();
     305             : 
     306      997905 :         for (i = 0; i < attributes_count; i++) {
     307      527977 :                 if (!cb.check_size(2))
     308           0 :                         return false;
     309             : 
     310             :                 /* attribute name index */
     311             : 
     312      527977 :                 attribute_name_index = cb.read_u2();
     313             : 
     314             :                 attribute_name =
     315      527977 :                         (utf*) class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
     316             : 
     317      527977 :                 if (attribute_name == NULL)
     318           0 :                         return false;
     319             : 
     320      527977 :                 if (attribute_name == utf8::Code) {
     321             :                         /* Code */
     322             : 
     323      398374 :                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
     324           0 :                                 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
     325           0 :                                 return false;
     326             :                         }
     327             :                         
     328      398374 :                         if (m->jcode) {
     329           0 :                                 exceptions_throw_classformaterror(c, "Multiple Code attributes");
     330           0 :                                 return false;
     331             :                         }
     332             : 
     333      398374 :                         if (!cb.check_size(4 + 2 + 2))
     334           0 :                                 return false;
     335             : 
     336      398374 :                         cb.read_u4();
     337      398374 :                         m->maxstack  = cb.read_u2();
     338      398374 :                         m->maxlocals = cb.read_u2();
     339             : 
     340      398374 :                         if (m->maxlocals < argcount) {
     341           0 :                                 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
     342           0 :                                 return false;
     343             :                         }
     344             :                         
     345      398374 :                         if (!cb.check_size(4))
     346           0 :                                 return false;
     347             : 
     348      398374 :                         m->jcodelength = cb.read_u4();
     349             : 
     350      398374 :                         if (m->jcodelength == 0) {
     351           0 :                                 exceptions_throw_classformaterror(c, "Code of a method has length 0");
     352           0 :                                 return false;
     353             :                         }
     354             :                         
     355      398374 :                         if (m->jcodelength > 65535) {
     356           0 :                                 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
     357           0 :                                 return false;
     358             :                         }
     359             : 
     360      398374 :                         if (!cb.check_size(m->jcodelength))
     361           0 :                                 return false;
     362             : 
     363      398374 :                         m->jcode = MNEW(u1, m->jcodelength);
     364      398374 :                         cb.read_nbytes(m->jcode, m->jcodelength);
     365             : 
     366      398374 :                         if (!cb.check_size(2))
     367           0 :                                 return false;
     368             : 
     369      398374 :                         m->rawexceptiontablelength = cb.read_u2();
     370      398374 :                         if (!cb.check_size((2 + 2 + 2 + 2) * m->rawexceptiontablelength))
     371           0 :                                 return false;
     372             : 
     373      398374 :                         m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
     374             : 
     375             :                         STATISTICS(count_vmcode_len += m->jcodelength + 18);
     376             :                         STATISTICS(count_extable_len +=
     377             :                                 m->rawexceptiontablelength * sizeof(raw_exception_entry));
     378             : 
     379      441557 :                         for (j = 0; j < m->rawexceptiontablelength; j++) {
     380             :                                 u4 idx;
     381       43183 :                                 m->rawexceptiontable[j].startpc   = cb.read_u2();
     382       43183 :                                 m->rawexceptiontable[j].endpc     = cb.read_u2();
     383       43183 :                                 m->rawexceptiontable[j].handlerpc = cb.read_u2();
     384             : 
     385       43183 :                                 idx = cb.read_u2();
     386             : 
     387       43183 :                                 if (!idx) {
     388       20709 :                                         m->rawexceptiontable[j].catchtype.any = NULL;
     389             :                                 }
     390             :                                 else {
     391             :                                         /* the classref is created later */
     392       22474 :                                         if (!(m->rawexceptiontable[j].catchtype.any =
     393             :                                                   (utf *) class_getconstant(c, idx, CONSTANT_ClassName)))
     394           0 :                                                 return false;
     395             :                                 }
     396             :                         }
     397             : 
     398      398374 :                         if (!cb.check_size(2))
     399           0 :                                 return false;
     400             : 
     401             :                         /* code attributes count */
     402             : 
     403      398374 :                         code_attributes_count = cb.read_u2();
     404             : 
     405      946103 :                         for (k = 0; k < code_attributes_count; k++) {
     406      547729 :                                 if (!cb.check_size(2))
     407           0 :                                         return false;
     408             : 
     409             :                                 /* code attribute name index */
     410             : 
     411      547729 :                                 code_attribute_name_index = cb.read_u2();
     412             : 
     413             :                                 code_attribute_name =
     414      547729 :                                         (utf*) class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
     415             : 
     416      547729 :                                 if (code_attribute_name == NULL)
     417           0 :                                         return false;
     418             : 
     419             :                                 /* check which code attribute */
     420             : 
     421      547729 :                                 if (code_attribute_name == utf8::LineNumberTable) {
     422             :                                         /* LineNumberTable */
     423             : 
     424      397933 :                                         if (!cb.check_size(4 + 2))
     425           0 :                                                 return false;
     426             : 
     427             :                                         /* attribute length */
     428             : 
     429      397933 :                                         (void) cb.read_u4();
     430             : 
     431             :                                         /* line number table length */
     432             : 
     433      397933 :                                         m->linenumbercount = cb.read_u2();
     434             : 
     435      397933 :                                         if (!cb.check_size((2 + 2) * m->linenumbercount))
     436           0 :                                                 return false;
     437             : 
     438      397933 :                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
     439             : 
     440             :                                         STATISTICS(size_lineinfo += sizeof(lineinfo) * m->linenumbercount);
     441             : 
     442     2344518 :                                         for (l = 0; l < m->linenumbercount; l++) {
     443     1946585 :                                                 m->linenumbers[l].start_pc    = cb.read_u2();
     444     1946585 :                                                 m->linenumbers[l].line_number = cb.read_u2();
     445             :                                         }
     446             :                                 }
     447             : #if defined(ENABLE_JAVASE)
     448      149796 :                                 else if (code_attribute_name == utf8::StackMapTable) {
     449             :                                         /* StackTableMap */
     450             : 
     451      148188 :                                         if (!stackmap_load_attribute_stackmaptable(cb, m))
     452           0 :                                                 return false;
     453             :                                 }
     454             : # if defined(ENABLE_JVMTI)
     455             :                                 else if (code_attribute_name == utf8::LocalVariableTable) {
     456             :                                         /* LocalVariableTable */
     457             : 
     458             :                                         if (m->localvars != NULL) {
     459             :                                                 exceptions_throw_classformaterror(c, "Multiple LocalVariableTable attributes");
     460             :                                                 return false;
     461             :                                         }
     462             : 
     463             :                                         if (!cb.check_size(4 + 2))
     464             :                                                 return false;
     465             : 
     466             :                                         // Attribute length.
     467             :                                         (void) cb.read_u4();
     468             : 
     469             :                                         m->localvarcount = cb.read_u2();
     470             : 
     471             :                                         if (!cb.check_size(10 * m->localvarcount))
     472             :                                                 return false;
     473             : 
     474             :                                         m->localvars = MNEW(localvarinfo, m->localvarcount);
     475             : 
     476             :                                         for (l = 0; l < m->localvarcount; l++) {
     477             :                                                 m->localvars[l].start_pc = cb.read_u2();
     478             :                                                 m->localvars[l].length   = cb.read_u2();
     479             : 
     480             :                                                 uint16_t name_index = cb.read_u2();
     481             :                                                 if (!(m->localvars[l].name = (utf*) class_getconstant(c, name_index, CONSTANT_Utf8)))
     482             :                                                         return false;
     483             : 
     484             :                                                 uint16_t descriptor_index = cb.read_u2();
     485             :                                                 if (!(m->localvars[l].descriptor = (utf*) class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
     486             :                                                         return false;
     487             : 
     488             :                                                 m->localvars[l].index = cb.read_u2();
     489             : 
     490             :                                                 // XXX Check if index is in range.
     491             :                                                 // XXX Check if index already taken.
     492             :                                         }
     493             :                                 }
     494             : # endif /* defined(ENABLE_JVMTI) */
     495             : #endif /* defined(ENABLE_JAVASE) */
     496             :                                 else {
     497             :                                         /* unknown code attribute */
     498             : 
     499        1608 :                                         if (!loader_skip_attribute_body(cb))
     500           0 :                                                 return false;
     501             :                                 }
     502             :                         }
     503             :                 }
     504      129603 :                 else if (attribute_name == utf8::Exceptions) {
     505             :                         /* Exceptions */
     506             : 
     507       57861 :                         if (m->thrownexceptions != NULL) {
     508           0 :                                 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
     509           0 :                                 return false;
     510             :                         }
     511             : 
     512       57861 :                         if (!cb.check_size(4 + 2))
     513           0 :                                 return false;
     514             : 
     515             :                         /* attribute length */
     516             : 
     517       57861 :                         (void) cb.read_u4();
     518             : 
     519       57861 :                         m->thrownexceptionscount = cb.read_u2();
     520             : 
     521       57861 :                         if (!cb.check_size(2 * m->thrownexceptionscount))
     522           0 :                                 return false;
     523             : 
     524       57861 :                         m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
     525             : 
     526      120425 :                         for (j = 0; j < m->thrownexceptionscount; j++) {
     527             :                                 /* the classref is created later */
     528       62564 :                                 if (!((m->thrownexceptions)[j].any =
     529             :                                           (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_ClassName)))
     530           0 :                                         return false;
     531             :                         }
     532             :                 }
     533             : #if defined(ENABLE_JAVASE)
     534       71742 :                 else if (attribute_name == utf8::Signature) {
     535             :                         /* Signature */
     536             : 
     537             :                         // TODO: change methodinfo.signature to Utf8String
     538             :                         //       and use it directly
     539             : 
     540       66076 :                         Utf8String signature = m->signature;
     541             : 
     542       66076 :                         if (!loader_load_attribute_signature(cb, signature)) {
     543           0 :                                 return false;
     544             :                         }
     545             : 
     546       66076 :                         m->signature = signature;
     547             :                 }
     548             : 
     549             : # if defined(ENABLE_ANNOTATIONS)
     550        5666 :                 else if (attribute_name == utf8::RuntimeVisibleAnnotations) {
     551             :                         /* RuntimeVisibleAnnotations */
     552         236 :                         if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
     553           0 :                                 return false;
     554             :                 }
     555        5430 :                 else if (attribute_name == utf8::RuntimeInvisibleAnnotations) {
     556             :                         /* RuntimeInvisibleAnnotations */
     557           0 :                         if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
     558           0 :                                 return false;
     559             :                 }
     560        5430 :                 else if (attribute_name == utf8::RuntimeVisibleParameterAnnotations) {
     561             :                         /* RuntimeVisibleParameterAnnotations */
     562           2 :                         if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
     563           0 :                                 return false;
     564             :                 }
     565        5428 :                 else if (attribute_name == utf8::RuntimeInvisibleParameterAnnotations) {
     566             :                         /* RuntimeInvisibleParameterAnnotations */
     567           0 :                         if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
     568           0 :                                 return false;
     569             :                 }
     570        5428 :                 else if (attribute_name == utf8::AnnotationDefault) {
     571             :                         /* AnnotationDefault */
     572          31 :                         if (!annotation_load_method_attribute_annotationdefault(cb, m))
     573           0 :                                 return false;
     574             :                 }
     575             : # endif
     576             : #endif
     577             :                 else {
     578             :                         /* unknown attribute */
     579             : 
     580        5397 :                         if (!loader_skip_attribute_body(cb))
     581           0 :                                 return false;
     582             :                 }
     583             :         }
     584             : 
     585      469928 :         if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
     586           0 :                 exceptions_throw_classformaterror(c, "Missing Code attribute");
     587           0 :                 return false;
     588             :         }
     589             : 
     590             : #if defined(ENABLE_REPLACEMENT)
     591             :         /* initialize the hit countdown field */
     592             : 
     593             :         m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
     594             : #endif
     595             : 
     596             :         /* everything was ok */
     597             : 
     598      469928 :         return true;
     599             : }
     600             : 
     601             : 
     602             : /* method_free *****************************************************************
     603             : 
     604             :    Frees all memory that was allocated for this method.
     605             : 
     606             : *******************************************************************************/
     607             : 
     608           2 : void method_free(methodinfo *m)
     609             : {
     610           2 :         if (m->mutex)
     611           2 :                 delete m->mutex;
     612             : 
     613           2 :         if (m->jcode)
     614           2 :                 MFREE(m->jcode, u1, m->jcodelength);
     615             : 
     616           2 :         if (m->rawexceptiontable)
     617           0 :                 MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
     618             : 
     619           2 :         code_free_code_of_method(m);
     620             : 
     621           2 :         if (m->stubroutine) {
     622           0 :                 if (m->flags & ACC_NATIVE) {
     623           0 :                         NativeStub::remove(m->stubroutine);
     624             :                 }
     625             :                 else {
     626           0 :                         CompilerStub::remove(m->stubroutine);
     627             :                 }
     628             :         }
     629             : 
     630           2 :         if (m->breakpoints)
     631           0 :                 delete m->breakpoints;
     632           2 : }
     633             : 
     634             : 
     635             : /* method_canoverwrite *********************************************************
     636             : 
     637             :    Check if m and old are identical with respect to type and
     638             :    name. This means that old can be overwritten with m.
     639             :         
     640             : *******************************************************************************/
     641             : 
     642     9956448 : bool method_canoverwrite(methodinfo *m, methodinfo *old)
     643             : {
     644     9956448 :         if (m->name != old->name)
     645     9431904 :                 return false;
     646             : 
     647      524544 :         if (m->descriptor != old->descriptor)
     648      229579 :                 return false;
     649             : 
     650      294965 :         if (m->flags & ACC_STATIC)
     651           0 :                 return false;
     652             : 
     653      294965 :         return true;
     654             : }
     655             : 
     656             : 
     657             : /* method_new_builtin **********************************************************
     658             : 
     659             :    Creates a minimal methodinfo structure for builtins. This comes handy
     660             :    when dealing with builtin stubs or stacktraces.
     661             : 
     662             : *******************************************************************************/
     663             : 
     664        2282 : methodinfo *method_new_builtin(builtintable_entry *bte)
     665             : {
     666             :         methodinfo *m;
     667             : 
     668             :         /* allocate the methodinfo structure */
     669             : 
     670        2282 :         m = NEW(methodinfo);
     671             : 
     672             :         /* initialize methodinfo structure */
     673             : 
     674        2282 :         MZERO(m, methodinfo, 1);
     675             :         
     676        2282 :         m->mutex      = new Mutex();
     677        2282 :         m->flags      = ACC_METHOD_BUILTIN;
     678        2282 :         m->parseddesc = bte->md;
     679        2282 :         m->name       = bte->name;
     680        2282 :         m->descriptor = bte->descriptor;
     681             : 
     682             :         /* return the newly created methodinfo */
     683             : 
     684        2282 :         return m;
     685             : }
     686             : 
     687             : 
     688             : /* method_vftbl_lookup *********************************************************
     689             : 
     690             :    Does a method lookup in the passed virtual function table.  This
     691             :    function does exactly the same thing as JIT, but additionally
     692             :    relies on the fact, that the methodinfo pointer is at the first
     693             :    data segment slot (even for compiler stubs).
     694             : 
     695             : *******************************************************************************/
     696             : 
     697      665092 : methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
     698             : {
     699             :         methodptr   mptr;
     700             :         methodptr  *pmptr;
     701             :         methodinfo *resm;                   /* pointer to new resolved method     */
     702             : 
     703             :         /* If the method is not an instance method, just return it. */
     704             : 
     705      665092 :         if (m->flags & ACC_STATIC)
     706           0 :                 return m;
     707             : 
     708      665092 :         assert(vftbl);
     709             : 
     710             :         /* Get the method from the virtual function table.  Is this an
     711             :            interface method? */
     712             : 
     713      665092 :         if (m->clazz->flags & ACC_INTERFACE) {
     714           0 :                 pmptr = vftbl->interfacetable[-(m->clazz->index)];
     715           0 :                 mptr  = pmptr[(m - m->clazz->methods)];
     716             :         }
     717             :         else {
     718      665092 :                 mptr = vftbl->table[m->vftblindex];
     719             :         }
     720             : 
     721             :         /* and now get the codeinfo pointer from the first data segment slot */
     722             : 
     723      665092 :         resm = code_get_methodinfo_for_pv(mptr);
     724             : 
     725      665092 :         return resm;
     726             : }
     727             : 
     728             : 
     729             : /* method_get_parametercount **************************************************
     730             : 
     731             :    Use the descriptor of a method to determine the number of parameters
     732             :    of the method. The this pointer of non-static methods is not counted.
     733             : 
     734             :    IN:
     735             :        m........the method of which the parameters should be counted
     736             : 
     737             :    RETURN VALUE:
     738             :        The parameter count.
     739             : 
     740             : *******************************************************************************/
     741             : 
     742          12 : int32_t method_get_parametercount(methodinfo *m)
     743             : {
     744             :         methoddesc *md;             /* method descriptor of m   */
     745          12 :         int32_t     paramcount = 0; /* the parameter count of m */
     746             : 
     747          12 :         md = m->parseddesc;
     748             : 
     749             :         /* is the descriptor fully parsed? */
     750             : 
     751          12 :         md->params_from_paramtypes(m->flags);
     752             : 
     753          12 :         paramcount = md->paramcount;
     754             : 
     755             :         /* skip `this' pointer */
     756             : 
     757          12 :         if (!(m->flags & ACC_STATIC)) {
     758           9 :                 --paramcount;
     759             :         }
     760             : 
     761          12 :         return paramcount;
     762             : }
     763             : 
     764             : 
     765             : /* method_get_parametertypearray ***********************************************
     766             : 
     767             :    Use the descriptor of a method to generate a java.lang.Class array
     768             :    which contains the classes of the parametertypes of the method.
     769             : 
     770             :    This function is called by java.lang.reflect.{Constructor,Method}.
     771             : 
     772             : *******************************************************************************/
     773             : 
     774        1727 : java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
     775             : {
     776             :         methoddesc* md;
     777             :         typedesc*   paramtypes;
     778             :         int32_t     paramcount;
     779             :         int32_t     i;
     780             :         classinfo*  c;
     781             : 
     782        1727 :         md = m->parseddesc;
     783             : 
     784             :         /* is the descriptor fully parsed? */
     785             : 
     786        1727 :         md->params_from_paramtypes(m->flags);
     787             : 
     788        1727 :         paramtypes = md->paramtypes;
     789        1727 :         paramcount = md->paramcount;
     790             : 
     791             :         /* skip `this' pointer */
     792             : 
     793        1727 :         if (!(m->flags & ACC_STATIC)) {
     794        1686 :                 paramtypes++;
     795        1686 :                 paramcount--;
     796             :         }
     797             : 
     798             :         /* create class-array */
     799             : 
     800        1727 :         ClassArray ca(paramcount);
     801             : 
     802        1727 :         if (ca.is_null())
     803           0 :                 return NULL;
     804             : 
     805             :     /* get classes */
     806             : 
     807        2283 :         for (i = 0; i < paramcount; i++) {
     808         556 :                 if (!resolve_class_from_typedesc(&paramtypes[i], true, false, &c))
     809           0 :                         return NULL;
     810             : 
     811         556 :                 ca.set_element(i, c);
     812             :         }
     813             : 
     814        1727 :         return ca.get_handle();
     815             : }
     816             : 
     817             : 
     818             : /* method_get_exceptionarray ***************************************************
     819             : 
     820             :    Get the exceptions which can be thrown by a method.
     821             : 
     822             : *******************************************************************************/
     823             : 
     824          74 : java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
     825             : {
     826             :         classinfo* c;
     827             :         s4         i;
     828             : 
     829             :         /* create class-array */
     830             : 
     831          74 :         ClassArray ca(m->thrownexceptionscount);
     832             : 
     833          74 :         if (ca.is_null())
     834           0 :                 return NULL;
     835             : 
     836             :         /* iterate over all exceptions and store the class in the array */
     837             : 
     838          74 :         for (i = 0; i < m->thrownexceptionscount; i++) {
     839           0 :                 c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
     840             : 
     841           0 :                 if (c == NULL)
     842           0 :                         return NULL;
     843             : 
     844           0 :                 ca.set_element(i, c);
     845             :         }
     846             : 
     847          74 :         return ca.get_handle();
     848             : }
     849             : 
     850             : 
     851             : /* method_returntype_get *******************************************************
     852             : 
     853             :    Get the return type of the method.
     854             : 
     855             : *******************************************************************************/
     856             : 
     857         987 : classinfo *method_returntype_get(methodinfo *m)
     858             : {
     859             :         typedesc  *td;
     860             :         classinfo *c;
     861             : 
     862         987 :         td = &(m->parseddesc->returntype);
     863             : 
     864         987 :         if (!resolve_class_from_typedesc(td, true, false, &c))
     865           0 :                 return NULL;
     866             : 
     867         987 :         return c;
     868             : }
     869             : 
     870             : 
     871             : /* method_count_implementations ************************************************
     872             : 
     873             :    Count the implementations of a method in a class cone (a class and all its
     874             :    subclasses.)
     875             : 
     876             :    IN:
     877             :        m................the method to count
     878             :            c................class at which to start the counting (this class and
     879             :                             all its subclasses will be searched)
     880             : 
     881             :    OUT:
     882             :        *found...........if found != NULL, *found receives the method
     883             :                             implementation that was found. This value is only
     884             :                                                 meaningful if the return value is 1.
     885             : 
     886             :    RETURN VALUE:
     887             :        the number of implementations found
     888             : 
     889             : *******************************************************************************/
     890             : 
     891           0 : s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
     892             : {
     893             :         s4          count;
     894             :         methodinfo *mp;
     895             :         methodinfo *mend;
     896             :         classinfo  *child;
     897             : 
     898           0 :         count = 0;
     899             : 
     900           0 :         mp = c->methods;
     901           0 :         mend = mp + c->methodscount;
     902             : 
     903           0 :         for (; mp < mend; ++mp) {
     904           0 :                 if (method_canoverwrite(mp, m)) {
     905           0 :                         if (found)
     906           0 :                                 *found = mp;
     907           0 :                         count++;
     908           0 :                         break;
     909             :                 }
     910             :         }
     911             : 
     912           0 :         for (child = c->sub; child != NULL; child = child->nextsub) {
     913           0 :                 count += method_count_implementations(m, child, found);
     914             :         }
     915             : 
     916           0 :         return count;
     917             : }
     918             : 
     919             : 
     920             : /* method_get_annotations ******************************************************
     921             : 
     922             :    Get a methods' unparsed annotations in a byte array.
     923             : 
     924             :    IN:
     925             :        m........the method of which the annotations should be returned
     926             : 
     927             :    RETURN VALUE:
     928             :        The unparsed annotations in a byte array (or NULL if there aren't any).
     929             : 
     930             : *******************************************************************************/
     931             : 
     932        8509 : java_handle_bytearray_t *method_get_annotations(methodinfo *m)
     933             : {
     934             : #if defined(ENABLE_ANNOTATIONS)
     935             :         classinfo     *c;                  /* methods' declaring class          */
     936             :         int            slot;               /* methods' slot                     */
     937             :         java_handle_t *method_annotations; /* all methods' unparsed annotations */
     938             :                                            /* of the declaring class            */
     939             : 
     940        8509 :         c    = m->clazz;
     941        8509 :         slot = m - c->methods;
     942             : 
     943        8509 :         LLNI_classinfo_field_get(c, method_annotations, method_annotations);
     944             : 
     945        8509 :         ObjectArray oa((java_handle_objectarray_t*) method_annotations);
     946             : 
     947             :         /* the method_annotations array might be shorter then the method
     948             :          * count if the methods above a certain index have no annotations.
     949             :          */     
     950        8509 :         if (method_annotations != NULL && oa.get_length() > slot) {
     951         305 :                 return (java_handle_bytearray_t*) oa.get_element(slot);
     952             :         } else {
     953        8204 :                 return NULL;
     954           0 :         }
     955             : #else
     956             :         return NULL;
     957             : #endif
     958             : }
     959             : 
     960             : 
     961             : /* method_get_parameterannotations ********************************************
     962             : 
     963             :    Get a methods' unparsed parameter annotations in an array of byte
     964             :    arrays.
     965             : 
     966             :    IN:
     967             :        m........the method of which the parameter annotations should be
     968             :                     returned
     969             : 
     970             :    RETURN VALUE:
     971             :        The unparsed parameter annotations in a byte array (or NULL if
     972             :            there aren't any).
     973             : 
     974             : *******************************************************************************/
     975             : 
     976        8509 : java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
     977             : {
     978             : #if defined(ENABLE_ANNOTATIONS)
     979             :         classinfo     *c;                           /* methods' declaring class */
     980             :         int            slot;                        /* methods' slot            */
     981             :         java_handle_t *method_parameterannotations; /* all methods' unparsed    */
     982             :                                                     /* parameter annotations of */
     983             :                                                     /* the declaring class      */
     984             : 
     985        8509 :         c    = m->clazz;
     986        8509 :         slot = m - c->methods;
     987             : 
     988        8509 :         LLNI_classinfo_field_get(
     989             :                 c, method_parameterannotations, method_parameterannotations);
     990             : 
     991        8509 :         ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations);
     992             : 
     993             :         /* the method_annotations array might be shorter then the method
     994             :          * count if the methods above a certain index have no annotations.
     995             :          */     
     996        8509 :         if (method_parameterannotations != NULL && oa.get_length() > slot) {
     997           9 :                 return (java_handle_bytearray_t*) oa.get_element(slot);
     998             :         } else {
     999        8500 :                 return NULL;
    1000           0 :         }
    1001             : #else
    1002             :         return NULL;
    1003             : #endif
    1004             : }
    1005             : 
    1006             : 
    1007             : /* method_get_annotationdefault ***********************************************
    1008             : 
    1009             :    Get a methods' unparsed annotation default value in a byte array.
    1010             :    
    1011             :    IN:
    1012             :        m........the method of which the annotation default value should be
    1013             :                     returned
    1014             : 
    1015             :    RETURN VALUE:
    1016             :        The unparsed annotation default value in a byte array (or NULL if
    1017             :            there isn't one).
    1018             : 
    1019             : *******************************************************************************/
    1020             : 
    1021        7933 : java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
    1022             : {
    1023             : #if defined(ENABLE_ANNOTATIONS)
    1024             :         classinfo     *c;                         /* methods' declaring class     */
    1025             :         int            slot;                      /* methods' slot                */
    1026             :         java_handle_t *method_annotationdefaults; /* all methods' unparsed        */
    1027             :                                                   /* annotation default values of */
    1028             :                                                   /* the declaring class          */
    1029             : 
    1030        7933 :         c    = m->clazz;
    1031        7933 :         slot = m - c->methods;
    1032             : 
    1033        7933 :         LLNI_classinfo_field_get(
    1034             :                 c, method_annotationdefaults, method_annotationdefaults);
    1035             : 
    1036        7933 :         ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults);
    1037             : 
    1038             :         /* the method_annotations array might be shorter then the method
    1039             :          * count if the methods above a certain index have no annotations.
    1040             :          */
    1041        7933 :         if (method_annotationdefaults != NULL && oa.get_length() > slot) {
    1042        1696 :                 return (java_handle_bytearray_t*) oa.get_element(slot);
    1043             :         } else {
    1044        6237 :                 return NULL;
    1045           0 :         }
    1046             : #else
    1047             :         return NULL;
    1048             : #endif
    1049             : }
    1050             : 
    1051             : 
    1052             : /* method_add_to_worklist ******************************************************
    1053             : 
    1054             :    Add the method to the given worklist. If the method already occurs in
    1055             :    the worklist, the worklist remains unchanged.
    1056             : 
    1057             : *******************************************************************************/
    1058             : 
    1059           0 : static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
    1060             : {
    1061             :         method_worklist *wi;
    1062             : 
    1063           0 :         for (wi = *wl; wi != NULL; wi = wi->next)
    1064           0 :                 if (wi->m == m)
    1065           0 :                         return;
    1066             : 
    1067           0 :         wi = NEW(method_worklist);
    1068           0 :         wi->next = *wl;
    1069           0 :         wi->m = m;
    1070             : 
    1071           0 :         *wl = wi;
    1072             : }
    1073             : 
    1074             : 
    1075             : /* method_add_assumption_monomorphic *******************************************
    1076             : 
    1077             :    Record the assumption that the method is monomorphic.
    1078             : 
    1079             :    IN:
    1080             :       m.................the method
    1081             :           caller............the caller making the assumption
    1082             : 
    1083             : *******************************************************************************/
    1084             : 
    1085           0 : void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
    1086             : {
    1087             :         method_assumption *as;
    1088             : 
    1089             :         /* XXX LOCKING FOR THIS FUNCTION? */
    1090             : 
    1091             :         /* check if we already have registered this assumption */
    1092             : 
    1093           0 :         for (as = m->assumptions; as != NULL; as = as->next) {
    1094           0 :                 if (as->context == caller)
    1095           0 :                         return;
    1096             :         }
    1097             : 
    1098             :         /* register the assumption */
    1099             : 
    1100           0 :         as = NEW(method_assumption);
    1101           0 :         as->next = m->assumptions;
    1102           0 :         as->context = caller;
    1103             : 
    1104           0 :         m->assumptions = as;
    1105             : }
    1106             : 
    1107             : /* method_break_assumption_monomorphic *****************************************
    1108             : 
    1109             :    Break the assumption that this method is monomorphic. All callers that
    1110             :    have registered this assumption are added to the worklist.
    1111             : 
    1112             :    IN:
    1113             :       m.................the method
    1114             :           wl................worklist where to add invalidated callers
    1115             : 
    1116             : *******************************************************************************/
    1117             : 
    1118       76646 : void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
    1119             : {
    1120             :         method_assumption *as;
    1121             : 
    1122             :         /* XXX LOCKING FOR THIS FUNCTION? */
    1123             : 
    1124       76646 :         for (as = m->assumptions; as != NULL; as = as->next) {
    1125             :                 INLINELOG(
    1126             :                         printf("ASSUMPTION BROKEN (monomorphism): ");
    1127             :                         method_print(m);
    1128             :                         printf(" in ");
    1129             :                         method_println(as->context);
    1130             :                 );
    1131             : 
    1132           0 :                 method_add_to_worklist(as->context, wl);
    1133             : 
    1134             : #if defined(ENABLE_TLH) && 0
    1135             :                 /* XXX hack */
    1136             :                 method_assumption *as2;
    1137             :                 as2 = m->assumptions;
    1138             :                 m->assumptions = NULL;
    1139             :                 method_break_assumption_monomorphic(as->context, wl);
    1140             :                 /*
    1141             :                 assert(m->assumptions == NULL);
    1142             :                 m->assumptions = as2;*/
    1143             : #endif
    1144             : 
    1145             :         }
    1146       76646 : }
    1147             : 
    1148             : /* method_printflags ***********************************************************
    1149             : 
    1150             :    Prints the flags of a method to stdout like.
    1151             : 
    1152             : *******************************************************************************/
    1153             : 
    1154             : #if !defined(NDEBUG)
    1155           0 : void method_printflags(methodinfo *m)
    1156             : {
    1157           0 :         if (m == NULL) {
    1158           0 :                 printf("NULL");
    1159           0 :                 return;
    1160             :         }
    1161             : 
    1162           0 :         if (m->flags & ACC_PUBLIC)             printf(" PUBLIC");
    1163           0 :         if (m->flags & ACC_PRIVATE)            printf(" PRIVATE");
    1164           0 :         if (m->flags & ACC_PROTECTED)          printf(" PROTECTED");
    1165           0 :         if (m->flags & ACC_STATIC)             printf(" STATIC");
    1166           0 :         if (m->flags & ACC_FINAL)              printf(" FINAL");
    1167           0 :         if (m->flags & ACC_SYNCHRONIZED)       printf(" SYNCHRONIZED");
    1168           0 :         if (m->flags & ACC_VOLATILE)           printf(" VOLATILE");
    1169           0 :         if (m->flags & ACC_TRANSIENT)          printf(" TRANSIENT");
    1170           0 :         if (m->flags & ACC_NATIVE)             printf(" NATIVE");
    1171           0 :         if (m->flags & ACC_INTERFACE)          printf(" INTERFACE");
    1172           0 :         if (m->flags & ACC_ABSTRACT)           printf(" ABSTRACT");
    1173           0 :         if (m->flags & ACC_METHOD_BUILTIN)     printf(" (builtin)");
    1174           0 :         if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
    1175           0 :         if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
    1176             : }
    1177             : #endif /* !defined(NDEBUG) */
    1178             : 
    1179             : 
    1180             : /* method_print ****************************************************************
    1181             : 
    1182             :    Prints a method to stdout like:
    1183             : 
    1184             :    java.lang.Object.<init>()V
    1185             : 
    1186             : *******************************************************************************/
    1187             : 
    1188             : #if !defined(NDEBUG)
    1189           0 : void method_print(methodinfo *m)
    1190             : {
    1191           0 :         if (m == NULL) {
    1192           0 :                 printf("NULL");
    1193           0 :                 return;
    1194             :         }
    1195             : 
    1196           0 :         if (m->clazz != NULL)
    1197           0 :                 utf_display_printable_ascii_classname(m->clazz->name);
    1198             :         else
    1199           0 :                 printf("NULL");
    1200           0 :         printf(".");
    1201           0 :         utf_display_printable_ascii(m->name);
    1202           0 :         utf_display_printable_ascii(m->descriptor);
    1203             : 
    1204           0 :         method_printflags(m);
    1205             : }
    1206             : #endif /* !defined(NDEBUG) */
    1207             : 
    1208             : 
    1209             : /* method_println **************************************************************
    1210             : 
    1211             :    Prints a method plus new line to stdout like:
    1212             : 
    1213             :    java.lang.Object.<init>()V
    1214             : 
    1215             : *******************************************************************************/
    1216             : 
    1217             : #if !defined(NDEBUG)
    1218           0 : void method_println(methodinfo *m)
    1219             : {
    1220           0 :         if (opt_debugcolor) printf("\033[31m");       /* red */
    1221           0 :         method_print(m);
    1222           0 :         if (opt_debugcolor) printf("\033[m");
    1223           0 :         printf("\n");
    1224           0 : }
    1225             : #endif /* !defined(NDEBUG) */
    1226             : 
    1227             : 
    1228             : /* method_methodref_print ******************************************************
    1229             : 
    1230             :    Prints a method reference to stdout.
    1231             : 
    1232             : *******************************************************************************/
    1233             : 
    1234             : #if !defined(NDEBUG)
    1235           0 : void method_methodref_print(constant_FMIref *mr)
    1236             : {
    1237           0 :         if (!mr) {
    1238           0 :                 printf("(constant_FMIref *)NULL");
    1239           0 :                 return;
    1240             :         }
    1241             : 
    1242           0 :         if (mr->is_resolved()) {
    1243           0 :                 printf("<method> ");
    1244           0 :                 method_print(mr->p.method);
    1245             :         }
    1246             :         else {
    1247           0 :                 printf("<methodref> ");
    1248           0 :                 utf_display_printable_ascii_classname(mr->p.classref->name);
    1249           0 :                 printf(".");
    1250           0 :                 utf_display_printable_ascii(mr->name);
    1251           0 :                 utf_display_printable_ascii(mr->descriptor);
    1252             :         }
    1253             : }
    1254             : #endif /* !defined(NDEBUG) */
    1255             : 
    1256             : 
    1257             : /* method_methodref_println ****************************************************
    1258             : 
    1259             :    Prints a method reference to stdout, followed by a newline.
    1260             : 
    1261             : *******************************************************************************/
    1262             : 
    1263             : #if !defined(NDEBUG)
    1264           0 : void method_methodref_println(constant_FMIref *mr)
    1265             : {
    1266           0 :         method_methodref_print(mr);
    1267           0 :         printf("\n");
    1268           0 : }
    1269             : #endif /* !defined(NDEBUG) */
    1270             : 
    1271       92267 : bool method_matches(methodinfo *m, const char* name) {
    1272       92267 :         if (!m || !name)
    1273       92267 :                 return false;
    1274           0 :         return m->name == Utf8String::from_utf8(name);
    1275             : }
    1276             : 
    1277             : namespace cacao {
    1278             : namespace {
    1279             : 
    1280           0 : inline OStream& method_printflags_OS(OStream &OS, const struct methodinfo &m)
    1281             : {
    1282           0 :         if (m.flags & ACC_PUBLIC)             OS << " PUBLIC" ;
    1283           0 :         if (m.flags & ACC_PRIVATE)            OS << " PRIVATE" ;
    1284           0 :         if (m.flags & ACC_PROTECTED)          OS << " PROTECTED" ;
    1285           0 :         if (m.flags & ACC_STATIC)             OS << " STATIC" ;
    1286           0 :         if (m.flags & ACC_FINAL)              OS << " FINAL" ;
    1287           0 :         if (m.flags & ACC_SYNCHRONIZED)       OS << " SYNCHRONIZED" ;
    1288           0 :         if (m.flags & ACC_VOLATILE)           OS << " VOLATILE" ;
    1289           0 :         if (m.flags & ACC_TRANSIENT)          OS << " TRANSIENT" ;
    1290           0 :         if (m.flags & ACC_NATIVE)             OS << " NATIVE" ;
    1291           0 :         if (m.flags & ACC_INTERFACE)          OS << " INTERFACE" ;
    1292           0 :         if (m.flags & ACC_ABSTRACT)           OS << " ABSTRACT" ;
    1293           0 :         if (m.flags & ACC_METHOD_BUILTIN)     OS << " (builtin)" ;
    1294           0 :         if (m.flags & ACC_METHOD_MONOMORPHIC) OS << " (mono)" ;
    1295           0 :         if (m.flags & ACC_METHOD_IMPLEMENTED) OS << " (impl)" ;
    1296           0 :         return OS;
    1297             : }
    1298             : } // end anonymous namespace
    1299             : 
    1300           0 : OStream& operator<<(OStream &OS, const struct methodinfo &m)
    1301             : {
    1302             :         OS << (Utf8String)m.clazz->name << "."
    1303             :            << (Utf8String)m.name
    1304           0 :            << (Utf8String)m.descriptor;
    1305           0 :         method_printflags_OS(OS,m);
    1306           0 :         return OS;
    1307             : }
    1308             : 
    1309             : } // end namespace cacao
    1310             : 
    1311             : /*
    1312             :  * These are local overrides for various environment variables in Emacs.
    1313             :  * Please do not remove this and leave it at the end of the file, where
    1314             :  * Emacs will automagically detect them.
    1315             :  * ---------------------------------------------------------------------
    1316             :  * Local variables:
    1317             :  * mode: c++
    1318             :  * indent-tabs-mode: t
    1319             :  * c-basic-offset: 4
    1320             :  * tab-width: 4
    1321             :  * End:
    1322             :  * vim:noexpandtab:sw=4:ts=4:
    1323             :  */

Generated by: LCOV version 1.11