#include "final.h"
#include "heap.h"
#include "mm/memory.h"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
/* Global Variables ***********************************************************/
#include "mm/memory.h"
#include "toolbox/logging.h"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
#include "vm/rt-timing.h"
#include "vm/vm.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
#include "vm/global.h"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "toolbox/list.hpp"
#include "vm/exceptions.hpp"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
#include "vm/global.h"
#include "vm/options.h"
#include "vm/string.hpp"
classcache.cpp \
classcache.hpp \
$(CYCLES_STATS_SOURCES) \
- descriptor.c \
- descriptor.h \
+ descriptor.cpp \
+ descriptor.hpp \
exceptions.cpp \
exceptions.hpp \
field.cpp \
field.hpp \
- finalizer.c \
- finalizer.h \
+ finalizer.cpp \
+ finalizer.hpp \
globals.cpp \
globals.hpp \
initialize.cpp \
+++ /dev/null
-/* src/vm/descriptor.c - checking and parsing of field / method descriptors
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "vm/descriptor.h"
-#include "vm/exceptions.hpp"
-#include "vm/options.h"
-#include "vm/primitive.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit/abi.h"
-
-
-/* constants (private to descriptor.c) ****************************************/
-
-/* initial number of entries for the classrefhash of a descriptor_pool */
-/* (currently the hash is never grown!) */
-#define CLASSREFHASH_INIT_SIZE 64
-
-/* initial number of entries for the descriptorhash of a descriptor_pool */
-/* (currently the hash is never grown!) */
-#define DESCRIPTORHASH_INIT_SIZE 128
-
-/* data structures (private to descriptor.c) **********************************/
-
-typedef struct classref_hash_entry classref_hash_entry;
-typedef struct descriptor_hash_entry descriptor_hash_entry;
-
-/* entry struct for the classrefhash of descriptor_pool */
-struct classref_hash_entry {
- classref_hash_entry *hashlink; /* for hash chaining */
- utf *name; /* name of the class refered to */
- u2 index; /* index into classref table */
-};
-
-/* entry struct for the descriptorhash of descriptor_pool */
-struct descriptor_hash_entry {
- descriptor_hash_entry *hashlink;
- utf *desc;
- parseddesc_t parseddesc;
- s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
-};
-
-
-/****************************************************************************/
-/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
-/****************************************************************************/
-
-/* SKIP_FIELDDESCRIPTOR:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * CAUTION: This macro does not check for an unexpected end of the
- * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
- */
-#define SKIP_FIELDDESCRIPTOR(utf_ptr) \
- do { while (*(utf_ptr)=='[') (utf_ptr)++; \
- if (*(utf_ptr)++=='L') \
- while(*(utf_ptr)++ != ';') /* skip */; } while(0)
-
-/* SKIP_FIELDDESCRIPTOR_SAFE:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * Input:
- * utf_ptr....points to first char of descriptor
- * end_ptr....points to first char after the end of the string
- * errorflag..must be initialized (to false) by the caller!
- * Output:
- * utf_ptr....points to first char after the descriptor
- * errorflag..set to true if the string ended unexpectedly
- */
-#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
- do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
- if ((utf_ptr) == (end_ptr)) \
- (errorflag) = true; \
- else \
- if (*(utf_ptr)++=='L') { \
- while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
- /* skip */; \
- if ((utf_ptr)[-1] != ';') \
- (errorflag) = true; }} while(0)
-
-
-/****************************************************************************/
-/* DEBUG HELPERS */
-/****************************************************************************/
-
-/*#define DESCRIPTOR_VERBOSE*/
-
-/****************************************************************************/
-/* FUNCTIONS */
-/****************************************************************************/
-
-/* descriptor_to_basic_type ****************************************************
-
- Return the basic type to use for a value with this descriptor.
-
- IN:
- utf..............descriptor utf string
-
- OUT:
- A TYPE_* constant.
-
- PRECONDITIONS:
- This function assumes that the descriptor has passed
- descriptor_pool_add checks and that it does not start with '('.
-
-*******************************************************************************/
-
-int descriptor_to_basic_type(utf *descriptor)
-{
- assert(descriptor->blength >= 1);
-
- switch (descriptor->text[0]) {
- case 'Z':
- case 'B':
- case 'C':
- case 'S':
- case 'I':
- return TYPE_INT;
-
- case 'J':
- return TYPE_LNG;
-
- case 'F':
- return TYPE_FLT;
-
- case 'D':
- return TYPE_DBL;
-
- case 'L':
- case '[':
- return TYPE_ADR;
-
- default:
- vm_abort("descriptor_to_basic_type: invalid type %c",
- descriptor->text[0]);
- }
-
- /* keep the compiler happy */
-
- return 0;
-}
-
-
-/* descriptor_typesize *********************************************************
-
- Return the size in bytes needed for the given type.
-
- IN:
- td..............typedesc describing the type
-
- OUT:
- The number of bytes
-
-*******************************************************************************/
-
-int descriptor_typesize(typedesc *td)
-{
- assert(td);
-
- switch (td->type) {
- case TYPE_INT:
- case TYPE_FLT:
- return 4;
-
- case TYPE_LNG:
- case TYPE_DBL:
- return 8;
-
- case TYPE_ADR:
- return SIZEOF_VOID_P;
-
- default:
- vm_abort("descriptor_typesize: invalid type %d", td->type);
- }
-
- /* keep the compiler happy */
-
- return 0;
-}
-
-
-/* name_from_descriptor ********************************************************
-
- Return the class name indicated by the given descriptor
- (Internally used helper function)
-
- IN:
- c................class containing the descriptor
- utf_ptr..........first character of descriptor
- end_ptr..........first character after the end of the string
- mode.............a combination (binary or) of the following flags:
-
- (Flags marked with * are the default settings.)
-
- How to handle "V" descriptors:
-
- * DESCRIPTOR_VOID.....handle it like other primitive types
- DESCRIPTOR_NOVOID...treat it as an error
-
- How to deal with extra characters after the end of the
- descriptor:
-
- * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
- DESCRIPTOR_CHECKEND.....treat them as an error
-
- OUT:
- *next............if non-NULL, *next is set to the first character after
- the descriptor. (Undefined if an error occurs.)
- *name............set to the utf name of the class
-
- RETURN VALUE:
- true.............descriptor parsed successfully
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#define DESCRIPTOR_VOID 0 /* default */
-#define DESCRIPTOR_NOVOID 0x0040
-#define DESCRIPTOR_NOCHECKEND 0 /* default */
-#define DESCRIPTOR_CHECKEND 0x1000
-
-static bool
-name_from_descriptor(classinfo *c,
- char *utf_ptr, char *end_ptr,
- char **next, int mode, utf **name)
-{
- char *start = utf_ptr;
- bool error = false;
-
- assert(c);
- assert(utf_ptr);
- assert(end_ptr);
- assert(name);
-
- *name = NULL;
- SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
-
- if (mode & DESCRIPTOR_CHECKEND)
- error |= (utf_ptr != end_ptr);
-
- if (!error) {
- if (next) *next = utf_ptr;
-
- switch (*start) {
- case 'V':
- if (mode & DESCRIPTOR_NOVOID)
- break;
- /* FALLTHROUGH! */
- case 'I':
- case 'J':
- case 'F':
- case 'D':
- case 'B':
- case 'C':
- case 'S':
- case 'Z':
- return true;
-
- case 'L':
- start++;
- utf_ptr--;
- /* FALLTHROUGH! */
- case '[':
- *name = utf_new(start, utf_ptr - start);
- return true;
- }
- }
-
- exceptions_throw_classformaterror(c, "Invalid descriptor");
- return false;
-}
-
-
-/* descriptor_to_typedesc ******************************************************
-
- Parse the given type descriptor and fill a typedesc struct
- (Internally used helper function)
-
- IN:
- pool.............the descriptor pool
- utf_ptr..........points to first character of type descriptor
- end_pos..........points after last character of the whole descriptor
-
- OUT:
- *next............set to next character after type descriptor
- *d...............filled with parsed information
-
- RETURN VALUE:
- true.............parsing succeeded
- false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool
-descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
- char **next, typedesc *td)
-{
- utf *name;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
- return false;
-
- if (name) {
- /* a reference type */
- td->type = TYPE_ADR;
- td->primitivetype = TYPE_ADR;
- td->arraydim = 0;
- for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
- td->arraydim++;
- td->classref = descriptor_pool_lookup_classref(pool, name);
-
- } else {
- /* a primitive type */
- switch (*utf_ptr) {
- case 'B':
- td->primitivetype = PRIMITIVETYPE_BYTE;
- td->type = TYPE_INT;
- break;
- case 'C':
- td->primitivetype = PRIMITIVETYPE_CHAR;
- td->type = TYPE_INT;
- break;
- case 'S':
- td->primitivetype = PRIMITIVETYPE_SHORT;
- td->type = TYPE_INT;
- break;
- case 'Z':
- td->primitivetype = PRIMITIVETYPE_BOOLEAN;
- td->type = TYPE_INT;
- break;
- case 'I':
- td->primitivetype = PRIMITIVETYPE_INT;
- td->type = TYPE_INT;
- break;
- case 'D':
- td->primitivetype = PRIMITIVETYPE_DOUBLE;
- td->type = TYPE_DBL;
- break;
- case 'F':
- td->primitivetype = PRIMITIVETYPE_FLOAT;
- td->type = TYPE_FLT;
- break;
- case 'J':
- td->primitivetype = PRIMITIVETYPE_LONG;
- td->type = TYPE_LNG;
- break;
- case 'V':
- td->primitivetype = PRIMITIVETYPE_VOID;
- td->type = TYPE_VOID;
- break;
- default:
- assert(false);
- }
-
- td->arraydim = 0;
- td->classref = NULL;
- }
-
- return true;
-}
-
-
-/* descriptor_pool_new *********************************************************
-
- Allocate a new descriptor_pool
-
- IN:
- referer..........class for which to create the pool
-
- RETURN VALUE:
- a pointer to the new descriptor_pool
-
-*******************************************************************************/
-
-descriptor_pool *
-descriptor_pool_new(classinfo *referer)
-{
- descriptor_pool *pool;
- u4 hashsize;
- u4 slot;
-
- pool = DNEW(descriptor_pool);
- assert(pool);
-
- pool->referer = referer;
- pool->fieldcount = 0;
- pool->methodcount = 0;
- pool->paramcount = 0;
- pool->descriptorsize = 0;
- pool->descriptors = NULL;
- pool->descriptors_next = NULL;
- pool->classrefs = NULL;
- pool->descriptor_kind = NULL;
- pool->descriptor_kind_next = NULL;
-
- hashsize = CLASSREFHASH_INIT_SIZE;
- pool->classrefhash.size = hashsize;
- pool->classrefhash.entries = 0;
- pool->classrefhash.ptr = DMNEW(void*, hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->classrefhash.ptr[slot] = NULL;
-
- hashsize = DESCRIPTORHASH_INIT_SIZE;
- pool->descriptorhash.size = hashsize;
- pool->descriptorhash.entries = 0;
- pool->descriptorhash.ptr = DMNEW(void*, hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->descriptorhash.ptr[slot] = NULL;
-
- return pool;
-}
-
-
-/* descriptor_pool_add_class ***************************************************
-
- Add the given class reference to the pool
-
- IN:
- pool.............the descriptor_pool
- name.............the class reference to add
-
- RETURN VALUE:
- true.............reference has been added
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool
-descriptor_pool_add_class(descriptor_pool *pool, utf *name)
-{
- u4 key,slot;
- classref_hash_entry *c;
-
- assert(pool);
- assert(name);
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
- utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
-#endif
-
- /* find a place in the hashtable */
-
- key = utf_hashkey(name->text, name->blength);
- slot = key & (pool->classrefhash.size - 1);
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
-
- while (c) {
- if (c->name == name)
- return true; /* already stored */
- c = c->hashlink;
- }
-
- /* check if the name is a valid classname */
-
- if (!is_valid_name(name->text,UTF_END(name))) {
- exceptions_throw_classformaterror(pool->referer, "Invalid class name");
- return false; /* exception */
- }
-
- /* XXX check maximum array dimension */
-
- c = DNEW(classref_hash_entry);
- c->name = name;
- c->index = pool->classrefhash.entries++;
- c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- pool->classrefhash.ptr[slot] = c;
-
- return true;
-}
-
-
-/* descriptor_pool_add *********************************************************
-
- Check the given descriptor and add it to the pool
-
- IN:
- pool.............the descriptor_pool
- desc.............the descriptor to add. Maybe a field or method desc.
-
- OUT:
- *paramslots......if non-NULL, set to the number of parameters.
- LONG and DOUBLE are counted twice
-
- RETURN VALUE:
- true.............descriptor has been added
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool
-descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
-{
- u4 key,slot;
- descriptor_hash_entry *d;
- char *utf_ptr;
- char *end_pos;
- utf *name;
- s4 argcount = 0;
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
- utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
-#endif
-
- assert(pool);
- assert(desc);
-
- /* find a place in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- /* Save all method descriptors in the hashtable, since the parsed */
- /* descriptor may vary between differenf methods (static vs. non-static). */
-
- utf_ptr = desc->text;
-
- if (*utf_ptr != '(') {
- while (d) {
- if (d->desc == desc) {
- if (paramslots)
- *paramslots = d->paramslots;
- return true; /* already stored */
- }
- d = d->hashlink;
- }
- }
-
- /* add the descriptor to the pool */
-
- d = DNEW(descriptor_hash_entry);
- d->desc = desc;
- d->parseddesc.any = NULL;
- d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
- pool->descriptorhash.ptr[slot] = d;
-
- /* now check the descriptor */
-
- end_pos = UTF_END(desc);
-
- if (*utf_ptr == '(') {
- /* a method descriptor */
-
- pool->methodcount++;
- utf_ptr++;
-
- /* check arguments */
-
- while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
- pool->paramcount++;
-
- /* We cannot count the `this' argument here because
- * we don't know if the method is static. */
-
- if (*utf_ptr == 'J' || *utf_ptr == 'D')
- argcount += 2;
- else
- argcount++;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
- DESCRIPTOR_NOVOID, &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool, name))
- return false;
- }
-
- if (utf_ptr == end_pos) {
- exceptions_throw_classformaterror(pool->referer,
- "Missing ')' in method descriptor");
- return false;
- }
-
- utf_ptr++; /* skip ')' */
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
- DESCRIPTOR_CHECKEND, &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool,name))
- return false;
-
- if (argcount > 255) {
- exceptions_throw_classformaterror(pool->referer,
- "Too many arguments in signature");
- return false;
- }
-
- } else {
- /* a field descriptor */
-
- pool->fieldcount++;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
- DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
- &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool,name))
- return false;
- }
-
- d->paramslots = argcount;
-
- if (paramslots)
- *paramslots = argcount;
-
- return true;
-}
-
-
-/* descriptor_pool_create_classrefs ********************************************
-
- Create a table containing all the classrefs which were added to the pool
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *count...........if count is non-NULL, this is set to the number
- of classrefs in the table
-
- RETURN VALUE:
- a pointer to the constant_classref table
-
-*******************************************************************************/
-
-constant_classref *
-descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
-{
- u4 nclasses;
- u4 slot;
- classref_hash_entry *c;
- constant_classref *ref;
-
- assert(pool);
-
- nclasses = pool->classrefhash.entries;
- pool->classrefs = MNEW(constant_classref,nclasses);
-
- /* fill the constant_classref structs */
-
- for (slot = 0; slot < pool->classrefhash.size; ++slot) {
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- while (c) {
- ref = pool->classrefs + c->index;
- CLASSREF_INIT(*ref, pool->referer, c->name);
- c = c->hashlink;
- }
- }
-
- if (count)
- *count = nclasses;
-
- return pool->classrefs;
-}
-
-
-/* descriptor_pool_lookup_classref *********************************************
-
- Return the constant_classref for the given class name
-
- IN:
- pool.............the descriptor_pool
- classname........name of the class to look up
-
- RETURN VALUE:
- a pointer to the constant_classref, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-constant_classref *
-descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
-{
- u4 key,slot;
- classref_hash_entry *c;
-
- assert(pool);
- assert(pool->classrefs);
- assert(classname);
-
- key = utf_hashkey(classname->text, classname->blength);
- slot = key & (pool->classrefhash.size - 1);
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
-
- while (c) {
- if (c->name == classname)
- return pool->classrefs + c->index;
- c = c->hashlink;
- }
-
- exceptions_throw_internalerror("Class reference not found in descriptor pool");
- return NULL;
-}
-
-
-/* descriptor_pool_alloc_parsed_descriptors ************************************
-
- Allocate space for the parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- NOTE:
- This function must be called after all descriptors have been added
- with descriptor_pool_add.
-
-*******************************************************************************/
-
-void
-descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
-{
- u4 size;
-
- assert(pool);
-
- /* TWISTI: paramcount + 1: we don't know if the method is static or */
- /* not, i have no better solution yet. */
-
- size =
- pool->fieldcount * sizeof(typedesc) +
- pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
- pool->paramcount * sizeof(typedesc) +
- pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
-
- pool->descriptorsize = size;
- if (size) {
- pool->descriptors = MNEW(u1, size);
- pool->descriptors_next = pool->descriptors;
- }
-
- size = pool->fieldcount + pool->methodcount;
- if (size) {
- pool->descriptor_kind = DMNEW(u1, size);
- pool->descriptor_kind_next = pool->descriptor_kind;
- }
-}
-
-
-/* descriptor_pool_parse_field_descriptor **************************************
-
- Parse the given field descriptor
-
- IN:
- pool.............the descriptor_pool
- desc.............the field descriptor
-
- RETURN VALUE:
- a pointer to the parsed field descriptor, or
- NULL if an exception has been thrown
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called (once)
- before this function is used.
-
-*******************************************************************************/
-
-typedesc *
-descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
-{
- u4 key,slot;
- descriptor_hash_entry *d;
- typedesc *td;
-
- assert(pool);
- assert(pool->descriptors);
- assert(pool->descriptors_next);
-
- /* lookup the descriptor in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- while (d) {
- if (d->desc == desc) {
- /* found */
- if (d->parseddesc.fd)
- return d->parseddesc.fd;
- break;
- }
- d = d->hashlink;
- }
-
- assert(d);
-
- if (desc->text[0] == '(') {
- exceptions_throw_classformaterror(pool->referer,
- "Method descriptor used in field reference");
- return NULL;
- }
-
- td = (typedesc *) pool->descriptors_next;
- pool->descriptors_next += sizeof(typedesc);
-
- if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
- return NULL;
-
- *(pool->descriptor_kind_next++) = 'f';
-
- d->parseddesc.fd = td;
-
- return td;
-}
-
-
-/* descriptor_pool_parse_method_descriptor *************************************
-
- Parse the given method descriptor
-
- IN:
- pool.............the descriptor_pool
- desc.............the method descriptor
- mflags...........the method flags
- thisclass........classref to the class containing the method.
- This is ignored if mflags contains ACC_STATIC.
- The classref is stored for inserting the 'this' argument.
-
- RETURN VALUE:
- a pointer to the parsed method descriptor, or
- NULL if an exception has been thrown
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called
- (once) before this function is used.
-
-*******************************************************************************/
-
-methoddesc *
-descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
- s4 mflags,constant_classref *thisclass)
-{
- u4 key, slot;
- descriptor_hash_entry *d;
- methoddesc *md;
- typedesc *td;
- char *utf_ptr;
- char *end_pos;
- s2 paramcount = 0;
- s2 paramslots = 0;
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
- (void*)pool,(int)mflags,(void*)thisclass);
- utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
-#endif
-
- assert(pool);
- assert(pool->descriptors);
- assert(pool->descriptors_next);
-
- /* check that it is a method descriptor */
-
- if (desc->text[0] != '(') {
- exceptions_throw_classformaterror(pool->referer,
- "Field descriptor used in method reference");
- return NULL;
- }
-
- /* lookup the descriptor in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- /* find an un-parsed descriptor */
-
- while (d) {
- if (d->desc == desc)
- if (!d->parseddesc.md)
- break;
- d = d->hashlink;
- }
-
- assert(d);
-
- md = (methoddesc *) pool->descriptors_next;
- pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
-
- utf_ptr = desc->text + 1; /* skip '(' */
- end_pos = UTF_END(desc);
-
- td = md->paramtypes;
-
- /* count the `this' pointer */
-
- if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
- td->type = TYPE_ADR;
- td->primitivetype = TYPE_ADR;
- td->arraydim = 0;
- td->classref = thisclass;
-
- td++;
- pool->descriptors_next += sizeof(typedesc);
- paramcount++;
- paramslots++;
- }
-
- while (*utf_ptr != ')') {
- /* parse a parameter type */
-
- if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
- return NULL;
-
- if (IS_2_WORD_TYPE(td->type))
- paramslots++;
-
- td++;
- pool->descriptors_next += sizeof(typedesc);
- paramcount++;
- paramslots++;
- }
- utf_ptr++; /* skip ')' */
-
- /* Skip possible `this' pointer in paramtypes array to allow a possible */
- /* memory move later in parse. */
- /* We store the thisclass reference, so we can later correctly fill in */
- /* the parameter slot of the 'this' argument. */
-
- if (mflags == ACC_UNDEF) {
- td->classref = thisclass;
- td++;
- pool->descriptors_next += sizeof(typedesc);
- }
-
- /* parse return type */
-
- if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
- &(md->returntype)))
- return NULL;
-
- md->paramcount = paramcount;
- md->paramslots = paramslots;
-
- /* If mflags != ACC_UNDEF we parse a real loaded method, so do
- param prealloc. Otherwise we do this in stack analysis. */
-
- if (mflags != ACC_UNDEF) {
- if (md->paramcount > 0) {
- /* allocate memory for params */
-
- md->params = MNEW(paramdesc, md->paramcount);
- }
- else {
- md->params = METHODDESC_NOPARAMS;
- }
-
- /* fill the paramdesc */
- /* md_param_alloc has to be called if md->paramcount == 0,
- too, so it can make the reservation for the Linkage Area,
- Return Register... */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- {
- /* As builtin-functions are native functions, we have
- to pre-allocate for the native ABI. */
-
- if (mflags & ACC_METHOD_BUILTIN)
- md_param_alloc_native(md);
- else
- md_param_alloc(md);
- }
-#endif
- }
- else {
- /* params will be allocated later by
- descriptor_params_from_paramtypes if necessary */
-
- md->params = NULL;
- }
-
- *(pool->descriptor_kind_next++) = 'm';
-
- d->parseddesc.md = md;
-
- return md;
-}
-
-/* descriptor_params_from_paramtypes *******************************************
-
- Create the paramdescs for a method descriptor. This function is called
- when we know whether the method is static or not. This function may only
- be called once for each methoddesc, and only if md->params == NULL.
-
- IN:
- md...............the parsed method descriptor
- md->params MUST be NULL.
- mflags...........the ACC_* access flags of the method. Only the
- ACC_STATIC bit is checked.
- The value ACC_UNDEF is NOT allowed.
-
- RETURN VALUE:
- true.............the paramdescs were created successfully
- false............an exception has been thrown
-
- POSTCONDITION:
- md->parms != NULL
-
-*******************************************************************************/
-
-bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
-{
- typedesc *td;
-
- assert(md);
- assert(md->params == NULL);
- assert(mflags != ACC_UNDEF);
-
- td = md->paramtypes;
-
- /* check for `this' pointer */
-
- if (!(mflags & ACC_STATIC)) {
- constant_classref *thisclass;
-
- /* fetch class reference from reserved param slot */
- thisclass = td[md->paramcount].classref;
- assert(thisclass);
-
- if (md->paramcount > 0) {
- /* shift param types by 1 argument */
- MMOVE(td + 1, td, typedesc, md->paramcount);
- }
-
- /* fill in first argument `this' */
-
- td->type = TYPE_ADR;
- td->primitivetype = TYPE_ADR;
- td->arraydim = 0;
- td->classref = thisclass;
-
- md->paramcount++;
- md->paramslots++;
- }
-
- /* if the method has params, process them */
-
- if (md->paramcount > 0) {
- /* allocate memory for params */
-
- md->params = MNEW(paramdesc, md->paramcount);
-
- } else {
- md->params = METHODDESC_NOPARAMS;
- }
-
- /* fill the paramdesc */
- /* md_param_alloc has to be called if md->paramcount == 0, too, so
- it can make the reservation for the Linkage Area, Return
- Register.. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- {
- /* As builtin-functions are native functions, we have to
- pre-allocate for the native ABI. */
-
- if (mflags & ACC_METHOD_BUILTIN)
- md_param_alloc_native(md);
- else
- md_param_alloc(md);
- }
-#endif
-
- return true;
-}
-
-
-/* descriptor_pool_get_parsed_descriptors **************************************
-
- Return a pointer to the block of parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *size............if size is non-NULL, this is set to the size of the
- parsed descriptor block (in u1)
-
- RETURN VALUE:
- a pointer to the block of parsed descriptors
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called (once)
- before this function is used.
-
-*******************************************************************************/
-
-void *
-descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
-{
- assert(pool);
- assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
-
- if (size)
- *size = pool->descriptorsize;
-
- return pool->descriptors;
-}
-
-
-/* descriptor_pool_get_sizes ***************************************************
-
- Get the sizes of the class reference table and the parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *classrefsize....set to size of the class reference table
- *descsize........set to size of the parsed descriptors
-
- NOTE:
- This function may only be called after both
- descriptor_pool_create_classrefs, and
- descriptor_pool_alloc_parsed_descriptors
- have been called.
-
-*******************************************************************************/
-
-void
-descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
-{
- assert(pool);
- assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
- assert(pool->classrefs);
- assert(classrefsize);
- assert(descsize);
-
- *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
- *descsize = pool->descriptorsize;
-}
-
-
-/****************************************************************************/
-/* DEBUG HELPERS */
-/****************************************************************************/
-
-#ifndef NDEBUG
-/* descriptor_debug_print_typedesc *********************************************
-
- Print the given typedesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parsed descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_typedesc(FILE *file,typedesc *d)
-{
- int ch;
-
- if (!d) {
- fprintf(file,"(typedesc *)NULL");
- return;
- }
-
- if (d->type == TYPE_ADR) {
- if (d->classref)
- utf_fprint_printable_ascii(file,d->classref->name);
- else
- fprintf(file,"<class=NULL>");
- }
- else {
- switch (d->primitivetype) {
- case PRIMITIVETYPE_INT : ch='I'; break;
- case PRIMITIVETYPE_CHAR : ch='C'; break;
- case PRIMITIVETYPE_BYTE : ch='B'; break;
- case PRIMITIVETYPE_SHORT : ch='S'; break;
- case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
- case PRIMITIVETYPE_LONG : ch='J'; break;
- case PRIMITIVETYPE_FLOAT : ch='F'; break;
- case PRIMITIVETYPE_DOUBLE : ch='D'; break;
- case PRIMITIVETYPE_VOID : ch='V'; break;
- default : ch='!';
- }
- fputc(ch,file);
- }
- if (d->arraydim)
- fprintf(file,"[%d]",d->arraydim);
-}
-
-/* descriptor_debug_print_paramdesc ********************************************
-
- Print the given paramdesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parameter descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
-{
- if (!d) {
- fprintf(file,"(paramdesc *)NULL");
- return;
- }
-
- if (d->inmemory) {
- fprintf(file,"<m%d>",d->regoff);
- }
- else {
- fprintf(file,"<r%d>",d->regoff);
- }
-}
-
-/* descriptor_debug_print_methoddesc *******************************************
-
- Print the given methoddesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parsed descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
-{
- int i;
-
- if (!d) {
- fprintf(file,"(methoddesc *)NULL");
- return;
- }
-
- fputc('(',file);
- for (i=0; i<d->paramcount; ++i) {
- if (i)
- fputc(',',file);
- descriptor_debug_print_typedesc(file,d->paramtypes + i);
- if (d->params) {
- descriptor_debug_print_paramdesc(file,d->params + i);
- }
- }
- if (d->params == METHODDESC_NOPARAMS)
- fputs("<NOPARAMS>",file);
- fputc(')',file);
- descriptor_debug_print_typedesc(file,&(d->returntype));
-}
-
-/* descriptor_pool_debug_dump **************************************************
-
- Print the state of the descriptor_pool to the given stream
-
- IN:
- pool.............the descriptor_pool
- file.............stream to print to
-
-*******************************************************************************/
-
-void
-descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
-{
- u4 slot;
- u1 *pos;
- u1 *kind;
- u4 size;
-
- fprintf(file,"======[descriptor_pool for ");
- utf_fprint_printable_ascii(file,pool->referer->name);
- fprintf(file,"]======\n");
-
- fprintf(file,"fieldcount: %d\n",pool->fieldcount);
- fprintf(file,"methodcount: %d\n",pool->methodcount);
- fprintf(file,"paramcount: %d\n",pool->paramcount);
- fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
- fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
- fprintf(file,"classrefsize: %d bytes\n",
- (int)(pool->classrefhash.entries * sizeof(constant_classref)));
-
- fprintf(file,"class references:\n");
- for (slot=0; slot<pool->classrefhash.size; ++slot) {
- classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- while (c) {
- fprintf(file," %4d: ",c->index);
- utf_fprint_printable_ascii(file,c->name);
- fprintf(file,"\n");
- c = c->hashlink;
- }
- }
-
- fprintf(file,"hashed descriptors:\n");
- for (slot=0; slot<pool->descriptorhash.size; ++slot) {
- descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
- while (c) {
- fprintf(file," %p: ",c->parseddesc.any);
- utf_fprint_printable_ascii(file,c->desc);
- fprintf(file,"\n");
- c = c->hashlink;
- }
- }
-
- fprintf(file,"descriptors:\n");
- if (pool->descriptors) {
- pos = pool->descriptors;
- size = pool->descriptors_next - pool->descriptors;
- fprintf(file," size: %d bytes\n",size);
-
- if (pool->descriptor_kind) {
- kind = pool->descriptor_kind;
-
- while (pos < (pool->descriptors + size)) {
- fprintf(file," %p: ",pos);
- switch (*kind++) {
- case 'f':
- descriptor_debug_print_typedesc(file,(typedesc*)pos);
- pos += sizeof(typedesc);
- break;
- case 'm':
- descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
- pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
- pos += sizeof(methoddesc) - sizeof(typedesc);
- break;
- default:
- fprintf(file,"INVALID KIND");
- }
- fputc('\n',file);
- }
- }
- else {
- while (size >= sizeof(void*)) {
- fprintf(file," %p\n",*((void**)pos));
- pos += sizeof(void*);
- size -= sizeof(void*);
- }
- }
- }
-
- fprintf(file,"==========================================================\n");
-}
-#endif /* !defined(NDEBUG) */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
-
--- /dev/null
+/* src/vm/descriptor.c - checking and parsing of field / method descriptors
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "vm/descriptor.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi.h"
+
+
+/* constants (private to descriptor.c) ****************************************/
+
+/* initial number of entries for the classrefhash of a descriptor_pool */
+/* (currently the hash is never grown!) */
+#define CLASSREFHASH_INIT_SIZE 64
+
+/* initial number of entries for the descriptorhash of a descriptor_pool */
+/* (currently the hash is never grown!) */
+#define DESCRIPTORHASH_INIT_SIZE 128
+
+/* data structures (private to descriptor.c) **********************************/
+
+typedef struct classref_hash_entry classref_hash_entry;
+typedef struct descriptor_hash_entry descriptor_hash_entry;
+
+/* entry struct for the classrefhash of descriptor_pool */
+struct classref_hash_entry {
+ classref_hash_entry *hashlink; /* for hash chaining */
+ utf *name; /* name of the class refered to */
+ u2 index; /* index into classref table */
+};
+
+/* entry struct for the descriptorhash of descriptor_pool */
+struct descriptor_hash_entry {
+ descriptor_hash_entry *hashlink;
+ utf *desc;
+ parseddesc_t parseddesc;
+ s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
+};
+
+
+/****************************************************************************/
+/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
+/****************************************************************************/
+
+/* SKIP_FIELDDESCRIPTOR:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * CAUTION: This macro does not check for an unexpected end of the
+ * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
+ */
+#define SKIP_FIELDDESCRIPTOR(utf_ptr) \
+ do { while (*(utf_ptr)=='[') (utf_ptr)++; \
+ if (*(utf_ptr)++=='L') \
+ while(*(utf_ptr)++ != ';') /* skip */; } while(0)
+
+/* SKIP_FIELDDESCRIPTOR_SAFE:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * Input:
+ * utf_ptr....points to first char of descriptor
+ * end_ptr....points to first char after the end of the string
+ * errorflag..must be initialized (to false) by the caller!
+ * Output:
+ * utf_ptr....points to first char after the descriptor
+ * errorflag..set to true if the string ended unexpectedly
+ */
+#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
+ do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
+ if ((utf_ptr) == (end_ptr)) \
+ (errorflag) = true; \
+ else \
+ if (*(utf_ptr)++=='L') { \
+ while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
+ /* skip */; \
+ if ((utf_ptr)[-1] != ';') \
+ (errorflag) = true; }} while(0)
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/****************************************************************************/
+/* DEBUG HELPERS */
+/****************************************************************************/
+
+/*#define DESCRIPTOR_VERBOSE*/
+
+/****************************************************************************/
+/* FUNCTIONS */
+/****************************************************************************/
+
+/* descriptor_to_basic_type ****************************************************
+
+ Return the basic type to use for a value with this descriptor.
+
+ IN:
+ utf..............descriptor utf string
+
+ OUT:
+ A TYPE_* constant.
+
+ PRECONDITIONS:
+ This function assumes that the descriptor has passed
+ descriptor_pool_add checks and that it does not start with '('.
+
+*******************************************************************************/
+
+int descriptor_to_basic_type(utf *descriptor)
+{
+ assert(descriptor->blength >= 1);
+
+ switch (descriptor->text[0]) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ return TYPE_INT;
+
+ case 'J':
+ return TYPE_LNG;
+
+ case 'F':
+ return TYPE_FLT;
+
+ case 'D':
+ return TYPE_DBL;
+
+ case 'L':
+ case '[':
+ return TYPE_ADR;
+
+ default:
+ vm_abort("descriptor_to_basic_type: invalid type %c",
+ descriptor->text[0]);
+ }
+
+ /* keep the compiler happy */
+
+ return 0;
+}
+
+
+/* descriptor_typesize *********************************************************
+
+ Return the size in bytes needed for the given type.
+
+ IN:
+ td..............typedesc describing the type
+
+ OUT:
+ The number of bytes
+
+*******************************************************************************/
+
+int descriptor_typesize(typedesc *td)
+{
+ assert(td);
+
+ switch (td->type) {
+ case TYPE_INT:
+ case TYPE_FLT:
+ return 4;
+
+ case TYPE_LNG:
+ case TYPE_DBL:
+ return 8;
+
+ case TYPE_ADR:
+ return SIZEOF_VOID_P;
+
+ default:
+ vm_abort("descriptor_typesize: invalid type %d", td->type);
+ }
+
+ /* keep the compiler happy */
+
+ return 0;
+}
+
+
+/* name_from_descriptor ********************************************************
+
+ Return the class name indicated by the given descriptor
+ (Internally used helper function)
+
+ IN:
+ c................class containing the descriptor
+ utf_ptr..........first character of descriptor
+ end_ptr..........first character after the end of the string
+ mode.............a combination (binary or) of the following flags:
+
+ (Flags marked with * are the default settings.)
+
+ How to handle "V" descriptors:
+
+ * DESCRIPTOR_VOID.....handle it like other primitive types
+ DESCRIPTOR_NOVOID...treat it as an error
+
+ How to deal with extra characters after the end of the
+ descriptor:
+
+ * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
+ DESCRIPTOR_CHECKEND.....treat them as an error
+
+ OUT:
+ *next............if non-NULL, *next is set to the first character after
+ the descriptor. (Undefined if an error occurs.)
+ *name............set to the utf name of the class
+
+ RETURN VALUE:
+ true.............descriptor parsed successfully
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#define DESCRIPTOR_VOID 0 /* default */
+#define DESCRIPTOR_NOVOID 0x0040
+#define DESCRIPTOR_NOCHECKEND 0 /* default */
+#define DESCRIPTOR_CHECKEND 0x1000
+
+static bool
+name_from_descriptor(classinfo *c,
+ char *utf_ptr, char *end_ptr,
+ char **next, int mode, utf **name)
+{
+ char *start = utf_ptr;
+ bool error = false;
+
+ assert(c);
+ assert(utf_ptr);
+ assert(end_ptr);
+ assert(name);
+
+ *name = NULL;
+ SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
+
+ if (mode & DESCRIPTOR_CHECKEND)
+ error |= (utf_ptr != end_ptr);
+
+ if (!error) {
+ if (next) *next = utf_ptr;
+
+ switch (*start) {
+ case 'V':
+ if (mode & DESCRIPTOR_NOVOID)
+ break;
+ /* FALLTHROUGH! */
+ case 'I':
+ case 'J':
+ case 'F':
+ case 'D':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ return true;
+
+ case 'L':
+ start++;
+ utf_ptr--;
+ /* FALLTHROUGH! */
+ case '[':
+ *name = utf_new(start, utf_ptr - start);
+ return true;
+ }
+ }
+
+ exceptions_throw_classformaterror(c, "Invalid descriptor");
+ return false;
+}
+
+
+/* descriptor_to_typedesc ******************************************************
+
+ Parse the given type descriptor and fill a typedesc struct
+ (Internally used helper function)
+
+ IN:
+ pool.............the descriptor pool
+ utf_ptr..........points to first character of type descriptor
+ end_pos..........points after last character of the whole descriptor
+
+ OUT:
+ *next............set to next character after type descriptor
+ *d...............filled with parsed information
+
+ RETURN VALUE:
+ true.............parsing succeeded
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool
+descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
+ char **next, typedesc *td)
+{
+ utf *name;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
+ return false;
+
+ if (name) {
+ /* a reference type */
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
+ td->arraydim++;
+ td->classref = descriptor_pool_lookup_classref(pool, name);
+
+ } else {
+ /* a primitive type */
+ switch (*utf_ptr) {
+ case 'B':
+ td->primitivetype = PRIMITIVETYPE_BYTE;
+ td->type = TYPE_INT;
+ break;
+ case 'C':
+ td->primitivetype = PRIMITIVETYPE_CHAR;
+ td->type = TYPE_INT;
+ break;
+ case 'S':
+ td->primitivetype = PRIMITIVETYPE_SHORT;
+ td->type = TYPE_INT;
+ break;
+ case 'Z':
+ td->primitivetype = PRIMITIVETYPE_BOOLEAN;
+ td->type = TYPE_INT;
+ break;
+ case 'I':
+ td->primitivetype = PRIMITIVETYPE_INT;
+ td->type = TYPE_INT;
+ break;
+ case 'D':
+ td->primitivetype = PRIMITIVETYPE_DOUBLE;
+ td->type = TYPE_DBL;
+ break;
+ case 'F':
+ td->primitivetype = PRIMITIVETYPE_FLOAT;
+ td->type = TYPE_FLT;
+ break;
+ case 'J':
+ td->primitivetype = PRIMITIVETYPE_LONG;
+ td->type = TYPE_LNG;
+ break;
+ case 'V':
+ td->primitivetype = PRIMITIVETYPE_VOID;
+ td->type = TYPE_VOID;
+ break;
+ default:
+ assert(false);
+ }
+
+ td->arraydim = 0;
+ td->classref = NULL;
+ }
+
+ return true;
+}
+
+
+/* descriptor_pool_new *********************************************************
+
+ Allocate a new descriptor_pool
+
+ IN:
+ referer..........class for which to create the pool
+
+ RETURN VALUE:
+ a pointer to the new descriptor_pool
+
+*******************************************************************************/
+
+descriptor_pool *
+descriptor_pool_new(classinfo *referer)
+{
+ descriptor_pool *pool;
+ u4 hashsize;
+ u4 slot;
+
+ pool = (descriptor_pool*) DumpMemory::allocate(sizeof(descriptor_pool));
+ assert(pool);
+
+ pool->referer = referer;
+ pool->fieldcount = 0;
+ pool->methodcount = 0;
+ pool->paramcount = 0;
+ pool->descriptorsize = 0;
+ pool->descriptors = NULL;
+ pool->descriptors_next = NULL;
+ pool->classrefs = NULL;
+ pool->descriptor_kind = NULL;
+ pool->descriptor_kind_next = NULL;
+
+ hashsize = CLASSREFHASH_INIT_SIZE;
+ pool->classrefhash.size = hashsize;
+ pool->classrefhash.entries = 0;
+ pool->classrefhash.ptr = (void **) DumpMemory::allocate(sizeof(void*) * hashsize);
+ for (slot=0; slot<hashsize; ++slot)
+ pool->classrefhash.ptr[slot] = NULL;
+
+ hashsize = DESCRIPTORHASH_INIT_SIZE;
+ pool->descriptorhash.size = hashsize;
+ pool->descriptorhash.entries = 0;
+ pool->descriptorhash.ptr = (void**) DumpMemory::allocate(sizeof(void*) * hashsize);
+ for (slot=0; slot<hashsize; ++slot)
+ pool->descriptorhash.ptr[slot] = NULL;
+
+ return pool;
+}
+
+
+/* descriptor_pool_add_class ***************************************************
+
+ Add the given class reference to the pool
+
+ IN:
+ pool.............the descriptor_pool
+ name.............the class reference to add
+
+ RETURN VALUE:
+ true.............reference has been added
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+descriptor_pool_add_class(descriptor_pool *pool, utf *name)
+{
+ u4 key,slot;
+ classref_hash_entry *c;
+
+ assert(pool);
+ assert(name);
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
+ utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
+#endif
+
+ /* find a place in the hashtable */
+
+ key = utf_hashkey(name->text, name->blength);
+ slot = key & (pool->classrefhash.size - 1);
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
+ while (c) {
+ if (c->name == name)
+ return true; /* already stored */
+ c = c->hashlink;
+ }
+
+ /* check if the name is a valid classname */
+
+ if (!is_valid_name(name->text,UTF_END(name))) {
+ exceptions_throw_classformaterror(pool->referer, "Invalid class name");
+ return false; /* exception */
+ }
+
+ /* XXX check maximum array dimension */
+
+ c = (classref_hash_entry*) DumpMemory::allocate(sizeof(classref_hash_entry));
+ c->name = name;
+ c->index = pool->classrefhash.entries++;
+ c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ pool->classrefhash.ptr[slot] = c;
+
+ return true;
+}
+
+
+/* descriptor_pool_add *********************************************************
+
+ Check the given descriptor and add it to the pool
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the descriptor to add. Maybe a field or method desc.
+
+ OUT:
+ *paramslots......if non-NULL, set to the number of parameters.
+ LONG and DOUBLE are counted twice
+
+ RETURN VALUE:
+ true.............descriptor has been added
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
+{
+ u4 key,slot;
+ descriptor_hash_entry *d;
+ char *utf_ptr;
+ char *end_pos;
+ utf *name;
+ s4 argcount = 0;
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
+ utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
+#endif
+
+ assert(pool);
+ assert(desc);
+
+ /* find a place in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ /* Save all method descriptors in the hashtable, since the parsed */
+ /* descriptor may vary between differenf methods (static vs. non-static). */
+
+ utf_ptr = desc->text;
+
+ if (*utf_ptr != '(') {
+ while (d) {
+ if (d->desc == desc) {
+ if (paramslots)
+ *paramslots = d->paramslots;
+ return true; /* already stored */
+ }
+ d = d->hashlink;
+ }
+ }
+
+ /* add the descriptor to the pool */
+
+ d = (descriptor_hash_entry*) DumpMemory::allocate(sizeof(descriptor_hash_entry));
+ d->desc = desc;
+ d->parseddesc.any = NULL;
+ d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+ pool->descriptorhash.ptr[slot] = d;
+
+ /* now check the descriptor */
+
+ end_pos = UTF_END(desc);
+
+ if (*utf_ptr == '(') {
+ /* a method descriptor */
+
+ pool->methodcount++;
+ utf_ptr++;
+
+ /* check arguments */
+
+ while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
+ pool->paramcount++;
+
+ /* We cannot count the `this' argument here because
+ * we don't know if the method is static. */
+
+ if (*utf_ptr == 'J' || *utf_ptr == 'D')
+ argcount += 2;
+ else
+ argcount++;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
+ DESCRIPTOR_NOVOID, &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool, name))
+ return false;
+ }
+
+ if (utf_ptr == end_pos) {
+ exceptions_throw_classformaterror(pool->referer,
+ "Missing ')' in method descriptor");
+ return false;
+ }
+
+ utf_ptr++; /* skip ')' */
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+ DESCRIPTOR_CHECKEND, &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
+
+ if (argcount > 255) {
+ exceptions_throw_classformaterror(pool->referer,
+ "Too many arguments in signature");
+ return false;
+ }
+
+ } else {
+ /* a field descriptor */
+
+ pool->fieldcount++;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+ DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
+ &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
+ }
+
+ d->paramslots = argcount;
+
+ if (paramslots)
+ *paramslots = argcount;
+
+ return true;
+}
+
+
+/* descriptor_pool_create_classrefs ********************************************
+
+ Create a table containing all the classrefs which were added to the pool
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *count...........if count is non-NULL, this is set to the number
+ of classrefs in the table
+
+ RETURN VALUE:
+ a pointer to the constant_classref table
+
+*******************************************************************************/
+
+constant_classref *
+descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
+{
+ u4 nclasses;
+ u4 slot;
+ classref_hash_entry *c;
+ constant_classref *ref;
+
+ assert(pool);
+
+ nclasses = pool->classrefhash.entries;
+ pool->classrefs = MNEW(constant_classref,nclasses);
+
+ /* fill the constant_classref structs */
+
+ for (slot = 0; slot < pool->classrefhash.size; ++slot) {
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ while (c) {
+ ref = pool->classrefs + c->index;
+ CLASSREF_INIT(*ref, pool->referer, c->name);
+ c = c->hashlink;
+ }
+ }
+
+ if (count)
+ *count = nclasses;
+
+ return pool->classrefs;
+}
+
+
+/* descriptor_pool_lookup_classref *********************************************
+
+ Return the constant_classref for the given class name
+
+ IN:
+ pool.............the descriptor_pool
+ classname........name of the class to look up
+
+ RETURN VALUE:
+ a pointer to the constant_classref, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+constant_classref *
+descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
+{
+ u4 key,slot;
+ classref_hash_entry *c;
+
+ assert(pool);
+ assert(pool->classrefs);
+ assert(classname);
+
+ key = utf_hashkey(classname->text, classname->blength);
+ slot = key & (pool->classrefhash.size - 1);
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
+ while (c) {
+ if (c->name == classname)
+ return pool->classrefs + c->index;
+ c = c->hashlink;
+ }
+
+ exceptions_throw_internalerror("Class reference not found in descriptor pool");
+ return NULL;
+}
+
+
+/* descriptor_pool_alloc_parsed_descriptors ************************************
+
+ Allocate space for the parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ NOTE:
+ This function must be called after all descriptors have been added
+ with descriptor_pool_add.
+
+*******************************************************************************/
+
+void
+descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
+{
+ u4 size;
+
+ assert(pool);
+
+ /* TWISTI: paramcount + 1: we don't know if the method is static or */
+ /* not, i have no better solution yet. */
+
+ size =
+ pool->fieldcount * sizeof(typedesc) +
+ pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
+ pool->paramcount * sizeof(typedesc) +
+ pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
+
+ pool->descriptorsize = size;
+ if (size) {
+ pool->descriptors = MNEW(u1, size);
+ pool->descriptors_next = pool->descriptors;
+ }
+
+ size = pool->fieldcount + pool->methodcount;
+ if (size) {
+ pool->descriptor_kind = (u1*) DumpMemory::allocate(sizeof(u1) * size);
+ pool->descriptor_kind_next = pool->descriptor_kind;
+ }
+}
+
+
+/* descriptor_pool_parse_field_descriptor **************************************
+
+ Parse the given field descriptor
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the field descriptor
+
+ RETURN VALUE:
+ a pointer to the parsed field descriptor, or
+ NULL if an exception has been thrown
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called (once)
+ before this function is used.
+
+*******************************************************************************/
+
+typedesc *
+descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
+{
+ u4 key,slot;
+ descriptor_hash_entry *d;
+ typedesc *td;
+
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
+
+ /* lookup the descriptor in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ while (d) {
+ if (d->desc == desc) {
+ /* found */
+ if (d->parseddesc.fd)
+ return d->parseddesc.fd;
+ break;
+ }
+ d = d->hashlink;
+ }
+
+ assert(d);
+
+ if (desc->text[0] == '(') {
+ exceptions_throw_classformaterror(pool->referer,
+ "Method descriptor used in field reference");
+ return NULL;
+ }
+
+ td = (typedesc *) pool->descriptors_next;
+ pool->descriptors_next += sizeof(typedesc);
+
+ if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
+ return NULL;
+
+ *(pool->descriptor_kind_next++) = 'f';
+
+ d->parseddesc.fd = td;
+
+ return td;
+}
+
+
+/* descriptor_pool_parse_method_descriptor *************************************
+
+ Parse the given method descriptor
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the method descriptor
+ mflags...........the method flags
+ thisclass........classref to the class containing the method.
+ This is ignored if mflags contains ACC_STATIC.
+ The classref is stored for inserting the 'this' argument.
+
+ RETURN VALUE:
+ a pointer to the parsed method descriptor, or
+ NULL if an exception has been thrown
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called
+ (once) before this function is used.
+
+*******************************************************************************/
+
+methoddesc *
+descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
+ s4 mflags,constant_classref *thisclass)
+{
+ u4 key, slot;
+ descriptor_hash_entry *d;
+ methoddesc *md;
+ typedesc *td;
+ char *utf_ptr;
+ char *end_pos;
+ s2 paramcount = 0;
+ s2 paramslots = 0;
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
+ (void*)pool,(int)mflags,(void*)thisclass);
+ utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
+#endif
+
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
+
+ /* check that it is a method descriptor */
+
+ if (desc->text[0] != '(') {
+ exceptions_throw_classformaterror(pool->referer,
+ "Field descriptor used in method reference");
+ return NULL;
+ }
+
+ /* lookup the descriptor in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ /* find an un-parsed descriptor */
+
+ while (d) {
+ if (d->desc == desc)
+ if (!d->parseddesc.md)
+ break;
+ d = d->hashlink;
+ }
+
+ assert(d);
+
+ md = (methoddesc *) pool->descriptors_next;
+ pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
+
+ utf_ptr = desc->text + 1; /* skip '(' */
+ end_pos = UTF_END(desc);
+
+ td = md->paramtypes;
+
+ /* count the `this' pointer */
+
+ if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ td->classref = thisclass;
+
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ paramcount++;
+ paramslots++;
+ }
+
+ while (*utf_ptr != ')') {
+ /* parse a parameter type */
+
+ if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
+ return NULL;
+
+ if (IS_2_WORD_TYPE(td->type))
+ paramslots++;
+
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ paramcount++;
+ paramslots++;
+ }
+ utf_ptr++; /* skip ')' */
+
+ /* Skip possible `this' pointer in paramtypes array to allow a possible */
+ /* memory move later in parse. */
+ /* We store the thisclass reference, so we can later correctly fill in */
+ /* the parameter slot of the 'this' argument. */
+
+ if (mflags == ACC_UNDEF) {
+ td->classref = thisclass;
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ }
+
+ /* parse return type */
+
+ if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
+ &(md->returntype)))
+ return NULL;
+
+ md->paramcount = paramcount;
+ md->paramslots = paramslots;
+
+ /* If mflags != ACC_UNDEF we parse a real loaded method, so do
+ param prealloc. Otherwise we do this in stack analysis. */
+
+ if (mflags != ACC_UNDEF) {
+ if (md->paramcount > 0) {
+ /* allocate memory for params */
+
+ md->params = MNEW(paramdesc, md->paramcount);
+ }
+ else {
+ md->params = METHODDESC_NOPARAMS;
+ }
+
+ /* fill the paramdesc */
+ /* md_param_alloc has to be called if md->paramcount == 0,
+ too, so it can make the reservation for the Linkage Area,
+ Return Register... */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ {
+ /* As builtin-functions are native functions, we have
+ to pre-allocate for the native ABI. */
+
+ if (mflags & ACC_METHOD_BUILTIN)
+ md_param_alloc_native(md);
+ else
+ md_param_alloc(md);
+ }
+#endif
+ }
+ else {
+ /* params will be allocated later by
+ descriptor_params_from_paramtypes if necessary */
+
+ md->params = NULL;
+ }
+
+ *(pool->descriptor_kind_next++) = 'm';
+
+ d->parseddesc.md = md;
+
+ return md;
+}
+
+/* descriptor_params_from_paramtypes *******************************************
+
+ Create the paramdescs for a method descriptor. This function is called
+ when we know whether the method is static or not. This function may only
+ be called once for each methoddesc, and only if md->params == NULL.
+
+ IN:
+ md...............the parsed method descriptor
+ md->params MUST be NULL.
+ mflags...........the ACC_* access flags of the method. Only the
+ ACC_STATIC bit is checked.
+ The value ACC_UNDEF is NOT allowed.
+
+ RETURN VALUE:
+ true.............the paramdescs were created successfully
+ false............an exception has been thrown
+
+ POSTCONDITION:
+ md->parms != NULL
+
+*******************************************************************************/
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
+{
+ typedesc *td;
+
+ assert(md);
+ assert(md->params == NULL);
+ assert(mflags != ACC_UNDEF);
+
+ td = md->paramtypes;
+
+ /* check for `this' pointer */
+
+ if (!(mflags & ACC_STATIC)) {
+ constant_classref *thisclass;
+
+ /* fetch class reference from reserved param slot */
+ thisclass = td[md->paramcount].classref;
+ assert(thisclass);
+
+ if (md->paramcount > 0) {
+ /* shift param types by 1 argument */
+ MMOVE(td + 1, td, typedesc, md->paramcount);
+ }
+
+ /* fill in first argument `this' */
+
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ td->classref = thisclass;
+
+ md->paramcount++;
+ md->paramslots++;
+ }
+
+ /* if the method has params, process them */
+
+ if (md->paramcount > 0) {
+ /* allocate memory for params */
+
+ md->params = MNEW(paramdesc, md->paramcount);
+
+ } else {
+ md->params = METHODDESC_NOPARAMS;
+ }
+
+ /* fill the paramdesc */
+ /* md_param_alloc has to be called if md->paramcount == 0, too, so
+ it can make the reservation for the Linkage Area, Return
+ Register.. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ {
+ /* As builtin-functions are native functions, we have to
+ pre-allocate for the native ABI. */
+
+ if (mflags & ACC_METHOD_BUILTIN)
+ md_param_alloc_native(md);
+ else
+ md_param_alloc(md);
+ }
+#endif
+
+ return true;
+}
+
+
+/* descriptor_pool_get_parsed_descriptors **************************************
+
+ Return a pointer to the block of parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *size............if size is non-NULL, this is set to the size of the
+ parsed descriptor block (in u1)
+
+ RETURN VALUE:
+ a pointer to the block of parsed descriptors
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called (once)
+ before this function is used.
+
+*******************************************************************************/
+
+void *
+descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
+{
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+
+ if (size)
+ *size = pool->descriptorsize;
+
+ return pool->descriptors;
+}
+
+
+/* descriptor_pool_get_sizes ***************************************************
+
+ Get the sizes of the class reference table and the parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *classrefsize....set to size of the class reference table
+ *descsize........set to size of the parsed descriptors
+
+ NOTE:
+ This function may only be called after both
+ descriptor_pool_create_classrefs, and
+ descriptor_pool_alloc_parsed_descriptors
+ have been called.
+
+*******************************************************************************/
+
+void
+descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
+{
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+ assert(pool->classrefs);
+ assert(classrefsize);
+ assert(descsize);
+
+ *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
+ *descsize = pool->descriptorsize;
+}
+
+
+/****************************************************************************/
+/* DEBUG HELPERS */
+/****************************************************************************/
+
+#ifndef NDEBUG
+/* descriptor_debug_print_typedesc *********************************************
+
+ Print the given typedesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parsed descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_typedesc(FILE *file,typedesc *d)
+{
+ int ch;
+
+ if (!d) {
+ fprintf(file,"(typedesc *)NULL");
+ return;
+ }
+
+ if (d->type == TYPE_ADR) {
+ if (d->classref)
+ utf_fprint_printable_ascii(file,d->classref->name);
+ else
+ fprintf(file,"<class=NULL>");
+ }
+ else {
+ switch (d->primitivetype) {
+ case PRIMITIVETYPE_INT : ch='I'; break;
+ case PRIMITIVETYPE_CHAR : ch='C'; break;
+ case PRIMITIVETYPE_BYTE : ch='B'; break;
+ case PRIMITIVETYPE_SHORT : ch='S'; break;
+ case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
+ case PRIMITIVETYPE_LONG : ch='J'; break;
+ case PRIMITIVETYPE_FLOAT : ch='F'; break;
+ case PRIMITIVETYPE_DOUBLE : ch='D'; break;
+ case PRIMITIVETYPE_VOID : ch='V'; break;
+ default : ch='!';
+ }
+ fputc(ch,file);
+ }
+ if (d->arraydim)
+ fprintf(file,"[%d]",d->arraydim);
+}
+
+/* descriptor_debug_print_paramdesc ********************************************
+
+ Print the given paramdesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parameter descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
+{
+ if (!d) {
+ fprintf(file,"(paramdesc *)NULL");
+ return;
+ }
+
+ if (d->inmemory) {
+ fprintf(file,"<m%d>",d->regoff);
+ }
+ else {
+ fprintf(file,"<r%d>",d->regoff);
+ }
+}
+
+/* descriptor_debug_print_methoddesc *******************************************
+
+ Print the given methoddesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parsed descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
+{
+ int i;
+
+ if (!d) {
+ fprintf(file,"(methoddesc *)NULL");
+ return;
+ }
+
+ fputc('(',file);
+ for (i=0; i<d->paramcount; ++i) {
+ if (i)
+ fputc(',',file);
+ descriptor_debug_print_typedesc(file,d->paramtypes + i);
+ if (d->params) {
+ descriptor_debug_print_paramdesc(file,d->params + i);
+ }
+ }
+ if (d->params == METHODDESC_NOPARAMS)
+ fputs("<NOPARAMS>",file);
+ fputc(')',file);
+ descriptor_debug_print_typedesc(file,&(d->returntype));
+}
+
+/* descriptor_pool_debug_dump **************************************************
+
+ Print the state of the descriptor_pool to the given stream
+
+ IN:
+ pool.............the descriptor_pool
+ file.............stream to print to
+
+*******************************************************************************/
+
+void
+descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
+{
+ u4 slot;
+ u1 *pos;
+ u1 *kind;
+ u4 size;
+
+ fprintf(file,"======[descriptor_pool for ");
+ utf_fprint_printable_ascii(file,pool->referer->name);
+ fprintf(file,"]======\n");
+
+ fprintf(file,"fieldcount: %d\n",pool->fieldcount);
+ fprintf(file,"methodcount: %d\n",pool->methodcount);
+ fprintf(file,"paramcount: %d\n",pool->paramcount);
+ fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
+ fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
+ fprintf(file,"classrefsize: %d bytes\n",
+ (int)(pool->classrefhash.entries * sizeof(constant_classref)));
+
+ fprintf(file,"class references:\n");
+ for (slot=0; slot<pool->classrefhash.size; ++slot) {
+ classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ while (c) {
+ fprintf(file," %4d: ",c->index);
+ utf_fprint_printable_ascii(file,c->name);
+ fprintf(file,"\n");
+ c = c->hashlink;
+ }
+ }
+
+ fprintf(file,"hashed descriptors:\n");
+ for (slot=0; slot<pool->descriptorhash.size; ++slot) {
+ descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+ while (c) {
+ fprintf(file," %p: ",c->parseddesc.any);
+ utf_fprint_printable_ascii(file,c->desc);
+ fprintf(file,"\n");
+ c = c->hashlink;
+ }
+ }
+
+ fprintf(file,"descriptors:\n");
+ if (pool->descriptors) {
+ pos = pool->descriptors;
+ size = pool->descriptors_next - pool->descriptors;
+ fprintf(file," size: %d bytes\n",size);
+
+ if (pool->descriptor_kind) {
+ kind = pool->descriptor_kind;
+
+ while (pos < (pool->descriptors + size)) {
+ fprintf(file," %p: ",pos);
+ switch (*kind++) {
+ case 'f':
+ descriptor_debug_print_typedesc(file,(typedesc*)pos);
+ pos += sizeof(typedesc);
+ break;
+ case 'm':
+ descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
+ pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
+ pos += sizeof(methoddesc) - sizeof(typedesc);
+ break;
+ default:
+ fprintf(file,"INVALID KIND");
+ }
+ fputc('\n',file);
+ }
+ }
+ else {
+ while (size >= sizeof(void*)) {
+ fprintf(file," %p\n",*((void**)pos));
+ pos += sizeof(void*);
+ size -= sizeof(void*);
+ }
+ }
+ }
+
+ fprintf(file,"==========================================================\n");
+}
+#endif /* !defined(NDEBUG) */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
+++ /dev/null
-/* src/vm/descriptor.h - checking and parsing of field / method descriptors
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _DESCRIPTOR_H
-#define _DESCRIPTOR_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct descriptor_pool descriptor_pool;
-typedef struct typedesc typedesc;
-typedef struct paramdesc paramdesc;
-typedef struct methoddesc methoddesc;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/class.hpp"
-#include "vm/global.h"
-#include "vm/method.hpp"
-#include "vm/references.h"
-#include "vm/utf8.h"
-
-#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */
-
-
-/* data structures ************************************************************/
-
-/*----------------------------------------------------------------------------*/
-/* Descriptor Pools */
-/* */
-/* A descriptor_pool is a temporary data structure used during loading of */
-/* a class. The descriptor_pool is used to allocate the table of */
-/* constant_classrefs the class uses, and for parsing the field and method */
-/* descriptors which occurr within the class. The inner workings of */
-/* descriptor_pool are not important for outside code. */
-/* */
-/* You use a descriptor_pool as follows: */
-/* */
-/* 1. create one with descriptor_pool_new */
-/* 2. add all explicit class references with descriptor_pool_add_class */
-/* 3. add all field/method descriptors with descriptor_pool_add */
-/* 4. call descriptor_pool_create_classrefs */
-/* You can now lookup classrefs with descriptor_pool_lookup_classref */
-/* 5. call descriptor_pool_alloc_parsed_descriptors */
-/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */
-/* for each method descriptor call descriptor_pool_parse_method_descriptor */
-/* 7. call descriptor_pool_get_parsed_descriptors */
-/* */
-/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */
-/* memory which can be thrown away when the steps above have been */
-/* done. */
-/*----------------------------------------------------------------------------*/
-
-struct descriptor_pool {
- classinfo *referer;
- u4 fieldcount;
- u4 methodcount;
- u4 paramcount;
- u4 descriptorsize;
- u1 *descriptors;
- u1 *descriptors_next;
- hashtable descriptorhash;
- constant_classref *classrefs;
- hashtable classrefhash;
- u1 *descriptor_kind; /* useful for debugging */
- u1 *descriptor_kind_next; /* useful for debugging */
-};
-
-
-/* data structures for parsed field/method descriptors ************************/
-
-struct typedesc {
- constant_classref *classref; /* class reference for TYPE_ADR types */
- u1 type; /* TYPE_??? constant [1] */
- u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */
- u1 arraydim; /* array dimension (0 if no array) */
-};
-
-/* [1]...the type field contains the basic type used within the VM. So ints, */
-/* shorts, chars, bytes, booleans all have TYPE_INT. */
-/* [2]...the primitivetype field contains the declared type. */
-/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */
-/* For non-primitive types primitivetype is TYPE_ADR. */
-
-struct paramdesc {
-#if defined(__MIPS__)
- u1 type; /* TYPE_??? of the register allocated */
-#endif
- bool inmemory; /* argument in register or on stack */
- uint32_t index; /* index into argument register array */
- uint32_t regoff; /* register index or stack offset */
-};
-
-struct methoddesc {
- s2 paramcount; /* number of parameters */
- s2 paramslots; /* like above but LONG,DOUBLE count twice */
- s4 argintreguse; /* number of used integer argument registers */
- s4 argfltreguse; /* number of used float argument registers */
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- s4 argadrreguse; /* number of used address registers */
-#endif
- s4 memuse; /* number of stack slots used */
- paramdesc *params; /* allocated parameter descriptions [3] */
- typedesc returntype; /* parsed descriptor of the return type */
- typedesc paramtypes[1]; /* parameter types, variable length! */
-};
-
-/* [3]...If params is NULL, the parameter descriptions have not yet been */
-/* allocated. In this case ___the possible 'this' pointer of the method */
-/* is NOT counted in paramcount/paramslots and it is NOT included in */
-/* the paramtypes array___. */
-/* If params != NULL, the parameter descriptions have been */
-/* allocated, and the 'this' pointer of the method, if any, IS included.*/
-/* In case the method has no parameters at all, the special value */
-/* METHODDESC_NO_PARAMS is used (see below). */
-
-/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */
-/* indicating that the method is a static method without any parameters. */
-/* This special value must be != NULL and it may only be set if */
-/* md->paramcount == 0. */
-
-#define METHODDESC_NOPARAMS ((paramdesc*)1)
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-descriptor_pool * descriptor_pool_new(classinfo *referer);
-
-bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
-bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots);
-
-int descriptor_to_basic_type(utf *desc);
-int descriptor_typesize(typedesc *td);
-
-constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool,
- s4 *count);
-constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname);
-
-void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool);
-
-typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc);
-methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags,
- constant_classref *thisclass);
-
-bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags);
-
-void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size);
-void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize,
- u4 *descsize);
-
-#ifndef NDEBUG
-void descriptor_debug_print_typedesc(FILE *file,typedesc *d);
-void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
-void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
-void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
-#endif /* !defined(NDEBUG) */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DESCRIPTOR_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/vm/descriptor.h - checking and parsing of field / method descriptors
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _DESCRIPTOR_H
+#define _DESCRIPTOR_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct descriptor_pool descriptor_pool;
+typedef struct typedesc typedesc;
+typedef struct paramdesc paramdesc;
+typedef struct methoddesc methoddesc;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.hpp"
+#include "vm/global.h"
+#include "vm/method.hpp"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */
+
+
+/* data structures ************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Descriptor Pools */
+/* */
+/* A descriptor_pool is a temporary data structure used during loading of */
+/* a class. The descriptor_pool is used to allocate the table of */
+/* constant_classrefs the class uses, and for parsing the field and method */
+/* descriptors which occurr within the class. The inner workings of */
+/* descriptor_pool are not important for outside code. */
+/* */
+/* You use a descriptor_pool as follows: */
+/* */
+/* 1. create one with descriptor_pool_new */
+/* 2. add all explicit class references with descriptor_pool_add_class */
+/* 3. add all field/method descriptors with descriptor_pool_add */
+/* 4. call descriptor_pool_create_classrefs */
+/* You can now lookup classrefs with descriptor_pool_lookup_classref */
+/* 5. call descriptor_pool_alloc_parsed_descriptors */
+/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */
+/* for each method descriptor call descriptor_pool_parse_method_descriptor */
+/* 7. call descriptor_pool_get_parsed_descriptors */
+/* */
+/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */
+/* memory which can be thrown away when the steps above have been */
+/* done. */
+/*----------------------------------------------------------------------------*/
+
+struct descriptor_pool {
+ classinfo *referer;
+ u4 fieldcount;
+ u4 methodcount;
+ u4 paramcount;
+ u4 descriptorsize;
+ u1 *descriptors;
+ u1 *descriptors_next;
+ hashtable descriptorhash;
+ constant_classref *classrefs;
+ hashtable classrefhash;
+ u1 *descriptor_kind; /* useful for debugging */
+ u1 *descriptor_kind_next; /* useful for debugging */
+};
+
+
+/* data structures for parsed field/method descriptors ************************/
+
+struct typedesc {
+ constant_classref *classref; /* class reference for TYPE_ADR types */
+ u1 type; /* TYPE_??? constant [1] */
+ u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */
+ u1 arraydim; /* array dimension (0 if no array) */
+};
+
+/* [1]...the type field contains the basic type used within the VM. So ints, */
+/* shorts, chars, bytes, booleans all have TYPE_INT. */
+/* [2]...the primitivetype field contains the declared type. */
+/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */
+/* For non-primitive types primitivetype is TYPE_ADR. */
+
+struct paramdesc {
+#if defined(__MIPS__)
+ u1 type; /* TYPE_??? of the register allocated */
+#endif
+ bool inmemory; /* argument in register or on stack */
+ uint32_t index; /* index into argument register array */
+ uint32_t regoff; /* register index or stack offset */
+};
+
+struct methoddesc {
+ s2 paramcount; /* number of parameters */
+ s2 paramslots; /* like above but LONG,DOUBLE count twice */
+ s4 argintreguse; /* number of used integer argument registers */
+ s4 argfltreguse; /* number of used float argument registers */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ s4 argadrreguse; /* number of used address registers */
+#endif
+ s4 memuse; /* number of stack slots used */
+ paramdesc *params; /* allocated parameter descriptions [3] */
+ typedesc returntype; /* parsed descriptor of the return type */
+ typedesc paramtypes[1]; /* parameter types, variable length! */
+};
+
+/* [3]...If params is NULL, the parameter descriptions have not yet been */
+/* allocated. In this case ___the possible 'this' pointer of the method */
+/* is NOT counted in paramcount/paramslots and it is NOT included in */
+/* the paramtypes array___. */
+/* If params != NULL, the parameter descriptions have been */
+/* allocated, and the 'this' pointer of the method, if any, IS included.*/
+/* In case the method has no parameters at all, the special value */
+/* METHODDESC_NO_PARAMS is used (see below). */
+
+/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */
+/* indicating that the method is a static method without any parameters. */
+/* This special value must be != NULL and it may only be set if */
+/* md->paramcount == 0. */
+
+#define METHODDESC_NOPARAMS ((paramdesc*)1)
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+descriptor_pool * descriptor_pool_new(classinfo *referer);
+
+bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
+bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots);
+
+int descriptor_to_basic_type(utf *desc);
+int descriptor_typesize(typedesc *td);
+
+constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool,
+ s4 *count);
+constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname);
+
+void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool);
+
+typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc);
+methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags,
+ constant_classref *thisclass);
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags);
+
+void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size);
+void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize,
+ u4 *descsize);
+
+#ifndef NDEBUG
+void descriptor_debug_print_typedesc(FILE *file,typedesc *d);
+void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
+void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
+void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
+#endif /* !defined(NDEBUG) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DESCRIPTOR_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "vm/array.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/class.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/exceptions.hpp"
#include "vm/field.hpp"
#include "vm/global.h"
#include "config.h"
#include "vm/types.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/class.hpp"
#include "vm/global.h"
#include "vm/loader.hpp"
+++ /dev/null
-/* src/vm/finalizer.c - finalizer linked list and thread
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/condition.hpp"
-#include "threads/mutex.hpp"
-#include "threads/thread.hpp"
-
-#include "vm/jit/builtin.hpp"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/options.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/asmpart.h"
-
-
-/* global variables ***********************************************************/
-
-#if defined(ENABLE_THREADS)
-static Mutex *finalizer_thread_mutex;
-static Condition *finalizer_thread_cond;
-#endif
-
-
-/* finalizer_init **************************************************************
-
- Initializes the finalizer global lock and the linked list.
-
-*******************************************************************************/
-
-bool finalizer_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("finalizer_init");
-
-#if defined(ENABLE_THREADS)
- finalizer_thread_mutex = Mutex_new();
- finalizer_thread_cond = Condition_new();
-#endif
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* finalizer_thread ************************************************************
-
- This thread waits on an object for a notification and the runs the
- finalizers (finalizer thread). This is necessary because of a
- possible deadlock in the GC.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-static void finalizer_thread(void)
-{
- while (true) {
- /* get the lock on the finalizer mutex, so we can call wait */
-
- Mutex_lock(finalizer_thread_mutex);
-
- /* wait forever on that condition till we are signaled */
-
- Condition_wait(finalizer_thread_cond, finalizer_thread_mutex);
-
- /* leave the lock */
-
- Mutex_unlock(finalizer_thread_mutex);
-
-#if !defined(NDEBUG)
- if (opt_DebugFinalizer)
- log_println("[finalizer thread : status=awake]");
-#endif
-
- /* and call the finalizers */
-
- gc_invoke_finalizers();
-
-#if !defined(NDEBUG)
- if (opt_DebugFinalizer)
- log_println("[finalizer thread : status=sleeping]");
-#endif
- }
-}
-#endif
-
-
-/* finalizer_start_thread ******************************************************
-
- Starts the finalizer thread.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-bool finalizer_start_thread(void)
-{
- utf *name;
-
- name = utf_new_char("Finalizer");
-
- if (!threads_thread_start_internal(name, finalizer_thread))
- return false;
-
- /* everything's ok */
-
- return true;
-}
-#endif
-
-
-/* finalizer_notify ************************************************************
-
- Notifies the finalizer thread that it should run the
- gc_invoke_finalizers from the GC.
-
-*******************************************************************************/
-
-void finalizer_notify(void)
-{
-#if !defined(NDEBUG)
- if (opt_DebugFinalizer)
- log_println("[finalizer notified]");
-#endif
-
-#if defined(ENABLE_THREADS)
- /* get the lock on the finalizer lock object, so we can call wait */
-
- Mutex_lock(finalizer_thread_mutex);
-
- /* signal the finalizer thread */
-
- Condition_signal(finalizer_thread_cond);
-
- /* leave the lock */
-
- Mutex_unlock(finalizer_thread_mutex);
-#else
- /* if we don't have threads, just run the finalizers */
-
- gc_invoke_finalizers();
-#endif
-}
-
-
-/* finalizer_run ***************************************************************
-
- Actually run the finalizer functions.
-
-*******************************************************************************/
-
-void finalizer_run(void *o, void *p)
-{
- java_handle_t *h;
- classinfo *c;
-
- h = (java_handle_t *) o;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
- /* XXX this is only a dirty hack to make Boehm work with handles */
-
- h = LLNI_WRAP((java_object_t *) h);
-#endif
-
- LLNI_class_get(h, c);
-
-#if !defined(NDEBUG)
- if (opt_DebugFinalizer) {
- log_start();
- log_print("[finalizer running : o=%p p=%p class=", o, p);
- class_print(c);
- log_print("]");
- log_finish();
- }
-#endif
-
- /* call the finalizer function */
-
- (void) vm_call_method(c->finalizer, h);
-
-#if !defined(NDEBUG)
- if (opt_DebugFinalizer && (exceptions_get_exception() != NULL)) {
- log_println("[finalizer exception]");
- exceptions_print_stacktrace();
- }
-#endif
-
- /* if we had an exception in the finalizer, ignore it */
-
- exceptions_clear_exception();
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
--- /dev/null
+/* src/vm/finalizer.c - finalizer linked list and thread
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+
+
+/* global variables ***********************************************************/
+
+#if defined(ENABLE_THREADS)
+static Mutex *finalizer_thread_mutex;
+static Condition *finalizer_thread_cond;
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* finalizer_init **************************************************************
+
+ Initializes the finalizer global lock and the linked list.
+
+*******************************************************************************/
+
+bool finalizer_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("finalizer_init");
+
+#if defined(ENABLE_THREADS)
+ finalizer_thread_mutex = new Mutex();
+ finalizer_thread_cond = new Condition();
+#endif
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* finalizer_thread ************************************************************
+
+ This thread waits on an object for a notification and the runs the
+ finalizers (finalizer thread). This is necessary because of a
+ possible deadlock in the GC.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+static void finalizer_thread(void)
+{
+ while (true) {
+ /* get the lock on the finalizer mutex, so we can call wait */
+
+ finalizer_thread_mutex->lock();
+
+ /* wait forever on that condition till we are signaled */
+
+ finalizer_thread_cond->wait(finalizer_thread_mutex);
+
+ /* leave the lock */
+
+ finalizer_thread_mutex->unlock();
+
+#if !defined(NDEBUG)
+ if (opt_DebugFinalizer)
+ log_println("[finalizer thread : status=awake]");
+#endif
+
+ /* and call the finalizers */
+
+ gc_invoke_finalizers();
+
+#if !defined(NDEBUG)
+ if (opt_DebugFinalizer)
+ log_println("[finalizer thread : status=sleeping]");
+#endif
+ }
+}
+#endif
+
+
+/* finalizer_start_thread ******************************************************
+
+ Starts the finalizer thread.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+bool finalizer_start_thread(void)
+{
+ utf *name;
+
+ name = utf_new_char("Finalizer");
+
+ if (!threads_thread_start_internal(name, finalizer_thread))
+ return false;
+
+ /* everything's ok */
+
+ return true;
+}
+#endif
+
+
+/* finalizer_notify ************************************************************
+
+ Notifies the finalizer thread that it should run the
+ gc_invoke_finalizers from the GC.
+
+*******************************************************************************/
+
+void finalizer_notify(void)
+{
+#if !defined(NDEBUG)
+ if (opt_DebugFinalizer)
+ log_println("[finalizer notified]");
+#endif
+
+#if defined(ENABLE_THREADS)
+ /* get the lock on the finalizer lock object, so we can call wait */
+
+ finalizer_thread_mutex->lock();
+
+ /* signal the finalizer thread */
+
+ finalizer_thread_cond->signal();
+
+ /* leave the lock */
+
+ finalizer_thread_mutex->unlock();
+#else
+ /* if we don't have threads, just run the finalizers */
+
+ gc_invoke_finalizers();
+#endif
+}
+
+
+/* finalizer_run ***************************************************************
+
+ Actually run the finalizer functions.
+
+*******************************************************************************/
+
+void finalizer_run(void *o, void *p)
+{
+ java_handle_t *h;
+ classinfo *c;
+
+ h = (java_handle_t *) o;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+ /* XXX this is only a dirty hack to make Boehm work with handles */
+
+ h = LLNI_WRAP((java_object_t *) h);
+#endif
+
+ LLNI_class_get(h, c);
+
+#if !defined(NDEBUG)
+ if (opt_DebugFinalizer) {
+ log_start();
+ log_print("[finalizer running : o=%p p=%p class=", o, p);
+ class_print(c);
+ log_print("]");
+ log_finish();
+ }
+#endif
+
+ /* call the finalizer function */
+
+ (void) vm_call_method(c->finalizer, h);
+
+#if !defined(NDEBUG)
+ if (opt_DebugFinalizer && (exceptions_get_exception() != NULL)) {
+ log_println("[finalizer exception]");
+ exceptions_print_stacktrace();
+ }
+#endif
+
+ /* if we had an exception in the finalizer, ignore it */
+
+ exceptions_clear_exception();
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+++ /dev/null
-/* src/vm/finalizer.h - finalizer linked list and thread header
-
- Copyright (C) 1996-2005, 2006, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _FINALIZER_H
-#define _FINALIZER_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-bool finalizer_init(void);
-bool finalizer_start_thread(void);
-void finalizer_notify(void);
-void finalizer_run(void *o, void *p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FINALIZER_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
--- /dev/null
+/* src/vm/finalizer.h - finalizer linked list and thread header
+
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _FINALIZER_H
+#define _FINALIZER_H
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
+/* function prototypes ********************************************************/
+
+bool finalizer_init(void);
+bool finalizer_start_thread(void);
+void finalizer_notify(void);
+void finalizer_run(void *o, void *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FINALIZER_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
#include "vm/jit/alpha/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "native/llni.h"
#include "vm/array.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/method.hpp"
#include "vm/primitive.hpp"
#include "vm/jit/arm/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "toolbox/logging.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/utf8.h"
#include "toolbox/list.hpp"
#include "vm/jit/builtin.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/method.hpp"
#include "vm/references.h"
#include "md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/os.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/i386/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include <stdint.h>
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/jit/ir/instruction.hpp"
#include <stdint.h>
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/jit/jit.hpp"
#include "vm/jit/replace.hpp"
#include "mm/memory.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/method.hpp"
#include "toolbox/bitvector.h"
#include "vm/class.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/references.h"
#include "vm/resolve.hpp"
#include "vm/jit/powerpc/darwin/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/powerpc/linux/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/powerpc/netbsd/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/powerpc64/linux/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "config.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/types.h"
#include "vm/jit/sparc64/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/array.hpp"
#include "vm/class.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
#include "vm/loader.hpp"
#include "vm/jit/x86_64/md-abi.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/types.h"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/class.hpp"
#include "vm/global.h"
#include "vm/method.hpp"
#include "threads/mutex.hpp"
#include "vm/jit/builtin.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/global.h"
#include "vm/linker.hpp"
#include "vm/loader.hpp"
#include "vm/types.h"
#include "vm/class.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/method.hpp"
#include "vm/access.hpp"
#include "vm/classcache.hpp"
-#include "vm/descriptor.h"
+#include "vm/descriptor.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/classcache.hpp"
#include "vm/exceptions.hpp"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/initialize.hpp"
#include "vm/types.h"
-#include "vm/descriptor.h" /* needed to prevent circular dependency */
+#include "vm/descriptor.hpp" /* needed to prevent circular dependency */
#include "toolbox/hashtable.h"
#include "mm/memory.h"