/* src/vm/class.c - class related functions
- 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: Reinhard Grafl
Changes: Mark Probst
Andreas Krall
Christian Thalinger
+ Edwin Steiner
- $Id: class.c 4335 2006-01-22 14:39:28Z twisti $
+ $Id: class.c 6033 2006-11-21 16:56:56Z michi $
*/
#include "config.h"
#include <assert.h>
+#include <stdio.h>
#include <string.h>
#include "vm/types.h"
#include "mm/memory.h"
-#if defined(USE_THREADS)
-# if defined(NATIVE_THREADS)
-# include "threads/native/threads.h"
-# else
-# include "threads/green/threads.h"
-# include "threads/green/locks.h"
-# endif
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
#endif
#include "toolbox/logging.h"
#include "vm/utf8.h"
-/******************************************************************************/
-/* DEBUG HELPERS */
-/******************************************************************************/
-
-#ifndef NDEBUG
-#define CLASS_DEBUG
-#endif
-
-#ifdef CLASS_DEBUG
-#define CLASS_ASSERT(cond) assert(cond)
-#else
-#define CLASS_ASSERT(cond)
-#endif
-
-
/* global variables ***********************************************************/
list unlinkedclasses; /* this is only used for eager class */
/* important system classes */
-classinfo *class_java_lang_Object = NULL;
-classinfo *class_java_lang_Class = NULL;
-classinfo *class_java_lang_ClassLoader = NULL;
-classinfo *class_java_lang_Cloneable = NULL;
-classinfo *class_java_lang_SecurityManager = NULL;
-classinfo *class_java_lang_String = NULL;
-classinfo *class_java_lang_System = NULL;
-classinfo *class_java_lang_Thread = NULL;
-classinfo *class_java_lang_ThreadGroup = NULL;
-classinfo *class_java_lang_VMThread = NULL;
-classinfo *class_java_io_Serializable = NULL;
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_Class;
+classinfo *class_java_lang_ClassLoader;
+classinfo *class_java_lang_Cloneable;
+classinfo *class_java_lang_SecurityManager;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_System;
+classinfo *class_java_lang_Thread;
+classinfo *class_java_lang_ThreadGroup;
+classinfo *class_java_lang_VMSystem;
+classinfo *class_java_lang_VMThread;
+classinfo *class_java_io_Serializable;
/* system exception classes required in cacao */
-classinfo *class_java_lang_Throwable = NULL;
-classinfo *class_java_lang_VMThrowable = NULL;
-classinfo *class_java_lang_Error = NULL;
-classinfo *class_java_lang_NoClassDefFoundError = NULL;
-classinfo *class_java_lang_LinkageError = NULL;
-classinfo *class_java_lang_NoSuchMethodError = NULL;
-classinfo *class_java_lang_OutOfMemoryError = NULL;
-
-classinfo *class_java_lang_Exception = NULL;
-classinfo *class_java_lang_ClassNotFoundException = NULL;
-classinfo *class_java_lang_IllegalArgumentException = NULL;
-classinfo *class_java_lang_IllegalMonitorStateException = NULL;
-
-classinfo *class_java_lang_Void = NULL;
-classinfo *class_java_lang_Boolean = NULL;
-classinfo *class_java_lang_Byte = NULL;
-classinfo *class_java_lang_Character = NULL;
-classinfo *class_java_lang_Short = NULL;
-classinfo *class_java_lang_Integer = NULL;
-classinfo *class_java_lang_Long = NULL;
-classinfo *class_java_lang_Float = NULL;
-classinfo *class_java_lang_Double = NULL;
+classinfo *class_java_lang_Throwable;
+classinfo *class_java_lang_VMThrowable;
+classinfo *class_java_lang_Error;
+classinfo *class_java_lang_AbstractMethodError;
+classinfo *class_java_lang_LinkageError;
+classinfo *class_java_lang_NoClassDefFoundError;
+classinfo *class_java_lang_NoSuchMethodError;
+classinfo *class_java_lang_OutOfMemoryError;
+
+classinfo *class_java_lang_Exception;
+classinfo *class_java_lang_ClassCastException;
+classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_IllegalArgumentException;
+classinfo *class_java_lang_IllegalMonitorStateException;
+
+classinfo *class_java_lang_Void;
+classinfo *class_java_lang_Boolean;
+classinfo *class_java_lang_Byte;
+classinfo *class_java_lang_Character;
+classinfo *class_java_lang_Short;
+classinfo *class_java_lang_Integer;
+classinfo *class_java_lang_Long;
+classinfo *class_java_lang_Float;
+classinfo *class_java_lang_Double;
/* some runtime exception */
-classinfo *class_java_lang_NullPointerException = NULL;
+classinfo *class_java_lang_NullPointerException;
/* some classes which may be used more often */
-classinfo *class_java_lang_StackTraceElement = NULL;
-classinfo *class_java_lang_reflect_Constructor = NULL;
-classinfo *class_java_lang_reflect_Field = NULL;
-classinfo *class_java_lang_reflect_Method = NULL;
-classinfo *class_java_security_PrivilegedAction = NULL;
-classinfo *class_java_util_Vector = NULL;
+classinfo *class_java_lang_StackTraceElement;
+classinfo *class_java_lang_reflect_Constructor;
+classinfo *class_java_lang_reflect_Field;
+classinfo *class_java_lang_reflect_Method;
+classinfo *class_java_security_PrivilegedAction;
+classinfo *class_java_util_Vector;
-classinfo *arrayclass_java_lang_Object = NULL;
+classinfo *arrayclass_java_lang_Object;
/* pseudo classes for the typechecker */
-classinfo *pseudo_class_Arraystub = NULL;
-classinfo *pseudo_class_Null = NULL;
-classinfo *pseudo_class_New = NULL;
+classinfo *pseudo_class_Arraystub;
+classinfo *pseudo_class_Null;
+classinfo *pseudo_class_New;
/* class_set_packagename *******************************************************
#if defined(ENABLE_STATISTICS)
if (opt_stat)
- count_class_infos += sizeof(classinfo);
+ size_classinfo += sizeof(classinfo);
#endif
/* we use a safe name for temporarily unnamed classes */
if (classname != utf_not_named_yet)
class_set_packagename(c);
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- initObjectLock(&c->object.header);
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(&c->object.header);
#endif
return c;
if (c->fields) {
for (i = 0; i < c->fieldscount; i++)
field_free(&(c->fields[i]));
-/* MFREE(c->fields, fieldinfo, c->fieldscount); */
+#if defined(ENABLE_CACAO_GC)
+ MFREE(c->fields, fieldinfo, c->fieldscount);
+#endif
}
if (c->methods) {
return NULL;
}
- CLASS_ASSERT(c);
- CLASS_ASSERT(c->state & CLASS_LOADED);
- CLASS_ASSERT(c->classloader == defloader);
+ assert(c);
+ assert(c->state & CLASS_LOADED);
+ assert(c->classloader == defloader);
if (link && !(c->state & CLASS_LINKED))
if (!link_class(c))
return NULL;
- CLASS_ASSERT(!link || (c->state & CLASS_LINKED));
+ assert(!link || (c->state & CLASS_LINKED));
return c;
}
{
s4 namelen;
char *namebuf;
+ s4 dumpsize;
+ classinfo *c;
+
+ dumpsize = dump_size();
/* Assemble the array class name */
namelen = component->name->blength;
namelen += 3;
}
- return get_array_class(utf_new(namebuf, namelen),
- component->classloader,
- component->classloader,
- link);
+ c = get_array_class(utf_new(namebuf, namelen),
+ component->classloader,
+ component->classloader,
+ link);
+
+ dump_release(dumpsize);
+
+ return c;
}
{
s4 namelen;
char *namebuf;
+ s4 dumpsize;
+ classinfo *c;
+
+ dumpsize = dump_size();
if (dim < 1) {
log_text("Invalid array dimension requested");
}
memset(namebuf, '[', dim);
- return get_array_class(utf_new(namebuf, namelen),
- element->classloader,
- element->classloader,
- link);
+ c = get_array_class(utf_new(namebuf, namelen),
+ element->classloader,
+ element->classloader,
+ link);
+
+ dump_release(dumpsize);
+
+ return c;
}
extra_classref *xref;
int count;
- CLASS_ASSERT(cls);
- CLASS_ASSERT(name);
- CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
+ assert(cls);
+ assert(name);
+ assert(!cls->classrefcount || cls->classrefs);
/* first search the main classref table */
count = cls->classrefcount;
constant_classref *ref;
extra_classref *xref;
- CLASS_ASSERT(cls);
- CLASS_ASSERT(name);
+ assert(cls);
+ assert(name);
ref = class_lookup_classref(cls,name);
if (ref)
{
s4 namelen;
char *namebuf;
+ s4 dumpsize;
+ constant_classref *cr;
+
+ assert(ref);
+ assert(dim >= 1 && dim <= 255);
- CLASS_ASSERT(ref);
- CLASS_ASSERT(dim >= 1 && dim <= 255);
+ dumpsize = dump_size();
/* Assemble the array class name */
namelen = ref->name->blength;
}
memset(namebuf, '[', dim);
- return class_get_classref(ref->referer,utf_new(namebuf, namelen));
+ cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
+
+ dump_release(dumpsize);
+
+ return cr;
}
s4 namelen;
char *name;
- CLASS_ASSERT(ref);
+ assert(ref);
name = ref->name->text;
if (*name++ != '[')
}
-/************************* Function: class_findmethod_approx ******************
-
- like class_findmethod but ignores the return value when comparing the
- descriptor.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
-{
- s4 i;
-
- for (i = 0; i < c->methodscount; i++) {
- if (c->methods[i].name == name) {
- utf *meth_descr = c->methods[i].descriptor;
-
- if (desc == NULL)
- /* ignore type */
- return &(c->methods[i]);
-
- if (desc->blength <= meth_descr->blength) {
- /* current position in utf text */
- char *desc_utf_ptr = desc->text;
- char *meth_utf_ptr = meth_descr->text;
- /* points behind utf strings */
- char *desc_end = UTF_END(desc);
- char *meth_end = UTF_END(meth_descr);
- char ch;
-
- /* compare argument types */
- while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
-
- if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
- break; /* no match */
-
- if (ch == ')')
- return &(c->methods[i]); /* all parameter types equal */
- }
- }
- }
- }
-
- return NULL;
-}
-
-
/* class_resolvemethod *********************************************************
Searches a class and it's super classes for a method.
{
methodinfo *m;
s4 i;
-
+
+ /* try to find the method in the class */
+
m = class_findmethod(c, name, desc);
- if (m)
+ if (m != NULL)
return m;
- /* try the superinterfaces */
+ /* no method found? try the superinterfaces */
for (i = 0; i < c->interfacescount; i++) {
m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
- name, desc);
+ name, desc);
- if (m)
+ if (m != NULL)
return m;
}
-
+
+ /* no method found */
+
return NULL;
}
methodinfo *m;
s4 i;
- /* XXX resolve class c */
- /* XXX check access from REFERER to C */
-
/* if (c->flags & ACC_INTERFACE) { */
/* if (throwexception) */
/* *exceptionptr = */
m = class_resolvemethod(cls, name, desc);
- if (m)
+ if (m != NULL)
goto found;
/* try the superinterfaces */
for (i = 0; i < c->interfacescount; i++) {
m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
- name, desc);
+ name, desc);
- if (m)
+ if (m != NULL)
goto found;
}
if (throwexception)
- *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
+ exceptions_throw_nosuchmethoderror(c, name, desc);
return NULL;
found:
if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
if (throwexception)
- *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
+ exceptions_throw_abstractmethoderror();
return NULL;
}
{
methodinfo *mi;
- /* XXX resolve class c */
- /* XXX check access from REFERER to C */
-
if (!(c->flags & ACC_INTERFACE)) {
if (throwexception)
*exceptionptr =
{
fieldinfo *fi;
- /* XXX resolve class c */
- /* XXX check access from REFERER to C */
-
fi = class_resolvefield_int(c, name, desc);
if (!fi) {
#if !defined(NDEBUG)
void class_printflags(classinfo *c)
{
+ if (c == NULL) {
+ printf("NULL");
+ return;
+ }
+
if (c->flags & ACC_PUBLIC) printf(" PUBLIC");
if (c->flags & ACC_PRIVATE) printf(" PRIVATE");
if (c->flags & ACC_PROTECTED) printf(" PROTECTED");
#if !defined(NDEBUG)
void class_print(classinfo *c)
{
- utf_display(c->name);
+ if (c == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii(c->name);
class_printflags(c);
}
#endif
+/* class_classref_print ********************************************************
+
+ Prints classname plus referer class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_print(constant_classref *cr)
+{
+ if (cr == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii(cr->name);
+ printf("(ref.by ");
+ if (cr->referer)
+ class_print(cr->referer);
+ else
+ printf("NULL");
+ printf(")");
+}
+#endif
+
+
/* class_println ***************************************************************
Prints classname plus flags and new line.
#endif
+/* class_classref_println ******************************************************
+
+ Prints classname plus referer class and new line.
+
+*******************************************************************************/
+
#if !defined(NDEBUG)
-void class_showconstanti(classinfo *c, int ii)
+void class_classref_println(constant_classref *cr)
{
- u4 i = ii;
- voidptr e;
-
- e = c->cpinfos [i];
- printf ("#%d: ", (int) i);
- if (e) {
- switch (c->cptags [i]) {
- case CONSTANT_Class:
- printf("Classreference -> ");
- utf_display(((constant_classref*)e)->name);
- break;
-
- case CONSTANT_Fieldref:
- printf("Fieldref -> "); goto displayFMIi;
- case CONSTANT_Methodref:
- printf("Methodref -> "); goto displayFMIi;
- case CONSTANT_InterfaceMethodref:
- printf("InterfaceMethod -> "); goto displayFMIi;
- displayFMIi:
- {
- constant_FMIref *fmi = e;
- utf_display(fmi->classref->name);
- printf(".");
- utf_display(fmi->name);
- printf(" ");
- utf_display(fmi->descriptor);
- }
- break;
-
- case CONSTANT_String:
- printf("String -> ");
- utf_display(e);
- break;
- case CONSTANT_Integer:
- printf("Integer -> %d", (int) (((constant_integer*)e)->value));
- break;
- case CONSTANT_Float:
- printf("Float -> %f", ((constant_float*)e)->value);
- break;
- case CONSTANT_Double:
- printf("Double -> %f", ((constant_double*)e)->value);
- break;
- case CONSTANT_Long:
- {
- u8 v = ((constant_long*)e)->value;
-#if U8_AVAILABLE
- printf("Long -> %ld", (long int) v);
-#else
- printf("Long -> HI: %ld, LO: %ld\n",
- (long int) v.high, (long int) v.low);
-#endif
- }
- break;
- case CONSTANT_NameAndType:
- {
- constant_nameandtype *cnt = e;
- printf("NameAndType: ");
- utf_display(cnt->name);
- printf(" ");
- utf_display(cnt->descriptor);
- }
- break;
- case CONSTANT_Utf8:
- printf("Utf8 -> ");
- utf_display(e);
- break;
- default:
- log_text("Invalid type of ConstantPool-Entry");
- assert(0);
- }
+ class_classref_print(cr);
+ printf("\n");
+}
+#endif
+
+
+/* class_classref_or_classinfo_print *******************************************
+
+ Prints classname plus referer class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_or_classinfo_print(classref_or_classinfo c)
+{
+ if (c.any == NULL) {
+ printf("(classref_or_classinfo) NULL");
+ return;
}
+ if (IS_CLASSREF(c))
+ class_classref_print(c.ref);
+ else
+ class_print(c.cls);
+}
+#endif
+
+
+/* class_classref_or_classinfo_println *****************************************
+
+ Prints classname plus referer class and a newline.
+
+*******************************************************************************/
+
+void class_classref_or_classinfo_println(classref_or_classinfo c)
+{
+ class_classref_or_classinfo_println(c);
printf("\n");
}
+/* class_showconstantpool ******************************************************
+
+ Dump the constant pool of the given class to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
void class_showconstantpool (classinfo *c)
{
u4 i;
switch (c -> cptags [i]) {
case CONSTANT_Class:
printf ("Classreference -> ");
- utf_display ( ((constant_classref*)e) -> name );
+ utf_display_printable_ascii ( ((constant_classref*)e) -> name );
break;
-
case CONSTANT_Fieldref:
- printf ("Fieldref -> "); goto displayFMI;
+ printf ("Fieldref -> ");
+ field_fieldref_print((constant_FMIref *) e);
+ break;
case CONSTANT_Methodref:
- printf ("Methodref -> "); goto displayFMI;
+ printf ("Methodref -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
case CONSTANT_InterfaceMethodref:
- printf ("InterfaceMethod -> "); goto displayFMI;
- displayFMI:
- {
- constant_FMIref *fmi = e;
- utf_display ( fmi->classref->name );
- printf (".");
- utf_display ( fmi->name);
- printf (" ");
- utf_display ( fmi->descriptor );
- }
+ printf ("InterfaceMethod -> ");
+ method_methodref_print((constant_FMIref *) e);
break;
-
case CONSTANT_String:
printf ("String -> ");
- utf_display (e);
+ utf_display_printable_ascii (e);
break;
case CONSTANT_Integer:
printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
{
constant_nameandtype *cnt = e;
printf ("NameAndType: ");
- utf_display (cnt->name);
+ utf_display_printable_ascii (cnt->name);
printf (" ");
- utf_display (cnt->descriptor);
+ utf_display_printable_ascii (cnt->descriptor);
}
break;
case CONSTANT_Utf8:
printf ("Utf8 -> ");
- utf_display (e);
+ utf_display_printable_ascii (e);
break;
default:
log_text("Invalid type of ConstantPool-Entry");
printf ("\n");
}
}
+#endif /* !defined(NDEBUG) */
+/* class_showmethods ***********************************************************
-/********** Function: class_showmethods (debugging only) *************/
+ Dump info about the fields and methods of the given class to stdout.
+*******************************************************************************/
+
+#if !defined(NDEBUG)
void class_showmethods (classinfo *c)
{
s4 i;
printf("\n");
printf("This: ");
- utf_display(c->name);
+ utf_display_printable_ascii(c->name);
printf("\n");
if (c->super.cls) {
printf("Super: ");
- utf_display(c->super.cls->name);
+ utf_display_printable_ascii(c->super.cls->name);
printf ("\n");
}
printf("Interfaces:\n");
for (i = 0; i < c->interfacescount; i++) {
printf(" ");
- utf_display(c->interfaces[i].cls->name);
+ utf_display_printable_ascii(c->interfaces[i].cls->name);
printf (" (%d)\n", c->interfaces[i].cls->index);
}
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/