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 4801 2006-04-20 21:47:41Z 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 bool 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 defined(ENABLE_VERIFIER)
628 if (!classcache_add_constraints_for_params(
629 c->classloader, tc->classloader, m))
633 m->vftblindex = tc->methods[j].vftblindex;
634 goto foundvftblindex;
642 m->vftblindex = (vftbllength++);
647 RT_TIMING_GET_TIME(time_compute_vftbl);
650 /* Check all interfaces of an abtract class (maybe be an interface
651 too) for unimplemented methods. Such methods are called
652 miranda-methods and are marked with the ACC_MIRANDA flag.
653 VMClass.getDeclaredMethods does not return such methods. */
655 if (c->flags & ACC_ABSTRACT) {
658 s4 abstractmethodscount;
662 abstractmethodscount = 0;
664 /* check all interfaces of the abtract class */
666 for (i = 0; i < c->interfacescount; i++) {
667 ic = c->interfaces[i].cls;
669 for (j = 0; j < ic->methodscount; j++) {
670 im = &(ic->methods[j]);
672 /* skip `<clinit>' and `<init>' */
674 if ((im->name == utf_clinit) || (im->name == utf_init))
677 for (tc = c; tc != NULL; tc = tc->super.cls) {
678 for (k = 0; k < tc->methodscount; k++) {
679 if (method_canoverwrite(im, &(tc->methods[k])))
680 goto noabstractmethod;
684 abstractmethodscount++;
691 if (abstractmethodscount > 0) {
694 /* reallocate methods memory */
696 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
697 c->methodscount + abstractmethodscount);
699 for (i = 0; i < c->interfacescount; i++) {
700 ic = c->interfaces[i].cls;
702 for (j = 0; j < ic->methodscount; j++) {
703 im = &(ic->methods[j]);
705 /* skip `<clinit>' and `<init>' */
707 if ((im->name == utf_clinit) || (im->name == utf_init))
710 for (tc = c; tc != NULL; tc = tc->super.cls) {
711 for (k = 0; k < tc->methodscount; k++) {
712 if (method_canoverwrite(im, &(tc->methods[k])))
713 goto noabstractmethod2;
717 /* Copy the method found into the new c->methods
718 array and tag it as miranda-method. */
720 am = &(c->methods[c->methodscount]);
723 MCOPY(am, im, methodinfo, 1);
725 am->vftblindex = (vftbllength++);
727 am->flags |= ACC_MIRANDA;
735 RT_TIMING_GET_TIME(time_abstract);
738 #if defined(ENABLE_STATISTICS)
741 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
744 /* compute interfacetable length */
746 interfacetablelength = 0;
749 for (i = 0; i < tc->interfacescount; i++) {
750 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
751 if (h > interfacetablelength)
752 interfacetablelength = h;
756 RT_TIMING_GET_TIME(time_compute_iftbl);
758 /* allocate virtual function table */
760 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
761 sizeof(methodptr) * (vftbllength - 1) +
762 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
763 v = (vftbl_t *) (((methodptr *) v) +
764 (interfacetablelength - 1) * (interfacetablelength > 1));
767 v->vftbllength = vftbllength;
768 v->interfacetablelength = interfacetablelength;
769 v->arraydesc = arraydesc;
771 /* store interface index in vftbl */
773 if (c->flags & ACC_INTERFACE)
774 v->baseval = -(c->index);
776 /* copy virtual function table of super class */
778 for (i = 0; i < supervftbllength; i++)
779 v->table[i] = super->vftbl->table[i];
781 /* add method stubs into virtual function table */
783 for (i = 0; i < c->methodscount; i++) {
784 methodinfo *m = &(c->methods[i]);
786 /* Methods in ABSTRACT classes from interfaces maybe already
787 have a stubroutine. */
789 if (!m->stubroutine) {
790 #if defined(ENABLE_JIT)
791 # if defined(ENABLE_INTRP)
793 m->stubroutine = intrp_createcompilerstub(m);
796 m->stubroutine = createcompilerstub(m);
798 m->stubroutine = intrp_createcompilerstub(m);
802 if (!(m->flags & ACC_STATIC))
803 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
805 RT_TIMING_GET_TIME(time_fill_vftbl);
807 /* compute instance size and offset of each field */
809 for (i = 0; i < c->fieldscount; i++) {
811 fieldinfo *f = &(c->fields[i]);
813 if (!(f->flags & ACC_STATIC)) {
814 dsize = descriptor_typesize(f->parseddesc);
815 c->instancesize = ALIGN(c->instancesize, dsize);
816 f->offset = c->instancesize;
817 c->instancesize += dsize;
820 RT_TIMING_GET_TIME(time_offsets);
822 /* initialize interfacetable and interfacevftbllength */
824 v->interfacevftbllength = MNEW(s4, interfacetablelength);
826 #if defined(ENABLE_STATISTICS)
828 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
831 for (i = 0; i < interfacetablelength; i++) {
832 v->interfacevftbllength[i] = 0;
833 v->interfacetable[-i] = NULL;
838 for (tc = c; tc != NULL; tc = tc->super.cls)
839 for (i = 0; i < tc->interfacescount; i++)
840 if (!linker_addinterface(c, tc->interfaces[i].cls))
843 RT_TIMING_GET_TIME(time_fill_iftbl);
845 /* add finalizer method (not for java.lang.Object) */
850 fi = class_findmethod(c, utf_finalize, utf_void__void);
853 if (!(fi->flags & ACC_STATIC))
856 RT_TIMING_GET_TIME(time_finalizer);
858 /* resolve exception class references */
860 for (i = 0; i < c->methodscount; i++) {
861 methodinfo *m = &(c->methods[i]);
863 for (j = 0; j < m->exceptiontablelength; j++) {
864 if (!m->exceptiontable[j].catchtype.any)
866 if (!resolve_classref_or_classinfo(NULL,
867 m->exceptiontable[j].catchtype,
868 resolveEager, true, false,
869 &(m->exceptiontable[j].catchtype.cls)))
873 RT_TIMING_GET_TIME(time_exceptions);
877 linker_compute_subclasses(c);
879 RT_TIMING_GET_TIME(time_subclasses);
881 /* revert the linking state and class is linked */
883 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
887 log_message_class("Linking done class: ", c);
890 RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
891 RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
892 RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
893 RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
894 RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
895 RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
896 RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
897 RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
898 RT_TIMING_TIME_DIFF(time_finalizer ,time_exceptions ,RT_TIMING_LINK_EXCEPTS);
899 RT_TIMING_TIME_DIFF(time_exceptions ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
901 /* just return c to show that we didn't had a problem */
907 /* link_array ******************************************************************
909 This function is called by link_class to create the arraydescriptor
912 This function returns NULL if the array cannot be linked because
913 the component type has not been linked yet.
915 *******************************************************************************/
917 static arraydescriptor *link_array(classinfo *c)
921 arraydescriptor *desc;
926 namelen = c->name->blength;
928 /* Check the component type */
930 switch (c->name->text[1]) {
932 /* c is an array of arrays. */
933 u = utf_new(c->name->text + 1, namelen - 1);
934 if (!(comp = load_class_from_classloader(u, c->classloader)))
939 /* c is an array of objects. */
940 u = utf_new(c->name->text + 2, namelen - 3);
941 if (!(comp = load_class_from_classloader(u, c->classloader)))
946 /* If the component type has not been linked, link it now */
948 assert(!comp || (comp->state & CLASS_LOADED));
950 if (comp && !(comp->state & CLASS_LINKED))
951 if (!link_class(comp))
954 /* Allocate the arraydescriptor */
956 desc = NEW(arraydescriptor);
959 /* c is an array of references */
960 desc->arraytype = ARRAYTYPE_OBJECT;
961 desc->componentsize = sizeof(void*);
962 desc->dataoffset = OFFSET(java_objectarray, data);
964 compvftbl = comp->vftbl;
967 log_text("Component class has no vftbl");
971 desc->componentvftbl = compvftbl;
973 if (compvftbl->arraydesc) {
974 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
976 if (compvftbl->arraydesc->dimension >= 255) {
977 log_text("Creating array of dimension >255");
981 desc->dimension = compvftbl->arraydesc->dimension + 1;
982 desc->elementtype = compvftbl->arraydesc->elementtype;
985 desc->elementvftbl = compvftbl;
987 desc->elementtype = ARRAYTYPE_OBJECT;
991 /* c is an array of a primitive type */
992 switch (c->name->text[1]) {
994 desc->arraytype = ARRAYTYPE_BOOLEAN;
995 desc->dataoffset = OFFSET(java_booleanarray,data);
996 desc->componentsize = sizeof(u1);
1000 desc->arraytype = ARRAYTYPE_BYTE;
1001 desc->dataoffset = OFFSET(java_bytearray,data);
1002 desc->componentsize = sizeof(u1);
1006 desc->arraytype = ARRAYTYPE_CHAR;
1007 desc->dataoffset = OFFSET(java_chararray,data);
1008 desc->componentsize = sizeof(u2);
1012 desc->arraytype = ARRAYTYPE_DOUBLE;
1013 desc->dataoffset = OFFSET(java_doublearray,data);
1014 desc->componentsize = sizeof(double);
1018 desc->arraytype = ARRAYTYPE_FLOAT;
1019 desc->dataoffset = OFFSET(java_floatarray,data);
1020 desc->componentsize = sizeof(float);
1024 desc->arraytype = ARRAYTYPE_INT;
1025 desc->dataoffset = OFFSET(java_intarray,data);
1026 desc->componentsize = sizeof(s4);
1030 desc->arraytype = ARRAYTYPE_LONG;
1031 desc->dataoffset = OFFSET(java_longarray,data);
1032 desc->componentsize = sizeof(s8);
1036 desc->arraytype = ARRAYTYPE_SHORT;
1037 desc->dataoffset = OFFSET(java_shortarray,data);
1038 desc->componentsize = sizeof(s2);
1042 *exceptionptr = new_noclassdeffounderror(c->name);
1046 desc->componentvftbl = NULL;
1047 desc->elementvftbl = NULL;
1048 desc->dimension = 1;
1049 desc->elementtype = desc->arraytype;
1056 /* linker_compute_subclasses ***************************************************
1060 *******************************************************************************/
1062 static void linker_compute_subclasses(classinfo *c)
1064 #if defined(USE_THREADS)
1065 #if defined(NATIVE_THREADS)
1072 if (!(c->flags & ACC_INTERFACE)) {
1077 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1078 c->nextsub = c->super.cls->sub;
1079 c->super.cls->sub = c;
1084 /* compute class values */
1086 linker_compute_class_values(class_java_lang_Object);
1088 #if defined(USE_THREADS)
1089 #if defined(NATIVE_THREADS)
1098 /* linker_compute_class_values *************************************************
1102 *******************************************************************************/
1104 static void linker_compute_class_values(classinfo *c)
1108 c->vftbl->baseval = ++classvalue;
1113 linker_compute_class_values(subs);
1115 subs = subs->nextsub;
1118 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1122 /* linker_addinterface *********************************************************
1124 Is needed by link_class for adding a VTBL to a class. All
1125 interfaces implemented by ic are added as well.
1128 true.........everything ok
1129 false........an exception has been thrown
1131 *******************************************************************************/
1133 static bool linker_addinterface(classinfo *c, classinfo *ic)
1137 vftbl_t *v = c->vftbl;
1139 if (i >= v->interfacetablelength) {
1140 log_text("Inernal error: interfacetable overflow");
1144 /* if this interface has already been added, return immediately */
1146 if (v->interfacetable[-i])
1149 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1150 v->interfacevftbllength[i] = 1;
1151 v->interfacetable[-i] = MNEW(methodptr, 1);
1152 v->interfacetable[-i][0] = NULL;
1156 v->interfacevftbllength[i] = ic->methodscount;
1157 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1159 #if defined(ENABLE_STATISTICS)
1161 count_vftbl_len += sizeof(methodptr) *
1162 (ic->methodscount + (ic->methodscount == 0));
1165 for (j = 0; j < ic->methodscount; j++) {
1169 for (m = 0; m < sc->methodscount; m++) {
1170 methodinfo *mi = &(sc->methods[m]);
1172 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1173 /* method mi overwrites the (abstract) interface method */
1174 #if defined(ENABLE_VERIFIER)
1175 if (!classcache_add_constraints_for_params(
1176 ic->classloader, c->classloader, mi))
1179 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1190 /* add superinterfaces of this interface */
1192 for (j = 0; j < ic->interfacescount; j++)
1193 if (!linker_addinterface(c, ic->interfaces[j].cls))
1201 /* class_highestinterface ******************************************************
1203 Used by the function link_class to determine the amount of memory
1204 needed for the interface table.
1206 *******************************************************************************/
1208 static s4 class_highestinterface(classinfo *c)
1214 /* check for ACC_INTERFACE bit already done in link_class_intern */
1218 for (i = 0; i < c->interfacescount; i++) {
1219 h2 = class_highestinterface(c->interfaces[i].cls);
1230 * These are local overrides for various environment variables in Emacs.
1231 * Please do not remove this and leave it at the end of the file, where
1232 * Emacs will automagically detect them.
1233 * ---------------------------------------------------------------------
1236 * indent-tabs-mode: t
1240 * vim:noexpandtab:sw=4:ts=4: