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 3803 2005-11-26 19:18:33Z twisti $
45 #include "mm/memory.h"
46 #include "native/native.h"
47 #include "vm/builtin.h"
49 #include "vm/classcache.h"
50 #include "vm/exceptions.h"
51 #include "vm/loader.h"
52 #include "vm/options.h"
53 #include "vm/resolve.h"
54 #include "vm/statistics.h"
55 #include "vm/stringlocal.h"
56 #include "vm/jit/codegen.inc.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->loaded = true;
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->loaded = true;
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->loaded = true;
257 pseudo_class_New->linked = true; /* 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 */
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;
344 primitivetype_table[i].arrayvftbl = c->vftbl;
352 /* link_class ******************************************************************
354 Wrapper function for link_class_intern to ease monitor enter/exit
355 and exception handling.
357 *******************************************************************************/
359 classinfo *link_class(classinfo *c)
364 *exceptionptr = new_nullpointerexception();
368 #if defined(USE_THREADS)
369 /* enter a monitor on the class */
371 builtin_monitorenter((java_objectheader *) c);
374 /* maybe the class is already linked */
376 #if defined(USE_THREADS)
377 builtin_monitorexit((java_objectheader *) c);
383 #if defined(STATISTICS)
386 if (getcompilingtime)
387 compilingtime_stop();
393 /* call the internal function */
395 r = link_class_intern(c);
397 /* if return value is NULL, we had a problem and the class is not linked */
402 #if defined(STATISTICS)
408 if (getcompilingtime)
409 compilingtime_start();
412 #if defined(USE_THREADS)
413 /* leave the monitor */
415 builtin_monitorexit((java_objectheader *) c);
422 /* link_class_intern ***********************************************************
424 Tries to link a class. The function calculates the length in bytes
425 that an instance of this class requires as well as the VTBL for
426 methods and interface methods.
428 *******************************************************************************/
430 static classinfo *link_class_intern(classinfo *c)
432 classinfo *super; /* super class */
433 classinfo *tc; /* temporary class variable */
434 s4 supervftbllength; /* vftbllegnth of super class */
435 s4 vftbllength; /* vftbllength of current class */
436 s4 interfacetablelength; /* interface table length */
437 vftbl_t *v; /* vftbl of current class */
438 s4 i,j; /* interface/method/field counter */
439 arraydescriptor *arraydesc; /* descriptor for array classes */
441 /* maybe the class is already linked */
447 log_message_class("Linking class: ", c);
449 /* the class must be loaded */
452 throw_cacao_exception_exit(string_java_lang_InternalError,
453 "Trying to link unloaded class");
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 /* ok, this class is somewhat linked */
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,
493 if (!(tc->flags & ACC_INTERFACE)) {
495 new_exception_message(string_java_lang_IncompatibleClassChangeError,
496 "Implementing class");
505 /* check super class */
509 if (c->super.any == NULL) { /* class java.lang.Object */
511 c->classUsed = USED; /* Object class is always used CO-RT*/
513 c->instancesize = sizeof(java_objectheader);
515 vftbllength = supervftbllength = 0;
520 /* resolve super class */
522 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
525 c->super.cls = super;
527 /* detect circularity */
531 new_exception_utfmessage(string_java_lang_ClassCircularityError,
536 assert(super->loaded);
538 if (super->flags & ACC_INTERFACE) {
539 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
540 log_text("Interface specified as super class");
544 /* Don't allow extending final classes */
546 if (super->flags & ACC_FINAL) {
548 new_exception_message(string_java_lang_VerifyError,
549 "Cannot inherit from final class");
554 if (!link_class(super))
557 /* handle array classes */
559 if (c->name->text[0] == '[')
560 if (!(arraydesc = link_array(c)))
563 if (c->flags & ACC_INTERFACE)
564 c->index = interfaceindex++;
566 c->index = super->index + 1;
568 c->instancesize = super->instancesize;
570 vftbllength = supervftbllength = super->vftbl->vftbllength;
572 c->finalizer = super->finalizer;
576 /* compute vftbl length */
578 for (i = 0; i < c->methodscount; i++) {
579 methodinfo *m = &(c->methods[i]);
581 if (!(m->flags & ACC_STATIC)) { /* is instance method */
587 for (j = 0; j < tc->methodscount; j++) {
588 if (method_canoverwrite(m, &(tc->methods[j]))) {
589 if (tc->methods[j].flags & ACC_PRIVATE)
590 goto notfoundvftblindex;
592 if (tc->methods[j].flags & ACC_FINAL) {
593 /* class a overrides final method . */
595 new_exception(string_java_lang_VerifyError);
599 m->vftblindex = tc->methods[j].vftblindex;
600 goto foundvftblindex;
608 m->vftblindex = (vftbllength++);
615 /* check interfaces of ABSTRACT class for unimplemented methods */
617 if (c->flags & ACC_ABSTRACT) {
620 s4 abstractmethodscount;
624 abstractmethodscount = 0;
626 for (i = 0; i < c->interfacescount; i++) {
627 ic = c->interfaces[i].cls;
629 for (j = 0; j < ic->methodscount; j++) {
630 im = &(ic->methods[j]);
632 /* skip `<clinit>' and `<init>' */
634 if (im->name == utf_clinit || im->name == utf_init)
640 for (k = 0; k < tc->methodscount; k++) {
641 if (method_canoverwrite(im, &(tc->methods[k])))
642 goto noabstractmethod;
648 abstractmethodscount++;
655 if (abstractmethodscount > 0) {
658 /* reallocate methods memory */
660 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
661 c->methodscount + abstractmethodscount);
663 for (i = 0; i < c->interfacescount; i++) {
664 ic = c->interfaces[i].cls;
666 for (j = 0; j < ic->methodscount; j++) {
667 im = &(ic->methods[j]);
669 /* skip `<clinit>' and `<init>' */
671 if (im->name == utf_clinit || im->name == utf_init)
677 for (k = 0; k < tc->methodscount; k++) {
678 if (method_canoverwrite(im, &(tc->methods[k])))
679 goto noabstractmethod2;
685 am = &(c->methods[c->methodscount]);
688 MCOPY(am, im, methodinfo, 1);
690 am->vftblindex = (vftbllength++);
701 #if defined(STATISTICS)
704 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
707 /* compute interfacetable length */
709 interfacetablelength = 0;
712 for (i = 0; i < tc->interfacescount; i++) {
713 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
714 if (h > interfacetablelength)
715 interfacetablelength = h;
720 /* allocate virtual function table */
722 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
723 sizeof(methodptr) * (vftbllength - 1) +
724 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
725 v = (vftbl_t *) (((methodptr *) v) +
726 (interfacetablelength - 1) * (interfacetablelength > 1));
729 v->vftbllength = vftbllength;
730 v->interfacetablelength = interfacetablelength;
731 v->arraydesc = arraydesc;
733 /* store interface index in vftbl */
735 if (c->flags & ACC_INTERFACE)
736 v->baseval = -(c->index);
738 /* copy virtual function table of super class */
740 for (i = 0; i < supervftbllength; i++)
741 v->table[i] = super->vftbl->table[i];
743 /* add method stubs into virtual function table */
745 for (i = 0; i < c->methodscount; i++) {
746 methodinfo *m = &(c->methods[i]);
748 /* Methods in ABSTRACT classes from interfaces maybe already have a */
752 m->stubroutine = createcompilerstub(m);
754 if (!(m->flags & ACC_STATIC))
755 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
758 /* compute instance size and offset of each field */
760 for (i = 0; i < c->fieldscount; i++) {
762 fieldinfo *f = &(c->fields[i]);
764 if (!(f->flags & ACC_STATIC)) {
765 dsize = desc_typesize(f->descriptor);
766 c->instancesize = ALIGN(c->instancesize, dsize);
767 f->offset = c->instancesize;
768 c->instancesize += dsize;
772 /* initialize interfacetable and interfacevftbllength */
774 v->interfacevftbllength = MNEW(s4, interfacetablelength);
776 #if defined(STATISTICS)
778 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
781 for (i = 0; i < interfacetablelength; i++) {
782 v->interfacevftbllength[i] = 0;
783 v->interfacetable[-i] = NULL;
788 for (tc = c; tc != NULL; tc = tc->super.cls)
789 for (i = 0; i < tc->interfacescount; i++)
790 linker_addinterface(c, tc->interfaces[i].cls);
792 /* add finalizer method (not for java.lang.Object) */
797 fi = class_findmethod(c, utf_finalize, utf_void__void);
800 if (!(fi->flags & ACC_STATIC))
804 /* resolve exception class references */
806 for (i = 0; i < c->methodscount; i++) {
807 methodinfo *m = &(c->methods[i]);
809 for (j = 0; j < m->exceptiontablelength; j++) {
810 if (!m->exceptiontable[j].catchtype.any)
812 if (!resolve_classref_or_classinfo(NULL,
813 m->exceptiontable[j].catchtype,
814 resolveEager, true, false,
815 &(m->exceptiontable[j].catchtype.cls)))
822 linker_compute_subclasses(c);
825 log_message_class("Linking done class: ", c);
827 /* just return c to show that we didn't had a problem */
833 /* link_array ******************************************************************
835 This function is called by link_class to create the arraydescriptor
838 This function returns NULL if the array cannot be linked because
839 the component type has not been linked yet.
841 *******************************************************************************/
843 static arraydescriptor *link_array(classinfo *c)
847 arraydescriptor *desc;
852 namelen = c->name->blength;
854 /* Check the component type */
856 switch (c->name->text[1]) {
858 /* c is an array of arrays. */
859 u = utf_new(c->name->text + 1, namelen - 1);
860 if (!(comp = load_class_from_classloader(u, c->classloader)))
865 /* c is an array of objects. */
866 u = utf_new(c->name->text + 2, namelen - 3);
867 if (!(comp = load_class_from_classloader(u, c->classloader)))
872 /* If the component type has not been linked, link it now */
873 assert(!comp || comp->loaded);
874 if (comp && !comp->linked) {
876 if (!link_class(comp))
880 /* Allocate the arraydescriptor */
881 desc = NEW(arraydescriptor);
884 /* c is an array of references */
885 desc->arraytype = ARRAYTYPE_OBJECT;
886 desc->componentsize = sizeof(void*);
887 desc->dataoffset = OFFSET(java_objectarray, data);
889 compvftbl = comp->vftbl;
892 log_text("Component class has no vftbl");
896 desc->componentvftbl = compvftbl;
898 if (compvftbl->arraydesc) {
899 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
901 if (compvftbl->arraydesc->dimension >= 255) {
902 log_text("Creating array of dimension >255");
906 desc->dimension = compvftbl->arraydesc->dimension + 1;
907 desc->elementtype = compvftbl->arraydesc->elementtype;
910 desc->elementvftbl = compvftbl;
912 desc->elementtype = ARRAYTYPE_OBJECT;
916 /* c is an array of a primitive type */
917 switch (c->name->text[1]) {
919 desc->arraytype = ARRAYTYPE_BOOLEAN;
920 desc->dataoffset = OFFSET(java_booleanarray,data);
921 desc->componentsize = sizeof(u1);
925 desc->arraytype = ARRAYTYPE_BYTE;
926 desc->dataoffset = OFFSET(java_bytearray,data);
927 desc->componentsize = sizeof(u1);
931 desc->arraytype = ARRAYTYPE_CHAR;
932 desc->dataoffset = OFFSET(java_chararray,data);
933 desc->componentsize = sizeof(u2);
937 desc->arraytype = ARRAYTYPE_DOUBLE;
938 desc->dataoffset = OFFSET(java_doublearray,data);
939 desc->componentsize = sizeof(double);
943 desc->arraytype = ARRAYTYPE_FLOAT;
944 desc->dataoffset = OFFSET(java_floatarray,data);
945 desc->componentsize = sizeof(float);
949 desc->arraytype = ARRAYTYPE_INT;
950 desc->dataoffset = OFFSET(java_intarray,data);
951 desc->componentsize = sizeof(s4);
955 desc->arraytype = ARRAYTYPE_LONG;
956 desc->dataoffset = OFFSET(java_longarray,data);
957 desc->componentsize = sizeof(s8);
961 desc->arraytype = ARRAYTYPE_SHORT;
962 desc->dataoffset = OFFSET(java_shortarray,data);
963 desc->componentsize = sizeof(s2);
967 *exceptionptr = new_noclassdeffounderror(c->name);
971 desc->componentvftbl = NULL;
972 desc->elementvftbl = NULL;
974 desc->elementtype = desc->arraytype;
981 /* linker_compute_subclasses ***************************************************
985 *******************************************************************************/
987 static void linker_compute_subclasses(classinfo *c)
989 #if defined(USE_THREADS)
990 #if defined(NATIVE_THREADS)
997 if (!(c->flags & ACC_INTERFACE)) {
1002 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1003 c->nextsub = c->super.cls->sub;
1004 c->super.cls->sub = c;
1009 /* compute class values */
1011 linker_compute_class_values(class_java_lang_Object);
1013 #if defined(USE_THREADS)
1014 #if defined(NATIVE_THREADS)
1023 /* linker_compute_class_values *************************************************
1027 *******************************************************************************/
1029 static void linker_compute_class_values(classinfo *c)
1033 c->vftbl->baseval = ++classvalue;
1038 linker_compute_class_values(subs);
1040 subs = subs->nextsub;
1043 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1047 /* linker_addinterface *********************************************************
1049 Is needed by link_class for adding a VTBL to a class. All
1050 interfaces implemented by ic are added as well.
1052 *******************************************************************************/
1054 static void linker_addinterface(classinfo *c, classinfo *ic)
1058 vftbl_t *v = c->vftbl;
1060 if (i >= v->interfacetablelength) {
1061 log_text("Inernal error: interfacetable overflow");
1065 if (v->interfacetable[-i])
1068 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1069 v->interfacevftbllength[i] = 1;
1070 v->interfacetable[-i] = MNEW(methodptr, 1);
1071 v->interfacetable[-i][0] = NULL;
1074 v->interfacevftbllength[i] = ic->methodscount;
1075 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1077 #if defined(STATISTICS)
1079 count_vftbl_len += sizeof(methodptr) *
1080 (ic->methodscount + (ic->methodscount == 0));
1083 for (j = 0; j < ic->methodscount; j++) {
1087 for (m = 0; m < sc->methodscount; m++) {
1088 methodinfo *mi = &(sc->methods[m]);
1090 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1091 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1102 for (j = 0; j < ic->interfacescount; j++)
1103 linker_addinterface(c, ic->interfaces[j].cls);
1107 /* class_highestinterface ******************************************************
1109 Used by the function link_class to determine the amount of memory
1110 needed for the interface table.
1112 *******************************************************************************/
1114 static s4 class_highestinterface(classinfo *c)
1120 /* check for ACC_INTERFACE bit already done in link_class_intern */
1124 for (i = 0; i < c->interfacescount; i++) {
1125 h2 = class_highestinterface(c->interfaces[i].cls);
1136 * These are local overrides for various environment variables in Emacs.
1137 * Please do not remove this and leave it at the end of the file, where
1138 * Emacs will automagically detect them.
1139 * ---------------------------------------------------------------------
1142 * indent-tabs-mode: t