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 4690 2006-03-27 11:37:46Z 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/access.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;
305 /* prevent loader from loading primitive class */
307 c->state |= CLASS_LOADED;
309 /* INFO: don't put primitive classes into the classcache */
314 primitivetype_table[i].class_primitive = c;
316 /* create class for wrapping the primitive type */
318 u = utf_new_char(primitivetype_table[i].wrapname);
320 if (!(c = load_class_bootstrap(u)))
323 primitivetype_table[i].class_wrap = c;
325 /* create the primitive array class */
327 if (primitivetype_table[i].arrayname) {
328 u = utf_new_char(primitivetype_table[i].arrayname);
329 c = class_create_classinfo(u);
330 c = load_newly_created_array(c, NULL);
334 primitivetype_table[i].arrayclass = c;
336 assert(c->state & CLASS_LOADED);
338 if (!(c->state & CLASS_LINKED))
342 primitivetype_table[i].arrayvftbl = c->vftbl;
350 /* link_class ******************************************************************
352 Wrapper function for link_class_intern to ease monitor enter/exit
353 and exception handling.
355 *******************************************************************************/
357 classinfo *link_class(classinfo *c)
362 exceptions_throw_nullpointerexception();
366 #if defined(USE_THREADS)
367 /* enter a monitor on the class */
369 builtin_monitorenter((java_objectheader *) c);
372 /* maybe the class is already linked */
374 if (c->state & CLASS_LINKED) {
375 #if defined(USE_THREADS)
376 builtin_monitorexit((java_objectheader *) c);
382 #if defined(ENABLE_STATISTICS)
385 if (getcompilingtime)
386 compilingtime_stop();
392 /* call the internal function */
394 r = link_class_intern(c);
396 /* if return value is NULL, we had a problem and the class is not linked */
399 c->state &= ~CLASS_LINKING;
401 #if defined(ENABLE_STATISTICS)
407 if (getcompilingtime)
408 compilingtime_start();
411 #if defined(USE_THREADS)
412 /* leave the monitor */
414 builtin_monitorexit((java_objectheader *) c);
421 /* link_class_intern ***********************************************************
423 Tries to link a class. The function calculates the length in bytes
424 that an instance of this class requires as well as the VTBL for
425 methods and interface methods.
427 *******************************************************************************/
429 static classinfo *link_class_intern(classinfo *c)
431 classinfo *super; /* super class */
432 classinfo *tc; /* temporary class variable */
433 s4 supervftbllength; /* vftbllegnth of super class */
434 s4 vftbllength; /* vftbllength of current class */
435 s4 interfacetablelength; /* interface table length */
436 vftbl_t *v; /* vftbl of current class */
437 s4 i,j; /* interface/method/field counter */
438 arraydescriptor *arraydesc; /* descriptor for array classes */
440 /* the class is already linked */
442 if (c->state & CLASS_LINKED)
447 log_message_class("Linking class: ", c);
450 /* the class must be loaded */
452 /* XXX should this be a specific exception? */
453 assert(c->state & CLASS_LOADED);
455 /* cache the self-reference of this class */
456 /* we do this for cases where the defining loader of the class */
457 /* has not yet been recorded as an initiating loader for the class */
458 /* this is needed so subsequent code can assume that self-refs */
459 /* will always resolve lazily */
460 /* No need to do it for the bootloader - it is always registered */
461 /* as initiating loader for the classes it loads. */
463 classcache_store(c->classloader,c,false);
465 /* this class is currently linking */
467 c->state |= CLASS_LINKING;
471 /* check interfaces */
473 for (i = 0; i < c->interfacescount; i++) {
474 /* resolve this super interface */
476 if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager,
480 c->interfaces[i].cls = tc;
482 /* detect circularity */
486 new_exception_utfmessage(string_java_lang_ClassCircularityError,
491 assert(tc->state & CLASS_LOADED);
493 if (!(tc->flags & ACC_INTERFACE)) {
495 new_exception_message(string_java_lang_IncompatibleClassChangeError,
496 "Implementing class");
500 if (!(tc->state & CLASS_LINKED))
505 /* check super class */
509 if (c->super.any == NULL) { /* class java.lang.Object */
511 c->instancesize = sizeof(java_objectheader);
513 vftbllength = supervftbllength = 0;
518 /* resolve super class */
520 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
523 c->super.cls = super;
525 /* detect circularity */
529 new_exception_utfmessage(string_java_lang_ClassCircularityError,
534 assert(super->state & CLASS_LOADED);
536 if (super->flags & ACC_INTERFACE) {
537 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
538 log_text("Interface specified as super class");
542 /* Don't allow extending final classes */
544 if (super->flags & ACC_FINAL) {
546 new_exception_message(string_java_lang_VerifyError,
547 "Cannot inherit from final class");
551 if (!(super->state & CLASS_LINKED))
552 if (!link_class(super))
555 /* handle array classes */
557 if (c->name->text[0] == '[')
558 if (!(arraydesc = link_array(c)))
561 if (c->flags & ACC_INTERFACE)
562 c->index = interfaceindex++;
564 c->index = super->index + 1;
566 c->instancesize = super->instancesize;
568 vftbllength = supervftbllength = super->vftbl->vftbllength;
570 c->finalizer = super->finalizer;
574 /* compute vftbl length */
576 for (i = 0; i < c->methodscount; i++) {
577 methodinfo *m = &(c->methods[i]);
579 if (!(m->flags & ACC_STATIC)) { /* is instance method */
585 for (j = 0; j < tc->methodscount; j++) {
586 if (method_canoverwrite(m, &(tc->methods[j]))) {
587 if (tc->methods[j].flags & ACC_PRIVATE)
588 goto notfoundvftblindex;
590 /* package-private methods in other packages */
591 /* must not be overridden */
592 /* (see Java Language Specification 8.4.8.1) */
593 if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
594 && !SAME_PACKAGE(c,tc) )
596 goto notfoundvftblindex;
599 if (tc->methods[j].flags & ACC_FINAL) {
600 /* class a overrides final method . */
602 new_exception(string_java_lang_VerifyError);
606 m->vftblindex = tc->methods[j].vftblindex;
607 goto foundvftblindex;
615 m->vftblindex = (vftbllength++);
622 /* Check all interfaces of an abtract class (maybe be an interface
623 too) for unimplemented methods. Such methods are called
624 miranda-methods and are marked with the ACC_MIRANDA flag.
625 VMClass.getDeclaredMethods does not return such methods. */
627 if (c->flags & ACC_ABSTRACT) {
630 s4 abstractmethodscount;
634 abstractmethodscount = 0;
636 /* check all interfaces of the abtract class */
638 for (i = 0; i < c->interfacescount; i++) {
639 ic = c->interfaces[i].cls;
641 for (j = 0; j < ic->methodscount; j++) {
642 im = &(ic->methods[j]);
644 /* skip `<clinit>' and `<init>' */
646 if ((im->name == utf_clinit) || (im->name == utf_init))
649 for (tc = c; tc != NULL; tc = tc->super.cls) {
650 for (k = 0; k < tc->methodscount; k++) {
651 if (method_canoverwrite(im, &(tc->methods[k])))
652 goto noabstractmethod;
656 abstractmethodscount++;
663 if (abstractmethodscount > 0) {
666 /* reallocate methods memory */
668 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
669 c->methodscount + abstractmethodscount);
671 for (i = 0; i < c->interfacescount; i++) {
672 ic = c->interfaces[i].cls;
674 for (j = 0; j < ic->methodscount; j++) {
675 im = &(ic->methods[j]);
677 /* skip `<clinit>' and `<init>' */
679 if ((im->name == utf_clinit) || (im->name == utf_init))
682 for (tc = c; tc != NULL; tc = tc->super.cls) {
683 for (k = 0; k < tc->methodscount; k++) {
684 if (method_canoverwrite(im, &(tc->methods[k])))
685 goto noabstractmethod2;
689 /* Copy the method found into the new c->methods
690 array and tag it as miranda-method. */
692 am = &(c->methods[c->methodscount]);
695 MCOPY(am, im, methodinfo, 1);
697 am->vftblindex = (vftbllength++);
699 am->flags |= ACC_MIRANDA;
709 #if defined(ENABLE_STATISTICS)
712 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
715 /* compute interfacetable length */
717 interfacetablelength = 0;
720 for (i = 0; i < tc->interfacescount; i++) {
721 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
722 if (h > interfacetablelength)
723 interfacetablelength = h;
728 /* allocate virtual function table */
730 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
731 sizeof(methodptr) * (vftbllength - 1) +
732 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
733 v = (vftbl_t *) (((methodptr *) v) +
734 (interfacetablelength - 1) * (interfacetablelength > 1));
737 v->vftbllength = vftbllength;
738 v->interfacetablelength = interfacetablelength;
739 v->arraydesc = arraydesc;
741 /* store interface index in vftbl */
743 if (c->flags & ACC_INTERFACE)
744 v->baseval = -(c->index);
746 /* copy virtual function table of super class */
748 for (i = 0; i < supervftbllength; i++)
749 v->table[i] = super->vftbl->table[i];
751 /* add method stubs into virtual function table */
753 for (i = 0; i < c->methodscount; i++) {
754 methodinfo *m = &(c->methods[i]);
756 /* Methods in ABSTRACT classes from interfaces maybe already
757 have a stubroutine. */
759 if (!m->stubroutine) {
760 #if defined(ENABLE_JIT)
761 # if defined(ENABLE_INTRP)
763 m->stubroutine = intrp_createcompilerstub(m);
766 m->stubroutine = createcompilerstub(m);
768 m->stubroutine = intrp_createcompilerstub(m);
772 if (!(m->flags & ACC_STATIC))
773 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
776 /* compute instance size and offset of each field */
778 for (i = 0; i < c->fieldscount; i++) {
780 fieldinfo *f = &(c->fields[i]);
782 if (!(f->flags & ACC_STATIC)) {
783 dsize = descriptor_typesize(f->parseddesc);
784 c->instancesize = ALIGN(c->instancesize, dsize);
785 f->offset = c->instancesize;
786 c->instancesize += dsize;
790 /* initialize interfacetable and interfacevftbllength */
792 v->interfacevftbllength = MNEW(s4, interfacetablelength);
794 #if defined(ENABLE_STATISTICS)
796 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
799 for (i = 0; i < interfacetablelength; i++) {
800 v->interfacevftbllength[i] = 0;
801 v->interfacetable[-i] = NULL;
806 for (tc = c; tc != NULL; tc = tc->super.cls)
807 for (i = 0; i < tc->interfacescount; i++)
808 linker_addinterface(c, tc->interfaces[i].cls);
810 /* add finalizer method (not for java.lang.Object) */
815 fi = class_findmethod(c, utf_finalize, utf_void__void);
818 if (!(fi->flags & ACC_STATIC))
822 /* resolve exception class references */
824 for (i = 0; i < c->methodscount; i++) {
825 methodinfo *m = &(c->methods[i]);
827 for (j = 0; j < m->exceptiontablelength; j++) {
828 if (!m->exceptiontable[j].catchtype.any)
830 if (!resolve_classref_or_classinfo(NULL,
831 m->exceptiontable[j].catchtype,
832 resolveEager, true, false,
833 &(m->exceptiontable[j].catchtype.cls)))
840 linker_compute_subclasses(c);
842 /* revert the linking state and class is linked */
844 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
848 log_message_class("Linking done class: ", c);
851 /* just return c to show that we didn't had a problem */
857 /* link_array ******************************************************************
859 This function is called by link_class to create the arraydescriptor
862 This function returns NULL if the array cannot be linked because
863 the component type has not been linked yet.
865 *******************************************************************************/
867 static arraydescriptor *link_array(classinfo *c)
871 arraydescriptor *desc;
876 namelen = c->name->blength;
878 /* Check the component type */
880 switch (c->name->text[1]) {
882 /* c is an array of arrays. */
883 u = utf_new(c->name->text + 1, namelen - 1);
884 if (!(comp = load_class_from_classloader(u, c->classloader)))
889 /* c is an array of objects. */
890 u = utf_new(c->name->text + 2, namelen - 3);
891 if (!(comp = load_class_from_classloader(u, c->classloader)))
896 /* If the component type has not been linked, link it now */
898 assert(!comp || (comp->state & CLASS_LOADED));
900 if (comp && !(comp->state & CLASS_LINKED))
901 if (!link_class(comp))
904 /* Allocate the arraydescriptor */
906 desc = NEW(arraydescriptor);
909 /* c is an array of references */
910 desc->arraytype = ARRAYTYPE_OBJECT;
911 desc->componentsize = sizeof(void*);
912 desc->dataoffset = OFFSET(java_objectarray, data);
914 compvftbl = comp->vftbl;
917 log_text("Component class has no vftbl");
921 desc->componentvftbl = compvftbl;
923 if (compvftbl->arraydesc) {
924 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
926 if (compvftbl->arraydesc->dimension >= 255) {
927 log_text("Creating array of dimension >255");
931 desc->dimension = compvftbl->arraydesc->dimension + 1;
932 desc->elementtype = compvftbl->arraydesc->elementtype;
935 desc->elementvftbl = compvftbl;
937 desc->elementtype = ARRAYTYPE_OBJECT;
941 /* c is an array of a primitive type */
942 switch (c->name->text[1]) {
944 desc->arraytype = ARRAYTYPE_BOOLEAN;
945 desc->dataoffset = OFFSET(java_booleanarray,data);
946 desc->componentsize = sizeof(u1);
950 desc->arraytype = ARRAYTYPE_BYTE;
951 desc->dataoffset = OFFSET(java_bytearray,data);
952 desc->componentsize = sizeof(u1);
956 desc->arraytype = ARRAYTYPE_CHAR;
957 desc->dataoffset = OFFSET(java_chararray,data);
958 desc->componentsize = sizeof(u2);
962 desc->arraytype = ARRAYTYPE_DOUBLE;
963 desc->dataoffset = OFFSET(java_doublearray,data);
964 desc->componentsize = sizeof(double);
968 desc->arraytype = ARRAYTYPE_FLOAT;
969 desc->dataoffset = OFFSET(java_floatarray,data);
970 desc->componentsize = sizeof(float);
974 desc->arraytype = ARRAYTYPE_INT;
975 desc->dataoffset = OFFSET(java_intarray,data);
976 desc->componentsize = sizeof(s4);
980 desc->arraytype = ARRAYTYPE_LONG;
981 desc->dataoffset = OFFSET(java_longarray,data);
982 desc->componentsize = sizeof(s8);
986 desc->arraytype = ARRAYTYPE_SHORT;
987 desc->dataoffset = OFFSET(java_shortarray,data);
988 desc->componentsize = sizeof(s2);
992 *exceptionptr = new_noclassdeffounderror(c->name);
996 desc->componentvftbl = NULL;
997 desc->elementvftbl = NULL;
999 desc->elementtype = desc->arraytype;
1006 /* linker_compute_subclasses ***************************************************
1010 *******************************************************************************/
1012 static void linker_compute_subclasses(classinfo *c)
1014 #if defined(USE_THREADS)
1015 #if defined(NATIVE_THREADS)
1022 if (!(c->flags & ACC_INTERFACE)) {
1027 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1028 c->nextsub = c->super.cls->sub;
1029 c->super.cls->sub = c;
1034 /* compute class values */
1036 linker_compute_class_values(class_java_lang_Object);
1038 #if defined(USE_THREADS)
1039 #if defined(NATIVE_THREADS)
1048 /* linker_compute_class_values *************************************************
1052 *******************************************************************************/
1054 static void linker_compute_class_values(classinfo *c)
1058 c->vftbl->baseval = ++classvalue;
1063 linker_compute_class_values(subs);
1065 subs = subs->nextsub;
1068 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1072 /* linker_addinterface *********************************************************
1074 Is needed by link_class for adding a VTBL to a class. All
1075 interfaces implemented by ic are added as well.
1077 *******************************************************************************/
1079 static void linker_addinterface(classinfo *c, classinfo *ic)
1083 vftbl_t *v = c->vftbl;
1085 if (i >= v->interfacetablelength) {
1086 log_text("Inernal error: interfacetable overflow");
1090 if (v->interfacetable[-i])
1093 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1094 v->interfacevftbllength[i] = 1;
1095 v->interfacetable[-i] = MNEW(methodptr, 1);
1096 v->interfacetable[-i][0] = NULL;
1099 v->interfacevftbllength[i] = ic->methodscount;
1100 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1102 #if defined(ENABLE_STATISTICS)
1104 count_vftbl_len += sizeof(methodptr) *
1105 (ic->methodscount + (ic->methodscount == 0));
1108 for (j = 0; j < ic->methodscount; j++) {
1112 for (m = 0; m < sc->methodscount; m++) {
1113 methodinfo *mi = &(sc->methods[m]);
1115 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1116 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1127 for (j = 0; j < ic->interfacescount; j++)
1128 linker_addinterface(c, ic->interfaces[j].cls);
1132 /* class_highestinterface ******************************************************
1134 Used by the function link_class to determine the amount of memory
1135 needed for the interface table.
1137 *******************************************************************************/
1139 static s4 class_highestinterface(classinfo *c)
1145 /* check for ACC_INTERFACE bit already done in link_class_intern */
1149 for (i = 0; i < c->interfacescount; i++) {
1150 h2 = class_highestinterface(c->interfaces[i].cls);
1161 * These are local overrides for various environment variables in Emacs.
1162 * Please do not remove this and leave it at the end of the file, where
1163 * Emacs will automagically detect them.
1164 * ---------------------------------------------------------------------
1167 * indent-tabs-mode: t
1171 * vim:noexpandtab:sw=4:ts=4: