1 /* loader.c - class loader functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
28 Changes: Andreas Krall
33 $Id: loader.c 880 2004-01-13 17:17:12Z edwin $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_finalize; /* finalize */
89 static utf *utf_fidesc; /* ()V changed */
90 static utf *utf_init; /* <init> */
91 static utf *utf_clinit; /* <clinit> */
92 static utf *utf_initsystemclass; /* initializeSystemClass */
93 static utf *utf_systemclass; /* java/lang/System */
94 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
95 static utf *utf_vmclass; /* java/lang/VMClassLoader */
96 static utf *utf_initialize;
97 static utf *utf_initializedesc;
98 static utf *utf_java_lang_Object; /* java/lang/Object */
111 /* important system classes ***************************************************/
113 classinfo *class_java_lang_Object;
114 classinfo *class_java_lang_String;
116 classinfo *class_java_lang_Throwable;
117 classinfo *class_java_lang_Cloneable;
118 classinfo *class_java_io_Serializable;
120 /* Pseudo classes for the typechecker */
121 classinfo *pseudo_class_Arraystub = NULL;
122 classinfo *pseudo_class_Null = NULL;
123 classinfo *pseudo_class_New = NULL;
124 vftbl *pseudo_class_Arraystub_vftbl = NULL;
127 /* These are made static so they cannot be used for throwing in native */
129 static classinfo *class_java_lang_ClassCastException;
130 static classinfo *class_java_lang_NullPointerException;
131 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
132 static classinfo *class_java_lang_NegativeArraySizeException;
133 static classinfo *class_java_lang_OutOfMemoryError;
134 static classinfo *class_java_lang_ArithmeticException;
135 static classinfo *class_java_lang_ArrayStoreException;
136 static classinfo *class_java_lang_ThreadDeath;
138 utf *array_packagename = NULL;
140 static int loader_inited = 0;
143 /********************************************************************
144 list of classpath entries (either filesystem directories or
146 ********************************************************************/
147 static classpath_info *classpath_entries=0;
150 /******************************************************************************
152 structure for primitive classes: contains the class for wrapping the
153 primitive type, the primitive class, the name of the class for wrapping,
154 the one character type signature and the name of the primitive class
156 ******************************************************************************/
158 /* CAUTION: Don't change the order of the types. This table is indexed
159 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
161 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
162 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
163 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
164 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
165 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
166 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
167 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
168 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
169 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
170 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
174 /* instances of important system classes **************************************/
176 java_objectheader *proto_java_lang_ClassCastException;
177 java_objectheader *proto_java_lang_NullPointerException;
178 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
179 java_objectheader *proto_java_lang_NegativeArraySizeException;
180 java_objectheader *proto_java_lang_OutOfMemoryError;
181 java_objectheader *proto_java_lang_ArithmeticException;
182 java_objectheader *proto_java_lang_ArrayStoreException;
183 java_objectheader *proto_java_lang_ThreadDeath;
185 /************* functions for reading classdata *********************************
187 getting classdata in blocks of variable size
188 (8,16,32,64-bit integer or float)
190 *******************************************************************************/
192 static char *classpath = ""; /* searchpath for classfiles */
193 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
194 static u1 *classbuf_pos; /* current position in classfile buffer */
195 static int classbuffer_size; /* size of classfile-data */
197 /* assert that at least <len> bytes are left to read */
198 /* <len> is limited to the range of non-negative s4 values */
199 #define ASSERT_LEFT(len) \
200 do {if ( ((s4)(len)) < 0 \
201 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
202 panic("Unexpected end of classfile"); } while(0)
204 /* transfer block of classfile data into a buffer */
206 #define suck_nbytes(buffer,len) \
207 do {ASSERT_LEFT(len); \
208 memcpy(buffer,classbuf_pos+1,len); \
209 classbuf_pos+=len;} while (0)
211 /* skip block of classfile data */
213 #define skip_nbytes(len) \
214 do {ASSERT_LEFT(len); \
215 classbuf_pos+=len;} while(0)
220 return *++classbuf_pos;
224 u1 a=suck_u1(), b=suck_u1();
225 return ((u2)a<<8)+(u2)b;
229 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
230 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
232 #define suck_s8() (s8) suck_u8()
233 #define suck_s2() (s2) suck_u2()
234 #define suck_s4() (s4) suck_u4()
235 #define suck_s1() (s1) suck_u1()
238 /* get u8 from classfile data */
245 return (hi << 32) + lo;
255 /* get float from classfile data */
256 static float suck_float()
263 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
264 memcpy((u1*) (&f), buffer, 4);
266 suck_nbytes((u1*) (&f), 4);
269 PANICIF (sizeof(float) != 4, "Incompatible float-format");
275 /* get double from classfile data */
276 static double suck_double()
283 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
284 memcpy((u1*) (&d), buffer, 8);
286 suck_nbytes((u1*) (&d), 8);
289 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
295 /************************** function suck_init *********************************
297 called once at startup, sets the searchpath for the classfiles
299 *******************************************************************************/
301 void suck_init(char *cpath)
308 union classpath_info *tmp;
309 union classpath_info *insertAfter=0;
314 if (classpath_entries) panic("suck_init should be called only once");
315 for(start=classpath;(*start)!='\0';) {
316 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
319 filenamelen=(end-start);
353 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
354 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
355 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
358 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
359 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
360 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
365 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
367 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
368 strncpy(filename,start,filenamelen);
369 filename[filenamelen+1]='\0';
374 unzFile uf=unzOpen(filename);
376 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
377 tmp->archive.type=CLASSPATH_ARCHIVE;
383 panic("Zip/JAR not supported");
387 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
388 tmp->filepath.type=CLASSPATH_PATH;
389 tmp->filepath.next=0;
390 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
391 filename[filenamelen]='/';
392 filename[filenamelen+1]='\0';
396 tmp->filepath.filename=filename;
397 tmp->filepath.pathlen=filenamelen;
403 insertAfter->filepath.next=tmp;
405 classpath_entries=tmp;
410 if ((*end)==':') start=end+1; else start=end;
413 if (filename!=0) free(filename);
418 /************************** function suck_start ********************************
420 returns true if classbuffer is already loaded or a file for the
421 specified class has succussfully been read in. All directories of
422 the searchpath are used to find the classfile (<classname>.class).
423 Returns false if no classfile is found and writes an error message.
425 *******************************************************************************/
427 bool suck_start(utf *classname)
429 classpath_info *currPos;
432 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
438 if (classbuffer) return true; /* classbuffer is already valid */
440 utf_ptr = classname->text;
441 while (utf_ptr < utf_end(classname)) {
442 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
444 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
446 filename[filenamelen++] = c;
448 strcpy(filename + filenamelen, ".class");
450 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
452 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
453 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
454 unz_file_info file_info;
455 /*log_text("Class found in zip file");*/
456 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
457 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
458 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
459 classbuffer_size = file_info.uncompressed_size;
460 classbuffer = MNEW(u1, classbuffer_size);
461 classbuf_pos = classbuffer - 1;
462 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
463 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
464 unzCloseCurrentFile(currPos->archive.uf);
467 MFREE(classbuffer, u1, classbuffer_size);
468 log_text("Error while unzipping");
470 } else log_text("Error while opening file in archive");
471 } else log_text("Error while retrieving fileinfo");
473 unzCloseCurrentFile(currPos->archive.uf);
477 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
478 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
479 classfile = fopen(currPos->filepath.filename, "r");
480 if (classfile) { /* file exists */
482 /* determine size of classfile */
484 /* dolog("File: %s",filename); */
486 err = stat(currPos->filepath.filename, &buffer);
488 if (!err) { /* read classfile data */
489 classbuffer_size = buffer.st_size;
490 classbuffer = MNEW(u1, classbuffer_size);
491 classbuf_pos = classbuffer - 1;
492 fread(classbuffer, 1, classbuffer_size, classfile);
503 dolog("Warning: Can not open class file '%s'", filename);
510 /************************** function suck_stop *********************************
512 frees memory for buffer with classfile data.
513 Caution: this function may only be called if buffer has been allocated
514 by suck_start with reading a file
516 *******************************************************************************/
520 /* determine amount of classdata not retrieved by suck-operations */
522 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
524 if (classdata_left > 0) {
526 dolog("There are %d extra bytes at end of classfile",
528 /* The JVM spec disallows extra bytes. */
529 panic("Extra bytes at end of classfile");
534 MFREE(classbuffer, u1, classbuffer_size);
539 /******************************************************************************/
540 /******************* Some support functions ***********************************/
541 /******************************************************************************/
543 void fprintflags (FILE *fp, u2 f)
545 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
546 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
547 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
548 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
549 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
550 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
551 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
552 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
553 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
554 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
555 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
559 /********** internal function: printflags (only for debugging) ***************/
561 void printflags(u2 f)
563 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
564 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
565 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
566 if ( f & ACC_STATIC ) printf (" STATIC");
567 if ( f & ACC_FINAL ) printf (" FINAL");
568 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
569 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
570 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
571 if ( f & ACC_NATIVE ) printf (" NATIVE");
572 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
573 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
577 /************************* Function: skipattribute *****************************
579 skips a (1) 'attribute' structure in the class file
581 *******************************************************************************/
583 static void skipattribute()
592 /********************** Function: skipattributebody ****************************
594 skips an attribute after the 16 bit reference to attribute_name has already
597 *******************************************************************************/
599 static void skipattributebody()
607 /************************* Function: skipattributes ****************************
609 skips num attribute structures
611 *******************************************************************************/
613 static void skipattributes(u4 num)
616 for (i = 0; i < num; i++)
621 /******************** function: innerclass_getconstant ************************
623 like class_getconstant, but if cptags is ZERO null is returned
625 *******************************************************************************/
627 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
629 /* invalid position in constantpool */
630 if (pos >= c->cpcount)
631 panic("Attempt to access constant outside range");
633 /* constantpool entry of type 0 */
637 /* check type of constantpool entry */
638 if (c->cptags[pos] != ctype) {
639 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
640 (int) ctype, (int) c->cptags[pos] );
643 return c->cpinfos[pos];
647 /************************ function: attribute_load ****************************
649 read attributes from classfile
651 *******************************************************************************/
653 static void attribute_load(u4 num, classinfo *c)
657 for (i = 0; i < num; i++) {
658 /* retrieve attribute name */
659 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
661 if (aname == utf_innerclasses) {
662 /* innerclasses attribute */
664 if (c->innerclass != NULL)
665 panic("Class has more than one InnerClasses attribute");
667 /* skip attribute length */
669 /* number of records */
670 c->innerclasscount = suck_u2();
671 /* allocate memory for innerclass structure */
672 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
674 for (j = 0; j < c->innerclasscount; j++) {
675 /* The innerclass structure contains a class with an encoded name,
676 its defining scope, its simple name and a bitmask of the access flags.
677 If an inner class is not a member, its outer_class is NULL,
678 if a class is anonymous, its name is NULL. */
680 innerclassinfo *info = c->innerclass + j;
682 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
683 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
684 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
685 info->flags = suck_u2(); /* access_flags bitmask */
689 /* unknown attribute */
696 /******************* function: checkfielddescriptor ****************************
698 checks whether a field-descriptor is valid and aborts otherwise
699 all referenced classes are inserted into the list of unloaded classes
701 *******************************************************************************/
703 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
705 class_from_descriptor(utf_ptr,end_pos,NULL,
707 | CLASSLOAD_NULLPRIMITIVE
709 | CLASSLOAD_CHECKEND);
711 /* XXX use the following if -noverify */
713 char *tstart; /* pointer to start of classname */
715 char *start = utf_ptr;
717 switch (*utf_ptr++) {
731 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
732 panic ("Ill formed descriptor");
736 panic ("Ill formed descriptor");
739 /* exceeding characters */
740 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
745 /******************* function checkmethoddescriptor ****************************
747 checks whether a method-descriptor is valid and aborts otherwise.
748 All referenced classes are inserted into the list of unloaded classes.
750 The number of arguments is returned. A long or double argument is counted
753 *******************************************************************************/
755 static int checkmethoddescriptor (utf *d)
757 char *utf_ptr = d->text; /* current position in utf text */
758 char *end_pos = utf_end(d); /* points behind utf string */
759 int argcount = 0; /* number of arguments */
761 /* method descriptor must start with parenthesis */
762 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
764 /* check arguments */
765 while (utf_ptr != end_pos && *utf_ptr != ')') {
766 /* XXX we cannot count the this argument here because
767 * we don't know if the method is static. */
768 if (*utf_ptr == 'J' || *utf_ptr == 'D')
772 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
774 | CLASSLOAD_NULLPRIMITIVE
778 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
779 utf_ptr++; /* skip ')' */
781 class_from_descriptor(utf_ptr,end_pos,NULL,
783 | CLASSLOAD_NULLPRIMITIVE
784 | CLASSLOAD_CHECKEND);
787 panic("Invalid method descriptor: too many arguments");
791 /* XXX use the following if -noverify */
793 /* XXX check length */
794 /* check arguments */
795 while ((c = *utf_ptr++) != ')') {
812 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
813 panic ("Ill formed method descriptor");
817 panic ("Ill formed methodtype-descriptor");
821 /* check returntype */
823 /* returntype void */
824 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
827 /* treat as field-descriptor */
828 checkfielddescriptor (utf_ptr,end_pos);
833 /***************** Function: print_arraydescriptor ****************************
835 Debugging helper for displaying an arraydescriptor
837 *******************************************************************************/
839 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
842 fprintf(file, "<NULL>");
847 if (desc->componentvftbl) {
848 if (desc->componentvftbl->class)
849 utf_fprint(file, desc->componentvftbl->class->name);
851 fprintf(file, "<no classinfo>");
857 if (desc->elementvftbl) {
858 if (desc->elementvftbl->class)
859 utf_fprint(file, desc->elementvftbl->class->name);
861 fprintf(file, "<no classinfo>");
865 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
866 desc->dataoffset, desc->componentsize);
870 /******************************************************************************/
871 /************************** Functions for fields ****************************/
872 /******************************************************************************/
875 /************************ Function: field_load *********************************
877 Load everything about a class field from the class file and fill a
878 'fieldinfo' structure. For static fields, space in the data segment is
881 *******************************************************************************/
883 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
885 static void field_load(fieldinfo *f, classinfo *c)
889 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
891 f->flags = suck_u2(); /* ACC flags */
892 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
893 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
894 f->type = jtype = desc_to_type(f->descriptor); /* data type */
895 f->offset = 0; /* offset from start of object */
899 /* check flag consistency */
901 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
902 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
903 panic("Field has invalid access flags");
904 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
905 panic("Field is declared final and volatile");
906 if ((c->flags & ACC_INTERFACE) != 0) {
907 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
908 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
909 panic("Interface field is not declared static final public");
910 if ((f->flags & ACC_TRANSIENT) != 0)
911 panic("Interface field declared transient");
916 case TYPE_INT: f->value.i = 0; break;
917 case TYPE_FLOAT: f->value.f = 0.0; break;
918 case TYPE_DOUBLE: f->value.d = 0.0; break;
919 case TYPE_ADDRESS: f->value.a = NULL; break;
922 f->value.l = 0; break;
924 f->value.l.low = 0; f->value.l.high = 0; break;
928 /* read attributes */
930 for (i = 0; i < attrnum; i++) {
933 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
935 if (aname != utf_constantvalue) {
936 /* unknown attribute */
940 /* constant value attribute */
942 if (pindex != field_load_NOVALUE)
943 panic("Field has more than one ConstantValue attribute");
945 /* check attribute length */
947 panic("ConstantValue attribute has invalid length");
949 /* index of value in constantpool */
952 /* initialize field with value from constantpool */
955 constant_integer *ci =
956 class_getconstant(c, pindex, CONSTANT_Integer);
957 f->value.i = ci->value;
963 class_getconstant(c, pindex, CONSTANT_Long);
964 f->value.l = cl->value;
970 class_getconstant(c, pindex, CONSTANT_Float);
971 f->value.f = cf->value;
976 constant_double *cd =
977 class_getconstant(c, pindex, CONSTANT_Double);
978 f->value.d = cd->value;
983 utf *u = class_getconstant(c, pindex, CONSTANT_String);
984 /* create javastring from compressed utf8-string */
985 f->value.a = literalstring_new(u);
990 log_text ("Invalid Constant - Type");
997 /********************** function: field_free **********************************/
999 static void field_free (fieldinfo *f)
1005 /**************** Function: field_display (debugging only) ********************/
1007 void field_display(fieldinfo *f)
1010 printflags(f->flags);
1012 utf_display(f->name);
1014 utf_display(f->descriptor);
1015 printf(" offset: %ld\n", (long int) (f->offset));
1019 /******************************************************************************/
1020 /************************* Functions for methods ******************************/
1021 /******************************************************************************/
1024 /*********************** Function: method_load *********************************
1026 Loads a method from the class file and fills an existing 'methodinfo'
1027 structure. For native methods, the function pointer field is set to the
1028 real function pointer, for JavaVM methods a pointer to the compiler is used
1031 *******************************************************************************/
1033 static void method_load(methodinfo *m, classinfo *c)
1039 count_all_methods++;
1044 m->flags = suck_u2();
1045 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1046 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1047 argcount = checkmethoddescriptor(m->descriptor);
1048 if ((m->flags & ACC_STATIC) == 0)
1049 argcount++; /* count the 'this' argument */
1053 panic("Method has more than 255 arguments");
1055 /* check flag consistency */
1056 /* XXX could check if <clinit> is STATIC */
1057 if (m->name != utf_clinit) {
1058 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1059 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1060 panic("Method has invalid access flags");
1061 if ((m->flags & ACC_ABSTRACT) != 0) {
1062 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1063 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1064 panic("Abstract method has invalid flags set");
1066 if ((c->flags & ACC_INTERFACE) != 0) {
1067 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1068 != (ACC_ABSTRACT | ACC_PUBLIC))
1069 panic("Interface method is not declared abstract and public");
1071 if (m->name == utf_init) {
1072 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1073 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1074 panic("Instance initialization method has invalid flags set");
1080 m->exceptiontable = NULL;
1081 m->entrypoint = NULL;
1083 m->stubroutine = NULL;
1084 m->methodUsed = NOTUSED;
1087 m->subRedefsUsed = 0;
1091 if (!(m->flags & ACC_NATIVE)) {
1092 m->stubroutine = createcompilerstub(m);
1095 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1096 (m->flags & ACC_STATIC) != 0);
1098 m->stubroutine = createnativestub(f, m);
1103 attrnum = suck_u2();
1104 for (i = 0; i < attrnum; i++) {
1107 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1109 if (aname != utf_code) {
1110 skipattributebody();
1114 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1115 panic("Code attribute for native or abstract method");
1118 panic("Method has more than one Code attribute");
1121 m->maxstack = suck_u2();
1122 m->maxlocals = suck_u2();
1123 if (m->maxlocals < argcount)
1124 panic("max_locals is smaller than the number of arguments");
1126 codelen = suck_u4();
1128 panic("bytecode has zero length");
1129 if (codelen > 65536)
1130 panic("bytecode too long");
1131 m->jcodelength = codelen;
1132 m->jcode = MNEW(u1, m->jcodelength);
1133 suck_nbytes(m->jcode, m->jcodelength);
1134 m->exceptiontablelength = suck_u2();
1136 MNEW(exceptiontable, m->exceptiontablelength);
1139 count_vmcode_len += m->jcodelength + 18;
1140 count_extable_len += 8 * m->exceptiontablelength;
1143 for (e = 0; e < m->exceptiontablelength; e++) {
1145 m->exceptiontable[e].startpc = suck_u2();
1146 m->exceptiontable[e].endpc = suck_u2();
1147 m->exceptiontable[e].handlerpc = suck_u2();
1151 m->exceptiontable[e].catchtype = NULL;
1154 m->exceptiontable[e].catchtype =
1155 class_getconstant(c, idx, CONSTANT_Class);
1159 skipattributes(suck_u2());
1163 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1164 panic("Method missing Code attribute");
1168 /********************* Function: method_free ***********************************
1170 frees all memory that was allocated for this method
1172 *******************************************************************************/
1174 static void method_free(methodinfo *m)
1177 MFREE(m->jcode, u1, m->jcodelength);
1179 if (m->exceptiontable)
1180 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1183 CFREE(m->mcode, m->mcodelength);
1185 if (m->stubroutine) {
1186 if (m->flags & ACC_NATIVE) {
1187 removenativestub(m->stubroutine);
1190 removecompilerstub(m->stubroutine);
1196 /************** Function: method_display (debugging only) **************/
1198 void method_display(methodinfo *m)
1201 printflags(m->flags);
1203 utf_display(m->name);
1205 utf_display(m->descriptor);
1210 /******************** Function: method_canoverwrite ****************************
1212 Check if m and old are identical with respect to type and name. This means
1213 that old can be overwritten with m.
1215 *******************************************************************************/
1217 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1219 if (m->name != old->name) return false;
1220 if (m->descriptor != old->descriptor) return false;
1221 if (m->flags & ACC_STATIC) return false;
1228 /******************************************************************************/
1229 /************************ Functions for class *********************************/
1230 /******************************************************************************/
1233 /******************** function:: class_getconstant ******************************
1235 retrieves the value at position 'pos' of the constantpool of a class
1236 if the type of the value is other than 'ctype' the system is stopped
1238 *******************************************************************************/
1240 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1242 /* invalid position in constantpool */
1243 /* (pos == 0 is caught by type comparison) */
1244 if (pos >= c->cpcount)
1245 panic("Attempt to access constant outside range");
1247 /* check type of constantpool entry */
1249 if (c->cptags[pos] != ctype) {
1250 class_showconstantpool(c);
1251 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1252 (int) ctype, (int) c->cptags[pos]);
1255 return c->cpinfos[pos];
1259 /********************* Function: class_constanttype ****************************
1261 Determines the type of a class entry in the ConstantPool
1263 *******************************************************************************/
1265 u4 class_constanttype(classinfo *c, u4 pos)
1267 if (pos >= c->cpcount)
1268 panic("Attempt to access constant outside range");
1270 return c->cptags[pos];
1274 /******************** function: class_loadcpool ********************************
1276 loads the constantpool of a class,
1277 the entries are transformed into a simpler format
1278 by resolving references
1279 (a detailed overview of the compact structures can be found in global.h)
1281 *******************************************************************************/
1283 static void class_loadcpool(classinfo *c)
1286 /* The following structures are used to save information which cannot be
1287 processed during the first pass. After the complete constantpool has
1288 been traversed the references can be resolved.
1289 (only in specific order) */
1291 /* CONSTANT_Class_info entries */
1292 typedef struct forward_class {
1293 struct forward_class *next;
1298 /* CONSTANT_String */
1299 typedef struct forward_string {
1300 struct forward_string *next;
1305 /* CONSTANT_NameAndType */
1306 typedef struct forward_nameandtype {
1307 struct forward_nameandtype *next;
1311 } forward_nameandtype;
1313 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1314 typedef struct forward_fieldmethint {
1315 struct forward_fieldmethint *next;
1319 u2 nameandtype_index;
1320 } forward_fieldmethint;
1324 long int dumpsize = dump_size ();
1326 forward_class *forward_classes = NULL;
1327 forward_string *forward_strings = NULL;
1328 forward_nameandtype *forward_nameandtypes = NULL;
1329 forward_fieldmethint *forward_fieldmethints = NULL;
1331 /* number of entries in the constant_pool table plus one */
1332 u4 cpcount = c -> cpcount = suck_u2();
1333 /* allocate memory */
1334 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1335 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1338 panic("Invalid constant_pool_count (0)");
1341 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1344 /* initialize constantpool */
1345 for (idx=0; idx<cpcount; idx++) {
1346 cptags[idx] = CONSTANT_UNUSED;
1347 cpinfos[idx] = NULL;
1351 /******* first pass *******/
1352 /* entries which cannot be resolved now are written into
1353 temporary structures and traversed again later */
1356 while (idx < cpcount) {
1357 /* get constant type */
1361 case CONSTANT_Class: {
1362 forward_class *nfc = DNEW(forward_class);
1364 nfc -> next = forward_classes;
1365 forward_classes = nfc;
1367 nfc -> thisindex = idx;
1368 /* reference to CONSTANT_NameAndType */
1369 nfc -> name_index = suck_u2 ();
1375 case CONSTANT_Fieldref:
1376 case CONSTANT_Methodref:
1377 case CONSTANT_InterfaceMethodref: {
1378 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1380 nff -> next = forward_fieldmethints;
1381 forward_fieldmethints = nff;
1383 nff -> thisindex = idx;
1386 /* class or interface type that contains the declaration of the field or method */
1387 nff -> class_index = suck_u2 ();
1388 /* name and descriptor of the field or method */
1389 nff -> nameandtype_index = suck_u2 ();
1395 case CONSTANT_String: {
1396 forward_string *nfs = DNEW (forward_string);
1398 nfs -> next = forward_strings;
1399 forward_strings = nfs;
1401 nfs -> thisindex = idx;
1402 /* reference to CONSTANT_Utf8_info with string characters */
1403 nfs -> string_index = suck_u2 ();
1409 case CONSTANT_NameAndType: {
1410 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1412 nfn -> next = forward_nameandtypes;
1413 forward_nameandtypes = nfn;
1415 nfn -> thisindex = idx;
1416 /* reference to CONSTANT_Utf8_info containing simple name */
1417 nfn -> name_index = suck_u2 ();
1418 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1419 nfn -> sig_index = suck_u2 ();
1425 case CONSTANT_Integer: {
1426 constant_integer *ci = NEW (constant_integer);
1429 count_const_pool_len += sizeof(constant_integer);
1432 ci -> value = suck_s4 ();
1433 cptags [idx] = CONSTANT_Integer;
1440 case CONSTANT_Float: {
1441 constant_float *cf = NEW (constant_float);
1444 count_const_pool_len += sizeof(constant_float);
1447 cf -> value = suck_float ();
1448 cptags [idx] = CONSTANT_Float;
1454 case CONSTANT_Long: {
1455 constant_long *cl = NEW(constant_long);
1458 count_const_pool_len += sizeof(constant_long);
1461 cl -> value = suck_s8 ();
1462 cptags [idx] = CONSTANT_Long;
1466 panic("Long constant exceeds constant pool");
1470 case CONSTANT_Double: {
1471 constant_double *cd = NEW(constant_double);
1474 count_const_pool_len += sizeof(constant_double);
1477 cd -> value = suck_double ();
1478 cptags [idx] = CONSTANT_Double;
1482 panic("Double constant exceeds constant pool");
1486 case CONSTANT_Utf8: {
1488 /* number of bytes in the bytes array (not string-length) */
1489 u4 length = suck_u2();
1490 cptags [idx] = CONSTANT_Utf8;
1491 /* validate the string */
1492 ASSERT_LEFT(length);
1494 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1496 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1497 panic("Invalid UTF-8 string");
1499 /* insert utf-string into the utf-symboltable */
1500 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1501 /* skip bytes of the string */
1502 skip_nbytes(length);
1508 error ("Unkown constant type: %d",(int) t);
1516 /* resolve entries in temporary structures */
1518 while (forward_classes) {
1520 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1522 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1523 /* retrieve class from class-table */
1524 cpinfos [forward_classes -> thisindex] = class_new (name);
1526 forward_classes = forward_classes -> next;
1530 while (forward_strings) {
1532 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1534 log_text("forward_string:");
1535 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1537 log_text("\n------------------"); */
1538 /* resolve utf-string */
1539 cptags [forward_strings -> thisindex] = CONSTANT_String;
1540 cpinfos [forward_strings -> thisindex] = text;
1542 forward_strings = forward_strings -> next;
1545 while (forward_nameandtypes) {
1546 constant_nameandtype *cn = NEW (constant_nameandtype);
1549 count_const_pool_len += sizeof(constant_nameandtype);
1552 /* resolve simple name and descriptor */
1553 cn -> name = class_getconstant
1554 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1555 cn -> descriptor = class_getconstant
1556 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1558 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1559 cpinfos [forward_nameandtypes -> thisindex] = cn;
1561 forward_nameandtypes = forward_nameandtypes -> next;
1565 while (forward_fieldmethints) {
1566 constant_nameandtype *nat;
1567 constant_FMIref *fmi = NEW (constant_FMIref);
1570 count_const_pool_len += sizeof(constant_FMIref);
1572 /* resolve simple name and descriptor */
1573 nat = class_getconstant
1574 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1577 log_text("trying to resolve:");
1578 log_text(nat->name->text);
1579 switch(forward_fieldmethints ->tag) {
1580 case CONSTANT_Fieldref:
1581 log_text("CONSTANT_Fieldref");
1583 case CONSTANT_InterfaceMethodref:
1584 log_text("CONSTANT_InterfaceMethodref");
1586 case CONSTANT_Methodref:
1587 log_text("CONSTANT_Methodref");
1591 fmi -> class = class_getconstant
1592 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1593 fmi -> name = nat -> name;
1594 fmi -> descriptor = nat -> descriptor;
1596 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1597 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1599 switch (forward_fieldmethints -> tag) {
1600 case CONSTANT_Fieldref: /* check validity of descriptor */
1601 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1603 case CONSTANT_InterfaceMethodref:
1604 case CONSTANT_Methodref: /* check validity of descriptor */
1605 /* XXX check special names (<init>) */
1606 checkmethoddescriptor (fmi->descriptor);
1610 forward_fieldmethints = forward_fieldmethints -> next;
1614 /* class_showconstantpool(c); */
1616 dump_release (dumpsize);
1620 /********************** Function: class_load ***********************************
1622 Loads everything interesting about a class from the class file. The
1623 'classinfo' structure must have been allocated previously.
1625 The super class and the interfaces implemented by this class need not be
1626 loaded. The link is set later by the function 'class_link'.
1628 The loaded class is removed from the list 'unloadedclasses' and added to
1629 the list 'unlinkedclasses'.
1631 *******************************************************************************/
1633 static int class_load(classinfo *c)
1639 count_class_loads++;
1642 /* output for debugging purposes */
1644 char logtext[MAXLOGTEXT];
1645 sprintf(logtext, "Loading class: ");
1646 utf_sprint(logtext + strlen(logtext), c->name);
1650 /* load classdata, throw exception on error */
1652 if (!suck_start(c->name)) {
1653 throw_noclassdeffounderror_message(c->name);
1657 /* check signature */
1658 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1662 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1663 error("File version %d.%d is not supported", (int) ma, (int) mi);
1668 c->erroneous_state = 0;
1669 c->initializing_thread = 0;
1671 c->classUsed = NOTUSED; /* not used initially CO-RT */
1675 c->flags = suck_u2();
1676 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1678 /* check ACC flags consistency */
1679 if ((c->flags & ACC_INTERFACE) != 0) {
1680 if ((c->flags & ACC_ABSTRACT) == 0) {
1681 /* XXX We work around this because interfaces in JDK 1.1 are
1682 * not declared abstract. */
1684 c->flags |= ACC_ABSTRACT;
1685 /* panic("Interface class not declared abstract"); */
1687 if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
1688 panic("Interface class has invalid flags");
1690 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1691 panic("Class is declared both abstract and final");
1695 if (class_getconstant(c, i, CONSTANT_Class) != c)
1696 panic("Invalid this_class in class file");
1698 /* retrieve superclass */
1699 if ((i = suck_u2())) {
1700 c->super = class_getconstant(c, i, CONSTANT_Class);
1702 /* java.lang.Object may not have a super class. */
1703 if (c->name == utf_java_lang_Object)
1704 panic("java.lang.Object with super class");
1706 /* Interfaces must have j.l.O as super class. */
1707 if ((c->flags & ACC_INTERFACE) != 0
1708 && c->super->name != utf_java_lang_Object)
1710 panic("Interface with super class other than java.lang.Object");
1715 /* This is only allowed for java.lang.Object. */
1716 if (c->name != utf_java_lang_Object)
1717 panic("Class (not java.lang.Object) without super class");
1720 /* retrieve interfaces */
1721 c->interfacescount = suck_u2();
1722 c->interfaces = MNEW(classinfo*, c->interfacescount);
1723 for (i = 0; i < c->interfacescount; i++) {
1725 class_getconstant(c, suck_u2(), CONSTANT_Class);
1729 c->fieldscount = suck_u2();
1730 /* utf_display(c->name);
1731 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1733 c->fields = GCNEW(fieldinfo, c->fieldscount);
1734 for (i = 0; i < c->fieldscount; i++) {
1735 field_load(&(c->fields[i]), c);
1739 c->methodscount = suck_u2();
1740 c->methods = MNEW(methodinfo, c->methodscount);
1741 for (i = 0; i < c->methodscount; i++) {
1742 method_load(&(c->methods[i]), c);
1745 /* Check if all fields and methods can be uniquely
1746 * identified by (name,descriptor). */
1748 /* We use a hash table here to avoid making the
1749 * average case quadratic in # of methods, fields.
1751 static int shift = 0;
1753 u2 *next; /* for chaining colliding hash entries */
1759 /* Allocate hashtable */
1760 len = c->methodscount;
1761 if (len < c->fieldscount) len = c->fieldscount;
1763 hashtab = MNEW(u2,(hashlen + len));
1764 next = hashtab + hashlen;
1766 /* Determine bitshift (to get good hash values) */
1776 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1777 for (i = 0; i<c->fieldscount; ++i) {
1778 fieldinfo *fi = c->fields + i;
1779 /* It's ok if we lose bits here */
1780 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1782 if ((old = hashtab[index]) != 0) {
1784 /* dolog("HASHHIT %d --> %d",index,old); */
1787 /* dolog("HASHCHECK %d",old); */
1788 if (c->fields[old].name == fi->name
1789 && c->fields[old].descriptor == fi->descriptor)
1791 dolog("Duplicate field (%d,%d):",i,old);
1792 log_utf(fi->name); log_utf(fi->descriptor);
1793 panic("Fields with same name and descriptor");
1795 } while ((old = next[old]) != 0);
1797 /* else dolog("HASHLUCKY"); */
1798 hashtab[index] = i+1;
1802 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1803 for (i = 0; i<c->methodscount; ++i) {
1804 methodinfo *mi = c->methods + i;
1805 /* It's ok if we lose bits here */
1806 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1808 if ((old = hashtab[index]) != 0) {
1810 /* dolog("HASHHIT %d --> %d",index,old); */
1813 /* dolog("HASHCHECK %d",old); */
1814 if (c->methods[old].name == mi->name
1815 && c->methods[old].descriptor == mi->descriptor)
1817 dolog("Duplicate method (%d,%d):",i,old);
1818 log_utf(mi->name); log_utf(mi->descriptor);
1819 panic("Methods with same name and descriptor");
1821 } while ((old = next[old]) != 0);
1823 /* else dolog("HASHLUCKY"); */
1824 hashtab[index] = i+1;
1827 MFREE(hashtab,u2,(hashlen + len));
1831 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1832 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1833 count_class_infos += sizeof(methodinfo) * c->methodscount;
1836 /* load variable-length attribute structures */
1837 attribute_load(suck_u2(), c);
1842 /* remove class from list of unloaded classes and
1843 add to list of unlinked classes */
1844 list_remove(&unloadedclasses, c);
1845 list_addlast(&unlinkedclasses, c);
1854 /************** internal Function: class_highestinterface ***********************
1856 Used by the function class_link to determine the amount of memory needed
1857 for the interface table.
1859 *******************************************************************************/
1861 static s4 class_highestinterface(classinfo *c)
1866 if (!(c->flags & ACC_INTERFACE)) {
1867 char logtext[MAXLOGTEXT];
1868 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1869 utf_sprint(logtext + strlen(logtext), c->name);
1870 error("%s",logtext);
1874 for (i = 0; i < c->interfacescount; i++) {
1875 s4 h2 = class_highestinterface(c->interfaces[i]);
1883 /* class_addinterface **********************************************************
1885 Is needed by class_link for adding a VTBL to a class. All interfaces
1886 implemented by ic are added as well.
1888 *******************************************************************************/
1890 static void class_addinterface (classinfo *c, classinfo *ic)
1894 vftbl *vftbl = c->vftbl;
1896 if (i >= vftbl->interfacetablelength)
1897 panic ("Inernal error: interfacetable overflow");
1898 if (vftbl->interfacetable[-i])
1901 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1902 vftbl->interfacevftbllength[i] = 1;
1903 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1904 vftbl->interfacetable[-i][0] = NULL;
1907 vftbl->interfacevftbllength[i] = ic->methodscount;
1908 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1911 count_vftbl_len += sizeof(methodptr) *
1912 (ic->methodscount + (ic->methodscount == 0));
1915 for (j=0; j<ic->methodscount; j++) {
1918 for (m = 0; m < sc->methodscount; m++) {
1919 methodinfo *mi = &(sc->methods[m]);
1920 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1921 vftbl->interfacetable[-i][j] =
1922 vftbl->table[mi->vftblindex];
1932 for (j = 0; j < ic->interfacescount; j++)
1933 class_addinterface(c, ic->interfaces[j]);
1937 /******************* Function: class_new_array *********************************
1939 This function is called by class_new to setup an array class.
1941 *******************************************************************************/
1943 void class_new_array(classinfo *c)
1945 classinfo *comp = NULL;
1949 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1951 /* Array classes are not loaded from classfiles. */
1952 list_remove(&unloadedclasses, c);
1954 /* Check array class name */
1955 namelen = c->name->blength;
1956 if (namelen < 2 || c->name->text[0] != '[')
1957 panic("Invalid array class name");
1959 /* Check the component type */
1960 switch (c->name->text[1]) {
1962 /* c is an array of arrays. We have to create the component class. */
1963 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1967 /* c is an array of objects. */
1968 if (namelen < 4 || c->name->text[namelen - 1] != ';')
1969 panic("Invalid array class name");
1970 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1974 /* Setup the array class */
1975 c->super = class_java_lang_Object;
1976 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1978 c->interfacescount = 2;
1979 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1980 c->interfaces[0] = class_java_lang_Cloneable;
1981 c->interfaces[1] = class_java_io_Serializable;
1983 c->methodscount = 1;
1984 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1987 memset(clone, 0, sizeof(methodinfo));
1988 clone->flags = ACC_PUBLIC; /* XXX protected? */
1989 clone->name = utf_new_char("clone");
1990 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1992 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
1993 clone->monoPoly = MONO; /* XXX should be poly? */
1995 /* XXX: field: length? */
1997 /* The array class has to be linked */
1998 list_addlast(&unlinkedclasses,c);
2001 * Array classes which are created after the other classes have been
2002 * loaded and linked are linked explicitely.
2007 loader_load(c->name); /* XXX handle errors */
2011 /****************** Function: class_link_array *********************************
2013 This function is called by class_link to create the
2014 arraydescriptor for an array class.
2016 This function returns NULL if the array cannot be linked because
2017 the component type has not been linked yet.
2019 *******************************************************************************/
2021 static arraydescriptor *class_link_array(classinfo *c)
2023 classinfo *comp = NULL;
2024 int namelen = c->name->blength;
2025 arraydescriptor *desc;
2028 /* Check the component type */
2029 switch (c->name->text[1]) {
2031 /* c is an array of arrays. */
2032 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2033 if (!comp) panic("Could not find component array class.");
2037 /* c is an array of objects. */
2038 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2039 if (!comp) panic("Could not find component class.");
2043 /* If the component type has not been linked return NULL */
2044 if (comp && !comp->linked)
2047 /* Allocate the arraydescriptor */
2048 desc = NEW(arraydescriptor);
2051 /* c is an array of references */
2052 desc->arraytype = ARRAYTYPE_OBJECT;
2053 desc->componentsize = sizeof(void*);
2054 desc->dataoffset = OFFSET(java_objectarray,data);
2056 compvftbl = comp->vftbl;
2058 panic("Component class has no vftbl");
2059 desc->componentvftbl = compvftbl;
2061 if (compvftbl->arraydesc) {
2062 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2063 if (compvftbl->arraydesc->dimension >= 255)
2064 panic("Creating array of dimension >255");
2065 desc->dimension = compvftbl->arraydesc->dimension + 1;
2066 desc->elementtype = compvftbl->arraydesc->elementtype;
2069 desc->elementvftbl = compvftbl;
2070 desc->dimension = 1;
2071 desc->elementtype = ARRAYTYPE_OBJECT;
2075 /* c is an array of a primitive type */
2076 switch (c->name->text[1]) {
2077 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2078 desc->dataoffset = OFFSET(java_booleanarray,data);
2079 desc->componentsize = sizeof(u1);
2082 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2083 desc->dataoffset = OFFSET(java_bytearray,data);
2084 desc->componentsize = sizeof(u1);
2087 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2088 desc->dataoffset = OFFSET(java_chararray,data);
2089 desc->componentsize = sizeof(u2);
2092 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2093 desc->dataoffset = OFFSET(java_doublearray,data);
2094 desc->componentsize = sizeof(double);
2097 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2098 desc->dataoffset = OFFSET(java_floatarray,data);
2099 desc->componentsize = sizeof(float);
2102 case 'I': desc->arraytype = ARRAYTYPE_INT;
2103 desc->dataoffset = OFFSET(java_intarray,data);
2104 desc->componentsize = sizeof(s4);
2107 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2108 desc->dataoffset = OFFSET(java_longarray,data);
2109 desc->componentsize = sizeof(s8);
2112 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2113 desc->dataoffset = OFFSET(java_shortarray,data);
2114 desc->componentsize = sizeof(s2);
2118 panic("Invalid array class name");
2121 desc->componentvftbl = NULL;
2122 desc->elementvftbl = NULL;
2123 desc->dimension = 1;
2124 desc->elementtype = desc->arraytype;
2131 /********************** Function: class_link ***********************************
2133 Tries to link a class. The super class and every implemented interface must
2134 already have been linked. The function calculates the length in bytes that
2135 an instance of this class requires as well as the VTBL for methods and
2138 If the class can be linked, it is removed from the list 'unlinkedclasses'
2139 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2142 Attention: If cyclical class definitions are encountered, the program gets
2143 into an infinite loop (we'll have to work that out)
2145 *******************************************************************************/
2147 void class_link(classinfo *c)
2149 s4 supervftbllength; /* vftbllegnth of super class */
2150 s4 vftbllength; /* vftbllength of current class */
2151 s4 interfacetablelength; /* interface table length */
2152 classinfo *super = c->super; /* super class */
2153 classinfo *ic, *c2; /* intermediate class variables */
2154 vftbl *v; /* vftbl of current class */
2155 s4 i; /* interface/method/field counter */
2156 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2159 /* check if all superclasses are already linked, if not put c at end of
2160 unlinked list and return. Additionally initialize class fields. */
2162 /* check interfaces */
2164 for (i = 0; i < c->interfacescount; i++) {
2165 ic = c->interfaces[i];
2167 list_remove(&unlinkedclasses, c);
2168 list_addlast(&unlinkedclasses, c);
2171 if ((ic->flags & ACC_INTERFACE) == 0) {
2172 dolog("Specified interface is not declared as interface:");
2176 panic("Specified interface is not declared as interface");
2180 /* check super class */
2182 if (super == NULL) { /* class java.long.Object */
2184 c->classUsed = USED; /* Object class is always used CO-RT*/
2186 c->instancesize = sizeof(java_objectheader);
2188 vftbllength = supervftbllength = 0;
2190 c->finalizer = NULL;
2193 if (!super->linked) {
2194 list_remove(&unlinkedclasses, c);
2195 list_addlast(&unlinkedclasses, c);
2199 if ((super->flags & ACC_INTERFACE) != 0)
2200 panic("Interface specified as super class");
2202 /* handle array classes */
2203 /* The component class must have been linked already. */
2204 if (c->name->text[0] == '[')
2205 if ((arraydesc = class_link_array(c)) == NULL) {
2206 list_remove(&unlinkedclasses, c);
2207 list_addlast(&unlinkedclasses, c);
2211 /* Don't allow extending final classes */
2212 if ((super->flags & ACC_FINAL) != 0)
2213 panic("Trying to extend final class");
2215 if (c->flags & ACC_INTERFACE)
2216 c->index = interfaceindex++;
2218 c->index = super->index + 1;
2220 c->instancesize = super->instancesize;
2222 vftbllength = supervftbllength = super->vftbl->vftbllength;
2224 c->finalizer = super->finalizer;
2229 char logtext[MAXLOGTEXT];
2230 sprintf(logtext, "Linking Class: ");
2231 utf_sprint(logtext + strlen(logtext), c->name );
2235 /* compute vftbl length */
2237 for (i = 0; i < c->methodscount; i++) {
2238 methodinfo *m = &(c->methods[i]);
2240 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2241 classinfo *sc = super;
2244 for (j = 0; j < sc->methodscount; j++) {
2245 if (method_canoverwrite(m, &(sc->methods[j]))) {
2246 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2247 panic("Trying to overwrite final method");
2248 m->vftblindex = sc->methods[j].vftblindex;
2249 goto foundvftblindex;
2254 m->vftblindex = (vftbllength++);
2260 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2263 /* compute interfacetable length */
2265 interfacetablelength = 0;
2268 for (i = 0; i < c2->interfacescount; i++) {
2269 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2270 if (h > interfacetablelength)
2271 interfacetablelength = h;
2276 /* allocate virtual function table */
2278 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2279 (vftbllength - 1) + sizeof(methodptr*) *
2280 (interfacetablelength - (interfacetablelength > 0)));
2281 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2282 (interfacetablelength > 1));
2283 c->header.vftbl = c->vftbl = v;
2285 v->vftbllength = vftbllength;
2286 v->interfacetablelength = interfacetablelength;
2287 v->arraydesc = arraydesc;
2289 /* store interface index in vftbl */
2290 if (c->flags & ACC_INTERFACE)
2291 v->baseval = -(c->index);
2293 /* copy virtual function table of super class */
2295 for (i = 0; i < supervftbllength; i++)
2296 v->table[i] = super->vftbl->table[i];
2298 /* add method stubs into virtual function table */
2300 for (i = 0; i < c->methodscount; i++) {
2301 methodinfo *m = &(c->methods[i]);
2302 if (!(m->flags & ACC_STATIC)) {
2303 v->table[m->vftblindex] = m->stubroutine;
2307 /* compute instance size and offset of each field */
2309 for (i = 0; i < c->fieldscount; i++) {
2311 fieldinfo *f = &(c->fields[i]);
2313 if (!(f->flags & ACC_STATIC) ) {
2314 dsize = desc_typesize(f->descriptor);
2315 c->instancesize = ALIGN(c->instancesize, dsize);
2316 f->offset = c->instancesize;
2317 c->instancesize += dsize;
2321 /* initialize interfacetable and interfacevftbllength */
2323 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2326 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2329 for (i = 0; i < interfacetablelength; i++) {
2330 v->interfacevftbllength[i] = 0;
2331 v->interfacetable[-i] = NULL;
2334 /* add interfaces */
2336 for (c2 = c; c2 != NULL; c2 = c2->super)
2337 for (i = 0; i < c2->interfacescount; i++) {
2338 class_addinterface(c, c2->interfaces[i]);
2341 /* add finalizer method (not for java.lang.Object) */
2343 if (super != NULL) {
2345 static utf *finame = NULL;
2346 static utf *fidesc = NULL;
2349 finame = utf_finalize;
2351 fidesc = utf_fidesc;
2353 fi = class_findmethod(c, finame, fidesc);
2355 if (!(fi->flags & ACC_STATIC)) {
2365 list_remove(&unlinkedclasses, c);
2366 list_addlast(&linkedclasses, c);
2370 /******************* Function: class_freepool **********************************
2372 Frees all resources used by this classes Constant Pool.
2374 *******************************************************************************/
2376 static void class_freecpool (classinfo *c)
2382 for (idx=0; idx < c->cpcount; idx++) {
2383 tag = c->cptags[idx];
2384 info = c->cpinfos[idx];
2388 case CONSTANT_Fieldref:
2389 case CONSTANT_Methodref:
2390 case CONSTANT_InterfaceMethodref:
2391 FREE (info, constant_FMIref);
2393 case CONSTANT_Integer:
2394 FREE (info, constant_integer);
2396 case CONSTANT_Float:
2397 FREE (info, constant_float);
2400 FREE (info, constant_long);
2402 case CONSTANT_Double:
2403 FREE (info, constant_double);
2405 case CONSTANT_NameAndType:
2406 FREE (info, constant_nameandtype);
2412 MFREE (c -> cptags, u1, c -> cpcount);
2413 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2417 /*********************** Function: class_free **********************************
2419 Frees all resources used by the class.
2421 *******************************************************************************/
2423 static void class_free(classinfo *c)
2430 MFREE(c->interfaces, classinfo*, c->interfacescount);
2432 for (i = 0; i < c->fieldscount; i++)
2433 field_free(&(c->fields[i]));
2435 for (i = 0; i < c->methodscount; i++)
2436 method_free(&(c->methods[i]));
2437 MFREE(c->methods, methodinfo, c->methodscount);
2439 if ((v = c->vftbl) != NULL) {
2441 mem_free(v->arraydesc,sizeof(arraydescriptor));
2443 for (i = 0; i < v->interfacetablelength; i++) {
2444 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2446 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2448 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2449 sizeof(methodptr*) * (v->interfacetablelength -
2450 (v->interfacetablelength > 0));
2451 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2452 (v->interfacetablelength > 1));
2456 if (c->innerclasscount)
2457 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2459 /* if (c->classvftbl)
2460 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2466 /************************* Function: class_findfield ***************************
2468 Searches a 'classinfo' structure for a field having the given name and
2471 *******************************************************************************/
2473 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2477 for (i = 0; i < c->fieldscount; i++) {
2478 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2479 return &(c->fields[i]);
2482 panic("Can not find field given in CONSTANT_Fieldref");
2484 /* keep compiler happy */
2489 /************************* Function: class_findmethod **************************
2491 Searches a 'classinfo' structure for a method having the given name and
2492 type and returns the index in the class info structure.
2493 If type is NULL, it is ignored.
2495 *******************************************************************************/
2497 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2500 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2502 int buffer_len, pos;
2504 #ifdef JOWENN_DEBUG1
2507 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2509 buffer = MNEW(char, buffer_len);
2511 strcpy(buffer, "class_findmethod: method:");
2512 utf_sprint(buffer + strlen(buffer), name);
2513 strcpy(buffer + strlen(buffer), ", desc: ");
2514 utf_sprint(buffer + strlen(buffer), desc);
2515 strcpy(buffer + strlen(buffer), ", classname: ");
2516 utf_sprint(buffer + strlen(buffer), c->name);
2520 MFREE(buffer, char, buffer_len);
2522 for (i = 0; i < c->methodscount; i++) {
2523 #ifdef JOWENN_DEBUG2
2525 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2527 buffer = MNEW(char, buffer_len);
2529 strcpy(buffer, "class_findmethod: comparing to method:");
2530 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2531 strcpy(buffer + strlen(buffer), ", desc: ");
2532 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2536 MFREE(buffer, char, buffer_len);
2540 if ((c->methods[i].name == name) && ((desc == NULL) ||
2541 (c->methods[i].descriptor == desc))) {
2546 #ifdef JOWENN_DEBUG2
2547 class_showconstantpool(c);
2548 log_text("class_findmethod: returning NULL");
2555 /************************* Function: class_findmethod **************************
2557 Searches a 'classinfo' structure for a method having the given name and
2559 If type is NULL, it is ignored.
2561 *******************************************************************************/
2563 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2567 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2569 int buffer_len, pos;
2571 #ifdef JOWENN_DEBUG1
2574 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2576 buffer = MNEW(char, buffer_len);
2578 strcpy(buffer, "class_findmethod: method:");
2579 utf_sprint(buffer + strlen(buffer), name);
2580 strcpy(buffer + strlen(buffer), ", desc: ");
2581 utf_sprint(buffer + strlen(buffer), desc);
2582 strcpy(buffer + strlen(buffer), ", classname: ");
2583 utf_sprint(buffer + strlen(buffer), c->name);
2587 MFREE(buffer, char, buffer_len);
2589 for (i = 0; i < c->methodscount; i++) {
2590 #ifdef JOWENN_DEBUG2
2592 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2594 buffer = MNEW(char, buffer_len);
2596 strcpy(buffer, "class_findmethod: comparing to method:");
2597 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2598 strcpy(buffer + strlen(buffer), ", desc: ");
2599 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2603 MFREE(buffer, char, buffer_len);
2606 if ((c->methods[i].name == name) && ((desc == NULL) ||
2607 (c->methods[i].descriptor == desc))) {
2608 return &(c->methods[i]);
2611 #ifdef JOWENN_DEBUG2
2612 class_showconstantpool(c);
2613 log_text("class_findmethod: returning NULL");
2618 s4 idx=class_findmethodIndex(c, name, desc);
2619 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2620 if (idx == -1) return NULL;
2622 return &(c->methods[idx]);
2626 /*********************** Function: class_fetchmethod **************************
2628 like class_findmethod, but aborts with an error if the method is not found
2630 *******************************************************************************/
2632 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2635 mi = class_findmethod(c, name, desc);
2638 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2639 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2640 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2641 panic("Method not found");
2648 /************************* Function: class_findmethod_approx ******************
2650 like class_findmethod but ignores the return value when comparing the
2653 *******************************************************************************/
2655 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2659 for (i = 0; i < c->methodscount; i++) {
2660 if (c->methods[i].name == name) {
2661 utf *meth_descr = c->methods[i].descriptor;
2665 return &(c->methods[i]);
2667 if (desc->blength <= meth_descr->blength) {
2668 /* current position in utf text */
2669 char *desc_utf_ptr = desc->text;
2670 char *meth_utf_ptr = meth_descr->text;
2671 /* points behind utf strings */
2672 char *desc_end = utf_end(desc);
2673 char *meth_end = utf_end(meth_descr);
2676 /* compare argument types */
2677 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2679 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2680 break; /* no match */
2683 return &(c->methods[i]); /* all parameter types equal */
2693 /***************** Function: class_resolvemethod_approx ***********************
2695 Searches a class and every super class for a method (without paying
2696 attention to the return value)
2698 *******************************************************************************/
2700 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2703 /* search for method (ignore returntype) */
2704 methodinfo *m = class_findmethod_approx(c, name, desc);
2707 /* search superclass */
2715 /************************* Function: class_resolvemethod ***********************
2717 Searches a class and every super class for a method.
2719 *******************************************************************************/
2721 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2724 methodinfo *m = class_findmethod(c, name, desc);
2726 /* search superclass */
2734 /************************* Function: class_issubclass **************************
2736 Checks if sub is a descendant of super.
2738 *******************************************************************************/
2740 bool class_issubclass(classinfo *sub, classinfo *super)
2743 if (!sub) return false;
2744 if (sub == super) return true;
2750 /****************** Initialization function for classes ******************
2752 In Java, every class can have a static initialization function. This
2753 function has to be called BEFORE calling other methods or accessing static
2756 *******************************************************************************/
2758 void class_init(classinfo *c)
2766 if (!makeinitializations)
2771 c->initialized = true;
2774 count_class_inits++;
2777 /* initialize super class */
2780 char logtext[MAXLOGTEXT];
2781 sprintf(logtext, "Initialize super class ");
2782 utf_sprint(logtext + strlen(logtext), c->super->name);
2783 sprintf(logtext + strlen(logtext), " from ");
2784 utf_sprint(logtext + strlen(logtext), c->name);
2787 class_init(c->super);
2790 /* initialize interface classes */
2791 for (i = 0; i < c->interfacescount; i++) {
2793 char logtext[MAXLOGTEXT];
2794 sprintf(logtext, "Initialize interface class ");
2795 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2796 sprintf(logtext + strlen(logtext), " from ");
2797 utf_sprint(logtext + strlen(logtext), c->name);
2800 class_init(c->interfaces[i]); /* real */
2803 m = class_findmethod(c, utf_clinit, utf_fidesc);
2806 char logtext[MAXLOGTEXT];
2807 sprintf(logtext, "Class ");
2808 utf_sprint(logtext + strlen(logtext), c->name);
2809 sprintf(logtext + strlen(logtext), " has no initializer");
2812 /* goto callinitialize;*/
2816 if (!(m->flags & ACC_STATIC))
2817 panic("Class initializer is not static!");
2820 char logtext[MAXLOGTEXT];
2821 sprintf(logtext, "Starting initializer for class: ");
2822 utf_sprint(logtext + strlen(logtext), c->name);
2831 /* now call the initializer */
2832 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2835 assert(blockInts == 0);
2839 /* we have to throw an exception */
2840 if (*exceptionptr) {
2841 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2842 printf("Caused by: ");
2843 utf_display((*exceptionptr)->vftbl->class->name);
2850 char logtext[MAXLOGTEXT];
2851 sprintf(logtext, "Finished initializer for class: ");
2852 utf_sprint(logtext + strlen(logtext), c->name);
2856 if (c->name == utf_systemclass) {
2857 /* class java.lang.System requires explicit initialization */
2860 printf("#### Initializing class System");
2862 /* find initializing method */
2863 m = class_findmethod(c,
2864 utf_initsystemclass,
2868 /* no method found */
2869 /* printf("initializeSystemClass failed"); */
2878 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2881 assert(blockInts == 0);
2885 if (*exceptionptr) {
2886 printf("#### initializeSystemClass has thrown: ");
2887 utf_display((*exceptionptr)->vftbl->class->name);
2895 /********* Function: find_class_method_constant *********/
2897 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2902 for (i=0; i<c->cpcount; i++) {
2904 e = c -> cpinfos [i];
2907 switch (c -> cptags [i]) {
2908 case CONSTANT_Methodref:
2910 constant_FMIref *fmi = e;
2911 if ( (fmi->class->name == c1)
2912 && (fmi->name == m1)
2913 && (fmi->descriptor == d1)) {
2920 case CONSTANT_InterfaceMethodref:
2922 constant_FMIref *fmi = e;
2923 if ( (fmi->class->name == c1)
2924 && (fmi->name == m1)
2925 && (fmi->descriptor == d1)) {
2939 void class_showconstanti(classinfo *c, int ii)
2945 printf ("#%d: ", (int) i);
2947 switch (c->cptags [i]) {
2948 case CONSTANT_Class:
2949 printf("Classreference -> ");
2950 utf_display(((classinfo*)e)->name);
2953 case CONSTANT_Fieldref:
2954 printf("Fieldref -> "); goto displayFMIi;
2955 case CONSTANT_Methodref:
2956 printf("Methodref -> "); goto displayFMIi;
2957 case CONSTANT_InterfaceMethodref:
2958 printf("InterfaceMethod -> "); goto displayFMIi;
2961 constant_FMIref *fmi = e;
2962 utf_display(fmi->class->name);
2964 utf_display(fmi->name);
2966 utf_display(fmi->descriptor);
2970 case CONSTANT_String:
2971 printf("String -> ");
2974 case CONSTANT_Integer:
2975 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2977 case CONSTANT_Float:
2978 printf("Float -> %f", ((constant_float*)e)->value);
2980 case CONSTANT_Double:
2981 printf("Double -> %f", ((constant_double*)e)->value);
2985 u8 v = ((constant_long*)e)->value;
2987 printf("Long -> %ld", (long int) v);
2989 printf("Long -> HI: %ld, LO: %ld\n",
2990 (long int) v.high, (long int) v.low);
2994 case CONSTANT_NameAndType:
2996 constant_nameandtype *cnt = e;
2997 printf("NameAndType: ");
2998 utf_display(cnt->name);
3000 utf_display(cnt->descriptor);
3008 panic("Invalid type of ConstantPool-Entry");
3015 void class_showconstantpool (classinfo *c)
3020 printf ("---- dump of constant pool ----\n");
3022 for (i=0; i<c->cpcount; i++) {
3023 printf ("#%d: ", (int) i);
3025 e = c -> cpinfos [i];
3028 switch (c -> cptags [i]) {
3029 case CONSTANT_Class:
3030 printf ("Classreference -> ");
3031 utf_display ( ((classinfo*)e) -> name );
3034 case CONSTANT_Fieldref:
3035 printf ("Fieldref -> "); goto displayFMI;
3036 case CONSTANT_Methodref:
3037 printf ("Methodref -> "); goto displayFMI;
3038 case CONSTANT_InterfaceMethodref:
3039 printf ("InterfaceMethod -> "); goto displayFMI;
3042 constant_FMIref *fmi = e;
3043 utf_display ( fmi->class->name );
3045 utf_display ( fmi->name);
3047 utf_display ( fmi->descriptor );
3051 case CONSTANT_String:
3052 printf ("String -> ");
3055 case CONSTANT_Integer:
3056 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3058 case CONSTANT_Float:
3059 printf ("Float -> %f", ((constant_float*)e) -> value);
3061 case CONSTANT_Double:
3062 printf ("Double -> %f", ((constant_double*)e) -> value);
3066 u8 v = ((constant_long*)e) -> value;
3068 printf ("Long -> %ld", (long int) v);
3070 printf ("Long -> HI: %ld, LO: %ld\n",
3071 (long int) v.high, (long int) v.low);
3075 case CONSTANT_NameAndType:
3077 constant_nameandtype *cnt = e;
3078 printf ("NameAndType: ");
3079 utf_display (cnt->name);
3081 utf_display (cnt->descriptor);
3085 printf ("Utf8 -> ");
3089 panic ("Invalid type of ConstantPool-Entry");
3099 /********** Function: class_showmethods (debugging only) *************/
3101 void class_showmethods (classinfo *c)
3105 printf ("--------- Fields and Methods ----------------\n");
3106 printf ("Flags: "); printflags (c->flags); printf ("\n");
3108 printf ("This: "); utf_display (c->name); printf ("\n");
3110 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3112 printf ("Index: %d\n", c->index);
3114 printf ("interfaces:\n");
3115 for (i=0; i < c-> interfacescount; i++) {
3117 utf_display (c -> interfaces[i] -> name);
3118 printf (" (%d)\n", c->interfaces[i] -> index);
3121 printf ("fields:\n");
3122 for (i=0; i < c -> fieldscount; i++) {
3123 field_display (&(c -> fields[i]));
3126 printf ("methods:\n");
3127 for (i=0; i < c -> methodscount; i++) {
3128 methodinfo *m = &(c->methods[i]);
3129 if ( !(m->flags & ACC_STATIC))
3130 printf ("vftblindex: %d ", m->vftblindex);
3132 method_display ( m );
3136 printf ("Virtual function table:\n");
3137 for (i=0; i<c->vftbl->vftbllength; i++) {
3138 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3145 /******************************************************************************/
3146 /******************* General functions for the class loader *******************/
3147 /******************************************************************************/
3149 /********************* Function: loader_load ***********************************
3151 Loads and links the class desired class and each class and interface
3153 Returns: a pointer to this class
3155 *******************************************************************************/
3157 static int loader_load_running = 0;
3159 classinfo *loader_load(utf *topname)
3165 classinfo *notlinkable;
3167 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3168 pthread_mutex_lock(&compiler_mutex);
3171 /* avoid recursive calls */
3172 if (loader_load_running)
3173 return class_new(topname);
3175 loader_load_running++;
3180 starttime = getcputime();
3182 top = class_new(topname);
3185 while ((c = list_first(&unloadedclasses))) {
3186 if (!class_load(c)) {
3188 dolog("Failed to load class");
3189 list_remove(&unloadedclasses, c);
3196 dolog("Linking...");
3198 /* XXX added a hack to break infinite linking loops. A better
3199 * linking algorithm would be nice. -Edwin */
3201 while ((c = list_first(&unlinkedclasses))) {
3206 else if (notlinkable == c) {
3207 /* We tried to link this class for the second time and
3208 * no other classes were linked in between, so we are
3212 dolog("Cannot resolve linking dependencies");
3215 throw_linkageerror_message(c->name);
3223 dolog("Linking done.");
3226 loader_compute_subclasses();
3229 if (getloadingtime) {
3230 stoptime = getcputime();
3231 loadingtime += (stoptime - starttime);
3235 loader_load_running--;
3237 /* check if a former loader_load call tried to load/link the class and
3238 failed. This is needed because the class didn't appear in the
3239 undloadclasses or unlinkedclasses list during this class. */
3242 if (linkverbose) dolog("Failed to load class (former call)");
3243 throw_noclassdeffounderror_message(top->name);
3246 } else if (!top->linked) {
3248 dolog("Failed to link class (former call)");
3249 throw_linkageerror_message(top->name);
3256 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3257 pthread_mutex_unlock(&compiler_mutex);
3260 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
3266 /****************** Function: loader_load_sysclass ****************************
3268 Loads and links the class desired class and each class and interface
3271 The pointer to the classinfo is stored in *top if top != NULL.
3272 The pointer is also returned.
3274 If the class could not be loaded the function aborts with an error.
3276 *******************************************************************************/
3278 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3282 if ((cls = loader_load(topname)) == NULL) {
3283 log_plain("Could not load important system class: ");
3284 log_plain_utf(topname);
3286 panic("Could not load important system class");
3289 if (top) *top = cls;
3295 /**************** function: create_primitive_classes ***************************
3297 create classes representing primitive types
3299 ********************************************************************************/
3302 void create_primitive_classes()
3306 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3307 /* create primitive class */
3308 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3309 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3310 c -> impldBy = NULL;
3312 /* prevent loader from loading primitive class */
3313 list_remove (&unloadedclasses, c);
3315 /* add to unlinked classes */
3316 list_addlast (&unlinkedclasses, c);
3317 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3320 primitivetype_table[i].class_primitive = c;
3322 /* create class for wrapping the primitive type */
3323 primitivetype_table[i].class_wrap =
3324 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3325 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3326 primitivetype_table[i].class_wrap -> impldBy = NULL;
3328 /* create the primitive array class */
3329 if (primitivetype_table[i].arrayname) {
3330 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3331 primitivetype_table[i].arrayclass = c;
3333 if (!c->linked) class_link(c);
3334 primitivetype_table[i].arrayvftbl = c->vftbl;
3339 /**************** function: class_primitive_from_sig ***************************
3341 return the primitive class indicated by the given signature character
3343 If the descriptor does not indicate a valid primitive type the
3344 return value is NULL.
3346 ********************************************************************************/
3348 classinfo *class_primitive_from_sig(char sig)
3351 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3352 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3353 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3354 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3355 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3356 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3357 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3358 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3359 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3364 /****************** function: class_from_descriptor ****************************
3366 return the class indicated by the given descriptor
3368 utf_ptr....first character of descriptor
3369 end_ptr....first character after the end of the string
3370 next.......if non-NULL, *next is set to the first character after
3371 the descriptor. (Undefined if an error occurs.)
3373 mode.......a combination (binary or) of the following flags:
3375 (Flags marked with * are the default settings.)
3377 What to do if a reference type descriptor is parsed successfully:
3379 CLASSLOAD_SKIP...skip it and return something != NULL
3380 * CLASSLOAD_NEW....get classinfo * via class_new
3381 CLASSLOAD_LOAD...get classinfo * via loader_load
3383 How to handle primitive types:
3385 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3386 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3388 How to handle "V" descriptors:
3390 * CLASSLOAD_VOID.....handle it like other primitive types
3391 CLASSLOAD_NOVOID...treat it as an error
3393 How to deal with extra characters after the end of the
3396 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3397 CLASSLOAD_CHECKEND.....treat them as an error
3399 How to deal with errors:
3401 * CLASSLOAD_PANIC....abort execution with an error message
3402 CLASSLOAD_NOPANIC..return NULL on error
3404 ********************************************************************************/
3406 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3407 char **next, int mode)
3409 char *start = utf_ptr;
3413 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3415 if (mode & CLASSLOAD_CHECKEND)
3416 error |= (utf_ptr != end_ptr);
3419 if (next) *next = utf_ptr;
3423 if (mode & CLASSLOAD_NOVOID)
3434 return (mode & CLASSLOAD_NULLPRIMITIVE)
3436 : class_primitive_from_sig(*start);
3443 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3444 name = utf_new(start,utf_ptr-start);
3445 return (mode & CLASSLOAD_LOAD)
3446 ? loader_load(name) : class_new(name); /* XXX */
3450 /* An error occurred */
3451 if (mode & CLASSLOAD_NOPANIC)
3454 log_plain("Invalid descriptor at beginning of '");
3455 log_plain_utf(utf_new(start, end_ptr-start));
3459 panic("Invalid descriptor");
3461 /* keep compiler happy */
3466 /******************* function: type_from_descriptor ****************************
3468 return the basic type indicated by the given descriptor
3470 This function parses a descriptor and returns its basic type as
3471 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3473 cls...if non-NULL the referenced variable is set to the classinfo *
3474 returned by class_from_descriptor.
3476 For documentation of the arguments utf_ptr, end_ptr, next and mode
3477 see class_from_descriptor. The only difference is that
3478 type_from_descriptor always uses CLASSLOAD_PANIC.
3480 ********************************************************************************/
3482 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3483 char **next, int mode)
3486 if (!cls) cls = &mycls;
3487 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3504 return TYPE_ADDRESS;
3508 /*************** function: create_pseudo_classes *******************************
3510 create pseudo classes used by the typechecker
3512 ********************************************************************************/
3514 static void create_pseudo_classes()
3516 /* pseudo class for Arraystubs (extends java.lang.Object) */
3518 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3519 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3521 pseudo_class_Arraystub->super = class_java_lang_Object;
3522 pseudo_class_Arraystub->interfacescount = 2;
3523 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3524 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3525 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3527 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3528 class_link(pseudo_class_Arraystub);
3530 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3532 /* pseudo class representing the null type */
3534 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3535 list_remove(&unloadedclasses, pseudo_class_Null);
3537 pseudo_class_Null->super = class_java_lang_Object;
3539 list_addlast(&unlinkedclasses, pseudo_class_Null);
3540 class_link(pseudo_class_Null);
3542 /* pseudo class representing new uninitialized objects */
3544 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3545 list_remove(&unloadedclasses, pseudo_class_New);
3547 pseudo_class_New->super = class_java_lang_Object;
3549 list_addlast(&unlinkedclasses, pseudo_class_New);
3550 class_link(pseudo_class_New);
3554 /********************** Function: loader_init **********************************
3556 Initializes all lists and loads all classes required for the system or the
3559 *******************************************************************************/
3561 void loader_init(u1 *stackbottom)
3565 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3566 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3567 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3569 /* create utf-symbols for pointer comparison of frequently used strings */
3570 utf_innerclasses = utf_new_char("InnerClasses");
3571 utf_constantvalue = utf_new_char("ConstantValue");
3572 utf_code = utf_new_char("Code");
3573 utf_finalize = utf_new_char("finalize");
3574 utf_fidesc = utf_new_char("()V");
3575 utf_init = utf_new_char("<init>");
3576 utf_clinit = utf_new_char("<clinit>");
3577 utf_initsystemclass = utf_new_char("initializeSystemClass");
3578 utf_systemclass = utf_new_char("java/lang/System");
3579 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3580 utf_initialize = utf_new_char("initialize");
3581 utf_initializedesc = utf_new_char("(I)V");
3583 utf_vmclass = utf_new_char("java/lang/VMClass");
3584 utf_java_lang_Object= utf_new_char("java/lang/Object");
3586 array_packagename = utf_new_char("<the array package>");
3588 /* create some important classes */
3589 /* These classes have to be created now because the classinfo
3590 * pointers are used in the loading code.
3592 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3593 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3594 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3595 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3597 if (verbose) log_text("loader_init: java/lang/Object");
3598 /* load the classes which were created above */
3599 loader_load_sysclass(NULL, class_java_lang_Object->name);
3601 loader_inited = 1; /*JOWENN*/
3603 loader_load_sysclass(&class_java_lang_Throwable,
3604 utf_new_char("java/lang/Throwable"));
3606 if (verbose) log_text("loader_init: loader_load: java/lang/ClassCastException");
3607 loader_load_sysclass(&class_java_lang_ClassCastException,
3608 utf_new_char ("java/lang/ClassCastException"));
3609 loader_load_sysclass(&class_java_lang_NullPointerException,
3610 utf_new_char ("java/lang/NullPointerException"));
3611 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3612 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3613 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3614 utf_new_char ("java/lang/NegativeArraySizeException"));
3615 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3616 utf_new_char ("java/lang/OutOfMemoryError"));
3617 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3618 utf_new_char ("java/lang/ArrayStoreException"));
3619 loader_load_sysclass(&class_java_lang_ArithmeticException,
3620 utf_new_char ("java/lang/ArithmeticException"));
3621 loader_load_sysclass(&class_java_lang_ThreadDeath,
3622 utf_new_char ("java/lang/ThreadDeath"));
3624 /* create classes representing primitive types */
3625 create_primitive_classes();
3627 /* create classes used by the typechecker */
3628 create_pseudo_classes();
3630 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3631 stringtable_update();
3638 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3639 proto_java_lang_ClassCastException =
3640 builtin_new(class_java_lang_ClassCastException);
3642 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3644 proto_java_lang_NullPointerException =
3645 builtin_new(class_java_lang_NullPointerException);
3646 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3648 proto_java_lang_ArrayIndexOutOfBoundsException =
3649 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3651 proto_java_lang_NegativeArraySizeException =
3652 builtin_new(class_java_lang_NegativeArraySizeException);
3654 proto_java_lang_OutOfMemoryError =
3655 builtin_new(class_java_lang_OutOfMemoryError);
3657 proto_java_lang_ArithmeticException =
3658 builtin_new(class_java_lang_ArithmeticException);
3660 proto_java_lang_ArrayStoreException =
3661 builtin_new(class_java_lang_ArrayStoreException);
3663 proto_java_lang_ThreadDeath =
3664 builtin_new(class_java_lang_ThreadDeath);
3670 /********************* Function: loader_initclasses ****************************
3672 Initializes all loaded but uninitialized classes
3674 *******************************************************************************/
3677 /* XXX TWISTI: i think we do not need this */
3678 void loader_initclasses ()
3682 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3683 pthread_mutex_lock(&compiler_mutex);
3686 intsDisable(); /* schani */
3688 if (makeinitializations) {
3689 c = list_first(&linkedclasses);
3692 c = list_next(&linkedclasses, c);
3696 intsRestore(); /* schani */
3698 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3699 pthread_mutex_unlock(&compiler_mutex);
3705 static void loader_compute_class_values(classinfo *c)
3709 c->vftbl->baseval = ++classvalue;
3712 while (subs != NULL) {
3713 loader_compute_class_values(subs);
3714 subs = subs->nextsub;
3716 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3721 for (i = 0; i < c->index; i++)
3723 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3724 utf_display(c->name);
3731 void loader_compute_subclasses()
3735 intsDisable(); /* schani */
3737 c = list_first(&linkedclasses);
3739 if (!(c->flags & ACC_INTERFACE)) {
3743 c = list_next(&linkedclasses, c);
3746 c = list_first(&linkedclasses);
3748 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3749 c->nextsub = c->super->sub;
3752 c = list_next(&linkedclasses, c);
3756 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3759 loader_compute_class_values(class_java_lang_Object);
3760 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3764 intsRestore(); /* schani */
3768 /******************** function classloader_buffer ******************************
3770 sets buffer for reading classdata
3772 *******************************************************************************/
3774 void classload_buffer(u1 *buf, int len)
3777 classbuffer_size = len;
3778 classbuf_pos = buf - 1;
3782 /******************** Function: loader_close ***********************************
3786 *******************************************************************************/
3792 while ((c = list_first(&unloadedclasses))) {
3793 list_remove(&unloadedclasses, c);
3796 while ((c = list_first(&unlinkedclasses))) {
3797 list_remove(&unlinkedclasses, c);
3800 while ((c = list_first(&linkedclasses))) {
3801 list_remove(&linkedclasses, c);
3808 * These are local overrides for various environment variables in Emacs.
3809 * Please do not remove this and leave it at the end of the file, where
3810 * Emacs will automagically detect them.
3811 * ---------------------------------------------------------------------
3814 * indent-tabs-mode: t