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 4126 2006-01-10 20:55:41Z 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"
59 /* global variables ***********************************************************/
61 static s4 interfaceindex; /* sequential numbering of interfaces */
65 /* primitivetype_table *********************************************************
67 Structure for primitive classes: contains the class for wrapping
68 the primitive type, the primitive class, the name of the class for
69 wrapping, the one character type signature and the name of the
72 CAUTION: Don't change the order of the types. This table is indexed
73 by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
75 *******************************************************************************/
77 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
78 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
79 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
80 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
81 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
82 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
83 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
84 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
85 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
86 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
87 { NULL, NULL, NULL, 0 , NULL , NULL, NULL, NULL },
88 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
92 /* private functions **********************************************************/
94 static bool link_primitivetype_table(void);
95 static classinfo *link_class_intern(classinfo *c);
96 static arraydescriptor *link_array(classinfo *c);
97 static void linker_compute_class_values(classinfo *c);
98 static void linker_compute_subclasses(classinfo *c);
99 static void linker_addinterface(classinfo *c, classinfo *ic);
100 static s4 class_highestinterface(classinfo *c);
103 /* linker_init *****************************************************************
105 Initializes the linker subsystem.
107 *******************************************************************************/
109 bool linker_init(void)
111 /* reset interface index */
115 /* link java.lang.Class as first class of the system, because we
116 need it's vftbl for all other classes so we can use a class as
119 if (!link_class(class_java_lang_Class))
122 /* now set the header.vftbl of all classes which were created
123 before java.lang.Class was linked */
125 class_postset_header_vftbl();
128 /* link important system classes */
130 if (!link_class(class_java_lang_Object))
133 if (!link_class(class_java_lang_String))
136 if (!link_class(class_java_lang_Cloneable))
139 if (!link_class(class_java_io_Serializable))
143 /* link classes for wrapping primitive types */
145 if (!link_class(class_java_lang_Void))
148 if (!link_class(class_java_lang_Boolean))
151 if (!link_class(class_java_lang_Byte))
154 if (!link_class(class_java_lang_Character))
157 if (!link_class(class_java_lang_Short))
160 if (!link_class(class_java_lang_Integer))
163 if (!link_class(class_java_lang_Long))
166 if (!link_class(class_java_lang_Float))
169 if (!link_class(class_java_lang_Double))
173 /* load some other important classes */
175 if (!link_class(class_java_lang_ClassLoader))
178 if (!link_class(class_java_lang_SecurityManager))
181 if (!link_class(class_java_lang_System))
184 if (!link_class(class_java_lang_Thread))
187 if (!link_class(class_java_lang_ThreadGroup))
190 if (!link_class(class_java_lang_VMThread))
194 /* some classes which may be used more often */
196 if (!link_class(class_java_lang_StackTraceElement))
199 if (!link_class(class_java_lang_reflect_Constructor))
202 if (!link_class(class_java_lang_reflect_Field))
205 if (!link_class(class_java_lang_reflect_Method))
208 if (!link_class(class_java_security_PrivilegedAction))
211 if (!link_class(class_java_util_Vector))
214 if (!link_class(arrayclass_java_lang_Object))
218 /* create pseudo classes used by the typechecker */
220 /* pseudo class for Arraystubs (extends java.lang.Object) */
222 pseudo_class_Arraystub =
223 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
224 pseudo_class_Arraystub->state |= CLASS_LOADED;
225 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
226 pseudo_class_Arraystub->interfacescount = 2;
227 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
228 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
229 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
231 if (!classcache_store_unique(pseudo_class_Arraystub)) {
232 log_text("could not cache pseudo_class_Arraystub");
236 if (!link_class(pseudo_class_Arraystub))
239 /* pseudo class representing the null type */
241 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
242 pseudo_class_Null->state |= CLASS_LOADED;
243 pseudo_class_Null->super.cls = class_java_lang_Object;
245 if (!classcache_store_unique(pseudo_class_Null)) {
246 log_text("could not cache pseudo_class_Null");
250 if (!link_class(pseudo_class_Null))
253 /* pseudo class representing new uninitialized objects */
255 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
256 pseudo_class_New->state |= CLASS_LOADED;
257 pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
258 pseudo_class_New->super.cls = class_java_lang_Object;
260 if (!classcache_store_unique(pseudo_class_New)) {
261 log_text("could not cache pseudo_class_New");
265 /* create classes representing primitive types */
267 if (!link_primitivetype_table())
271 /* Correct vftbl-entries (retarded loading and linking of class */
272 /* java/lang/String). */
274 stringtable_update();
280 /* link_primitivetype_table ****************************************************
282 Create classes representing primitive types.
284 *******************************************************************************/
286 static bool link_primitivetype_table(void)
292 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
295 if (!primitivetype_table[i].name)
298 /* create primitive class */
300 c = class_create_classinfo(utf_new_char(primitivetype_table[i].name));
302 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
303 c->classUsed = NOTUSED; /* not used initially CO-RT */
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;
325 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
326 primitivetype_table[i].class_wrap->impldBy = NULL;
328 /* create the primitive array class */
330 if (primitivetype_table[i].arrayname) {
331 u = utf_new_char(primitivetype_table[i].arrayname);
332 c = class_create_classinfo(u);
333 c = load_newly_created_array(c, NULL);
337 primitivetype_table[i].arrayclass = c;
339 assert(c->state & CLASS_LOADED);
341 if (!(c->state & CLASS_LINKED))
345 primitivetype_table[i].arrayvftbl = c->vftbl;
353 /* link_class ******************************************************************
355 Wrapper function for link_class_intern to ease monitor enter/exit
356 and exception handling.
358 *******************************************************************************/
360 classinfo *link_class(classinfo *c)
365 exceptions_throw_nullpointerexception();
369 #if defined(USE_THREADS)
370 /* enter a monitor on the class */
372 builtin_monitorenter((java_objectheader *) c);
375 /* maybe the class is already linked */
377 if (c->state & CLASS_LINKED) {
378 #if defined(USE_THREADS)
379 builtin_monitorexit((java_objectheader *) c);
385 #if defined(ENABLE_STATISTICS)
388 if (getcompilingtime)
389 compilingtime_stop();
395 /* call the internal function */
397 r = link_class_intern(c);
399 /* if return value is NULL, we had a problem and the class is not linked */
402 c->state &= ~CLASS_LINKING;
404 #if defined(ENABLE_STATISTICS)
410 if (getcompilingtime)
411 compilingtime_start();
414 #if defined(USE_THREADS)
415 /* leave the monitor */
417 builtin_monitorexit((java_objectheader *) c);
424 /* link_class_intern ***********************************************************
426 Tries to link a class. The function calculates the length in bytes
427 that an instance of this class requires as well as the VTBL for
428 methods and interface methods.
430 *******************************************************************************/
432 static classinfo *link_class_intern(classinfo *c)
434 classinfo *super; /* super class */
435 classinfo *tc; /* temporary class variable */
436 s4 supervftbllength; /* vftbllegnth of super class */
437 s4 vftbllength; /* vftbllength of current class */
438 s4 interfacetablelength; /* interface table length */
439 vftbl_t *v; /* vftbl of current class */
440 s4 i,j; /* interface/method/field counter */
441 arraydescriptor *arraydesc; /* descriptor for array classes */
443 /* the class is already linked */
445 if (c->state & CLASS_LINKED)
449 log_message_class("Linking class: ", c);
451 /* the class must be loaded */
453 /* XXX should this be a specific exception? */
454 assert(c->state & CLASS_LOADED);
456 /* cache the self-reference of this class */
457 /* we do this for cases where the defining loader of the class */
458 /* has not yet been recorded as an initiating loader for the class */
459 /* this is needed so subsequent code can assume that self-refs */
460 /* will always resolve lazily */
461 /* No need to do it for the bootloader - it is always registered */
462 /* as initiating loader for the classes it loads. */
464 classcache_store(c->classloader,c,false);
466 /* this class is currently linking */
468 c->state |= CLASS_LINKING;
472 /* check interfaces */
474 for (i = 0; i < c->interfacescount; i++) {
475 /* resolve this super interface */
477 if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager,
481 c->interfaces[i].cls = tc;
483 /* detect circularity */
487 new_exception_utfmessage(string_java_lang_ClassCircularityError,
492 assert(tc->state & CLASS_LOADED);
494 if (!(tc->flags & ACC_INTERFACE)) {
496 new_exception_message(string_java_lang_IncompatibleClassChangeError,
497 "Implementing class");
501 if (!(tc->state & CLASS_LINKED))
506 /* check super class */
510 if (c->super.any == NULL) { /* class java.lang.Object */
512 c->classUsed = USED; /* Object class is always used CO-RT*/
514 c->instancesize = sizeof(java_objectheader);
516 vftbllength = supervftbllength = 0;
521 /* resolve super class */
523 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
526 c->super.cls = super;
528 /* detect circularity */
532 new_exception_utfmessage(string_java_lang_ClassCircularityError,
537 assert(super->state & CLASS_LOADED);
539 if (super->flags & ACC_INTERFACE) {
540 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
541 log_text("Interface specified as super class");
545 /* Don't allow extending final classes */
547 if (super->flags & ACC_FINAL) {
549 new_exception_message(string_java_lang_VerifyError,
550 "Cannot inherit from final class");
554 if (!(super->state & CLASS_LINKED))
555 if (!link_class(super))
558 /* handle array classes */
560 if (c->name->text[0] == '[')
561 if (!(arraydesc = link_array(c)))
564 if (c->flags & ACC_INTERFACE)
565 c->index = interfaceindex++;
567 c->index = super->index + 1;
569 c->instancesize = super->instancesize;
571 vftbllength = supervftbllength = super->vftbl->vftbllength;
573 c->finalizer = super->finalizer;
577 /* compute vftbl length */
579 for (i = 0; i < c->methodscount; i++) {
580 methodinfo *m = &(c->methods[i]);
582 if (!(m->flags & ACC_STATIC)) { /* is instance method */
588 for (j = 0; j < tc->methodscount; j++) {
589 if (method_canoverwrite(m, &(tc->methods[j]))) {
590 if (tc->methods[j].flags & ACC_PRIVATE)
591 goto notfoundvftblindex;
593 if (tc->methods[j].flags & ACC_FINAL) {
594 /* class a overrides final method . */
596 new_exception(string_java_lang_VerifyError);
600 m->vftblindex = tc->methods[j].vftblindex;
601 goto foundvftblindex;
609 m->vftblindex = (vftbllength++);
616 /* check interfaces of ABSTRACT class for unimplemented methods */
618 if (c->flags & ACC_ABSTRACT) {
621 s4 abstractmethodscount;
625 abstractmethodscount = 0;
627 for (i = 0; i < c->interfacescount; i++) {
628 ic = c->interfaces[i].cls;
630 for (j = 0; j < ic->methodscount; j++) {
631 im = &(ic->methods[j]);
633 /* skip `<clinit>' and `<init>' */
635 if (im->name == utf_clinit || im->name == utf_init)
641 for (k = 0; k < tc->methodscount; k++) {
642 if (method_canoverwrite(im, &(tc->methods[k])))
643 goto noabstractmethod;
649 abstractmethodscount++;
656 if (abstractmethodscount > 0) {
659 /* reallocate methods memory */
661 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
662 c->methodscount + abstractmethodscount);
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)
678 for (k = 0; k < tc->methodscount; k++) {
679 if (method_canoverwrite(im, &(tc->methods[k])))
680 goto noabstractmethod2;
686 am = &(c->methods[c->methodscount]);
689 MCOPY(am, im, methodinfo, 1);
691 am->vftblindex = (vftbllength++);
702 #if defined(ENABLE_STATISTICS)
705 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
708 /* compute interfacetable length */
710 interfacetablelength = 0;
713 for (i = 0; i < tc->interfacescount; i++) {
714 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
715 if (h > interfacetablelength)
716 interfacetablelength = h;
721 /* allocate virtual function table */
723 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
724 sizeof(methodptr) * (vftbllength - 1) +
725 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
726 v = (vftbl_t *) (((methodptr *) v) +
727 (interfacetablelength - 1) * (interfacetablelength > 1));
730 v->vftbllength = vftbllength;
731 v->interfacetablelength = interfacetablelength;
732 v->arraydesc = arraydesc;
734 /* store interface index in vftbl */
736 if (c->flags & ACC_INTERFACE)
737 v->baseval = -(c->index);
739 /* copy virtual function table of super class */
741 for (i = 0; i < supervftbllength; i++)
742 v->table[i] = super->vftbl->table[i];
744 /* add method stubs into virtual function table */
746 for (i = 0; i < c->methodscount; i++) {
747 methodinfo *m = &(c->methods[i]);
749 /* Methods in ABSTRACT classes from interfaces maybe already have a */
753 m->stubroutine = createcompilerstub(m);
755 if (!(m->flags & ACC_STATIC))
756 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
759 /* compute instance size and offset of each field */
761 for (i = 0; i < c->fieldscount; i++) {
763 fieldinfo *f = &(c->fields[i]);
765 if (!(f->flags & ACC_STATIC)) {
766 dsize = descriptor_typesize(f->parseddesc);
767 c->instancesize = ALIGN(c->instancesize, dsize);
768 f->offset = c->instancesize;
769 c->instancesize += dsize;
773 /* initialize interfacetable and interfacevftbllength */
775 v->interfacevftbllength = MNEW(s4, interfacetablelength);
777 #if defined(ENABLE_STATISTICS)
779 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
782 for (i = 0; i < interfacetablelength; i++) {
783 v->interfacevftbllength[i] = 0;
784 v->interfacetable[-i] = NULL;
789 for (tc = c; tc != NULL; tc = tc->super.cls)
790 for (i = 0; i < tc->interfacescount; i++)
791 linker_addinterface(c, tc->interfaces[i].cls);
793 /* add finalizer method (not for java.lang.Object) */
798 fi = class_findmethod(c, utf_finalize, utf_void__void);
801 if (!(fi->flags & ACC_STATIC))
805 /* resolve exception class references */
807 for (i = 0; i < c->methodscount; i++) {
808 methodinfo *m = &(c->methods[i]);
810 for (j = 0; j < m->exceptiontablelength; j++) {
811 if (!m->exceptiontable[j].catchtype.any)
813 if (!resolve_classref_or_classinfo(NULL,
814 m->exceptiontable[j].catchtype,
815 resolveEager, true, false,
816 &(m->exceptiontable[j].catchtype.cls)))
823 linker_compute_subclasses(c);
825 /* revert the linking state and class is linked */
827 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
830 log_message_class("Linking done class: ", c);
832 /* just return c to show that we didn't had a problem */
838 /* link_array ******************************************************************
840 This function is called by link_class to create the arraydescriptor
843 This function returns NULL if the array cannot be linked because
844 the component type has not been linked yet.
846 *******************************************************************************/
848 static arraydescriptor *link_array(classinfo *c)
852 arraydescriptor *desc;
857 namelen = c->name->blength;
859 /* Check the component type */
861 switch (c->name->text[1]) {
863 /* c is an array of arrays. */
864 u = utf_new(c->name->text + 1, namelen - 1);
865 if (!(comp = load_class_from_classloader(u, c->classloader)))
870 /* c is an array of objects. */
871 u = utf_new(c->name->text + 2, namelen - 3);
872 if (!(comp = load_class_from_classloader(u, c->classloader)))
877 /* If the component type has not been linked, link it now */
879 assert(!comp || (comp->state & CLASS_LOADED));
881 if (comp && !(comp->state & CLASS_LINKED))
882 if (!link_class(comp))
885 /* Allocate the arraydescriptor */
887 desc = NEW(arraydescriptor);
890 /* c is an array of references */
891 desc->arraytype = ARRAYTYPE_OBJECT;
892 desc->componentsize = sizeof(void*);
893 desc->dataoffset = OFFSET(java_objectarray, data);
895 compvftbl = comp->vftbl;
898 log_text("Component class has no vftbl");
902 desc->componentvftbl = compvftbl;
904 if (compvftbl->arraydesc) {
905 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
907 if (compvftbl->arraydesc->dimension >= 255) {
908 log_text("Creating array of dimension >255");
912 desc->dimension = compvftbl->arraydesc->dimension + 1;
913 desc->elementtype = compvftbl->arraydesc->elementtype;
916 desc->elementvftbl = compvftbl;
918 desc->elementtype = ARRAYTYPE_OBJECT;
922 /* c is an array of a primitive type */
923 switch (c->name->text[1]) {
925 desc->arraytype = ARRAYTYPE_BOOLEAN;
926 desc->dataoffset = OFFSET(java_booleanarray,data);
927 desc->componentsize = sizeof(u1);
931 desc->arraytype = ARRAYTYPE_BYTE;
932 desc->dataoffset = OFFSET(java_bytearray,data);
933 desc->componentsize = sizeof(u1);
937 desc->arraytype = ARRAYTYPE_CHAR;
938 desc->dataoffset = OFFSET(java_chararray,data);
939 desc->componentsize = sizeof(u2);
943 desc->arraytype = ARRAYTYPE_DOUBLE;
944 desc->dataoffset = OFFSET(java_doublearray,data);
945 desc->componentsize = sizeof(double);
949 desc->arraytype = ARRAYTYPE_FLOAT;
950 desc->dataoffset = OFFSET(java_floatarray,data);
951 desc->componentsize = sizeof(float);
955 desc->arraytype = ARRAYTYPE_INT;
956 desc->dataoffset = OFFSET(java_intarray,data);
957 desc->componentsize = sizeof(s4);
961 desc->arraytype = ARRAYTYPE_LONG;
962 desc->dataoffset = OFFSET(java_longarray,data);
963 desc->componentsize = sizeof(s8);
967 desc->arraytype = ARRAYTYPE_SHORT;
968 desc->dataoffset = OFFSET(java_shortarray,data);
969 desc->componentsize = sizeof(s2);
973 *exceptionptr = new_noclassdeffounderror(c->name);
977 desc->componentvftbl = NULL;
978 desc->elementvftbl = NULL;
980 desc->elementtype = desc->arraytype;
987 /* linker_compute_subclasses ***************************************************
991 *******************************************************************************/
993 static void linker_compute_subclasses(classinfo *c)
995 #if defined(USE_THREADS)
996 #if defined(NATIVE_THREADS)
1003 if (!(c->flags & ACC_INTERFACE)) {
1008 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1009 c->nextsub = c->super.cls->sub;
1010 c->super.cls->sub = c;
1015 /* compute class values */
1017 linker_compute_class_values(class_java_lang_Object);
1019 #if defined(USE_THREADS)
1020 #if defined(NATIVE_THREADS)
1029 /* linker_compute_class_values *************************************************
1033 *******************************************************************************/
1035 static void linker_compute_class_values(classinfo *c)
1039 c->vftbl->baseval = ++classvalue;
1044 linker_compute_class_values(subs);
1046 subs = subs->nextsub;
1049 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1053 /* linker_addinterface *********************************************************
1055 Is needed by link_class for adding a VTBL to a class. All
1056 interfaces implemented by ic are added as well.
1058 *******************************************************************************/
1060 static void linker_addinterface(classinfo *c, classinfo *ic)
1064 vftbl_t *v = c->vftbl;
1066 if (i >= v->interfacetablelength) {
1067 log_text("Inernal error: interfacetable overflow");
1071 if (v->interfacetable[-i])
1074 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1075 v->interfacevftbllength[i] = 1;
1076 v->interfacetable[-i] = MNEW(methodptr, 1);
1077 v->interfacetable[-i][0] = NULL;
1080 v->interfacevftbllength[i] = ic->methodscount;
1081 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1083 #if defined(ENABLE_STATISTICS)
1085 count_vftbl_len += sizeof(methodptr) *
1086 (ic->methodscount + (ic->methodscount == 0));
1089 for (j = 0; j < ic->methodscount; j++) {
1093 for (m = 0; m < sc->methodscount; m++) {
1094 methodinfo *mi = &(sc->methods[m]);
1096 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1097 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1108 for (j = 0; j < ic->interfacescount; j++)
1109 linker_addinterface(c, ic->interfaces[j].cls);
1113 /* class_highestinterface ******************************************************
1115 Used by the function link_class to determine the amount of memory
1116 needed for the interface table.
1118 *******************************************************************************/
1120 static s4 class_highestinterface(classinfo *c)
1126 /* check for ACC_INTERFACE bit already done in link_class_intern */
1130 for (i = 0; i < c->interfacescount; i++) {
1131 h2 = class_highestinterface(c->interfaces[i].cls);
1142 * These are local overrides for various environment variables in Emacs.
1143 * Please do not remove this and leave it at the end of the file, where
1144 * Emacs will automagically detect them.
1145 * ---------------------------------------------------------------------
1148 * indent-tabs-mode: t