1 /* src/vm/linker.c - class linker functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
35 $Id: linker.c 4000 2005-12-22 14:05:01Z twisti $
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/jit/codegen.inc.h"
60 /* global variables ***********************************************************/
62 static s4 interfaceindex; /* sequential numbering of interfaces */
66 /* primitivetype_table *********************************************************
68 Structure for primitive classes: contains the class for wrapping
69 the primitive type, the primitive class, the name of the class for
70 wrapping, the one character type signature and the name of the
73 CAUTION: Don't change the order of the types. This table is indexed
74 by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
76 *******************************************************************************/
78 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
79 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
80 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
81 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
82 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
83 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
84 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
85 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
86 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
87 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
88 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
89 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
93 /* private functions **********************************************************/
95 static bool link_primitivetype_table(void);
96 static classinfo *link_class_intern(classinfo *c);
97 static arraydescriptor *link_array(classinfo *c);
98 static void linker_compute_class_values(classinfo *c);
99 static void linker_compute_subclasses(classinfo *c);
100 static void linker_addinterface(classinfo *c, classinfo *ic);
101 static s4 class_highestinterface(classinfo *c);
104 /* linker_init *****************************************************************
106 Initializes the linker subsystem.
108 *******************************************************************************/
110 bool linker_init(void)
112 /* reset interface index */
116 /* link java.lang.Class as first class of the system, because we
117 need it's vftbl for all other classes so we can use a class as
120 if (!link_class(class_java_lang_Class))
123 /* now set the header.vftbl of all classes which were created
124 before java.lang.Class was linked */
126 class_postset_header_vftbl();
129 /* link important system classes */
131 if (!link_class(class_java_lang_Object))
134 if (!link_class(class_java_lang_String))
137 if (!link_class(class_java_lang_Cloneable))
140 if (!link_class(class_java_io_Serializable))
144 /* link classes for wrapping primitive types */
146 if (!link_class(class_java_lang_Void))
149 if (!link_class(class_java_lang_Boolean))
152 if (!link_class(class_java_lang_Byte))
155 if (!link_class(class_java_lang_Character))
158 if (!link_class(class_java_lang_Short))
161 if (!link_class(class_java_lang_Integer))
164 if (!link_class(class_java_lang_Long))
167 if (!link_class(class_java_lang_Float))
170 if (!link_class(class_java_lang_Double))
174 /* load some other important classes */
176 if (!link_class(class_java_lang_ClassLoader))
179 if (!link_class(class_java_lang_SecurityManager))
182 if (!link_class(class_java_lang_System))
185 if (!link_class(class_java_lang_Thread))
188 if (!link_class(class_java_lang_ThreadGroup))
191 if (!link_class(class_java_lang_VMThread))
195 /* some classes which may be used more often */
197 if (!link_class(class_java_lang_StackTraceElement))
200 if (!link_class(class_java_lang_reflect_Constructor))
203 if (!link_class(class_java_lang_reflect_Field))
206 if (!link_class(class_java_lang_reflect_Method))
209 if (!link_class(class_java_security_PrivilegedAction))
212 if (!link_class(class_java_util_Vector))
215 if (!link_class(arrayclass_java_lang_Object))
219 /* create pseudo classes used by the typechecker */
221 /* pseudo class for Arraystubs (extends java.lang.Object) */
223 pseudo_class_Arraystub =
224 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
225 pseudo_class_Arraystub->state |= CLASS_LOADED;
226 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
227 pseudo_class_Arraystub->interfacescount = 2;
228 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
229 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
230 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
232 if (!classcache_store_unique(pseudo_class_Arraystub)) {
233 log_text("could not cache pseudo_class_Arraystub");
237 if (!link_class(pseudo_class_Arraystub))
240 /* pseudo class representing the null type */
242 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
243 pseudo_class_Null->state |= CLASS_LOADED;
244 pseudo_class_Null->super.cls = class_java_lang_Object;
246 if (!classcache_store_unique(pseudo_class_Null)) {
247 log_text("could not cache pseudo_class_Null");
251 if (!link_class(pseudo_class_Null))
254 /* pseudo class representing new uninitialized objects */
256 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
257 pseudo_class_New->state |= CLASS_LOADED;
258 pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
259 pseudo_class_New->super.cls = class_java_lang_Object;
261 if (!classcache_store_unique(pseudo_class_New)) {
262 log_text("could not cache pseudo_class_New");
266 /* create classes representing primitive types */
268 if (!link_primitivetype_table())
272 /* Correct vftbl-entries (retarded loading and linking of class */
273 /* java/lang/String). */
275 stringtable_update();
281 /* link_primitivetype_table ****************************************************
283 Create classes representing primitive types.
285 *******************************************************************************/
287 static bool link_primitivetype_table(void)
293 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
296 if (!primitivetype_table[i].name)
299 /* create primitive class */
301 c = class_create_classinfo(utf_new_char(primitivetype_table[i].name));
303 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
304 c->classUsed = NOTUSED; /* not used initially CO-RT */
307 /* prevent loader from loading primitive class */
309 c->state |= CLASS_LOADED;
311 /* INFO: don't put primitive classes into the classcache */
316 primitivetype_table[i].class_primitive = c;
318 /* create class for wrapping the primitive type */
320 u = utf_new_char(primitivetype_table[i].wrapname);
322 if (!(c = load_class_bootstrap(u)))
325 primitivetype_table[i].class_wrap = c;
326 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
327 primitivetype_table[i].class_wrap->impldBy = NULL;
329 /* create the primitive array class */
331 if (primitivetype_table[i].arrayname) {
332 u = utf_new_char(primitivetype_table[i].arrayname);
333 c = class_create_classinfo(u);
334 c = load_newly_created_array(c, NULL);
338 primitivetype_table[i].arrayclass = c;
340 assert(c->state & CLASS_LOADED);
342 if (!(c->state & CLASS_LINKED))
346 primitivetype_table[i].arrayvftbl = c->vftbl;
354 /* link_class ******************************************************************
356 Wrapper function for link_class_intern to ease monitor enter/exit
357 and exception handling.
359 *******************************************************************************/
361 classinfo *link_class(classinfo *c)
366 *exceptionptr = new_nullpointerexception();
370 #if defined(USE_THREADS)
371 /* enter a monitor on the class */
373 builtin_monitorenter((java_objectheader *) c);
376 /* maybe the class is already linked */
378 if (c->state & CLASS_LINKED) {
379 #if defined(USE_THREADS)
380 builtin_monitorexit((java_objectheader *) c);
386 #if defined(ENABLE_STATISTICS)
389 if (getcompilingtime)
390 compilingtime_stop();
396 /* call the internal function */
398 r = link_class_intern(c);
400 /* if return value is NULL, we had a problem and the class is not linked */
403 c->state &= ~CLASS_LINKING;
405 #if defined(ENABLE_STATISTICS)
411 if (getcompilingtime)
412 compilingtime_start();
415 #if defined(USE_THREADS)
416 /* leave the monitor */
418 builtin_monitorexit((java_objectheader *) c);
425 /* link_class_intern ***********************************************************
427 Tries to link a class. The function calculates the length in bytes
428 that an instance of this class requires as well as the VTBL for
429 methods and interface methods.
431 *******************************************************************************/
433 static classinfo *link_class_intern(classinfo *c)
435 classinfo *super; /* super class */
436 classinfo *tc; /* temporary class variable */
437 s4 supervftbllength; /* vftbllegnth of super class */
438 s4 vftbllength; /* vftbllength of current class */
439 s4 interfacetablelength; /* interface table length */
440 vftbl_t *v; /* vftbl of current class */
441 s4 i,j; /* interface/method/field counter */
442 arraydescriptor *arraydesc; /* descriptor for array classes */
444 /* the class is already linked */
446 if (c->state & CLASS_LINKED)
450 log_message_class("Linking class: ", c);
452 /* the class must be loaded */
454 /* XXX should this be a specific exception? */
455 assert(c->state & CLASS_LOADED);
457 /* cache the self-reference of this class */
458 /* we do this for cases where the defining loader of the class */
459 /* has not yet been recorded as an initiating loader for the class */
460 /* this is needed so subsequent code can assume that self-refs */
461 /* will always resolve lazily */
462 /* No need to do it for the bootloader - it is always registered */
463 /* as initiating loader for the classes it loads. */
465 classcache_store(c->classloader,c,false);
467 /* this class is currently linking */
469 c->state |= CLASS_LINKING;
473 /* check interfaces */
475 for (i = 0; i < c->interfacescount; i++) {
476 /* resolve this super interface */
478 if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager,
482 c->interfaces[i].cls = tc;
484 /* detect circularity */
488 new_exception_utfmessage(string_java_lang_ClassCircularityError,
493 assert(tc->state & CLASS_LOADED);
495 if (!(tc->flags & ACC_INTERFACE)) {
497 new_exception_message(string_java_lang_IncompatibleClassChangeError,
498 "Implementing class");
502 if (!(tc->state & CLASS_LINKED))
507 /* check super class */
511 if (c->super.any == NULL) { /* class java.lang.Object */
513 c->classUsed = USED; /* Object class is always used CO-RT*/
515 c->instancesize = sizeof(java_objectheader);
517 vftbllength = supervftbllength = 0;
522 /* resolve super class */
524 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
527 c->super.cls = super;
529 /* detect circularity */
533 new_exception_utfmessage(string_java_lang_ClassCircularityError,
538 assert(super->state & CLASS_LOADED);
540 if (super->flags & ACC_INTERFACE) {
541 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
542 log_text("Interface specified as super class");
546 /* Don't allow extending final classes */
548 if (super->flags & ACC_FINAL) {
550 new_exception_message(string_java_lang_VerifyError,
551 "Cannot inherit from final class");
555 if (!(super->state & CLASS_LINKED))
556 if (!link_class(super))
559 /* handle array classes */
561 if (c->name->text[0] == '[')
562 if (!(arraydesc = link_array(c)))
565 if (c->flags & ACC_INTERFACE)
566 c->index = interfaceindex++;
568 c->index = super->index + 1;
570 c->instancesize = super->instancesize;
572 vftbllength = supervftbllength = super->vftbl->vftbllength;
574 c->finalizer = super->finalizer;
578 /* compute vftbl length */
580 for (i = 0; i < c->methodscount; i++) {
581 methodinfo *m = &(c->methods[i]);
583 if (!(m->flags & ACC_STATIC)) { /* is instance method */
589 for (j = 0; j < tc->methodscount; j++) {
590 if (method_canoverwrite(m, &(tc->methods[j]))) {
591 if (tc->methods[j].flags & ACC_PRIVATE)
592 goto notfoundvftblindex;
594 if (tc->methods[j].flags & ACC_FINAL) {
595 /* class a overrides final method . */
597 new_exception(string_java_lang_VerifyError);
601 m->vftblindex = tc->methods[j].vftblindex;
602 goto foundvftblindex;
610 m->vftblindex = (vftbllength++);
617 /* check interfaces of ABSTRACT class for unimplemented methods */
619 if (c->flags & ACC_ABSTRACT) {
622 s4 abstractmethodscount;
626 abstractmethodscount = 0;
628 for (i = 0; i < c->interfacescount; i++) {
629 ic = c->interfaces[i].cls;
631 for (j = 0; j < ic->methodscount; j++) {
632 im = &(ic->methods[j]);
634 /* skip `<clinit>' and `<init>' */
636 if (im->name == utf_clinit || im->name == utf_init)
642 for (k = 0; k < tc->methodscount; k++) {
643 if (method_canoverwrite(im, &(tc->methods[k])))
644 goto noabstractmethod;
650 abstractmethodscount++;
657 if (abstractmethodscount > 0) {
660 /* reallocate methods memory */
662 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
663 c->methodscount + abstractmethodscount);
665 for (i = 0; i < c->interfacescount; i++) {
666 ic = c->interfaces[i].cls;
668 for (j = 0; j < ic->methodscount; j++) {
669 im = &(ic->methods[j]);
671 /* skip `<clinit>' and `<init>' */
673 if (im->name == utf_clinit || im->name == utf_init)
679 for (k = 0; k < tc->methodscount; k++) {
680 if (method_canoverwrite(im, &(tc->methods[k])))
681 goto noabstractmethod2;
687 am = &(c->methods[c->methodscount]);
690 MCOPY(am, im, methodinfo, 1);
692 am->vftblindex = (vftbllength++);
703 #if defined(ENABLE_STATISTICS)
706 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
709 /* compute interfacetable length */
711 interfacetablelength = 0;
714 for (i = 0; i < tc->interfacescount; i++) {
715 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
716 if (h > interfacetablelength)
717 interfacetablelength = h;
722 /* allocate virtual function table */
724 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
725 sizeof(methodptr) * (vftbllength - 1) +
726 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
727 v = (vftbl_t *) (((methodptr *) v) +
728 (interfacetablelength - 1) * (interfacetablelength > 1));
731 v->vftbllength = vftbllength;
732 v->interfacetablelength = interfacetablelength;
733 v->arraydesc = arraydesc;
735 /* store interface index in vftbl */
737 if (c->flags & ACC_INTERFACE)
738 v->baseval = -(c->index);
740 /* copy virtual function table of super class */
742 for (i = 0; i < supervftbllength; i++)
743 v->table[i] = super->vftbl->table[i];
745 /* add method stubs into virtual function table */
747 for (i = 0; i < c->methodscount; i++) {
748 methodinfo *m = &(c->methods[i]);
750 /* Methods in ABSTRACT classes from interfaces maybe already have a */
754 m->stubroutine = createcompilerstub(m);
756 if (!(m->flags & ACC_STATIC))
757 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
760 /* compute instance size and offset of each field */
762 for (i = 0; i < c->fieldscount; i++) {
764 fieldinfo *f = &(c->fields[i]);
766 if (!(f->flags & ACC_STATIC)) {
767 dsize = descriptor_typesize(f->parseddesc);
768 c->instancesize = ALIGN(c->instancesize, dsize);
769 f->offset = c->instancesize;
770 c->instancesize += dsize;
774 /* initialize interfacetable and interfacevftbllength */
776 v->interfacevftbllength = MNEW(s4, interfacetablelength);
778 #if defined(ENABLE_STATISTICS)
780 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
783 for (i = 0; i < interfacetablelength; i++) {
784 v->interfacevftbllength[i] = 0;
785 v->interfacetable[-i] = NULL;
790 for (tc = c; tc != NULL; tc = tc->super.cls)
791 for (i = 0; i < tc->interfacescount; i++)
792 linker_addinterface(c, tc->interfaces[i].cls);
794 /* add finalizer method (not for java.lang.Object) */
799 fi = class_findmethod(c, utf_finalize, utf_void__void);
802 if (!(fi->flags & ACC_STATIC))
806 /* resolve exception class references */
808 for (i = 0; i < c->methodscount; i++) {
809 methodinfo *m = &(c->methods[i]);
811 for (j = 0; j < m->exceptiontablelength; j++) {
812 if (!m->exceptiontable[j].catchtype.any)
814 if (!resolve_classref_or_classinfo(NULL,
815 m->exceptiontable[j].catchtype,
816 resolveEager, true, false,
817 &(m->exceptiontable[j].catchtype.cls)))
824 linker_compute_subclasses(c);
826 /* revert the linking state and class is linked */
828 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
831 log_message_class("Linking done class: ", c);
833 /* just return c to show that we didn't had a problem */
839 /* link_array ******************************************************************
841 This function is called by link_class to create the arraydescriptor
844 This function returns NULL if the array cannot be linked because
845 the component type has not been linked yet.
847 *******************************************************************************/
849 static arraydescriptor *link_array(classinfo *c)
853 arraydescriptor *desc;
858 namelen = c->name->blength;
860 /* Check the component type */
862 switch (c->name->text[1]) {
864 /* c is an array of arrays. */
865 u = utf_new(c->name->text + 1, namelen - 1);
866 if (!(comp = load_class_from_classloader(u, c->classloader)))
871 /* c is an array of objects. */
872 u = utf_new(c->name->text + 2, namelen - 3);
873 if (!(comp = load_class_from_classloader(u, c->classloader)))
878 /* If the component type has not been linked, link it now */
880 assert(!comp || (comp->state & CLASS_LOADED));
882 if (comp && !(comp->state & CLASS_LINKED))
883 if (!link_class(comp))
886 /* Allocate the arraydescriptor */
888 desc = NEW(arraydescriptor);
891 /* c is an array of references */
892 desc->arraytype = ARRAYTYPE_OBJECT;
893 desc->componentsize = sizeof(void*);
894 desc->dataoffset = OFFSET(java_objectarray, data);
896 compvftbl = comp->vftbl;
899 log_text("Component class has no vftbl");
903 desc->componentvftbl = compvftbl;
905 if (compvftbl->arraydesc) {
906 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
908 if (compvftbl->arraydesc->dimension >= 255) {
909 log_text("Creating array of dimension >255");
913 desc->dimension = compvftbl->arraydesc->dimension + 1;
914 desc->elementtype = compvftbl->arraydesc->elementtype;
917 desc->elementvftbl = compvftbl;
919 desc->elementtype = ARRAYTYPE_OBJECT;
923 /* c is an array of a primitive type */
924 switch (c->name->text[1]) {
926 desc->arraytype = ARRAYTYPE_BOOLEAN;
927 desc->dataoffset = OFFSET(java_booleanarray,data);
928 desc->componentsize = sizeof(u1);
932 desc->arraytype = ARRAYTYPE_BYTE;
933 desc->dataoffset = OFFSET(java_bytearray,data);
934 desc->componentsize = sizeof(u1);
938 desc->arraytype = ARRAYTYPE_CHAR;
939 desc->dataoffset = OFFSET(java_chararray,data);
940 desc->componentsize = sizeof(u2);
944 desc->arraytype = ARRAYTYPE_DOUBLE;
945 desc->dataoffset = OFFSET(java_doublearray,data);
946 desc->componentsize = sizeof(double);
950 desc->arraytype = ARRAYTYPE_FLOAT;
951 desc->dataoffset = OFFSET(java_floatarray,data);
952 desc->componentsize = sizeof(float);
956 desc->arraytype = ARRAYTYPE_INT;
957 desc->dataoffset = OFFSET(java_intarray,data);
958 desc->componentsize = sizeof(s4);
962 desc->arraytype = ARRAYTYPE_LONG;
963 desc->dataoffset = OFFSET(java_longarray,data);
964 desc->componentsize = sizeof(s8);
968 desc->arraytype = ARRAYTYPE_SHORT;
969 desc->dataoffset = OFFSET(java_shortarray,data);
970 desc->componentsize = sizeof(s2);
974 *exceptionptr = new_noclassdeffounderror(c->name);
978 desc->componentvftbl = NULL;
979 desc->elementvftbl = NULL;
981 desc->elementtype = desc->arraytype;
988 /* linker_compute_subclasses ***************************************************
992 *******************************************************************************/
994 static void linker_compute_subclasses(classinfo *c)
996 #if defined(USE_THREADS)
997 #if defined(NATIVE_THREADS)
1004 if (!(c->flags & ACC_INTERFACE)) {
1009 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1010 c->nextsub = c->super.cls->sub;
1011 c->super.cls->sub = c;
1016 /* compute class values */
1018 linker_compute_class_values(class_java_lang_Object);
1020 #if defined(USE_THREADS)
1021 #if defined(NATIVE_THREADS)
1030 /* linker_compute_class_values *************************************************
1034 *******************************************************************************/
1036 static void linker_compute_class_values(classinfo *c)
1040 c->vftbl->baseval = ++classvalue;
1045 linker_compute_class_values(subs);
1047 subs = subs->nextsub;
1050 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1054 /* linker_addinterface *********************************************************
1056 Is needed by link_class for adding a VTBL to a class. All
1057 interfaces implemented by ic are added as well.
1059 *******************************************************************************/
1061 static void linker_addinterface(classinfo *c, classinfo *ic)
1065 vftbl_t *v = c->vftbl;
1067 if (i >= v->interfacetablelength) {
1068 log_text("Inernal error: interfacetable overflow");
1072 if (v->interfacetable[-i])
1075 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1076 v->interfacevftbllength[i] = 1;
1077 v->interfacetable[-i] = MNEW(methodptr, 1);
1078 v->interfacetable[-i][0] = NULL;
1081 v->interfacevftbllength[i] = ic->methodscount;
1082 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1084 #if defined(ENABLE_STATISTICS)
1086 count_vftbl_len += sizeof(methodptr) *
1087 (ic->methodscount + (ic->methodscount == 0));
1090 for (j = 0; j < ic->methodscount; j++) {
1094 for (m = 0; m < sc->methodscount; m++) {
1095 methodinfo *mi = &(sc->methods[m]);
1097 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1098 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1109 for (j = 0; j < ic->interfacescount; j++)
1110 linker_addinterface(c, ic->interfaces[j].cls);
1114 /* class_highestinterface ******************************************************
1116 Used by the function link_class to determine the amount of memory
1117 needed for the interface table.
1119 *******************************************************************************/
1121 static s4 class_highestinterface(classinfo *c)
1127 /* check for ACC_INTERFACE bit already done in link_class_intern */
1131 for (i = 0; i < c->interfacescount; i++) {
1132 h2 = class_highestinterface(c->interfaces[i].cls);
1143 * These are local overrides for various environment variables in Emacs.
1144 * Please do not remove this and leave it at the end of the file, where
1145 * Emacs will automagically detect them.
1146 * ---------------------------------------------------------------------
1149 * indent-tabs-mode: t