--- /dev/null
+ /* src/vm/class.c - class related functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <assert.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ #include "vm/types.h"
+
+ #include "arch.h"
+
+ #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/class.h"
+ #include "vm/classcache.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/javaobjects.hpp"
++#include "vm/jit/jitcache.h"
+ #include "vm/linker.h"
+ #include "vm/loader.h"
+ #include "vm/options.h"
+ #include "vm/resolve.h"
+
+ #if defined(ENABLE_STATISTICS)
+ # include "vm/statistics.h"
+ #endif
+
+ #include "vm/suck.h"
+ #include "vm/utf8.h"
+
+ #include "vm/jit/asmpart.h"
+
+
+ /* class_set_packagename *******************************************************
+
+ Derive the package name from the class name and store it in the
+ struct.
+
+ An internal package name consists of the package name plus the
+ trailing '/', e.g. "java/lang/".
+
+ For classes in the unnamed package, the package name is set to
+ NULL.
+
+ *******************************************************************************/
+
+ void class_set_packagename(classinfo *c)
+ {
+ char *p;
+ char *start;
+
+ p = UTF_END(c->name) - 1;
+ start = c->name->text;
+
+ if (c->name->text[0] == '[') {
+ /* Set packagename of arrays to the element's package. */
+
+ for (; *start == '['; start++);
+
+ /* Skip the 'L' in arrays of references. */
+
+ if (*start == 'L')
+ start++;
+ }
+
+ /* Search for last '/'. */
+
+ for (; (p > start) && (*p != '/'); --p);
+
+ /* If we found a '/' we set the package name plus the trailing
+ '/'. Otherwise we set the packagename to NULL. */
+
+ if (p > start)
+ c->packagename = utf_new(start, p - start + 1);
+ else
+ c->packagename = NULL;
+ }
+
+
+ /* class_create_classinfo ******************************************************
+
+ Create a new classinfo struct. The class name is set to the given utf *,
+ most other fields are initialized to zero.
+
+ Note: classname may be NULL. In this case a not-yet-named classinfo is
+ created. The name must be filled in later and class_set_packagename
+ must be called after that.
+
+ *******************************************************************************/
+
+ classinfo *class_create_classinfo(utf *classname)
+ {
+ classinfo *c;
+
+ #if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_classinfo += sizeof(classinfo);
+ #endif
+
+ /* we use a safe name for temporarily unnamed classes */
+
+ if (classname == NULL)
+ classname = utf_not_named_yet;
+
+ #if !defined(NDEBUG)
+ if (initverbose)
+ log_message_utf("Creating class: ", classname);
+ #endif
+
+ #if !defined(ENABLE_GC_BOEHM)
+ c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+ /*c = NEW(classinfo);
+ MZERO(c, classinfo, 1);*/
+ #else
+ c = GCNEW_UNCOLLECTABLE(classinfo, 1);
+ /* GCNEW_UNCOLLECTABLE clears the allocated memory */
+ #endif
+
+ c->name = classname;
+
+ /* 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 != NULL)
+ if (class_java_lang_Class->vftbl != NULL)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+
+ #if defined(ENABLE_JAVASE)
+ /* check if the class is a reference class and flag it */
+
+ if (classname == utf_java_lang_ref_SoftReference) {
+ c->flags |= ACC_CLASS_REFERENCE_SOFT;
+ }
+ else if (classname == utf_java_lang_ref_WeakReference) {
+ c->flags |= ACC_CLASS_REFERENCE_WEAK;
+ }
+ else if (classname == utf_java_lang_ref_PhantomReference) {
+ c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
+ }
+ #endif
+
+ if (classname != utf_not_named_yet)
+ class_set_packagename(c);
++#if defined (ENABLE_JITCACHE)
++ c->cache_file_fd = 0;
++#endif
+
+ LOCK_INIT_OBJECT_LOCK(&c->object.header);
+
+ 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_define ****************************************************************
+
+ Calls the loader and defines a class in the VM.
+
+ *******************************************************************************/
+
+ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
+ {
+ classinfo *c;
+ classinfo *r;
+ classbuffer *cb;
+
+ if (name != NULL) {
+ /* check if this class has already been defined */
+
+ c = classcache_lookup_defined_or_initiated(cl, name);
+
+ if (c != NULL) {
+ exceptions_throw_linkageerror("duplicate class definition: ", c);
+ return NULL;
+ }
+ }
+
+ /* create a new classinfo struct */
+
+ c = class_create_classinfo(name);
+
+ #if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+ #endif
+
+ /* build a classbuffer with the given data */
+
+ cb = NEW(classbuffer);
+
+ cb->clazz = c;
+ cb->size = length;
+ cb->data = data;
+ cb->pos = cb->data;
+
+ /* preset the defining classloader */
+
+ c->classloader = cl;
+
+ /* load the class from this buffer */
+
+ r = load_class_from_classbuffer(cb);
+
+ /* free memory */
+
+ FREE(cb, classbuffer);
+
+ #if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+ #endif
+
+ if (r == NULL) {
+ /* If return value is NULL, we had a problem and the class is
+ not loaded. Now free the allocated memory, otherwise we
+ could run into a DOS. */
+
+ class_free(c);
+
+ return NULL;
+ }
+
+ #if defined(ENABLE_JAVASE)
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* 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
+ newly created class by the one defined earlier. */
+
+ /* Important: The classinfo given to classcache_store must be
+ fully prepared because another thread may return
+ this pointer after the lookup at to top of this
+ function directly after the class cache lock has
+ been released. */
+
+ c = classcache_store(cl, c, true);
+
+ return c;
+ }
+
+
+ /* class_load_attribute_sourcefile *********************************************
+
+ SourceFile_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 sourcefile_index;
+ }
+
+ *******************************************************************************/
+
+ static bool class_load_attribute_sourcefile(classbuffer *cb)
+ {
+ classinfo *c;
+ u4 attribute_length;
+ u2 sourcefile_index;
+ utf *sourcefile;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 2) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* there can be no more than one SourceFile attribute */
+
+ if (c->sourcefile != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
+ return false;
+ }
+
+ /* get sourcefile */
+
+ sourcefile_index = suck_u2(cb);
+ sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
+
+ if (sourcefile == NULL)
+ return false;
+
+ /* store sourcefile */
+
+ c->sourcefile = sourcefile;
+
+ return true;
+ }
+
+
+ /* class_load_attribute_enclosingmethod ****************************************
+
+ EnclosingMethod_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 class_index;
+ u2 method_index;
+ }
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ static bool class_load_attribute_enclosingmethod(classbuffer *cb)
+ {
+ classinfo *c;
+ u4 attribute_length;
+ u2 class_index;
+ u2 method_index;
+ classref_or_classinfo cr;
+ constant_nameandtype *cn;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 4) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* there can be no more than one EnclosingMethod attribute */
+
+ if (c->enclosingmethod != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
+ return false;
+ }
+
+ /* get class index */
+
+ class_index = suck_u2(cb);
+ cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class);
+
+ /* get method index */
+
+ method_index = suck_u2(cb);
+ cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
+
+ /* store info in classinfo */
+
+ c->enclosingclass.any = cr.any;
+ c->enclosingmethod = cn;
+
+ return true;
+ }
+ #endif /* defined(ENABLE_JAVASE) */
+
+
+ /* class_load_attributes *******************************************************
+
+ Read attributes from ClassFile.
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ InnerClasses_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ }
+
+ *******************************************************************************/
+
+ bool class_load_attributes(classbuffer *cb)
+ {
+ 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->clazz;
+
+ /* get attributes count */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attributes_count = suck_u2(cb);
+
+ for (i = 0; i < attributes_count; i++) {
+ /* get attribute name */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attribute_name_index = suck_u2(cb);
+ attribute_name =
+ class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
+
+ if (attribute_name == NULL)
+ return false;
+
+ if (attribute_name == utf_InnerClasses) {
+ /* InnerClasses */
+
+ if (c->innerclass != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* skip attribute length */
+ suck_u4(cb);
+
+ /* number of records */
+ c->innerclasscount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+ return false;
+
+ /* allocate memory for innerclass structure */
+ c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
+
+ 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. */
+
+ 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) {
+ /* SourceFile */
+
+ if (!class_load_attribute_sourcefile(cb))
+ return false;
+ }
+ #if defined(ENABLE_JAVASE)
+ else if (attribute_name == utf_EnclosingMethod) {
+ /* EnclosingMethod */
+
+ if (!class_load_attribute_enclosingmethod(cb))
+ return false;
+ }
+ else if (attribute_name == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(c->signature)))
+ return false;
+ }
+ #endif
+
+ #if defined(ENABLE_ANNOTATIONS)
+ else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
+ return false;
+ }
+ #endif
+
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /* class_freepool **************************************************************
+
+ Frees all resources used by this classes Constant Pool.
+
+ *******************************************************************************/
+
+ static void class_freecpool(classinfo *c)
+ {
+ u4 idx;
+ u4 tag;
+ void* info;
+
+ if (c->cptags && c->cpinfos) {
+ for (idx = 0; idx < c->cpcount; idx++) {
+ tag = c->cptags[idx];
+ info = c->cpinfos[idx];
+
+ if (info != NULL) {
+ switch (tag) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ FREE(info, constant_FMIref);
+ break;
+ case CONSTANT_Integer:
+ FREE(info, constant_integer);
+ break;
+ case CONSTANT_Float:
+ FREE(info, constant_float);
+ break;
+ case CONSTANT_Long:
+ FREE(info, constant_long);
+ break;
+ case CONSTANT_Double:
+ FREE(info, constant_double);
+ break;
+ case CONSTANT_NameAndType:
+ FREE(info, constant_nameandtype);
+ break;
+ }
+ }
+ }
+ }
+
+ if (c->cptags)
+ MFREE(c->cptags, u1, c->cpcount);
+
+ if (c->cpinfos)
+ MFREE(c->cpinfos, void*, c->cpcount);
+ }
+
+
+ /* class_getconstant ***********************************************************
+
+ Retrieves the value at position 'pos' of the constantpool of a
+ class. If the type of the value is other than 'ctype', an error is
+ thrown.
+
+ *******************************************************************************/
+
+ void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
+ {
+ /* check index and type of constantpool entry */
+ /* (pos == 0 is caught by type comparison) */
+
+ if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
+ }
+
+
+ /* innerclass_getconstant ******************************************************
+
+ Like class_getconstant, but if cptags is ZERO, null is returned.
+
+ *******************************************************************************/
+
+ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+ {
+ /* invalid position in constantpool */
+
+ if (pos >= c->cpcount) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ /* constantpool entry of type 0 */
+
+ if (c->cptags[pos] == 0)
+ return NULL;
+
+ /* check type of constantpool entry */
+
+ if (c->cptags[pos] != ctype) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
+ }
+
+
+ /* class_free ******************************************************************
+
+ Frees all resources used by the class.
+
+ *******************************************************************************/
+
+ void class_free(classinfo *c)
+ {
+ s4 i;
+ vftbl_t *v;
+
++#if defined(ENABLE_JITCACHE)
++/* TODO: Find a way around the linker problem */
++/* jitcache_freeclass(c);*/
++#endif
++
+ class_freecpool(c);
+
+ if (c->interfaces != NULL)
+ MFREE(c->interfaces, classinfo*, c->interfacescount);
+
+ if (c->fields) {
+ for (i = 0; i < c->fieldscount; i++)
+ field_free(&(c->fields[i]));
+ MFREE(c->fields, fieldinfo, c->fieldscount);
+ }
+
+ if (c->methods) {
+ for (i = 0; i < c->methodscount; i++)
+ method_free(&(c->methods[i]));
+ MFREE(c->methods, methodinfo, c->methodscount);
+ }
+
+ if ((v = c->vftbl) != NULL) {
+ if (v->arraydesc)
+ mem_free(v->arraydesc,sizeof(arraydescriptor));
+
+ for (i = 0; i < v->interfacetablelength; i++) {
+ MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
+ }
+ MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
+
+ i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
+ sizeof(methodptr*) * (v->interfacetablelength -
+ (v->interfacetablelength > 0));
+ v = (vftbl_t*) (((methodptr*) v) -
+ (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
+ mem_free(v, i);
+ }
+
+ if (c->innerclass)
+ MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
+
+ /* if (c->classvftbl)
+ mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
+
+ /* GCFREE(c); */
+ }
+
+
+ /* get_array_class *************************************************************
+
+ Returns the array class with the given name for the given
+ classloader, or NULL if an exception occurred.
+
+ Note: This function does eager loading.
+
+ *******************************************************************************/
+
+ static classinfo *get_array_class(utf *name,classloader_t *initloader,
+ classloader_t *defloader,bool link)
+ {
+ classinfo *c;
+
+ /* lookup this class in the classcache */
+ c = classcache_lookup(initloader,name);
+ if (!c)
+ c = classcache_lookup_defined(defloader,name);
+
+ if (!c) {
+ /* we have to create it */
+ c = class_create_classinfo(name);
+ c = load_newly_created_array(c,initloader);
+ if (c == NULL)
+ return NULL;
+ }
+
+ assert(c);
+ assert(c->state & CLASS_LOADED);
+ assert(c->classloader == defloader);
+
+ if (link && !(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ assert(!link || (c->state & CLASS_LINKED));
+
+ return c;
+ }
+
+
+ /* class_array_of **************************************************************
+
+ Returns an array class with the given component class. The array
+ class is dynamically created if neccessary.
+
+ *******************************************************************************/
+
+ classinfo *class_array_of(classinfo *component, bool link)
+ {
+ classloader_t *cl;
+ s4 namelen;
+ char *namebuf;
+ utf *u;
+ classinfo *c;
+ int32_t dumpmarker;
+
+ cl = component->classloader;
+
+ DMARKER;
+
+ /* Assemble the array class name */
+ namelen = component->name->blength;
+
+ if (component->name->text[0] == '[') {
+ /* the component is itself an array */
+ namebuf = DMNEW(char, namelen + 1);
+ namebuf[0] = '[';
+ MCOPY(namebuf + 1, component->name->text, char, namelen);
+ namelen++;
+ }
+ else {
+ /* the component is a non-array class */
+ namebuf = DMNEW(char, namelen + 3);
+ namebuf[0] = '[';
+ namebuf[1] = 'L';
+ MCOPY(namebuf + 2, component->name->text, char, namelen);
+ namebuf[2 + namelen] = ';';
+ namelen += 3;
+ }
+
+ u = utf_new(namebuf, namelen);
+
+ c = get_array_class(u, cl, cl, link);
+
+ DRELEASE;
+
+ return c;
+ }
+
+
+ /* class_multiarray_of *********************************************************
+
+ Returns an array class with the given dimension and element class.
+ The array class is dynamically created if neccessary.
+
+ *******************************************************************************/
+
+ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
+ {
+ s4 namelen;
+ char *namebuf;
+ classinfo *c;
+ int32_t dumpmarker;
+
+ DMARKER;
+
+ if (dim < 1) {
+ log_text("Invalid array dimension requested");
+ assert(0);
+ }
+
+ /* Assemble the array class name */
+ namelen = element->name->blength;
+
+ if (element->name->text[0] == '[') {
+ /* the element is itself an array */
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, element->name->text, namelen);
+ namelen += dim;
+ }
+ else {
+ /* the element is a non-array class */
+ namebuf = DMNEW(char, namelen + 2 + dim);
+ namebuf[dim] = 'L';
+ memcpy(namebuf + dim + 1, element->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
+ }
+ memset(namebuf, '[', dim);
+
+ c = get_array_class(utf_new(namebuf, namelen),
+ element->classloader,
+ element->classloader,
+ link);
+
+ DRELEASE;
+
+ return c;
+ }
+
+
+ /* class_lookup_classref *******************************************************
+
+ Looks up the constant_classref for a given classname in the classref
+ tables of a class.
+
+ IN:
+ cls..............the class containing the reference
+ name.............the name of the class refered to
+
+ RETURN VALUE:
+ a pointer to a constant_classref, or
+ NULL if the reference was not found
+
+ *******************************************************************************/
+
+ constant_classref *class_lookup_classref(classinfo *cls, utf *name)
+ {
+ constant_classref *ref;
+ extra_classref *xref;
+ int count;
+
+ assert(cls);
+ assert(name);
+ assert(!cls->classrefcount || cls->classrefs);
+
+ /* first search the main classref table */
+ count = cls->classrefcount;
+ ref = cls->classrefs;
+ for (; count; --count, ++ref)
+ if (ref->name == name)
+ return ref;
+
+ /* next try the list of extra classrefs */
+ for (xref = cls->extclassrefs; xref; xref = xref->next) {
+ if (xref->classref.name == name)
+ return &(xref->classref);
+ }
+
+ /* not found */
+ return NULL;
+ }
+
+
+ /* class_get_classref **********************************************************
+
+ Returns the constant_classref for a given classname.
+
+ IN:
+ cls..............the class containing the reference
+ name.............the name of the class refered to
+
+ RETURN VALUE:
+ a pointer to a constant_classref (never NULL)
+
+ NOTE:
+ The given name is not checked for validity!
+
+ *******************************************************************************/
+
+ constant_classref *class_get_classref(classinfo *cls, utf *name)
+ {
+ constant_classref *ref;
+ extra_classref *xref;
+
+ assert(cls);
+ assert(name);
+
+ ref = class_lookup_classref(cls,name);
+ if (ref)
+ return ref;
+
+ xref = NEW(extra_classref);
+ CLASSREF_INIT(xref->classref,cls,name);
+
+ xref->next = cls->extclassrefs;
+ cls->extclassrefs = xref;
+
+ return &(xref->classref);
+ }
+
+
+ /* class_get_self_classref *****************************************************
+
+ Returns the constant_classref to the class itself.
+
+ IN:
+ cls..............the class containing the reference
+
+ RETURN VALUE:
+ a pointer to a constant_classref (never NULL)
+
+ *******************************************************************************/
+
+ constant_classref *class_get_self_classref(classinfo *cls)
+ {
+ /* XXX this should be done in a faster way. Maybe always make */
+ /* the classref of index 0 a self reference. */
+ return class_get_classref(cls,cls->name);
+ }
+
+ /* class_get_classref_multiarray_of ********************************************
+
+ Returns an array type reference with the given dimension and element class
+ reference.
+
+ IN:
+ dim..............the requested dimension
+ dim must be in [1;255]. This is NOT checked!
+ ref..............the component class reference
+
+ RETURN VALUE:
+ a pointer to the class reference for the array type
+
+ NOTE:
+ The referer of `ref` is used as the referer for the new classref.
+
+ *******************************************************************************/
+
+ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
+ {
+ s4 namelen;
+ char *namebuf;
+ constant_classref *cr;
+ int32_t dumpmarker;
+
+ assert(ref);
+ assert(dim >= 1 && dim <= 255);
+
+ DMARKER;
+
+ /* Assemble the array class name */
+ namelen = ref->name->blength;
+
+ if (ref->name->text[0] == '[') {
+ /* the element is itself an array */
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, ref->name->text, namelen);
+ namelen += dim;
+ }
+ else {
+ /* the element is a non-array class */
+ namebuf = DMNEW(char, namelen + 2 + dim);
+ namebuf[dim] = 'L';
+ memcpy(namebuf + dim + 1, ref->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
+ }
+ memset(namebuf, '[', dim);
+
+ cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
+
+ DRELEASE;
+
+ return cr;
+ }
+
+
+ /* class_get_classref_component_of *********************************************
+
+ Returns the component classref of a given array type reference
+
+ IN:
+ ref..............the array type reference
+
+ RETURN VALUE:
+ a reference to the component class, or
+ NULL if `ref` is not an object array type reference
+
+ NOTE:
+ The referer of `ref` is used as the referer for the new classref.
+
+ *******************************************************************************/
+
+ constant_classref *class_get_classref_component_of(constant_classref *ref)
+ {
+ s4 namelen;
+ char *name;
+
+ assert(ref);
+
+ name = ref->name->text;
+ if (*name++ != '[')
+ return NULL;
+
+ namelen = ref->name->blength - 1;
+ if (*name == 'L') {
+ name++;
+ namelen -= 2;
+ }
+ else if (*name != '[') {
+ return NULL;
+ }
+
+ return class_get_classref(ref->referer, utf_new(name, namelen));
+ }
+
+
+ /* 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;
+ }
+
+ 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 super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], 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 super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], 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)
+ exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
+
+ return NULL;
+ }
+
+ mi = class_resolveinterfacemethod_intern(c, name, desc);
+
+ if (mi != NULL)
+ return mi;
+
+ /* try class java.lang.Object */
+
+ mi = class_findmethod(class_java_lang_Object, name, desc);
+
+ if (mi != NULL)
+ return mi;
+
+ if (throwexception)
+ exceptions_throw_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+ }
+
+
+ /* class_findfield *************************************************************
+
+ Searches for field with specified name and type in a classinfo
+ structure. If no such field is found NULL is returned.
+
+ *******************************************************************************/
+
+ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
+ {
+ s4 i;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
+ return &(c->fields[i]);
+
+ if (c->super != NULL)
+ return class_findfield(c->super, name, desc);
+
+ return NULL;
+ }
+
+
+ /* class_findfield_approx ******************************************************
+
+ Searches in 'classinfo'-structure for a field with the specified
+ name.
+
+ *******************************************************************************/
+
+ fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
+ {
+ for (int32_t i = 0; i < c->fieldscount; i++) {
+ fieldinfo* f = &(c->fields[i]);
+
+ if (f->name == name)
+ return f;
+ }
+
+ // Field not found.
+ exceptions_throw_nosuchfielderror(c, name);
+ return NULL;
+ }
+
+
+ /****************** 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 super interfaces recursively. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ fi = class_resolvefield_int(c->interfaces[i], name, desc);
+
+ if (fi != NULL)
+ return fi;
+ }
+
+ /* Try super class. */
+
+ if (c->super != NULL)
+ return class_resolvefield_int(c->super, 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, an exception is thrown and the
+ return value is NULL.
+
+ *******************************************************************************/
+
+ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
+ {
+ fieldinfo *fi;
+
+ fi = class_resolvefield_int(c, name, desc);
+
+ if (!fi) {
+ exceptions_throw_nosuchfielderror(c, 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)
+ {
+ classinfo *c;
+
+ c = sub;
+
+ for (;;) {
+ /* We reached java/lang/Object and did not find the requested
+ super class. */
+
+ if (c == NULL)
+ return false;
+
+ /* We found the requested super class. */
+
+ if (c == super)
+ return true;
+
+ c = c->super;
+ }
+ }
+
+
+ /* class_isanysubclass *********************************************************
+
+ Checks a subclass relation between two classes. Implemented
+ interfaces are interpreted as super classes.
+
+ Return value: 1 ... sub is subclass of super
+ 0 ... otherwise
+
+ *******************************************************************************/
+
+ bool class_isanysubclass(classinfo *sub, classinfo *super)
+ {
+ uint32_t diffval;
+ bool result;
+
+ /* This is the trivial case. */
+
+ if (sub == super)
+ return true;
+
+ /* Primitive classes are only subclasses of themselves. */
+
+ if (class_is_primitive(sub) || class_is_primitive(super))
+ return false;
+
+ /* Check for interfaces. */
+
+ if (super->flags & ACC_INTERFACE) {
+ result = (sub->vftbl->interfacetablelength > super->index) &&
+ (sub->vftbl->interfacetable[-super->index] != NULL);
+ }
+ else {
+ /* java.lang.Object is the only super class of any
+ interface. */
+
+ if (sub->flags & ACC_INTERFACE)
+ return (super == class_java_lang_Object);
+
+ LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+ diffval = sub->vftbl->baseval - super->vftbl->baseval;
+ result = diffval <= (uint32_t) super->vftbl->diffval;
+
+ LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+ }
+
+ return result;
+ }
+
+
+ /* class_is_assignable_from ****************************************************
+
+ Return whether an instance of the "from" class parameter would be
+ an instance of this class "to" as well.
+
+ ARGUMENTS:
+ to ..... class
+ from ... class
+
+ RETURN:
+ true .... is assignable
+ false ... is not assignable
+
+ *******************************************************************************/
+
+ bool class_is_assignable_from(classinfo *to, classinfo *from)
+ {
+ if (!(to->state & CLASS_LINKED))
+ if (!link_class(to))
+ return false;
+
+ if (!(from->state & CLASS_LINKED))
+ if (!link_class(from))
+ return false;
+
+ return class_isanysubclass(from, to);
+ }
+
+
+ /* class_is_instance ***********************************************************
+
+ Return if the given Java object is an instance of the given class.
+
+ ARGUMENTS:
+ c ... class
+ h ... Java object
+
+ RETURN:
+ true .... is instance
+ false ... is not instance
+
+ *******************************************************************************/
+
+ bool class_is_instance(classinfo *c, java_handle_t *h)
+ {
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return builtin_instanceof(h, c);
+ }
+
+
+ /* 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;
+
+ ad = c->vftbl->arraydesc;
+
+ if (ad == NULL)
+ return NULL;
+
+ if (ad->arraytype == ARRAYTYPE_OBJECT)
+ component = ad->componentvftbl->clazz;
+ else
+ component = Primitive_get_class_by_type(ad->arraytype);
+
+ return component;
+ }
+
+
+ /* 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++;
+ }
+ }
+
+ /* 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;
+ }
+
+
+ /**
+ * Return an array of declared constructors of the given class.
+ *
+ * @param c class to get the constructors of
+ * @param publicOnly show only public fields
+ *
+ * @return array of java.lang.reflect.Constructor
+ */
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+ {
+ methodinfo* m;
+ java_handle_objectarray_t* oa;
+ java_handle_t* rc;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of constructors. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init))
+ count++;
+ }
+
+ /* Create array of constructors. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the constructors and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init)) {
+ // Create a java.lang.reflect.Constructor object.
+
+ rc = java_lang_reflect_Constructor_create(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, rc);
+ index++;
+ }
+ }
+
+ return oa;
+ }
+ #endif
+
+
+ /* class_get_declaredfields ****************************************************
+
+ Return an array of declared fields of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the fields of
+ publicOnly ... show only public fields
+
+ RETURN:
+ array of java.lang.reflect.Field
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+ {
+ java_handle_objectarray_t *oa;
+ fieldinfo *f;
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of fields. */
+
+ count = 0;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+ count++;
+
+ /* Create array of fields. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the fields and store them in the array. */
+
+ for (i = 0, index = 0; i < c->fieldscount; i++) {
+ f = &(c->fields[i]);
+
+ if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+ // Create a java.lang.reflect.Field object.
+
+ h = java_lang_reflect_Field_create(f);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+ }
+ #endif
+
+
+ /* class_get_declaredmethods ***************************************************
+
+ Return an array of declared methods of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the methods of
+ publicOnly ... show only public methods
+
+ RETURN:
+ array of java.lang.reflect.Method
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+ {
+ java_handle_objectarray_t *oa; /* result: array of Method-objects */
+ methodinfo *m; /* the current method to be represented */
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* JOWENN: array classes do not declare methods according to mauve
+ test. It should be considered, if we should return to my old
+ clone method overriding instead of declaring it as a member
+ function. */
+
+ if (class_is_array(c))
+ return builtin_anewarray(0, class_java_lang_reflect_Method);
+
+ /* Determine number of methods. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA))
+ count++;
+ }
+
+ /* Create array of methods. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the methods and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA)) {
+ // Create java.lang.reflect.Method object.
+
+ h = java_lang_reflect_Method_create(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+ }
+ #endif
+
+
+ /* class_get_declaringclass ****************************************************
+
+ If the class or interface given is a member of another class,
+ return the declaring class. For array and primitive classes return
+ NULL.
+
+ *******************************************************************************/
+
+ classinfo *class_get_declaringclass(classinfo *c)
+ {
+ classref_or_classinfo cr;
+ classinfo *dc;
+
+ /* Get declaring class. */
+
+ cr = c->declaringclass;
+
+ if (cr.any == NULL)
+ return NULL;
+
+ /* 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. */
+
+ 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;
+
+ /* Resolve the class if necessary. */
+
+ if (IS_CLASSREF(cr)) {
+ /* ec = resolve_classref_eager(cr.ref); */
+ ec = resolve_classref_or_classinfo_eager(cr, true);
+
+ if (ec == NULL)
+ return NULL;
+
+ /* Store the resolved class in the class structure. */
+
+ cr.cls = ec;
+ }
+
+ ec = cr.cls;
+
+ return ec;
+ }
+
+
+ /**
+ * Return the enclosing constructor as java.lang.reflect.Constructor
+ * object for the given class.
+ *
+ * @param c class to return the enclosing constructor for
+ *
+ * @return java.lang.reflect.Constructor object of the enclosing
+ * constructor
+ */
+ #if defined(ENABLE_JAVASE)
+ java_handle_t* class_get_enclosingconstructor(classinfo *c)
+ {
+ methodinfo* m;
+ java_handle_t* rc;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* Check for <init>. */
+
+ if (m->name != utf_init)
+ return NULL;
+
+ // Create a java.lang.reflect.Constructor object.
+
+ rc = java_lang_reflect_Constructor_create(m);
+
+ return rc;
+ }
+ #endif
+
+
+ /* class_get_enclosingmethod ***************************************************
+
+ Return the enclosing method for the given class.
+
+ IN:
+ c ... class to return the enclosing method for
+
+ RETURN:
+ methodinfo of the enclosing method
+
+ *******************************************************************************/
+
+ methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+ {
+ constant_nameandtype *cn;
+ classinfo *ec;
+ methodinfo *m;
+
+ /* get enclosing class and method */
+
+ ec = class_get_enclosingclass(c);
+ cn = c->enclosingmethod;
+
+ /* check for enclosing class and method */
+
+ if (ec == NULL)
+ return NULL;
+
+ if (cn == NULL)
+ return NULL;
+
+ /* find method in enclosing class */
+
+ m = class_findmethod(ec, cn->name, cn->descriptor);
+
+ if (m == NULL) {
+ exceptions_throw_internalerror("Enclosing method doesn't exist");
+ return NULL;
+ }
+
+ return m;
+ }
+
+
+ /**
+ * Return the enclosing method as java.lang.reflect.Method object for
+ * the given class.
+ *
+ * @param c class to return the enclosing method for
+ *
+ * @return java.lang.reflect.Method object of the enclosing method
+ */
+ #if defined(ENABLE_JAVASE)
+ java_handle_t* class_get_enclosingmethod(classinfo *c)
+ {
+ methodinfo* m;
+ java_handle_t* rm;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* check for <init> */
+
+ if (m->name == utf_init)
+ return NULL;
+
+ // Create a java.lang.reflect.Method object.
+
+ rm = java_lang_reflect_Method_create(m);
+
+ return rm;
+ }
+ #endif
+
+
+ /* class_get_interfaces ********************************************************
+
+ Return an array of interfaces of the given class.
+
+ *******************************************************************************/
+
+ 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];
+
+ LLNI_array_direct(oa, i) = (java_object_t *) ic;
+ }
+
+ return oa;
+ }
+
+
+ /* class_get_annotations *******************************************************
+
+ Get the unparsed declared annotations in a byte array
+ of the given class.
+
+ IN:
+ c........the class of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed declared annotations in a byte array
+ (or NULL if there aren't any).
+
+ *******************************************************************************/
+
+ java_handle_bytearray_t *class_get_annotations(classinfo *c)
+ {
+ #if defined(ENABLE_ANNOTATIONS)
+ java_handle_t *annotations; /* unparsed annotations */
+
+ LLNI_classinfo_field_get(c, annotations, annotations);
+
+ return (java_handle_bytearray_t*)annotations;
+ #else
+ return NULL;
+ #endif
+ }
+
+
+ /* class_get_modifiers *********************************************************
+
+ Get the modifier flags of the given class.
+
+ IN:
+ c....the class of which the modifier flags should be returned
+ ignoreInnerClassesAttrib
+ RETURN VALUE:
+ modifier flags
+
+ *******************************************************************************/
+
+ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
+ {
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *innername;
+ int i;
+
+ if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
+ /* search for passed class as inner class */
+
+ for (i = 0; i < c->innerclasscount; i++) {
+ inner = c->innerclass[i].inner_class;
+ outer = c->innerclass[i].outer_class;
+
+ /* Check if inner is a classref or a real class and get
+ the name of the structure */
+
+ innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
+
+ /* innerclass is this class */
+
+ if (innername == c->name) {
+ /* has the class actually an outer class? */
+
+ if (outer.any)
+ /* return flags got from the outer class file */
+ return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
+ else
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+ }
+ }
+ }
+
+ /* passed class is no inner class or it was not requested */
+
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+ }
+
+
+ /* class_get_signature *********************************************************
+
+ Return the signature of the given class. For array and primitive
+ classes return NULL.
+
+ *******************************************************************************/
+
+ #if defined(ENABLE_JAVASE)
+ utf *class_get_signature(classinfo *c)
+ {
+ /* For array and primitive classes return NULL. */
+
+ if (class_is_array(c) || class_is_primitive(c))
+ return NULL;
+
+ return c->signature;
+ }
+ #endif
+
+
+ /* 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.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_classref_or_classinfo_println(classref_or_classinfo c)
+ {
+ class_classref_or_classinfo_print(c);
+ printf("\n");
+ }
+ #endif
+
+
+ /* class_showconstantpool ******************************************************
+
+ Dump the constant pool of the given class to stdout.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ void class_showconstantpool (classinfo *c)
+ {
+ u4 i;
+ void* 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) {
+ printf("Super: ");
+ utf_display_printable_ascii(c->super->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]->name);
+ printf (" (%d)\n", c->interfaces[i]->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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
-
+ /* src/vm/class.h - class related functions header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _CLASS_H
+ #define _CLASS_H
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ /* forward typedefs ***********************************************************/
+
+ typedef struct classinfo classinfo;
+ typedef struct innerclassinfo innerclassinfo;
+ typedef struct extra_classref extra_classref;
+
+
+ #include "config.h"
+
+ #include <stdint.h>
+
+ #include "vm/types.h"
+
+ #include "toolbox/list.h"
+
+ #if defined(ENABLE_JAVASE)
+ # include "vm/annotation.h"
+ #endif
+
+ #include "vm/field.h"
+ #include "vm/global.h"
+ #include "vm/linker.h"
+ #include "vm/loader.h"
+ #include "vm/method.h"
+ #include "vm/references.h"
+ #include "vm/string.hpp"
+ #include "vm/utf8.h"
+
+ /* class state defines ********************************************************/
+
+ #define CLASS_LOADING 0x0001
+ #define CLASS_LOADED 0x0002
+ #define CLASS_LINKING 0x0004
+ #define CLASS_LINKED 0x0008
+ #define CLASS_INITIALIZING 0x0010
+ #define CLASS_INITIALIZED 0x0020
+ #define CLASS_ERROR 0x0040
+
+
+ /* some macros ****************************************************************/
+
+ #define CLASS_IS_OR_ALMOST_INITIALIZED(c) \
+ (((c)->state & CLASS_INITIALIZING) || ((c)->state & CLASS_INITIALIZED))
+
+
+ /* classinfo ******************************************************************/
+
+ /* We define this dummy structure of java_lang_Class so we can
+ bootstrap cacaoh without needing a java_lang_Class.h file. Whether
+ the size of the dummy structure is big enough is checked during
+ runtime in vm_create. */
+
+ typedef struct {
+ java_object_t header;
+ #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ intptr_t padding[4];
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ intptr_t padding[19];
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+ intptr_t padding[3];
+ #else
+ # error unknown classpath configuration
+ #endif
+ } dummy_java_lang_Class;
+
+ struct classinfo { /* class structure */
+ dummy_java_lang_Class object;
+
+ s4 flags; /* ACC flags */
+ utf *name; /* class name */
+
+ s4 cpcount; /* number of entries in constant pool */
+ u1 *cptags; /* constant pool tags */
+ void* *cpinfos; /* pointer to constant pool info structures */
+
+ s4 classrefcount; /* number of symbolic class references */
+ constant_classref *classrefs; /* table of symbolic class references */
+ extra_classref *extclassrefs; /* additional classrefs */
+ s4 parseddescsize; /* size of the parsed descriptors block */
+ u1 *parseddescs; /* parsed descriptors */
+
+ classinfo *super; /* super class */
+ classinfo *sub; /* sub class pointer */
+ classinfo *nextsub; /* pointer to next class in sub class list */
+
+ int32_t interfacescount; /* number of interfaces */
+ classinfo **interfaces; /* super interfaces */
+
+ int32_t fieldscount; /* number of fields */
+ fieldinfo *fields; /* field table */
+
+ int32_t methodscount; /* number of methods */
+ methodinfo *methods; /* method table */
+
+ s4 state; /* current class state */
+ s4 index; /* hierarchy depth (classes) or index */
+ /* (interfaces) */
+ s4 instancesize; /* size of an instance of this class */
+
+ vftbl_t *vftbl; /* pointer to virtual function table */
+
+ methodinfo *finalizer; /* finalizer method */
+
+ u2 innerclasscount; /* number of inner classes */
+ innerclassinfo *innerclass;
+
+ classref_or_classinfo declaringclass;
+ classref_or_classinfo enclosingclass; /* enclosing class */
+ constant_nameandtype *enclosingmethod; /* enclosing method */
+
+ utf *packagename; /* full name of the package */
+ utf *sourcefile; /* SourceFile attribute */
+ #if defined(ENABLE_JAVASE)
+ utf *signature; /* Signature attribute */
+ #if defined(ENABLE_ANNOTATIONS)
+ /* All the annotation attributes are NULL (and not a zero length array) */
+ /* if there is nothing. */
+ java_object_t *annotations; /* annotations of this class */
+
+ java_object_t *method_annotations; /* array of annotations of the methods */
+ java_object_t *method_parameterannotations; /* array of parameter */
+ /* annotations of the methods */
+ java_object_t *method_annotationdefaults; /* array of annotation default */
+ /* values of the methods */
+
+ java_object_t *field_annotations; /* array of annotations of the fields */
+
+ #endif
+ #endif
+ classloader_t *classloader; /* NULL for bootstrap classloader */
+
+ #if defined(ENABLE_JAVASE)
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ java_object_t *protectiondomain;
+ java_objectarray_t *signers;
+ # endif
+ #endif
++#if defined(ENABLE_JITCACHE)
++ int cache_file_fd;
++#endif
+ };
+
+
+ /* innerclassinfo *************************************************************/
+
+ struct innerclassinfo {
+ classref_or_classinfo inner_class; /* inner class pointer */
+ classref_or_classinfo outer_class; /* outer class pointer */
+ utf *name; /* innerclass name */
+ s4 flags; /* ACC flags */
+ };
+
+
+ /* extra_classref **************************************************************
+
+ for classrefs not occurring within descriptors
+
+ *******************************************************************************/
+
+ struct extra_classref {
+ extra_classref *next;
+ constant_classref classref;
+ };
+
+
+ /* inline functions ***********************************************************/
+
+ /**
+ * Returns the classname of the class, where slashes ('/') are
+ * replaced by dots ('.').
+ *
+ * @param c class to get name of
+ * @return classname
+ */
+ inline static java_handle_t* class_get_classname(classinfo* c)
+ {
+ java_handle_t *s;
+
+ /* Create a java string. */
+
+ s = javastring_new_slash_to_dot(c->name);
+
+ return s;
+ }
+
+
+ /* class_is_primitive **********************************************************
+
+ Checks if the given class is a primitive class.
+
+ *******************************************************************************/
+
+ static inline bool class_is_primitive(classinfo *c)
+ {
+ if (c->flags & ACC_CLASS_PRIMITIVE)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_is_anonymousclass *****************************************************
+
+ Checks if the given class is an anonymous class.
+
+ *******************************************************************************/
+
+ static inline 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.
+
+ *******************************************************************************/
+
+ static inline bool class_is_array(classinfo *c)
+ {
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return (c->vftbl->arraydesc != NULL);
+ }
+
+
+ /* class_is_interface **********************************************************
+
+ Checks if the given class is an interface.
+
+ *******************************************************************************/
+
+ static inline bool class_is_interface(classinfo *c)
+ {
+ if (c->flags & ACC_INTERFACE)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_is_localclass *********************************************************
+
+ Checks if the given class is a local class.
+
+ *******************************************************************************/
+
+ static inline 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.
+
+ *******************************************************************************/
+
+ static inline bool class_is_memberclass(classinfo *c)
+ {
+ if (c->flags & ACC_CLASS_MEMBER)
+ return true;
+
+ return false;
+ }
+
+
+ /* class_get_classloader *******************************************************
+
+ Return the classloader of the given class.
+
+ *******************************************************************************/
+
+ static inline classloader_t *class_get_classloader(classinfo *c)
+ {
+ classloader_t *cl;
+
+ cl = c->classloader;
+
+ /* The classloader may be NULL. */
+
+ return cl;
+ }
+
+
+ /* class_get_superclass ********************************************************
+
+ Return the super class of the given class.
+
+ *******************************************************************************/
+
+ static inline classinfo *class_get_superclass(classinfo *c)
+ {
+ /* For interfaces we return NULL. */
+
+ if (c->flags & ACC_INTERFACE)
+ return NULL;
+
+ /* For java/lang/Object, primitive-type and Void classes c->super
+ is NULL and we return NULL. */
+
+ return c->super;
+ }
+
+
+ /* function prototypes ********************************************************/
+
+ classinfo *class_create_classinfo(utf *u);
+ void class_postset_header_vftbl(void);
+ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd);
+ void class_set_packagename(classinfo *c);
+
+ bool class_load_attributes(classbuffer *cb);
+
+ /* retrieve constantpool element */
+ void* class_getconstant(classinfo *c, u4 pos, u4 ctype);
+ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype);
+
+ /* frees all resources used by the class */
+ void class_free(classinfo *);
+
+ /* return an array class with the given component class */
+ classinfo *class_array_of(classinfo *component,bool link);
+
+ /* return an array class with the given dimension and element class */
+ classinfo *class_multiarray_of(s4 dim, classinfo *element,bool link);
+
+ /* return a classref for the given class name */
+ /* (does a linear search!) */
+ constant_classref *class_lookup_classref(classinfo *cls,utf *name);
+
+ /* return a classref for the given class name */
+ /* (does a linear search!) */
+ constant_classref *class_get_classref(classinfo *cls,utf *name);
+
+ /* return a classref to the class itself */
+ /* (does a linear search!) */
+ constant_classref *class_get_self_classref(classinfo *cls);
+
+ /* return a classref for an array with the given dimension of with the */
+ /* given component type */
+ constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref);
+
+ /* return a classref for the component type of the given array type */
+ constant_classref *class_get_classref_component_of(constant_classref *ref);
+
+ /* get a class' field by name and descriptor */
+ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc);
+
+ /* search 'classinfo'-structure for a field with the specified name */
+ fieldinfo *class_findfield_by_name(classinfo *c, utf *name);
+
+ /* search class for a field */
+ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer);
+
+ /* search for a method with a specified name and descriptor */
+ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc);
+ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *dest);
+ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+
+ bool class_issubclass(classinfo *sub, classinfo *super);
+ bool class_isanysubclass(classinfo *sub, classinfo *super);
+ bool class_is_assignable_from(classinfo *to, classinfo *from);
+ bool class_is_instance(classinfo *c, java_handle_t *h);
+
+ classloader_t *class_get_classloader(classinfo *c);
+ classinfo *class_get_superclass(classinfo *c);
+ classinfo *class_get_componenttype(classinfo *c);
+ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly);
+ classinfo *class_get_declaringclass(classinfo *c);
+ classinfo *class_get_enclosingclass(classinfo *c);
+ java_handle_t* class_get_enclosingconstructor(classinfo *c);
+ methodinfo* class_get_enclosingmethod_raw(classinfo *c);
+ java_handle_t* class_get_enclosingmethod(classinfo *c);
+ java_handle_objectarray_t *class_get_interfaces(classinfo *c);
+ java_handle_bytearray_t *class_get_annotations(classinfo *c);
+ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib);
+ java_handle_t *class_get_name(classinfo *c);
+
+ #if defined(ENABLE_JAVASE)
+ utf *class_get_signature(classinfo *c);
+ #endif
+
+ /* some debugging functions */
+
+ #if !defined(NDEBUG)
+ void class_printflags(classinfo *c);
+ void class_print(classinfo *c);
+ void class_println(classinfo *c);
+ void class_classref_print(constant_classref *cr);
+ void class_classref_println(constant_classref *cr);
+ void class_classref_or_classinfo_print(classref_or_classinfo c);
+ void class_classref_or_classinfo_println(classref_or_classinfo c);
+ #endif
+
+ /* debug purposes */
+ void class_showmethods(classinfo *c);
+ void class_showconstantpool(classinfo *c);
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif /* _CLASS_H */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/jitcache.h"
#include "vm/jit/methodtree.h"
+#include "vm/jit/patcher-common.h"
- #include "vmcore/options.h"
-
/* code_init *******************************************************************
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
++#include "vm/jit/jitcache.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher-common.h"
superindex = super->index;
supervftbl = super->vftbl;
}
-
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
-
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
/* if class is not resolved, check which code to call */
}
M_MOV_IMM(supervftbl, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
/* if (s1 != REG_ITMP1) { */
M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_ISUB(REG_ITMP3, REG_ITMP2);
M_MOV_IMM(supervftbl, REG_ITMP3);
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
/* } */
M_CMP(REG_ITMP3, REG_ITMP2);
}
M_MOV_IMM(supervftbl, REG_ITMP2);
-
+ JITCACHE_ADD_CACHED_REF_JD(jd, CRT_CLASSINFO_VFTBL, super);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
#include "vm/jit/show.h"
#include "vm/jit/stack.h"
+#if defined(ENABLE_JITCACHE)
+# include "vm/jit/jitcache.h"
+#endif
+
+ #if defined(ENABLE_OPAGENT)
+ #include "vm/jit/oprofile-agent.hpp"
+ #endif
+
#include "vm/jit/allocator/simplereg.h"
#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
# include "vm/jit/allocator/lsra.h"
ptrint datap; /* absolute position in data segment */
s4 disp; /* displacement of ref in the data segment */
functionptr patcher; /* patcher function to call */
- voidptr ref; /* reference passed */
+ void* ref; /* reference passed */
u8 mcode; /* machine code to be patched back in */
bool done; /* XXX preliminary: patch already applied? */
+#if defined (ENABLE_JITCACHE)
+ struct cachedref_t *attached_ref;
+ /* cached reference which must be resolved *
+ * patcher has been run. */
+#endif
listnode_t linkage;
} patchref_t;
--- /dev/null
+ /* src/vm/options.c - contains global options
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <limits.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ #include "mm/memory.h"
+
+ #include "native/jni.h"
+
+ #include "vm/options.h"
+ #include "vm/os.hpp"
+ #include "vm/vm.hpp"
+
+
+ /* command line option ********************************************************/
+
+ s4 opt_index = 0; /* index of processed arguments */
+ char *opt_arg; /* this one exports the option argument */
+
+ bool opt_foo = false; /* option for development */
+
+ bool opt_jar = false;
+
+ #if defined(ENABLE_JIT)
+ bool opt_jit = true; /* JIT mode execution (default) */
+ bool opt_intrp = false; /* interpreter mode execution */
+ #else
+ bool opt_jit = false; /* JIT mode execution */
+ bool opt_intrp = true; /* interpreter mode execution (default) */
+ #endif
+
+ bool opt_run = true;
+
+ s4 opt_heapmaxsize = 0; /* maximum heap size */
+ s4 opt_heapstartsize = 0; /* initial heap size */
+ s4 opt_stacksize = 0; /* thread stack size */
+
+ bool opt_verbose = false;
+ bool opt_debugcolor = false; /* use ANSI terminal sequences */
+ bool compileall = false;
+
+ bool loadverbose = false;
+ bool initverbose = false;
+
+ bool opt_verboseclass = false;
+ bool opt_verbosegc = false;
+ bool opt_verbosejni = false;
+ bool opt_verbosecall = false; /* trace all method invocation */
+
+ bool showmethods = false;
+ bool showconstantpool = false;
+ bool showutf = false;
+
+ char *opt_method = NULL;
+ char *opt_signature = NULL;
+
+ bool compileverbose = false; /* trace compiler actions */
+ bool showstack = false;
+
+ bool opt_showdisassemble = false; /* generate disassembler listing */
+ bool opt_shownops = false;
+ bool opt_showddatasegment = false; /* generate data segment listing */
+ bool opt_showintermediate = false; /* generate intermediate code listing */
+
+ bool checkbounds = true; /* check array bounds */
+ bool opt_noieee = false; /* don't implement ieee compliant floats */
+ bool checksync = true; /* do synchronization */
+ #if defined(ENABLE_LOOP)
+ bool opt_loops = false; /* optimize array accesses in loops */
+ #endif
+
+ bool makeinitializations = true;
+
+ #if defined(ENABLE_STATISTICS)
+ bool opt_stat = false;
+ bool opt_getloadingtime = false; /* to measure the runtime */
+ bool opt_getcompilingtime = false; /* compute compile time */
+ #endif
+ #if defined(ENABLE_VERIFIER)
+ bool opt_verify = true; /* true if classfiles should be verified */
+ #endif
+
+ #if defined(ENABLE_PROFILING)
+ bool opt_prof = false;
+ bool opt_prof_bb = false;
+ #endif
+
+ #if defined(ENABLE_OPAGENT)
+ bool opt_opagent = false;
+ #endif
+
+ /* optimization options *******************************************************/
+
+ #if defined(ENABLE_IFCONV)
+ bool opt_ifconv = false;
+ #endif
+
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ bool opt_lsra = false;
+ #endif
+ #if defined(ENABLE_SSA)
+ bool opt_ssa_dce = false; /* enable dead code elemination */
+ bool opt_ssa_cp = false; /* enable copy propagation */
+ #endif
+
+
+ /* interpreter options ********************************************************/
+
+ #if defined(ENABLE_INTRP)
+ bool opt_no_dynamic = false; /* suppress dynamic superinstructions */
+ bool opt_no_replication = false; /* don't use replication in intrp */
+ bool opt_no_quicksuper = false; /* instructions for quickening cannot be
+ part of dynamic superinstructions */
+
+ s4 opt_static_supers = 0x7fffffff;
+ bool vm_debug = false; /* XXX this should be called `opt_trace' */
+ #endif
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ const char *opt_filter_verbosecall_include = 0;
+ const char *opt_filter_verbosecall_exclude = 0;
+ const char *opt_filter_show_method = 0;
+ #endif
+
+
+ /* -XX options ****************************************************************/
+
+ /* NOTE: For better readability keep these alpha-sorted. */
+
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ int64_t opt_MaxDirectMemorySize = -1;
+ int opt_MaxPermSize = 0;
+ int opt_PermSize = 0;
+ int opt_ThreadStackSize = 0;
+
+ /* Debugging options which can be turned off. */
+
+ int opt_DebugExceptions = 0;
+ int opt_DebugFinalizer = 0;
++#if defined(ENABLE_JITCACHE)
++int opt_DebugJitCache = 0;
++#endif
+ int opt_DebugLocalReferences = 0;
+ int opt_DebugLocks = 0;
+ int opt_DebugPackage = 0;
+ int opt_DebugPatcher = 0;
+ int opt_DebugProperties = 0;
+ int opt_DebugStackFrameInfo = 0;
+ int opt_DebugStackTrace = 0;
+ int opt_DebugThreads = 0;
+ #if defined(ENABLE_DISASSEMBLER)
+ int opt_DisassembleStubs = 0;
+ #endif
+ #if defined(ENABLE_OPAGENT)
+ int opt_EnableOpagent = 0;
+ #endif
+ #if defined(ENABLE_GC_CACAO)
+ int opt_GCDebugRootSet = 0;
+ int opt_GCStress = 0;
+ #endif
+ #if defined(ENABLE_INLINING)
+ int opt_Inline = 0;
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ int opt_InlineAll = 0;
+ int opt_InlineCount = INT_MAX;
+ int opt_InlineMaxSize = INT_MAX;
+ int opt_InlineMinSize = 0;
+ #endif
+ #endif
+ int opt_PrintConfig = 0;
+ int opt_ProfileGCMemoryUsage = 0;
+ int opt_ProfileMemoryUsage = 0;
+ FILE *opt_ProfileMemoryUsageGNUPlot = NULL;
+ #if defined(ENABLE_REPLACEMENT)
+ int opt_TestReplacement = 0;
+ #endif
+ int opt_TraceCompilerCalls = 0;
+ int opt_TraceExceptions = 0;
+ int opt_TraceHPI = 0;
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ int opt_TraceInlining = 0;
+ #endif
+ int opt_TraceJavaCalls = 0;
+ int opt_TraceJNICalls = 0;
+ int opt_TraceJVMCalls = 0;
+ int opt_TraceJVMCallsVerbose = 0;
+ int opt_TraceLinkClass = 0;
+ #if defined(ENABLE_REPLACEMENT)
+ int opt_TraceReplacement = 0;
+ #endif
+ int opt_TraceSubsystemInitialization = 0;
+ int opt_TraceTraps = 0;
+
+
+ enum {
+ OPT_TYPE_BOOLEAN,
+ OPT_TYPE_VALUE
+ };
+
+ enum {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ OPT_MaxDirectMemorySize,
+ OPT_MaxPermSize,
+ OPT_PermSize,
+ OPT_ThreadStackSize,
+
+ /* Debugging options which can be turned off. */
+
+ OPT_DebugExceptions,
+ OPT_DebugFinalizer,
++ OPT_DebugJitCache,
+ OPT_DebugLocalReferences,
+ OPT_DebugLocks,
+ OPT_DebugPackage,
+ OPT_DebugPatcher,
+ OPT_DebugProperties,
+ OPT_DebugStackFrameInfo,
+ OPT_DebugStackTrace,
+ OPT_DebugThreads,
+ OPT_DisassembleStubs,
+ OPT_EnableOpagent,
+ OPT_GCDebugRootSet,
+ OPT_GCStress,
+ OPT_Inline,
+ OPT_InlineAll,
+ OPT_InlineCount,
+ OPT_InlineMaxSize,
+ OPT_InlineMinSize,
+ OPT_PrintConfig,
+ OPT_ProfileGCMemoryUsage,
+ OPT_ProfileMemoryUsage,
+ OPT_ProfileMemoryUsageGNUPlot,
+ OPT_TestReplacement,
+ OPT_TraceCompilerCalls,
+ OPT_TraceExceptions,
+ OPT_TraceHPI,
+ OPT_TraceInlining,
+ OPT_TraceJavaCalls,
+ OPT_TraceJNICalls,
+ OPT_TraceJVMCalls,
+ OPT_TraceJVMCallsVerbose,
+ OPT_TraceLinkClass,
+ OPT_TraceReplacement,
+ OPT_TraceSubsystemInitialization,
+ OPT_TraceTraps,
+ OPT_Vmlog,
+ OPT_VmlogStrings,
+ OPT_VmlogIgnore
+ };
+
+
+ option_t options_XX[] = {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ { "MaxDirectMemorySize", OPT_MaxDirectMemorySize, OPT_TYPE_VALUE, "Maximum total size of NIO direct-buffer allocations" },
+ { "MaxPermSize", OPT_MaxPermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "PermSize", OPT_PermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "ThreadStackSize", OPT_ThreadStackSize, OPT_TYPE_VALUE, "TODO" },
+
+ /* Debugging options which can be turned off. */
+
+ { "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
+ { "DebugFinalizer", OPT_DebugFinalizer, OPT_TYPE_BOOLEAN, "debug finalizer thread" },
++#if defined (ENABLE_JITCACHE)
++ { "DebugJitCache", OPT_DebugJitCache, OPT_TYPE_BOOLEAN, "debug JIT cache actions" },
++#endif
+ { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
+ { "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
+ { "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
+ { "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
+ { "DebugProperties", OPT_DebugProperties, OPT_TYPE_BOOLEAN, "print debug information for properties" },
+ { "DebugStackFrameInfo", OPT_DebugStackFrameInfo, OPT_TYPE_BOOLEAN, "TODO" },
+ { "DebugStackTrace", OPT_DebugStackTrace, OPT_TYPE_BOOLEAN, "debug stacktrace creation" },
+ { "DebugThreads", OPT_DebugThreads, OPT_TYPE_BOOLEAN, "print debug information for threads" },
+ #if defined(ENABLE_DISASSEMBLER)
+ { "DisassembleStubs", OPT_DisassembleStubs, OPT_TYPE_BOOLEAN, "disassemble builtin and native stubs when generated" },
+ #endif
+ #if defined(ENABLE_OPAGENT)
+ { "EnableOpagent", OPT_EnableOpagent, OPT_TYPE_BOOLEAN, "enable providing JIT output to Oprofile" },
+ #endif
+ #if defined(ENABLE_GC_CACAO)
+ { "GCDebugRootSet", OPT_GCDebugRootSet, OPT_TYPE_BOOLEAN, "GC: print root-set at collection" },
+ { "GCStress", OPT_GCStress, OPT_TYPE_BOOLEAN, "GC: forced collection at every allocation" },
+ #endif
+ #if defined(ENABLE_INLINING)
+ { "Inline", OPT_Inline, OPT_TYPE_BOOLEAN, "enable method inlining" },
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ { "InlineAll", OPT_InlineAll, OPT_TYPE_BOOLEAN, "use inlining in all compilations" },
+ { "InlineCount", OPT_InlineCount, OPT_TYPE_VALUE, "stop inlining after the given number of roots" },
+ { "InlineMaxSize", OPT_InlineMaxSize, OPT_TYPE_VALUE, "maximum size for inlined result" },
+ { "InlineMinSize", OPT_InlineMinSize, OPT_TYPE_VALUE, "minimum size for inlined result" },
+ #endif
+ #endif
+ { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" },
+ { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, <value> is in seconds (default: 5)" },
+ { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" },
+ { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" },
+ #if defined(ENABLE_REPLACEMENT)
+ { "TestReplacement", OPT_TestReplacement, OPT_TYPE_BOOLEAN, "activate all replacement points during code generation" },
+ #endif
+ { "TraceCompilerCalls", OPT_TraceCompilerCalls, OPT_TYPE_BOOLEAN, "trace JIT compiler calls" },
+ { "TraceExceptions", OPT_TraceExceptions, OPT_TYPE_BOOLEAN, "trace Exception throwing" },
+ { "TraceHPI", OPT_TraceHPI, OPT_TYPE_BOOLEAN, "Trace Host Porting Interface (HPI)" },
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ { "TraceInlining", OPT_TraceInlining, OPT_TYPE_VALUE, "trace method inlining with the given verbosity level (default: 1)" },
+ #endif
+ #if !defined(ENABLE_VMLOG)
+ { "TraceJavaCalls", OPT_TraceJavaCalls, OPT_TYPE_BOOLEAN, "trace Java method calls" },
+ #endif
+ { "TraceJNICalls", OPT_TraceJNICalls, OPT_TYPE_BOOLEAN, "trace JNI method calls" },
+ { "TraceJVMCalls", OPT_TraceJVMCalls, OPT_TYPE_BOOLEAN, "trace JVM method calls but omit very frequent ones" },
+ { "TraceJVMCallsVerbose", OPT_TraceJVMCallsVerbose, OPT_TYPE_BOOLEAN, "trace all JVM method calls" },
+ { "TraceLinkClass", OPT_TraceLinkClass, OPT_TYPE_BOOLEAN, "trace class linking" },
+ #if defined(ENABLE_REPLACEMENT)
+ { "TraceReplacement", OPT_TraceReplacement, OPT_TYPE_VALUE, "trace on-stack replacement with the given verbosity level (default: 1)" },
+ #endif
+ { "TraceSubsystemInitialization", OPT_TraceSubsystemInitialization, OPT_TYPE_BOOLEAN, "trace initialization of subsystems" },
+ { "TraceTraps", OPT_TraceTraps, OPT_TYPE_BOOLEAN, "trace traps generated by JIT code" },
+ #if defined(ENABLE_VMLOG)
+ { "Vmlog", OPT_Vmlog, OPT_TYPE_VALUE, "prefix for vmlog trace files (enables vmlog)" },
+ { "VmlogStrings", OPT_VmlogStrings, OPT_TYPE_VALUE, "prefix of vmlog string file to load" },
+ { "VmlogIgnore", OPT_VmlogIgnore, OPT_TYPE_VALUE, "prefix of vmlog ignore file to load" },
+ #endif
+
+ /* end marker */
+
+ { NULL, -1, -1, NULL }
+ };
+
+
+ /* options_get *****************************************************************
+
+ DOCUMENT ME!!!
+
+ *******************************************************************************/
+
+ int options_get(opt_struct *opts, JavaVMInitArgs *vm_args)
+ {
+ char *option;
+ int i;
+
+ if (opt_index >= vm_args->nOptions)
+ return OPT_DONE;
+
+ /* get the current option */
+
+ option = vm_args->options[opt_index].optionString;
+
+ if ((option == NULL) || (option[0] != '-'))
+ return OPT_DONE;
+
+ for (i = 0; opts[i].name; i++) {
+ if (!opts[i].arg) {
+ /* boolean option found */
+
+ if (strcmp(option + 1, opts[i].name) == 0) {
+ opt_index++;
+ return opts[i].value;
+ }
+
+ } else {
+ /* parameter option found */
+
+ /* with a space between */
+
+ if (strcmp(option + 1, opts[i].name) == 0) {
+ opt_index++;
+
+ if (opt_index < vm_args->nOptions) {
+ opt_arg = os_strdup(vm_args->options[opt_index].optionString);
+ opt_index++;
+ return opts[i].value;
+ }
+
+ return OPT_ERROR;
+
+ } else {
+ /* parameter and option have no space between */
+
+ /* FIXME: this assumption is plain wrong, hits you if there is a
+ * parameter with no argument starting with same letter as param with argument
+ * but named after that one, ouch! */
+
+ size_t l = os_strlen(opts[i].name);
+
+ if (os_strlen(option + 1) > l) {
+ if (memcmp(option + 1, opts[i].name, l) == 0) {
+ opt_index++;
+ opt_arg = os_strdup(option + 1 + l);
+ return opts[i].value;
+ }
+ }
+ }
+ }
+ }
+
+ return OPT_ERROR;
+ }
+
+
+ /* options_xxusage *************************************************************
+
+ Print usage message for debugging options.
+
+ *******************************************************************************/
+
+ static void options_xxusage(void)
+ {
+ option_t *opt;
+ int length;
+ int i;
+ const char *c;
+
+ /* Prevent compiler warning. */
+
+ length = 0;
+
+ for (opt = options_XX; opt->name != NULL; opt++) {
+ printf(" -XX:");
+
+ switch (opt->type) {
+ case OPT_TYPE_BOOLEAN:
+ printf("+%s", opt->name);
+ length = os_strlen(" -XX:+") + os_strlen(opt->name);
+ break;
+
+ case OPT_TYPE_VALUE:
+ printf("%s=<value>", opt->name);
+ length = os_strlen(" -XX:") + os_strlen(opt->name) +
+ os_strlen("=<value>");
+ break;
+
+ default:
+ vm_abort("options_xxusage: unkown option type %d", opt->type);
+ }
+
+ /* Check if the help fits into one 80-column line.
+ Documentation starts at column 29. */
+
+ if (length < (29 - 1)) {
+ /* Print missing spaces up to column 29. */
+
+ for (i = length; i < 29; i++)
+ printf(" ");
+ }
+ else {
+ printf("\n");
+ printf(" "); /* 29 spaces */
+ }
+
+ /* Check documentation length. */
+
+ length = os_strlen(opt->doc);
+
+ if (length < (80 - 29)) {
+ printf("%s", opt->doc);
+ }
+ else {
+ for (c = opt->doc, i = 29; *c != 0; c++, i++) {
+ /* If we are at the end of the line, break it. */
+
+ if (i == 80) {
+ printf("\n");
+ printf(" "); /* 29 spaces */
+ i = 29;
+ }
+
+ printf("%c", *c);
+ }
+ }
+
+ printf("\n");
+ }
+
+ /* exit with error code */
+
+ exit(1);
+ }
+
+
+ /* options_xx ******************************************************************
+
+ Handle -XX: options.
+
+ *******************************************************************************/
+
+ void options_xx(JavaVMInitArgs *vm_args)
+ {
+ const char *name;
+ const char *start;
+ char *end;
+ int length;
+ int enable;
+ char *value;
+ option_t *opt;
+ char *filename;
+ FILE *file;
+ int i;
+
+ /* Iterate over all passed options. */
+
+ for (i = 0; i < vm_args->nOptions; i++) {
+ /* Get the current option. */
+
+ name = vm_args->options[i].optionString;
+
+ /* Check for help (-XX). */
+
+ if (strcmp(name, "-XX") == 0)
+ options_xxusage();
+
+ /* Check if the option start with -XX. */
+
+ start = strstr(name, "-XX:");
+
+ if ((start == NULL) || (start != name))
+ continue;
+
+ /* Check if the option is a boolean option. */
+
+ if (name[4] == '+') {
+ start = name + 4 + 1;
+ enable = 1;
+ }
+ else if (name[4] == '-') {
+ start = name + 4 + 1;
+ enable = 0;
+ }
+ else {
+ start = name + 4;
+ enable = -1;
+ }
+
+ /* Search for a '=' in the option name and get the option name
+ length and the value of the option. */
+
+ end = strchr(start, '=');
+
+ if (end == NULL) {
+ length = os_strlen(start);
+ value = NULL;
+ }
+ else {
+ length = end - start;
+ value = end + 1;
+ }
+
+ /* Search the option in the option array. */
+
+ for (opt = options_XX; opt->name != NULL; opt++) {
+ if (strncmp(opt->name, start, length) == 0) {
+ /* Check if the options passed fits to the type. */
+
+ switch (opt->type) {
+ case OPT_TYPE_BOOLEAN:
+ if ((enable == -1) || (value != NULL))
+ options_xxusage();
+ break;
+ case OPT_TYPE_VALUE:
+ if ((enable != -1) || (value == NULL))
+ options_xxusage();
+ break;
+ default:
+ vm_abort("options_xx: unknown option type %d for option %s",
+ opt->type, opt->name);
+ }
+
+ break;
+ }
+ }
+
+ /* Process the option. */
+
+ switch (opt->value) {
+
+ /* Options which must always be available (production options
+ in HotSpot). */
+
+ case OPT_MaxDirectMemorySize:
+ opt_MaxDirectMemorySize = os_atoi(value);
+ break;
+
+ case OPT_MaxPermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_PermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_ThreadStackSize:
+ /* currently ignored */
+ break;
+
+ /* Debugging options which can be turned off. */
+
+ case OPT_DebugExceptions:
+ opt_DebugExceptions = enable;
+ break;
+
+ case OPT_DebugFinalizer:
+ opt_DebugFinalizer = enable;
+ break;
+
++#if defined(ENABLE_JITCACHE)
++ case OPT_DebugJitCache:
++ opt_DebugJitCache = enable;
++ break;
++#endif
++
+ case OPT_DebugLocalReferences:
+ opt_DebugLocalReferences = enable;
+ break;
+
+ case OPT_DebugLocks:
+ opt_DebugLocks = enable;
+ break;
+
+ case OPT_DebugPackage:
+ opt_DebugPackage = enable;
+ break;
+
+ case OPT_DebugPatcher:
+ opt_DebugPatcher = enable;
+ break;
+
+ case OPT_DebugProperties:
+ opt_DebugProperties = enable;
+ break;
+
+ case OPT_DebugStackFrameInfo:
+ opt_DebugStackFrameInfo = enable;
+ break;
+
+ case OPT_DebugStackTrace:
+ opt_DebugStackTrace = enable;
+ break;
+
+ case OPT_DebugThreads:
+ opt_DebugThreads = enable;
+ break;
+
+ #if defined(ENABLE_DISASSEMBLER)
+ case OPT_DisassembleStubs:
+ opt_DisassembleStubs = enable;
+ break;
+ #endif
+
+ #if defined(ENABLE_OPAGENT)
+ case OPT_EnableOpagent:
+ opt_EnableOpagent = enable;
+ break;
+ #endif
+
+ #if defined(ENABLE_GC_CACAO)
+ case OPT_GCDebugRootSet:
+ opt_GCDebugRootSet = enable;
+ break;
+
+ case OPT_GCStress:
+ opt_GCStress = enable;
+ break;
+ #endif
+
+ #if defined(ENABLE_INLINING)
+ case OPT_Inline:
+ opt_Inline = enable;
+ break;
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ case OPT_InlineAll:
+ opt_InlineAll = enable;
+ break;
+
+ case OPT_InlineCount:
+ if (value != NULL)
+ opt_InlineCount = os_atoi(value);
+ break;
+
+ case OPT_InlineMaxSize:
+ if (value != NULL)
+ opt_InlineMaxSize = os_atoi(value);
+ break;
+
+ case OPT_InlineMinSize:
+ if (value != NULL)
+ opt_InlineMinSize = os_atoi(value);
+ break;
+ #endif
+ #endif
+
+ case OPT_PrintConfig:
+ opt_PrintConfig = enable;
+ break;
+
+ case OPT_ProfileGCMemoryUsage:
+ if (value == NULL)
+ opt_ProfileGCMemoryUsage = 5;
+ else
+ opt_ProfileGCMemoryUsage = os_atoi(value);
+ break;
+
+ case OPT_ProfileMemoryUsage:
+ if (value == NULL)
+ opt_ProfileMemoryUsage = 5;
+ else
+ opt_ProfileMemoryUsage = os_atoi(value);
+
+ # if defined(ENABLE_STATISTICS)
+ /* we also need statistics */
+
+ opt_stat = true;
+ # endif
+ break;
+
+ case OPT_ProfileMemoryUsageGNUPlot:
+ if (value == NULL)
+ filename = "profile.dat";
+ else
+ filename = value;
+
+ file = fopen(filename, "w");
+
+ if (file == NULL)
+ vm_abort_errno("options_xx: fopen failed");
+
+ opt_ProfileMemoryUsageGNUPlot = file;
+ break;
+
+ #if defined(ENABLE_REPLACEMENT)
+ case OPT_TestReplacement:
+ opt_TestReplacement = enable;
+ break;
+ #endif
+
+ case OPT_TraceCompilerCalls:
+ opt_TraceCompilerCalls = enable;
+ break;
+
+ case OPT_TraceExceptions:
+ opt_TraceExceptions = enable;
+ break;
+
+ case OPT_TraceHPI:
+ opt_TraceHPI = enable;
+ break;
+
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ case OPT_TraceInlining:
+ if (value == NULL)
+ opt_TraceInlining = 1;
+ else
+ opt_TraceInlining = os_atoi(value);
+ break;
+ #endif
+
+ case OPT_TraceJavaCalls:
+ opt_verbosecall = enable;
+ opt_TraceJavaCalls = enable;
+ break;
+
+ case OPT_TraceJNICalls:
+ opt_TraceJNICalls = enable;
+ break;
+
+ case OPT_TraceJVMCalls:
+ opt_TraceJVMCalls = enable;
+ break;
+
+ case OPT_TraceJVMCallsVerbose:
+ opt_TraceJVMCallsVerbose = enable;
+ break;
+
+ case OPT_TraceLinkClass:
+ opt_TraceLinkClass = enable;
+ break;
+
+ #if defined(ENABLE_REPLACEMENT)
+ case OPT_TraceReplacement:
+ if (value == NULL)
+ opt_TraceReplacement = 1;
+ else
+ opt_TraceReplacement = os_atoi(value);
+ break;
+ #endif
+
+ case OPT_TraceSubsystemInitialization:
+ opt_TraceSubsystemInitialization = enable;
+ break;
+
+ case OPT_TraceTraps:
+ opt_TraceTraps = enable;
+ break;
+
+ #if defined(ENABLE_VMLOG)
+ case OPT_Vmlog:
+ if (value == NULL)
+ vmlog_cacao_set_prefix("vmlog");
+ else
+ vmlog_cacao_set_prefix(value);
+ opt_verbosecall = 1;
+ opt_TraceJavaCalls = 1;
+ break;
+
+ case OPT_VmlogStrings:
+ if (value != NULL)
+ vmlog_cacao_set_stringprefix(value);
+ break;
+
+ case OPT_VmlogIgnore:
+ if (value != NULL)
+ vmlog_cacao_set_ignoreprefix(value);
+ break;
+ #endif
+
+ default:
+ printf("Unknown -XX option: %s\n", name);
+ break;
+ }
+ }
+ }
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+ /* src/vm/options.h - define global options extern
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _OPTIONS_H
+ #define _OPTIONS_H
+
+ #include "config.h"
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #include <stdint.h>
+
+ #include "vm/types.h"
+
+ #include "native/jni.h"
+
+ #include "vm/global.h"
+
+
+ /* reserved option numbers ****************************************************/
+
+ /* define these negative since the other options are an enum */
+
+ #define OPT_DONE -1
+ #define OPT_ERROR -2
+ #define OPT_IGNORE -3
+
+
+ typedef struct opt_struct opt_struct;
+
+ struct opt_struct {
+ const char *name;
+ bool arg;
+ int value;
+ };
+
+
+ typedef struct option_t option_t;
+
+ struct option_t {
+ const char *name;
+ int value;
+ int type;
+ const char *doc;
+ };
+
+
+ /* global variables ***********************************************************/
+
+ extern s4 opt_index;
+ extern char *opt_arg;
+
+ extern bool opt_foo;
+
+ extern bool opt_jit;
+ extern bool opt_intrp;
+
+ extern bool opt_jar;
+ extern bool opt_run;
+
+ extern s4 opt_heapmaxsize;
+ extern s4 opt_heapstartsize;
+ extern s4 opt_stacksize;
+
+ extern bool opt_verbose;
+ extern bool opt_debugcolor;
+ extern bool compileall;
+
+ extern bool loadverbose; /* Print debug messages during loading */
+ extern bool initverbose; /* Log class initialization */
+
+ extern bool opt_verboseclass;
+ extern bool opt_verbosegc;
+ extern bool opt_verbosejni;
+ extern bool opt_verbosecall;
+
+ extern bool showmethods;
+ extern bool showconstantpool;
+ extern bool showutf;
+
+ extern char *opt_method;
+ extern char *opt_signature;
+
+ extern bool compileverbose;
+ extern bool showstack;
+
+ extern bool opt_showdisassemble;
+ extern bool opt_shownops;
+ extern bool opt_showddatasegment;
+ extern bool opt_showintermediate;
+
+ extern bool checkbounds;
+ extern bool opt_noieee;
+ extern bool checksync;
+ #if defined(ENABLE_LOOP)
+ extern bool opt_loops;
+ #endif
+
+ extern bool makeinitializations;
+
+ #if defined(ENABLE_STATISTICS)
+ extern bool opt_stat;
+ extern bool opt_getloadingtime;
+ extern bool opt_getcompilingtime;
+ #endif
+ #if defined(ENABLE_VERIFIER)
+ extern bool opt_verify;
+ #endif
+
+ #if defined(ENABLE_PROFILING)
+ extern bool opt_prof;
+ extern bool opt_prof_bb;
+ #endif
+
+ /* optimization options *******************************************************/
+
+ #if defined(ENABLE_IFCONV)
+ extern bool opt_ifconv;
+ #endif
+
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ extern bool opt_lsra;
+ #endif
+ #if defined(ENABLE_SSA)
+ extern bool opt_ssa_dce; /* enable dead code elemination */
+ extern bool opt_ssa_cp; /* enable copy propagation */
+ #endif
+
+ /* interpreter options ********************************************************/
+
+ #if defined(ENABLE_INTRP)
+ extern bool opt_no_dynamic;
+ extern bool opt_no_replication;
+ extern bool opt_no_quicksuper;
+
+ extern s4 opt_static_supers;
+ extern bool vm_debug;
+ #endif
+
+ /* debug output filtering options *********************************************/
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ extern const char *opt_filter_verbosecall_include;
+ extern const char *opt_filter_verbosecall_exclude;
+ extern const char *opt_filter_show_method;
+ #endif
+
+
+ /* -XX options ****************************************************************/
+
+ /* NOTE: For better readability keep these alpha-sorted. */
+
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ extern int64_t opt_MaxDirectMemorySize;
+ extern int opt_MaxPermSize;
+ extern int opt_PermSize;
+ extern int opt_ThreadStackSize;
+
+ /* Debugging options which can be turned off. */
+
+ extern int opt_DebugExceptions;
+ extern int opt_DebugFinalizer;
++#if defined(ENABLE_JITCACHE)
++extern int opt_DebugJitCache;
++#endif
+ extern int opt_DebugLocalReferences;
+ extern int opt_DebugLocks;
+ extern int opt_DebugPatcher;
+ extern int opt_DebugPackage;
+ extern int opt_DebugProperties;
+ extern int opt_DebugStackFrameInfo;
+ extern int opt_DebugStackTrace;
+ extern int opt_DebugThreads;
+ #if defined(ENABLE_DISASSEMBLER)
+ extern int opt_DisassembleStubs;
+ #endif
+ #if defined(ENABLE_OPAGENT)
+ extern int opt_EnableOpagent;
+ #endif
+ #if defined(ENABLE_GC_CACAO)
+ extern int opt_GCDebugRootSet;
+ extern int opt_GCStress;
+ #endif
+ #if defined(ENABLE_INLINING)
+ extern int opt_Inline;
+ #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ extern int opt_InlineAll;
+ extern int opt_InlineCount;
+ extern int opt_InlineMaxSize;
+ extern int opt_InlineMinSize;
+ #endif
+ #endif
+ extern int opt_PrintConfig;
+ extern int opt_ProfileGCMemoryUsage;
+ extern int opt_ProfileMemoryUsage;
+ extern FILE *opt_ProfileMemoryUsageGNUPlot;
+ #if defined(ENABLE_REPLACEMENT)
+ extern int opt_TestReplacement;
+ #endif
+ extern int opt_TraceCompilerCalls;
+ extern int opt_TraceExceptions;
+ extern int opt_TraceHPI;
+ #if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ extern int opt_TraceInlining;
+ #endif
+ extern int opt_TraceJavaCalls;
+ extern int opt_TraceJNICalls;
+ extern int opt_TraceJVMCalls;
+ extern int opt_TraceJVMCallsVerbose;
+ extern int opt_TraceLinkClass;
+ #if defined(ENABLE_REPLACEMENT)
+ extern int opt_TraceReplacement;
+ #endif
+ extern int opt_TraceSubsystemInitialization;
+ extern int opt_TraceTraps;
+
+
+ /* function prototypes ********************************************************/
+
+ int options_get(opt_struct *opts, JavaVMInitArgs *vm_args);
+ void options_xx(JavaVMInitArgs *vm_args);
+
+
+ /* debug **********************************************************************/
+
+ #if !defined(NDEBUG)
+ # define TRACESUBSYSTEMINITIALIZATION(text) \
+ do { \
+ if (opt_TraceSubsystemInitialization) { \
+ log_println("[Initializing subsystem: %s]", text); \
+ } \
+ } while (0)
+ #else
+ # define TRACESUBSYSTEMINITIALIZATION(text)
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif /* _OPTIONS_H */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+ /* src/vm/os.hpp - system (OS) functions
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _OS_HPP
+ #define _OS_HPP
+
+ #include "config.h"
+
+ /* NOTE: In this file we check for all system headers, because we wrap
+ all system calls into inline functions for better portability. */
+
+ #if defined(HAVE_DIRENT_H)
+ # include <dirent.h>
+ #endif
+
+ #if defined(HAVE_DLFCN_H)
+ # include <dlfcn.h>
+ #endif
+
+ #if defined(HAVE_ERRNO_H)
+ # include <errno.h>
+ #endif
+
+ #if defined(HAVE_FCNTL_H)
+ # include <fcntl.h>
+ #endif
+
+ #if defined(ENABLE_JRE_LAYOUT)
+ # if defined(HAVE_LIBGEN_H)
+ # include <libgen.h>
+ # endif
+ #endif
+
+ #if defined(HAVE_SIGNAL_H)
+ # include <signal.h>
+ #endif
+
+ #if defined(HAVE_STDINT_H)
+ # include <stdint.h>
+ #endif
+
+ #if defined(HAVE_STDIO_H)
+ # include <stdio.h>
+ #endif
+
+ #if defined(HAVE_STDLIB_H)
+ # include <stdlib.h>
+ #endif
+
+ #if defined(HAVE_STRING_H)
+ # include <string.h>
+ #endif
+
+ #if defined(HAVE_UNISTD_H)
+ # include <unistd.h>
+ #endif
+
+ #if defined(HAVE_SYS_MMAN_H)
+ # include <sys/mman.h>
+ #endif
+
+ #if defined(HAVE_SYS_SOCKET_H)
+ # include <sys/socket.h>
+ #endif
+
+ #if defined(HAVE_SYS_STAT_H)
+ # include <sys/stat.h>
+ #endif
+
+ #if defined(HAVE_SYS_TYPES_H)
+ # include <sys/types.h>
+ #endif
+
+
+ #ifdef __cplusplus
+
+ // Class wrapping system (OS) functions.
+ class os {
+ public:
+ // Inline functions.
+ static inline void abort();
+ static inline int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
+ static inline int access(const char *pathname, int mode);
+ static inline int atoi(const char* nptr);
+ static inline void* calloc(size_t nmemb, size_t size);
+ static inline int close(int fd);
+ static inline int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
+ #if defined(ENABLE_JRE_LAYOUT)
+ static inline char* dirname(char* path);
+ #endif
+ static inline int dlclose(void* handle);
+ static inline char* dlerror(void);
+ static inline void* dlopen(const char* filename, int flag);
+ static inline void* dlsym(void* handle, const char* symbol);
+ static inline int fclose(FILE* fp);
+ static inline FILE* fopen(const char* path, const char* mode);
+ static inline size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+ static inline void free(void* ptr);
+ static inline int gethostname(char* name, size_t len);
+ static inline int getpagesize(void);
+ static inline int getsockname(int s, struct sockaddr* name, socklen_t* namelen);
+ static inline int getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen);
+ static inline int listen(int sockfd, int backlog);
+ static inline void* malloc(size_t size);
+ static inline void* memcpy(void* dest, const void* src, size_t n);
+ static inline void* memset(void* s, int c, size_t n);
+ static inline int mprotect(void* addr, size_t len, int prot);
+ static inline int scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
+ static inline int setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen);
+ static inline int shutdown(int s, int how);
+ static inline int socket(int domain, int type, int protocol);
+ static inline int stat(const char* path, struct stat* buf);
+ #if defined(__SOLARIS__)
+ static inline int str2sig(const char* str, int* signum);
+ #endif
+ static inline char* strcat(char* dest, const char* src);
+ static inline char* strcpy(char* dest, const char* src);
+ static inline char* strdup(const char* s);
+ static inline size_t strlen(const char* s);
+ static inline char* strerror(int errnum);
+
+ static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
+ static int processors_online(void);
+ };
+
+
+ inline void os::abort(void)
+ {
+ #if defined(HAVE_ABORT)
+ ::abort();
+ #else
+ # error abort not available
+ #endif
+ }
+
+ inline int os::accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
+ {
+ #if defined(HAVE_ACCEPT)
+ return ::accept(sockfd, addr, addrlen);
+ #else
+ # error accept not available
+ #endif
+ }
+
+ inline int os::access(const char* pathname, int mode)
+ {
+ #if defined(HAVE_ACCESS)
+ return ::access(pathname, mode);
+ #else
+ # error access not available
+ #endif
+ }
+
+ inline int os::atoi(const char* nptr)
+ {
+ #if defined(HAVE_ATOI)
+ return ::atoi(nptr);
+ #else
+ # error atoi not available
+ #endif
+ }
+
+ inline void* os::calloc(size_t nmemb, size_t size)
+ {
+ #if defined(HAVE_CALLOC)
+ return ::calloc(nmemb, size);
+ #else
+ # error calloc not available
+ #endif
+ }
+
+ inline int os::close(int fd)
+ {
+ #if defined(HAVE_CLOSE)
+ return ::close(fd);
+ #else
+ # error close not available
+ #endif
+ }
+
+ inline int os::connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)
+ {
+ #if defined(HAVE_CONNECT)
+ return ::connect(sockfd, serv_addr, addrlen);
+ #else
+ # error connect not available
+ #endif
+ }
+
+ #if defined(ENABLE_JRE_LAYOUT)
+ inline char* os::dirname(char* path)
+ {
+ #if defined(HAVE_DIRNAME)
+ return ::dirname(path);
+ #else
+ # error dirname not available
+ #endif
+ }
+ #endif
+
+ inline int os::dlclose(void* handle)
+ {
+ #if defined(HAVE_DLCLOSE)
+ return ::dlclose(handle);
+ #else
+ # error dlclose not available
+ #endif
+ }
+
+ inline char* os::dlerror(void)
+ {
+ #if defined(HAVE_DLERROR)
+ return ::dlerror();
+ #else
+ # error dlerror not available
+ #endif
+ }
+
+ inline void* os::dlopen(const char* filename, int flag)
+ {
+ #if defined(HAVE_DLOPEN)
+ return ::dlopen(filename, flag);
+ #else
+ # error dlopen not available
+ #endif
+ }
+
+ inline void* os::dlsym(void* handle, const char* symbol)
+ {
+ #if defined(HAVE_DLSYM)
+ return ::dlsym(handle, symbol);
+ #else
+ # error dlsym not available
+ #endif
+ }
+
+ inline int os::fclose(FILE* fp)
+ {
+ #if defined(HAVE_FCLOSE)
+ return ::fclose(fp);
+ #else
+ # error fclose not available
+ #endif
+ }
+
+ inline FILE* os::fopen(const char* path, const char* mode)
+ {
+ #if defined(HAVE_FOPEN)
+ return ::fopen(path, mode);
+ #else
+ # error fopen not available
+ #endif
+ }
+
+ inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
+ {
+ #if defined(HAVE_FREAD)
+ return ::fread(ptr, size, nmemb, stream);
+ #else
+ # error fread not available
+ #endif
+ }
+
++inline static int system_fseek(FILE *stream, off_t offset, int whence)
++{
++#if defined(HAVE_FSEEK)
++ return fseek(stream, offset, whence);
++#else
++# error fseek not available
++#endif
++}
++
+ inline void os::free(void* ptr)
+ {
+ #if defined(HAVE_FREE)
+ ::free(ptr);
+ #else
+ # error free not available
+ #endif
+ }
+
+ inline static int system_fsync(int fd)
+ {
+ #if defined(HAVE_FSYNC)
+ return fsync(fd);
+ #else
+ # error fsync not available
+ #endif
+ }
+
+ inline static int system_ftruncate(int fd, off_t length)
+ {
+ #if defined(HAVE_FTRUNCATE)
+ return ftruncate(fd, length);
+ #else
+ # error ftruncate not available
+ #endif
+ }
+
+ inline int os::gethostname(char* name, size_t len)
+ {
+ #if defined(HAVE_GETHOSTNAME)
+ return ::gethostname(name, len);
+ #else
+ # error gethostname not available
+ #endif
+ }
+
+ inline int os::getpagesize(void)
+ {
+ #if defined(HAVE_GETPAGESIZE)
+ return ::getpagesize();
+ #else
+ # error getpagesize not available
+ #endif
+ }
+
+ inline int os::getsockname(int s, struct sockaddr* name, socklen_t* namelen)
+ {
+ #if defined(HAVE_GETSOCKNAME)
+ return ::getsockname(s, name, namelen);
+ #else
+ # error getsockname not available
+ #endif
+ }
+
+ inline int os::getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen)
+ {
+ #if defined(HAVE_GETSOCKOPT)
+ return ::getsockopt(s, level, optname, optval, optlen);
+ #else
+ # error getsockopt not available
+ #endif
+ }
+
+ inline int os::listen(int sockfd, int backlog)
+ {
+ #if defined(HAVE_LISTEN)
+ return ::listen(sockfd, backlog);
+ #else
+ # error listen not available
+ #endif
+ }
+
+ inline static off_t system_lseek(int fildes, off_t offset, int whence)
+ {
+ #if defined(HAVE_LSEEK)
+ return lseek(fildes, offset, whence);
+ #else
+ # error lseek not available
+ #endif
+ }
+
+ inline void* os::malloc(size_t size)
+ {
+ #if defined(HAVE_MALLOC)
+ return ::malloc(size);
+ #else
+ # error malloc not available
+ #endif
+ }
+
+ inline void* os::memcpy(void* dest, const void* src, size_t n)
+ {
+ #if defined(HAVE_MEMCPY)
+ return ::memcpy(dest, src, n);
+ #else
+ # error memcpy not available
+ #endif
+ }
+
+ inline void* os::memset(void* s, int c, size_t n)
+ {
+ #if defined(HAVE_MEMSET)
+ return ::memset(s, c, n);
+ #else
+ # error memset not available
+ #endif
+ }
+
+ inline int os::mprotect(void* addr, size_t len, int prot)
+ {
+ #if defined(HAVE_MPROTECT)
+ return ::mprotect(addr, len, prot);
+ #else
+ # error mprotect not available
+ #endif
+ }
+
+ inline static int system_open(const char *pathname, int flags, mode_t mode)
+ {
+ #if defined(HAVE_OPEN)
+ return open(pathname, flags, mode);
+ #else
+ # error open not available
+ #endif
+ }
+
+ inline static ssize_t system_read(int fd, void *buf, size_t count)
+ {
+ #if defined(HAVE_READ)
+ return read(fd, buf, count);
+ #else
+ # error read not available
+ #endif
+ }
+
+ inline static void *system_realloc(void *ptr, size_t size)
+ {
+ #if defined(HAVE_REALLOC)
+ return realloc(ptr, size);
+ #else
+ # error realloc not available
+ #endif
+ }
+
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
+ /*
+ #elif defined(__SOLARIS__)
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
+ #elif defined(__IRIX__)
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(dirent_t *), int(*compar)(dirent_t **, dirent_t **))
+ #else
+ inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(struct dirent *), int(*compar)(const void *, const void *))
+ #endif
+ */
+ {
+ #if defined(HAVE_SCANDIR)
+ # if defined(__LINUX__)
+ return ::scandir(dir, namelist, filter, compar);
+ #elif defined(__SOLARIS__)
+ return ::scandir(dir, namelist, filter, (int (*)(const dirent**, const dirent**)) compar);
+ # else
+ return ::scandir(dir, namelist, (int (*)(struct dirent*)) filter, compar);
+ # endif
+ #else
+ # error scandir not available
+ #endif
+ }
+
+ inline int os::setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen)
+ {
+ #if defined(HAVE_SETSOCKOPT)
+ return ::setsockopt(s, level, optname, optval, optlen);
+ #else
+ # error setsockopt not available
+ #endif
+ }
+
+ inline int os::shutdown(int s, int how)
+ {
+ #if defined(HAVE_SHUTDOWN)
+ return ::shutdown(s, how);
+ #else
+ # error shutdown not available
+ #endif
+ }
+
+ inline int os::socket(int domain, int type, int protocol)
+ {
+ #if defined(HAVE_SOCKET)
+ return ::socket(domain, type, protocol);
+ #else
+ # error socket not available
+ #endif
+ }
+
+ inline int os::stat(const char* path, struct stat* buf)
+ {
+ #if defined(HAVE_STAT)
+ return ::stat(path, buf);
+ #else
+ # error stat not available
+ #endif
+ }
+
+ #if defined(__SOLARIS__)
+ inline int os::str2sig(const char* str, int* signum)
+ {
+ #if defined(HAVE_STR2SIG)
+ return ::str2sig(str, signum);
+ #else
+ # error str2sig not available
+ #endif
+ }
+ #endif
+
+ inline char* os::strcat(char* dest, const char* src)
+ {
+ #if defined(HAVE_STRCAT)
+ return ::strcat(dest, src);
+ #else
+ # error strcat not available
+ #endif
+ }
+
+ inline char* os::strcpy(char* dest, const char* src)
+ {
+ #if defined(HAVE_STRCPY)
+ return ::strcpy(dest, src);
+ #else
+ # error strcpy not available
+ #endif
+ }
+
+ inline char* os::strdup(const char* s)
+ {
+ #if defined(HAVE_STRDUP)
+ return ::strdup(s);
+ #else
+ # error strdup not available
+ #endif
+ }
+
+ inline char* os::strerror(int errnum)
+ {
+ #if defined(HAVE_STRERROR)
+ return ::strerror(errnum);
+ #else
+ # error strerror not available
+ #endif
+ }
+
+ inline size_t os::strlen(const char* s)
+ {
+ #if defined(HAVE_STRLEN)
+ return ::strlen(s);
+ #else
+ # error strlen not available
+ #endif
+ }
+
+ inline static ssize_t system_write(int fd, const void *buf, size_t count)
+ {
+ #if defined(HAVE_WRITE)
+ return write(fd, buf, count);
+ #else
+ # error write not available
+ #endif
+ }
+
+ #else
+
+ void* os_mmap_anonymous(void *addr, size_t len, int prot, int flags);
+
+ void os_abort(void);
+ int os_access(const char* pathname, int mode);
+ int os_atoi(const char* nptr);
+ void* os_calloc(size_t nmemb, size_t size);
+ char* os_dirname(char* path);
+ int os_dlclose(void* handle);
+ char* os_dlerror(void);
+ void* os_dlopen(const char* filename, int flag);
+ void* os_dlsym(void* handle, const char* symbol);
+ int os_fclose(FILE* fp);
+ FILE* os_fopen(const char* path, const char* mode);
+ size_t os_fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+ void os_free(void* ptr);
+ int os_getpagesize(void);
+ void* os_memcpy(void* dest, const void* src, size_t n);
+ void* os_memset(void* s, int c, size_t n);
+ int os_mprotect(void* addr, size_t len, int prot);
+ int os_scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
+ int os_stat(const char* path, struct stat* buf);
+ char* os_strcat(char* dest, const char* src);
+ char* os_strcpy(char* dest, const char* src);
+ char* os_strdup(const char* s);
+ int os_strlen(const char* s);
+
+ #endif
+
+ #endif // _OS_HPP
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
-/* macro for accessing the class name of a method reference */
+ /* src/vm/references.h - references to classes/fields/methods
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+ #ifndef _REFERENCES_H_
+ #define _REFERENCES_H_
+
+ /* forward typedefs ***********************************************************/
+
+ typedef struct constant_classref constant_classref;
+ typedef struct constant_FMIref constant_FMIref;
+
+
+ /* constant_classref **********************************************************/
+
+ struct constant_classref {
+ void *pseudo_vftbl; /* for distinguishing it from classinfo */
+ struct classinfo *referer; /* class containing the reference */
+ struct utf *name; /* name of the class refered to */
+ };
+
+
+ /* classref_or_classinfo ******************************************************/
+
+ typedef union classref_or_classinfo {
+ constant_classref *ref; /* a symbolic class reference */
+ struct classinfo *cls; /* an already loaded class */
+ void *any; /* used for general access (x != NULL,...) */
+ } classref_or_classinfo;
+
+
+ /* parseddesc_t ***************************************************************/
+
+ typedef union parseddesc {
+ struct typedesc *fd; /* parsed field descriptor */
+ struct methoddesc *md; /* parsed method descriptor */
+ void *any; /* used for simple test against NULL */
+ } parseddesc_t;
+
+
+ #include "config.h"
+ #include "vm/types.h"
+
+ #include "vm/class.h"
+ #include "vm/descriptor.h"
+ #include "vm/field.h"
+ #include "vm/global.h"
+ #include "vm/method.h"
+ #include "vm/utf8.h"
+
+
+ /*----------------------------------------------------------------------------*/
+ /* References */
+ /* */
+ /* This header files defines the following types used for references to */
+ /* classes/methods/fields and descriptors: */
+ /* */
+ /* classinfo * a loaded class */
+ /* constant_classref a symbolic reference */
+ /* classref_or_classinfo a loaded class or a symbolic reference */
+ /* */
+ /* constant_FMIref a symb. ref. to a field/method/intf.method */
+ /* */
+ /* typedesc * describes a field type */
+ /* methoddesc * descrives a method type */
+ /* parseddesc describes a field type or a method type */
+ /*----------------------------------------------------------------------------*/
+
+ /* structs ********************************************************************/
+
+ /* constant_FMIref ************************************************************/
+
+ struct constant_FMIref{ /* Fieldref, Methodref and InterfaceMethodref */
+ union {
+ s4 index; /* used only within the loader */
+ constant_classref *classref; /* class having this field/meth./intfm. */
+ fieldinfo *field; /* resolved field */
+ methodinfo *method; /* resolved method */
+ } p;
+ utf *name; /* field/method/interfacemethod name */
+ utf *descriptor; /* field/method/intfmeth. type descriptor string */
+ parseddesc_t parseddesc; /* parsed descriptor */
+ };
+
+
+ /* macros *********************************************************************/
+
+ /* a value that never occurrs in classinfo.header.vftbl */
+ #define CLASSREF_PSEUDO_VFTBL ((void *) 1)
+
+ /* macro for testing if a classref_or_classinfo is a classref */
+ /* `reforinfo` is only evaluated once */
+ #define IS_CLASSREF(reforinfo) \
+ ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL)
+
+ /* macro for testing if a constant_FMIref has been resolved */
+ /* `fmiref` is only evaluated once */
+ #define IS_FMIREF_RESOLVED(fmiref) \
+ ((fmiref)->p.classref->pseudo_vftbl != CLASSREF_PSEUDO_VFTBL)
+
+ /* the same as IS_CLASSREF, but also check against NULL */
+ #define IS_XCLASSREF(reforinfo) \
+ ((reforinfo).any && IS_CLASSREF(reforinfo))
+
+ /* macro for casting a classref/classinfo * to a classref_or_classinfo */
+ #define CLASSREF_OR_CLASSINFO(value) \
+ (*((classref_or_classinfo *)(&(value))))
+
+ /* macro for accessing the name of a classref/classinfo */
+ #define CLASSREF_OR_CLASSINFO_NAME(value) \
+ (IS_CLASSREF(value) ? (value).ref->name : (value).cls->name)
+
+ /* macro for accessing the class name of a method reference */
+ #define METHODREF_CLASSNAME(fmiref) \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.method->clazz->name \
+ : (fmiref)->p.classref->name)
+
++/* macro for accessing the class name of a field reference */
+ #define FIELDREF_CLASSNAME(fmiref) \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.field->clazz->name \
+ : (fmiref)->p.classref->name)
+
+ /* initialize a constant_classref with referer `ref` and name `classname` */
+
+ #define CLASSREF_INIT(c,ref,classname) \
+ do { \
+ (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL; \
+ (c).referer = (ref); \
+ (c).name = (classname); \
+ } while (0)
+
+ #endif /* _REFERENCES_H_ */
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
--- /dev/null
- size_patchref;
+ /* src/vm/statistics.c - global variables for statistics
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <stdint.h>
+ #include <string.h>
+
+ #if defined(HAVE_TIME_H)
+ # include <time.h>
+ #endif
+
+ #if defined(HAVE_SYS_TIME_H)
+ # include <sys/time.h>
+ #endif
+
+ #if defined(HAVE_SYS_RESOURCE_H)
+ # include <sys/resource.h>
+ #endif
+
+ #include "vm/types.h"
+
+ #include "mm/gc.hpp"
+
+ #include "toolbox/logging.h"
+
+ #include "vm/class.h"
+ #include "vm/field.h"
+ #include "vm/global.h"
+ #include "vm/method.h"
+ #include "vm/options.h"
+ #include "vm/statistics.h"
+
+ #include "vm/jit/code.h"
+
+
+ /* global variables ***********************************************************/
+
+ static s8 loadingtime = 0; /* accumulated loading time */
+ static s8 loadingstarttime = 0;
+ static s8 loadingstoptime = 0;
+ static s4 loadingtime_recursion = 0;
+
+ static s8 compilingtime = 0; /* accumulated compile time */
+ static s8 compilingstarttime = 0;
+ static s8 compilingstoptime = 0;
+ static s4 compilingtime_recursion = 0;
+
+ s4 codememusage = 0;
+ s4 maxcodememusage = 0;
+
+ s4 memoryusage = 0;
+ s4 maxmemusage = 0;
+
+ s4 maxdumpsize = 0;
+
+ s4 globalallocateddumpsize = 0;
+ s4 globaluseddumpsize = 0;
+
+
+ /* variables for measurements *************************************************/
+
+ s4 size_classinfo = 0;
+ s4 size_fieldinfo = 0;
+ s4 size_methodinfo = 0;
+ s4 size_lineinfo = 0;
+ s4 size_codeinfo = 0;
+
+ s4 size_stub_native = 0;
+
+ s4 size_stack_map = 0;
+ s4 size_string = 0;
+
+ s4 size_threadobject = 0;
+ int32_t size_thread_index_t = 0;
+ int32_t size_stacksize = 0;
+
+ s4 size_lock_record = 0;
+ s4 size_lock_hashtable = 0;
+ s4 size_lock_waiter = 0;
+
+ int32_t count_linenumbertable = 0;
+ int32_t size_linenumbertable = 0;
+
+ s4 size_patchref = 0;
+
++s4 size_cachedref = 0;
++
+ u8 count_calls_java_to_native = 0;
+ u8 count_calls_native_to_java = 0;
+
+ int count_const_pool_len = 0;
+ int count_classref_len = 0;
+ int count_parsed_desc_len = 0;
+ int count_vftbl_len = 0;
+ int count_all_methods = 0;
+ int count_methods_marked_used = 0; /* RTA */
+
+ int count_vmcode_len = 0;
+ int count_extable_len = 0;
+ int count_class_loads = 0;
+ int count_class_inits = 0;
+
+ int count_utf_len = 0; /* size of utf hash */
+ int count_utf_new = 0; /* calls of utf_new */
+ int count_utf_new_found = 0; /* calls of utf_new with fast return */
+
+ int count_locals_conflicts = 0; /* register allocator statistics */
+ int count_locals_spilled = 0;
+ int count_locals_register = 0;
+ int count_ss_spilled = 0;
+ int count_ss_register = 0;
+ int count_methods_allocated_by_lsra = 0;
+ int count_mem_move_bb = 0;
+ int count_interface_size = 0;
+ int count_argument_mem_ss = 0;
+ int count_argument_reg_ss = 0;
+ int count_method_in_register = 0;
+ int count_mov_reg_reg = 0;
+ int count_mov_mem_reg = 0;
+ int count_mov_reg_mem = 0;
+ int count_mov_mem_mem = 0;
+
+ int count_jit_calls = 0;
+ int count_methods = 0;
+ int count_spills_read_ila = 0;
+ int count_spills_read_flt = 0;
+ int count_spills_read_dbl = 0;
+ int count_spills_write_ila = 0;
+ int count_spills_write_flt = 0;
+ int count_spills_write_dbl = 0;
+ int count_pcmd_activ = 0;
+ int count_pcmd_drop = 0;
+ int count_pcmd_zero = 0;
+ int count_pcmd_const_store = 0;
+ int count_pcmd_const_alu = 0;
+ int count_pcmd_const_bra = 0;
+ int count_pcmd_load = 0;
+ int count_pcmd_move = 0;
+ int count_load_instruction = 0;
+ int count_pcmd_store = 0;
+ int count_pcmd_store_comb = 0;
+ int count_dup_instruction = 0;
+ int count_pcmd_op = 0;
+ int count_pcmd_mem = 0;
+ int count_pcmd_met = 0;
+ int count_pcmd_bra = 0;
+ int count_pcmd_table = 0;
+ int count_pcmd_return = 0;
+ int count_pcmd_returnx = 0;
+ int count_check_null = 0;
+ int count_check_bound = 0;
+ int count_max_basic_blocks = 0;
+ int count_basic_blocks = 0;
+ int count_javainstr = 0;
+ int count_max_javainstr = 0;
+ int count_javacodesize = 0;
+ int count_javaexcsize = 0;
+ int count_calls = 0;
+ int count_tryblocks = 0;
+ int count_code_len = 0;
+ int count_data_len = 0;
+ int count_cstub_len = 0;
+ int count_max_new_stack = 0;
+ int count_upper_bound_new_stack = 0;
+
+ int count_emit_branch = 0;
+ int count_emit_branch_8bit = 0;
+ int count_emit_branch_16bit = 0;
+ int count_emit_branch_32bit = 0;
+ int count_emit_branch_64bit = 0;
+
+ s4 count_branches_resolved = 0;
+ s4 count_branches_unresolved = 0;
+
+ u8 count_jni_callXmethod_calls=0;
+ u8 count_jni_calls=0;
+
+
+ static int count_block_stack_init[11] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+ };
+ int *count_block_stack = count_block_stack_init;
+ static int count_analyse_iterations_init[5] = {
+ 0, 0, 0, 0, 0
+ };
+ int *count_analyse_iterations = count_analyse_iterations_init;
+ static int count_method_bb_distribution_init[9] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+ int *count_method_bb_distribution = count_method_bb_distribution_init;
+ static int count_block_size_distribution_init[18] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0
+ };
+ int *count_block_size_distribution = count_block_size_distribution_init;
+ static int count_store_length_init[21] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+ };
+ int *count_store_length = count_store_length_init;
+ static int count_store_depth_init[11] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+ };
+ int *count_store_depth = count_store_depth_init;
+
+
+ /* instruction scheduler statistics *******************************************/
+
+ s4 count_schedule_basic_blocks = 0;
+ s4 count_schedule_nodes = 0;
+ s4 count_schedule_leaders = 0;
+ s4 count_schedule_max_leaders = 0;
+ s4 count_schedule_critical_path = 0;
+
+
+ /* jnicallXmethodinvokation ***************************************************
+
+ increments the jni CallXMethod invokation count by one
+
+ *******************************************************************************/
+
+ void jnicallXmethodnvokation(void)
+ {
+ /* XXX do locking here */
+ count_jni_callXmethod_calls++;
+ }
+
+
+ /* jniinvokation *************************************************************
+
+ increments the jni overall invokation count by one
+
+ *******************************************************************************/
+
+ void jniinvokation(void)
+ {
+ /* XXX do locking here */
+ count_jni_calls++;
+ }
+
+
+ /* getcputime *********************************** ******************************
+
+ Returns the used CPU time in microseconds
+
+ *******************************************************************************/
+
+ s8 getcputime(void)
+ {
+ #if defined(HAVE_GETRUSAGE)
+ struct rusage ru;
+ int sec, usec;
+
+ getrusage(RUSAGE_SELF, &ru);
+
+ sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+ usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+
+ return sec * 1000000 + usec;
+ #else
+ /* If we don't have getrusage, simply return 0. */
+
+ return 0;
+ #endif
+ }
+
+
+ /* loadingtime_stop ************************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void loadingtime_start(void)
+ {
+ loadingtime_recursion++;
+
+ if (loadingtime_recursion == 1)
+ loadingstarttime = getcputime();
+ }
+
+
+ /* loadingtime_stop ************************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void loadingtime_stop(void)
+ {
+ if (loadingtime_recursion == 1) {
+ loadingstoptime = getcputime();
+ loadingtime += (loadingstoptime - loadingstarttime);
+ }
+
+ loadingtime_recursion--;
+ }
+
+
+ /* compilingtime_stop **********************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void compilingtime_start(void)
+ {
+ compilingtime_recursion++;
+
+ if (compilingtime_recursion == 1)
+ compilingstarttime = getcputime();
+ }
+
+
+ /* compilingtime_stop **********************************************************
+
+ XXX
+
+ *******************************************************************************/
+
+ void compilingtime_stop(void)
+ {
+ if (compilingtime_recursion == 1) {
+ compilingstoptime = getcputime();
+ compilingtime += (compilingstoptime - compilingstarttime);
+ }
+
+ compilingtime_recursion--;
+ }
+
+
+ /* print_times *****************************************************************
+
+ Prints a summary of CPU time usage.
+
+ *******************************************************************************/
+
+ void print_times(void)
+ {
+ s8 totaltime;
+ s8 runtime;
+
+ totaltime = getcputime();
+ runtime = totaltime - loadingtime - compilingtime;
+
+ #if SIZEOF_VOID_P == 8
+ dolog("Time for loading classes: %6ld ms", loadingtime / 1000);
+ dolog("Time for compiling code: %6ld ms", compilingtime / 1000);
+ dolog("Time for running program: %6ld ms", runtime / 1000);
+ dolog("Total time: %6ld ms", totaltime / 1000);
+ #else
+ dolog("Time for loading classes: %6lld ms", loadingtime / 1000);
+ dolog("Time for compiling code: %6lld ms", compilingtime / 1000);
+ dolog("Time for running program: %6lld ms", runtime / 1000);
+ dolog("Total time: %6lld ms", totaltime / 1000);
+ #endif
+ }
+
+
+ /* print_stats *****************************************************************
+
+ outputs detailed compiler statistics
+
+ *******************************************************************************/
+
+ void print_stats(void)
+ {
+ s4 i;
+ float f;
+ s4 sum;
+
+
+ dolog("Number of JIT compiler calls: %6d", count_jit_calls);
+ dolog("Number of compiled methods: %6d", count_methods);
+
+ dolog("Number of compiled basic blocks: %6d",
+ count_basic_blocks);
+ dolog("Number of max. basic blocks per method: %6d",
+ count_max_basic_blocks);
+
+ dolog("Number of compiled JavaVM instructions: %6d",
+ count_javainstr);
+ dolog("Number of max. JavaVM instructions per method: %6d",
+ count_max_javainstr);
+ dolog("Size of compiled JavaVM instructions: %6d(%d)",
+ count_javacodesize, count_javacodesize - count_methods * 18);
+
+ dolog("Size of compiled Exception Tables: %d", count_javaexcsize);
+ dolog("Number of Machine-Instructions: %d", count_code_len >> 2);
+ dolog("Number of Spills (write to memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
+ count_spills_write_ila + count_spills_write_flt + count_spills_write_dbl,
+ count_spills_write_ila, count_spills_write_flt, count_spills_write_dbl);
+ dolog("Number of Spills (read from memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
+ count_spills_read_ila + count_spills_read_flt + count_spills_read_dbl,
+ count_spills_read_ila, count_spills_read_flt, count_spills_read_dbl);
+ dolog("Number of Activ Pseudocommands: %6d", count_pcmd_activ);
+ dolog("Number of Drop Pseudocommands: %6d", count_pcmd_drop);
+ dolog("Number of Const Pseudocommands: %6d (zero:%5d)",
+ count_pcmd_load, count_pcmd_zero);
+ dolog("Number of ConstAlu Pseudocommands: %6d (cmp: %5d, store:%5d)",
+ count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+ dolog("Number of Move Pseudocommands: %6d", count_pcmd_move);
+ dolog("Number of Load Pseudocommands: %6d", count_load_instruction);
+ dolog("Number of Store Pseudocommands: %6d (combined: %5d)",
+ count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+ dolog("Number of OP Pseudocommands: %6d", count_pcmd_op);
+ dolog("Number of DUP Pseudocommands: %6d", count_dup_instruction);
+ dolog("Number of Mem Pseudocommands: %6d", count_pcmd_mem);
+ dolog("Number of Method Pseudocommands: %6d", count_pcmd_met);
+ dolog("Number of Branch Pseudocommands: %6d (rets:%5d, Xrets: %5d)",
+ count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+ log_println(" resolved branches: %6d", count_branches_resolved);
+ log_println(" unresolved branches: %6d", count_branches_unresolved);
+ dolog("Number of Table Pseudocommands: %6d", count_pcmd_table);
+ dolog("Number of Useful Pseudocommands: %6d", count_pcmd_table +
+ count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+ dolog("Number of Null Pointer Checks: %6d", count_check_null);
+ dolog("Number of Array Bound Checks: %6d", count_check_bound);
+ dolog("Number of Try-Blocks: %d", count_tryblocks);
+
+ dolog("Number of branch_emit (total, 8bit/16bit/32bit/64bit offset): %d, %d/%d/%d/%d",
+ count_emit_branch, count_emit_branch_8bit, count_emit_branch_16bit,
+ count_emit_branch_32bit, count_emit_branch_64bit);
+
+ dolog("Maximal count of stack elements: %d", count_max_new_stack);
+ dolog("Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+ dolog("Distribution of stack sizes at block boundary");
+ dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_block_stack[0], count_block_stack[1], count_block_stack[2],
+ count_block_stack[3], count_block_stack[4], count_block_stack[5],
+ count_block_stack[6], count_block_stack[7], count_block_stack[8],
+ count_block_stack[9], count_block_stack[10]);
+ dolog("Distribution of store stack depth");
+ dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_depth[0], count_store_depth[1], count_store_depth[2],
+ count_store_depth[3], count_store_depth[4], count_store_depth[5],
+ count_store_depth[6], count_store_depth[7], count_store_depth[8],
+ count_store_depth[9], count_store_depth[10]);
+ dolog("Distribution of store creator chains first part");
+ dolog(" 0 1 2 3 4 5 6 7 8 9");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_length[0], count_store_length[1], count_store_length[2],
+ count_store_length[3], count_store_length[4], count_store_length[5],
+ count_store_length[6], count_store_length[7], count_store_length[8],
+ count_store_length[9]);
+ dolog("Distribution of store creator chains second part");
+ dolog(" 10 11 12 13 14 15 16 17 18 19 >=20");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_length[10], count_store_length[11],
+ count_store_length[12], count_store_length[13],
+ count_store_length[14], count_store_length[15],
+ count_store_length[16], count_store_length[17],
+ count_store_length[18], count_store_length[19],
+ count_store_length[20]);
+ dolog("Distribution of analysis iterations");
+ dolog(" 1 2 3 4 >=5");
+ dolog("%6d%6d%6d%6d%6d",
+ count_analyse_iterations[0], count_analyse_iterations[1],
+ count_analyse_iterations[2], count_analyse_iterations[3],
+ count_analyse_iterations[4]);
+
+
+ /* Distribution of basic blocks per method ********************************/
+
+ log_println("Distribution of basic blocks per method:");
+ log_println(" <=5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
+
+ log_start();
+ for (i = 0; i <= 8; i++)
+ log_print("%6d", count_method_bb_distribution[i]);
+ log_finish();
+
+ /* print ratio */
+
+ f = (float) count_methods;
+
+ log_start();
+ for (i = 0; i <= 8; i++)
+ log_print("%6.2f", (float) count_method_bb_distribution[i] / f);
+ log_finish();
+
+ /* print cumulated ratio */
+
+ log_start();
+ for (i = 0, sum = 0; i <= 8; i++) {
+ sum += count_method_bb_distribution[i];
+ log_print("%6.2f", (float) sum / f);
+ }
+ log_finish();
+
+
+ /* Distribution of basic block sizes **************************************/
+
+ log_println("Distribution of basic block sizes:");
+ log_println(" 0 1 2 3 4 5 6 7 8 9 <13 <15 <17 <19 <21 <26 <31 >30");
+
+ /* print block sizes */
+
+ log_start();
+ for (i = 0; i <= 17; i++)
+ log_print("%6d", count_block_size_distribution[i]);
+ log_finish();
+
+ /* print ratio */
+
+ f = (float) count_basic_blocks;
+
+ log_start();
+ for (i = 0; i <= 17; i++)
+ log_print("%6.2f", (float) count_block_size_distribution[i] / f);
+ log_finish();
+
+ /* print cumulated ratio */
+
+ log_start();
+ for (i = 0, sum = 0; i <= 17; i++) {
+ sum += count_block_size_distribution[i];
+ log_print("%6.2f", (float) sum / f);
+ }
+ log_finish();
+
+ statistics_print_memory_usage();
+
+ dolog("Number of class loads: %6d", count_class_loads);
+ dolog("Number of class inits: %6d", count_class_inits);
+ dolog("Number of loaded Methods: %6d\n", count_all_methods);
+
+ dolog("Calls of utf_new: %6d", count_utf_new);
+ dolog("Calls of utf_new (element found): %6d\n", count_utf_new_found);
+
+
+ /* LSRA statistics ********************************************************/
+
+ dolog("Moves reg -> reg: %6d", count_mov_reg_reg);
+ dolog("Moves mem -> reg: %6d", count_mov_mem_reg);
+ dolog("Moves reg -> mem: %6d", count_mov_reg_mem);
+ dolog("Moves mem -> mem: %6d", count_mov_mem_mem);
+
+ dolog("Methods allocated by LSRA: %6d",
+ count_methods_allocated_by_lsra);
+ dolog("Conflicts between local Variables: %6d", count_locals_conflicts);
+ dolog("Local Variables held in Memory: %6d", count_locals_spilled);
+ dolog("Local Variables held in Registers: %6d", count_locals_register);
+ dolog("Stackslots held in Memory: %6d", count_ss_spilled);
+ dolog("Stackslots held in Registers: %6d", count_ss_register);
+ dolog("Memory moves at BB Boundaries: %6d", count_mem_move_bb);
+ dolog("Number of interface slots: %6d\n", count_interface_size);
+ dolog("Number of Argument stack slots in register: %6d",
+ count_argument_reg_ss);
+ dolog("Number of Argument stack slots in memory: %6d\n",
+ count_argument_mem_ss);
+ dolog("Number of Methods kept in registers: %6d\n",
+ count_method_in_register);
+
+
+ /* instruction scheduler statistics ***************************************/
+
+ #if defined(USE_SCHEDULER)
+ dolog("Instruction scheduler statistics:");
+ dolog("Number of basic blocks: %7d", count_schedule_basic_blocks);
+ dolog("Number of nodes: %7d", count_schedule_nodes);
+ dolog("Number of leaders nodes: %7d", count_schedule_leaders);
+ dolog("Number of max. leaders nodes: %7d", count_schedule_max_leaders);
+ dolog("Length of critical path: %7d\n", count_schedule_critical_path);
+ #endif
+
+
+ /* call statistics ********************************************************/
+
+ dolog("Function call statistics:");
+ dolog("Number of jni->CallXMethod function invokations: %ld",
+ count_jni_callXmethod_calls);
+ dolog("Overall number of jni invokations: %ld",
+ count_jni_calls);
+
+ log_println("java-to-native calls: %10ld", count_calls_java_to_native);
+ log_println("native-to-java calls: %10ld", count_calls_native_to_java);
+
+
+ /* now print other statistics ********************************************/
+
+ #if defined(ENABLE_INTRP)
+ print_dynamic_super_statistics();
+ #endif
+ }
+
+
+ /* statistics_print_date *******************************************************
+
+ Print current date and time.
+
+ *******************************************************************************/
+
+ void statistics_print_date(void)
+ {
+ time_t t;
+ struct tm tm;
+
+ #if defined(HAVE_TIME)
+ time(&t);
+ #else
+ # error !HAVE_TIME
+ #endif
+
+ #if defined(HAVE_LOCALTIME_R)
+ localtime_r(&t, &tm);
+ #else
+ # error !HAVE_LOCALTIME_R
+ #endif
+
+ log_println("%d-%02d-%02d %02d:%02d:%02d",
+ 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ }
+
+
+ /* statistics_print_memory_usage ***********************************************
+
+ Print current memory usage.
+
+ *******************************************************************************/
+
+ void statistics_print_memory_usage(void)
+ {
+ s4 sum;
+
+ log_println("memory usage ----------------------");
+ log_println("");
+ log_println("code: %10d", count_code_len);
+ log_println("data: %10d", count_data_len);
+ log_println(" ----------");
+
+ sum =
+ count_code_len +
+ count_data_len;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("classinfo (%3d B): %10d", (int) sizeof(classinfo), size_classinfo);
+ log_println("fieldinfo (%3d B): %10d", (int) sizeof(fieldinfo), size_fieldinfo);
+ log_println("methodinfo (%3d B): %10d", (int) sizeof(methodinfo), size_methodinfo);
+ log_println("lineinfo (%3d B): %10d", (int) sizeof(lineinfo), size_lineinfo);
+ log_println("codeinfo (%3d B): %10d", (int) sizeof(codeinfo), size_codeinfo);
+ log_println(" ----------");
+
+ sum =
+ size_classinfo +
+ size_fieldinfo +
+ size_methodinfo +
+ size_lineinfo +
+ size_codeinfo;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("linenumber tables (%5d): %10d", count_linenumbertable, size_linenumbertable);
+ log_println("exception tables: %10d", count_extable_len);
+ log_println("patcher references: %10d", size_patchref);
++ log_println("cached references: %10d", size_cachedref);
+ log_println(" ----------");
+
+ sum =
+ size_linenumbertable +
+ count_extable_len +
++ size_patchref +
++ size_cachedref;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("constant pool: %10d", count_const_pool_len);
+ log_println("classref: %10d", count_classref_len);
+ log_println("parsed descriptors: %10d", count_parsed_desc_len);
+ log_println("vftbl: %10d", count_vftbl_len);
+ log_println("compiler stubs: %10d", count_cstub_len);
+ log_println("native stubs: %10d", size_stub_native);
+ log_println("utf: %10d", count_utf_len);
+ log_println("vmcode: %10d", count_vmcode_len);
+ log_println("stack map: %10d", size_stack_map);
+ log_println("string: %10d", size_string);
+ log_println("threadobject: %10d", size_threadobject);
+ log_println("thread index: %10d", size_thread_index_t);
+ log_println("stack size: %10d", size_stacksize);
+ log_println("lock record: %10d", size_lock_record);
+ log_println("lock hashtable: %10d", size_lock_hashtable);
+ log_println("lock waiter: %10d", size_lock_waiter);
+ log_println(" ----------");
+
+ sum =
+ count_const_pool_len +
+ count_classref_len +
+ count_parsed_desc_len +
+ count_vftbl_len +
+ count_cstub_len +
+ size_stub_native +
+ count_utf_len +
+ count_vmcode_len +
+ size_stack_map +
+ size_string +
+ size_threadobject +
+ size_thread_index_t +
+ size_stacksize +
+ size_lock_record +
+ size_lock_hashtable +
+ size_lock_waiter;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("max. code memory: %10d", maxcodememusage);
+ log_println("max. heap memory: %10d", maxmemusage);
+ log_println("max. dump memory: %10d", maxdumpsize);
+ log_println("");
+ log_println("heap memory not freed: %10d", (int32_t) memoryusage);
+ log_println("dump memory not freed: %10d", (int32_t) globalallocateddumpsize);
+
+ log_println("");
+ }
+
+
+ /* statistics_print_gc_memory_usage ********************************************
+
+ Print current GC memory usage.
+
+ *******************************************************************************/
+
+ void statistics_print_gc_memory_usage(void)
+ {
+ static int64_t count = 0;
+ int64_t max;
+ int64_t size;
+ int64_t free;
+ int64_t used;
+ int64_t total;
+
+ count++;
+
+ max = gc_get_max_heap_size();
+ size = gc_get_heap_size();
+ free = gc_get_free_bytes();
+ used = size - free;
+ total = gc_get_total_bytes();
+
+ if (opt_ProfileMemoryUsageGNUPlot) {
+ if (count == 1)
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "plot \"profile.dat\" using 1:2 with lines title \"max. Java heap size\", \"profile.dat\" using 1:3 with lines title \"Java heap size\", \"profile.dat\" using 1:4 with lines title \"used\", \"profile.dat\" using 1:5 with lines title \"free\"\n");
+
+ #if SIZEOF_VOID_P == 8
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "%ld %ld %ld %ld %ld\n", count, max, size, used, free);
+ #else
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "%lld %lld %lld %lld %lld\n", count, max, size, used, free);
+ #endif
+
+ fflush(opt_ProfileMemoryUsageGNUPlot);
+ }
+ else {
+ log_println("GC memory usage -------------------");
+ log_println("");
+ log_println("max. Java heap size: %10lld", max);
+ log_println("");
+ log_println("Java heap size: %10lld", size);
+ log_println("used: %10lld", used);
+ log_println("free: %10lld", free);
+ log_println("totally used: %10lld", total);
+ log_println("");
+ }
+ }
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+ /* src/vm/statistics.h - exports global varables for statistics
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #ifndef _STATISTICS_H
+ #define _STATISTICS_H
+
+ #include "config.h"
+
+ #include <stdint.h>
+
+ #include "vm/types.h"
+
+ #include "vm/global.h"
+
+
+ /* statistic macros ***********************************************************/
+
+ #if defined(ENABLE_STATISTICS)
+ #define STATISTICS(x) \
+ do { \
+ if (opt_stat) { \
+ x; \
+ } \
+ } while (0)
+ #else
+ #define STATISTICS(x) /* nothing */
+ #endif
+
+ /* in_ inline statistics */
+
+ #define IN_MAX 9
+ #define IN_UNIQUEVIRT 0x0000
+ #define IN_UNIQUE_INTERFACE 0x0001
+ #define IN_OUTSIDERS 0x0004
+ #define IN_MAXDEPTH 0x0008
+ #define IN_MAXCODE 0x0010
+ #define IN_JCODELENGTH 0x0020
+ #define IN_EXCEPTION 0x0040
+ #define IN_NOT_UNIQUE_VIRT 0x0080
+ #define IN_NOT_UNIQUE_INTERFACE 0x0100
+
+ #define N_UNIQUEVIRT 0
+ #define N_UNIQUE_INTERFACE 1
+ #define N_OUTSIDERS 2
+ #define N_MAXDEPTH 3
+ #define N_MAXCODE 4
+ #define N_JCODELENGTH 5
+ #define N_EXCEPTION 6
+ #define N_NOT_UNIQUE_VIRT 7
+ #define N_NOT_UNIQUE_INTERFACE 8
+
+
+ /* global variables ***********************************************************/
+
+ extern s4 codememusage;
+ extern s4 maxcodememusage;
+
+ extern s4 memoryusage;
+ extern s4 maxmemusage;
+
+ extern s4 maxdumpsize;
+
+ extern s4 globalallocateddumpsize;
+ extern s4 globaluseddumpsize;
+
+
+ /* variables for measurements *************************************************/
+
+ extern s4 size_classinfo;
+ extern s4 size_fieldinfo;
+ extern s4 size_methodinfo;
+ extern s4 size_lineinfo;
+ extern s4 size_codeinfo;
+
+ extern s4 size_stub_native;
+
+ extern s4 size_stack_map;
+ extern s4 size_string;
+
+ extern s4 size_threadobject;
+ extern int32_t size_thread_index_t;
+ extern int32_t size_stacksize;
+
+ extern s4 size_lock_record;
+ extern s4 size_lock_hashtable;
+ extern s4 size_lock_waiter;
+
+ extern int32_t count_linenumbertable;
+ extern int32_t size_linenumbertable;
+
+ extern s4 size_patchref;
+
++extern s4 size_cachedref;
++
+ extern u8 count_calls_java_to_native;
+ extern u8 count_calls_native_to_java;
+
+ extern int count_const_pool_len;
+ extern int count_classref_len;
+ extern int count_parsed_desc_len;
+ extern int count_vftbl_len;
+ extern int count_all_methods;
+ extern int count_methods_marked_used; /*RTA*/
+ extern int count_vmcode_len;
+ extern int count_extable_len;
+ extern int count_class_loads;
+ extern int count_class_inits;
+
+ extern int count_utf_len; /* size of utf hash */
+ extern int count_utf_new;
+ extern int count_utf_new_found;
+
+ extern int count_locals_conflicts;
+ extern int count_locals_spilled;
+ extern int count_locals_register;
+ extern int count_ss_spilled;
+ extern int count_ss_register;
+ extern int count_methods_allocated_by_lsra;
+ extern int count_mem_move_bb;
+ extern int count_interface_size;
+ extern int count_argument_mem_ss;
+ extern int count_argument_reg_ss;
+ extern int count_method_in_register;
+ extern int count_mov_reg_reg;
+ extern int count_mov_mem_reg;
+ extern int count_mov_reg_mem;
+ extern int count_mov_mem_mem;
+
+ extern int count_jit_calls;
+ extern int count_methods;
+ extern int count_spills_read_ila;
+ extern int count_spills_read_flt;
+ extern int count_spills_read_dbl;
+ extern int count_spills_write_ila;
+ extern int count_spills_write_flt;
+ extern int count_spills_write_dbl;
+ extern int count_pcmd_activ;
+ extern int count_pcmd_drop;
+ extern int count_pcmd_zero;
+ extern int count_pcmd_const_store;
+ extern int count_pcmd_const_alu;
+ extern int count_pcmd_const_bra;
+ extern int count_pcmd_load;
+ extern int count_pcmd_move;
+ extern int count_load_instruction;
+ extern int count_pcmd_store;
+ extern int count_pcmd_store_comb;
+ extern int count_dup_instruction;
+ extern int count_pcmd_op;
+ extern int count_pcmd_mem;
+ extern int count_pcmd_met;
+ extern int count_pcmd_bra;
+ extern int count_pcmd_table;
+ extern int count_pcmd_return;
+ extern int count_pcmd_returnx;
+ extern int count_check_null;
+ extern int count_check_bound;
+ extern int count_max_basic_blocks;
+ extern int count_basic_blocks;
+ extern int count_max_javainstr;
+ extern int count_javainstr;
+ extern int count_javacodesize;
+ extern int count_javaexcsize;
+ extern int count_calls;
+ extern int count_tryblocks;
+ extern int count_code_len;
+ extern int count_data_len;
+ extern int count_cstub_len;
+ extern int count_max_new_stack;
+ extern int count_upper_bound_new_stack;
+
+ extern int count_emit_branch;
+ extern int count_emit_branch_8bit;
+ extern int count_emit_branch_16bit;
+ extern int count_emit_branch_32bit;
+ extern int count_emit_branch_64bit;
+
+ extern s4 count_branches_resolved;
+ extern s4 count_branches_unresolved;
+
+ extern int *count_block_stack;
+ extern int *count_analyse_iterations;
+ extern int *count_method_bb_distribution;
+ extern int *count_block_size_distribution;
+ extern int *count_store_length;
+ extern int *count_store_depth;
+ /* in_ inline statistics */
+ extern int count_in;
+ extern int count_in_uniqVirt;
+ extern int count_in_uniqIntf;
+ extern int count_in_rejected;
+ extern int count_in_rejected_mult;
+ extern int count_in_outsiders;
+ extern int count_in_uniqueVirt_not_inlined;
+ extern int count_in_uniqueInterface_not_inlined;
+ extern int count_in_maxDepth;
+ extern int count_in_maxMethods;
+
+ extern u2 count_in_not [512];
+
+ /* instruction scheduler statistics *******************************************/
+
+ extern s4 count_schedule_basic_blocks;
+ extern s4 count_schedule_nodes;
+ extern s4 count_schedule_leaders;
+ extern s4 count_schedule_max_leaders;
+ extern s4 count_schedule_critical_path;
+
+
+ /* function prototypes ********************************************************/
+
+ s8 getcputime(void);
+
+ void loadingtime_start(void);
+ void loadingtime_stop(void);
+ void compilingtime_start(void);
+ void compilingtime_stop(void);
+
+ void print_times(void);
+ void print_stats(void);
+
+ void statistics_print_date(void);
+ void statistics_print_memory_usage(void);
+ void statistics_print_gc_memory_usage(void);
+
+ void mem_usagelog(bool givewarnings);
+
+ void compiledinvokation(void);
+ void jnicallXmethodnvokation(void);
+ void jniinvokation(void);
+
+ #endif /* _STATISTICS_H */
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+ /* src/vm/vm.cpp - VM startup and shutdown functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ */
+
+
+ #include "config.h"
+
+ #include <stdint.h>
+
+ #include <exception>
+
+ #include <assert.h>
+ #include <errno.h>
+ #include <stdlib.h>
+
+ #include "vm/types.h"
+
+ #include "arch.h"
+ #include "md-abi.h"
+
+ #include "vm/jit/abi-asm.h"
+
+ #include "mm/codememory.h"
+ #include "mm/gc.hpp"
+ #include "mm/memory.h"
+
+ #include "native/jni.h"
+ #include "native/llni.h"
+ #include "native/localref.h"
+ #include "native/native.h"
+
+ #include "native/vm/nativevm.h"
+
+ #include "threads/lock-common.h"
+ #include "threads/threadlist.h"
+ #include "threads/thread.hpp"
+
+ #include "toolbox/logging.h"
+
+ #include "vm/array.h"
+
+ #if defined(ENABLE_ASSERTION)
+ #include "vm/assertion.h"
+ #endif
+
+ #include "vm/builtin.h"
+ #include "vm/classcache.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/finalizer.h"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/initialize.h"
+ #include "vm/options.h"
+ #include "vm/os.hpp"
+ #include "vm/package.hpp"
+ #include "vm/primitive.hpp"
+ #include "vm/properties.h"
+ #include "vm/signallocal.h"
+ #include "vm/statistics.h"
+ #include "vm/string.hpp"
+ #include "vm/suck.h"
+ #include "vm/vm.hpp"
+
+ #include "vm/jit/argument.h"
+ #include "vm/jit/asmpart.h"
+ #include "vm/jit/code.h"
+
+ #if defined(ENABLE_DISASSEMBLER)
+ # include "vm/jit/disass.h"
+ #endif
+
+ #include "vm/jit/jit.h"
++#include "vm/jit/jitcache.h"
+ #include "vm/jit/methodtree.h"
+
+ #if defined(ENABLE_PROFILING)
+ # include "vm/jit/optimizing/profile.h"
+ #endif
+
+ #include "vm/jit/optimizing/recompile.h"
+
+ #if defined(ENABLE_PYTHON)
+ # include "vm/jit/python.h"
+ #endif
+
+ #include "vm/jit/trap.h"
+
+ #if defined(ENABLE_JVMTI)
+ # include "native/jvmti/cacaodbg.h"
+ #endif
+
+ #if defined(ENABLE_VMLOG)
+ #include <vmlog_cacao.h>
+ #endif
+
+
+ /**
+ * This is _the_ instance of the VM.
+ */
+ VM* vm;
+
+
+ /* global variables ***********************************************************/
+
+ s4 vms = 0; /* number of VMs created */
+
+ static classinfo *mainclass = NULL;
+
+ #if defined(ENABLE_INTRP)
+ u1 *intrp_main_stack = NULL;
+ #endif
+
+
+ /* define heap sizes **********************************************************/
+
+ #define HEAP_MAXSIZE 128 * 1024 * 1024 /* default 128MB */
+ #define HEAP_STARTSIZE 2 * 1024 * 1024 /* default 2MB */
+ #define STACK_SIZE 128 * 1024 /* default 64kB */
+
+
+ /* define command line options ************************************************/
+
+ enum {
+ OPT_FOO,
+
+ /* Java options */
+
+ OPT_JAR,
+
+ OPT_D32,
+ OPT_D64,
+
+ OPT_CLASSPATH,
+ OPT_D,
+
+ OPT_VERBOSE,
+
+ OPT_VERSION,
+ OPT_SHOWVERSION,
+ OPT_FULLVERSION,
+
+ OPT_HELP,
+ OPT_X,
+ OPT_XX,
+
+ OPT_EA,
+ OPT_DA,
+ OPT_EA_NOARG,
+ OPT_DA_NOARG,
+
+
+ OPT_ESA,
+ OPT_DSA,
+
+ /* Java non-standard options */
+
+ OPT_JIT,
+ OPT_INTRP,
+
+ OPT_BOOTCLASSPATH,
+ OPT_BOOTCLASSPATH_A,
+ OPT_BOOTCLASSPATH_P,
+
+ OPT_BOOTCLASSPATH_C,
+
+ #if defined(ENABLE_PROFILING)
+ OPT_PROF,
+ OPT_PROF_OPTION,
+ #endif
+
+ OPT_MS,
+ OPT_MX,
+
+ /* CACAO options */
+
+ OPT_VERBOSE1,
+ OPT_NOIEEE,
+
+ #if defined(ENABLE_STATISTICS)
+ OPT_TIME,
+ OPT_STAT,
+ #endif
+
+ OPT_LOG,
+ OPT_CHECK,
+ OPT_LOAD,
+ OPT_SHOW,
+ OPT_DEBUGCOLOR,
+
+ #if !defined(NDEBUG)
+ OPT_ALL,
+ OPT_METHOD,
+ OPT_SIGNATURE,
+ #endif
+
+ #if defined(ENABLE_VERIFIER)
+ OPT_NOVERIFY,
+ #if defined(TYPECHECK_VERBOSE)
+ OPT_VERBOSETC,
+ #endif
+ #endif /* defined(ENABLE_VERIFIER) */
+
+ /* optimization options */
+
+ #if defined(ENABLE_LOOP)
+ OPT_OLOOP,
+ #endif
+
+ #if defined(ENABLE_IFCONV)
+ OPT_IFCONV,
+ #endif
+
+ #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ OPT_LSRA,
+ #endif
+
+ #if defined(ENABLE_INTRP)
+ /* interpreter options */
+
+ OPT_NO_DYNAMIC,
+ OPT_NO_REPLICATION,
+ OPT_NO_QUICKSUPER,
+ OPT_STATIC_SUPERS,
+ OPT_TRACE,
+ #endif
+
+ OPT_SS,
+
+ #ifdef ENABLE_JVMTI
+ OPT_DEBUG,
+ OPT_XRUNJDWP,
+ OPT_NOAGENT,
+ OPT_AGENTLIB,
+ OPT_AGENTPATH,
+ #endif
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ OPT_FILTER_VERBOSECALL_INCLUDE,
+ OPT_FILTER_VERBOSECALL_EXCLUDE,
+ OPT_FILTER_SHOW_METHOD,
+ #endif
+
+ DUMMY
+ };
+
+
+ opt_struct opts[] = {
+ { "foo", false, OPT_FOO },
+
+ /* Java options */
+
+ { "jar", false, OPT_JAR },
+
+ { "d32", false, OPT_D32 },
+ { "d64", false, OPT_D64 },
+ { "client", false, OPT_IGNORE },
+ { "server", false, OPT_IGNORE },
+ { "jvm", false, OPT_IGNORE },
+ { "hotspot", false, OPT_IGNORE },
+
+ { "classpath", true, OPT_CLASSPATH },
+ { "cp", true, OPT_CLASSPATH },
+ { "D", true, OPT_D },
+ { "version", false, OPT_VERSION },
+ { "showversion", false, OPT_SHOWVERSION },
+ { "fullversion", false, OPT_FULLVERSION },
+ { "help", false, OPT_HELP },
+ { "?", false, OPT_HELP },
+ { "X", false, OPT_X },
+ { "XX:", true, OPT_XX },
+
+ { "ea:", true, OPT_EA },
+ { "da:", true, OPT_DA },
+ { "ea", false, OPT_EA_NOARG },
+ { "da", false, OPT_DA_NOARG },
+
+ { "enableassertions:", true, OPT_EA },
+ { "disableassertions:", true, OPT_DA },
+ { "enableassertions", false, OPT_EA_NOARG },
+ { "disableassertions", false, OPT_DA_NOARG },
+
+ { "esa", false, OPT_ESA },
+ { "enablesystemassertions", false, OPT_ESA },
+ { "dsa", false, OPT_DSA },
+ { "disablesystemassertions", false, OPT_DSA },
+
+ { "noasyncgc", false, OPT_IGNORE },
+ #if defined(ENABLE_VERIFIER)
+ { "noverify", false, OPT_NOVERIFY },
+ { "Xverify:none", false, OPT_NOVERIFY },
+ #endif
+ { "v", false, OPT_VERBOSE1 },
+ { "verbose:", true, OPT_VERBOSE },
+
+ #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
+ { "verbosetc", false, OPT_VERBOSETC },
+ #endif
+ #if defined(__ALPHA__)
+ { "noieee", false, OPT_NOIEEE },
+ #endif
+ #if defined(ENABLE_STATISTICS)
+ { "time", false, OPT_TIME },
+ { "stat", false, OPT_STAT },
+ #endif
+ { "log", true, OPT_LOG },
+ { "c", true, OPT_CHECK },
+ { "l", false, OPT_LOAD },
+
+ #if !defined(NDEBUG)
+ { "all", false, OPT_ALL },
+ { "sig", true, OPT_SIGNATURE },
+ #endif
+
+ #if defined(ENABLE_LOOP)
+ { "oloop", false, OPT_OLOOP },
+ #endif
+ #if defined(ENABLE_IFCONV)
+ { "ifconv", false, OPT_IFCONV },
+ #endif
+ #if defined(ENABLE_LSRA)
+ { "lsra", false, OPT_LSRA },
+ #endif
+ #if defined(ENABLE_SSA)
+ { "lsra", true, OPT_LSRA },
+ #endif
+
+ #if defined(ENABLE_INTRP)
+ /* interpreter options */
+
+ { "trace", false, OPT_TRACE },
+ { "static-supers", true, OPT_STATIC_SUPERS },
+ { "no-dynamic", false, OPT_NO_DYNAMIC },
+ { "no-replication", false, OPT_NO_REPLICATION },
+ { "no-quicksuper", false, OPT_NO_QUICKSUPER },
+ #endif
+
+ /* JVMTI Agent Command Line Options */
+ #ifdef ENABLE_JVMTI
+ { "agentlib:", true, OPT_AGENTLIB },
+ { "agentpath:", true, OPT_AGENTPATH },
+ #endif
+
+ /* Java non-standard options */
+
+ { "Xjit", false, OPT_JIT },
+ { "Xint", false, OPT_INTRP },
+ { "Xbootclasspath:", true, OPT_BOOTCLASSPATH },
+ { "Xbootclasspath/a:", true, OPT_BOOTCLASSPATH_A },
+ { "Xbootclasspath/p:", true, OPT_BOOTCLASSPATH_P },
+ { "Xbootclasspath/c:", true, OPT_BOOTCLASSPATH_C },
+
+ #ifdef ENABLE_JVMTI
+ { "Xdebug", false, OPT_DEBUG },
+ { "Xnoagent", false, OPT_NOAGENT },
+ { "Xrunjdwp", true, OPT_XRUNJDWP },
+ #endif
+
+ { "Xms", true, OPT_MS },
+ { "ms", true, OPT_MS },
+ { "Xmx", true, OPT_MX },
+ { "mx", true, OPT_MX },
+ { "Xss", true, OPT_SS },
+ { "ss", true, OPT_SS },
+
+ #if defined(ENABLE_PROFILING)
+ { "Xprof:", true, OPT_PROF_OPTION },
+ { "Xprof", false, OPT_PROF },
+ #endif
+
+ /* keep these at the end of the list */
+
+ #if !defined(NDEBUG)
+ { "m", true, OPT_METHOD },
+ #endif
+
+ { "s", true, OPT_SHOW },
+ { "debug-color", false, OPT_DEBUGCOLOR },
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ { "XXfi", true, OPT_FILTER_VERBOSECALL_INCLUDE },
+ { "XXfx", true, OPT_FILTER_VERBOSECALL_EXCLUDE },
+ { "XXfm", true, OPT_FILTER_SHOW_METHOD },
+ #endif
+
+ { NULL, false, 0 }
+ };
+
+
+ /* usage ***********************************************************************
+
+ Prints the correct usage syntax to stdout.
+
+ *******************************************************************************/
+
+ void usage(void)
+ {
+ puts("Usage: cacao [-options] classname [arguments]");
+ puts(" (to run a class file)");
+ puts(" or cacao [-options] -jar jarfile [arguments]");
+ puts(" (to run a standalone jar file)\n");
+
+ puts("where options include:");
+ puts(" -d32 use 32-bit data model if available");
+ puts(" -d64 use 64-bit data model if available");
+ puts(" -client compatibility (currently ignored)");
+ puts(" -server compatibility (currently ignored)");
+ puts(" -jvm compatibility (currently ignored)");
+ puts(" -hotspot compatibility (currently ignored)\n");
+
+ puts(" -cp <path> specify a path to look for classes");
+ puts(" -classpath <path> specify a path to look for classes");
+ puts(" -D<name>=<value> add an entry to the property list");
+ puts(" -verbose[:class|gc|jni] enable specific verbose output");
+ puts(" -version print product version and exit");
+ puts(" -fullversion print jpackage-compatible product version and exit");
+ puts(" -showversion print product version and continue");
+ puts(" -help, -? print this help message");
+ puts(" -X print help on non-standard Java options");
+ puts(" -XX print help on debugging options");
+ puts(" -ea[:<packagename>...|:<classname>]");
+ puts(" -enableassertions[:<packagename>...|:<classname>]");
+ puts(" enable assertions with specified granularity");
+ puts(" -da[:<packagename>...|:<classname>]");
+ puts(" -disableassertions[:<packagename>...|:<classname>]");
+ puts(" disable assertions with specified granularity");
+ puts(" -esa | -enablesystemassertions");
+ puts(" enable system assertions");
+ puts(" -dsa | -disablesystemassertions");
+ puts(" disable system assertions");
+
+ #ifdef ENABLE_JVMTI
+ puts(" -agentlib:<agent-lib-name>=<options> library to load containg JVMTI agent");
+ puts (" for jdwp help use: -agentlib:jdwp=help");
+ puts(" -agentpath:<path-to-agent>=<options> path to library containg JVMTI agent");
+ #endif
+
+ /* exit with error code */
+
+ exit(1);
+ }
+
+
+ static void Xusage(void)
+ {
+ #if defined(ENABLE_JIT)
+ puts(" -Xjit JIT mode execution (default)");
+ #endif
+ #if defined(ENABLE_INTRP)
+ puts(" -Xint interpreter mode execution");
+ #endif
+ puts(" -Xbootclasspath:<zip/jar files and directories separated by :>");
+ puts(" value is set as bootstrap class path");
+ puts(" -Xbootclasspath/a:<zip/jar files and directories separated by :>");
+ puts(" value is appended to the bootstrap class path");
+ puts(" -Xbootclasspath/p:<zip/jar files and directories separated by :>");
+ puts(" value is prepended to the bootstrap class path");
+ puts(" -Xbootclasspath/c:<zip/jar files and directories separated by :>");
+ puts(" value is used as Java core library, but the");
+ puts(" hardcoded VM interface classes are prepended");
+ printf(" -Xms<size> set the initial size of the heap (default: %dMB)\n", HEAP_STARTSIZE / 1024 / 1024);
+ printf(" -Xmx<size> set the maximum size of the heap (default: %dMB)\n", HEAP_MAXSIZE / 1024 / 1024);
+ printf(" -Xss<size> set the thread stack size (default: %dkB)\n", STACK_SIZE / 1024);
+
+ #if defined(ENABLE_PROFILING)
+ puts(" -Xprof[:bb] collect and print profiling data");
+ #endif
+
+ #if defined(ENABLE_JVMTI)
+ /* -Xdebug option depend on gnu classpath JDWP options. options:
+ transport=dt_socket,address=<hostname:port>,server=(y|n),suspend(y|n) */
+ puts(" -Xdebug enable remote debugging\n");
+ puts(" -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
+ puts(" enable remote debugging\n");
+ #endif
+
+ /* exit with error code */
+
+ exit(1);
+ }
+
+
+ #if 0
+ static void XXusage(void)
+ {
+ puts(" -v write state-information");
+ #if !defined(NDEBUG)
+ puts(" -verbose:jit enable specific verbose output");
+ puts(" -debug-color colored output for ANSI terms");
+ #endif
+ #ifdef TYPECHECK_VERBOSE
+ puts(" -verbosetc write debug messages while typechecking");
+ #endif
+ #if defined(__ALPHA__)
+ puts(" -noieee don't use ieee compliant arithmetic");
+ #endif
+ #if defined(ENABLE_VERIFIER)
+ puts(" -noverify don't verify classfiles");
+ #endif
+ #if defined(ENABLE_STATISTICS)
+ puts(" -time measure the runtime");
+ puts(" -stat detailed compiler statistics");
+ #endif
+ puts(" -log logfile specify a name for the logfile");
+ puts(" -c(heck)b(ounds) don't check array bounds");
+ puts(" s(ync) don't check for synchronization");
+ #if defined(ENABLE_LOOP)
+ puts(" -oloop optimize array accesses in loops");
+ #endif
+ puts(" -l don't start the class after loading");
+ #if !defined(NDEBUG)
+ puts(" -all compile all methods, no execution");
+ puts(" -m compile only a specific method");
+ puts(" -sig specify signature for a specific method");
+ #endif
+
+ puts(" -s... show...");
+ puts(" (c)onstants the constant pool");
+ puts(" (m)ethods class fields and methods");
+ puts(" (u)tf the utf - hash");
+ puts(" (i)ntermediate intermediate representation");
+ #if defined(ENABLE_DISASSEMBLER)
+ puts(" (a)ssembler disassembled listing");
+ puts(" n(o)ps show NOPs in disassembler output");
+ #endif
+ puts(" (d)atasegment data segment listing");
+
+ #if defined(ENABLE_IFCONV)
+ puts(" -ifconv use if-conversion");
+ #endif
+ #if defined(ENABLE_LSRA)
+ puts(" -lsra use linear scan register allocation");
+ #endif
+ #if defined(ENABLE_SSA)
+ puts(" -lsra:... use linear scan register allocation (with SSA)");
+ puts(" (d)ead code elimination");
+ puts(" (c)opy propagation");
+ #endif
+ #if defined(ENABLE_DEBUG_FILTER)
+ puts(" -XXfi <regex> begin of dynamic scope for verbosecall filter");
+ puts(" -XXfx <regex> end of dynamic scope for verbosecall filter");
+ puts(" -XXfm <regex> filter for show options");
+ #endif
+ /* exit with error code */
+
+ exit(1);
+ }
+ #endif
+
+
+ /* version *********************************************************************
+
+ Only prints cacao version information.
+
+ *******************************************************************************/
+
+ static void version(bool opt_exit)
+ {
+ puts("java version \""JAVA_VERSION"\"");
+ puts("CACAO version "VERSION"\n");
+
+ puts("Copyright (C) 1996-2005, 2006, 2007, 2008");
+ puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
+ puts("This is free software; see the source for copying conditions. There is NO");
+ puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
+
+ /* exit normally, if requested */
+
+ if (opt_exit)
+ exit(0);
+ }
+
+
+ /* fullversion *****************************************************************
+
+ Prints a Sun compatible version information (required e.g. by
+ jpackage, www.jpackage.org).
+
+ *******************************************************************************/
+
+ static void fullversion(void)
+ {
+ puts("java full version \"cacao-"JAVA_VERSION"\"");
+
+ /* exit normally */
+
+ exit(0);
+ }
+
+
+ static void vm_printconfig(void)
+ {
+ puts("Configure/Build options:\n");
+ puts(" ./configure: "VERSION_CONFIGURE_ARGS"");
+ #if defined(__VERSION__)
+ puts(" CC : "VERSION_CC" ("__VERSION__")");
+ #else
+ puts(" CC : "VERSION_CC"");
+ #endif
+ puts(" CFLAGS : "VERSION_CFLAGS"\n");
+
+ puts("Default variables:\n");
+ printf(" maximum heap size : %d\n", HEAP_MAXSIZE);
+ printf(" initial heap size : %d\n", HEAP_STARTSIZE);
+ printf(" stack size : %d\n", STACK_SIZE);
+
+ #if defined(ENABLE_JRE_LAYOUT)
+ /* When we're building with JRE-layout, the default paths are the
+ same as the runtime paths. */
+ #else
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ puts(" gnu.classpath.boot.library.path: "JAVA_RUNTIME_LIBRARY_LIBDIR);
+ puts(" java.boot.class.path : "CACAO_VM_ZIP":"JAVA_RUNTIME_LIBRARY_CLASSES"");
+ # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ puts(" sun.boot.library.path : "JAVA_RUNTIME_LIBRARY_LIBDIR);
+ puts(" java.boot.class.path : "JAVA_RUNTIME_LIBRARY_CLASSES);
+ # endif
+ #endif
+
+ puts("");
+
+ puts("Runtime variables:\n");
+ printf(" maximum heap size : %d\n", opt_heapmaxsize);
+ printf(" initial heap size : %d\n", opt_heapstartsize);
+ printf(" stack size : %d\n", opt_stacksize);
+
+ #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ printf(" gnu.classpath.boot.library.path: %s\n", properties_get("gnu.classpath.boot.library.path"));
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ printf(" sun.boot.library.path : %s\n", properties_get("sun.boot.library.path"));
+ #endif
+
+ printf(" java.boot.class.path : %s\n", properties_get("java.boot.class.path"));
+ printf(" java.class.path : %s\n", properties_get("java.class.path"));
+ }
+
+
+ /* forward declarations *******************************************************/
+
+ static char *vm_get_mainclass_from_jar(char *mainstring);
+ #if !defined(NDEBUG)
+ static void vm_compile_all(void);
+ static void vm_compile_method(char* mainname);
+ #endif
+
+
+ /**
+ * Implementation for JNI_CreateJavaVM. This function creates a VM
+ * object.
+ *
+ * @param p_vm
+ * @param p_env
+ * @param vm_args
+ *
+ * @return true on success, false otherwise.
+ */
+ bool VM::create(JavaVM** p_vm, void** p_env, void* vm_args)
+ {
+ JavaVMInitArgs* _vm_args;
+
+ // Get the arguments for the new JVM.
+ _vm_args = (JavaVMInitArgs *) vm_args;
+
+ // Instantiate a new VM.
+ try {
+ vm = new VM(_vm_args);
+ }
+ catch (std::exception e) {
+ // FIXME How can we delete the resources allocated?
+ // /* release allocated memory */
+ // FREE(env, _Jv_JNIEnv);
+ // FREE(vm, _Jv_JavaVM);
+
+ vm = NULL;
+
+ return false;
+ }
+
+ // Return the values.
+
+ *p_vm = vm->get_javavm();
+ *p_env = vm->get_jnienv();
+
+ return true;
+ }
+
+
+ /**
+ * C wrapper for VM::create.
+ */
+ extern "C" {
+ bool VM_create(JavaVM** p_vm, void** p_env, void* vm_args)
+ {
+ return VM::create(p_vm, p_env, vm_args);
+ }
+ }
+
+
+ /**
+ * VM constructor.
+ */
+ VM::VM(JavaVMInitArgs* vm_args)
+ {
+ // Very first thing to do: we are initializing.
+ _initializing = true;
+
+ // Make ourself globally visible.
+ // XXX Is this a good idea?
+ vm = this;
+
+ /* create and fill a JavaVM structure */
+
+ _javavm = new JavaVM();
+
+ #if defined(ENABLE_JNI)
+ _javavm->functions = &_Jv_JNIInvokeInterface;
+ #endif
+
+ /* get the VM and Env tables (must be set before vm_create) */
+ /* XXX JVMTI Agents needs a JavaVM */
+
+ _jnienv = new JNIEnv();
+
+ #if defined(ENABLE_JNI)
+ _jnienv->functions = &_Jv_JNINativeInterface;
+ #endif
+
+ /* actually create the JVM */
+
+ int len;
+ char *p;
+ char *boot_class_path;
+ char *class_path;
+ int opt;
+ bool opt_version;
+ bool opt_exit;
+
+ #if defined(ENABLE_JVMTI)
+ lt_dlhandle handle;
+ char *libname, *agentarg;
+ bool jdwp,agentbypath;
+ jdwp = agentbypath = false;
+ #endif
+
+ #if defined(ENABLE_JNI)
+ /* Check the JNI version requested. */
+
+ if (!jni_version_check(vm_args->version))
+ throw std::exception();
+ #endif
+
+ /* We only support 1 JVM instance. */
+
+ if (vms > 0)
+ throw std::exception();
+
+ /* Install the exit handler. */
+
+ if (atexit(vm_exit_handler))
+ vm_abort("atexit failed: %s\n", strerror(errno));
+
+ /* Set some options. */
+
+ opt_version = false;
+ opt_exit = false;
+
+ opt_noieee = false;
+
+ opt_heapmaxsize = HEAP_MAXSIZE;
+ opt_heapstartsize = HEAP_STARTSIZE;
+ opt_stacksize = STACK_SIZE;
+
+ /* Initialize the properties list before command-line handling.
+ Otherwise -XX:+PrintConfig crashes. */
+
+ properties_init();
+
+ /* First of all, parse the -XX options. */
+
+ #if defined(ENABLE_VMLOG)
+ vmlog_cacao_init_options();
+ #endif
+
+ options_xx(vm_args);
+
+ #if defined(ENABLE_VMLOG)
+ vmlog_cacao_init();
+ #endif
+
+ /* We need to check if the actual size of a java.lang.Class object
+ is smaller or equal than the assumption made in
+ src/vm/class.h. */
+
+ #warning FIXME We need to check the size of java.lang.Class!!!
+ // if (sizeof(java_lang_Class) > sizeof(dummy_java_lang_Class))
+ // vm_abort("vm_create: java_lang_Class structure is bigger than classinfo.object (%d > %d)", sizeof(java_lang_Class), sizeof(dummy_java_lang_Class));
+
+ /* set the VM starttime */
+
+ _starttime = builtin_currenttimemillis();
+
+ #if defined(ENABLE_JVMTI)
+ /* initialize JVMTI related **********************************************/
+ jvmti = false;
+ #endif
+
+ /* Fill the properties before command-line handling. */
+
+ properties_set();
+
+ /* iterate over all passed options */
+
+ while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
+ switch (opt) {
+ case OPT_FOO:
+ opt_foo = true;
+ break;
+
+ case OPT_IGNORE:
+ break;
+
+ case OPT_JAR:
+ opt_jar = true;
+ break;
+
+ case OPT_D32:
+ #if SIZEOF_VOID_P == 8
+ puts("Running a 32-bit JVM is not supported on this platform.");
+ exit(1);
+ #endif
+ break;
+
+ case OPT_D64:
+ #if SIZEOF_VOID_P == 4
+ puts("Running a 64-bit JVM is not supported on this platform.");
+ exit(1);
+ #endif
+ break;
+
+ case OPT_CLASSPATH:
+ /* Forget old classpath and set the argument as new
+ classpath. */
+
+ // FIXME Make class_path const char*.
+ class_path = (char*) properties_get("java.class.path");
+
+ p = MNEW(char, strlen(opt_arg) + strlen("0"));
+
+ strcpy(p, opt_arg);
+
+ #if defined(ENABLE_JAVASE)
+ properties_add("java.class.path", p);
+ #endif
+
+ MFREE(class_path, char, strlen(class_path));
+ break;
+
+ case OPT_D:
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ if (opt_arg[i] == '=') {
+ opt_arg[i] = '\0';
+ properties_add(opt_arg, opt_arg + i + 1);
+ goto opt_d_done;
+ }
+ }
+
+ /* if no '=' is given, just create an empty property */
+
+ properties_add(opt_arg, "");
+
+ opt_d_done:
+ break;
+
+ case OPT_BOOTCLASSPATH:
+ /* Forget default bootclasspath and set the argument as
+ new boot classpath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ p = MNEW(char, strlen(opt_arg) + strlen("0"));
+
+ strcpy(p, opt_arg);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, strlen(boot_class_path));
+ break;
+
+ case OPT_BOOTCLASSPATH_A:
+ /* Append to bootclasspath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ len = strlen(boot_class_path);
+
+ // XXX (char*) quick hack
+ p = (char*) MREALLOC(boot_class_path,
+ char,
+ len + strlen("0"),
+ len + strlen(":") +
+ strlen(opt_arg) + strlen("0"));
+
+ strcat(p, ":");
+ strcat(p, opt_arg);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+ break;
+
+ case OPT_BOOTCLASSPATH_P:
+ /* Prepend to bootclasspath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ len = strlen(boot_class_path);
+
+ p = MNEW(char, strlen(opt_arg) + strlen(":") + len + strlen("0"));
+
+ strcpy(p, opt_arg);
+ strcat(p, ":");
+ strcat(p, boot_class_path);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, len);
+ break;
+
+ case OPT_BOOTCLASSPATH_C:
+ /* Use as Java core library, but prepend VM interface
+ classes. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ len =
+ strlen(CACAO_VM_ZIP) +
+ strlen(":") +
+ strlen(opt_arg) +
+ strlen("0");
+
+ p = MNEW(char, len);
+
+ strcpy(p, CACAO_VM_ZIP);
+ strcat(p, ":");
+ strcat(p, opt_arg);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, strlen(boot_class_path));
+ break;
+
+ #if defined(ENABLE_JVMTI)
+ case OPT_DEBUG:
+ /* this option exists only for compatibility reasons */
+ break;
+
+ case OPT_NOAGENT:
+ /* I don't know yet what Xnoagent should do. This is only for
+ compatiblity with eclipse - motse */
+ break;
+
+ case OPT_XRUNJDWP:
+ agentbypath = true;
+ jvmti = true;
+ jdwp = true;
+
+ len =
+ strlen(CACAO_LIBDIR) +
+ strlen("/libjdwp.so=") +
+ strlen(opt_arg) +
+ strlen("0");
+
+ agentarg = MNEW(char, len);
+
+ strcpy(agentarg, CACAO_LIBDIR);
+ strcat(agentarg, "/libjdwp.so=");
+ strcat(agentarg, &opt_arg[1]);
+ break;
+
+ case OPT_AGENTPATH:
+ agentbypath = true;
+
+ case OPT_AGENTLIB:
+ jvmti = true;
+ agentarg = opt_arg;
+ break;
+ #endif
+
+ case OPT_MX:
+ case OPT_MS:
+ case OPT_SS:
+ {
+ char c;
+ int j;
+
+ c = opt_arg[strlen(opt_arg) - 1];
+
+ if ((c == 'k') || (c == 'K')) {
+ j = atoi(opt_arg) * 1024;
+
+ } else if ((c == 'm') || (c == 'M')) {
+ j = atoi(opt_arg) * 1024 * 1024;
+
+ } else
+ j = atoi(opt_arg);
+
+ if (opt == OPT_MX)
+ opt_heapmaxsize = j;
+ else if (opt == OPT_MS)
+ opt_heapstartsize = j;
+ else
+ opt_stacksize = j;
+ }
+ break;
+
+ case OPT_VERBOSE1:
+ opt_verbose = true;
+ break;
+
+ case OPT_VERBOSE:
+ if (strcmp("class", opt_arg) == 0) {
+ opt_verboseclass = true;
+ }
+ else if (strcmp("gc", opt_arg) == 0) {
+ opt_verbosegc = true;
+ }
+ else if (strcmp("jni", opt_arg) == 0) {
+ opt_verbosejni = true;
+ }
+ #if !defined(NDEBUG)
+ else if (strcmp("jit", opt_arg) == 0) {
+ opt_verbose = true;
+ loadverbose = true;
+ initverbose = true;
+ compileverbose = true;
+ }
+ #endif
+ else {
+ printf("Unknown -verbose option: %s\n", opt_arg);
+ usage();
+ }
+ break;
+
+ case OPT_DEBUGCOLOR:
+ opt_debugcolor = true;
+ break;
+
+ #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
+ case OPT_VERBOSETC:
+ opt_typecheckverbose = true;
+ break;
+ #endif
+
+ case OPT_VERSION:
+ opt_version = true;
+ opt_exit = true;
+ break;
+
+ case OPT_FULLVERSION:
+ fullversion();
+ break;
+
+ case OPT_SHOWVERSION:
+ opt_version = true;
+ break;
+
+ case OPT_NOIEEE:
+ opt_noieee = true;
+ break;
+
+ #if defined(ENABLE_VERIFIER)
+ case OPT_NOVERIFY:
+ opt_verify = false;
+ break;
+ #endif
+
+ #if defined(ENABLE_STATISTICS)
+ case OPT_TIME:
+ opt_getcompilingtime = true;
+ opt_getloadingtime = true;
+ break;
+
+ case OPT_STAT:
+ opt_stat = true;
+ break;
+ #endif
+
+ case OPT_LOG:
+ log_init(opt_arg);
+ break;
+
+ case OPT_CHECK:
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'b':
+ checkbounds = false;
+ break;
+ case 's':
+ checksync = false;
+ break;
+ default:
+ usage();
+ }
+ }
+ break;
+
+ case OPT_LOAD:
+ opt_run = false;
+ makeinitializations = false;
+ break;
+
+ #if !defined(NDEBUG)
+ case OPT_ALL:
+ compileall = true;
+ opt_run = false;
+ makeinitializations = false;
+ break;
+
+ case OPT_METHOD:
+ opt_run = false;
+ opt_method = opt_arg;
+ makeinitializations = false;
+ break;
+
+ case OPT_SIGNATURE:
+ opt_signature = opt_arg;
+ break;
+ #endif
+
+ case OPT_SHOW: /* Display options */
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'c':
+ showconstantpool = true;
+ break;
+
+ case 'u':
+ showutf = true;
+ break;
+
+ case 'm':
+ showmethods = true;
+ break;
+
+ case 'i':
+ opt_showintermediate = true;
+ compileverbose = true;
+ break;
+
+ #if defined(ENABLE_DISASSEMBLER)
+ case 'a':
+ opt_showdisassemble = true;
+ compileverbose = true;
+ break;
+
+ case 'o':
+ opt_shownops = true;
+ break;
+ #endif
+
+ case 'd':
+ opt_showddatasegment = true;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ break;
+
+ #if defined(ENABLE_LOOP)
+ case OPT_OLOOP:
+ opt_loops = true;
+ break;
+ #endif
+
+ #if defined(ENABLE_IFCONV)
+ case OPT_IFCONV:
+ opt_ifconv = true;
+ break;
+ #endif
+
+ #if defined(ENABLE_LSRA)
+ case OPT_LSRA:
+ opt_lsra = true;
+ break;
+ #endif
+ #if defined(ENABLE_SSA)
+ case OPT_LSRA:
+ opt_lsra = true;
+ for (unsigned int i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'c':
+ opt_ssa_cp = true;
+ break;
+
+ case 'd':
+ opt_ssa_dce = true;
+ break;
+
+ case ':':
+ break;
+
+ default:
+ usage();
+ }
+ }
+ break;
+ #endif
+
+ case OPT_HELP:
+ usage();
+ break;
+
+ case OPT_X:
+ Xusage();
+ break;
+
+ case OPT_XX:
+ /* Already parsed. */
+ break;
+
+ case OPT_EA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_ea_da(opt_arg, true);
+ #endif
+ break;
+
+ case OPT_DA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_ea_da(opt_arg, false);
+ #endif
+ break;
+
+ case OPT_EA_NOARG:
+ #if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = true;
+ #endif
+ break;
+
+ case OPT_DA_NOARG:
+ #if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = false;
+ #endif
+ break;
+
+ case OPT_ESA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_system_enabled = true;
+ #endif
+ break;
+
+ case OPT_DSA:
+ #if defined(ENABLE_ASSERTION)
+ assertion_system_enabled = false;
+ #endif
+ break;
+
+ #if defined(ENABLE_PROFILING)
+ case OPT_PROF_OPTION:
+ /* use <= to get the last \0 too */
+
+ for (unsigned int i = 0, j = 0; i <= strlen(opt_arg); i++) {
+ if (opt_arg[i] == ',')
+ opt_arg[i] = '\0';
+
+ if (opt_arg[i] == '\0') {
+ if (strcmp("bb", opt_arg + j) == 0)
+ opt_prof_bb = true;
+
+ else {
+ printf("Unknown option: -Xprof:%s\n", opt_arg + j);
+ usage();
+ }
+
+ /* set k to next char */
+
+ j = i + 1;
+ }
+ }
+ /* fall through */
+
+ case OPT_PROF:
+ opt_prof = true;
+ break;
+ #endif
+
+ case OPT_JIT:
+ #if defined(ENABLE_JIT)
+ opt_jit = true;
+ #else
+ printf("-Xjit option not enabled.\n");
+ exit(1);
+ #endif
+ break;
+
+ case OPT_INTRP:
+ #if defined(ENABLE_INTRP)
+ opt_intrp = true;
+ #else
+ printf("-Xint option not enabled.\n");
+ exit(1);
+ #endif
+ break;
+
+ #if defined(ENABLE_INTRP)
+ case OPT_STATIC_SUPERS:
+ opt_static_supers = atoi(opt_arg);
+ break;
+
+ case OPT_NO_DYNAMIC:
+ opt_no_dynamic = true;
+ break;
+
+ case OPT_NO_REPLICATION:
+ opt_no_replication = true;
+ break;
+
+ case OPT_NO_QUICKSUPER:
+ opt_no_quicksuper = true;
+ break;
+
+ case OPT_TRACE:
+ vm_debug = true;
+ break;
+ #endif
+
+ #if defined(ENABLE_DEBUG_FILTER)
+ case OPT_FILTER_VERBOSECALL_INCLUDE:
+ opt_filter_verbosecall_include = opt_arg;
+ break;
+
+ case OPT_FILTER_VERBOSECALL_EXCLUDE:
+ opt_filter_verbosecall_exclude = opt_arg;
+ break;
+
+ case OPT_FILTER_SHOW_METHOD:
+ opt_filter_show_method = opt_arg;
+ break;
+
+ #endif
+ default:
+ printf("Unknown option: %s\n",
+ vm_args->options[opt_index].optionString);
+ usage();
+ }
+ }
+
+ #if defined(ENABLE_JVMTI)
+ if (jvmti) {
+ jvmti_set_phase(JVMTI_PHASE_ONLOAD);
+ jvmti_agentload(agentarg, agentbypath, &handle, &libname);
+
+ if (jdwp)
+ MFREE(agentarg, char, strlen(agentarg));
+
+ jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
+ }
+ #endif
+
+ /* initialize the garbage collector */
+
+ gc_init(opt_heapmaxsize, opt_heapstartsize);
+
+ #if defined(ENABLE_THREADS)
+ /* BEFORE: threads_preinit */
+
+ threadlist_init();
+
+ /* AFTER: gc_init */
+
+ threads_preinit();
+ lock_init();
+ #endif
+
+ /* install architecture dependent signal handlers */
+
+ if (!signal_init())
+ vm_abort("vm_create: signal_init failed");
+
+ #if defined(ENABLE_INTRP)
+ /* Allocate main thread stack on the Java heap. */
+
+ if (opt_intrp) {
+ intrp_main_stack = GCMNEW(u1, opt_stacksize);
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ }
+ #endif
+
+ /* AFTER: threads_preinit */
+
+ if (!string_init())
+ vm_abort("vm_create: string_init failed");
+
+ /* AFTER: threads_preinit */
+
+ utf8_init();
+
+ /* AFTER: thread_preinit */
+
+ if (!suck_init())
+ vm_abort("vm_create: suck_init failed");
+
+ suck_add_from_property("java.endorsed.dirs");
+
+ /* Now we have all options handled and we can print the version
+ information.
+
+ AFTER: suck_add_from_property("java.endorsed.dirs"); */
+
+ if (opt_version)
+ version(opt_exit);
+
+ /* AFTER: utf8_init */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+ suck_add(boot_class_path);
+
+ /* initialize the classcache hashtable stuff: lock, hashtable
+ (must be done _after_ threads_preinit) */
+
+ if (!classcache_init())
+ vm_abort("vm_create: classcache_init failed");
+
+ /* Initialize the code memory management. */
+ /* AFTER: threads_preinit */
+
+ codememory_init();
+
+ /* initialize the finalizer stuff (must be done _after_
+ threads_preinit) */
+
+ if (!finalizer_init())
+ vm_abort("vm_create: finalizer_init failed");
+
+ /* Initialize the JIT compiler. */
+
+ jit_init();
+ code_init();
+ methodtree_init();
+
+ #if defined(ENABLE_PYTHON)
+ pythonpass_init();
+ #endif
+
+ /* BEFORE: loader_preinit */
+
+ Package::initialize();
+
+ /* AFTER: utf8_init, classcache_init */
+
+ loader_preinit();
+ linker_preinit();
+
+ /* AFTER: loader_preinit, linker_preinit */
+
+ primitive_init();
+
+ loader_init();
+ linker_init();
+
+ /* AFTER: loader_init, linker_init */
+
+ primitive_postinit();
+ method_init();
+
+ #if defined(ENABLE_JIT)
+ trap_init();
+ #endif
+
+ if (!builtin_init())
+ vm_abort("vm_create: builtin_init failed");
+
+ /* Initialize the native subsystem. */
+ /* BEFORE: threads_init */
+
+ if (!native_init())
+ vm_abort("vm_create: native_init failed");
+
+ /* Register the native methods implemented in the VM. */
+ /* BEFORE: threads_init */
+
+ nativevm_preinit();
+
+ #if defined(ENABLE_JNI)
+ /* Initialize the JNI subsystem (must be done _before_
+ threads_init, as threads_init can call JNI methods
+ (e.g. NewGlobalRef). */
+
+ if (!jni_init())
+ vm_abort("vm_create: jni_init failed");
+ #endif
+
+ #if defined(ENABLE_JNI) || defined(ENABLE_HANDLES)
+ /* Initialize the local reference table for the main thread. */
+ /* BEFORE: threads_init */
+
+ if (!localref_table_init())
+ vm_abort("vm_create: localref_table_init failed");
+ #endif
+
+ /* Iinitialize some important system classes. */
+ /* BEFORE: threads_init */
+
+ initialize_init();
+
+ #if defined(ENABLE_THREADS)
+ threads_init();
+ #endif
+
+ /* Initialize the native VM subsystem. */
+ /* AFTER: threads_init (at least for SUN's classes) */
+
+ nativevm_init();
+
+ #if defined(ENABLE_PROFILING)
+ /* initialize profiling */
+
+ if (!profile_init())
+ vm_abort("vm_create: profile_init failed");
+ #endif
+
+ #if defined(ENABLE_THREADS)
+ /* initialize recompilation */
+
+ if (!recompile_init())
+ vm_abort("vm_create: recompile_init failed");
+
+ /* start the signal handler thread */
+
+ #if defined(__LINUX__)
+ /* XXX Remove for exact-GC. */
+ if (threads_pthreads_implementation_nptl)
+ #endif
+ if (!signal_start_thread())
+ vm_abort("vm_create: signal_start_thread failed");
+
+ /* finally, start the finalizer thread */
+
+ if (!finalizer_start_thread())
+ vm_abort("vm_create: finalizer_start_thread failed");
+
+ # if !defined(NDEBUG)
+ /* start the memory profiling thread */
+
+ if (opt_ProfileMemoryUsage || opt_ProfileGCMemoryUsage)
+ if (!memory_start_thread())
+ vm_abort("vm_create: memory_start_thread failed");
+ # endif
+
+ /* start the recompilation thread (must be done before the
+ profiling thread) */
+
+ if (!recompile_start_thread())
+ vm_abort("vm_create: recompile_start_thread failed");
+
+ # if defined(ENABLE_PROFILING)
+ /* start the profile sampling thread */
+
+ /* if (opt_prof) */
+ /* if (!profile_start_thread()) */
+ /* vm_abort("vm_create: profile_start_thread failed"); */
+ # endif
+ #endif
+
+ #if defined(ENABLE_JVMTI)
+ # if defined(ENABLE_GC_CACAO)
+ /* XXX this will not work with the new indirection cells for classloaders!!! */
+ assert(0);
+ # endif
+ if (jvmti) {
+ /* add agent library to native library hashtable */
+ native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle);
+ }
+ #endif
+
+ /* Increment the number of VMs. */
+
+ vms++;
+
+ // Initialization is done, VM is created.
+ _created = true;
+ _initializing = false;
+
+ /* Print the VM configuration after all stuff is set and the VM is
+ initialized. */
+
+ if (opt_PrintConfig)
+ vm_printconfig();
+ }
+
+
+ /* vm_run **********************************************************************
+
+ Runs the main-method of the passed class.
+
+ *******************************************************************************/
+
+ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
+ {
+ char* option;
+ char* mainname;
+ char* p;
+ utf *mainutf;
+ classinfo *mainclass;
+ java_handle_t *e;
+ methodinfo *m;
+ java_handle_objectarray_t *oa;
+ s4 oalength;
+ utf *u;
+ java_handle_t *s;
+ int status;
+
+ // Prevent compiler warnings.
+ oa = NULL;
+
+ #if !defined(NDEBUG)
+ if (compileall) {
+ vm_compile_all();
+ return;
+ }
+ #endif
+
+ /* Get the main class plus it's arguments. */
+
+ mainname = NULL;
+
+ if (opt_index < vm_args->nOptions) {
+ /* Get main-class argument. */
+
+ mainname = vm_args->options[opt_index].optionString;
+
+ /* If the main class argument is a jar file, put it into the
+ classpath. */
+
+ if (opt_jar == true) {
+ p = MNEW(char, strlen(mainname) + strlen("0"));
+
+ strcpy(p, mainname);
+
+ #if defined(ENABLE_JAVASE)
+ properties_add("java.class.path", p);
+ #endif
+ }
+ else {
+ /* Replace dots with slashes in the class name. */
+
+ for (unsigned int i = 0; i < strlen(mainname); i++)
+ if (mainname[i] == '.')
+ mainname[i] = '/';
+ }
+
+ /* Build argument array. Move index to first argument. */
+
+ opt_index++;
+
+ oalength = vm_args->nOptions - opt_index;
+
+ oa = builtin_anewarray(oalength, class_java_lang_String);
+
+ for (int i = 0; i < oalength; i++) {
+ option = vm_args->options[opt_index + i].optionString;
+
+ u = utf_new_char(option);
+ s = javastring_new(u);
+
+ array_objectarray_element_set(oa, i, s);
+ }
+ }
+
+ /* Do we have a main-class argument? */
+
+ if (mainname == NULL)
+ usage();
+
+ #if !defined(NDEBUG)
+ if (opt_method != NULL) {
+ vm_compile_method(mainname);
+ return;
+ }
+ #endif
+
+ /* set return value to OK */
+
+ status = 0;
+
+ if (opt_jar == true) {
+ /* open jar file with java.util.jar.JarFile */
+
+ mainname = vm_get_mainclass_from_jar(mainname);
+
+ if (mainname == NULL)
+ vm_exit(1);
+ }
+
+ /* load the main class */
+
+ mainutf = utf_new_char(mainname);
+
+ #if defined(ENABLE_JAVAME_CLDC1_1)
+ mainclass = load_class_bootstrap(mainutf);
+ #else
+ mainclass = load_class_from_sysloader(mainutf);
+ #endif
+
+ /* error loading class */
+
+ e = exceptions_get_and_clear_exception();
+
+ if ((e != NULL) || (mainclass == NULL)) {
+ exceptions_throw_noclassdeffounderror_cause(e);
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ if (!link_class(mainclass)) {
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ /* find the `main' method of the main class */
+
+ m = class_resolveclassmethod(mainclass,
+ utf_new_char("main"),
+ utf_new_char("([Ljava/lang/String;)V"),
+ class_java_lang_Object,
+ false);
+
+ if (exceptions_get_exception()) {
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ /* there is no main method or it isn't static */
+
+ if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+ exceptions_clear_exception();
+ exceptions_throw_nosuchmethoderror(mainclass,
+ utf_new_char("main"),
+ utf_new_char("([Ljava/lang/String;)V"));
+
+ exceptions_print_stacktrace();
+ vm_exit(1);
+ }
+
+ #ifdef TYPEINFO_DEBUG_TEST
+ /* test the typeinfo system */
+ typeinfo_test();
+ #endif
+
+ #if defined(ENABLE_JVMTI)
+ jvmti_set_phase(JVMTI_PHASE_LIVE);
+ #endif
+
+ /* set ThreadMXBean variables */
+
+ // _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+ // _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+ // if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+ // _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+ // _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+ // _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
+ #warning Move to C++
+
+ /* start the main thread */
+
+ (void) vm_call_method(m, NULL, oa);
+
+ /* exception occurred? */
+
+ if (exceptions_get_exception()) {
+ exceptions_print_stacktrace();
+ status = 1;
+ }
+
+ #if defined(ENABLE_THREADS)
+ /* Detach the main thread so that it appears to have ended when
+ the application's main method exits. */
+
+ if (!thread_detach_current_thread())
+ vm_abort("vm_run: Could not detach main thread.");
+ #endif
+
+ /* Destroy the JavaVM. */
+
+ (void) vm_destroy(vm);
+
+ /* And exit. */
+
+ vm_exit(status);
+ }
+
+
+ /* vm_destroy ******************************************************************
+
+ Unloads a Java VM and reclaims its resources.
+
+ *******************************************************************************/
+
+ int vm_destroy(JavaVM *vm)
+ {
+ #if defined(ENABLE_THREADS)
+ /* Create a a trivial new Java waiter thread called
+ "DestroyJavaVM". */
+
+ JavaVMAttachArgs args;
+
+ args.name = (char*) "DestroyJavaVM";
+ args.group = NULL;
+
+ if (!thread_attach_current_thread(&args, false))
+ return 1;
+
+ /* Wait until we are the last non-daemon thread. */
+
+ threads_join_all_threads();
+ #endif
+
+ /* VM is gone. */
+
+ // _created = false;
+ #warning Move to C++
+
+ /* Everything is ok. */
+
+ return 0;
+ }
+
+
+ /* vm_exit *********************************************************************
+
+ Calls java.lang.System.exit(I)V to exit the JavaVM correctly.
+
+ *******************************************************************************/
+
+ void vm_exit(s4 status)
+ {
+ methodinfo *m;
+
+ /* signal that we are exiting */
+
+ // _exiting = true;
+ #warning Move to C++
+
+ assert(class_java_lang_System);
+ assert(class_java_lang_System->state & CLASS_LOADED);
+
+ #if defined(ENABLE_JVMTI)
+ if (jvmti || (dbgcom!=NULL)) {
+ jvmti_set_phase(JVMTI_PHASE_DEAD);
+ if (jvmti) jvmti_agentunload();
+ }
+ #endif
+
+ if (!link_class(class_java_lang_System)) {
+ exceptions_print_stacktrace();
+ exit(1);
+ }
+
+ /* call java.lang.System.exit(I)V */
+
+ m = class_resolveclassmethod(class_java_lang_System,
+ utf_new_char("exit"),
+ utf_int__void,
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ exit(1);
+ }
+
+ /* call the exit function with passed exit status */
+
+ (void) vm_call_method(m, NULL, status);
+
+ /* If we had an exception, just ignore the exception and exit with
+ the proper code. */
+
+ vm_shutdown(status);
+ }
+
+
+ /* vm_shutdown *****************************************************************
+
+ Terminates the system immediately without freeing memory explicitly
+ (to be used only for abnormal termination).
+
+ *******************************************************************************/
+
+ void vm_shutdown(s4 status)
+ {
+ if (opt_verbose
+ #if defined(ENABLE_STATISTICS)
+ || opt_getcompilingtime || opt_stat
+ #endif
+ )
+ {
+ log_text("CACAO terminated by shutdown");
+ dolog("Exit status: %d\n", (s4) status);
+
+ }
+
+ #if defined(ENABLE_JVMTI)
+ /* terminate cacaodbgserver */
+ if (dbgcom!=NULL) {
+ mutex_lock(&dbgcomlock);
+ dbgcom->running=1;
+ mutex_unlock(&dbgcomlock);
+ jvmti_cacaodbgserver_quit();
+ }
+ #endif
+
++#if defined (ENABLE_JITCACHE)
++ jitcache_quit();
++#endif
++
+ exit(status);
+ }
+
+
+ /* vm_exit_handler *************************************************************
+
+ The exit_handler function is called upon program termination.
+
+ ATTENTION: Don't free system resources here! Some threads may still
+ be running as this is called from VMRuntime.exit(). The OS does the
+ cleanup for us.
+
+ *******************************************************************************/
+
+ void vm_exit_handler(void)
+ {
+ #if !defined(NDEBUG)
+ if (showmethods)
+ class_showmethods(mainclass);
+
+ if (showconstantpool)
+ class_showconstantpool(mainclass);
+
+ if (showutf)
+ utf_show();
+
+ # if defined(ENABLE_PROFILING)
+ if (opt_prof)
+ profile_printstats();
+ # endif
+ #endif /* !defined(NDEBUG) */
+
+ #if defined(ENABLE_RT_TIMING)
+ rt_timing_print_time_stats(stderr);
+ #endif
+
+ #if defined(ENABLE_CYCLES_STATS)
+ builtin_print_cycles_stats(stderr);
+ stacktrace_print_cycles_stats(stderr);
+ #endif
+
+ if (opt_verbose
+ #if defined(ENABLE_STATISTICS)
+ || opt_getcompilingtime || opt_stat
+ #endif
+ )
+ {
+ log_text("CACAO terminated");
+
+ #if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ print_stats();
+ #ifdef TYPECHECK_STATISTICS
+ typecheck_print_statistics(get_logfile());
+ #endif
+ }
+
+ if (opt_getcompilingtime)
+ print_times();
+ #endif /* defined(ENABLE_STATISTICS) */
+ }
+ /* vm_print_profile(stderr);*/
+ }
+
+
+ /* vm_abort ********************************************************************
+
+ Prints an error message and aborts the VM.
+
+ IN:
+ text ... error message to print
+
+ *******************************************************************************/
+
+ void vm_abort(const char *text, ...)
+ {
+ va_list ap;
+
+ /* Print the log message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_finish();
+
+ /* Now abort the VM. */
+
+ os::abort();
+ }
+
+
+ /* vm_abort_errnum *************************************************************
+
+ Prints an error message, appends ":" plus the strerror-message of
+ errnum and aborts the VM.
+
+ IN:
+ errnum ... error number
+ text ..... error message to print
+
+ *******************************************************************************/
+
+ void vm_abort_errnum(int errnum, const char *text, ...)
+ {
+ va_list ap;
+
+ /* Print the log message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ /* Print the strerror-message of errnum. */
+
+ log_print(": %s", os::strerror(errnum));
+
+ log_finish();
+
+ /* Now abort the VM. */
+
+ os::abort();
+ }
+
+
+ /* vm_abort_errno **************************************************************
+
+ Equal to vm_abort_errnum, but uses errno to get the error number.
+
+ IN:
+ text ... error message to print
+
+ *******************************************************************************/
+
+ void vm_abort_errno(const char *text, ...)
+ {
+ va_list ap;
+
+ va_start(ap, text);
+ vm_abort_errnum(errno, text, ap);
+ va_end(ap);
+ }
+
+
+ /* vm_abort_disassemble ********************************************************
+
+ Prints an error message, disassemble the given code range (if
+ enabled) and aborts the VM.
+
+ IN:
+ pc.......PC to disassemble
+ count....number of instructions to disassemble
+
+ *******************************************************************************/
+
+ void vm_abort_disassemble(void *pc, int count, const char *text, ...)
+ {
+ va_list ap;
+ #if defined(ENABLE_DISASSEMBLER)
+ int i;
+ #endif
+
+ /* Print debug message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_finish();
+
+ /* Print the PC. */
+
+ #if SIZEOF_VOID_P == 8
+ log_println("PC=0x%016lx", pc);
+ #else
+ log_println("PC=0x%08x", pc);
+ #endif
+
+ #if defined(ENABLE_DISASSEMBLER)
+ log_println("machine instructions at PC:");
+
+ /* Disassemble the given number of instructions. */
+
+ for (i = 0; i < count; i++)
+ // FIXME disassinstr should use void*.
+ pc = disassinstr((u1*) pc);
+ #endif
+
+ vm_abort("Aborting...");
+ }
+
+
+ /* vm_get_mainclass_from_jar ***************************************************
+
+ Gets the name of the main class from a JAR's manifest file.
+
+ *******************************************************************************/
+
+ static char *vm_get_mainclass_from_jar(char *mainname)
+ {
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *s;
+
+ c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+
+ if (c == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ /* create JarFile object */
+
+ o = builtin_new(c);
+
+ if (o == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ s = javastring_new_from_ascii(mainname);
+
+ (void) vm_call_method(m, o, s);
+
+ if (exceptions_get_exception()) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ /* get manifest object */
+
+ m = class_resolveclassmethod(c,
+ utf_new_char("getManifest"),
+ utf_new_char("()Ljava/util/jar/Manifest;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ o = vm_call_method(m, o);
+
+ if (o == NULL) {
+ fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainname);
+ return NULL;
+ }
+
+
+ /* get Main Attributes */
+
+ LLNI_class_get(o, c);
+
+ m = class_resolveclassmethod(c,
+ utf_new_char("getMainAttributes"),
+ utf_new_char("()Ljava/util/jar/Attributes;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ o = vm_call_method(m, o);
+
+ if (o == NULL) {
+ fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainname);
+ return NULL;
+ }
+
+
+ /* get property Main-Class */
+
+ LLNI_class_get(o, c);
+
+ m = class_resolveclassmethod(c,
+ utf_new_char("getValue"),
+ utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL) {
+ exceptions_print_stacktrace();
+ return NULL;
+ }
+
+ s = javastring_new_from_ascii("Main-Class");
+
+ o = vm_call_method(m, o, s);
+
+ if (o == NULL) {
+ fprintf(stderr, "Failed to load Main-Class manifest attribute from\n");
+ fprintf(stderr, "%s\n", mainname);
+ return NULL;
+ }
+
+ return javastring_tochar(o);
+ }
+
+
+ /* vm_compile_all **************************************************************
+
+ Compile all methods found in the bootclasspath.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ static void vm_compile_all(void)
+ {
+ classinfo *c;
+ methodinfo *m;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+ s4 i;
+
+ /* create all classes found in the bootclasspath */
+ /* XXX currently only works with zip/jar's */
+
+ loader_load_all_classes();
+
+ /* link all classes */
+
+ 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;
+
+ if (c == NULL)
+ continue;
+
+ if (!(c->state & CLASS_LINKED)) {
+ if (!link_class(c)) {
+ fprintf(stderr, "Error linking: ");
+ utf_fprint_printable_ascii_classname(stderr, c->name);
+ fprintf(stderr, "\n");
+
+ /* print out exception and cause */
+
+ exceptions_print_current_exception();
+
+ /* goto next class */
+
+ continue;
+ }
+ }
+
+ /* compile all class methods */
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (m->jcode != NULL) {
+ if (!jit_compile(m)) {
+ fprintf(stderr, "Error compiling: ");
+ utf_fprint_printable_ascii_classname(stderr, c->name);
+ fprintf(stderr, ".");
+ utf_fprint_printable_ascii(stderr, m->name);
+ utf_fprint_printable_ascii(stderr, m->descriptor);
+ fprintf(stderr, "\n");
+
+ /* print out exception and cause */
+
+ exceptions_print_current_exception();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ #endif /* !defined(NDEBUG) */
+
+
+ /* vm_compile_method ***********************************************************
+
+ Compile a specific method.
+
+ *******************************************************************************/
+
+ #if !defined(NDEBUG)
+ static void vm_compile_method(char* mainname)
+ {
+ methodinfo *m;
+
+ /* create, load and link the main class */
+
+ mainclass = load_class_bootstrap(utf_new_char(mainname));
+
+ if (mainclass == NULL)
+ exceptions_print_stacktrace();
+
+ if (!link_class(mainclass))
+ exceptions_print_stacktrace();
+
+ if (opt_signature != NULL) {
+ m = class_resolveclassmethod(mainclass,
+ utf_new_char(opt_method),
+ utf_new_char(opt_signature),
+ mainclass,
+ false);
+ }
+ else {
+ m = class_resolveclassmethod(mainclass,
+ utf_new_char(opt_method),
+ NULL,
+ mainclass,
+ false);
+ }
+
+ if (m == NULL)
+ vm_abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+ opt_method, opt_signature ? opt_signature : "");
+
+ jit_compile(m);
+ }
+ #endif /* !defined(NDEBUG) */
+
+
+ /* vm_call_array ***************************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ an argument array.
+
+ ATTENTION: This function has to be used outside the nativeworld.
+
+ *******************************************************************************/
+
+ #define VM_CALL_ARRAY(name, type) \
+ static type vm_call##name##_array(methodinfo *m, uint64_t *array) \
+ { \
+ methoddesc *md; \
+ void *pv; \
+ type value; \
+ \
+ assert(m->code != NULL); \
+ \
+ md = m->parseddesc; \
+ pv = m->code->entrypoint; \
+ \
+ STATISTICS(count_calls_native_to_java++); \
+ \
+ value = asm_vm_call_method##name(pv, array, md->memuse); \
+ \
+ return value; \
+ }
+
+ static java_handle_t *vm_call_array(methodinfo *m, uint64_t *array)
+ {
+ methoddesc *md;
+ void *pv;
+ java_object_t *o;
+
+ assert(m->code != NULL);
+
+ md = m->parseddesc;
+ pv = m->code->entrypoint;
+
+ STATISTICS(count_calls_native_to_java++);
+
+ o = asm_vm_call_method(pv, array, md->memuse);
+
+ if (md->returntype.type == TYPE_VOID)
+ o = NULL;
+
+ return LLNI_WRAP(o);
+ }
+
+ VM_CALL_ARRAY(_int, int32_t)
+ VM_CALL_ARRAY(_long, int64_t)
+ VM_CALL_ARRAY(_float, float)
+ VM_CALL_ARRAY(_double, double)
+
+
+ /* vm_call_method **************************************************************
+
+ Calls a Java method with a variable number of arguments.
+
+ *******************************************************************************/
+
+ #define VM_CALL_METHOD(name, type) \
+ type vm_call_method##name(methodinfo *m, java_handle_t *o, ...) \
+ { \
+ va_list ap; \
+ type value; \
+ \
+ va_start(ap, o); \
+ value = vm_call_method##name##_valist(m, o, ap); \
+ va_end(ap); \
+ \
+ return value; \
+ }
+
+ VM_CALL_METHOD(, java_handle_t *)
+ VM_CALL_METHOD(_int, int32_t)
+ VM_CALL_METHOD(_long, int64_t)
+ VM_CALL_METHOD(_float, float)
+ VM_CALL_METHOD(_double, double)
+
+
+ /* vm_call_method_valist *******************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a va_list.
+
+ *******************************************************************************/
+
+ #define VM_CALL_METHOD_VALIST(name, type) \
+ type vm_call_method##name##_valist(methodinfo *m, java_handle_t *o, \
+ va_list ap) \
+ { \
+ uint64_t *array; \
+ type value; \
+ int32_t dumpmarker; \
+ \
+ if (m->code == NULL) \
+ if (!jit_compile(m)) \
+ return 0; \
+ \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
+ \
+ array = argument_vmarray_from_valist(m, o, ap); \
+ value = vm_call##name##_array(m, array); \
+ \
+ DRELEASE; \
+ THREAD_NATIVEWORLD_ENTER; \
+ \
+ return value; \
+ }
+
+ VM_CALL_METHOD_VALIST(, java_handle_t *)
+ VM_CALL_METHOD_VALIST(_int, int32_t)
+ VM_CALL_METHOD_VALIST(_long, int64_t)
+ VM_CALL_METHOD_VALIST(_float, float)
+ VM_CALL_METHOD_VALIST(_double, double)
+
+
+ /* vm_call_method_jvalue *******************************************************
+
+ Calls a Java method with a variable number of arguments, passed via
+ a jvalue array.
+
+ *******************************************************************************/
+
+ #define VM_CALL_METHOD_JVALUE(name, type) \
+ type vm_call_method##name##_jvalue(methodinfo *m, java_handle_t *o, \
+ const jvalue *args) \
+ { \
+ uint64_t *array; \
+ type value; \
+ int32_t dumpmarker; \
+ \
+ if (m->code == NULL) \
+ if (!jit_compile(m)) \
+ return 0; \
+ \
+ THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
+ \
+ array = argument_vmarray_from_jvalue(m, o, args); \
+ value = vm_call##name##_array(m, array); \
+ \
+ DRELEASE; \
+ THREAD_NATIVEWORLD_ENTER; \
+ \
+ return value; \
+ }
+
+ VM_CALL_METHOD_JVALUE(, java_handle_t *)
+ VM_CALL_METHOD_JVALUE(_int, int32_t)
+ VM_CALL_METHOD_JVALUE(_long, int64_t)
+ VM_CALL_METHOD_JVALUE(_float, float)
+ VM_CALL_METHOD_JVALUE(_double, double)
+
+
+ /* vm_call_method_objectarray **************************************************
+
+ Calls a Java method with a variable number if arguments, passed via
+ an objectarray of boxed values. Returns a boxed value.
+
+ *******************************************************************************/
+
+ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
+ java_handle_objectarray_t *params)
+ {
+ uint64_t *array;
+ java_handle_t *xptr;
+ java_handle_t *ro;
+ imm_union value;
+ int32_t dumpmarker;
+
+ /* Prevent compiler warnings. */
+
+ ro = NULL;
+
+ /* compile methods which are not yet compiled */
+
+ if (m->code == NULL)
+ if (!jit_compile(m))
+ return NULL;
+
+ /* leave the nativeworld */
+
+ THREAD_NATIVEWORLD_EXIT;
+
+ /* mark start of dump memory area */
+
+ DMARKER;
+
+ /* Fill the argument array from a object-array. */
+
+ array = argument_vmarray_from_objectarray(m, o, params);
+
+ if (array == NULL) {
+ /* release dump area */
+
+ DRELEASE;
+
+ /* enter the nativeworld again */
+
+ THREAD_NATIVEWORLD_ENTER;
+
+ exceptions_throw_illegalargumentexception();
+
+ return NULL;
+ }
+
+ switch (m->parseddesc->returntype.primitivetype) {
+ case PRIMITIVETYPE_VOID:
+ value.a = vm_call_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ value.i = vm_call_int_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ value.l = vm_call_long_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ value.f = vm_call_float_array(m, array);
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ value.d = vm_call_double_array(m, array);
+ break;
+
+ case TYPE_ADR:
+ ro = vm_call_array(m, array);
+ break;
+
+ default:
+ vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
+ }
+
+ /* release dump area */
+
+ DRELEASE;
+
+ /* enter the nativeworld again */
+
+ THREAD_NATIVEWORLD_ENTER;
+
+ /* box the return value if necesarry */
+
+ if (m->parseddesc->returntype.primitivetype != TYPE_ADR)
+ ro = Primitive::box(m->parseddesc->returntype.primitivetype, value);
+
+ /* check for an exception */
+
+ xptr = exceptions_get_exception();
+
+ if (xptr != NULL) {
+ /* clear exception pointer, we are calling JIT code again */
+
+ exceptions_clear_exception();
+
+ exceptions_throw_invocationtargetexception(xptr);
+ }
+
+ return ro;
+ }
+
+
+ /* Legacy C interface *********************************************************/
+
+ extern "C" {
+
+ JavaVM* VM_get_javavm() { return vm->get_javavm(); }
+ JNIEnv* VM_get_jnienv() { return vm->get_jnienv(); }
+ bool VM_is_initializing() { return vm->is_initializing(); }
+ bool VM_is_created() { return vm->is_created(); }
+ int64_t VM_get_starttime() { return vm->get_starttime(); }
+
+ }
+
+
+ /*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */