/* 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, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
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.
-
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Edwin Steiner
-
- Changes: Christian Thalinger
- Christian Ullrich
-
- $Id: descriptor.c 3825 2005-12-01 18:46:29Z edwin $
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
*/
+#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/resolve.h"
-#include "vm/stringlocal.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) ****************************************/
/* (currently the hash is never grown!) */
#define DESCRIPTORHASH_INIT_SIZE 128
-/* data structures (private to descriptor.c) **********************************/
+/* data structures (private to descriptor.c) **********************************/
typedef struct classref_hash_entry classref_hash_entry;
typedef struct descriptor_hash_entry descriptor_hash_entry;
struct descriptor_hash_entry {
descriptor_hash_entry *hashlink;
utf *desc;
- parseddesc parseddesc;
+ parseddesc_t parseddesc;
s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
};
*******************************************************************************/
-u2 descriptor_to_basic_type(utf *descriptor)
+int descriptor_to_basic_type(utf *descriptor)
{
- char *utf_ptr = descriptor->text;
-
assert(descriptor->blength >= 1);
- switch (*utf_ptr++) {
- case 'B':
+ switch (descriptor->text[0]) {
+ case 'Z':
+ case 'B':
case 'C':
+ case 'S':
case 'I':
- case 'S':
- case 'Z': return TYPE_INT;
- case 'D': return TYPE_DOUBLE;
- case 'F': return TYPE_FLOAT;
- case 'J': return TYPE_LONG;
+ return TYPE_INT;
+
+ case 'J':
+ return TYPE_LNG;
+
+ case 'F':
+ return TYPE_FLT;
+
+ case 'D':
+ return TYPE_DBL;
+
case 'L':
- case '[': return TYPE_ADDRESS;
+ case '[':
+ return TYPE_ADR;
+
+ default:
+ vm_abort("descriptor_to_basic_type: invalid type %c",
+ descriptor->text[0]);
}
-
- assert(0);
- return 0; /* keep the compiler happy */
+ /* keep the compiler happy */
+
+ return 0;
}
-/* descriptor_typesize**** ****************************************************
+
+/* descriptor_typesize *********************************************************
Return the size in bytes needed for the given type.
*******************************************************************************/
-u2 descriptor_typesize(typedesc *td)
+int 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);
+ 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);
}
- assert(0);
+ /* keep the compiler happy */
- return 0; /* keep the compiler happy */
+ return 0;
}
+
/* name_from_descriptor ********************************************************
Return the class name indicated by the given descriptor
}
}
- *exceptionptr = new_classformaterror(c,"invalid descriptor");
+ exceptions_throw_classformaterror(c, "Invalid descriptor");
return false;
}
if (name) {
/* a reference type */
- td->type = TYPE_ADDRESS;
- td->decltype = TYPE_ADDRESS;
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
td->arraydim = 0;
for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
td->arraydim++;
/* a primitive type */
switch (*utf_ptr) {
case 'B':
- td->decltype = PRIMITIVETYPE_BYTE;
+ td->primitivetype = PRIMITIVETYPE_BYTE;
td->type = TYPE_INT;
break;
case 'C':
- td->decltype = PRIMITIVETYPE_CHAR;
+ td->primitivetype = PRIMITIVETYPE_CHAR;
td->type = TYPE_INT;
break;
case 'S':
- td->decltype = PRIMITIVETYPE_SHORT;
+ td->primitivetype = PRIMITIVETYPE_SHORT;
td->type = TYPE_INT;
break;
case 'Z':
- td->decltype = PRIMITIVETYPE_BOOLEAN;
+ td->primitivetype = PRIMITIVETYPE_BOOLEAN;
td->type = TYPE_INT;
break;
case 'I':
- td->decltype = PRIMITIVETYPE_INT;
+ td->primitivetype = PRIMITIVETYPE_INT;
td->type = TYPE_INT;
break;
case 'D':
- td->decltype = PRIMITIVETYPE_DOUBLE;
- td->type = TYPE_DOUBLE;
+ td->primitivetype = PRIMITIVETYPE_DOUBLE;
+ td->type = TYPE_DBL;
break;
case 'F':
- td->decltype = PRIMITIVETYPE_FLOAT;
- td->type = TYPE_FLOAT;
+ td->primitivetype = PRIMITIVETYPE_FLOAT;
+ td->type = TYPE_FLT;
break;
case 'J':
- td->decltype = PRIMITIVETYPE_LONG;
- td->type = TYPE_LONG;
+ td->primitivetype = PRIMITIVETYPE_LONG;
+ td->type = TYPE_LNG;
break;
case 'V':
- td->decltype = PRIMITIVETYPE_VOID;
+ td->primitivetype = PRIMITIVETYPE_VOID;
td->type = TYPE_VOID;
break;
default:
hashsize = CLASSREFHASH_INIT_SIZE;
pool->classrefhash.size = hashsize;
pool->classrefhash.entries = 0;
- pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
+ 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(voidptr,hashsize);
+ pool->descriptorhash.ptr = DMNEW(void*, hashsize);
for (slot=0; slot<hashsize; ++slot)
pool->descriptorhash.ptr[slot] = NULL;
#ifdef DESCRIPTOR_VERBOSE
fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
- utf_fprint(stderr,name);fprintf(stderr,")\n");
+ utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
#endif
/* find a place in the hashtable */
/* check if the name is a valid classname */
if (!is_valid_name(name->text,UTF_END(name))) {
- *exceptionptr = new_classformaterror(pool->referer,
- "Invalid class name");
+ exceptions_throw_classformaterror(pool->referer, "Invalid class name");
return false; /* exception */
}
#ifdef DESCRIPTOR_VERBOSE
fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
- utf_fprint(stderr,desc);fprintf(stderr,")\n");
+ utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
#endif
assert(pool);
}
if (utf_ptr == end_pos) {
- *exceptionptr = new_classformaterror(pool->referer,"Missing ')' in method descriptor");
+ exceptions_throw_classformaterror(pool->referer,
+ "Missing ')' in method descriptor");
return false;
}
return false;
if (argcount > 255) {
- *exceptionptr =
- new_classformaterror(pool->referer,"Too many arguments in signature");
+ exceptions_throw_classformaterror(pool->referer,
+ "Too many arguments in signature");
return false;
}
c = c->hashlink;
}
- *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
+ exceptions_throw_internalerror("Class reference not found in descriptor pool");
return NULL;
}
assert(d);
if (desc->text[0] == '(') {
- *exceptionptr = new_classformaterror(pool->referer,
- "Method descriptor used in field reference");
+ exceptions_throw_classformaterror(pool->referer,
+ "Method descriptor used in field reference");
return NULL;
}
#ifdef DESCRIPTOR_VERBOSE
fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
(void*)pool,(int)mflags,(void*)thisclass);
- utf_fprint(stderr,desc); fprintf(stderr,")\n");
+ utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
#endif
assert(pool);
/* check that it is a method descriptor */
if (desc->text[0] != '(') {
- *exceptionptr = new_classformaterror(pool->referer,
- "Field descriptor used in method reference");
+ exceptions_throw_classformaterror(pool->referer,
+ "Field descriptor used in method reference");
return NULL;
}
if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
td->type = TYPE_ADR;
- td->decltype = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
td->arraydim = 0;
td->classref = thisclass;
if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
return NULL;
- if (td->type == TYPE_LONG || td->type == TYPE_DOUBLE)
+ if (IS_2_WORD_TYPE(td->type))
paramslots++;
td++;
md->paramcount = paramcount;
md->paramslots = paramslots;
- /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
- /* Otherwise we do this in stack analysis. */
+ /* 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) {
}
/* 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
+ {
+ /* 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 */
+ /* params will be allocated later by
+ descriptor_params_from_paramtypes if necessary */
+
md->params = NULL;
}
/* fill in first argument `this' */
td->type = TYPE_ADR;
- td->decltype = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
td->arraydim = 0;
td->classref = thisclass;
/* 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
+ {
+ /* 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;
}
return;
}
- if (d->type == TYPE_ADDRESS) {
+ if (d->type == TYPE_ADR) {
if (d->classref)
- utf_fprint(file,d->classref->name);
+ utf_fprint_printable_ascii(file,d->classref->name);
else
fprintf(file,"<class=NULL>");
}
else {
- switch (d->decltype) {
+ switch (d->primitivetype) {
case PRIMITIVETYPE_INT : ch='I'; break;
case PRIMITIVETYPE_CHAR : ch='C'; break;
case PRIMITIVETYPE_BYTE : ch='B'; break;
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;
}
}
}
else {
- while (size >= sizeof(voidptr)) {
- fprintf(file," %p\n",*((voidptr*)pos));
- pos += sizeof(voidptr);
- size -= sizeof(voidptr);
+ while (size >= sizeof(void*)) {
+ fprintf(file," %p\n",*((void**)pos));
+ pos += sizeof(void*);
+ size -= sizeof(void*);
}
}
}