Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: class.c 8230 2007-07-25 08:23:10Z twisti $
-
*/
#include "mm/memory.h"
+#include "native/llni.h"
+
#include "threads/lock-common.h"
#include "toolbox/logging.h"
+#include "vm/array.h"
+#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/resolve.h"
#include "vmcore/class.h"
#include "vmcore/classcache.h"
+#include "vmcore/linker.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
classinfo *class_java_lang_VMThread;
classinfo *class_java_io_Serializable;
+#if defined(WITH_CLASSPATH_SUN)
+classinfo *class_sun_reflect_MagicAccessorImpl;
+#endif
/* system exception classes required in cacao */
classinfo *class_java_util_Vector;
classinfo *arrayclass_java_lang_Object;
+
+#if defined(ENABLE_ANNOTATIONS)
+classinfo *class_sun_reflect_ConstantPool;
+classinfo *class_sun_reflect_annotation_AnnotationParser;
+#endif
#endif
*******************************************************************************/
-classinfo *class_define(utf *name, java_objectheader *cl, int32_t length, const uint8_t *data)
+classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_t *data, java_handle_t *pd)
{
classinfo *c;
classinfo *r;
return NULL;
}
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_SUN)
+ /* Store the protection domain. */
+
+ c->protectiondomain = pd;
+# endif
+#endif
+
/* Store the newly defined class in the class cache. This call
also checks whether a class of the same name has already been
defined by the same defining loader, and if so, replaces the
bool class_load_attributes(classbuffer *cb)
{
- classinfo *c;
- u4 i, j;
- u2 attributes_count;
- u2 attribute_name_index;
- utf *attribute_name;
+ classinfo *c;
+ uint16_t attributes_count;
+ uint16_t attribute_name_index;
+ utf *attribute_name;
+ innerclassinfo *info;
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *name;
+ uint16_t flags;
+ int i, j;
c = cb->class;
for (j = 0; j < c->innerclasscount; j++) {
/* The innerclass structure contains a class with an encoded
name, its defining scope, its simple name and a bitmask of
- the access flags. If an inner class is not a member, its
- outer_class is NULL, if a class is anonymous, its name is
- NULL. */
+ the access flags. */
- innerclassinfo *info = c->innerclass + j;
-
- info->inner_class.ref =
- innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
- info->outer_class.ref =
- innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
- info->name =
- innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- info->flags = suck_u2(cb);
+ info = c->innerclass + j;
+
+ inner.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ outer.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ flags = suck_u2(cb);
+
+ /* If the current inner-class is the currently loaded
+ class check for some special flags. */
+
+ if (inner.ref->name == c->name) {
+ /* If an inner-class is not a member, its
+ outer-class is NULL. */
+
+ if (outer.ref != NULL) {
+ c->flags |= ACC_CLASS_MEMBER;
+
+ /* A member class doesn't have an
+ EnclosingMethod attribute, so set the
+ enclosing-class to be the same as the
+ declaring-class. */
+
+ c->declaringclass = outer;
+ c->enclosingclass = outer;
+ }
+
+ /* If an inner-class is anonymous, its name is
+ NULL. */
+
+ if (name == NULL)
+ c->flags |= ACC_CLASS_ANONYMOUS;
+ }
+
+ info->inner_class = inner;
+ info->outer_class = outer;
+ info->name = name;
+ info->flags = flags;
}
}
else if (attribute_name == utf_SourceFile) {
if (!loader_load_attribute_signature(cb, &(c->signature)))
return false;
}
-#if 0
+#endif
+
+#if defined(ENABLE_ANNOTATIONS)
/* XXX We can't do a release with that enabled */
else if (attribute_name == utf_RuntimeVisibleAnnotations) {
/* RuntimeVisibleAnnotations */
-
- if (!annotation_load_attribute_runtimevisibleannotations(cb))
+ if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
+ return false;
+ }
+ /* XXX RuntimeInvisibleAnnotations should only be loaded
+ * (or returned to Java) if some commandline options says so.
+ * Currently there is no such option available in cacao,
+ * therefore I load them allways (for testing purpose).
+ * Anyway, bytecode for RuntimeInvisibleAnnotations is only
+ * generated if you tell javac to do so. So in most cases
+ * there won't be any.
+ */
+ else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
return false;
}
#endif
-#endif
+
else {
/* unknown attribute */
mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
/* GCFREE(c); */
+
+#if defined(ENABLE_ANNOTATIONS)
+ annotation_bytearray_free(c->annotations);
+
+ annotation_bytearrays_free(c->method_annotations);
+ annotation_bytearrays_free(c->method_parameterannotations);
+ annotation_bytearrays_free(c->method_annotationdefaults);
+
+ annotation_bytearrays_free(c->field_annotations);
+#endif
}
*******************************************************************************/
-static classinfo *get_array_class(utf *name,java_objectheader *initloader,
- java_objectheader *defloader,bool link)
+static classinfo *get_array_class(utf *name,classloader *initloader,
+ classloader *defloader,bool link)
{
classinfo *c;
classinfo *class_array_of(classinfo *component, bool link)
{
- java_objectheader *cl;
+ classloader *cl;
s4 namelen;
char *namebuf;
utf *u;
}
+/* class_resolve_superclass ****************************************************
+
+ Resolves the super class reference of the given class if necessary.
+
+*******************************************************************************/
+
+static classinfo *class_resolve_superclass(classinfo *c)
+{
+ classinfo *super;
+
+ if (c->super.any == NULL)
+ return NULL;
+
+ /* Check if the super class is a reference. */
+
+ if (IS_CLASSREF(c->super)) {
+ /* XXX I'm very sure this is not correct. */
+ super = resolve_classref_or_classinfo_eager(c->super, true);
+/* super = resolve_classref_or_classinfo_eager(c->super, false); */
+
+ if (super == NULL)
+ return NULL;
+
+ /* Store the resolved super class in the class structure. */
+
+ c->super.cls = super;
+ }
+
+ return c->super.cls;
+}
+
+
/* class_issubclass ************************************************************
Checks if sub is a descendant of super.
bool class_issubclass(classinfo *sub, classinfo *super)
{
for (;;) {
- if (!sub)
+ if (sub == NULL)
return false;
if (sub == super)
return true;
+/* sub = class_resolve_superclass(sub); */
+ if (sub->super.any == NULL)
+ return false;
+
+ assert(IS_CLASSREF(sub->super) == 0);
+
sub = sub->super.cls;
}
}
bool class_isanysubclass(classinfo *sub, classinfo *super)
{
- castinfo classvalues;
- u4 diffval;
+ uint32_t diffval;
bool result;
/* This is the trivial case. */
if (sub->flags & ACC_INTERFACE)
return (super == class_java_lang_Object);
- ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
+ LOCK_MONITOR_ENTER(linker_classrenumber_lock);
- diffval = classvalues.sub_baseval - classvalues.super_baseval;
- result = diffval <= (u4) classvalues.super_diffval;
+ diffval = sub->vftbl->baseval - super->vftbl->baseval;
+ result = diffval <= (uint32_t) super->vftbl->diffval;
+
+ LOCK_MONITOR_EXIT(linker_classrenumber_lock);
}
return result;
}
+/* class_is_anonymousclass *****************************************************
+
+ Checks if the given class is an anonymous class.
+
+*******************************************************************************/
+
+bool class_is_anonymousclass(classinfo *c)
+{
+ if (c->flags & ACC_CLASS_ANONYMOUS)
+ return true;
+
+ return false;
+}
+
+
/* class_is_array **************************************************************
Checks if the given class is an array class.
}
+/* class_is_localclass *********************************************************
+
+ Checks if the given class is a local class.
+
+*******************************************************************************/
+
+bool class_is_localclass(classinfo *c)
+{
+ if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
+ return true;
+
+ return false;
+}
+
+
+/* class_is_memberclass ********************************************************
+
+ Checks if the given class is a member class.
+
+*******************************************************************************/
+
+bool class_is_memberclass(classinfo *c)
+{
+ if (c->flags & ACC_CLASS_MEMBER)
+ return true;
+
+ return false;
+}
+
+
/* class_get_superclass ********************************************************
Return the super class of the given class. If the super-field is a
/* We may have to resolve the super class reference. */
- if (IS_CLASSREF(c->super)) {
- super = resolve_classref_or_classinfo_eager(c->super, true);
+ super = class_resolve_superclass(c);
- if (super == NULL)
+ return super;
+}
+
+
+/* class_get_componenttype *****************************************************
+
+ Return the component class of the given class. If the given class
+ is not an array, return NULL.
+
+*******************************************************************************/
+
+classinfo *class_get_componenttype(classinfo *c)
+{
+ classinfo *component;
+ arraydescriptor *ad;
+
+ /* XXX maybe we could find a way to do this without linking. */
+ /* This way should be safe and easy, however. */
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
return NULL;
- /* Store the resolved super class in the class structure. */
+ ad = c->vftbl->arraydesc;
+
+ if (ad == NULL)
+ return NULL;
+
+ if (ad->arraytype == ARRAYTYPE_OBJECT)
+ component = ad->componentvftbl->class;
+ else
+ component = primitive_class_get_by_type(ad->arraytype);
+
+ return component;
+}
- c->super.cls = super;
+
+/* class_get_declaredclasses ***************************************************
+
+ Return an array of declared classes of the given class.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
+{
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *outername;
+ int declaredclasscount; /* number of declared classes */
+ int pos; /* current declared class */
+ java_handle_objectarray_t *oa; /* array of declared classes */
+ int i;
+ classinfo *ic;
+
+ declaredclasscount = 0;
+
+ if (!class_is_primitive(c) && !class_is_array(c)) {
+ /* Determine number of declared classes. */
+
+ for (i = 0; i < c->innerclasscount; i++) {
+ /* Get outer-class. If the inner-class is not a member
+ class, the outer-class is NULL. */
+
+ outer = c->innerclass[i].outer_class;
+
+ if (outer.any == NULL)
+ continue;
+
+ /* Check if outer-class is a classref or a real class and
+ get the class name from the structure. */
+
+ outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+ /* Outer class is this class. */
+
+ if ((outername == c->name) &&
+ ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
+ declaredclasscount++;
+ }
}
- return c->super.cls;
+ /* Allocate Class[] and check for OOM. */
+
+ oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+ inner = c->innerclass[i].inner_class;
+ outer = c->innerclass[i].outer_class;
+
+ /* Get outer-class. If the inner-class is not a member class,
+ the outer-class is NULL. */
+
+ if (outer.any == NULL)
+ continue;
+
+ /* Check if outer_class is a classref or a real class and get
+ the class name from the structure. */
+
+ outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+ /* Outer class is this class. */
+
+ if ((outername == c->name) &&
+ ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
+
+ ic = resolve_classref_or_classinfo_eager(inner, false);
+
+ if (ic == NULL)
+ return NULL;
+
+ if (!(ic->state & CLASS_LINKED))
+ if (!link_class(ic))
+ return NULL;
+
+ LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
+ }
+ }
+
+ return oa;
}
classinfo *class_get_declaringclass(classinfo *c)
{
- classref_or_classinfo innercr;
- utf *innername;
- classref_or_classinfo outercr;
- classinfo *outer;
- int16_t i;
+ classref_or_classinfo cr;
+ classinfo *dc;
- /* return NULL for arrayclasses and primitive classes */
+ /* Get declaring class. */
- if (class_is_primitive(c) || (c->name->text[0] == '['))
+ cr = c->declaringclass;
+
+ if (cr.any == NULL)
return NULL;
- /* no innerclasses exist */
+ /* Resolve the class if necessary. */
+
+ if (IS_CLASSREF(cr)) {
+/* dc = resolve_classref_eager(cr.ref); */
+ dc = resolve_classref_or_classinfo_eager(cr, true);
+
+ if (dc == NULL)
+ return NULL;
+
+ /* Store the resolved class in the class structure. */
- if (c->innerclasscount == 0)
+ cr.cls = dc;
+ }
+
+ dc = cr.cls;
+
+ return dc;
+}
+
+
+/* class_get_enclosingclass ****************************************************
+
+ Return the enclosing class for the given class.
+
+*******************************************************************************/
+
+classinfo *class_get_enclosingclass(classinfo *c)
+{
+ classref_or_classinfo cr;
+ classinfo *ec;
+
+ /* Get enclosing class. */
+
+ cr = c->enclosingclass;
+
+ if (cr.any == NULL)
return NULL;
- for (i = 0; i < c->innerclasscount; i++) {
- /* Check if inner_class is a classref or a real class and get
- the class name from the structure. */
+ /* Resolve the class if necessary. */
- innercr = c->innerclass[i].inner_class;
+ if (IS_CLASSREF(cr)) {
+/* ec = resolve_classref_eager(cr.ref); */
+ ec = resolve_classref_or_classinfo_eager(cr, true);
- innername = IS_CLASSREF(innercr) ?
- innercr.ref->name : innercr.cls->name;
+ if (ec == NULL)
+ return NULL;
- /* Is the current innerclass this class? */
+ /* Store the resolved class in the class structure. */
- if (innername == c->name) {
- /* Maybe the outer class is not loaded yet. */
+ cr.cls = ec;
+ }
- outercr = c->innerclass[i].outer_class;
+ ec = cr.cls;
- outer = resolve_classref_or_classinfo_eager(outercr, false);
+ return ec;
+}
- if (outer == NULL)
- return NULL;
- if (!(outer->state & CLASS_LINKED))
- if (!link_class(outer))
- return NULL;
+/* class_get_interfaces ********************************************************
+
+ Return an array of interfaces of the given class.
- return outer;
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_interfaces(classinfo *c)
+{
+ classinfo *ic;
+ java_handle_objectarray_t *oa;
+ u4 i;
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i].cls;
+
+ LLNI_array_direct(oa, i) = (java_object_t *) ic;
+ }
+
+ return oa;
+}
+
+
+/* class_get_annotations *******************************************************
+
+ Return the unparsed declared annotations in an byte array
+ of the given class (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *class_get_annotations(classinfo *c)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ java_handle_bytearray_t *annotations = NULL;
+ uint32_t size = 0;
+
+ /* Return null for arrays and primitives: */
+ if (class_is_primitive(c) || class_is_array(c)) {
+ return NULL;
+ }
+
+ /* copy the annotations into a java byte array: */
+ if (c->annotations != NULL) {
+ size = c->annotations->size;
+ annotations = builtin_newarray_byte(size);
+
+ if(annotations != NULL) {
+ MCOPY(annotations->data, c->annotations->data, uint8_t, size);
}
}
+ return annotations;
+#else
return NULL;
+#endif
}
*******************************************************************************/
+#if defined(ENABLE_JAVASE)
utf *class_get_signature(classinfo *c)
{
/* For array and primitive classes return NULL. */
return c->signature;
}
+#endif
/* class_printflags ************************************************************