X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=loader.c;h=0d83a6aa57ceae99b3585031d3553972de88519e;hb=45379aa278d184dbfd0b2eca0208879fca2a226d;hp=4c499b31654244840a1e785c0c42da1751c31466;hpb=dc6e70341980bdb12ca13dd2d8b5c526681624dc;p=cacao.git diff --git a/loader.c b/loader.c index 4c499b316..0d83a6aa5 100644 --- a/loader.c +++ b/loader.c @@ -1,45 +1,66 @@ +/* loader.c - class loader functions -/* loader.c ******************************************************************** + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 + R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, + M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, + P. Tomsich, J. Wenninger - Copyright (c) 1999 A. Krall, R. Grafl, R. Obermaiser, M. Probst + This file is part of CACAO. - See file COPYRIGHT for information on usage and disclaimer of warranties + 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. - Contains the functions of the class loader. + 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. - Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at - Changes: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at - Roman Obermaiser EMAIL: cacao@complang.tuwien.ac.at - Mark Probst EMAIL: cacao@complang.tuwien.ac.at + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. - Last Change: 1999/11/08 + Contact: cacao@complang.tuwien.ac.at -*******************************************************************************/ + Authors: Reinhard Grafl + Changes: Andreas Krall + Roman Obermaiser + Mark Probst + Edwin Steiner + $Id: loader.c 771 2003-12-13 23:11:08Z stefan $ + +*/ -#include +#include +#include +#include #include "global.h" #include "loader.h" +#include "main.h" #include "native.h" #include "tables.h" #include "builtin.h" #include "jit.h" -#ifdef OLD_COMPILER -#include "compiler.h" -#endif #include "asmpart.h" - -#ifdef USE_BOEHM #include "toolbox/memory.h" -#endif - +#include "toolbox/loging.h" #include "threads/thread.h" +#include "threads/locks.h" #include -/* global variables ***********************************************************/ +#ifdef USE_ZLIB +#include "unzip.h" +#endif -extern bool newcompiler; /* true if new compiler is used */ +#undef JOWENN_DEBUG +#undef JOWENN_DEBUG1 +#undef JOWENN_DEBUG2 + +/* global variables ***********************************************************/ int count_class_infos = 0; /* variables for measurements */ int count_const_pool_len = 0; @@ -50,15 +71,6 @@ int count_extable_len = 0; int count_class_loads = 0; int count_class_inits = 0; -bool loadverbose = false; /* switches for debug messages */ -bool linkverbose = false; -bool initverbose = false; - -bool makeinitializations = true; - -bool getloadingtime = false; /* to measure the runtime */ -long int loadingtime = 0; - static s4 interfaceindex; /* sequential numbering of interfaces */ list unloadedclasses; /* list of all referenced but not loaded classes */ @@ -68,29 +80,63 @@ list linkedclasses; /* list of all completely linked classes */ /* utf-symbols for pointer comparison of frequently used strings */ -static utf *utf_innerclasses; /* InnerClasses */ -static utf *utf_constantvalue; /* ConstantValue */ -static utf *utf_code; /* Code */ -static utf *utf_finalize; /* finalize */ -static utf *utf_fidesc; /* ()V */ -static utf *utf_clinit; /* */ +static utf *utf_innerclasses; /* InnerClasses */ +static utf *utf_constantvalue; /* ConstantValue */ +static utf *utf_code; /* Code */ +static utf *utf_finalize; /* finalize */ +static utf *utf_fidesc; /* ()V changed */ +static utf *utf_clinit; /* */ static utf *utf_initsystemclass; /* initializeSystemClass */ -static utf *utf_systemclass; /* java/lang/System */ +static utf *utf_systemclass; /* java/lang/System */ +static utf *utf_vmclassloader; /* java/lang/VMClassLoader */ +static utf *utf_vmclass; /* java/lang/VMClassLoader */ +static utf *utf_initialize; +static utf *utf_initializedesc; + + +#ifdef USE_ZLIB +static unzFile uf = 0; +#endif + + +utf* clinit_desc(){ + return utf_fidesc; +} +utf* clinit_name(){ + return utf_clinit; +} /* important system classes ***************************************************/ classinfo *class_java_lang_Object; classinfo *class_java_lang_String; -classinfo *class_java_lang_ClassCastException; -classinfo *class_java_lang_NullPointerException; -classinfo *class_java_lang_ArrayIndexOutOfBoundsException; -classinfo *class_java_lang_NegativeArraySizeException; -classinfo *class_java_lang_OutOfMemoryError; -classinfo *class_java_lang_ArithmeticException; -classinfo *class_java_lang_ArrayStoreException; -classinfo *class_java_lang_ThreadDeath; -classinfo *class_array = NULL; + +classinfo *class_java_lang_Throwable; +classinfo *class_java_lang_Cloneable; +classinfo *class_java_io_Serializable; + +/* Pseudo classes for the typechecker */ +classinfo *pseudo_class_Arraystub = NULL; +classinfo *pseudo_class_Null = NULL; +classinfo *pseudo_class_New = NULL; +vftbl *pseudo_class_Arraystub_vftbl = NULL; + +/* stefan */ +/* These are made static so they cannot be used for throwing in native */ +/* functions. */ +static classinfo *class_java_lang_ClassCastException; +static classinfo *class_java_lang_NullPointerException; +static classinfo *class_java_lang_ArrayIndexOutOfBoundsException; +static classinfo *class_java_lang_NegativeArraySizeException; +static classinfo *class_java_lang_OutOfMemoryError; +static classinfo *class_java_lang_ArithmeticException; +static classinfo *class_java_lang_ArrayStoreException; +static classinfo *class_java_lang_ThreadDeath; + +static methodinfo method_clone_array; + +static int loader_inited = 0; /****************************************************************************** @@ -100,18 +146,20 @@ classinfo *class_array = NULL; the one character type signature and the name of the primitive class ******************************************************************************/ - -primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { - { NULL, NULL, "java/lang/Double", 'D', "double" }, - { NULL, NULL, "java/lang/Float", 'F', "float" }, - { NULL, NULL, "java/lang/Character", 'C', "char" }, - { NULL, NULL, "java/lang/Integer", 'I', "int" }, - { NULL, NULL, "java/lang/Long", 'J', "long" }, - { NULL, NULL, "java/lang/Byte", 'B', "byte" }, - { NULL, NULL, "java/lang/Short", 'S', "short" }, - { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" }, - { NULL, NULL, "java/lang/Void", 'V', "void" }}; +/* CAUTION: Don't change the order of the types. This table is indexed + * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT). + */ +primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { + { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL }, + { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL }, + { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL }, + { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL }, + { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL }, + { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL }, + { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL }, + { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL }, + { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }}; /* instances of important system classes **************************************/ @@ -124,7 +172,6 @@ java_objectheader *proto_java_lang_ArithmeticException; java_objectheader *proto_java_lang_ArrayStoreException; java_objectheader *proto_java_lang_ThreadDeath; - /************* functions for reading classdata ********************************* getting classdata in blocks of variable size @@ -137,17 +184,29 @@ static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */ static u1 *classbuf_pos; /* current position in classfile buffer */ static int classbuffer_size; /* size of classfile-data */ +/* assert that at least bytes are left to read */ +/* is limited to the range of non-negative s4 values */ +#define ASSERT_LEFT(len) \ + do {if ( ((s4)(len)) < 0 \ + || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \ + panic("Unexpected end of classfile"); } while(0) + /* transfer block of classfile data into a buffer */ -#define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \ - classbuf_pos+=len; +#define suck_nbytes(buffer,len) \ + do {ASSERT_LEFT(len); \ + memcpy(buffer,classbuf_pos+1,len); \ + classbuf_pos+=len;} while (0) /* skip block of classfile data */ -#define skip_nbytes(len) classbuf_pos+=len; +#define skip_nbytes(len) \ + do {ASSERT_LEFT(len); \ + classbuf_pos+=len;} while(0) inline u1 suck_u1() { + ASSERT_LEFT(1); return *++classbuf_pos; } inline u2 suck_u2() @@ -167,14 +226,13 @@ inline u4 suck_u4() /* get u8 from classfile data */ - -static u8 suck_u8 () +static u8 suck_u8() { #if U8_AVAILABLE - u8 lo,hi; + u8 lo, hi; hi = suck_u4(); lo = suck_u4(); - return (hi<<32) + lo; + return (hi << 32) + lo; #else u8 v; v.high = suck_u4(); @@ -183,19 +241,19 @@ static u8 suck_u8 () #endif } -/* get float from classfile data */ -static float suck_float () +/* get float from classfile data */ +static float suck_float() { float f; #if !WORDS_BIGENDIAN u1 buffer[4]; u2 i; - for (i=0; i<4; i++) buffer[3-i] = suck_u1 (); - memcpy ( (u1*) (&f), buffer, 4); + for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1(); + memcpy((u1*) (&f), buffer, 4); #else - suck_nbytes ( (u1*) (&f), 4 ); + suck_nbytes((u1*) (&f), 4); #endif PANICIF (sizeof(float) != 4, "Incompatible float-format"); @@ -203,18 +261,19 @@ static float suck_float () return f; } + /* get double from classfile data */ -static double suck_double () +static double suck_double() { double d; #if !WORDS_BIGENDIAN u1 buffer[8]; u2 i; - for (i=0; i<8; i++) buffer[7-i] = suck_u1 (); - memcpy ( (u1*) (&d), buffer, 8); + for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 (); + memcpy((u1*) (&d), buffer, 8); #else - suck_nbytes ( (u1*) (&d), 8 ); + suck_nbytes((u1*) (&d), 8); #endif PANICIF (sizeof(double) != 8, "Incompatible double-format" ); @@ -222,13 +281,14 @@ static double suck_double () return d; } + /************************** function suck_init ********************************* called once at startup, sets the searchpath for the classfiles *******************************************************************************/ -void suck_init (char *cpath) +void suck_init(char *cpath) { classpath = cpath; classbuffer = NULL; @@ -244,8 +304,8 @@ void suck_init (char *cpath) *******************************************************************************/ - -bool suck_start (utf *classname) { +bool suck_start(utf *classname) +{ #define MAXFILENAME 1000 /* maximum length of a filename */ @@ -255,7 +315,8 @@ bool suck_start (utf *classname) { FILE *classfile; int filenamelen, err; struct stat buffer; - + int isZip; + if (classbuffer) /* classbuffer is already valid */ return true; @@ -271,49 +332,99 @@ bool suck_start (utf *classname) { /* extract directory from searchpath */ filenamelen = 0; - while ((*pathpos) && (*pathpos!=':')) { - PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ; + while ((*pathpos) && (*pathpos != ':')) { + PANICIF (filenamelen >= MAXFILENAME, "Filename too long"); filename[filenamelen++] = *(pathpos++); } - filename[filenamelen++] = '/'; + isZip = 0; + if (filenamelen > 4) { + if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) & + ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) & + ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) { + isZip = 1; + } + } + + if (isZip) { +#ifdef USE_ZLIB + filename[filenamelen++] = '\0'; + if (uf == 0) uf = unzOpen(filename); + if (uf != 0) { + utf_ptr = classname->text; + filenamelen = 0; + while (utf_ptr < utf_end(classname)) { + PANICIF (filenamelen >= MAXFILENAME, "Filename too long"); + c = *utf_ptr++; + if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */ + c = '?'; + filename[filenamelen++] = c; + } + strcpy(filename + filenamelen, ".class"); + if (cacao_locate(uf,classname) == UNZ_OK) { + unz_file_info file_info; + log_text("Class found in zip file"); + if (unzGetCurrentFileInfo(uf, &file_info, filename, + sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) { + if (unzOpenCurrentFile(uf) == UNZ_OK) { + classbuffer_size = file_info.uncompressed_size; + classbuffer = MNEW(u1, classbuffer_size); + classbuf_pos = classbuffer - 1; + /*printf("classfile size: %d\n",file_info.uncompressed_size);*/ + if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) { + unzCloseCurrentFile(uf); + return true; + } else { + MFREE(classbuffer, u1, classbuffer_size); + log_text("Error while unzipping"); + } + } else log_text("Error while opening file in archive"); + } else log_text("Error while retrieving fileinfo"); + } + unzCloseCurrentFile(uf); + + } +#endif + } else { + filename[filenamelen++] = '/'; - /* add classname to filename */ - - utf_ptr = classname->text; - while (utf_ptr < utf_end(classname)) { - PANICIF (filenamelen >= MAXFILENAME, "Filename too long"); - c = *utf_ptr++; - if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */ - c = '?'; - filename[filenamelen++] = c; + /* add classname to filename */ + + utf_ptr = classname->text; + while (utf_ptr < utf_end(classname)) { + PANICIF (filenamelen >= MAXFILENAME, "Filename too long"); + c = *utf_ptr++; + if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */ + c = '?'; + filename[filenamelen++] = c; } - - /* add suffix */ + + /* add suffix */ - strcpy (filename+filenamelen, ".class"); + strcpy(filename + filenamelen, ".class"); - classfile = fopen(filename, "r"); - if (classfile) { /* file exists */ - - /* determine size of classfile */ + classfile = fopen(filename, "r"); + if (classfile) { /* file exists */ + + /* determine size of classfile */ - err = stat (filename, &buffer); + /* dolog("File: %s",filename); */ - if (!err) { /* read classfile data */ - classbuffer_size = buffer.st_size; - classbuffer = MNEW(u1, classbuffer_size); - classbuf_pos = classbuffer-1; - fread(classbuffer, 1, classbuffer_size, classfile); - fclose(classfile); - return true; + err = stat(filename, &buffer); + + if (!err) { /* read classfile data */ + classbuffer_size = buffer.st_size; + classbuffer = MNEW(u1, classbuffer_size); + classbuf_pos = classbuffer - 1; + fread(classbuffer, 1, classbuffer_size, classfile); + fclose(classfile); + return true; + } } } } - if (verbose) { - sprintf (logtext, "Warning: Can not open class file '%s'", filename); - dolog(); + dolog("Warning: Can not open class file '%s'", filename); } return false; @@ -328,17 +439,17 @@ bool suck_start (utf *classname) { *******************************************************************************/ -void suck_stop () { - +void suck_stop() +{ /* determine amount of classdata not retrieved by suck-operations */ - int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1); + int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1); - if (classdata_left > 0) { + if (classdata_left > 0) { /* surplus */ - sprintf (logtext,"There are %d access bytes at end of classfile", - classdata_left); - dolog(); + dolog("There are %d access bytes at end of classfile", + classdata_left); + /* XXX panic? */ } /* free memory */ @@ -347,14 +458,30 @@ void suck_stop () { classbuffer = NULL; } + /******************************************************************************/ /******************* Some support functions ***********************************/ /******************************************************************************/ -/********** internal function: printflags (only for debugging) ***************/ -static void printflags (u2 f) +void fprintflags (FILE *fp, u2 f) +{ + if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC"); + if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE"); + if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED"); + if ( f & ACC_STATIC ) fprintf (fp," STATIC"); + if ( f & ACC_FINAL ) fprintf (fp," FINAL"); + if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED"); + if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE"); + if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT"); + if ( f & ACC_NATIVE ) fprintf (fp," NATIVE"); + if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE"); + if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT"); +} + +/********** internal function: printflags (only for debugging) ***************/ +void printflags (u2 f) { if ( f & ACC_PUBLIC ) printf (" PUBLIC"); if ( f & ACC_PRIVATE ) printf (" PRIVATE"); @@ -378,8 +505,10 @@ static void printflags (u2 f) static void skipattribute () { + u4 len; suck_u2 (); - skip_nbytes(suck_u4()); + len = suck_u4(); + skip_nbytes(len); } /********************** Function: skipattributebody **************************** @@ -391,7 +520,9 @@ static void skipattribute () static void skipattributebody () { - skip_nbytes(suck_u4()); + u4 len; + len = suck_u4(); + skip_nbytes(len); } /************************* Function: skipattributes **************************** @@ -425,9 +556,8 @@ voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype) /* check type of constantpool entry */ if (c->cptags[pos] != ctype) { - sprintf (logtext, "Type mismatch on constant: %d requested, %d here", + error ("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)", (int) ctype, (int) c->cptags[pos] ); - error(); } return c->cpinfos[pos]; @@ -487,76 +617,41 @@ static void attribute_load (u4 num, classinfo *c) static void checkfielddescriptor (char *utf_ptr, char *end_pos) { + class_from_descriptor(utf_ptr,end_pos,NULL, + CLASSLOAD_NEW + | CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NOVOID + | CLASSLOAD_CHECKEND); +#if 0 char *tstart; /* pointer to start of classname */ char ch; - - switch (*utf_ptr++) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - case 'J': - case 'F': - case 'D': - /* primitive type */ - break; - - case 'L': - /* save start of classname */ - tstart = utf_ptr; - - /* determine length of classname */ - while ( *utf_ptr++ != ';' ) - if (utf_ptr>=end_pos) - panic ("Missing ';' in objecttype-descriptor"); - - /* cause loading of referenced class */ - class_new ( utf_new(tstart, utf_ptr-tstart-1) ); - break; - - case '[' : - /* array type */ - while ((ch = *utf_ptr++)=='[') - /* skip */ ; - - /* component type of array */ - switch (ch) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - case 'J': - case 'F': - case 'D': - /* primitive type */ - break; - - case 'L': - /* save start of classname */ - tstart = utf_ptr; - - /* determine length of classname */ - while ( *utf_ptr++ != ';' ) - if (utf_ptr>=end_pos) - panic ("Missing ';' in objecttype-descriptor"); - - /* cause loading of referenced class */ - class_new ( utf_new(tstart, utf_ptr-tstart-1) ); - break; + char *start = utf_ptr; - default: - panic ("Ill formed methodtype-descriptor"); - } - break; - - default: - panic ("Ill formed methodtype-descriptor"); + switch (*utf_ptr++) { + case 'B': + case 'C': + case 'I': + case 'S': + case 'Z': + case 'J': + case 'F': + case 'D': + /* primitive type */ + break; + + case '[': + case 'L': + if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW)) + panic ("Ill formed descriptor"); + break; + + default: + panic ("Ill formed descriptor"); } - - /* exceeding characters */ + + /* exceeding characters */ if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars"); +#endif } @@ -571,14 +666,32 @@ static void checkmethoddescriptor (utf *d) { char *utf_ptr = d->text; /* current position in utf text */ char *end_pos = utf_end(d); /* points behind utf string */ - char *tstart; /* pointer to start of classname */ - char c,ch; /* method descriptor must start with parenthesis */ - if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); + if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); + + /* check arguments */ + while (utf_ptr != end_pos && *utf_ptr != ')') { + class_from_descriptor(utf_ptr,end_pos,&utf_ptr, + CLASSLOAD_NEW + | CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_NOVOID); + } + if (utf_ptr == end_pos) panic("Missing return type in method descriptor"); + utf_ptr++; /* skip ')' */ + + class_from_descriptor(utf_ptr,end_pos,NULL, + CLASSLOAD_NEW + | CLASSLOAD_NULLPRIMITIVE + | CLASSLOAD_CHECKEND); + +#if 0 + /* XXX check length */ /* check arguments */ while ((c = *utf_ptr++) != ')') { + start = utf_ptr-1; + switch (c) { case 'B': case 'C': @@ -591,58 +704,15 @@ static void checkmethoddescriptor (utf *d) /* primitive type */ break; + case '[': case 'L': - /* save start of classname */ - tstart = utf_ptr; - - /* determine length of classname */ - while ( *utf_ptr++ != ';' ) - if (utf_ptr>=end_pos) - panic ("Missing ';' in objecttype-descriptor"); - - /* cause loading of referenced class */ - class_new ( utf_new(tstart, utf_ptr-tstart-1) ); - break; - - case '[' : - /* array type */ - while ((ch = *utf_ptr++)=='[') - /* skip */ ; - - /* component type of array */ - switch (ch) { - case 'B': - case 'C': - case 'I': - case 'S': - case 'Z': - case 'J': - case 'F': - case 'D': - /* primitive type */ - break; - - case 'L': - /* save start of classname */ - tstart = utf_ptr; - - /* determine length of classname */ - while ( *utf_ptr++ != ';' ) - if (utf_ptr>=end_pos) - panic ("Missing ';' in objecttype-descriptor"); - - /* cause loading of referenced class */ - class_new ( utf_new(tstart, utf_ptr-tstart-1) ); - break; - - default: - panic ("Ill formed methodtype-descriptor"); - } + if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW)) + panic ("Ill formed method descriptor"); break; default: panic ("Ill formed methodtype-descriptor"); - } + } } /* check returntype */ @@ -653,89 +723,47 @@ static void checkmethoddescriptor (utf *d) else /* treat as field-descriptor */ checkfielddescriptor (utf_ptr,end_pos); -} - - -/******************** Function: buildarraydescriptor *************************** - - creates a constant_arraydescriptor structure for the array type named by an - utf string - -*******************************************************************************/ - -constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen) -{ - constant_arraydescriptor *d; - - if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array"); - - d = NEW (constant_arraydescriptor); - d -> objectclass = NULL; - d -> elementdescriptor = NULL; - -#ifdef STATISTICS - count_const_pool_len += sizeof(constant_arraydescriptor); #endif - - switch (*utf_ptr) { - case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break; - case 'B': d -> arraytype = ARRAYTYPE_BYTE; break; - case 'C': d -> arraytype = ARRAYTYPE_CHAR; break; - case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break; - case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break; - case 'I': d -> arraytype = ARRAYTYPE_INT; break; - case 'J': d -> arraytype = ARRAYTYPE_LONG; break; - case 'S': d -> arraytype = ARRAYTYPE_SHORT; break; - - case '[': - d -> arraytype = ARRAYTYPE_ARRAY; - d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1); - break; - - case 'L': - d -> arraytype = ARRAYTYPE_OBJECT; - d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) ); - break; - } - return d; } -/******************* Function: freearraydescriptor ***************************** +/***************** Function: print_arraydescriptor **************************** - removes a structure created by buildarraydescriptor from memory + Debugging helper for displaying an arraydescriptor *******************************************************************************/ -static void freearraydescriptor (constant_arraydescriptor *d) +void print_arraydescriptor(FILE *file, arraydescriptor *desc) { - while (d) { - constant_arraydescriptor *n = d->elementdescriptor; - FREE (d, constant_arraydescriptor); - d = n; - } -} - -/*********************** Function: displayarraydescriptor *********************/ + if (!desc) { + fprintf(file, ""); + return; + } -static void displayarraydescriptor (constant_arraydescriptor *d) -{ - switch (d->arraytype) { - case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break; - case ARRAYTYPE_BYTE: printf ("byte[]"); break; - case ARRAYTYPE_CHAR: printf ("char[]"); break; - case ARRAYTYPE_DOUBLE: printf ("double[]"); break; - case ARRAYTYPE_FLOAT: printf ("float[]"); break; - case ARRAYTYPE_INT: printf ("int[]"); break; - case ARRAYTYPE_LONG: printf ("long[]"); break; - case ARRAYTYPE_SHORT: printf ("short[]"); break; - case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break; - case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break; + fprintf(file, "{"); + if (desc->componentvftbl) { + if (desc->componentvftbl->class) + utf_fprint(file, desc->componentvftbl->class->name); + else + fprintf(file, ""); + } + else + fprintf(file, "0"); + + fprintf(file, ","); + if (desc->elementvftbl) { + if (desc->elementvftbl->class) + utf_fprint(file, desc->elementvftbl->class->name); + else + fprintf(file, ""); } + else + fprintf(file, "0"); + fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension, + desc->dataoffset, desc->componentsize); } - /******************************************************************************/ /************************** Functions for fields ****************************/ /******************************************************************************/ @@ -759,13 +787,15 @@ static void field_load (fieldinfo *f, classinfo *c) f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */ f -> type = jtype = desc_to_type (f->descriptor); /* data type */ f -> offset = 0; /* offset from start of object */ + f -> class = c; + f->xta = NULL; switch (f->type) { case TYPE_INT: f->value.i = 0; break; case TYPE_FLOAT: f->value.f = 0.0; break; case TYPE_DOUBLE: f->value.d = 0.0; break; case TYPE_ADDRESS: f->value.a = NULL; - heap_addreference (&(f->value.a)); /* make global reference (GC) */ +/* heap_addreference (&(f->value.a)); /* make global reference (GC) */ break; case TYPE_LONG: #if U8_AVAILABLE @@ -855,15 +885,15 @@ static void field_free (fieldinfo *f) /**************** Function: field_display (debugging only) ********************/ -static void field_display (fieldinfo *f) +void field_display(fieldinfo *f) { - printf (" "); - printflags (f -> flags); - printf (" "); - utf_display (f -> name); - printf (" "); - utf_display (f -> descriptor); - printf (" offset: %ld\n", (long int) (f -> offset) ); + printf(" "); + printflags(f->flags); + printf(" "); + utf_display(f->name); + printf(" "); + utf_display(f->descriptor); + printf(" offset: %ld\n", (long int) (f->offset)); } @@ -881,124 +911,140 @@ static void field_display (fieldinfo *f) *******************************************************************************/ -static void method_load (methodinfo *m, classinfo *c) +static void method_load(methodinfo *m, classinfo *c) { - u4 attrnum,i,e; + u4 attrnum, i, e; #ifdef STATISTICS count_all_methods++; #endif - m -> class = c; + m->class = c; - m -> flags = suck_u2 (); - m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); - m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); + m->flags = suck_u2(); + m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); + m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); + checkmethoddescriptor(m->descriptor); - m -> jcode = NULL; - m -> exceptiontable = NULL; - m -> entrypoint = NULL; - m -> mcode = NULL; - m -> stubroutine = NULL; + m->jcode = NULL; + m->exceptiontable = NULL; + m->entrypoint = NULL; + m->mcode = NULL; + m->stubroutine = NULL; + m->methodUsed = NOTUSED; + m->monoPoly = MONO; + m->subRedefs = 0; + m->subRedefsUsed = 0; + + m->xta = NULL; - if (! (m->flags & ACC_NATIVE) ) { - m -> stubroutine = createcompilerstub (m); - } - else { + if (!(m->flags & ACC_NATIVE)) { + m->stubroutine = createcompilerstub(m); - functionptr f = native_findfunction - (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0); + } else { + functionptr f = native_findfunction(c->name, m->name, m->descriptor, + (m->flags & ACC_STATIC) != 0); if (f) { -#ifdef OLD_COMPILER - if (newcompiler) -#endif - m -> stubroutine = createnativestub (f, m); -#ifdef OLD_COMPILER - else - m -> stubroutine = oldcreatenativestub (f, m); -#endif - } + m->stubroutine = createnativestub(f, m); } + } attrnum = suck_u2(); - for (i=0; i jcode) panic ("Two code-attributes for one method!"); + if (aname != utf_code) { + skipattributebody(); + + } else { + u4 codelen; + if (m->jcode) + panic("Two code-attributes for one method!"); suck_u4(); - m -> maxstack = suck_u2(); - m -> maxlocals = suck_u2(); - m -> jcodelength = suck_u4(); - m -> jcode = MNEW (u1, m->jcodelength); - suck_nbytes (m->jcode, m->jcodelength); - m -> exceptiontablelength = suck_u2 (); - m -> exceptiontable = - MNEW (exceptiontable, m->exceptiontablelength); + m->maxstack = suck_u2(); + m->maxlocals = suck_u2(); + codelen = suck_u4(); + if (codelen == 0) + panic("bytecode has zero length"); + if (codelen > 65536) + panic("bytecode too long"); + m->jcodelength = codelen; + m->jcode = MNEW(u1, m->jcodelength); + suck_nbytes(m->jcode, m->jcodelength); + m->exceptiontablelength = suck_u2(); + m->exceptiontable = + MNEW(exceptiontable, m->exceptiontablelength); #ifdef STATISTICS - count_vmcode_len += m->jcodelength + 18; - count_extable_len += 8 * m->exceptiontablelength; + count_vmcode_len += m->jcodelength + 18; + count_extable_len += 8 * m->exceptiontablelength; #endif - for (e=0; e < m->exceptiontablelength; e++) { + for (e = 0; e < m->exceptiontablelength; e++) { u4 idx; - m -> exceptiontable[e].startpc = suck_u2(); - m -> exceptiontable[e].endpc = suck_u2(); - m -> exceptiontable[e].handlerpc = suck_u2(); + m->exceptiontable[e].startpc = suck_u2(); + m->exceptiontable[e].endpc = suck_u2(); + m->exceptiontable[e].handlerpc = suck_u2(); idx = suck_u2(); - if (!idx) m -> exceptiontable[e].catchtype = NULL; - else { - m -> exceptiontable[e].catchtype = - class_getconstant (c, idx, CONSTANT_Class); - } - } + if (!idx) { + m->exceptiontable[e].catchtype = NULL; - skipattributes ( suck_u2() ); - } - - } + } else { + m->exceptiontable[e].catchtype = + class_getconstant(c, idx, CONSTANT_Class); + } + } + skipattributes(suck_u2()); + } + } } + /********************* Function: method_free *********************************** frees all memory that was allocated for this method *******************************************************************************/ -static void method_free (methodinfo *m) +static void method_free(methodinfo *m) { - if (m->jcode) MFREE (m->jcode, u1, m->jcodelength); - if (m->exceptiontable) - MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength); - if (m->mcode) CFREE (m->mcode, m->mcodelength); + if (m->jcode) + MFREE(m->jcode, u1, m->jcodelength); + + if (m->exceptiontable) + MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength); + + if (m->mcode) + CFREE(m->mcode, m->mcodelength); + if (m->stubroutine) { - if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine); - else removecompilerstub (m->stubroutine); + if (m->flags & ACC_NATIVE) { + removenativestub(m->stubroutine); + + } else { + removecompilerstub(m->stubroutine); } + } } /************** Function: method_display (debugging only) **************/ -void method_display (methodinfo *m) +void method_display(methodinfo *m) { - printf (" "); - printflags (m -> flags); - printf (" "); - utf_display (m -> name); - printf (" "); - utf_display (m -> descriptor); - printf ("\n"); + printf(" "); + printflags(m->flags); + printf(" "); + utf_display(m->name); + printf(" "); + utf_display(m->descriptor); + printf("\n"); } @@ -1025,25 +1071,26 @@ static bool method_canoverwrite (methodinfo *m, methodinfo *old) /******************************************************************************/ -/******************** function: class_getconstant ****************************** +/******************** function:: class_getconstant ****************************** retrieves the value at position 'pos' of the constantpool of a class if the type of the value is other than 'ctype' the system is stopped *******************************************************************************/ -voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) +voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype) { /* invalid position in constantpool */ - if (pos >= c->cpcount) - panic ("Attempt to access constant outside range"); + if (pos >= c->cpcount) + panic("Attempt to access constant outside range"); /* check type of constantpool entry */ + if (c->cptags[pos] != ctype) { - sprintf (logtext, "Type mismatch on constant: %d requested, %d here", - (int) ctype, (int) c->cptags[pos] ); - error(); - } + class_showconstantpool(c); + error("Type mismatch on constant: %d requested, %d here (class_getconstant)", + (int) ctype, (int) c->cptags[pos]); + } return c->cpinfos[pos]; } @@ -1055,10 +1102,11 @@ voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) *******************************************************************************/ -u4 class_constanttype (classinfo *c, u4 pos) +u4 class_constanttype(classinfo *c, u4 pos) { - if (pos >= c->cpcount) - panic ("Attempt to access constant outside range"); + if (pos >= c->cpcount) + panic("Attempt to access constant outside range"); + return c->cptags[pos]; } @@ -1072,7 +1120,7 @@ u4 class_constanttype (classinfo *c, u4 pos) *******************************************************************************/ -static void class_loadcpool (classinfo *c) +static void class_loadcpool(classinfo *c) { /* The following structures are used to save information which cannot be @@ -1273,6 +1321,10 @@ static void class_loadcpool (classinfo *c) /* number of bytes in the bytes array (not string-length) */ u4 length = suck_u2(); cptags [idx] = CONSTANT_Utf8; + /* validate the string */ + ASSERT_LEFT(length); + if (!is_valid_utf(classbuf_pos+1, classbuf_pos+1+length)) + panic("Invalid UTF-8 string"); /* insert utf-string into the utf-symboltable */ cpinfos [idx] = utf_new(classbuf_pos+1, length); /* skip bytes of the string */ @@ -1282,8 +1334,7 @@ static void class_loadcpool (classinfo *c) } default: - sprintf (logtext, "Unkown constant type: %d",(int) t); - error (); + error ("Unkown constant type: %d",(int) t); } /* end switch */ @@ -1296,21 +1347,11 @@ static void class_loadcpool (classinfo *c) while (forward_classes) { utf *name = class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8); - - if ( (name->blength>0) && (name->text[0]=='[') ) { - /* check validity of descriptor */ - checkfielddescriptor (name->text, utf_end(name)); - cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor; - cpinfos [forward_classes -> thisindex] = - buildarraydescriptor(name->text, name->blength); + cptags [forward_classes -> thisindex] = CONSTANT_Class; + /* retrieve class from class-table */ + cpinfos [forward_classes -> thisindex] = class_new (name); - } - else { - cptags [forward_classes -> thisindex] = CONSTANT_Class; - /* retrieve class from class-table */ - cpinfos [forward_classes -> thisindex] = class_new (name); - } forward_classes = forward_classes -> next; } @@ -1318,7 +1359,11 @@ static void class_loadcpool (classinfo *c) while (forward_strings) { utf *text = class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8); - +/* + log_text("forward_string:"); + printf( "classpoolid: %d\n",forward_strings -> thisindex); + utf_display(text); + log_text("\n------------------"); */ /* resolve utf-string */ cptags [forward_strings -> thisindex] = CONSTANT_String; cpinfos [forward_strings -> thisindex] = text; @@ -1357,6 +1402,21 @@ static void class_loadcpool (classinfo *c) nat = class_getconstant (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType); +#ifdef JOWENN_DEBUG + log_text("trying to resolve:"); + log_text(nat->name->text); + switch(forward_fieldmethints ->tag) { + case CONSTANT_Fieldref: + log_text("CONSTANT_Fieldref"); + break; + case CONSTANT_InterfaceMethodref: + log_text("CONSTANT_InterfaceMethodref"); + break; + case CONSTANT_Methodref: + log_text("CONSTANT_Methodref"); + break; + } +#endif fmi -> class = class_getconstant (c, forward_fieldmethints -> class_index, CONSTANT_Class); fmi -> name = nat -> name; @@ -1371,6 +1431,7 @@ static void class_loadcpool (classinfo *c) break; case CONSTANT_InterfaceMethodref: case CONSTANT_Methodref: /* check validity of descriptor */ + /* XXX check special names () */ checkmethoddescriptor (fmi->descriptor); break; } @@ -1379,6 +1440,7 @@ static void class_loadcpool (classinfo *c) } +/* class_showconstantpool(c); */ dump_release (dumpsize); } @@ -1397,7 +1459,7 @@ static void class_loadcpool (classinfo *c) *******************************************************************************/ -static int class_load (classinfo *c) +static int class_load(classinfo *c) { u4 i; u4 mi,ma; @@ -1408,14 +1470,16 @@ static int class_load (classinfo *c) /* output for debugging purposes */ if (loadverbose) { - sprintf (logtext, "Loading class: "); - utf_sprint (logtext+strlen(logtext), c->name ); - dolog(); - } + char logtext[MAXLOGTEXT]; + sprintf(logtext, "Loading class: "); + utf_sprint(logtext + strlen(logtext), c->name); + log_text(logtext); + } /* load classdata, throw exception on error */ - if (!suck_start (c->name)) { - throw_classnotfoundexception(); + + if (!suck_start(c->name)) { + throw_noclassdeffounderror_message(c->name); return false; } @@ -1425,69 +1489,75 @@ static int class_load (classinfo *c) mi = suck_u2(); ma = suck_u2(); if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) { - sprintf (logtext, "File version %d.%d is not supported", - (int) ma, (int) mi); - error(); - } + error("File version %d.%d is not supported", (int) ma, (int) mi); + } + class_loadcpool(c); + /*JOWENN*/ + c->erroneous_state = 0; + c->initializing_thread = 0; + /*JOWENN*/ + c->classUsed = NOTUSED; /* not used initially CO-RT */ + c->impldBy = NULL; - class_loadcpool (c); - /* ACC flags */ - c -> flags = suck_u2 (); + c->flags = suck_u2(); + /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/ + /* this class */ - suck_u2 (); + suck_u2(); /* retrieve superclass */ - if ( (i = suck_u2 () ) ) { - c -> super = class_getconstant (c, i, CONSTANT_Class); - } - else { - c -> super = NULL; - } + if ((i = suck_u2())) { + c->super = class_getconstant(c, i, CONSTANT_Class); + + } else { + c->super = NULL; + } /* retrieve interfaces */ - c -> interfacescount = suck_u2 (); - c -> interfaces = MNEW (classinfo*, c -> interfacescount); - for (i=0; i < c -> interfacescount; i++) { - c -> interfaces [i] = - class_getconstant (c, suck_u2(), CONSTANT_Class); - } + c->interfacescount = suck_u2(); + c->interfaces = MNEW(classinfo*, c->interfacescount); + for (i = 0; i < c->interfacescount; i++) { + c->interfaces [i] = + class_getconstant(c, suck_u2(), CONSTANT_Class); + } /* load fields */ - c -> fieldscount = suck_u2 (); -#ifdef USE_BOEHM - c -> fields = GCNEW (fieldinfo, c -> fieldscount); -#else - c -> fields = MNEW (fieldinfo, c -> fieldscount); -#endif - for (i=0; i < c -> fieldscount; i++) { - field_load (&(c->fields[i]), c); - } + c->fieldscount = suck_u2(); +/* utf_display(c->name); + printf(" ,Fieldscount: %d\n",c->fieldscount);*/ + + c->fields = GCNEW(fieldinfo, c->fieldscount); + for (i = 0; i < c->fieldscount; i++) { + field_load(&(c->fields[i]), c); + } /* load methods */ - c -> methodscount = suck_u2 (); - c -> methods = MNEW (methodinfo, c -> methodscount); - for (i=0; i < c -> methodscount; i++) { - method_load (&(c -> methods [i]), c); - } + c->methodscount = suck_u2(); + c->methods = MNEW(methodinfo, c->methodscount); + for (i = 0; i < c->methodscount; i++) { + method_load(&(c->methods[i]), c); + } #ifdef STATISTICS - count_class_infos += sizeof(classinfo*) * c -> interfacescount; - count_class_infos += sizeof(fieldinfo) * c -> fieldscount; - count_class_infos += sizeof(methodinfo) * c -> methodscount; + count_class_infos += sizeof(classinfo*) * c->interfacescount; + count_class_infos += sizeof(fieldinfo) * c->fieldscount; + count_class_infos += sizeof(methodinfo) * c->methodscount; #endif /* load variable-length attribute structures */ - attribute_load (suck_u2(), c); + attribute_load(suck_u2(), c); /* free memory */ - suck_stop (); + suck_stop(); /* remove class from list of unloaded classes and add to list of unlinked classes */ - list_remove (&unloadedclasses, c); - list_addlast (&unlinkedclasses, c); + list_remove(&unloadedclasses, c); + list_addlast(&unlinkedclasses, c); + + c->loaded = true; return true; } @@ -1501,22 +1571,24 @@ static int class_load (classinfo *c) *******************************************************************************/ -static s4 class_highestinterface (classinfo *c) +static s4 class_highestinterface(classinfo *c) { s4 h; s4 i; - if ( ! (c->flags & ACC_INTERFACE) ) { - sprintf (logtext, "Interface-methods count requested for non-interface: "); - utf_sprint (logtext+strlen(logtext), c->name); - error(); - } + if (!(c->flags & ACC_INTERFACE)) { + char logtext[MAXLOGTEXT]; + sprintf(logtext, "Interface-methods count requested for non-interface: "); + utf_sprint(logtext + strlen(logtext), c->name); + error(logtext); + } h = c->index; - for (i=0; iinterfacescount; i++) { - s4 h2 = class_highestinterface (c->interfaces[i]); - if (h2>h) h=h2; - } + for (i = 0; i < c->interfacescount; i++) { + s4 h2 = class_highestinterface(c->interfaces[i]); + if (h2 > h) h = h2; + } + return h; } @@ -1575,6 +1647,182 @@ static void class_addinterface (classinfo *c, classinfo *ic) } +/******************* Function: class_new_array ********************************* + + This function is called by class_new to setup an array class. + +*******************************************************************************/ + +void class_new_array(classinfo *c) +{ + classinfo *comp = NULL; + methodinfo *clone; + int namelen; + + /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */ + + /* Array classes are not loaded from classfiles. */ + list_remove (&unloadedclasses, c); + + /* Check array class name */ + namelen = c->name->blength; + if (namelen < 2 || c->name->text[0] != '[') + panic("Invalid array class name"); + + /* Check the component type */ + switch (c->name->text[1]) { + case '[': + /* c is an array of arrays. We have to create the component class. */ + comp = class_new(utf_new(c->name->text + 1,namelen - 1)); + break; + + case 'L': + /* c is an array of objects. */ + if (namelen < 4 || c->name->text[namelen-1] != ';') + panic("Invalid array class name"); + comp = class_new(utf_new(c->name->text + 2,namelen - 3)); + break; + } + + /* Setup the array class */ + c->super = class_java_lang_Object; + c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT; + + c->interfacescount = 2; + c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */ + c->interfaces[0] = class_java_lang_Cloneable; + c->interfaces[1] = class_java_io_Serializable; + + c->methodscount = 1; + c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */ + + clone = c->methods; + memset(clone, 0, sizeof(methodinfo)); + clone->flags = ACC_PUBLIC; /* XXX protected? */ + clone->name = utf_new_char("clone"); + clone->descriptor = utf_new_char("()Ljava/lang/Object;"); + clone->class = c; + clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone); + clone->monoPoly = MONO; /* XXX should be poly? */ + + /* XXX: field: length? */ + + /* The array class has to be linked */ + list_addlast(&unlinkedclasses,c); + + /* + * Array classes which are created after the other classes have been + * loaded and linked are linked explicitely. + */ + c->loaded=true; + + if (loader_inited) + loader_load(c->name); /* XXX handle errors */ +} + + +/****************** Function: class_link_array ********************************* + + This function is called by class_link to create the + arraydescriptor for an array class. + + This function returns NULL if the array cannot be linked because + the component type has not been linked yet. + +*******************************************************************************/ + +static arraydescriptor *class_link_array(classinfo *c) +{ + classinfo *comp = NULL; + int namelen = c->name->blength; + arraydescriptor *desc; + vftbl *compvftbl; + + /* Check the component type */ + switch (c->name->text[1]) { + case '[': + /* c is an array of arrays. */ + comp = class_get(utf_new(c->name->text + 1,namelen - 1)); + if (!comp) panic("Could not find component array class."); + break; + + case 'L': + /* c is an array of objects. */ + comp = class_get(utf_new(c->name->text + 2,namelen - 3)); + if (!comp) panic("Could not find component class."); + break; + } + + /* If the component type has not been linked return NULL */ + if (comp && !comp->linked) + return NULL; + + /* Allocate the arraydescriptor */ + desc = NEW(arraydescriptor); + + if (comp) { + /* c is an array of references */ + desc->arraytype = ARRAYTYPE_OBJECT; + desc->componentsize = sizeof(void*); + desc->dataoffset = OFFSET(java_objectarray,data); + + compvftbl = comp->vftbl; + if (!compvftbl) + panic("Component class has no vftbl."); + desc->componentvftbl = compvftbl; + + if (compvftbl->arraydesc) { + desc->elementvftbl = compvftbl->arraydesc->elementvftbl; + desc->dimension = compvftbl->arraydesc->dimension + 1; + desc->elementtype = compvftbl->arraydesc->elementtype; + } + else { + desc->elementvftbl = compvftbl; + desc->dimension = 1; + desc->elementtype = ARRAYTYPE_OBJECT; + } + } + else { + /* c is an array of a primitive type */ + switch (c->name->text[1]) { + case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN; + desc->dataoffset = OFFSET(java_booleanarray,data); + desc->componentsize = sizeof(u1); break; + case 'B': desc->arraytype = ARRAYTYPE_BYTE; + desc->dataoffset = OFFSET(java_bytearray,data); + desc->componentsize = sizeof(u1); break; + case 'C': desc->arraytype = ARRAYTYPE_CHAR; + desc->dataoffset = OFFSET(java_chararray,data); + desc->componentsize = sizeof(u2); break; + case 'D': desc->arraytype = ARRAYTYPE_DOUBLE; + desc->dataoffset = OFFSET(java_doublearray,data); + desc->componentsize = sizeof(double); break; + case 'F': desc->arraytype = ARRAYTYPE_FLOAT; + desc->dataoffset = OFFSET(java_floatarray,data); + desc->componentsize = sizeof(float); break; + case 'I': desc->arraytype = ARRAYTYPE_INT; + desc->dataoffset = OFFSET(java_intarray,data); + desc->componentsize = sizeof(s4); break; + case 'J': desc->arraytype = ARRAYTYPE_LONG; + desc->dataoffset = OFFSET(java_longarray,data); + desc->componentsize = sizeof(s8); break; + case 'S': desc->arraytype = ARRAYTYPE_SHORT; + desc->dataoffset = OFFSET(java_shortarray,data); + desc->componentsize = sizeof(s2); break; + default: + panic("Invalid array class name"); + } + + desc->componentvftbl = NULL; + desc->elementvftbl = NULL; + desc->dimension = 1; + desc->elementtype = desc->arraytype; + } + + return desc; +} + + /********************** Function: class_link *********************************** Tries to link a class. The super class and every implemented interface must @@ -1591,7 +1839,7 @@ static void class_addinterface (classinfo *c, classinfo *ic) *******************************************************************************/ -static void class_link (classinfo *c) +void class_link(classinfo *c) { s4 supervftbllength; /* vftbllegnth of super class */ s4 vftbllength; /* vftbllength of current class */ @@ -1599,7 +1847,8 @@ static void class_link (classinfo *c) classinfo *super = c->super; /* super class */ classinfo *ic, *c2; /* intermediate class variables */ vftbl *v; /* vftbl of current class */ - s4 i; /* interface/method/field counter */ + s4 i; /* interface/method/field counter */ + arraydescriptor *arraydesc = NULL; /* descriptor for array classes */ /* check if all superclasses are already linked, if not put c at end of @@ -1613,26 +1862,36 @@ static void class_link (classinfo *c) list_remove(&unlinkedclasses, c); list_addlast(&unlinkedclasses, c); return; - } } + } /* check super class */ if (super == NULL) { /* class java.long.Object */ c->index = 0; + c->classUsed = USED; /* Object class is always used CO-RT*/ + c -> impldBy = NULL; c->instancesize = sizeof(java_objectheader); vftbllength = supervftbllength = 0; c->finalizer = NULL; - } - else { + + } else { if (!super->linked) { list_remove(&unlinkedclasses, c); list_addlast(&unlinkedclasses, c); return; - } + } + /* handle array classes */ + if (c->name->text[0] == '[') + if ((arraydesc = class_link_array(c)) == NULL) { + list_remove(&unlinkedclasses, c); + list_addlast(&unlinkedclasses, c); + return; + } + if (c->flags & ACC_INTERFACE) c->index = interfaceindex++; else @@ -1643,14 +1902,15 @@ static void class_link (classinfo *c) vftbllength = supervftbllength = super->vftbl->vftbllength; c->finalizer = super->finalizer; - } + } if (linkverbose) { - sprintf (logtext, "Linking Class: "); - utf_sprint (logtext+strlen(logtext), c->name ); - dolog (); - } + char logtext[MAXLOGTEXT]; + sprintf(logtext, "Linking Class: "); + utf_sprint(logtext + strlen(logtext), c->name ); + log_text(logtext); + } /* compute vftbl length */ @@ -1665,17 +1925,17 @@ static void class_link (classinfo *c) if (method_canoverwrite(m, &(sc->methods[j]))) { m->vftblindex = sc->methods[j].vftblindex; goto foundvftblindex; - } } - sc = sc->super; } - m->vftblindex = (vftbllength++); -foundvftblindex: ; + sc = sc->super; } - } + m->vftblindex = (vftbllength++); + foundvftblindex: ; + } + } #ifdef STATISTICS - count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1); + count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1)); #endif /* compute interfacetable length */ @@ -1687,26 +1947,31 @@ foundvftblindex: ; s4 h = class_highestinterface (c2->interfaces[i]) + 1; if (h > interfacetablelength) interfacetablelength = h; - } - c2 = c2->super; } + c2 = c2->super; + } /* allocate virtual function table */ v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) * - (vftbllength - 1) + sizeof(methodptr*) * - (interfacetablelength - (interfacetablelength > 0))); + (vftbllength - 1) + sizeof(methodptr*) * + (interfacetablelength - (interfacetablelength > 0))); v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) * - (interfacetablelength > 1)); + (interfacetablelength > 1)); c->header.vftbl = c->vftbl = v; v->class = c; v->vftbllength = vftbllength; v->interfacetablelength = interfacetablelength; + v->arraydesc = arraydesc; + + /* store interface index in vftbl */ + if (c->flags & ACC_INTERFACE) + v->baseval = -(c->index); /* copy virtual function table of super class */ for (i = 0; i < supervftbllength; i++) - v->table[i] = super->vftbl->table[i]; + v->table[i] = super->vftbl->table[i]; /* add method stubs into virtual function table */ @@ -1714,8 +1979,8 @@ foundvftblindex: ; methodinfo *m = &(c->methods[i]); if (!(m->flags & ACC_STATIC)) { v->table[m->vftblindex] = m->stubroutine; - } } + } /* compute instance size and offset of each field */ @@ -1724,16 +1989,16 @@ foundvftblindex: ; fieldinfo *f = &(c->fields[i]); if (!(f->flags & ACC_STATIC) ) { - dsize = desc_typesize (f->descriptor); - c->instancesize = ALIGN (c->instancesize, dsize); + dsize = desc_typesize(f->descriptor); + c->instancesize = ALIGN(c->instancesize, dsize); f->offset = c->instancesize; c->instancesize += dsize; - } } + } /* initialize interfacetable and interfacevftbllength */ - v->interfacevftbllength = MNEW (s4, interfacetablelength); + v->interfacevftbllength = MNEW(s4, interfacetablelength); #ifdef STATISTICS count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength; @@ -1742,14 +2007,14 @@ foundvftblindex: ; for (i = 0; i < interfacetablelength; i++) { v->interfacevftbllength[i] = 0; v->interfacetable[-i] = NULL; - } + } /* add interfaces */ for (c2 = c; c2 != NULL; c2 = c2->super) for (i = 0; i < c2->interfacescount; i++) { - class_addinterface (c, c2->interfaces[i]); - } + class_addinterface(c, c2->interfaces[i]); + } /* add finalizer method (not for java.lang.Object) */ @@ -1763,20 +2028,20 @@ foundvftblindex: ; if (fidesc == NULL) fidesc = utf_fidesc; - fi = class_findmethod (c, finame, fidesc); + fi = class_findmethod(c, finame, fidesc); if (fi != NULL) { if (!(fi->flags & ACC_STATIC)) { c->finalizer = fi; - } } } + } /* final tasks */ c->linked = true; - list_remove (&unlinkedclasses, c); - list_addlast (&linkedclasses, c); + list_remove(&unlinkedclasses, c); + list_addlast(&linkedclasses, c); } @@ -1818,9 +2083,6 @@ static void class_freecpool (classinfo *c) case CONSTANT_NameAndType: FREE (info, constant_nameandtype); break; - case CONSTANT_Arraydescriptor: - freearraydescriptor (info); - break; } } } @@ -1836,45 +2098,49 @@ static void class_freecpool (classinfo *c) *******************************************************************************/ -static void class_free (classinfo *c) +static void class_free(classinfo *c) { s4 i; vftbl *v; - class_freecpool (c); + class_freecpool(c); - MFREE (c->interfaces, classinfo*, c->interfacescount); + MFREE(c->interfaces, classinfo*, c->interfacescount); for (i = 0; i < c->fieldscount; i++) field_free(&(c->fields[i])); -#ifndef USE_BOEHM - MFREE (c->fields, fieldinfo, c->fieldscount); -#endif for (i = 0; i < c->methodscount; i++) method_free(&(c->methods[i])); - MFREE (c->methods, methodinfo, c->methodscount); + 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); + MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]); + } + MFREE(v->interfacevftbllength, s4, v->interfacetablelength); i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) + sizeof(methodptr*) * (v->interfacetablelength - (v->interfacetablelength > 0)); v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) * (v->interfacetablelength > 1)); - mem_free (v, i); - } + mem_free(v, i); + } if (c->innerclasscount) - MFREE (c->innerclass, innerclassinfo, c->innerclasscount); + MFREE(c->innerclass, innerclassinfo, c->innerclasscount); - FREE (c, classinfo); + /* if (c->classvftbl) + mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */ + + GCFREE(c); } + /************************* Function: class_findfield *************************** Searches a 'classinfo' structure for a field having the given name and @@ -1882,21 +2148,88 @@ static void class_free (classinfo *c) *******************************************************************************/ - -fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc) +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]); } - panic ("Can not find field given in CONSTANT_Fieldref"); + panic("Can not find field given in CONSTANT_Fieldref"); + + /* keep compiler happy */ return NULL; } +/************************* Function: class_findmethod ************************** + + Searches a 'classinfo' structure for a method having the given name and + type and returns the index in the class info structure. + If type is NULL, it is ignored. + +*******************************************************************************/ + +s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc) +{ + s4 i; +#if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2) + char *buffer; + int buffer_len, pos; +#endif +#ifdef JOWENN_DEBUG1 + + buffer_len = + utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64; + + buffer = MNEW(char, buffer_len); + + strcpy(buffer, "class_findmethod: method:"); + utf_sprint(buffer + strlen(buffer), name); + strcpy(buffer + strlen(buffer), ", desc: "); + utf_sprint(buffer + strlen(buffer), desc); + strcpy(buffer + strlen(buffer), ", classname: "); + utf_sprint(buffer + strlen(buffer), c->name); + + log_text(buffer); + + MFREE(buffer, char, buffer_len); +#endif + for (i = 0; i < c->methodscount; i++) { +#ifdef JOWENN_DEBUG2 + buffer_len = + utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64; + + buffer = MNEW(char, buffer_len); + + strcpy(buffer, "class_findmethod: comparing to method:"); + utf_sprint(buffer + strlen(buffer), c->methods[i].name); + strcpy(buffer + strlen(buffer), ", desc: "); + utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor); + + log_text(buffer); + + MFREE(buffer, char, buffer_len); +#endif + + + if ((c->methods[i].name == name) && ((desc == NULL) || + (c->methods[i].descriptor == desc))) { + return i; + } + } + +#ifdef JOWENN_DEBUG2 + class_showconstantpool(c); + log_text("class_findmethod: returning NULL"); +#endif + + return -1; +} + + /************************* Function: class_findmethod ************************** Searches a 'classinfo' structure for a method having the given name and @@ -1905,17 +2238,91 @@ fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc) *******************************************************************************/ -methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc) +methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc) { +#if 0 s4 i; +#if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2) + char *buffer; + int buffer_len, pos; +#endif +#ifdef JOWENN_DEBUG1 + + buffer_len = + utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64; + + buffer = MNEW(char, buffer_len); + + strcpy(buffer, "class_findmethod: method:"); + utf_sprint(buffer + strlen(buffer), name); + strcpy(buffer + strlen(buffer), ", desc: "); + utf_sprint(buffer + strlen(buffer), desc); + strcpy(buffer + strlen(buffer), ", classname: "); + utf_sprint(buffer + strlen(buffer), c->name); + + log_text(buffer); + + MFREE(buffer, char, buffer_len); +#endif for (i = 0; i < c->methodscount; i++) { +#ifdef JOWENN_DEBUG2 + buffer_len = + utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64; + + buffer = MNEW(char, buffer_len); + + strcpy(buffer, "class_findmethod: comparing to method:"); + utf_sprint(buffer + strlen(buffer), c->methods[i].name); + strcpy(buffer + strlen(buffer), ", desc: "); + utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor); + + log_text(buffer); + + MFREE(buffer, char, buffer_len); +#endif + if ((c->methods[i].name == name) && ((desc == NULL) || - (c->methods[i].descriptor == desc))) + (c->methods[i].descriptor == desc))) { return &(c->methods[i]); } + } +#ifdef JOWENN_DEBUG2 + class_showconstantpool(c); + log_text("class_findmethod: returning NULL"); +#endif return NULL; +#endif + + s4 idx=class_findmethodIndex(c, name, desc); +/* if (idx==-1) log_text("class_findmethod: method not found");*/ + if (idx == -1) return NULL; + + return &(c->methods[idx]); +} + + +/*********************** Function: class_fetchmethod ************************** + + like class_findmethod, but aborts with an error if the method is not found + +*******************************************************************************/ + +methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc) +{ + methodinfo *mi; + mi = class_findmethod(c, name, desc); + + if (!mi) { + log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl(); + log_plain("Method: "); if (name) log_plain_utf(name); log_nl(); + log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl(); + panic("Method not found"); + } + + return mi; } + /************************* Function: class_findmethod_approx ****************** like class_findmethod but ignores the return value when comparing the @@ -1923,11 +2330,11 @@ methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc) *******************************************************************************/ -methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc) +methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc) { s4 i; - for (i = 0; i < c->methodscount; i++) + for (i = 0; i < c->methodscount; i++) { if (c->methods[i].name == name) { utf *meth_descr = c->methods[i].descriptor; @@ -1936,29 +2343,31 @@ methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc) return &(c->methods[i]); if (desc->blength <= meth_descr->blength) { - /* current position in utf text */ - char *desc_utf_ptr = desc->text; - char *meth_utf_ptr = meth_descr->text; - /* points behind utf strings */ - char *desc_end = utf_end(desc); - char *meth_end = utf_end(meth_descr); - char ch; - - /* compare argument types */ - while (desc_utf_ptrmethods[i]); /* all parameter types equal */ - } + /* current position in utf text */ + char *desc_utf_ptr = desc->text; + char *meth_utf_ptr = meth_descr->text; + /* points behind utf strings */ + char *desc_end = utf_end(desc); + char *meth_end = utf_end(meth_descr); + char ch; + + /* compare argument types */ + while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) { + + if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++)) + break; /* no match */ + + if (ch == ')') + return &(c->methods[i]); /* all parameter types equal */ + } } } + } return NULL; } + /***************** Function: class_resolvemethod_approx *********************** Searches a class and every super class for a method (without paying @@ -1966,16 +2375,17 @@ methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc) *******************************************************************************/ -methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc) +methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc) { while (c) { /* search for method (ignore returntype) */ - methodinfo *m = class_findmethod_approx (c, name, desc); + methodinfo *m = class_findmethod_approx(c, name, desc); /* method found */ if (m) return m; /* search superclass */ c = c->super; - } + } + return NULL; } @@ -1986,18 +2396,17 @@ methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc) *******************************************************************************/ - -methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc) +methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc) { while (c) { - methodinfo *m = class_findmethod (c, name, desc); + methodinfo *m = class_findmethod(c, name, desc); if (m) return m; /* search superclass */ c = c->super; - } + } + return NULL; } - /************************* Function: class_issubclass ************************** @@ -2006,17 +2415,16 @@ methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc) *******************************************************************************/ -bool class_issubclass (classinfo *sub, classinfo *super) +bool class_issubclass(classinfo *sub, classinfo *super) { for (;;) { if (!sub) return false; - if (sub==super) return true; - sub = sub -> super; - } + if (sub == super) return true; + sub = sub->super; + } } - /****************** Initialization function for classes ****************** In Java, every class can have a static initialization function. This @@ -2025,50 +2433,51 @@ bool class_issubclass (classinfo *sub, classinfo *super) *******************************************************************************/ -#ifdef USE_THREADS -extern int blockInts; -#endif - -void class_init (classinfo *c) +void class_init(classinfo *c) { - methodinfo *m; - java_objectheader *exceptionptr; + methodinfo *m; s4 i; +#ifdef USE_THREADS int b; +#endif if (!makeinitializations) return; - if (c->initialized) - return; - c -> initialized = true; - + if (c->initialized) + return; + + c->initialized = true; + #ifdef STATISTICS count_class_inits++; #endif - if (c->super) - class_init (c->super); - for (i=0; i < c->interfacescount; i++) - class_init(c->interfaces[i]); + if (c->super) + class_init (c->super); + for (i = 0; i < c->interfacescount; i++) + class_init(c->interfaces[i]); /* real */ - m = class_findmethod (c, utf_clinit, utf_fidesc); + m = class_findmethod(c, utf_clinit, utf_fidesc); if (!m) { if (initverbose) { - sprintf (logtext, "Class "); - utf_sprint (logtext+strlen(logtext), c->name); - sprintf (logtext+strlen(logtext), " has no initializer"); - dolog (); - } - return; + char logtext[MAXLOGTEXT]; + sprintf(logtext, "Class "); + utf_sprint(logtext + strlen(logtext), c->name); + sprintf(logtext + strlen(logtext), " has no initializer"); + log_text(logtext); } - - if (! (m->flags & ACC_STATIC)) - panic ("Class initializer is not static!"); - + /* goto callinitialize;*/ + return; + } + + if (!(m->flags & ACC_STATIC)) + panic("Class initializer is not static!"); + if (initverbose) { - sprintf (logtext, "Starting initializer for class: "); - utf_sprint (logtext+strlen(logtext), c->name); - dolog (); + char logtext[MAXLOGTEXT]; + sprintf(logtext, "Starting initializer for class: "); + utf_sprint(logtext + strlen(logtext), c->name); + log_text(logtext); } #ifdef USE_THREADS @@ -2076,70 +2485,186 @@ void class_init (classinfo *c) blockInts = 0; #endif - exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL); + asm_calljavafunction(m, NULL, NULL, NULL, NULL); #ifdef USE_THREADS assert(blockInts == 0); blockInts = b; #endif - if (exceptionptr) { - printf ("#### Initializer of "); - utf_display (c->name); - printf (" has thrown: "); - utf_display (exceptionptr->vftbl->class->name); - printf ("\n"); - fflush (stdout); - } + if (exceptionptr) { + printf("#### Initializer of "); + utf_display(c->name); + printf(" has thrown: "); + utf_display(exceptionptr->vftbl->class->name); + printf("\n"); + fflush(stdout); + } if (initverbose) { - sprintf (logtext, "Finished initializer for class: "); - utf_sprint (logtext+strlen(logtext), c->name); - dolog (); + char logtext[MAXLOGTEXT]; + sprintf(logtext, "Finished initializer for class: "); + utf_sprint(logtext + strlen(logtext), c->name); + log_text(logtext); } - if (c->name == utf_systemclass) { /* class java.lang.System requires explicit initialization */ - + if (initverbose) - printf ("#### Initializing class System"); + printf("#### Initializing class System"); - /* find initializing method */ - m = class_findmethod (c, - utf_initsystemclass, - utf_fidesc); + /* find initializing method */ + m = class_findmethod(c, + utf_initsystemclass, + utf_fidesc); if (!m) { /* no method found */ - log("initializeSystemClass failed"); + /* printf("initializeSystemClass failed"); */ return; } - #ifdef USE_THREADS - b = blockInts; - blockInts = 0; - #endif +#ifdef USE_THREADS + b = blockInts; + blockInts = 0; +#endif - exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL); + asm_calljavafunction(m, NULL, NULL, NULL, NULL); - #ifdef USE_THREADS - assert(blockInts == 0); - blockInts = b; - #endif +#ifdef USE_THREADS + assert(blockInts == 0); + blockInts = b; +#endif - if (exceptionptr) { - printf ("#### initializeSystemClass has thrown: "); - utf_display (exceptionptr->vftbl->class->name); - printf ("\n"); - fflush (stdout); + if (exceptionptr) { + printf("#### initializeSystemClass has thrown: "); + utf_display(exceptionptr->vftbl->class->name); + printf("\n"); + fflush(stdout); } } } +/********* Function: find_class_method_constant *********/ + +int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1) +{ + u4 i; + voidptr e; + for (i=0; icpcount; i++) { + + e = c -> cpinfos [i]; + if (e) { + + switch (c -> cptags [i]) { + case CONSTANT_Methodref: + { + constant_FMIref *fmi = e; + if ( (fmi->class->name == c1) + && (fmi->name == m1) + && (fmi->descriptor == d1)) { + + return i; + } + } + break; + + case CONSTANT_InterfaceMethodref: + { + constant_FMIref *fmi = e; + if ( (fmi->class->name == c1) + && (fmi->name == m1) + && (fmi->descriptor == d1)) { + + return i; + } + } + break; + } + } + } + + return -1; +} + + +void class_showconstanti(classinfo *c, int ii) +{ + u4 i = ii; + voidptr e; + + e = c->cpinfos [i]; + printf ("#%d: ", (int) i); + if (e) { + switch (c->cptags [i]) { + case CONSTANT_Class: + printf("Classreference -> "); + utf_display(((classinfo*)e)->name); + break; + + case CONSTANT_Fieldref: + printf("Fieldref -> "); goto displayFMIi; + case CONSTANT_Methodref: + printf("Methodref -> "); goto displayFMIi; + case CONSTANT_InterfaceMethodref: + printf("InterfaceMethod -> "); goto displayFMIi; + displayFMIi: + { + constant_FMIref *fmi = e; + utf_display(fmi->class->name); + printf("."); + utf_display(fmi->name); + printf(" "); + utf_display(fmi->descriptor); + } + break; + + case CONSTANT_String: + printf("String -> "); + utf_display(e); + break; + case CONSTANT_Integer: + printf("Integer -> %d", (int) (((constant_integer*)e)->value)); + break; + case CONSTANT_Float: + printf("Float -> %f", ((constant_float*)e)->value); + break; + case CONSTANT_Double: + printf("Double -> %f", ((constant_double*)e)->value); + break; + case CONSTANT_Long: + { + u8 v = ((constant_long*)e)->value; +#if U8_AVAILABLE + printf("Long -> %ld", (long int) v); +#else + printf("Long -> HI: %ld, LO: %ld\n", + (long int) v.high, (long int) v.low); +#endif + } + break; + case CONSTANT_NameAndType: + { + constant_nameandtype *cnt = e; + printf("NameAndType: "); + utf_display(cnt->name); + printf(" "); + utf_display(cnt->descriptor); + } + break; + case CONSTANT_Utf8: + printf("Utf8 -> "); + utf_display(e); + break; + default: + panic("Invalid type of ConstantPool-Entry"); + } + } + printf("\n"); +} -/********* Function: class_showconstantpool (debugging only) *********/ void class_showconstantpool (classinfo *c) { @@ -2155,78 +2680,72 @@ void class_showconstantpool (classinfo *c) if (e) { switch (c -> cptags [i]) { - case CONSTANT_Class: - printf ("Classreference -> "); - utf_display ( ((classinfo*)e) -> name ); - break; + case CONSTANT_Class: + printf ("Classreference -> "); + utf_display ( ((classinfo*)e) -> name ); + break; - case CONSTANT_Fieldref: - printf ("Fieldref -> "); goto displayFMI; - case CONSTANT_Methodref: - printf ("Methodref -> "); goto displayFMI; - case CONSTANT_InterfaceMethodref: - printf ("InterfaceMethod -> "); goto displayFMI; - displayFMI: - { + case CONSTANT_Fieldref: + printf ("Fieldref -> "); goto displayFMI; + case CONSTANT_Methodref: + printf ("Methodref -> "); goto displayFMI; + case CONSTANT_InterfaceMethodref: + printf ("InterfaceMethod -> "); goto displayFMI; + displayFMI: + { constant_FMIref *fmi = e; utf_display ( fmi->class->name ); printf ("."); utf_display ( fmi->name); printf (" "); utf_display ( fmi->descriptor ); - } - break; + } + break; - case CONSTANT_String: - printf ("String -> "); - utf_display (e); - break; - case CONSTANT_Integer: - printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) ); - break; - case CONSTANT_Float: - printf ("Float -> %f", ((constant_float*)e) -> value); - break; - case CONSTANT_Double: - printf ("Double -> %f", ((constant_double*)e) -> value); - break; - case CONSTANT_Long: - { + case CONSTANT_String: + printf ("String -> "); + utf_display (e); + break; + case CONSTANT_Integer: + printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) ); + break; + case CONSTANT_Float: + printf ("Float -> %f", ((constant_float*)e) -> value); + break; + case CONSTANT_Double: + printf ("Double -> %f", ((constant_double*)e) -> value); + break; + case CONSTANT_Long: + { u8 v = ((constant_long*)e) -> value; #if U8_AVAILABLE printf ("Long -> %ld", (long int) v); #else printf ("Long -> HI: %ld, LO: %ld\n", - (long int) v.high, (long int) v.low); + (long int) v.high, (long int) v.low); #endif - } - break; - case CONSTANT_NameAndType: - { constant_nameandtype *cnt = e; - printf ("NameAndType: "); - utf_display (cnt->name); - printf (" "); - utf_display (cnt->descriptor); - } - break; - case CONSTANT_Utf8: - printf ("Utf8 -> "); - utf_display (e); - break; - case CONSTANT_Arraydescriptor: { - printf ("Arraydescriptor: "); - displayarraydescriptor (e); - } - break; - default: - panic ("Invalid type of ConstantPool-Entry"); } - + break; + case CONSTANT_NameAndType: + { + constant_nameandtype *cnt = e; + printf ("NameAndType: "); + utf_display (cnt->name); + printf (" "); + utf_display (cnt->descriptor); + } + break; + case CONSTANT_Utf8: + printf ("Utf8 -> "); + utf_display (e); + break; + default: + panic ("Invalid type of ConstantPool-Entry"); } + } printf ("\n"); - } - + } } @@ -2281,8 +2800,6 @@ void class_showmethods (classinfo *c) /******************* General functions for the class loader *******************/ /******************************************************************************/ -static int loader_inited = 0; - /********************* Function: loader_load *********************************** Loads and links the class desired class and each class and interface @@ -2291,31 +2808,73 @@ static int loader_inited = 0; *******************************************************************************/ -classinfo *loader_load (utf *topname) +static int loader_load_running = 0; + +classinfo *loader_load(utf *topname) { classinfo *top; classinfo *c; - long int starttime=0,stoptime=0; + s8 starttime = 0; + s8 stoptime = 0; + classinfo *notlinkable; + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + pthread_mutex_lock(&compiler_mutex); +#endif + + /* avoid recursive calls */ + if (loader_load_running) + return class_new(topname); + + loader_load_running++; - intsDisable(); /* schani */ + intsDisable(); if (getloadingtime) starttime = getcputime(); - top = class_new (topname); + top = class_new(topname); /* load classes */ - while ( (c = list_first(&unloadedclasses)) ) { - if (!class_load (c)) { - list_remove (&unloadedclasses, c); - top=NULL; - } - } + while ((c = list_first(&unloadedclasses))) { + if (!class_load(c)) { + if (linkverbose) + dolog("Failed to load class"); + list_remove(&unloadedclasses, c); + top = NULL; + } + } /* link classes */ - while ( (c = list_first(&unlinkedclasses)) ) { - class_link (c); - } + if (linkverbose) + dolog("Linking..."); + + /* XXX added a hack to break infinite linking loops. A better + * linking algorithm would be nice. -Edwin */ + notlinkable = NULL; + while ((c = list_first(&unlinkedclasses))) { + class_link(c); + if (!c->linked) { + if (!notlinkable) + notlinkable = c; + else if (notlinkable == c) { + /* We tried to link this class for the second time and + * no other classes were linked in between, so we are + * caught in a loop. + */ + if (linkverbose) + dolog("Cannot resolve linking dependencies"); + top = NULL; + if (!exceptionptr) + throw_linkageerror_message(c->name); + break; + } + + } else + notlinkable = NULL; + } + if (linkverbose) + dolog("Linking done."); if (loader_inited) loader_compute_subclasses(); @@ -2323,14 +2882,67 @@ classinfo *loader_load (utf *topname) /* measure time */ if (getloadingtime) { stoptime = getcputime(); - loadingtime += (stoptime-starttime); + loadingtime += (stoptime - starttime); + } + + + loader_load_running--; + + /* check if a former loader_load call tried to load/link the class and + failed. This is needed because the class didn't appear in the + undloadclasses or unlinkedclasses list during this class. */ + if (top) { + if (!top->loaded) { + if (linkverbose) dolog("Failed to load class (former call)"); + throw_noclassdeffounderror_message(top->name); + top = NULL; + + } else if (!top->linked) { + if (linkverbose) + dolog("Failed to link class (former call)"); + throw_linkageerror_message(top->name); + top = NULL; } + } - intsRestore(); /* schani */ + intsRestore(); + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + pthread_mutex_unlock(&compiler_mutex); +#endif + /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load"); + return top; } +/****************** Function: loader_load_sysclass **************************** + + Loads and links the class desired class and each class and interface + referenced by it. + + The pointer to the classinfo is stored in *top if top != NULL. + The pointer is also returned. + + If the class could not be loaded the function aborts with an error. + +*******************************************************************************/ + +classinfo *loader_load_sysclass(classinfo **top,utf *topname) +{ + classinfo *cls; + + if ((cls = loader_load(topname)) == NULL) { + log_plain("Could not important system class: "); + log_plain_utf(topname); + log_nl(); + panic("Could not load important system class"); + } + + if (top) *top = cls; + + return cls; +} /**************** function: create_primitive_classes *************************** @@ -2346,12 +2958,15 @@ void create_primitive_classes() for (i=0;i classUsed = NOTUSED; /* not used initially CO-RT */ + c -> impldBy = NULL; /* prevent loader from loading primitive class */ list_remove (&unloadedclasses, c); + c->loaded=true; /* add to unlinked classes */ list_addlast (&unlinkedclasses, c); - c -> super = class_java_lang_Object; +/*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */ class_link (c); primitivetype_table[i].class_primitive = c; @@ -2359,29 +2974,235 @@ void create_primitive_classes() /* create class for wrapping the primitive type */ primitivetype_table[i].class_wrap = class_new( utf_new_char(primitivetype_table[i].wrapname) ); + primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */ + primitivetype_table[i].class_wrap -> impldBy = NULL; + + /* create the primitive array class */ + if (primitivetype_table[i].arrayname) { + c = class_new( utf_new_char(primitivetype_table[i].arrayname) ); + primitivetype_table[i].arrayclass = c; + c->loaded=true; + if (!c->linked) class_link(c); + primitivetype_table[i].arrayvftbl = c->vftbl; + } } } -/***************** function: create_array_class ******************************** +/**************** function: class_primitive_from_sig *************************** + + return the primitive class indicated by the given signature character - create class representing an array + If the descriptor does not indicate a valid primitive type the + return value is NULL. ********************************************************************************/ +classinfo *class_primitive_from_sig(char sig) +{ + switch (sig) { + case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive; + case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive; + case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive; + case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive; + case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive; + case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive; + case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive; + case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive; + case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive; + } + return NULL; +} + +/****************** function: class_from_descriptor **************************** -classinfo *create_array_class(utf *u) -{ - classinfo *c = class_new (u); - /* prevent loader from loading the array class */ - list_remove (&unloadedclasses, c); - /* add to unlinked classes */ - list_addlast (&unlinkedclasses, c); - c -> super = class_java_lang_Object; - class_link(c); + return the class indicated by the given descriptor + + utf_ptr....first character of descriptor + end_ptr....first character after the end of the string + next.......if non-NULL, *next is set to the first character after + the descriptor. (Undefined if an error occurs.) + + mode.......a combination (binary or) of the following flags: + + (Flags marked with * are the default settings.) + + What to do if a reference type descriptor is parsed successfully: + + CLASSLOAD_SKIP...skip it and return something != NULL + * CLASSLOAD_NEW....get classinfo * via class_new + CLASSLOAD_LOAD...get classinfo * via loader_load + + How to handle primitive types: - return c; + * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int") + CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types + + How to handle "V" descriptors: + + * CLASSLOAD_VOID.....handle it like other primitive types + CLASSLOAD_NOVOID...treat it as an error + + How to deal with extra characters after the end of the + descriptor: + + * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists) + CLASSLOAD_CHECKEND.....treat them as an error + + How to deal with errors: + + * CLASSLOAD_PANIC....abort execution with an error message + CLASSLOAD_NOPANIC..return NULL on error + +********************************************************************************/ + +classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr, + char **next, int mode) +{ + char *start = utf_ptr; + bool error = false; + utf *name; + + SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error); + + if (mode & CLASSLOAD_CHECKEND) + error |= (utf_ptr != end_ptr); + + if (!error) { + if (next) *next = utf_ptr; + + switch (*start) { + case 'V': + if (mode & CLASSLOAD_NOVOID) + break; + /* FALLTHROUGH! */ + case 'I': + case 'J': + case 'F': + case 'D': + case 'B': + case 'C': + case 'S': + case 'Z': + return (mode & CLASSLOAD_NULLPRIMITIVE) + ? NULL + : class_primitive_from_sig(*start); + + case 'L': + start++; + utf_ptr--; + /* FALLTHROUGH! */ + case '[': + if (mode & CLASSLOAD_SKIP) return class_java_lang_Object; + name = utf_new(start,utf_ptr-start); + return (mode & CLASSLOAD_LOAD) + ? loader_load(name) : class_new(name); /* XXX */ + } + } + + /* An error occurred */ + if (mode & CLASSLOAD_NOPANIC) + return NULL; + + log_plain("Invalid descriptor at beginning of '"); + log_plain_utf(utf_new(start, end_ptr-start)); + log_plain("'"); + log_nl(); + + panic("Invalid descriptor"); + + /* keep compiler happy */ + return NULL; } + +/******************* function: type_from_descriptor **************************** + + return the basic type indicated by the given descriptor + + This function parses a descriptor and returns its basic type as + TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID. + + cls...if non-NULL the referenced variable is set to the classinfo * + returned by class_from_descriptor. + + For documentation of the arguments utf_ptr, end_ptr, next and mode + see class_from_descriptor. The only difference is that + type_from_descriptor always uses CLASSLOAD_PANIC. + +********************************************************************************/ + +int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr, + char **next, int mode) +{ + classinfo *mycls; + if (!cls) cls = &mycls; + *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC)); + switch (*utf_ptr) { + case 'B': + case 'C': + case 'I': + case 'S': + case 'Z': + return TYPE_INT; + case 'D': + return TYPE_DOUBLE; + case 'F': + return TYPE_FLOAT; + case 'J': + return TYPE_LONG; + case 'V': + return TYPE_VOID; + } + return TYPE_ADDRESS; +} + + +/*************** function: create_pseudo_classes ******************************* + + create pseudo classes used by the typechecker + +********************************************************************************/ + +static void create_pseudo_classes() +{ + /* pseudo class for Arraystubs (extends java.lang.Object) */ + + pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$")); + list_remove(&unloadedclasses, pseudo_class_Arraystub); + + pseudo_class_Arraystub->super = class_java_lang_Object; + pseudo_class_Arraystub->interfacescount = 2; + pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2); + pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable; + pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable; + + list_addlast(&unlinkedclasses, pseudo_class_Arraystub); + class_link(pseudo_class_Arraystub); + + pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl; + + /* pseudo class representing the null type */ + + pseudo_class_Null = class_new(utf_new_char("$NULL$")); + list_remove(&unloadedclasses, pseudo_class_Null); + + pseudo_class_Null->super = class_java_lang_Object; + + list_addlast(&unlinkedclasses, pseudo_class_Null); + class_link(pseudo_class_Null); + + /* pseudo class representing new uninitialized objects */ + + pseudo_class_New = class_new( utf_new_char("$NEW$") ); + list_remove(&unloadedclasses,pseudo_class_New); + + pseudo_class_New->super = class_java_lang_Object; + + list_addlast(&unlinkedclasses,pseudo_class_New); + class_link(pseudo_class_New); +} + + /********************** Function: loader_init ********************************** Initializes all lists and loads all classes required for the system or the @@ -2389,11 +3210,12 @@ classinfo *create_array_class(utf *u) *******************************************************************************/ -void loader_init () +void loader_init(u1 * stackbottom) { - utf *string_class; interfaceindex = 0; + log_text("Entering loader_init"); + list_init (&unloadedclasses, OFFSET(classinfo, listnode) ); list_init (&unlinkedclasses, OFFSET(classinfo, listnode) ); list_init (&linkedclasses, OFFSET(classinfo, listnode) ); @@ -2407,89 +3229,102 @@ void loader_init () utf_clinit = utf_new_char(""); utf_initsystemclass = utf_new_char("initializeSystemClass"); utf_systemclass = utf_new_char("java/lang/System"); + utf_vmclassloader = utf_new_char("java/lang/VMClassLoader"); + utf_initialize = utf_new_char("initialize"); + utf_initializedesc = utf_new_char("(I)V"); + + utf_vmclass = utf_new_char("java/lang/VMClass"); + + /* create some important classes */ + /* These classes have to be created now because the classinfo + * pointers are used in the loading code. + */ + class_java_lang_Object = class_new(utf_new_char("java/lang/Object")); + class_java_lang_String = class_new(utf_new_char("java/lang/String")); + class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable")); + class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable")); + + log_text("loader_init: java/lang/Object"); + /* load the classes which were created above */ + loader_load_sysclass(NULL, class_java_lang_Object->name); + + loader_inited = 1; /*JOWENN*/ + + loader_load_sysclass(&class_java_lang_Throwable, + utf_new_char("java/lang/Throwable")); + + log_text("loader_init: loader_load: java/lang/ClassCastException"); + loader_load_sysclass(&class_java_lang_ClassCastException, + utf_new_char ("java/lang/ClassCastException")); + loader_load_sysclass(&class_java_lang_NullPointerException, + utf_new_char ("java/lang/NullPointerException")); + loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException, + utf_new_char ("java/lang/ArrayIndexOutOfBoundsException")); + loader_load_sysclass(&class_java_lang_NegativeArraySizeException, + utf_new_char ("java/lang/NegativeArraySizeException")); + loader_load_sysclass(&class_java_lang_OutOfMemoryError, + utf_new_char ("java/lang/OutOfMemoryError")); + loader_load_sysclass(&class_java_lang_ArrayStoreException, + utf_new_char ("java/lang/ArrayStoreException")); + loader_load_sysclass(&class_java_lang_ArithmeticException, + utf_new_char ("java/lang/ArithmeticException")); + loader_load_sysclass(&class_java_lang_ThreadDeath, + utf_new_char ("java/lang/ThreadDeath")); + + /* create classes representing primitive types */ + create_primitive_classes(); - /* create class for arrays */ - class_array = class_new ( utf_new_char ("The_Array_Class") ); - list_remove (&unloadedclasses, class_array); - - /* create class for strings, load it after class Object was loaded */ - string_class = utf_new_char ("java/lang/String"); - class_java_lang_String = class_new(string_class); - list_remove (&unloadedclasses, class_java_lang_String); - - class_java_lang_Object = - loader_load ( utf_new_char ("java/lang/Object") ); - - list_addlast(&unloadedclasses, class_java_lang_String); - - class_java_lang_String = - loader_load ( string_class ); - class_java_lang_ClassCastException = - loader_load ( utf_new_char ("java/lang/ClassCastException") ); - class_java_lang_NullPointerException = - loader_load ( utf_new_char ("java/lang/NullPointerException") ); - class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( - utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") ); - class_java_lang_NegativeArraySizeException = loader_load ( - utf_new_char ("java/lang/NegativeArraySizeException") ); - class_java_lang_OutOfMemoryError = loader_load ( - utf_new_char ("java/lang/OutOfMemoryError") ); - class_java_lang_ArrayStoreException = - loader_load ( utf_new_char ("java/lang/ArrayStoreException") ); - class_java_lang_ArithmeticException = - loader_load ( utf_new_char ("java/lang/ArithmeticException") ); - class_java_lang_ThreadDeath = /* schani */ - loader_load ( utf_new_char ("java/lang/ThreadDeath") ); - - /* link class for arrays */ - list_addlast (&unlinkedclasses, class_array); - class_array -> super = class_java_lang_Object; - class_link (class_array); + /* create classes used by the typechecker */ + create_pseudo_classes(); /* correct vftbl-entries (retarded loading of class java/lang/String) */ - stringtable_update(); + stringtable_update(); - /* create classes representing primitive types */ - create_primitive_classes(); - - proto_java_lang_ClassCastException = +#ifdef USE_THREADS + if (stackbottom!=0) + initLocks(); +#endif + + log_text("loader_init: creating global proto_java_lang_ClassCastException"); + proto_java_lang_ClassCastException = builtin_new(class_java_lang_ClassCastException); - heap_addreference ( (void**) &proto_java_lang_ClassCastException); +/* heap_addreference((void**) &proto_java_lang_ClassCastException); */ + + log_text("loader_init: proto_java_lang_ClassCastException has been initialized"); - proto_java_lang_NullPointerException = + proto_java_lang_NullPointerException = builtin_new(class_java_lang_NullPointerException); - heap_addreference ( (void**) &proto_java_lang_NullPointerException); +/* heap_addreference((void**) &proto_java_lang_NullPointerException); */ + log_text("loader_init: proto_java_lang_NullPointerException has been initialized"); - proto_java_lang_ArrayIndexOutOfBoundsException = + proto_java_lang_ArrayIndexOutOfBoundsException = builtin_new(class_java_lang_ArrayIndexOutOfBoundsException); - heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException); +/* heap_addreference((void**) &proto_java_lang_ArrayIndexOutOfBoundsException); */ - proto_java_lang_NegativeArraySizeException = + proto_java_lang_NegativeArraySizeException = builtin_new(class_java_lang_NegativeArraySizeException); - heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException); +/* heap_addreference((void**) &proto_java_lang_NegativeArraySizeException); */ - proto_java_lang_OutOfMemoryError = + proto_java_lang_OutOfMemoryError = builtin_new(class_java_lang_OutOfMemoryError); - heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError); +/* heap_addreference((void**) &proto_java_lang_OutOfMemoryError); */ - proto_java_lang_ArithmeticException = + proto_java_lang_ArithmeticException = builtin_new(class_java_lang_ArithmeticException); - heap_addreference ( (void**) &proto_java_lang_ArithmeticException); +/* heap_addreference((void**) &proto_java_lang_ArithmeticException); */ - proto_java_lang_ArrayStoreException = + proto_java_lang_ArrayStoreException = builtin_new(class_java_lang_ArrayStoreException); - heap_addreference ( (void**) &proto_java_lang_ArrayStoreException); +/* heap_addreference((void**) &proto_java_lang_ArrayStoreException); */ proto_java_lang_ThreadDeath = /* schani */ - builtin_new(class_java_lang_ThreadDeath); - heap_addreference ( (void**) &proto_java_lang_ThreadDeath); + builtin_new(class_java_lang_ThreadDeath); +/* heap_addreference((void**) &proto_java_lang_ThreadDeath); */ loader_inited = 1; } - - /********************* Function: loader_initclasses **************************** Initializes all loaded but uninitialized classes @@ -2500,6 +3335,10 @@ void loader_initclasses () { classinfo *c; +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + pthread_mutex_lock(&compiler_mutex); +#endif + intsDisable(); /* schani */ if (makeinitializations) { @@ -2511,22 +3350,28 @@ void loader_initclasses () } intsRestore(); /* schani */ + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + pthread_mutex_unlock(&compiler_mutex); +#endif } static s4 classvalue; -static void loader_compute_class_values (classinfo *c) +static void loader_compute_class_values(classinfo *c) { classinfo *subs; c->vftbl->baseval = ++classvalue; + subs = c->sub; while (subs != NULL) { loader_compute_class_values(subs); subs = subs->nextsub; - } + } c->vftbl->diffval = classvalue - c->vftbl->baseval; -/* + + /* { int i; for (i = 0; i < c->index; i++) @@ -2535,42 +3380,47 @@ static void loader_compute_class_values (classinfo *c) utf_display(c->name); printf("\n"); } -*/ + */ } -void loader_compute_subclasses () +void loader_compute_subclasses() { classinfo *c; intsDisable(); /* schani */ - c = list_first (&linkedclasses); + c = list_first(&linkedclasses); while (c) { if (!(c->flags & ACC_INTERFACE)) { c->nextsub = 0; c->sub = 0; - } - c = list_next (&linkedclasses, c); } + c = list_next (&linkedclasses, c); + } c = list_first (&linkedclasses); while (c) { if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) { c->nextsub = c->super->sub; c->super->sub = c; - } - c = list_next (&linkedclasses, c); } + c = list_next (&linkedclasses, c); + } classvalue = 0; +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + cast_lock(); +#endif loader_compute_class_values(class_java_lang_Object); +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + cast_unlock(); +#endif intsRestore(); /* schani */ } - /******************** function classloader_buffer ****************************** sets buffer for reading classdata @@ -2579,9 +3429,9 @@ void loader_compute_subclasses () void classload_buffer(u1 *buf, int len) { - classbuffer = buf; - classbuffer_size = len; - classbuf_pos = buf - 1; + classbuffer = buf; + classbuffer_size = len; + classbuf_pos = buf - 1; } @@ -2591,22 +3441,22 @@ void classload_buffer(u1 *buf, int len) *******************************************************************************/ -void loader_close () +void loader_close() { classinfo *c; - while ( (c=list_first(&unloadedclasses)) ) { - list_remove (&unloadedclasses,c); - class_free (c); - } - while ( (c=list_first(&unlinkedclasses)) ) { - list_remove (&unlinkedclasses,c); - class_free (c); - } - while ( (c=list_first(&linkedclasses)) ) { - list_remove (&linkedclasses,c); - class_free (c); - } + while ((c = list_first(&unloadedclasses))) { + list_remove(&unloadedclasses, c); + class_free(c); + } + while ((c = list_first(&unlinkedclasses))) { + list_remove(&unlinkedclasses, c); + class_free(c); + } + while ((c = list_first(&linkedclasses))) { + list_remove(&linkedclasses, c); + class_free(c); + } } @@ -2622,4 +3472,3 @@ void loader_close () * tab-width: 4 * End: */ -