/* 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 3374 2005-10-06 13:11:37Z 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 "config.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/resolve.h"
#include "vm/statistics.h"
#include "vm/stringlocal.h"
-#include "vm/tables.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_OutOfMemoryError = 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 = NULL;
-classinfo *class_java_lang_ClassNotFoundException = NULL;
+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 = 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_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;
/* 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 *******************************************************
{
classinfo *c;
-#if defined(STATISTICS)
+#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)
classname = utf_not_named_yet;
+#if !defined(NDEBUG)
if (initverbose)
log_message_utf("Creating class: ", classname);
+#endif
+
+ /* GCNEW_UNCOLLECTABLE clears the allocated memory */
- c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
+ c = GCNEW_UNCOLLECTABLE(classinfo, 1);
/*c=NEW(classinfo);*/
- c->vmClass = 0;
- c->flags = 0;
c->name = classname;
- c->packagename = NULL;
- c->cpcount = 0;
- c->cptags = NULL;
- c->cpinfos = NULL;
- c->classrefs = NULL;
- c->extclassrefs = NULL;
- c->classrefcount = 0;
- c->parseddescs = NULL;
- c->parseddescsize = 0;
- c->super.any = NULL;
- c->sub = NULL;
- c->nextsub = NULL;
- c->interfacescount = 0;
- c->interfaces = NULL;
- c->fieldscount = 0;
- c->fields = NULL;
- c->methodscount = 0;
- c->methods = NULL;
- c->linked = false;
- c->loaded = false;
- c->index = 0;
- c->instancesize = 0;
- c->header.vftbl = NULL;
- c->innerclasscount = 0;
- c->innerclass = NULL;
- c->vftbl = NULL;
- c->initialized = false;
- c->initializing = false;
- c->classvftbl = false;
- c->classUsed = 0;
- c->impldBy = NULL;
- c->classloader = NULL;
- c->sourcefile = NULL;
+
+ /* set the header.vftbl of all loaded classes to the one of
+ java.lang.Class, so Java code can use a class as object */
+
+ if (class_java_lang_Class)
+ if (class_java_lang_Class->vftbl)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
- if (classname != utf_not_named_yet) {
+ if (classname != utf_not_named_yet)
class_set_packagename(c);
- }
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- initObjectLock(&c->header);
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(&c->object.header);
#endif
return c;
}
+
+/* class_postset_header_vftbl **************************************************
+
+ Set the header.vftbl of all classes created before java.lang.Class
+ was linked. This is necessary that Java code can use a class as
+ object.
+
+*******************************************************************************/
+
+void class_postset_header_vftbl(void)
+{
+ classinfo *c;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+
+ assert(class_java_lang_Class);
+
+ for (slot = 0; slot < hashtable_classcache.size; slot++) {
+ nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+ for (; nmen; nmen = nmen->hashlink) {
+ /* iterate over all class entries */
+
+ for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+ c = clsen->classobj;
+
+ /* now set the the vftbl */
+
+ if (c->object.header.vftbl == NULL)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+ }
+ }
+ }
+}
+
+
/* class_freepool **************************************************************
Frees all resources used by this classes Constant Pool.
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->loaded);
- CLASS_ASSERT(c->classloader == defloader);
+ assert(c);
+ assert(c->state & CLASS_LOADED);
+ assert(c->classloader == defloader);
- if (link && !c->linked)
+ if (link && !(c->state & CLASS_LINKED))
if (!link_class(c))
return NULL;
- CLASS_ASSERT(!link || c->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;
- CLASS_ASSERT(ref);
- CLASS_ASSERT(dim >= 1 && dim <= 255);
+ assert(ref);
+ 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;
}
+
/* class_get_classref_component_of *********************************************
Returns the component classref of a given array type reference
s4 namelen;
char *name;
- CLASS_ASSERT(ref);
+ assert(ref);
name = ref->name->text;
if (*name++ != '[')
}
+/* class_findmethod ************************************************************
+
+ Searches a 'classinfo' structure for a method having the given name
+ and descriptor. If descriptor is NULL, it is ignored.
+
+*******************************************************************************/
+
+methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+{
+ methodinfo *m;
+ s4 i;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
+ return m;
+ }
+
+ return NULL;
+}
+
+
+/* class_resolvemethod *********************************************************
+
+ Searches a class and it's super classes for a method.
+
+ Superinterfaces are *not* searched.
+
+*******************************************************************************/
+
+methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+{
+ methodinfo *m;
+
+ while (c) {
+ m = class_findmethod(c, name, desc);
+
+ if (m)
+ return m;
+
+ /* JVM Specification bug:
+
+ It is important NOT to resolve special <init> and <clinit>
+ methods to super classes or interfaces; yet, this is not
+ explicited in the specification. Section 5.4.3.3 should be
+ updated appropriately. */
+
+ if (name == utf_init || name == utf_clinit)
+ return NULL;
+
+ c = c->super.cls;
+ }
+
+ return NULL;
+}
+
+
+/* class_resolveinterfacemethod_intern *****************************************
+
+ Internally used helper function. Do not use this directly.
+
+*******************************************************************************/
+
+static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
+ utf *name, utf *desc)
+{
+ methodinfo *m;
+ s4 i;
+
+ /* try to find the method in the class */
+
+ m = class_findmethod(c, name, desc);
+
+ if (m != NULL)
+ return m;
+
+ /* no method found? try the superinterfaces */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
+ name, desc);
+
+ if (m != NULL)
+ return m;
+ }
+
+ /* no method found */
+
+ return NULL;
+}
+
+
+/* class_resolveclassmethod ****************************************************
+
+ Resolves a reference from REFERER to a method with NAME and DESC in
+ class C.
+
+ If the method cannot be resolved the return value is NULL. If
+ EXCEPT is true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+{
+ classinfo *cls;
+ methodinfo *m;
+ s4 i;
+
+/* if (c->flags & ACC_INTERFACE) { */
+/* if (throwexception) */
+/* *exceptionptr = */
+/* new_exception(string_java_lang_IncompatibleClassChangeError); */
+/* return NULL; */
+/* } */
+
+ /* try class c and its superclasses */
+
+ cls = c;
+
+ m = class_resolvemethod(cls, name, desc);
+
+ 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);
+
+ if (m != NULL)
+ goto found;
+ }
+
+ if (throwexception)
+ exceptions_throw_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+
+ found:
+ if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+ if (throwexception)
+ exceptions_throw_abstractmethoderror();
+
+ return NULL;
+ }
+
+ /* XXX check access rights */
+
+ return m;
+}
+
+
+/* class_resolveinterfacemethod ************************************************
+
+ Resolves a reference from REFERER to a method with NAME and DESC in
+ interface C.
+
+ If the method cannot be resolved the return value is NULL. If
+ EXCEPT is true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+{
+ methodinfo *mi;
+
+ if (!(c->flags & ACC_INTERFACE)) {
+ if (throwexception)
+ *exceptionptr =
+ new_exception(string_java_lang_IncompatibleClassChangeError);
+
+ return NULL;
+ }
+
+ mi = class_resolveinterfacemethod_intern(c, name, desc);
+
+ if (mi)
+ return mi;
+
+ /* try class java.lang.Object */
+
+ mi = class_findmethod(class_java_lang_Object, name, desc);
+
+ if (mi)
+ return mi;
+
+ if (throwexception)
+ *exceptionptr =
+ exceptions_new_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+}
+
+
/* class_findfield *************************************************************
Searches for field with specified name and type in a classinfo
{
s4 i;
- for (i = 0; i < c->fieldscount; i++) {
- /* compare field names */
- if ((c->fields[i].name == name))
- return &(c->fields[i]);
- }
+ /* get field index */
- /* field was not found, raise exception */
- *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
+ i = class_findfield_index_by_name(c, name);
- return NULL;
+ /* field was not found, return */
+
+ if (i == -1)
+ return NULL;
+
+ /* return field address */
+
+ return &(c->fields[i]);
}
for (i = 0; i < c->fieldscount; i++) {
/* compare field names */
+
if ((c->fields[i].name == name))
return i;
}
/* field was not found, raise exception */
+
*exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
return -1;
}
+/****************** Function: class_resolvefield_int ***************************
+
+ This is an internally used helper function. Do not use this directly.
+
+ Tries to resolve a field having the given name and type.
+ If the field cannot be resolved, NULL is returned.
+
+*******************************************************************************/
+
+static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
+{
+ fieldinfo *fi;
+ s4 i;
+
+ /* search for field in class c */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+ return &(c->fields[i]);
+ }
+ }
+
+ /* try superinterfaces recursively */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
+ if (fi)
+ return fi;
+ }
+
+ /* try superclass */
+
+ if (c->super.cls)
+ return class_resolvefield_int(c->super.cls, name, desc);
+
+ /* not found */
+
+ return NULL;
+}
+
+
+/********************* Function: class_resolvefield ***************************
+
+ Resolves a reference from REFERER to a field with NAME and DESC in class C.
+
+ If the field cannot be resolved the return value is NULL. If EXCEPT is
+ true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+{
+ fieldinfo *fi;
+
+ fi = class_resolvefield_int(c, name, desc);
+
+ if (!fi) {
+ if (throwexception)
+ *exceptionptr =
+ new_exception_utfmessage(string_java_lang_NoSuchFieldError,
+ name);
+
+ return NULL;
+ }
+
+ /* XXX check access rights */
+
+ return fi;
+}
+
+
+/* class_issubclass ************************************************************
+
+ Checks if sub is a descendant of super.
+
+*******************************************************************************/
+
+bool class_issubclass(classinfo *sub, classinfo *super)
+{
+ for (;;) {
+ if (!sub)
+ return false;
+
+ if (sub == super)
+ return true;
+
+ sub = sub->super.cls;
+ }
+}
+
+
+/* class_printflags ************************************************************
+
+ Prints flags of a class.
+
+*******************************************************************************/
+
+#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 (c->flags & ACC_STATIC) printf(" STATIC");
+ if (c->flags & ACC_FINAL) printf(" FINAL");
+ if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (c->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (c->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (c->flags & ACC_NATIVE) printf(" NATIVE");
+ if (c->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (c->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+}
+#endif
+
+
+/* class_print *****************************************************************
+
+ Prints classname plus flags.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_print(classinfo *c)
+{
+ 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.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_println(classinfo *c)
+{
+ class_print(c);
+ printf("\n");
+}
+#endif
+
+
+/* class_classref_println ******************************************************
+
+ Prints classname plus referer class and new line.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_println(constant_classref *cr)
+{
+ 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;
+ voidptr e;
+
+ printf ("---- dump of constant pool ----\n");
+
+ for (i=0; i<c->cpcount; i++) {
+ printf ("#%d: ", (int) i);
+
+ e = c -> cpinfos [i];
+ if (e) {
+
+ switch (c -> cptags [i]) {
+ case CONSTANT_Class:
+ printf ("Classreference -> ");
+ utf_display_printable_ascii ( ((constant_classref*)e) -> name );
+ break;
+ case CONSTANT_Fieldref:
+ printf ("Fieldref -> ");
+ field_fieldref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_Methodref:
+ printf ("Methodref -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_InterfaceMethodref:
+ printf ("InterfaceMethod -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_String:
+ printf ("String -> ");
+ utf_display_printable_ascii (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_printable_ascii (cnt->name);
+ printf (" ");
+ utf_display_printable_ascii (cnt->descriptor);
+ }
+ break;
+ case CONSTANT_Utf8:
+ printf ("Utf8 -> ");
+ utf_display_printable_ascii (e);
+ break;
+ default:
+ log_text("Invalid type of ConstantPool-Entry");
+ assert(0);
+ }
+ }
+
+ printf ("\n");
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* class_showmethods ***********************************************************
+
+ Dump info about the fields and methods of the given class to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_showmethods (classinfo *c)
+{
+ s4 i;
+
+ printf("--------- Fields and Methods ----------------\n");
+ printf("Flags: ");
+ class_printflags(c);
+ printf("\n");
+
+ printf("This: ");
+ utf_display_printable_ascii(c->name);
+ printf("\n");
+
+ if (c->super.cls) {
+ printf("Super: ");
+ utf_display_printable_ascii(c->super.cls->name);
+ printf ("\n");
+ }
+
+ printf("Index: %d\n", c->index);
+
+ printf("Interfaces:\n");
+ for (i = 0; i < c->interfacescount; i++) {
+ printf(" ");
+ utf_display_printable_ascii(c->interfaces[i].cls->name);
+ printf (" (%d)\n", c->interfaces[i].cls->index);
+ }
+
+ printf("Fields:\n");
+ for (i = 0; i < c->fieldscount; i++)
+ field_println(&(c->fields[i]));
+
+ printf("Methods:\n");
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (!(m->flags & ACC_STATIC))
+ printf("vftblindex: %d ", m->vftblindex);
+
+ method_println(m);
+ }
+
+ printf ("Virtual function table:\n");
+ for (i = 0; i < c->vftbl->vftbllength; i++)
+ printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]));
+}
+#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
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/