LCOV - code coverage report
Current view: top level - vm - descriptor.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 288 392 73.5 %
Date: 2015-06-10 18:10:59 Functions: 34 41 82.9 %

          Line data    Source code
       1             : /* src/vm/descriptor.cpp - checking and parsing of field / method descriptors
       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             : #include "vm/descriptor.hpp"
      26             : #include "config.h"                     // for ENABLE_JIT
      27             : 
      28             : #include <cassert>                      // for assert
      29             : #include <cstdarg>                      // for va_end, va_list, va_start
      30             : 
      31             : #include "mm/memory.hpp"                // for MNEW, MMOVE
      32             : 
      33             : #include "threads/mutex.hpp"            // for Mutex
      34             : 
      35             : #include "toolbox/OStream.hpp"          // for OStream
      36             : #include "toolbox/buffer.hpp"           // for Buffer
      37             : #include "toolbox/logging.hpp"          // for LOG
      38             : 
      39             : #include "vm/exceptions.hpp"
      40             : #include "vm/global.hpp"                // for Type::TYPE_ADR, etc
      41             : #include "vm/options.hpp"
      42             : #include "vm/primitive.hpp"             // for PrimitiveType, etc
      43             : #include "vm/references.hpp"            // for constant_classref
      44             : #include "vm/types.hpp"                 // for u4, u1, s4, s2, u2
      45             : #include "vm/utf8.hpp"                  // for Utf8String, operator<<, etc
      46             : #include "vm/vm.hpp"                    // for vm_abort
      47             : 
      48             : #include "vm/jit/abi.hpp"               // for md_param_alloc, etc
      49             : 
      50             : struct classinfo;
      51             : 
      52             : using namespace cacao;
      53             : 
      54             : #define DEBUG_NAME "descriptor"
      55             : 
      56             : 
      57             : /***
      58             :  *
      59             :  *      Field & method descriptor parsing
      60             :  *
      61             :  *      See JVM Spec §4.3.2 (Field Descriptors) and §4.3.3 (Method Descriptors)
      62             :  *
      63             :  *      All methods return true on success and throw an exception on error.
      64             :  *      They also check if the parsed type is valid for its position, for example 
      65             :  *      a field type can't be void but a return type can.
      66             :  *
      67             :  *      Calling a check or parse method consumes the input.
      68             :  *      In the following example the call to parse_field_descriptor() will fail
      69             :  *      because check_field_descriptor() has consumed the whole descriptor.
      70             :  *      @code
      71             :  *              DescriptorParser p(pool, Utf8String::from_utf8("J"));
      72             :  *              if (!p.check_field_descriptor())
      73             :  *                      return false;
      74             :  *              if (!p.parse_field_descriptor(&t))
      75             :  *                      return false;
      76             :  *      @endcode
      77             :  */
      78             : struct DescriptorParser {
      79             :         DescriptorParser(DescriptorPool *pool, Utf8String desc);
      80             : 
      81             :         /***
      82             :          *      Check if descriptor is valid.
      83             :          *      Any class references in descriptor will be added to pool
      84             :          */
      85             :         bool check_field_descriptor();
      86             :         bool check_param_descriptor(Type &dst);
      87             :         bool check_return_descriptor();
      88             : 
      89             :         /***
      90             :          *      Parse descriptor into typedesc.
      91             :          *      Descriptor must have previously been checked with check_*_descriptor()
      92             :          *      All class references are looked up in pool.
      93             :          */
      94             :         bool parse_field_descriptor(typedesc *dst);
      95             :         bool parse_param_descriptor(typedesc *dst);
      96             :         bool parse_return_descriptor(typedesc *dst);
      97             : 
      98             :         /***
      99             :          *      Start parsing a method descriptors parameter list
     100             :          */
     101             :         bool start_param_list();
     102             : 
     103             :         /***
     104             :          *      Check if the parameter list we are currently parsing 
     105             :          *      has more parameters to parse.
     106             :          */
     107             :         bool has_more_params();
     108             : private:
     109             :         enum ParserFlag {
     110             :                 FORBID_VOID_TYPE,
     111             :                 EXPECT_END_OF_INPUT
     112             :         };
     113             : 
     114             :         enum ParseResult {
     115             :                 PARSE_ERROR,
     116             :                 PRIMITIVE_TYPE,
     117             :                 REFERENCE_TYPE
     118             :         };
     119             : 
     120             : 
     121             :         template<int flags>
     122     2112362 :         bool check_type(const char *descriptor_type, Type& t);
     123             : 
     124             :         template<int flags>
     125     2112353 :         bool parse_type(const char *descriptor_type, typedesc *t);
     126             : 
     127             :         template<int flags>
     128             :         ParseResult parse_type(Type& t, PrimitiveType& p,
     129             :                                Utf8String& classname, size_t& arraydim);
     130             : 
     131             :         bool parse_classname(Utf8String& classname);
     132             :         bool parse_arraytype(Utf8String& classname, size_t& arraydim);
     133             : 
     134             :         bool skip_classname();
     135             : 
     136             :         bool read(char&);
     137             :         void unread();
     138             : 
     139             :         bool has_more_input() const;
     140             : 
     141             :         /// throws a classformat error and returns false
     142             :         bool throw_error(const char *reason, ...);
     143             : 
     144             :         DescriptorPool *const pool;
     145             :         const char     *descriptor_type;  // what kind of descriptor we are currently parsing
     146             :         const char     *pos, *end;        // text of descriptor
     147             : };
     148             : 
     149     2241356 : inline DescriptorParser::DescriptorParser(DescriptorPool *pool, Utf8String desc)
     150     2241356 :  : pool(pool), pos(desc.begin()), end(desc.end()) {}
     151             : 
     152       78559 : inline bool DescriptorParser::check_field_descriptor() {
     153             :         Type dummy;
     154             : 
     155       78559 :         return check_type<FORBID_VOID_TYPE | EXPECT_END_OF_INPUT>("field", dummy);
     156             : }
     157      991681 : inline bool DescriptorParser::check_param_descriptor(Type &dst) {
     158      991681 :         return check_type<FORBID_VOID_TYPE>("parameter", dst);
     159             : }
     160     1042122 : inline bool DescriptorParser::check_return_descriptor() {
     161             :         Type dummy;
     162             : 
     163     1042122 :         return check_type<EXPECT_END_OF_INPUT>("return type", dummy);
     164             : }
     165             : 
     166       78557 : inline bool DescriptorParser::parse_field_descriptor(typedesc *dst) {
     167       78557 :         return parse_type<FORBID_VOID_TYPE | EXPECT_END_OF_INPUT>("field", dst);
     168             : }
     169      991678 : inline bool DescriptorParser::parse_param_descriptor(typedesc *dst) {
     170      991678 :         return parse_type<FORBID_VOID_TYPE>("parameter", dst);
     171             : }
     172     1042118 : inline bool DescriptorParser::parse_return_descriptor(typedesc *dst) {
     173     1042118 :         return parse_type<EXPECT_END_OF_INPUT>("return type", dst);
     174             : }
     175             : 
     176     2084240 : inline bool DescriptorParser::start_param_list() {
     177     2084240 :         descriptor_type = "method";
     178             : 
     179     2084240 :         char c = 0;
     180             : 
     181     2084240 :         if (!read(c))
     182           0 :                 return false;
     183             : 
     184     2084240 :         if (c != '(')
     185           0 :                 return throw_error("Method descriptor does not start with '('");
     186             : 
     187     2084240 :         return true;
     188             : }
     189             : 
     190     4067599 : inline bool DescriptorParser::has_more_params() {
     191     4067599 :         if (!has_more_input())
     192           0 :                 return false;
     193     4067599 :         if (*pos == ')') {
     194     2084240 :                 pos++;
     195     2084240 :                 return false;
     196             :         }
     197             : 
     198     1983359 :         return true;
     199             : }
     200             : 
     201     6308955 : inline bool DescriptorParser::has_more_input() const {
     202     6308955 :         return pos != end;
     203             : }
     204             : 
     205             : template<int flags>
     206             : inline bool DescriptorParser::check_type(const char *descriptor_type, Type& dst) {
     207     2112362 :         this->descriptor_type = descriptor_type;
     208             : 
     209             :         Type          type;
     210             :         PrimitiveType primtype;
     211     2112362 :         Utf8String    classname;
     212     2112362 :         size_t        arraydim = 0;
     213             : 
     214     2112362 :         switch (parse_type<flags>(type, primtype, classname, arraydim)) {
     215             :         case PARSE_ERROR:
     216           0 :                 return false;
     217             :         case PRIMITIVE_TYPE:
     218     1049986 :                 dst = type;
     219     1049986 :                 return true;
     220             :         case REFERENCE_TYPE:
     221             :                 // descriptor is array or class type
     222     1062376 :                 dst = type;
     223     1062376 :                 return pool->add_class(classname);
     224             :         default:
     225           0 :                 assert(false);
     226             :                 return false;
     227             :         }
     228             : }
     229             : 
     230             : template<int flags>
     231             : inline bool DescriptorParser::parse_type(const char *descriptor_type, typedesc *dst) {
     232     2112353 :         this->descriptor_type = descriptor_type;
     233             : 
     234     2112353 :         Type          type     = TYPE_INT;
     235     2112353 :         PrimitiveType primtype = PRIMITIVETYPE_INT;
     236     2112353 :         Utf8String    classname;
     237     2112353 :         size_t        arraydim = 0;
     238             : 
     239     2112353 :         switch (parse_type<flags>(type, primtype, classname, arraydim)) {
     240             :         case PARSE_ERROR:
     241           0 :                 return false;
     242             :         case PRIMITIVE_TYPE:
     243     1049982 :                 dst->classref      = NULL;
     244     1049982 :                 dst->type          = type;
     245     1049982 :                 dst->primitivetype = primtype;
     246     1049982 :                 dst->arraydim      = 0;
     247     1049982 :                 return true;
     248             :         case REFERENCE_TYPE:
     249     1062371 :                 dst->classref      = pool->lookup_classref(classname);
     250     1062371 :                 dst->type          = TYPE_ADR;
     251     1062371 :                 dst->primitivetype = (PrimitiveType) TYPE_ADR;
     252     1062371 :                 dst->arraydim      = arraydim;
     253     1062371 :                 return true;
     254             :         default:
     255           0 :                 assert(false);
     256             :                 return false;
     257             :         }
     258             : }
     259             : 
     260             : template<int flags>
     261     4224715 : inline DescriptorParser::ParseResult DescriptorParser::parse_type(Type&          t,
     262             :                                                                   PrimitiveType& p,
     263             :                                                                   Utf8String&    classname,
     264             :                                                                   size_t&        arraydim) {
     265             :         ParseResult result;
     266     4224715 :         char        c = 0;
     267             : 
     268     4224715 :         if (!read(c))
     269           0 :                 return PARSE_ERROR;
     270             : 
     271     4224715 :         switch (c) {
     272             :         case 'B':
     273       18514 :                 t      = TYPE_INT;
     274       18514 :                 p      = PRIMITIVETYPE_BYTE;
     275       18514 :                 result = PRIMITIVE_TYPE;
     276       18514 :                 break;
     277             :         case 'C':
     278       73496 :                 t      = TYPE_INT;
     279       73496 :                 p      = PRIMITIVETYPE_CHAR;
     280       73496 :                 result = PRIMITIVE_TYPE;
     281       73496 :                 break;
     282             :         case 'D':
     283       64678 :                 t      = TYPE_DBL;
     284       64678 :                 p      = PRIMITIVETYPE_DOUBLE;
     285       64678 :                 result = PRIMITIVE_TYPE;
     286       64678 :                 break;
     287             :         case 'F':
     288       42170 :                 t      = TYPE_FLT;
     289       42170 :                 p      = PRIMITIVETYPE_FLOAT;
     290       42170 :                 result = PRIMITIVE_TYPE;
     291       42170 :                 break;
     292             :         case 'I':
     293      766696 :                 t      = TYPE_INT;
     294      766696 :                 p      = PRIMITIVETYPE_INT;
     295      766696 :                 result = PRIMITIVE_TYPE;
     296      766696 :                 break;
     297             :         case 'J':
     298      117336 :                 t      = TYPE_LNG;
     299      117336 :                 p      = PRIMITIVETYPE_LONG;
     300      117336 :                 result = PRIMITIVE_TYPE;
     301      117336 :                 break;
     302             :         case 'S':
     303       16120 :                 t      = TYPE_INT;
     304       16120 :                 p      = PRIMITIVETYPE_SHORT;
     305       16120 :                 result = PRIMITIVE_TYPE;
     306       16120 :                 break;
     307             :         case 'Z':
     308      321158 :                 t      = TYPE_INT;
     309      321158 :                 p      = PRIMITIVETYPE_BOOLEAN;
     310      321158 :                 result = PRIMITIVE_TYPE;
     311      321158 :                 break;
     312             :         case 'V':
     313             :                 if (flags & FORBID_VOID_TYPE) {
     314             :                         throw_error("Type void is illegal");
     315             :                         return PARSE_ERROR;
     316             :                 }
     317             : 
     318      679800 :                 t      = TYPE_VOID;
     319      679800 :                 p      = PRIMITIVETYPE_VOID;
     320      679800 :                 result = PRIMITIVE_TYPE;
     321      679800 :                 break;
     322             : 
     323             :         case 'L': // object (L<classname>;)
     324     1883365 :                 if (!parse_classname(classname))
     325           0 :                         return PARSE_ERROR;
     326             : 
     327     1883365 :                 t        = TYPE_ADR;
     328     1883365 :                 arraydim = 0;
     329     1883365 :                 result   = REFERENCE_TYPE;
     330     1883365 :                 break;
     331             :         case '[': // array type
     332      241382 :                 unread(); // parse_arraytype counts the '['
     333             : 
     334      241382 :                 if (!parse_arraytype(classname, arraydim))
     335           0 :                         return PARSE_ERROR;
     336             : 
     337      241382 :                 t      = TYPE_ADR;
     338      241382 :                 result = REFERENCE_TYPE;
     339      241382 :                 break;
     340             :         default:
     341           0 :                 throw_error("Illegal character '%c'", c);
     342           0 :                 return PARSE_ERROR;
     343             :         }
     344             : 
     345     2241356 :         if ((flags & EXPECT_END_OF_INPUT) && has_more_input()) {
     346           0 :                 throw_error("Unexpected characters at end of descriptor");
     347           0 :                 return PARSE_ERROR;
     348             :         }
     349             : 
     350     4224715 :         return result;
     351             : }
     352             : 
     353     1883365 : inline bool DescriptorParser::parse_classname(Utf8String& classname) {
     354             :         // find end of classname
     355             : 
     356     1883365 :         const char *mark = pos;
     357             : 
     358     1883365 :         if (!skip_classname())
     359           0 :                 return false;
     360             : 
     361             :         // utf8 string from classname
     362             : 
     363     1883365 :         Utf8String str = Utf8String::from_utf8(mark, pos - mark - 1);
     364             : 
     365     1883365 :         if (str == NULL)
     366           0 :                 return throw_error("Class name is not valid UTF-8");
     367             : 
     368             :         // done
     369             : 
     370     1883365 :         classname = str;
     371     1883365 :         return true;
     372             : }
     373             : 
     374      241382 : inline bool DescriptorParser::parse_arraytype(Utf8String& classname, size_t& arraydim) {
     375      241382 :         size_t array_dimension = 0;
     376             : 
     377      241382 :         const char *mark = pos;
     378             : 
     379      241382 :         char c = 0;
     380             : 
     381             :         // skip leading '['
     382             : 
     383      246300 :         while (true) {
     384      487682 :                 if (!read(c))
     385           0 :                         return false;
     386      487682 :                 if (c != '[')
     387             :                         break;
     388             : 
     389      246300 :                 array_dimension++;
     390             :         }
     391             : 
     392      241382 :         if (array_dimension > 255)
     393           0 :                 return throw_error("Too large array dimension: %lu", array_dimension);
     394             : 
     395             :         // check if element type is valid
     396             : 
     397      241382 :         switch (c) {
     398             :         case 'B': // primitive type
     399             :         case 'C':
     400             :         case 'D':
     401             :         case 'F':
     402             :         case 'I':
     403             :         case 'J':
     404             :         case 'S':
     405             :         case 'Z':
     406       97300 :                 break;
     407             : 
     408             :         case 'L': // object (L<classname>;)
     409      144082 :                 if(!skip_classname())
     410           0 :                         return false;
     411             : 
     412      144082 :                 break;
     413             : 
     414             :         default:
     415           0 :                 return throw_error("Illegal type of array element '%c'", c);
     416             :         }
     417             : 
     418      241382 :         classname = Utf8String::from_utf8(mark, pos - mark);
     419             : 
     420      241382 :         if (classname == NULL)
     421           0 :                 return throw_error("Name is not valid utf8: '%s'", mark);
     422             : 
     423      241382 :         arraydim = array_dimension;
     424             : 
     425      241382 :         return true;
     426             : }
     427             : 
     428    40016889 : inline bool DescriptorParser::skip_classname() {
     429             :         // classname is delimited by 'L' and ';'
     430             :         // but at this point the 'L' was already consumed
     431             : 
     432    37989442 :         while (true) {
     433    40016889 :                 char c = 0;
     434             : 
     435    40016889 :                 if (!read(c))
     436           0 :                         return false;
     437    40016889 :                 if (c == ';')
     438     2027447 :                         return true;
     439             :         }
     440             : }
     441             : 
     442    46813526 : inline bool DescriptorParser::read(char& c) {
     443    46813526 :         if (pos == end)
     444           0 :                 return throw_error("Truncated descriptor");
     445             : 
     446    46813526 :         c = *pos++;
     447    46813526 :         return true;
     448             : }
     449             : 
     450      241382 : inline void DescriptorParser::unread() {
     451      241382 :         pos--;
     452      241382 : }
     453             : 
     454           0 : inline bool DescriptorParser::throw_error(const char *reason, ...) {
     455           0 :         assert(descriptor_type);
     456             : 
     457           0 :         Buffer<> buf;
     458             :         va_list  ap;
     459             : 
     460           0 :         va_start(ap, reason);
     461           0 :         buf.write("Invalid ").write(descriptor_type).write(" descriptor: ").writevf(reason, ap);
     462           0 :         va_end(ap);
     463             : 
     464           0 :         exceptions_throw_classformaterror(pool->get_referer(), buf.utf8_str());
     465           0 :         return false;
     466             : }
     467             : 
     468             : //******************************************************************************
     469             : //      Descriptor pool
     470             : //******************************************************************************
     471             : 
     472             : // initial number of entries for the classrefhash of a descriptor pool
     473             : #define CLASSREFHASH_INIT_SIZE  256
     474             : 
     475             : // initial number of entries for the fieldrefhash of a descriptor pool
     476             : #define FIELDREFHASH_INIT_SIZE  256
     477             : 
     478             : 
     479       35953 : DescriptorPool::DescriptorPool(classinfo *referer) : classrefhash(CLASSREFHASH_INIT_SIZE),
     480             :                                                      fieldrefhash(FIELDREFHASH_INIT_SIZE),
     481             :                                                      referer(referer),
     482             :                                                      fieldcount(0),
     483             :                                                      methodcount(0),
     484             :                                                      paramcount(0),
     485             :                                                      descriptorsize(0),
     486             :                                                      classrefs(NULL),
     487             :                                                      mutex(new Mutex()),
     488             :                                                      descriptors(NULL),
     489       35953 :                                                      descriptors_next(NULL) {}
     490             : 
     491             : /***
     492             :  * Allocate an object from the descriptor pools private block of memory.
     493             :  * This function performs no checks, you can only allocate objects you have
     494             :  * previously added via add_field or add_method.
     495             :  */
     496             : template<typename T>
     497     3041703 : T *DescriptorPool::allocate(size_t size) {
     498     3041703 :         T *t = (T*) descriptors_next;
     499             : 
     500     3041703 :         descriptors_next += size;
     501             : 
     502     3041703 :         return t;
     503             : }
     504             : 
     505             : 
     506             : /***
     507             :  * Add the given class reference to the pool
     508             :  *
     509             :  * @return false iff an exception was thrown.
     510             : */
     511     1400320 : bool DescriptorPool::add_class(Utf8String name) {
     512             :         LOG("DescriptorPool::add_class(" << name << ")");
     513             : 
     514     1400320 :         assert(name);
     515             : 
     516             :         /* find a place in the hashtable */
     517             : 
     518     1400320 :         ClassrefHash::EntryRef ref = classrefhash.find(name);
     519             : 
     520     1400320 :         if (ref)
     521      979647 :                 return true; // classname was already present
     522             : 
     523             :         /* check if the name is a valid classname */
     524             : 
     525      420673 :         if (!name.is_valid_name()) {
     526           0 :                 exceptions_throw_classformaterror(referer, "Invalid class name");
     527           0 :                 return false; /* exception */
     528             :         }
     529             : 
     530             :         /* XXX check maximum array dimension */
     531             : 
     532      420673 :         classrefhash.insert(ref, name, classrefhash.size());
     533      420673 :         return true;
     534             : }
     535             : 
     536             : 
     537             : /***
     538             :  * Check the given descriptor and add it to the pool
     539             :  *
     540             :  * @param desc the field descriptor to add.
     541             :  * @return false iff an exception has been thrown
     542             :  */
     543      214307 : bool DescriptorPool::add_field(Utf8String desc) {
     544             :         LOG("DescriptorPool::add_field(" << ((void*) this) << ", " << desc << ")\n");
     545             : 
     546             :         // check if field descriptor was already in table
     547             : 
     548      214307 :         FieldrefHash::EntryRef ref = fieldrefhash.find(desc);
     549             : 
     550      214307 :         if (ref)
     551      135748 :                 return true;
     552             : 
     553             :         // check the descriptor
     554             : 
     555       78559 :         DescriptorParser parser(this, desc);
     556             : 
     557       78559 :         if (!parser.check_field_descriptor())
     558           0 :                 return false;
     559             : 
     560             :         // add the descriptor to the pool
     561             : 
     562       78559 :         fieldrefhash.insert(ref, desc, (typedesc*) NULL);
     563             : 
     564             :         // done
     565             : 
     566       78559 :         fieldcount++;
     567       78559 :         return true;
     568             : }
     569             : 
     570             : /***
     571             :  * Check the given descriptor and add it to the pool
     572             :  *
     573             :  * @param desc the method descriptor to add.
     574             :  * @return false iff an exception has been thrown
     575             :  */
     576     1042122 : ssize_t DescriptorPool::add_method(Utf8String desc) {
     577             :         LOG("DescriptorPool::add_method(" << ((void*) this) << ", " << desc << ")\n");
     578             : 
     579     1042122 :         assert(desc);
     580             : 
     581             :         // check the descriptor
     582             : 
     583     1042122 :         DescriptorParser parser(this, desc);
     584             : 
     585     1042122 :         size_t argcount = 0;
     586             : 
     587             :         // check parameters
     588             : 
     589     1042122 :         if (!parser.start_param_list())
     590           0 :                 return -1;
     591             : 
     592     3075925 :         while (parser.has_more_params()) {
     593             :                 // We cannot count the `this' argument here because
     594             :                 // we don't know if the method is static.
     595             : 
     596      991681 :                 paramcount++;
     597             : 
     598             :                 Type type;
     599             : 
     600      991681 :                 if (!parser.check_param_descriptor(type))
     601           0 :                         return -1;
     602             : 
     603      991681 :                 argcount += IS_2_WORD_TYPE(type) ? 2 : 1;
     604             :         }
     605             : 
     606     1042122 :         if (argcount > 255) {
     607           0 :                 exceptions_throw_classformaterror(referer, "Too many arguments in signature");
     608           0 :                 return -1;
     609             :         }
     610             : 
     611             :         // check return type
     612             : 
     613     1042122 :         if (!parser.check_return_descriptor())
     614           0 :                 return -1;
     615             : 
     616             :         // done
     617             : 
     618     1042122 :         methodcount++;
     619     1042122 :         return argcount;
     620             : }
     621             : 
     622             : 
     623             : /***
     624             :  * Create a table containing all the classrefs which were added to the pool
     625             :  *
     626             :  * @param[out] count  if count is non-NULL, this is set to the number
     627             :  *                    of classrefs in the table
     628             :  * @return a pointer to the constant_classref table
     629             :  */
     630       35953 : constant_classref *DescriptorPool::create_classrefs(s4 *count)
     631             : {
     632             :         size_t nclasses;
     633             : 
     634       35953 :         nclasses  = classrefhash.size();
     635       35953 :         classrefs = MNEW(constant_classref,nclasses);
     636             : 
     637             :         // fill the constant_classref structs
     638             : 
     639      456626 :         for (ClassrefHash::Iterator it = classrefhash.begin(), end = classrefhash.end(); it != end; ++it) {
     640      420673 :                 new (classrefs + it->value()) constant_classref(referer, it->key());
     641             :         }
     642             : 
     643       35953 :         if (count)
     644       35790 :                 *count = nclasses;
     645             : 
     646       35953 :         return classrefs;
     647             : }
     648             : 
     649             : 
     650             : /***
     651             :  *  Return the constant_classref for the given class name
     652             :  *
     653             :  * @param classname  name of the class to look up
     654             :  * @return a pointer to the constant_classref, or
     655             :  *           NULL if an exception has been thrown
     656             :  */
     657     1541093 : constant_classref *DescriptorPool::lookup_classref(Utf8String classname)
     658             : {
     659     1541093 :         assert(classrefs);
     660     1541093 :         assert(classname);
     661             : 
     662     1541093 :         if (ClassrefHash::EntryRef ref = classrefhash.find(classname)) {
     663     1541093 :                 return classrefs + ref->value();
     664             :         } else {
     665           0 :                 exceptions_throw_internalerror("Class reference not found in descriptor pool");
     666           0 :                 return NULL;
     667             :         }
     668             : }
     669             : 
     670             : 
     671             : /***
     672             :  * Allocate space for the parsed descriptors
     673             :  *
     674             :  * @note
     675             :  *    This function must be called after all descriptors have been added
     676             :  *    with DescriptorPool::add.
     677             :  */
     678       35953 : void DescriptorPool::alloc_parsed_descriptors() {
     679             :         /* TWISTI: paramcount + 1: we don't know if the method is static or   */
     680             :         /* not, i have no better solution yet.                                */
     681             : 
     682             :         size_t size = fieldcount  * sizeof(typedesc)
     683             :                         + methodcount * (sizeof(methoddesc) - sizeof(typedesc))
     684             :                         + paramcount  * sizeof(typedesc)
     685       35953 :                         + methodcount * sizeof(typedesc);      // possible `this' pointer
     686             : 
     687       35953 :         descriptorsize = size;
     688             : 
     689       35953 :         if (size) {
     690       35141 :                 descriptors      = MNEW(u1, size);
     691       35141 :                 descriptors_next = descriptors;
     692             :         }
     693       35953 : }
     694             : 
     695             : 
     696             : /***
     697             :  *  Parse the given field descriptor
     698             :  *
     699             :  * @param pool the descriptor_pool
     700             :  * @param desc the field descriptor
     701             :  * @return a pointer to the parsed field descriptor, or
     702             :  *         NULL if an exception has been thrown
     703             :  *
     704             :  * @note
     705             :  *    DescriptorPool::alloc_parsed_descriptors must be called (once)
     706             :  *    before this function is used.
     707             :  */
     708      214303 : typedesc *DescriptorPool::parse_field_descriptor(Utf8String desc) {
     709      214303 :         assert(descriptors);
     710      214303 :         assert(descriptors_next);
     711             : 
     712             :         // lookup the descriptor in the hashtable
     713             : 
     714      214303 :         FieldrefHash::EntryRef ref = fieldrefhash.find(desc);
     715             : 
     716      214303 :         assert(ref);
     717             : 
     718      214303 :         typedesc *td = ref->value();
     719             : 
     720      214303 :         if (!td) {
     721             :                 // field has been parsed yet.
     722       78557 :                 td = allocate<typedesc>();
     723             : 
     724       78557 :                 DescriptorParser parser(this, desc);
     725             : 
     726       78557 :                 if (!parser.parse_field_descriptor(td))
     727           0 :                         return NULL;
     728             : 
     729       78557 :                 ref->value() = td;
     730             :         }
     731             : 
     732      214303 :         return td;
     733             : }
     734             : 
     735             : 
     736             : /***
     737             :  * Parse the given method descriptor
     738             :  * 
     739             :  * @param desc      the method descriptor
     740             :  * @param mflags    the method flags
     741             :  * @param thisclass classref to the class containing the method.
     742             :  *                  This is ignored if mflags contains ACC_STATIC.
     743             :  *                  The classref is stored for inserting the 'this' argument.
     744             :  * @return a pointer to the parsed method descriptor, 
     745             :  *         or NULL if an exception has been thrown
     746             :  *
     747             :  * @note
     748             :  *      descriptor_pool::alloc_parsed_descriptors must be called
     749             :  *     (once) before this function is used.
     750             :  */
     751     1042118 : methoddesc *DescriptorPool::parse_method_descriptor(Utf8String         desc,
     752             :                                                                                             s4                 mflags,
     753             :                                                     constant_classref *thisclass) {
     754             :         LOG("DescriptorPool::parse_method_descriptor(" << ((void*) this) << ", " << mflags << ", " << thisclass << ")\n");
     755             : 
     756     1042118 :         assert(descriptors);
     757     1042118 :         assert(descriptors_next);
     758             : 
     759             :         // check that it is a method descriptor
     760             : 
     761     1042118 :         if (desc[0] != '(') {
     762             :                 exceptions_throw_classformaterror(referer,
     763           0 :                                                                                   "Field descriptor used in method reference");
     764           0 :                 return NULL;
     765             :         }
     766             : 
     767     1042118 :         methoddesc *md = allocate<methoddesc>(offsetof(methoddesc, paramtypes));
     768     1042118 :         md->pool_lock  = mutex;
     769             : 
     770     1042118 :         s2 paramcount = 0;
     771     1042118 :         s2 paramslots = 0;
     772             : 
     773             :         // count the `this' pointer
     774             : 
     775     1042118 :         if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
     776      361559 :                 typedesc *td = allocate<typedesc>();
     777             : 
     778      361559 :                 td->type          = TYPE_ADR;
     779      361559 :                 td->arraydim      = 0;
     780      361559 :                 td->classref      = thisclass;
     781             : 
     782      361559 :                 paramcount++;
     783      361559 :                 paramslots++;
     784             :         }
     785             : 
     786             :         // parse parameters
     787             : 
     788     1042118 :         DescriptorParser parser(this, desc);
     789             : 
     790     1042118 :         if (!parser.start_param_list())
     791           0 :                 return NULL;
     792             : 
     793     3075914 :         while (parser.has_more_params()) {
     794             :                 // parse a parameter type
     795             : 
     796      991678 :                 typedesc *td = allocate<typedesc>();
     797             : 
     798      991678 :                 if (!parser.parse_param_descriptor(td))
     799           0 :                         return NULL;
     800             : 
     801      991678 :                 if (IS_2_WORD_TYPE(td->type))
     802       49786 :                         paramslots++;
     803             : 
     804      991678 :                 paramcount++;
     805      991678 :                 paramslots++;
     806             :         }
     807             : 
     808     1042118 :         md->paramcount = paramcount;
     809     1042118 :         md->paramslots = paramslots;
     810             : 
     811             :         // Skip possible `this' pointer in paramtypes array to allow a possible
     812             :         // memory move later in parse.
     813             :         // We store the thisclass reference, so we can later correctly fill in
     814             :         // the parameter slot of the 'this' argument.
     815             : 
     816     1042118 :         if (mflags == ACC_UNDEF) {
     817      567791 :                 typedesc *td = allocate<typedesc>();
     818             : 
     819      567791 :                 td->classref = thisclass;
     820             :         }
     821             : 
     822             :         // parse return type
     823             : 
     824     1042118 :         if (!parser.parse_return_descriptor(&md->returntype))
     825           0 :                 return NULL;
     826             : 
     827             :         // If mflags != ACC_UNDEF we parse a real loaded method, so do
     828             :         // param prealloc.  Otherwise we do this in stack analysis.
     829             : 
     830     1042118 :         if (mflags != ACC_UNDEF) {
     831      474327 :                 if (md->paramcount > 0) {
     832             :                         // allocate memory for params
     833             : 
     834      451575 :                         md->params = MNEW(paramdesc, md->paramcount);
     835             :                 } else {
     836       22752 :                         md->params = METHODDESC_NOPARAMS;
     837             :                 }
     838             : 
     839             :                 // fill the paramdesc
     840             :                 // md_param_alloc has to be called if md->paramcount == 0,
     841             :                 // too, so it can make the reservation for the Linkage Area,
     842             :                 // Return Register...
     843             : 
     844             : #if defined(ENABLE_JIT)
     845             :                 // As builtin-functions are native functions, we have
     846             :                 // to pre-allocate for the native ABI.
     847             : 
     848      474327 :                 if (mflags & ACC_METHOD_BUILTIN)
     849        4401 :                         md_param_alloc_native(md);
     850             :                 else
     851      469926 :                         md_param_alloc(md);
     852             : #endif
     853             : 
     854             :                 // params already initialized; no need to lock
     855      474327 :                 md->pool_lock = NULL;
     856             :         } else {
     857             :                 // params will be allocated later by
     858             :                 // methoddesc::params_from_paramtypes if necessary
     859             : 
     860      567791 :                 md->params = NULL;
     861             :         }
     862             : 
     863     1042118 :         return md;
     864             : }
     865             : 
     866             : /***
     867             :  * Create the paramdescs for a method descriptor. This function is
     868             :  * called when we know whether the method is static or not. This
     869             :  * function does nothing if md->params != NULL (checked atomically).
     870             :  *
     871             :  * @param mflags the ACC_* access flags of the method. Only the
     872             :  *               ACC_STATIC bit is checked.
     873             :  *               The value ACC_UNDEF is NOT allowed.
     874             :  *
     875             :  * @post parms != NULL
     876             :  */
     877      880473 : void methoddesc::params_from_paramtypes(s4 mflags) {
     878      880473 :         bool has_lock = pool_lock != NULL;
     879             : 
     880      880473 :         if (pool_lock)
     881      637446 :                 pool_lock->lock();
     882      880473 :         if (params) {
     883      706858 :                 if (has_lock)
     884      468775 :                         pool_lock->unlock();
     885      706858 :                 return;
     886             :         }
     887             : 
     888      173615 :         assert(params == NULL);
     889      173615 :         assert(mflags != ACC_UNDEF);
     890             : 
     891      173615 :         typedesc *td = paramtypes;
     892             : 
     893             :         /* check for `this' pointer */
     894             : 
     895      173615 :         if (!(mflags & ACC_STATIC)) {
     896             :                 constant_classref *thisclass;
     897             : 
     898             :                 /* fetch class reference from reserved param slot */
     899      145688 :                 thisclass = td[paramcount].classref;
     900      145688 :                 assert(thisclass);
     901             : 
     902      145688 :                 if (paramcount > 0) {
     903             :                         /* shift param types by 1 argument */
     904       73803 :                         MMOVE(td + 1, td, typedesc, paramcount);
     905             :                 }
     906             : 
     907             :                 /* fill in first argument `this' */
     908             : 
     909      145688 :                 td->type          = TYPE_ADR;
     910      145688 :                 td->primitivetype = (PrimitiveType) TYPE_ADR;
     911      145688 :                 td->arraydim      = 0;
     912      145688 :                 td->classref      = thisclass;
     913             : 
     914      145688 :                 paramcount++;
     915      145688 :                 paramslots++;
     916             :         }
     917             : 
     918             :         // if the method has params, process them
     919             : 
     920      173615 :         if (paramcount > 0) {
     921             :                 // allocate memory for params
     922      166552 :                 params = MNEW(paramdesc, paramcount);
     923             :         } else {
     924        7063 :                 params = METHODDESC_NOPARAMS;
     925             :         }
     926             : 
     927             :         // fill the paramdesc
     928             :         // md_param_alloc has to be called if md->paramcount == 0, too, so
     929             :         // it can make the reservation for the Linkage Area, Return Register, ...
     930             : 
     931             : #if defined(ENABLE_JIT)
     932             :         // As builtin-functions are native functions, we have to
     933             :         // pre-allocate for the native ABI.
     934             : 
     935      173615 :         if (mflags & ACC_METHOD_BUILTIN)
     936           0 :                 md_param_alloc_native(this);
     937             :         else
     938      173615 :                 md_param_alloc(this);
     939             : #endif
     940             : 
     941      173615 :         if (has_lock)
     942      168671 :                 pool_lock->unlock();
     943             : }
     944             : 
     945           0 : classinfo *DescriptorPool::get_referer() {
     946           0 :         return referer;
     947             : }
     948             : 
     949             : /***
     950             :  * Get the sizes of the class reference table and the parsed descriptors
     951             :  *
     952             :  * @param[out] classrefsize  set to size of the class reference table
     953             :  * @param[out] descsize      set to size of the parsed descriptors
     954             :  *
     955             :  * @note
     956             :  *     This function may only be called after both
     957             :  *     descriptor_pool::create_classrefs, and
     958             :  *     descriptor_pool::alloc_parsed_descriptors
     959             :  *     have been called.
     960             :  */
     961           0 : void DescriptorPool::get_sizes(size_t *classrefsize, size_t *descsize) {
     962           0 :         assert((!fieldcount && !methodcount) || descriptors);
     963           0 :         assert(classrefs);
     964           0 :         assert(classrefsize);
     965           0 :         assert(descsize);
     966             : 
     967           0 :         *classrefsize = classrefhash.size() * sizeof(constant_classref);
     968           0 :         *descsize     = descriptorsize;
     969           0 : }
     970             : 
     971             : 
     972             : /***
     973             :  * Return the basic type to use for a value with this descriptor.
     974             :  *
     975             :  * @pre This function assumes that the descriptor has passed
     976             :  *      DescriptorPool::add_field checks and that it does not start with '('.
     977             :  */
     978      113368 : Type descriptor_to_basic_type(Utf8String descriptor) {
     979      113368 :         assert(descriptor.size() >= 1);
     980             : 
     981      113368 :         switch (descriptor[0]) {
     982             :         case 'Z':
     983             :         case 'B':
     984             :         case 'C':
     985             :         case 'S':
     986             :         case 'I':
     987       39898 :                 return TYPE_INT;
     988             : 
     989             :         case 'J':
     990       13977 :                 return TYPE_LNG;
     991             : 
     992             :         case 'F':
     993        2229 :                 return TYPE_FLT;
     994             : 
     995             :         case 'D':
     996        1289 :                 return TYPE_DBL;
     997             : 
     998             :         case 'L':
     999             :         case '[':
    1000       55975 :                 return TYPE_ADR;
    1001             : 
    1002             :         default:
    1003           0 :                 vm_abort("descriptor_to_basic_type: invalid type %c", descriptor[0]);
    1004           0 :                 return TYPE_VOID;
    1005             :         }
    1006             : }
    1007             : 
    1008             : 
    1009             : /****************************************************************************/
    1010             : /* DEBUG HELPERS                                                            */
    1011             : /****************************************************************************/
    1012             : 
    1013             : /***
    1014             :  * Print the given typedesc to the given stream
    1015             :  */
    1016           0 : void descriptor_debug_print_typedesc(FILE *file,typedesc *d) {
    1017             :         int ch;
    1018             : 
    1019           0 :         if (!d) {
    1020           0 :                 fprintf(file,"(typedesc *)NULL");
    1021           0 :                 return;
    1022             :         }
    1023             : 
    1024           0 :         if (d->type == TYPE_ADR) {
    1025           0 :                 if (d->classref)
    1026           0 :                         utf_fprint_printable_ascii(file,d->classref->name);
    1027             :                 else
    1028           0 :                         fprintf(file,"<class=NULL>");
    1029             :         }
    1030             :         else {
    1031           0 :                 switch (d->primitivetype) {
    1032           0 :                         case PRIMITIVETYPE_INT    : ch='I'; break;
    1033           0 :                         case PRIMITIVETYPE_CHAR   : ch='C'; break;
    1034           0 :                         case PRIMITIVETYPE_BYTE   : ch='B'; break;
    1035           0 :                         case PRIMITIVETYPE_SHORT  : ch='S'; break;
    1036           0 :                         case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
    1037           0 :                         case PRIMITIVETYPE_LONG   : ch='J'; break;
    1038           0 :                         case PRIMITIVETYPE_FLOAT  : ch='F'; break;
    1039           0 :                         case PRIMITIVETYPE_DOUBLE : ch='D'; break;
    1040           0 :                         case PRIMITIVETYPE_VOID   : ch='V'; break;
    1041           0 :                         default                   : ch='!';
    1042             :                 }
    1043           0 :                 fputc(ch,file);
    1044             :         }
    1045           0 :         if (d->arraydim)
    1046           0 :                 fprintf(file,"[%d]",d->arraydim);
    1047             : }
    1048             : 
    1049             : /***
    1050             :  * Print the given paramdesc to the given stream
    1051             :  */
    1052           0 : void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d) {
    1053           0 :         if (!d) {
    1054           0 :                 fprintf(file,"(paramdesc *)NULL");
    1055           0 :                 return;
    1056             :         }
    1057             : 
    1058           0 :         if (d->inmemory) {
    1059           0 :                 fprintf(file,"<m%d>",d->regoff);
    1060             :         }
    1061             :         else {
    1062           0 :                 fprintf(file,"<r%d>",d->regoff);
    1063             :         }
    1064             : }
    1065             : 
    1066             : /***
    1067             :  * Print the given methoddesc to the given stream
    1068             :  */
    1069           0 : void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d) {
    1070             :         int i;
    1071             : 
    1072           0 :         if (!d) {
    1073           0 :                 fprintf(file,"(methoddesc *)NULL");
    1074           0 :                 return;
    1075             :         }
    1076             : 
    1077           0 :         fputc('(',file);
    1078           0 :         for (i=0; i<d->paramcount; ++i) {
    1079           0 :                 if (i)
    1080           0 :                         fputc(',',file);
    1081           0 :                 descriptor_debug_print_typedesc(file,d->paramtypes + i);
    1082           0 :                 if (d->params) {
    1083           0 :                         descriptor_debug_print_paramdesc(file,d->params + i);
    1084             :                 }
    1085             :         }
    1086           0 :         if (d->params == METHODDESC_NOPARAMS)
    1087           0 :                 fputs("<NOPARAMS>",file);
    1088           0 :         fputc(')',file);
    1089           0 :         descriptor_debug_print_typedesc(file,&(d->returntype));
    1090             : }
    1091             : 
    1092             : 
    1093             : /*
    1094             :  * These are local overrides for various environment variables in Emacs.
    1095             :  * Please do not remove this and leave it at the end of the file, where
    1096             :  * Emacs will automagically detect them.
    1097             :  * ---------------------------------------------------------------------
    1098             :  * Local variables:
    1099             :  * mode: c++
    1100             :  * indent-tabs-mode: t
    1101             :  * c-basic-offset: 4
    1102             :  * tab-width: 4
    1103             :  * End:
    1104             :  * vim:noexpandtab:sw=4:ts=4:
    1105             :  */

Generated by: LCOV version 1.11