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 4357 2006-01-22 23:33:38Z 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 */
752 if (!m->stubroutine) {
753 #if defined(ENABLE_JIT)
754 # if defined(ENABLE_INTRP)
756 m->stubroutine = intrp_createcompilerstub(m);
759 m->stubroutine = createcompilerstub(m);
761 m->stubroutine = intrp_createcompilerstub(m);
765 if (!(m->flags & ACC_STATIC))
766 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
769 /* compute instance size and offset of each field */
771 for (i = 0; i < c->fieldscount; i++) {
773 fieldinfo *f = &(c->fields[i]);
775 if (!(f->flags & ACC_STATIC)) {
776 dsize = descriptor_typesize(f->parseddesc);
777 c->instancesize = ALIGN(c->instancesize, dsize);
778 f->offset = c->instancesize;
779 c->instancesize += dsize;
783 /* initialize interfacetable and interfacevftbllength */
785 v->interfacevftbllength = MNEW(s4, interfacetablelength);
787 #if defined(ENABLE_STATISTICS)
789 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
792 for (i = 0; i < interfacetablelength; i++) {
793 v->interfacevftbllength[i] = 0;
794 v->interfacetable[-i] = NULL;
799 for (tc = c; tc != NULL; tc = tc->super.cls)
800 for (i = 0; i < tc->interfacescount; i++)
801 linker_addinterface(c, tc->interfaces[i].cls);
803 /* add finalizer method (not for java.lang.Object) */
808 fi = class_findmethod(c, utf_finalize, utf_void__void);
811 if (!(fi->flags & ACC_STATIC))
815 /* resolve exception class references */
817 for (i = 0; i < c->methodscount; i++) {
818 methodinfo *m = &(c->methods[i]);
820 for (j = 0; j < m->exceptiontablelength; j++) {
821 if (!m->exceptiontable[j].catchtype.any)
823 if (!resolve_classref_or_classinfo(NULL,
824 m->exceptiontable[j].catchtype,
825 resolveEager, true, false,
826 &(m->exceptiontable[j].catchtype.cls)))
833 linker_compute_subclasses(c);
835 /* revert the linking state and class is linked */
837 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
840 log_message_class("Linking done class: ", c);
842 /* just return c to show that we didn't had a problem */
848 /* link_array ******************************************************************
850 This function is called by link_class to create the arraydescriptor
853 This function returns NULL if the array cannot be linked because
854 the component type has not been linked yet.
856 *******************************************************************************/
858 static arraydescriptor *link_array(classinfo *c)
862 arraydescriptor *desc;
867 namelen = c->name->blength;
869 /* Check the component type */
871 switch (c->name->text[1]) {
873 /* c is an array of arrays. */
874 u = utf_new(c->name->text + 1, namelen - 1);
875 if (!(comp = load_class_from_classloader(u, c->classloader)))
880 /* c is an array of objects. */
881 u = utf_new(c->name->text + 2, namelen - 3);
882 if (!(comp = load_class_from_classloader(u, c->classloader)))
887 /* If the component type has not been linked, link it now */
889 assert(!comp || (comp->state & CLASS_LOADED));
891 if (comp && !(comp->state & CLASS_LINKED))
892 if (!link_class(comp))
895 /* Allocate the arraydescriptor */
897 desc = NEW(arraydescriptor);
900 /* c is an array of references */
901 desc->arraytype = ARRAYTYPE_OBJECT;
902 desc->componentsize = sizeof(void*);
903 desc->dataoffset = OFFSET(java_objectarray, data);
905 compvftbl = comp->vftbl;
908 log_text("Component class has no vftbl");
912 desc->componentvftbl = compvftbl;
914 if (compvftbl->arraydesc) {
915 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
917 if (compvftbl->arraydesc->dimension >= 255) {
918 log_text("Creating array of dimension >255");
922 desc->dimension = compvftbl->arraydesc->dimension + 1;
923 desc->elementtype = compvftbl->arraydesc->elementtype;
926 desc->elementvftbl = compvftbl;
928 desc->elementtype = ARRAYTYPE_OBJECT;
932 /* c is an array of a primitive type */
933 switch (c->name->text[1]) {
935 desc->arraytype = ARRAYTYPE_BOOLEAN;
936 desc->dataoffset = OFFSET(java_booleanarray,data);
937 desc->componentsize = sizeof(u1);
941 desc->arraytype = ARRAYTYPE_BYTE;
942 desc->dataoffset = OFFSET(java_bytearray,data);
943 desc->componentsize = sizeof(u1);
947 desc->arraytype = ARRAYTYPE_CHAR;
948 desc->dataoffset = OFFSET(java_chararray,data);
949 desc->componentsize = sizeof(u2);
953 desc->arraytype = ARRAYTYPE_DOUBLE;
954 desc->dataoffset = OFFSET(java_doublearray,data);
955 desc->componentsize = sizeof(double);
959 desc->arraytype = ARRAYTYPE_FLOAT;
960 desc->dataoffset = OFFSET(java_floatarray,data);
961 desc->componentsize = sizeof(float);
965 desc->arraytype = ARRAYTYPE_INT;
966 desc->dataoffset = OFFSET(java_intarray,data);
967 desc->componentsize = sizeof(s4);
971 desc->arraytype = ARRAYTYPE_LONG;
972 desc->dataoffset = OFFSET(java_longarray,data);
973 desc->componentsize = sizeof(s8);
977 desc->arraytype = ARRAYTYPE_SHORT;
978 desc->dataoffset = OFFSET(java_shortarray,data);
979 desc->componentsize = sizeof(s2);
983 *exceptionptr = new_noclassdeffounderror(c->name);
987 desc->componentvftbl = NULL;
988 desc->elementvftbl = NULL;
990 desc->elementtype = desc->arraytype;
997 /* linker_compute_subclasses ***************************************************
1001 *******************************************************************************/
1003 static void linker_compute_subclasses(classinfo *c)
1005 #if defined(USE_THREADS)
1006 #if defined(NATIVE_THREADS)
1013 if (!(c->flags & ACC_INTERFACE)) {
1018 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1019 c->nextsub = c->super.cls->sub;
1020 c->super.cls->sub = c;
1025 /* compute class values */
1027 linker_compute_class_values(class_java_lang_Object);
1029 #if defined(USE_THREADS)
1030 #if defined(NATIVE_THREADS)
1039 /* linker_compute_class_values *************************************************
1043 *******************************************************************************/
1045 static void linker_compute_class_values(classinfo *c)
1049 c->vftbl->baseval = ++classvalue;
1054 linker_compute_class_values(subs);
1056 subs = subs->nextsub;
1059 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1063 /* linker_addinterface *********************************************************
1065 Is needed by link_class for adding a VTBL to a class. All
1066 interfaces implemented by ic are added as well.
1068 *******************************************************************************/
1070 static void linker_addinterface(classinfo *c, classinfo *ic)
1074 vftbl_t *v = c->vftbl;
1076 if (i >= v->interfacetablelength) {
1077 log_text("Inernal error: interfacetable overflow");
1081 if (v->interfacetable[-i])
1084 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1085 v->interfacevftbllength[i] = 1;
1086 v->interfacetable[-i] = MNEW(methodptr, 1);
1087 v->interfacetable[-i][0] = NULL;
1090 v->interfacevftbllength[i] = ic->methodscount;
1091 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1093 #if defined(ENABLE_STATISTICS)
1095 count_vftbl_len += sizeof(methodptr) *
1096 (ic->methodscount + (ic->methodscount == 0));
1099 for (j = 0; j < ic->methodscount; j++) {
1103 for (m = 0; m < sc->methodscount; m++) {
1104 methodinfo *mi = &(sc->methods[m]);
1106 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1107 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1118 for (j = 0; j < ic->interfacescount; j++)
1119 linker_addinterface(c, ic->interfaces[j].cls);
1123 /* class_highestinterface ******************************************************
1125 Used by the function link_class to determine the amount of memory
1126 needed for the interface table.
1128 *******************************************************************************/
1130 static s4 class_highestinterface(classinfo *c)
1136 /* check for ACC_INTERFACE bit already done in link_class_intern */
1140 for (i = 0; i < c->interfacescount; i++) {
1141 h2 = class_highestinterface(c->interfaces[i].cls);
1152 * These are local overrides for various environment variables in Emacs.
1153 * Please do not remove this and leave it at the end of the file, where
1154 * Emacs will automagically detect them.
1155 * ---------------------------------------------------------------------
1158 * indent-tabs-mode: t