1 /* src/vm/linker.c - class linker functions
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
35 $Id: linker.c 4799 2006-04-20 20:38:07Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "vm/builtin.h"
50 #include "vm/classcache.h"
51 #include "vm/exceptions.h"
52 #include "vm/loader.h"
53 #include "vm/options.h"
54 #include "vm/resolve.h"
55 #include "vm/statistics.h"
56 #include "vm/stringlocal.h"
57 #include "vm/access.h"
58 #include "vm/rt-timing.h"
61 /* global variables ***********************************************************/
63 static s4 interfaceindex; /* sequential numbering of interfaces */
67 /* primitivetype_table *********************************************************
69 Structure for primitive classes: contains the class for wrapping
70 the primitive type, the primitive class, the name of the class for
71 wrapping, the one character type signature and the name of the
74 CAUTION: Don't change the order of the types. This table is indexed
75 by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
77 *******************************************************************************/
79 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
80 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
81 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
82 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
83 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
84 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
85 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
86 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
87 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
88 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
89 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
90 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
94 /* private functions **********************************************************/
96 static bool link_primitivetype_table(void);
97 static classinfo *link_class_intern(classinfo *c);
98 static arraydescriptor *link_array(classinfo *c);
99 static void linker_compute_class_values(classinfo *c);
100 static void linker_compute_subclasses(classinfo *c);
101 static void linker_addinterface(classinfo *c, classinfo *ic);
102 static s4 class_highestinterface(classinfo *c);
105 /* linker_init *****************************************************************
107 Initializes the linker subsystem.
109 *******************************************************************************/
111 bool linker_init(void)
113 /* reset interface index */
117 /* link java.lang.Class as first class of the system, because we
118 need it's vftbl for all other classes so we can use a class as
121 if (!link_class(class_java_lang_Class))
124 /* now set the header.vftbl of all classes which were created
125 before java.lang.Class was linked */
127 class_postset_header_vftbl();
130 /* link important system classes */
132 if (!link_class(class_java_lang_Object))
135 if (!link_class(class_java_lang_String))
138 if (!link_class(class_java_lang_Cloneable))
141 if (!link_class(class_java_io_Serializable))
145 /* link classes for wrapping primitive types */
147 if (!link_class(class_java_lang_Void))
150 if (!link_class(class_java_lang_Boolean))
153 if (!link_class(class_java_lang_Byte))
156 if (!link_class(class_java_lang_Character))
159 if (!link_class(class_java_lang_Short))
162 if (!link_class(class_java_lang_Integer))
165 if (!link_class(class_java_lang_Long))
168 if (!link_class(class_java_lang_Float))
171 if (!link_class(class_java_lang_Double))
175 /* load some other important classes */
177 if (!link_class(class_java_lang_ClassLoader))
180 if (!link_class(class_java_lang_SecurityManager))
183 if (!link_class(class_java_lang_System))
186 if (!link_class(class_java_lang_Thread))
189 if (!link_class(class_java_lang_ThreadGroup))
192 if (!link_class(class_java_lang_VMThread))
196 /* some classes which may be used more often */
198 if (!link_class(class_java_lang_StackTraceElement))
201 if (!link_class(class_java_lang_reflect_Constructor))
204 if (!link_class(class_java_lang_reflect_Field))
207 if (!link_class(class_java_lang_reflect_Method))
210 if (!link_class(class_java_security_PrivilegedAction))
213 if (!link_class(class_java_util_Vector))
216 if (!link_class(arrayclass_java_lang_Object))
220 /* create pseudo classes used by the typechecker */
222 /* pseudo class for Arraystubs (extends java.lang.Object) */
224 pseudo_class_Arraystub =
225 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
226 pseudo_class_Arraystub->state |= CLASS_LOADED;
227 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
228 pseudo_class_Arraystub->interfacescount = 2;
229 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
230 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
231 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
233 if (!classcache_store_unique(pseudo_class_Arraystub)) {
234 log_text("could not cache pseudo_class_Arraystub");
238 if (!link_class(pseudo_class_Arraystub))
241 /* pseudo class representing the null type */
243 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
244 pseudo_class_Null->state |= CLASS_LOADED;
245 pseudo_class_Null->super.cls = class_java_lang_Object;
247 if (!classcache_store_unique(pseudo_class_Null)) {
248 log_text("could not cache pseudo_class_Null");
252 if (!link_class(pseudo_class_Null))
255 /* pseudo class representing new uninitialized objects */
257 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
258 pseudo_class_New->state |= CLASS_LOADED;
259 pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
260 pseudo_class_New->super.cls = class_java_lang_Object;
262 if (!classcache_store_unique(pseudo_class_New)) {
263 log_text("could not cache pseudo_class_New");
267 /* create classes representing primitive types */
269 if (!link_primitivetype_table())
273 /* Correct vftbl-entries (retarded loading and linking of class */
274 /* java/lang/String). */
276 stringtable_update();
282 /* link_primitivetype_table ****************************************************
284 Create classes representing primitive types.
286 *******************************************************************************/
288 static bool link_primitivetype_table(void)
294 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
297 if (!primitivetype_table[i].name)
300 /* create primitive class */
302 c = class_create_classinfo(utf_new_char(primitivetype_table[i].name));
304 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
306 /* prevent loader from loading primitive class */
308 c->state |= CLASS_LOADED;
310 /* INFO: don't put primitive classes into the classcache */
315 primitivetype_table[i].class_primitive = c;
317 /* create class for wrapping the primitive type */
319 u = utf_new_char(primitivetype_table[i].wrapname);
321 if (!(c = load_class_bootstrap(u)))
324 primitivetype_table[i].class_wrap = c;
326 /* create the primitive array class */
328 if (primitivetype_table[i].arrayname) {
329 u = utf_new_char(primitivetype_table[i].arrayname);
330 c = class_create_classinfo(u);
331 c = load_newly_created_array(c, NULL);
335 primitivetype_table[i].arrayclass = c;
337 assert(c->state & CLASS_LOADED);
339 if (!(c->state & CLASS_LINKED))
343 primitivetype_table[i].arrayvftbl = c->vftbl;
351 /* link_class ******************************************************************
353 Wrapper function for link_class_intern to ease monitor enter/exit
354 and exception handling.
356 *******************************************************************************/
358 classinfo *link_class(classinfo *c)
361 #if defined(ENABLE_RT_TIMING)
362 struct timespec time_start, time_end;
365 RT_TIMING_GET_TIME(time_start);
368 exceptions_throw_nullpointerexception();
372 #if defined(USE_THREADS)
373 /* enter a monitor on the class */
375 builtin_monitorenter((java_objectheader *) c);
378 /* maybe the class is already linked */
380 if (c->state & CLASS_LINKED) {
381 #if defined(USE_THREADS)
382 builtin_monitorexit((java_objectheader *) c);
388 #if defined(ENABLE_STATISTICS)
391 if (getcompilingtime)
392 compilingtime_stop();
398 /* call the internal function */
400 r = link_class_intern(c);
402 /* if return value is NULL, we had a problem and the class is not linked */
405 c->state &= ~CLASS_LINKING;
407 #if defined(ENABLE_STATISTICS)
413 if (getcompilingtime)
414 compilingtime_start();
417 #if defined(USE_THREADS)
418 /* leave the monitor */
420 builtin_monitorexit((java_objectheader *) c);
423 RT_TIMING_GET_TIME(time_end);
425 RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
431 /* link_class_intern ***********************************************************
433 Tries to link a class. The function calculates the length in bytes
434 that an instance of this class requires as well as the VTBL for
435 methods and interface methods.
437 *******************************************************************************/
439 static classinfo *link_class_intern(classinfo *c)
441 classinfo *super; /* super class */
442 classinfo *tc; /* temporary class variable */
443 s4 supervftbllength; /* vftbllegnth of super class */
444 s4 vftbllength; /* vftbllength of current class */
445 s4 interfacetablelength; /* interface table length */
446 vftbl_t *v; /* vftbl of current class */
447 s4 i,j; /* interface/method/field counter */
448 arraydescriptor *arraydesc; /* descriptor for array classes */
449 #if defined(ENABLE_RT_TIMING)
450 struct timespec time_start, time_resolving, time_compute_vftbl,
451 time_abstract, time_compute_iftbl, time_fill_vftbl,
452 time_offsets, time_fill_iftbl, time_finalizer,
453 time_exceptions, time_subclasses;
456 RT_TIMING_GET_TIME(time_start);
458 /* the class is already linked */
460 if (c->state & CLASS_LINKED)
465 log_message_class("Linking class: ", c);
468 /* the class must be loaded */
470 /* XXX should this be a specific exception? */
471 assert(c->state & CLASS_LOADED);
473 /* cache the self-reference of this class */
474 /* we do this for cases where the defining loader of the class */
475 /* has not yet been recorded as an initiating loader for the class */
476 /* this is needed so subsequent code can assume that self-refs */
477 /* will always resolve lazily */
478 /* No need to do it for the bootloader - it is always registered */
479 /* as initiating loader for the classes it loads. */
481 classcache_store(c->classloader,c,false);
483 /* this class is currently linking */
485 c->state |= CLASS_LINKING;
489 /* check interfaces */
491 for (i = 0; i < c->interfacescount; i++) {
492 /* resolve this super interface */
494 if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager,
498 c->interfaces[i].cls = tc;
500 /* detect circularity */
504 new_exception_utfmessage(string_java_lang_ClassCircularityError,
509 assert(tc->state & CLASS_LOADED);
511 if (!(tc->flags & ACC_INTERFACE)) {
513 new_exception_message(string_java_lang_IncompatibleClassChangeError,
514 "Implementing class");
518 if (!(tc->state & CLASS_LINKED))
523 /* check super class */
527 if (c->super.any == NULL) { /* class java.lang.Object */
529 c->instancesize = sizeof(java_objectheader);
531 vftbllength = supervftbllength = 0;
536 /* resolve super class */
538 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
541 c->super.cls = super;
543 /* detect circularity */
547 new_exception_utfmessage(string_java_lang_ClassCircularityError,
552 assert(super->state & CLASS_LOADED);
554 if (super->flags & ACC_INTERFACE) {
555 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
556 log_text("Interface specified as super class");
560 /* Don't allow extending final classes */
562 if (super->flags & ACC_FINAL) {
564 new_exception_message(string_java_lang_VerifyError,
565 "Cannot inherit from final class");
569 if (!(super->state & CLASS_LINKED))
570 if (!link_class(super))
573 /* handle array classes */
575 if (c->name->text[0] == '[')
576 if (!(arraydesc = link_array(c)))
579 if (c->flags & ACC_INTERFACE)
580 c->index = interfaceindex++;
582 c->index = super->index + 1;
584 c->instancesize = super->instancesize;
586 vftbllength = supervftbllength = super->vftbl->vftbllength;
588 c->finalizer = super->finalizer;
590 RT_TIMING_GET_TIME(time_resolving);
593 /* compute vftbl length */
595 for (i = 0; i < c->methodscount; i++) {
596 methodinfo *m = &(c->methods[i]);
598 if (!(m->flags & ACC_STATIC)) { /* is instance method */
604 for (j = 0; j < tc->methodscount; j++) {
605 if (method_canoverwrite(m, &(tc->methods[j]))) {
606 if (tc->methods[j].flags & ACC_PRIVATE)
607 goto notfoundvftblindex;
609 /* package-private methods in other packages */
610 /* must not be overridden */
611 /* (see Java Language Specification 8.4.8.1) */
612 if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
613 && !SAME_PACKAGE(c,tc) )
615 goto notfoundvftblindex;
618 if (tc->methods[j].flags & ACC_FINAL) {
619 /* class a overrides final method . */
621 new_exception(string_java_lang_VerifyError);
625 /* method m overwrites method j of class tc */
627 if (!classcache_add_constraints_for_params(
628 c->classloader, tc->classloader, m))
631 m->vftblindex = tc->methods[j].vftblindex;
632 goto foundvftblindex;
640 m->vftblindex = (vftbllength++);
645 RT_TIMING_GET_TIME(time_compute_vftbl);
648 /* Check all interfaces of an abtract class (maybe be an interface
649 too) for unimplemented methods. Such methods are called
650 miranda-methods and are marked with the ACC_MIRANDA flag.
651 VMClass.getDeclaredMethods does not return such methods. */
653 if (c->flags & ACC_ABSTRACT) {
656 s4 abstractmethodscount;
660 abstractmethodscount = 0;
662 /* check all interfaces of the abtract class */
664 for (i = 0; i < c->interfacescount; i++) {
665 ic = c->interfaces[i].cls;
667 for (j = 0; j < ic->methodscount; j++) {
668 im = &(ic->methods[j]);
670 /* skip `<clinit>' and `<init>' */
672 if ((im->name == utf_clinit) || (im->name == utf_init))
675 for (tc = c; tc != NULL; tc = tc->super.cls) {
676 for (k = 0; k < tc->methodscount; k++) {
677 if (method_canoverwrite(im, &(tc->methods[k])))
678 goto noabstractmethod;
682 abstractmethodscount++;
689 if (abstractmethodscount > 0) {
692 /* reallocate methods memory */
694 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
695 c->methodscount + abstractmethodscount);
697 for (i = 0; i < c->interfacescount; i++) {
698 ic = c->interfaces[i].cls;
700 for (j = 0; j < ic->methodscount; j++) {
701 im = &(ic->methods[j]);
703 /* skip `<clinit>' and `<init>' */
705 if ((im->name == utf_clinit) || (im->name == utf_init))
708 for (tc = c; tc != NULL; tc = tc->super.cls) {
709 for (k = 0; k < tc->methodscount; k++) {
710 if (method_canoverwrite(im, &(tc->methods[k])))
711 goto noabstractmethod2;
715 /* Copy the method found into the new c->methods
716 array and tag it as miranda-method. */
718 am = &(c->methods[c->methodscount]);
721 MCOPY(am, im, methodinfo, 1);
723 am->vftblindex = (vftbllength++);
725 am->flags |= ACC_MIRANDA;
733 RT_TIMING_GET_TIME(time_abstract);
736 #if defined(ENABLE_STATISTICS)
739 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
742 /* compute interfacetable length */
744 interfacetablelength = 0;
747 for (i = 0; i < tc->interfacescount; i++) {
748 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
749 if (h > interfacetablelength)
750 interfacetablelength = h;
754 RT_TIMING_GET_TIME(time_compute_iftbl);
756 /* allocate virtual function table */
758 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
759 sizeof(methodptr) * (vftbllength - 1) +
760 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
761 v = (vftbl_t *) (((methodptr *) v) +
762 (interfacetablelength - 1) * (interfacetablelength > 1));
765 v->vftbllength = vftbllength;
766 v->interfacetablelength = interfacetablelength;
767 v->arraydesc = arraydesc;
769 /* store interface index in vftbl */
771 if (c->flags & ACC_INTERFACE)
772 v->baseval = -(c->index);
774 /* copy virtual function table of super class */
776 for (i = 0; i < supervftbllength; i++)
777 v->table[i] = super->vftbl->table[i];
779 /* add method stubs into virtual function table */
781 for (i = 0; i < c->methodscount; i++) {
782 methodinfo *m = &(c->methods[i]);
784 /* Methods in ABSTRACT classes from interfaces maybe already
785 have a stubroutine. */
787 if (!m->stubroutine) {
788 #if defined(ENABLE_JIT)
789 # if defined(ENABLE_INTRP)
791 m->stubroutine = intrp_createcompilerstub(m);
794 m->stubroutine = createcompilerstub(m);
796 m->stubroutine = intrp_createcompilerstub(m);
800 if (!(m->flags & ACC_STATIC))
801 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
803 RT_TIMING_GET_TIME(time_fill_vftbl);
805 /* compute instance size and offset of each field */
807 for (i = 0; i < c->fieldscount; i++) {
809 fieldinfo *f = &(c->fields[i]);
811 if (!(f->flags & ACC_STATIC)) {
812 dsize = descriptor_typesize(f->parseddesc);
813 c->instancesize = ALIGN(c->instancesize, dsize);
814 f->offset = c->instancesize;
815 c->instancesize += dsize;
818 RT_TIMING_GET_TIME(time_offsets);
820 /* initialize interfacetable and interfacevftbllength */
822 v->interfacevftbllength = MNEW(s4, interfacetablelength);
824 #if defined(ENABLE_STATISTICS)
826 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
829 for (i = 0; i < interfacetablelength; i++) {
830 v->interfacevftbllength[i] = 0;
831 v->interfacetable[-i] = NULL;
836 for (tc = c; tc != NULL; tc = tc->super.cls)
837 for (i = 0; i < tc->interfacescount; i++)
838 linker_addinterface(c, tc->interfaces[i].cls);
840 RT_TIMING_GET_TIME(time_fill_iftbl);
842 /* add finalizer method (not for java.lang.Object) */
847 fi = class_findmethod(c, utf_finalize, utf_void__void);
850 if (!(fi->flags & ACC_STATIC))
853 RT_TIMING_GET_TIME(time_finalizer);
855 /* resolve exception class references */
857 for (i = 0; i < c->methodscount; i++) {
858 methodinfo *m = &(c->methods[i]);
860 for (j = 0; j < m->exceptiontablelength; j++) {
861 if (!m->exceptiontable[j].catchtype.any)
863 if (!resolve_classref_or_classinfo(NULL,
864 m->exceptiontable[j].catchtype,
865 resolveEager, true, false,
866 &(m->exceptiontable[j].catchtype.cls)))
870 RT_TIMING_GET_TIME(time_exceptions);
874 linker_compute_subclasses(c);
876 RT_TIMING_GET_TIME(time_subclasses);
878 /* revert the linking state and class is linked */
880 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
884 log_message_class("Linking done class: ", c);
887 RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
888 RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
889 RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
890 RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
891 RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
892 RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
893 RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
894 RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
895 RT_TIMING_TIME_DIFF(time_finalizer ,time_exceptions ,RT_TIMING_LINK_EXCEPTS);
896 RT_TIMING_TIME_DIFF(time_exceptions ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
898 /* just return c to show that we didn't had a problem */
904 /* link_array ******************************************************************
906 This function is called by link_class to create the arraydescriptor
909 This function returns NULL if the array cannot be linked because
910 the component type has not been linked yet.
912 *******************************************************************************/
914 static arraydescriptor *link_array(classinfo *c)
918 arraydescriptor *desc;
923 namelen = c->name->blength;
925 /* Check the component type */
927 switch (c->name->text[1]) {
929 /* c is an array of arrays. */
930 u = utf_new(c->name->text + 1, namelen - 1);
931 if (!(comp = load_class_from_classloader(u, c->classloader)))
936 /* c is an array of objects. */
937 u = utf_new(c->name->text + 2, namelen - 3);
938 if (!(comp = load_class_from_classloader(u, c->classloader)))
943 /* If the component type has not been linked, link it now */
945 assert(!comp || (comp->state & CLASS_LOADED));
947 if (comp && !(comp->state & CLASS_LINKED))
948 if (!link_class(comp))
951 /* Allocate the arraydescriptor */
953 desc = NEW(arraydescriptor);
956 /* c is an array of references */
957 desc->arraytype = ARRAYTYPE_OBJECT;
958 desc->componentsize = sizeof(void*);
959 desc->dataoffset = OFFSET(java_objectarray, data);
961 compvftbl = comp->vftbl;
964 log_text("Component class has no vftbl");
968 desc->componentvftbl = compvftbl;
970 if (compvftbl->arraydesc) {
971 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
973 if (compvftbl->arraydesc->dimension >= 255) {
974 log_text("Creating array of dimension >255");
978 desc->dimension = compvftbl->arraydesc->dimension + 1;
979 desc->elementtype = compvftbl->arraydesc->elementtype;
982 desc->elementvftbl = compvftbl;
984 desc->elementtype = ARRAYTYPE_OBJECT;
988 /* c is an array of a primitive type */
989 switch (c->name->text[1]) {
991 desc->arraytype = ARRAYTYPE_BOOLEAN;
992 desc->dataoffset = OFFSET(java_booleanarray,data);
993 desc->componentsize = sizeof(u1);
997 desc->arraytype = ARRAYTYPE_BYTE;
998 desc->dataoffset = OFFSET(java_bytearray,data);
999 desc->componentsize = sizeof(u1);
1003 desc->arraytype = ARRAYTYPE_CHAR;
1004 desc->dataoffset = OFFSET(java_chararray,data);
1005 desc->componentsize = sizeof(u2);
1009 desc->arraytype = ARRAYTYPE_DOUBLE;
1010 desc->dataoffset = OFFSET(java_doublearray,data);
1011 desc->componentsize = sizeof(double);
1015 desc->arraytype = ARRAYTYPE_FLOAT;
1016 desc->dataoffset = OFFSET(java_floatarray,data);
1017 desc->componentsize = sizeof(float);
1021 desc->arraytype = ARRAYTYPE_INT;
1022 desc->dataoffset = OFFSET(java_intarray,data);
1023 desc->componentsize = sizeof(s4);
1027 desc->arraytype = ARRAYTYPE_LONG;
1028 desc->dataoffset = OFFSET(java_longarray,data);
1029 desc->componentsize = sizeof(s8);
1033 desc->arraytype = ARRAYTYPE_SHORT;
1034 desc->dataoffset = OFFSET(java_shortarray,data);
1035 desc->componentsize = sizeof(s2);
1039 *exceptionptr = new_noclassdeffounderror(c->name);
1043 desc->componentvftbl = NULL;
1044 desc->elementvftbl = NULL;
1045 desc->dimension = 1;
1046 desc->elementtype = desc->arraytype;
1053 /* linker_compute_subclasses ***************************************************
1057 *******************************************************************************/
1059 static void linker_compute_subclasses(classinfo *c)
1061 #if defined(USE_THREADS)
1062 #if defined(NATIVE_THREADS)
1069 if (!(c->flags & ACC_INTERFACE)) {
1074 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1075 c->nextsub = c->super.cls->sub;
1076 c->super.cls->sub = c;
1081 /* compute class values */
1083 linker_compute_class_values(class_java_lang_Object);
1085 #if defined(USE_THREADS)
1086 #if defined(NATIVE_THREADS)
1095 /* linker_compute_class_values *************************************************
1099 *******************************************************************************/
1101 static void linker_compute_class_values(classinfo *c)
1105 c->vftbl->baseval = ++classvalue;
1110 linker_compute_class_values(subs);
1112 subs = subs->nextsub;
1115 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1119 /* linker_addinterface *********************************************************
1121 Is needed by link_class for adding a VTBL to a class. All
1122 interfaces implemented by ic are added as well.
1124 *******************************************************************************/
1126 static void linker_addinterface(classinfo *c, classinfo *ic)
1130 vftbl_t *v = c->vftbl;
1132 if (i >= v->interfacetablelength) {
1133 log_text("Inernal error: interfacetable overflow");
1137 if (v->interfacetable[-i])
1140 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1141 v->interfacevftbllength[i] = 1;
1142 v->interfacetable[-i] = MNEW(methodptr, 1);
1143 v->interfacetable[-i][0] = NULL;
1146 v->interfacevftbllength[i] = ic->methodscount;
1147 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1149 #if defined(ENABLE_STATISTICS)
1151 count_vftbl_len += sizeof(methodptr) *
1152 (ic->methodscount + (ic->methodscount == 0));
1155 for (j = 0; j < ic->methodscount; j++) {
1159 for (m = 0; m < sc->methodscount; m++) {
1160 methodinfo *mi = &(sc->methods[m]);
1162 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1163 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1174 for (j = 0; j < ic->interfacescount; j++)
1175 linker_addinterface(c, ic->interfaces[j].cls);
1179 /* class_highestinterface ******************************************************
1181 Used by the function link_class to determine the amount of memory
1182 needed for the interface table.
1184 *******************************************************************************/
1186 static s4 class_highestinterface(classinfo *c)
1192 /* check for ACC_INTERFACE bit already done in link_class_intern */
1196 for (i = 0; i < c->interfacescount; i++) {
1197 h2 = class_highestinterface(c->interfaces[i].cls);
1208 * These are local overrides for various environment variables in Emacs.
1209 * Please do not remove this and leave it at the end of the file, where
1210 * Emacs will automagically detect them.
1211 * ---------------------------------------------------------------------
1214 * indent-tabs-mode: t
1218 * vim:noexpandtab:sw=4:ts=4: