/* src/vm/descriptor.c - checking and parsing of field / method descriptors
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Edwin Steiner
Changes: Christian Thalinger
Christian Ullrich
- $Id: descriptor.c 2833 2005-06-26 21:47:29Z christian $
+ $Id: descriptor.c 4879 2006-05-05 17:34:49Z edwin $
*/
+#include "config.h"
+
#include <assert.h>
-#include "types.h"
+#include "vm/types.h"
+
#include "md-abi.h"
#include "mm/memory.h"
#include "vm/descriptor.h"
#include "vm/exceptions.h"
+#include "vm/options.h"
#include "vm/resolve.h"
#include "vm/stringlocal.h"
/* DEBUG HELPERS */
/****************************************************************************/
-#ifndef NDEBUG
-#define DESCRIPTOR_DEBUG
-#endif
+/*#define DESCRIPTOR_VERBOSE*/
-#ifdef DESCRIPTOR_DEBUG
-#define DESCRIPTOR_ASSERT(cond) assert(cond)
-#else
-#define DESCRIPTOR_ASSERT(cond)
-#endif
+/****************************************************************************/
+/* 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 '('.
+
+*******************************************************************************/
+
+u2 descriptor_to_basic_type(utf *descriptor)
+{
+ assert(descriptor->blength >= 1);
+
+ switch (descriptor->text[0]) {
+ case 'B':
+ case 'C':
+ case 'I':
+ case 'S':
+ case 'Z': return TYPE_INT;
+ case 'D': return TYPE_DOUBLE;
+ case 'F': return TYPE_FLOAT;
+ case 'J': return TYPE_LONG;
+ case 'L':
+ case '[': return TYPE_ADDRESS;
+ }
+
+ assert(0);
+
+ return 0; /* keep the compiler happy */
+}
+
+/* descriptor_typesize**** ****************************************************
+
+ Return the size in bytes needed for the given type.
+
+ IN:
+ td..............typedesc describing the type
+
+ OUT:
+ The number of bytes
+
+*******************************************************************************/
+
+u2 descriptor_typesize(typedesc *td)
+{
+ assert(td);
+
+ switch (td->type) {
+ case TYPE_INT: return 4;
+ case TYPE_LONG: return 8;
+ case TYPE_FLOAT: return 4;
+ case TYPE_DOUBLE: return 8;
+ case TYPE_ADDRESS: return sizeof(voidptr);
+ }
+
+ assert(0);
+
+ return 0; /* keep the compiler happy */
+}
/* name_from_descriptor ********************************************************
char *start = utf_ptr;
bool error = false;
- DESCRIPTOR_ASSERT(c);
- DESCRIPTOR_ASSERT(utf_ptr);
- DESCRIPTOR_ASSERT(end_ptr);
- DESCRIPTOR_ASSERT(name);
+ assert(c);
+ assert(utf_ptr);
+ assert(end_ptr);
+ assert(name);
*name = NULL;
SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
td->type = TYPE_VOID;
break;
default:
- DESCRIPTOR_ASSERT(false);
+ assert(false);
}
td->arraydim = 0;
u4 slot;
pool = DNEW(descriptor_pool);
- DESCRIPTOR_ASSERT(pool);
+ assert(pool);
pool->referer = referer;
pool->fieldcount = 0;
u4 key,slot;
classref_hash_entry *c;
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT(name);
+ 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 */
utf *name;
s4 argcount = 0;
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT(desc);
+#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 */
return false;
if (name)
- descriptor_pool_add_class(pool, name);
+ if (!descriptor_pool_add_class(pool, name))
+ return false;
}
if (utf_ptr == end_pos) {
return false;
if (name)
- descriptor_pool_add_class(pool,name);
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
if (argcount > 255) {
*exceptionptr =
} else {
/* a field descriptor */
+
pool->fieldcount++;
if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
return false;
if (name)
- descriptor_pool_add_class(pool,name);
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
}
d->paramslots = argcount;
classref_hash_entry *c;
constant_classref *ref;
- DESCRIPTOR_ASSERT(pool);
+ assert(pool);
nclasses = pool->classrefhash.entries;
pool->classrefs = MNEW(constant_classref,nclasses);
u4 key,slot;
classref_hash_entry *c;
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT(pool->classrefs);
- DESCRIPTOR_ASSERT(classname);
+ assert(pool);
+ assert(pool->classrefs);
+ assert(classname);
key = utf_hashkey(classname->text, classname->blength);
slot = key & (pool->classrefhash.size - 1);
c = c->hashlink;
}
- *exceptionptr =
- new_exception_message(string_java_lang_InternalError,
- "Class reference not found in descriptor pool");
+ *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
return NULL;
}
{
u4 size;
- DESCRIPTOR_ASSERT(pool);
+ assert(pool);
/* TWISTI: paramcount + 1: we don't know if the method is static or */
/* not, i have no better solution yet. */
descriptor_hash_entry *d;
typedesc *td;
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT(pool->descriptors);
- DESCRIPTOR_ASSERT(pool->descriptors_next);
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
/* lookup the descriptor in the hashtable */
d = d->hashlink;
}
- DESCRIPTOR_ASSERT(d);
+ assert(d);
if (desc->text[0] == '(') {
*exceptionptr = new_classformaterror(pool->referer,
s2 paramcount = 0;
s2 paramslots = 0;
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT(pool->descriptors);
- DESCRIPTOR_ASSERT(pool->descriptors_next);
+#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] != '(') {
+ *exceptionptr = new_classformaterror(pool->referer,
+ "Field descriptor used in method reference");
+ return NULL;
+ }
/* lookup the descriptor in the hashtable */
d = d->hashlink;
}
- DESCRIPTOR_ASSERT(d);
+ assert(d);
md = (methoddesc *) pool->descriptors_next;
pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
- utf_ptr = desc->text;
+ utf_ptr = desc->text + 1; /* skip '(' */
end_pos = UTF_END(desc);
- if (*utf_ptr++ != '(') {
- *exceptionptr = new_classformaterror(pool->referer,
- "Field descriptor used in method reference");
- return NULL;
- }
-
td = md->paramtypes;
/* count the `this' pointer */
}
/* 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... */
- md_param_alloc(md);
- }
- else {
- /* params will be allocated later by descriptor_params_from_paramtypes */
- /* if necessary */
+ /* 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
+ md_param_alloc(md);
+#endif
+
+ } else {
+ /* params will be allocated later by
+ descriptor_params_from_paramtypes if necessary */
+
md->params = NULL;
}
{
typedesc *td;
- DESCRIPTOR_ASSERT(md);
- DESCRIPTOR_ASSERT(md->params == NULL);
- DESCRIPTOR_ASSERT(mflags != ACC_UNDEF);
+ assert(md);
+ assert(md->params == NULL);
+ assert(mflags != ACC_UNDEF);
td = md->paramtypes;
/* fetch class reference from reserved param slot */
thisclass = td[md->paramcount].classref;
- DESCRIPTOR_ASSERT(thisclass);
+ assert(thisclass);
if (md->paramcount > 0) {
/* shift param types by 1 argument */
/* allocate memory for params */
md->params = MNEW(paramdesc, md->paramcount);
- }
- else {
+
+ } 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.. */
-
- md_param_alloc(md);
+ /* 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
+ md_param_alloc(md);
+#endif
return true;
}
void *
descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
{
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
if (size)
*size = pool->descriptorsize;
void
descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
{
- DESCRIPTOR_ASSERT(pool);
- DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
- DESCRIPTOR_ASSERT(pool->classrefs);
- DESCRIPTOR_ASSERT(classrefsize);
- DESCRIPTOR_ASSERT(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
if (d->type == TYPE_ADDRESS) {
if (d->classref)
- utf_fprint(file,d->classref->name);
+ utf_fprint_printable_ascii(file,d->classref->name);
else
fprintf(file,"<class=NULL>");
}
u4 size;
fprintf(file,"======[descriptor_pool for ");
- utf_fprint(file,pool->referer->name);
+ utf_fprint_printable_ascii(file,pool->referer->name);
fprintf(file,"]======\n");
fprintf(file,"fieldcount: %d\n",pool->fieldcount);
classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
while (c) {
fprintf(file," %4d: ",c->index);
- utf_fprint(file,c->name);
+ utf_fprint_printable_ascii(file,c->name);
fprintf(file,"\n");
c = c->hashlink;
}
descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
while (c) {
fprintf(file," %p: ",c->parseddesc.any);
- utf_fprint(file,c->desc);
+ utf_fprint_printable_ascii(file,c->desc);
fprintf(file,"\n");
c = c->hashlink;
}
fprintf(file,"==========================================================\n");
}
+#endif /* !defined(NDEBUG) */
/*
* These are local overrides for various environment variables in Emacs.