DEADSOFTWARE

Patched for Linux
[mp3cc.git] / MPC.3.5.LINUX / preverifier / classresolver.c
1 /*
2 * @(#)classresolver.c 1.19 02/09/27
3 *
4 * Copyright 1995-1998 by Sun Microsystems, Inc.,
5 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
6 * All rights reserved.
7 *
8 * This software is the confidential and proprietary information
9 * of Sun Microsystems, Inc. ("Confidential Information"). You
10 * shall not disclose such Confidential Information and shall use
11 * it only in accordance with the terms of the license agreement
12 * you entered into with Sun.
13 * Use is subject to license terms.
14 */
16 /*=========================================================================
17 * SYSTEM: Verifier
18 * SUBSYSTEM: class resolver.c.
19 * FILE: classresolver.c
20 * OVERVIEW: Routines for loading and resolving class definitions.
21 * These routines should not be depending upon the interpreter
22 * or the garbage collector.
23 * AUTHOR: Sheng Liang, Sun Microsystems, Inc.
24 * Modifications for CLDC compliance checks,
25 * Tasneem Sayeed, Sun Microsystems
26 * Frank Yellin, Sun Microsystems
27 *=======================================================================*/
29 /*=========================================================================
30 * Include files
31 *=======================================================================*/
33 #include <ctype.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <fcntl.h>
37 #include <sys/stat.h>
38 #include <stdlib.h>
40 #include "oobj.h"
41 #include "tree.h"
42 #include "signature.h"
43 #include "path.h"
44 #include "sys_api.h"
45 #include "convert_md.h"
47 /*=========================================================================
48 * Globals and extern declarations
49 *=======================================================================*/
51 ClassClass *classJavaLangObject;
52 ClassClass *classJavaLangClass = 0;
53 ClassClass *classJavaLangString;
54 ClassClass *classJavaLangThrowable;
55 ClassClass *classJavaLangError;
56 ClassClass *classJavaLangException;
57 ClassClass *classJavaLangRuntimeException;
58 ClassClass *classJavaLangThreadDeath;
60 ClassClass *interfaceJavaLangCloneable;
61 ClassClass *interfaceJavaIoSerializable;
63 bool_t inline_jsr_on = TRUE;
65 static bool_t RunClinit(ClassClass * cb);
67 static ClassClass *InitializeAndResolveClass(ClassClass *cb, bool_t resolve);
68 static char *Locked_InitializeClass(ClassClass * cb, char **detail);
69 static char *Locked_LinkClass(ClassClass * cb, char **detail);
70 char * LinkClass(ClassClass *cb, char **detail);
71 static ClassClass *FindLoadedClass(char *name,
72 struct Hjava_lang_ClassLoader *loader);
73 static ClassClass *Locked_FindArrayClassFromClass(struct execenv *ee,
74 char *name,
75 ClassClass *from);
76 static void InitPrimitiveClasses();
78 /* An Explanation of Class-related Locks
79 *
80 * There are two global locks related to class loading:
81 *
82 * LOADCLASS_LOCK: ensures that only one thread is loading a class at
83 * a given time. This eliminates the possibility of two threads loading
84 * classes with the same name and same loader.
85 *
86 * BINCLASS_LOCK: ensures that only one thread is updating the global
87 * class table (binclasses). This lock is also grabbed by the GC to ensure
88 * that the GC always sees a valid global class table state.
89 *
90 * In addition, each class may have its own associated locks that are
91 * created with monitorEnter(). ResolveClass, for example, need to
92 * first grab this lock to ensure that the class is resolved only by
93 * one thread, rather than simultaneously by multiple threads.
94 */
96 sys_mon_t *_loadclass_lock;
97 sys_mon_t *_binclass_lock;
99 static struct fieldblock **
100 addslots(struct fieldblock ** fb, ClassClass * cb)
102 long n = cbFieldsCount(cb);
103 struct fieldblock *sfb = cbFields(cb);
104 if (cbSuperclass(cb))
105 fb = addslots(fb, cbSuperclass(cb));
106 while (--n >= 0) {
107 *fb++ = sfb;
108 sfb++;
110 return fb;
113 int
114 Locked_makeslottable(ClassClass * clb)
116 ClassClass *sclb;
117 int nslots = 0;
119 if (cbSlotTable(clb)) {
120 return SYS_OK;
122 sclb = clb;
123 while (sclb) {
124 long n = cbFieldsCount(sclb);
125 struct fieldblock *fb = cbFields(sclb);
126 while (--n >= 0) {
127 nslots++;
128 fb++;
130 if (cbSuperclass(sclb) == 0) {
131 break;
133 sclb = cbSuperclass(sclb);
135 cbSlotTableSize(clb) = nslots;
136 if (nslots == 0) {
137 nslots++;
139 cbSlotTable(clb) = (struct fieldblock **)
140 sysMalloc(nslots * sizeof(struct fieldblock *));
141 if (cbSlotTable(clb) == 0) {
142 return SYS_NOMEM;
144 addslots(cbSlotTable(clb), clb);
145 return SYS_OK;
148 int
149 makeslottable(ClassClass * clb)
151 int result;
152 LOADCLASS_LOCK();
153 result = Locked_makeslottable(clb);
154 LOADCLASS_UNLOCK();
155 return result;
158 #if 0
159 static char *
160 copyclassname(char *src, char *dst)
162 sysAssert(*src == SIGNATURE_CLASS);
163 src++;
164 while (*src && *src != SIGNATURE_ENDCLASS)
165 *dst++ = *src++;
166 *dst = 0;
167 return src;
169 #endif
171 static char *
172 ResolveFields(ClassClass *cb, unsigned slot)
174 struct fieldblock *fb;
175 int size;
177 fb = cbFields(cb);
178 for (size = 0; size < (int) cbFieldsCount(cb); size++, fb++) {
179 char *signature = fieldsig(fb);
180 int size = (((signature[0] == SIGNATURE_LONG ||
181 signature[0] == SIGNATURE_DOUBLE)) ? 2 : 1);
182 fb->ID = NameAndTypeToHash(fb->name, signature);
183 if (fb->access & ACC_STATIC) {
184 /* Do nothing. Handled when the class is loaded. */
185 } else {
186 fb->u.offset = slot;
187 slot += size * sizeof(OBJECT);
189 #ifdef UNUSED
190 if ((fb->access & (ACC_STATIC | ACC_TRANSIENT)) == 0) {
191 for (s = fieldname(fb); (c = *s++) != 0;)
192 thishash = thishash * 7 + c;
193 for (s = fieldsig(fb); (c = *s++) != 0;)
194 thishash = thishash * 7 + c;
196 #endif
198 if (slot > 65535) {
199 return "java/lang/InternalError";
202 cbInstanceSize(cb) = slot;
203 #ifdef UNUSED
204 cbThisHash(cb) = thishash;
205 if (cbSuperclass(cb))
206 cbTotalHash(cb) = thishash - cbTotalHash(unhand(cbSuperclass(cb)));
207 else
208 cbTotalHash(cb) = thishash;
209 if (cbTotalHash(cb) < N_TYPECODES)
210 cbTotalHash(cb) += N_TYPECODES;
211 #endif
212 return NULL;
216 static char *
217 ResolveMethods(ClassClass *cb)
219 struct methodblock *mb;
220 int size;
221 struct methodtable *new_table;
222 struct methodblock **super_methods;
223 int mslot, super_methods_count;
224 void *ptr;
225 static unsigned finalizerID = 0;
227 if (finalizerID == 0)
228 finalizerID = NameAndTypeToHash(FINALIZER_METHOD_NAME,
229 FINALIZER_METHOD_SIGNATURE);
230 mb = cbMethods(cb);
231 for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
232 mb->fb.ID = NameAndTypeToHash(mb->fb.name, mb->fb.signature);
233 mb->fb.u.offset = 0;
234 mb->invoker = 0;
237 if (cbIsInterface(cb)) {
238 /* We don't really need to built a method table for interfaces. */
239 cbMethodTable(cb) = NULL;
240 cbMethodTableSize(cb) = 0;
241 mb = cbMethods(cb);
242 /* Each method's offset is its index in the interface */
243 for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
244 mb->fb.u.offset = size;
246 return NULL;
249 if (cbSuperclass(cb) != NULL) {
250 ClassClass *super = cbSuperclass(cb);
251 mslot = cbMethodTableSize(super);
252 super_methods = cbMethodTable(super)->methods;
253 super_methods_count = cbMethodTableSize(super);
254 /* Inherit one's parent's finalizer, if it has one */
255 cbFinalizer(cb) = cbFinalizer(cbSuperclass(cb));
256 } else {
257 mslot = 1;
258 super_methods = NULL;
259 super_methods_count = 0;
260 cbFinalizer(cb) = NULL;
263 mb = cbMethods(cb);
264 for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
265 unsigned long ID = mb->fb.ID;
266 struct methodblock **super_methods_p;
267 int count;
269 if ((mb->fb.access & ACC_STATIC) || (mb->fb.access & ACC_PRIVATE))
270 continue;
271 if (strcmp(mb->fb.name, "<init>") == 0)
272 continue;
274 /* If this item has its own finalizer method, grab it */
275 if (mb->fb.ID == finalizerID) {
276 if (no_finalizers) {
277 panic("finalize methods should not appear");
279 cbFinalizer(cb) = mb;
282 for (super_methods_p = super_methods, count = super_methods_count;
283 count > 0;
284 super_methods_p++, count--) {
285 if ((*super_methods_p != NULL) && ((*super_methods_p)->fb.ID == ID)) {
286 /* Private methods are not inherited outside of the class. */
287 if ((*super_methods_p)->fb.access & ACC_PRIVATE)
288 continue;
289 /* Package-private methods are not inherited outside of the
290 package. */
291 if (((*super_methods_p)->fb.access & ACC_PROTECTED) ||
292 ((*super_methods_p)->fb.access & ACC_PUBLIC) ||
293 IsSameClassPackage((*super_methods_p)->fb.clazz, cb)) {
294 mb->fb.u.offset = (*super_methods_p)->fb.u.offset;
295 break;
296 }
297 /*
298 jio_fprintf(stderr, "!!!%s.%s\n", cbName(cb), mb->fb.name);
299 */
303 if (mb->fb.u.offset == 0) {
304 mb->fb.u.offset = mslot;
305 mslot++;
309 if (mslot > 65535) {
310 return "java/lang/InternalError";
313 /*
314 * This should be the only place that method tables are
315 * allocated. We allocate more than we need here and mask the
316 * resulting pointer because the methodtable pointer field in
317 * object handles is overloaded and sometimes hold array types
318 * and array lengths. We must ensure that method table pointers
319 * are allocated on an appropriate boundary so we don't lose any
320 * address bits when we mask off the type portion of the pointer.
321 */
322 ptr = sysMalloc(sizeof(struct methodtable)
323 + (mslot - 1)* sizeof(struct methodblock *)
324 + FLAG_MASK);
325 if (ptr == NULL) {
326 CCSet(cb, Error);
327 return JAVAPKG "OutOfMemoryError";
329 cbMethodTableMem(cb) = ptr;
330 new_table = (struct methodtable *)((((long)ptr) + FLAG_MASK) & LENGTH_MASK);
331 new_table->classdescriptor = cb;
332 memset((char *)new_table->methods, 0, mslot * sizeof(struct methodblock *));
333 if (super_methods)
334 memcpy((char *) new_table->methods,
335 (char *) super_methods,
336 super_methods_count * sizeof(struct methodblock *));
337 mb = cbMethods(cb);
338 for (size = 0; size < (int) cbMethodsCount(cb); size++, mb++) {
339 int offset = (int)mb->fb.u.offset;
340 if (offset > 0) {
341 sysAssert(offset < mslot);
342 mt_slot(new_table, offset) = mb;
345 cbMethodTable(cb) = new_table;
346 cbMethodTableSize(cb) = mslot;
348 return NULL;
352 static char *
353 ResolveInterfaces(ClassClass *cb, char **detail)
355 const int ITEM_SIZE = sizeof(cbIntfMethodTable(cb)->itable[0]);
356 bool_t isInterface = cbIsInterface(cb);
357 if (cbImplementsCount(cb) == 0 && !isInterface) {
358 /* classes that don't implement their own interfaces can just inherit
359 * their parents imethodtable. */
360 if (cb == classJavaLangObject) {
361 /* We can preinitialize the imethodtable of java.lang.Object */
362 static struct imethodtable t = { 0 };
363 cbIntfMethodTable(cb) = &t;
364 } else {
365 ClassClass *super = cbSuperclass(cb);
366 cbIntfMethodTable(cb) = cbIntfMethodTable(super);
367 }
368 return NULL;
369 } else {
370 cp_item_type *constant_pool = cbConstantPool(cb);
371 ClassClass *super = cbSuperclass(cb);
372 unsigned char *mallocSpace, *mallocSpaceEnd;
373 ClassClass *icb; /* temporary */
374 struct imethodtable *super_itable = cbIntfMethodTable(super);
375 struct imethodtable *this_itable = NULL;
376 int super_itable_count = super_itable->icount;
377 int i, j, k, icount, mcount;
379 /* Resolve all the interfaces that this class implements, and
380 * make sure that they all really are interfaces
382 * icount will total all the interfaces that this class implements,
383 * (include interfaces implemented by our superclass, and by
384 * interfaces that we implement.)
385 * mcount will total the total amount of space (in sizeof(long)) for
386 * which we'll have to allocate space for in the offsets table.
387 */
388 icount = super_itable_count + (isInterface ? 1 : 0);
389 mcount = 0;
390 for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
391 int interface_index = cbImplements(cb)[i];
392 struct imethodtable *sub_itable;
394 icb = constant_pool[interface_index].clazz;
395 if (!cbIsInterface(icb)) {
396 *detail = "Implementing class";
397 return JAVAPKG "IncompatibleClassChangeError";
399 sub_itable = cbIntfMethodTable(icb);
400 icount += sub_itable->icount;
401 if (!isInterface)
402 for (j = sub_itable->icount; --j >= 0; )
403 mcount += cbMethodsCount(sub_itable->itable[j].classdescriptor);
406 {
407 int this_itable_size =
408 offsetof(struct imethodtable, itable) + icount * ITEM_SIZE;
409 int offsets_size = mcount * sizeof(unsigned long);
410 mallocSpace = sysMalloc(this_itable_size + offsets_size);
411 if (mallocSpace == NULL) {
412 return JAVAPKG "OutOfMemoryError";
414 mallocSpaceEnd = mallocSpace + this_itable_size + offsets_size;
415 this_itable = (struct imethodtable *)mallocSpace;
416 mallocSpace += this_itable_size;
417 sysAssert(mallocSpace <= mallocSpaceEnd);
420 cbIntfMethodTable(cb) = this_itable;
422 /* Start filling in the table. */
423 icount = 0;
424 if (isInterface) {
425 this_itable->itable[icount].classdescriptor = cb;
426 this_itable->itable[icount].offsets = NULL;
427 icount++;
429 if (super_itable_count > 0) {
430 /* We can copy our superclass's offset table. The offsets
431 will stay the same. */
432 memcpy(&this_itable->itable[icount],
433 &super_itable->itable[0],
434 super_itable_count * ITEM_SIZE);
435 icount += super_itable_count;
437 for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
438 /* Add the interfaces that we implement, either directly, or
439 * because those interfaces implement other interfaces. */
440 int interface_index = cbImplements(cb)[i];
441 icb = constant_pool[interface_index].clazz;
442 memcpy(&this_itable->itable[icount],
443 &cbIntfMethodTable(icb)->itable[0],
444 cbIntfMethodTable(icb)->icount * ITEM_SIZE);
445 icount += cbIntfMethodTable(icb)->icount;
447 sysAssert(!isInterface || super_itable_count == 0);
448 /* Delete duplicates from the table. This is very rare, so it can
449 * be quite inefficient. */
450 for (i = (isInterface ? 1 : super_itable_count); i < icount; i++) {
451 icb = this_itable->itable[i].classdescriptor;
452 for (j = 0; j < i; j++) {
453 if (icb == this_itable->itable[j].classdescriptor) {
454 /* We have an overlap. Item i is a duplicate. Delete from
455 * the table */
456 for (k = i + 1; k < icount; k++)
457 this_itable->itable[k - 1] = this_itable->itable[k];
458 icount--;
459 i--; /* Reconsider this entry! */
460 break;
464 this_itable->icount = icount;
465 if (isInterface || cbIsAbstract(cb)) {
466 /* Nothing more to do for interfaces or abstract classes */
467 return NULL;
470 /* For each additional interface . . . */
471 for (i = super_itable_count; i < icount; i++) {
472 /* The table length is the number of interface methods */
473 ClassClass *intfi = this_itable->itable[i].classdescriptor;
474 int intfi_count = cbMethodsCount(intfi);
475 unsigned long *offsets = (unsigned long *)mallocSpace;
476 mallocSpace += intfi_count * sizeof(unsigned long);
477 sysAssert(mallocSpace <= mallocSpaceEnd);
478 this_itable->itable[i].offsets = offsets;
479 /* Look at each interface method */
480 for (j = 0; j < intfi_count; j++) {
481 struct methodblock *imb = cbMethods(intfi) + j;
482 if ((imb->fb.access & ACC_STATIC) != 0) {
483 sysAssert(!strcmp(imb->fb.name, "<clinit>"));
484 offsets[j] = 0;
485 } else {
486 /* Find the class method that implements the interface
487 * method */
488 unsigned ID = imb->fb.ID;
489 struct methodblock **mbt = cbMethodTable(cb)->methods;
490 for (k = cbMethodTableSize(cb) - 1; k >= 0; --k) {
491 struct methodblock *mb = mbt[k];
492 if (mb != NULL
493 && mb->fb.ID == ID && IsPublic(mb->fb.access)) {
494 offsets[j] = mb->fb.u.offset;
495 break;
498 /*
499 if (k == -1) {
500 *detail = "Unimplemented interface method";
501 return JAVAPKG "IncompatibleClassChangeError";
503 */
507 return NULL;
512 char *
513 InitializeClass(ClassClass * cb, char **detail)
514 {
515 char *result;
516 monitorEnter(obj_monitor(cb));
517 result = Locked_InitializeClass(cb, detail);
518 monitorExit(obj_monitor(cb));
519 return result;
523 char *
524 ResolveClass(ClassClass *cb, char **detail)
526 char *result;
527 if (CCIs(cb, Resolved))
528 return 0;
529 result = LinkClass(cb, detail);
530 if (result == 0) {
531 if (!RunClinit(cb)) {
532 result = JAVAPKG "ExceptionInInitializerError";
533 *detail = cbName(cb);
536 return result;
539 char *
540 LinkClass(ClassClass *cb, char **detail)
542 char *result;
543 if (CCIs(cb, Linked))
544 return 0;
545 monitorEnter(obj_monitor(cb));
546 result = Locked_LinkClass(cb, detail);
547 monitorExit(obj_monitor(cb));
548 return result;
551 /*
552 * Detect class circularities from InitializeClass()
553 */
555 static void
556 pushSeen(ExecEnv *ee, struct seenclass *seen)
558 struct seenclass *prev = ee->seenclasses.next;
559 ee->seenclasses.next = seen;
560 seen->next = prev;
563 static void
564 popSeen(ExecEnv *ee, struct seenclass *seen)
566 if (seen != ee->seenclasses.next) /* paranoia */
567 panic("popSeen: corrupt seen class stack");
568 ee->seenclasses.next = ee->seenclasses.next->next;
571 static bool_t
572 checkSeen(ExecEnv *ee, ClassClass *cb)
574 struct seenclass *seen = ee->seenclasses.next;
575 while (seen) {
576 if (cb == seen->cb)
577 return TRUE;
578 seen = seen->next;
580 return FALSE;
583 static char *
584 Locked_InitializeClass(ClassClass * cb, char **detail)
586 ClassClass *super = 0;
587 char *ret = 0;
588 bool_t noLoader;
589 int i;
590 char buff[BUFSIZ];
591 char *nativeName = &buff[0];
593 if (CCIs(cb, Initialized))
594 return NULL;
596 #ifndef TRIMMED
597 if (verbose)
598 jio_fprintf(stderr, "[Initializing %s]\n", cbName(cb));
599 #endif
601 noLoader = (cbLoader(cb) == 0);
602 if (cbFieldsCount(cb) > 2000) {
603 return JAVAPKG "ClassFormatError";
605 if ((strcmp(cbName(cb), CLS_RESLV_INIT_CLASS) == 0) && noLoader) {
606 /* Temporarily disable class circularity checks */
607 ExecEnv *ee = EE();
608 struct seenclass *save = ee->seenclasses.next;
609 ee->seenclasses.next = NULL;
610 /* Note: don't bother restoring on (fatal) error during bootstrap */
612 classJavaLangClass = cb;
613 MakeClassSticky(cb);
614 classJavaLangString =
615 FindStickySystemClass(NULL, JAVAPKG "String", TRUE);
616 if (classJavaLangString == 0) {
617 *detail = JAVAPKG "String";
618 return JAVAPKG "NoClassDefFoundError";
620 /* classJavaLangThreadDeath =
621 FindStickySystemClass(NULL, JAVAPKG "ThreadDeath", TRUE);
622 if (classJavaLangThreadDeath == 0) {
623 *detail = JAVAPKG "ThreadDeath";
624 return JAVAPKG "NoClassDefFoundError";
626 */
627 classJavaLangThrowable =
628 FindStickySystemClass(NULL, JAVAPKG "Throwable", TRUE);
629 if (classJavaLangThrowable == 0) {
630 *detail = JAVAPKG "Throwable";
631 return JAVAPKG "NoClassDefFoundError";
633 /*
634 classJavaLangException =
635 FindStickySystemClass(NULL, JAVAPKG "Exception", TRUE);
636 if (classJavaLangException == 0) {
637 *detail = JAVAPKG "Exception";
638 return JAVAPKG "NoClassDefFoundError";
640 classJavaLangError =
641 FindStickySystemClass(NULL, JAVAPKG "Error", TRUE);
642 if (classJavaLangError == 0) {
643 *detail = JAVAPKG "Error";
644 return JAVAPKG "NoClassDefFoundError";
646 classJavaLangRuntimeException =
647 FindStickySystemClass(NULL, JAVAPKG "RuntimeException", TRUE);
648 if (classJavaLangRuntimeException == 0) {
649 *detail = JAVAPKG "RuntimeException";
650 return JAVAPKG "NoClassDefFoundError";
652 interfaceJavaLangCloneable =
653 FindStickySystemClass(NULL, JAVAPKG "Cloneable", TRUE);
654 if (interfaceJavaLangCloneable == 0) {
655 *detail = JAVAPKG "Cloneable";
656 return JAVAPKG "NoClassDefFoundError";
658 interfaceJavaIoSerializable =
659 FindStickySystemClass(NULL, "java/io/Serializable", TRUE);
660 if (interfaceJavaIoSerializable == 0) {
661 *detail = "java/io/Serializable";
662 return JAVAPKG "NoClassDefFoundError";
664 */
665 /* Restore stack for class circularity checks */
666 ee->seenclasses.next = save;
668 } else if ((strcmp(cbName(cb), CLS_RESLV_INIT_OBJECT) == 0) && noLoader){
669 classJavaLangObject = cb;
670 MakeClassSticky(classJavaLangObject);
673 if (noLoader) {
674 char *name = cbName(cb);
675 if (strcmp(name, CLS_RESLV_INIT_REF) == 0) {
676 CCSet(cb, SoftRef);
678 if (strncmp(name, "java/", 5) || strncmp(name, "sun/", 4)) {
679 CCSet(cb, SysLock);
682 if (cbSuperclass(cb) == NULL) {
683 if (cbSuperName(cb)) {
684 /* Check for class definition circularities */
685 ExecEnv *ee = EE();
686 struct seenclass this[1];
687 if (checkSeen(ee, cb)) {
688 *detail = cbName(cb);
689 CCSet(cb, Error);
690 return JAVAPKG "ClassCircularityError";
692 this->cb = cb;
693 this->next = NULL;
694 pushSeen(ee, this);
696 /* Conversion for Japanese file names */
697 utf2native(cbSuperName(cb), nativeName, BUFSIZ);
699 super = FindClassFromClass(ee, nativeName, FALSE, cb);
701 popSeen(ee, this);
702 if (super != NULL) {
703 sysAssert(CCIs(super, Initialized));
704 /* Don't allow a class to have a superclass it can't access */
705 if (!VerifyClassAccess(cb, super, FALSE)) {
706 super = NULL;
707 }
709 if (super != NULL) {
710 cbSuperclass(cb) = cbHandle(super);
711 if (CCIs(super, SoftRef))
712 CCSet(cb, SoftRef);
713 } else {
714 ret = JAVAPKG "NoClassDefFoundError";
715 *detail = cbSuperName(cb);
716 cbSuperclass(cb) = NULL;
717 CCSet(cb, Error);
718 }
719 } else if (cb == classJavaLangObject) {
720 cbSuperclass(cb) = 0;
721 } else {
722 *detail = cbName(cb);
723 return JAVAPKG "ClassFormatException";
727 for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
728 /* Be very careful, since not verified yet. . .
729 */
730 int interface_index = cbImplements(cb)[i];
731 cp_item_type *constant_pool = cbConstantPool(cb);
732 unsigned char *type_table =
733 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
734 ClassClass *icb;
735 int nconstants = cbConstantPoolCount(cb);
736 int iname_index;
737 char *iname;
739 if (interface_index <= 0 ||
740 interface_index >= nconstants ||
741 type_table[interface_index] != CONSTANT_Class ||
742 !(iname_index = constant_pool[interface_index].i) ||
743 iname_index <= 0 ||
744 iname_index >= nconstants ||
745 type_table[iname_index] !=
746 (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED)) {
747 *detail = "Bad interface index";
748 return JAVAPKG "ClassFormatError";
751 iname = constant_pool[iname_index].cp;
752 // if (iname == NULL || !IsLegalClassname(iname, FALSE)) {
753 // *detail = "Bad interface name";
754 // return JAVAPKG "ClassFormatError";
755 // }
758 ExecEnv *ee = EE();
759 struct seenclass this[1];
760 if (checkSeen(ee, cb)) {
761 *detail = cbName(cb);
762 CCSet(cb, Error);
763 return JAVAPKG "ClassCircularityError";
765 this->cb = cb;
766 this->next = NULL;
767 pushSeen(ee, this);
768 icb = FindClassFromClass(ee, iname, FALSE, cb);
769 popSeen(ee, this);
770 if (icb) {
771 constant_pool[interface_index].clazz = icb;
772 type_table[interface_index] |= CONSTANT_POOL_ENTRY_RESOLVED;
773 } else {
774 *detail = iname;
775 CCSet(cb, Error);
776 return JAVAPKG "NoClassDefFoundError";
781 CCSet(cb, Initialized);
783 /* Make sure we know what classJavaLangClass is, and that it's method table
784 * is filled in.
785 */
786 if (classJavaLangClass == 0) {
787 classJavaLangClass =
788 FindClassFromClass(0, CLS_RESLV_INIT_CLASS, TRUE, cb);
789 if (classJavaLangClass == 0) {
790 return JAVAPKG "NoClassDefFoundError";
794 /* The following may not do anything useful if classJavaLangClass hasn't
795 * been completely resolved. But we clean up in ResolveClass
796 */
798 cbHandle(cb)->methods = cbMethodTable(classJavaLangClass);
799 return ret;
802 static char *
803 Locked_LinkClass(ClassClass * cb, char **detail)
805 ClassClass *super = 0;
806 unsigned slot = 0;
807 char *ret = 0;
808 int i;
810 if (CCIs(cb, Error)) {
811 *detail = cbName(cb);
812 return JAVAPKG "NoClassDefFoundError";
815 sysAssert(CCIs(cb, Initialized));
817 if (CCIs(cb, Linked)) {
818 return NULL;
821 if (cbSuperclass(cb)) {
822 /* If this object has a superclass. . . */
823 super = cbSuperclass(cb);
824 if (!CCIs(super, Linked)) {
825 if ((ret = LinkClass(super, detail)) != 0) {
826 CCSet(cb, Error);
827 return ret;
830 sysAssert(CCIs(super, Linked));
831 slot = cbInstanceSize(super);
834 for (i = 0; i < (int)(cbImplementsCount(cb)); i++) {
835 int interface_index = cbImplements(cb)[i];
836 cp_item_type *constant_pool = cbConstantPool(cb);
837 ClassClass *icb;
838 icb = constant_pool[interface_index].clazz;
839 if (!CCIs(icb, Linked)) {
840 if ((ret = LinkClass(icb, detail)) != 0) {
841 CCSet(cb, Error);
842 return ret;
847 sysAssert(!CCIs(cb, Error));
848 sysAssert(!CCIs(cb, Linked));
850 #ifndef TRIMMED
851 if (verbose)
852 jio_fprintf(stderr, "[Resolving %s]\n", cbName(cb));
853 #endif
854 cbInstanceSize(cb) = -1;
855 if ((ret = ResolveFields(cb, slot))) { /* May return "InternalError" */
856 *detail = cbName(cb);
857 CCSet(cb, Error);
858 return ret;
861 if ((ret = ResolveMethods(cb))) {
862 /* May return "OutOfMemoryError" or "InternalError" */
863 *detail = cbName(cb);
864 CCSet(cb, Error);
865 return ret;
868 if ((ret = ResolveInterfaces(cb, detail))) { /* All sorts of errors */
869 CCSet(cb, Error);
870 return ret;
873 InitializeInvoker(cb);
875 if ((verifyclasses == VERIFY_ALL) ||
876 ((verifyclasses == VERIFY_REMOTE) && (cbLoader(cb) != NULL))) {
877 if (!VerifyClass(cb)) {
878 *detail = "";
879 return JAVAPKG "VerifyError";
883 CCSet(cb, Linked);
885 /* We need this for bootstrapping. We can't set the Handle's class block
886 * pointer in Object or Class until Class has been resolved.
887 */
888 if (cb == classJavaLangClass) {
889 int j;
890 ClassClass **pcb;
891 BINCLASS_LOCK();
892 for (j = nbinclasses, pcb = binclasses; --j >= 0; pcb++) {
893 cbHandle(*pcb)->methods = cbMethodTable(cb);
895 BINCLASS_UNLOCK();
896 InitPrimitiveClasses();
898 return NULL;
901 static bool_t
902 RunClinit(ClassClass * cb)
905 if (CCIs(cb, Resolved))
906 return TRUE;
908 if ((cbName(cb)[0] != SIGNATURE_ARRAY) && !cbIsPrimitive(cb)) {
909 /* Don't need to initialize or verify array or primitive classes */
910 return RunStaticInitializers(cb);
911 } else if (cbName(cb)[0] == SIGNATURE_ARRAY) {
912 ClassClass *inner_cb =
913 cbConstantPool(cb)[CONSTANT_POOL_ARRAY_CLASS_INDEX].clazz;
914 if (inner_cb) {
915 char *detail = 0;
916 char *ret = ResolveClass(inner_cb, &detail);
917 if (ret != NULL) {
918 if (!exceptionOccurred(EE())) {
919 SignalError(0, ret, detail);
921 CCSet(cb, Error);
922 return FALSE;
923 } else {
924 CCSet(cb, Resolved);
926 } else {
927 CCSet(cb, Resolved);
929 } else {
930 CCSet(cb, Resolved);
932 return TRUE;
936 /* Find an already loaded class with the given name. If no such class exists
937 * then return 0.
938 */
940 #ifdef DEBUG
941 void
942 PrintLoadedClasses()
944 int j;
945 ClassClass **pcb, *cb;
946 BINCLASS_LOCK();
947 pcb = binclasses;
948 for (j = nbinclasses; --j >= 0; pcb++) {
949 cb = *pcb;
950 jio_fprintf(stdout, "class=%s, 0x%x\n", cbName(cb), cbLoader(cb));
952 BINCLASS_UNLOCK();
954 #endif
956 static ClassClass *
957 FindLoadedClass(char *name, struct Hjava_lang_ClassLoader *loader)
959 int left, right, middle, result;
960 ClassClass *cb = NULL;
962 BINCLASS_LOCK();
963 left = 0;
964 right = nbinclasses - 1;
965 result = 1;
966 while (left <= right) {
967 middle = (left + right)/2;
968 cb = binclasses[middle];
969 result = strcmp(name, cbName(cb));
970 if (result == 0) {
971 if (loader < cbLoader(cb)) {
972 result = -1;
973 } else if (loader > cbLoader(cb)) {
974 result = 1;
975 } else {
976 result = 0;
979 if (result < 0) {
980 right = middle - 1;
981 } else if (result > 0) {
982 left = middle + 1;
983 } else {
984 break;
988 BINCLASS_UNLOCK();
989 if (result == 0) {
990 return cb;
992 return NULL;
995 /* We attempt to resolve it, also, if the "resolve" argument is true.
996 * Otherwise, we only perform a minimal initialization on it, such that
997 * it points to its superclass, which points to its superclass. . . .
998 */
1000 static ClassClass *
1001 InitializeAndResolveClass(ClassClass *cb, bool_t resolve)
1003 char *err, *detail = NULL;
1004 if ((err = InitializeClass(cb, &detail))) {
1005 /* Check for underlying error already posted */
1006 if (!exceptionOccurred(EE()))
1007 SignalError(0, err, detail);
1008 return 0;
1010 if (resolve) {
1011 err = ResolveClass(cb, &detail);
1012 if (err) {
1013 /* Check for underlying error already posted */
1014 if (!exceptionOccurred(EE()))
1015 SignalError(0, err, detail);
1016 return 0;
1019 return cb;
1022 /* Find the class with the given name.
1023 * If "resolve" is true, then we completely resolve the class. Otherwise,
1024 * we only make sure that it points to its superclass, which points to its
1025 * superclass, . . . .
1026 */
1027 ClassClass *(*class_loader_func)(HObject *loader, char *name, long resolve) = 0;
1029 ClassClass *
1030 FindClass(struct execenv *ee, char *name, bool_t resolve)
1032 return FindClassFromClass(ee, name, resolve, 0);
1036 /*
1037 * lock_classes and unlock_classes are exported by the JIT interface,
1038 * but no longer used anywhere else. It grabs both locks to ensure
1039 * backward compatibility with 1.0.2.
1040 */
1041 void
1042 lock_classes()
1044 LOADCLASS_LOCK();
1045 BINCLASS_LOCK();
1048 void
1049 unlock_classes()
1051 BINCLASS_UNLOCK();
1052 LOADCLASS_UNLOCK();
1055 extern char *output_path;
1057 extern ClassClass *
1058 LoadClassFromFile(char *fn, char *dir, char *class_name);
1060 ClassClass *
1061 FindClassFromClass(struct execenv *ee, char *name, bool_t resolve,
1062 ClassClass *from)
1064 char fn[64];
1065 sprintf(fn, "%s.class", name);
1066 return LoadClassFromFile(fn, output_path, name);
1069 /*
1070 * FindStickySystemClass is a variant of FindClassFromClass that makes the
1071 * class sticky (immune to class GC) if the class can be found. It is only
1072 * used on system classes, i.e. classes with no class loader, so it's
1073 * equivalent to FindClassFromClass with "from" argument 0. It returns 0
1074 * if the class can't be found, and like FindClass assumes that the caller
1075 * will deal with that. Note that until the class has been made sticky it
1076 * must be kept somewhere where GC will find it.
1077 */
1078 ClassClass *
1079 FindStickySystemClass(struct execenv *ee, char *name, bool_t resolve)
1081 ClassClass *cb;
1082 if ((cb = FindClassFromClass(ee, name, resolve, 0)) != NULL) {
1083 MakeClassSticky(cb);
1085 return cb;
1088 /* Find the array class with the specified name. */
1089 static ClassClass *
1090 Locked_FindArrayClassFromClass(struct execenv *ee, char *name,
1091 ClassClass *from) {
1092 struct Hjava_lang_ClassLoader *fromLoader =
1093 (from == NULL) ? NULL : cbLoader(from);
1094 char *name_p;
1095 int depth, base_type;
1096 ClassClass *cb;
1097 struct Hjava_lang_ClassLoader *loader;
1098 ClassClass *inner_cb;
1100 sysAssert(name[0] == SIGNATURE_ARRAY);
1102 if (fromLoader == NULL) {
1103 /* quick optimization if we know that we don't need a class loader */
1104 cb = FindLoadedClass(name, NULL);
1105 if (cb != NULL)
1106 return cb;
1111 /* Strip off all the initial SIGNATURE_ARRAY's to determine the depth,
1112 * and also what's left. When we're done, name_p points at the first
1113 * non-character, and depth is the count of the array depth
1114 */
1115 for (name_p = name, depth = 0; *name_p == SIGNATURE_ARRAY;
1116 name_p++, depth++);
1118 /* Look at the character to determine what type of array we have. */
1119 switch(*name_p++) {
1120 case SIGNATURE_INT: base_type = T_INT; break;
1121 case SIGNATURE_LONG: base_type = T_LONG; break;
1122 case SIGNATURE_FLOAT: base_type = T_FLOAT; break;
1123 case SIGNATURE_DOUBLE: base_type = T_DOUBLE; break;
1124 case SIGNATURE_BOOLEAN:base_type = T_BOOLEAN; break;
1125 case SIGNATURE_BYTE: base_type = T_BYTE; break;
1126 case SIGNATURE_CHAR: base_type = T_CHAR; break;
1127 case SIGNATURE_SHORT: base_type = T_SHORT; break;
1128 case SIGNATURE_CLASS: base_type = T_CLASS; break;
1129 default: return NULL; /* bad signature */
1131 if (base_type == T_CLASS) {
1132 char buffer_space[50];
1133 char *buffer = buffer_space;
1134 char *endChar = strchr(name_p, SIGNATURE_ENDCLASS);
1135 int nameLength = endChar - name_p;
1136 if (endChar == NULL || endChar[1] != '\0')
1137 return NULL;
1138 if (nameLength >= sizeof(buffer_space)) /* need bigger buffer */
1139 buffer = sysMalloc(nameLength + 1);
1140 memcpy(buffer, name_p, nameLength);
1141 buffer[nameLength] = '\0';
1142 inner_cb = FindClassFromClass(ee, buffer, FALSE, from);
1143 if (buffer != buffer_space) /* free buffer, if we malloc'ed it */
1144 sysFree(buffer);
1145 if (inner_cb == NULL)
1146 return NULL;
1147 /* loader should either be fromLoader or NULL. */
1148 loader = cbLoader(inner_cb);
1149 } else {
1150 if (*name_p != '\0') /* bad signature */
1151 return NULL;
1152 inner_cb = NULL;
1153 loader = NULL;
1157 LOADCLASS_LOCK();
1158 cb = FindLoadedClass(name, loader);
1159 if (cb == NULL) {
1160 /* Create the fake array class corresponding to this.
1161 */
1162 cb = createFakeArrayClass(name, base_type, depth, inner_cb, loader);
1163 }
1164 LOADCLASS_UNLOCK();
1165 return cb;
1168 /*
1169 * Convert a name and type to a hash code
1171 * We make copies of all strings that go into the hash table
1172 * in case the class that is the source of the strings being
1173 * inserted is eventually unloaded.
1174 */
1175 unsigned NameAndTypeToHash(char *name, char *type)
1177 extern struct StrIDhash *nameTypeHash;
1179 unsigned name_key;
1180 unsigned type_key;
1181 unsigned ret;
1183 NAMETYPEHASH_LOCK();
1184 if (((name_key = Str2ID(&nameTypeHash, name, 0, TRUE)) == 0) ||
1185 ((type_key = Str2ID(&nameTypeHash, type, 0, TRUE)) == 0)) {
1186 SignalError(0, JAVAPKG "OutOfMemoryError", 0);
1187 ret = 0;
1188 } else {
1189 ret = (name_key << 16) + type_key;
1191 NAMETYPEHASH_UNLOCK();
1193 return ret;
1196 /*
1197 * Pseudo-classes to represent primitive Java types.
1198 */
1200 ClassClass *class_void;
1201 ClassClass *class_boolean;
1202 ClassClass *class_byte;
1203 ClassClass *class_char;
1204 ClassClass *class_short;
1205 ClassClass *class_int;
1206 ClassClass *class_long;
1207 ClassClass *class_float;
1208 ClassClass *class_double;
1210 struct primtype {
1211 char *name;
1212 char typesig;
1213 unsigned char typecode;
1214 unsigned char slotsize;
1215 unsigned char elementsize;
1216 ClassClass **cellp;
1217 } const primitive_types[] = {
1218 { "void", SIGNATURE_VOID, T_VOID, 0, 0, &class_void },
1219 { "boolean",SIGNATURE_BOOLEAN, T_BOOLEAN, 4, 1, &class_boolean },
1220 { "byte", SIGNATURE_BYTE, T_BYTE, 4, 1, &class_byte },
1221 { "char", SIGNATURE_CHAR, T_CHAR, 4, 2, &class_char },
1222 { "short", SIGNATURE_SHORT, T_SHORT, 4, 2, &class_short },
1223 { "int", SIGNATURE_INT, T_INT, 4, 4, &class_int },
1224 { "long", SIGNATURE_LONG, T_LONG, 8, 8, &class_long },
1225 { "float", SIGNATURE_FLOAT, T_FLOAT, 4, 4, &class_float },
1226 { "double", SIGNATURE_DOUBLE, T_DOUBLE, 8, 8, &class_double }
1227 };
1229 #define PRIMITIVE_TYPE_COUNT \
1230 (sizeof (primitive_types) / sizeof (primitive_types[0]))
1232 #define GET_PRIMITIVE_CLASS(nm) \
1233 (class_##nm ? class_##nm : FindPrimitiveClass(#nm))
1235 ClassClass *
1236 FindPrimitiveClass(char *name)
1238 int i;
1239 ClassClass *cb;
1240 const struct primtype *p;
1242 for (i = 0; i < PRIMITIVE_TYPE_COUNT; i++) {
1243 p = &primitive_types[i];
1244 if (strcmp(name, p->name) == 0) {
1245 cb = *p->cellp;
1246 if (cb == NULL) {
1247 char *err, *detail = NULL;
1248 cb = createPrimitiveClass(p->name, p->typesig, p->typecode,
1249 p->slotsize, p->elementsize);
1250 sysAssert(cb != NULL);
1251 if ((err = InitializeClass(cb, &detail)) != NULL)
1252 return NULL; /* XXX */
1253 if ((err = ResolveClass(cb, &detail)) != NULL)
1254 return NULL; /* XXX*/
1255 *p->cellp = cb;
1257 return cb;
1260 return NULL;
1263 static void
1264 InitPrimitiveClasses()
1266 int i;
1267 for (i = 0; i < PRIMITIVE_TYPE_COUNT; i++)
1268 FindPrimitiveClass(primitive_types[i].name);