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 3685 2005-11-16 13:28:59Z 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 important system classes */
117 if (!link_class(class_java_lang_Object))
120 if (!link_class(class_java_lang_String))
123 if (!link_class(class_java_lang_Cloneable))
126 if (!link_class(class_java_io_Serializable))
130 /* link classes for wrapping primitive types */
132 if (!link_class(class_java_lang_Void))
135 if (!link_class(class_java_lang_Boolean))
138 if (!link_class(class_java_lang_Byte))
141 if (!link_class(class_java_lang_Character))
144 if (!link_class(class_java_lang_Short))
147 if (!link_class(class_java_lang_Integer))
150 if (!link_class(class_java_lang_Long))
153 if (!link_class(class_java_lang_Float))
156 if (!link_class(class_java_lang_Double))
160 /* load some other important classes */
162 if (!link_class(class_java_lang_Class))
165 if (!link_class(class_java_lang_ClassLoader))
168 if (!link_class(class_java_lang_SecurityManager))
171 if (!link_class(class_java_lang_System))
174 if (!link_class(class_java_lang_Thread))
177 if (!link_class(class_java_lang_ThreadGroup))
180 if (!link_class(class_java_lang_VMThread))
184 /* some classes which may be used more often */
186 if (!link_class(class_java_lang_StackTraceElement))
189 if (!link_class(class_java_lang_reflect_Constructor))
192 if (!link_class(class_java_lang_reflect_Field))
195 if (!link_class(class_java_lang_reflect_Method))
198 if (!link_class(class_java_security_PrivilegedAction))
201 if (!link_class(class_java_util_Vector))
204 if (!link_class(arrayclass_java_lang_Object))
208 /* create pseudo classes used by the typechecker */
210 /* pseudo class for Arraystubs (extends java.lang.Object) */
212 pseudo_class_Arraystub =
213 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
214 pseudo_class_Arraystub->loaded = true;
215 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
216 pseudo_class_Arraystub->interfacescount = 2;
217 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
218 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
219 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
221 if (!classcache_store_unique(pseudo_class_Arraystub)) {
222 log_text("could not cache pseudo_class_Arraystub");
226 if (!link_class(pseudo_class_Arraystub))
229 /* pseudo class representing the null type */
231 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
232 pseudo_class_Null->loaded = true;
233 pseudo_class_Null->super.cls = class_java_lang_Object;
235 if (!classcache_store_unique(pseudo_class_Null)) {
236 log_text("could not cache pseudo_class_Null");
240 if (!link_class(pseudo_class_Null))
243 /* pseudo class representing new uninitialized objects */
245 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
246 pseudo_class_New->loaded = true;
247 pseudo_class_New->linked = true; /* XXX is this allright? */
248 pseudo_class_New->super.cls = class_java_lang_Object;
250 if (!classcache_store_unique(pseudo_class_New)) {
251 log_text("could not cache pseudo_class_New");
255 /* create classes representing primitive types */
257 if (!link_primitivetype_table())
261 /* Correct vftbl-entries (retarded loading and linking of class */
262 /* java/lang/String). */
264 stringtable_update();
270 /* link_primitivetype_table ****************************************************
272 Create classes representing primitive types.
274 *******************************************************************************/
276 static bool link_primitivetype_table(void)
282 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
285 if (!primitivetype_table[i].name)
288 /* create primitive class */
290 c = class_create_classinfo(utf_new_char(primitivetype_table[i].name));
292 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
293 c->classUsed = NOTUSED; /* not used initially CO-RT */
296 /* prevent loader from loading primitive class */
300 /* INFO: don't put primitive classes into the classcache */
305 primitivetype_table[i].class_primitive = c;
307 /* create class for wrapping the primitive type */
309 u = utf_new_char(primitivetype_table[i].wrapname);
311 if (!(c = load_class_bootstrap(u)))
314 primitivetype_table[i].class_wrap = c;
315 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
316 primitivetype_table[i].class_wrap->impldBy = NULL;
318 /* create the primitive array class */
320 if (primitivetype_table[i].arrayname) {
321 u = utf_new_char(primitivetype_table[i].arrayname);
322 c = class_create_classinfo(u);
323 c = load_newly_created_array(c, NULL);
327 primitivetype_table[i].arrayclass = c;
334 primitivetype_table[i].arrayvftbl = c->vftbl;
342 /* link_class ******************************************************************
344 Wrapper function for link_class_intern to ease monitor enter/exit
345 and exception handling.
347 *******************************************************************************/
349 classinfo *link_class(classinfo *c)
354 *exceptionptr = new_nullpointerexception();
358 #if defined(USE_THREADS)
359 /* enter a monitor on the class */
361 builtin_monitorenter((java_objectheader *) c);
364 /* maybe the class is already linked */
366 #if defined(USE_THREADS)
367 builtin_monitorexit((java_objectheader *) c);
373 #if defined(STATISTICS)
376 if (getcompilingtime)
377 compilingtime_stop();
383 /* call the internal function */
385 r = link_class_intern(c);
387 /* if return value is NULL, we had a problem and the class is not linked */
392 #if defined(STATISTICS)
398 if (getcompilingtime)
399 compilingtime_start();
402 #if defined(USE_THREADS)
403 /* leave the monitor */
405 builtin_monitorexit((java_objectheader *) c);
412 /* link_class_intern ***********************************************************
414 Tries to link a class. The function calculates the length in bytes
415 that an instance of this class requires as well as the VTBL for
416 methods and interface methods.
418 *******************************************************************************/
420 static classinfo *link_class_intern(classinfo *c)
422 classinfo *super; /* super class */
423 classinfo *tc; /* temporary class variable */
424 s4 supervftbllength; /* vftbllegnth of super class */
425 s4 vftbllength; /* vftbllength of current class */
426 s4 interfacetablelength; /* interface table length */
427 vftbl_t *v; /* vftbl of current class */
428 s4 i,j; /* interface/method/field counter */
429 arraydescriptor *arraydesc; /* descriptor for array classes */
431 /* maybe the class is already linked */
437 log_message_class("Linking class: ", c);
439 /* the class must be loaded */
442 throw_cacao_exception_exit(string_java_lang_InternalError,
443 "Trying to link unloaded class");
445 /* cache the self-reference of this class */
446 /* we do this for cases where the defining loader of the class */
447 /* has not yet been recorded as an initiating loader for the class */
448 /* this is needed so subsequent code can assume that self-refs */
449 /* will always resolve lazily */
450 /* No need to do it for the bootloader - it is always registered */
451 /* as initiating loader for the classes it loads. */
453 classcache_store(c->classloader,c,false);
455 /* ok, this class is somewhat linked */
461 /* check interfaces */
463 for (i = 0; i < c->interfacescount; i++) {
464 /* resolve this super interface */
466 if (!resolve_classref_or_classinfo(NULL, c->interfaces[i], resolveEager,
470 c->interfaces[i].cls = tc;
472 /* detect circularity */
476 new_exception_utfmessage(string_java_lang_ClassCircularityError,
483 if (!(tc->flags & ACC_INTERFACE)) {
485 new_exception_message(string_java_lang_IncompatibleClassChangeError,
486 "Implementing class");
495 /* check super class */
499 if (c->super.any == NULL) { /* class java.lang.Object */
501 c->classUsed = USED; /* Object class is always used CO-RT*/
503 c->instancesize = sizeof(java_objectheader);
505 vftbllength = supervftbllength = 0;
510 /* resolve super class */
512 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager, true, false,
515 c->super.cls = super;
517 /* detect circularity */
521 new_exception_utfmessage(string_java_lang_ClassCircularityError,
526 assert(super->loaded);
528 if (super->flags & ACC_INTERFACE) {
529 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
530 log_text("Interface specified as super class");
534 /* Don't allow extending final classes */
536 if (super->flags & ACC_FINAL) {
538 new_exception_message(string_java_lang_VerifyError,
539 "Cannot inherit from final class");
544 if (!link_class(super))
547 /* handle array classes */
549 if (c->name->text[0] == '[')
550 if (!(arraydesc = link_array(c)))
553 if (c->flags & ACC_INTERFACE)
554 c->index = interfaceindex++;
556 c->index = super->index + 1;
558 c->instancesize = super->instancesize;
560 vftbllength = supervftbllength = super->vftbl->vftbllength;
562 c->finalizer = super->finalizer;
566 /* compute vftbl length */
568 for (i = 0; i < c->methodscount; i++) {
569 methodinfo *m = &(c->methods[i]);
571 if (!(m->flags & ACC_STATIC)) { /* is instance method */
577 for (j = 0; j < tc->methodscount; j++) {
578 if (method_canoverwrite(m, &(tc->methods[j]))) {
579 if (tc->methods[j].flags & ACC_PRIVATE)
580 goto notfoundvftblindex;
582 if (tc->methods[j].flags & ACC_FINAL) {
583 /* class a overrides final method . */
585 new_exception(string_java_lang_VerifyError);
589 m->vftblindex = tc->methods[j].vftblindex;
590 goto foundvftblindex;
598 m->vftblindex = (vftbllength++);
605 /* check interfaces of ABSTRACT class for unimplemented methods */
607 if (c->flags & ACC_ABSTRACT) {
610 s4 abstractmethodscount;
614 abstractmethodscount = 0;
616 for (i = 0; i < c->interfacescount; i++) {
617 ic = c->interfaces[i].cls;
619 for (j = 0; j < ic->methodscount; j++) {
620 im = &(ic->methods[j]);
622 /* skip `<clinit>' and `<init>' */
624 if (im->name == utf_clinit || im->name == utf_init)
630 for (k = 0; k < tc->methodscount; k++) {
631 if (method_canoverwrite(im, &(tc->methods[k])))
632 goto noabstractmethod;
638 abstractmethodscount++;
645 if (abstractmethodscount > 0) {
648 /* reallocate methods memory */
650 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
651 c->methodscount + abstractmethodscount);
653 for (i = 0; i < c->interfacescount; i++) {
654 ic = c->interfaces[i].cls;
656 for (j = 0; j < ic->methodscount; j++) {
657 im = &(ic->methods[j]);
659 /* skip `<clinit>' and `<init>' */
661 if (im->name == utf_clinit || im->name == utf_init)
667 for (k = 0; k < tc->methodscount; k++) {
668 if (method_canoverwrite(im, &(tc->methods[k])))
669 goto noabstractmethod2;
675 am = &(c->methods[c->methodscount]);
678 MCOPY(am, im, methodinfo, 1);
680 am->vftblindex = (vftbllength++);
691 #if defined(STATISTICS)
694 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
697 /* compute interfacetable length */
699 interfacetablelength = 0;
702 for (i = 0; i < tc->interfacescount; i++) {
703 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
704 if (h > interfacetablelength)
705 interfacetablelength = h;
710 /* allocate virtual function table */
712 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
713 sizeof(methodptr) * (vftbllength - 1) +
714 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
715 v = (vftbl_t *) (((methodptr *) v) +
716 (interfacetablelength - 1) * (interfacetablelength > 1));
717 c->header.vftbl = c->vftbl = v;
719 v->vftbllength = vftbllength;
720 v->interfacetablelength = interfacetablelength;
721 v->arraydesc = arraydesc;
723 /* store interface index in vftbl */
725 if (c->flags & ACC_INTERFACE)
726 v->baseval = -(c->index);
728 /* copy virtual function table of super class */
730 for (i = 0; i < supervftbllength; i++)
731 v->table[i] = super->vftbl->table[i];
733 /* add method stubs into virtual function table */
735 for (i = 0; i < c->methodscount; i++) {
736 methodinfo *m = &(c->methods[i]);
738 /* Methods in ABSTRACT classes from interfaces maybe already have a */
742 m->stubroutine = createcompilerstub(m);
744 if (!(m->flags & ACC_STATIC))
745 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
748 /* compute instance size and offset of each field */
750 for (i = 0; i < c->fieldscount; i++) {
752 fieldinfo *f = &(c->fields[i]);
754 if (!(f->flags & ACC_STATIC)) {
755 dsize = desc_typesize(f->descriptor);
756 c->instancesize = ALIGN(c->instancesize, dsize);
757 f->offset = c->instancesize;
758 c->instancesize += dsize;
762 /* initialize interfacetable and interfacevftbllength */
764 v->interfacevftbllength = MNEW(s4, interfacetablelength);
766 #if defined(STATISTICS)
768 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
771 for (i = 0; i < interfacetablelength; i++) {
772 v->interfacevftbllength[i] = 0;
773 v->interfacetable[-i] = NULL;
778 for (tc = c; tc != NULL; tc = tc->super.cls)
779 for (i = 0; i < tc->interfacescount; i++)
780 linker_addinterface(c, tc->interfaces[i].cls);
782 /* add finalizer method (not for java.lang.Object) */
787 fi = class_findmethod(c, utf_finalize, utf_void__void);
790 if (!(fi->flags & ACC_STATIC))
794 /* resolve exception class references */
796 for (i = 0; i < c->methodscount; i++) {
797 methodinfo *m = &(c->methods[i]);
799 for (j = 0; j < m->exceptiontablelength; j++) {
800 if (!m->exceptiontable[j].catchtype.any)
802 if (!resolve_classref_or_classinfo(NULL,
803 m->exceptiontable[j].catchtype,
804 resolveEager, true, false,
805 &(m->exceptiontable[j].catchtype.cls)))
812 linker_compute_subclasses(c);
815 log_message_class("Linking done class: ", c);
817 /* just return c to show that we didn't had a problem */
823 /* link_array ******************************************************************
825 This function is called by link_class to create the arraydescriptor
828 This function returns NULL if the array cannot be linked because
829 the component type has not been linked yet.
831 *******************************************************************************/
833 static arraydescriptor *link_array(classinfo *c)
837 arraydescriptor *desc;
842 namelen = c->name->blength;
844 /* Check the component type */
846 switch (c->name->text[1]) {
848 /* c is an array of arrays. */
849 u = utf_new(c->name->text + 1, namelen - 1);
850 if (!(comp = load_class_from_classloader(u, c->classloader)))
855 /* c is an array of objects. */
856 u = utf_new(c->name->text + 2, namelen - 3);
857 if (!(comp = load_class_from_classloader(u, c->classloader)))
862 /* If the component type has not been linked, link it now */
863 assert(!comp || comp->loaded);
864 if (comp && !comp->linked) {
866 if (!link_class(comp))
870 /* Allocate the arraydescriptor */
871 desc = NEW(arraydescriptor);
874 /* c is an array of references */
875 desc->arraytype = ARRAYTYPE_OBJECT;
876 desc->componentsize = sizeof(void*);
877 desc->dataoffset = OFFSET(java_objectarray, data);
879 compvftbl = comp->vftbl;
882 log_text("Component class has no vftbl");
886 desc->componentvftbl = compvftbl;
888 if (compvftbl->arraydesc) {
889 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
891 if (compvftbl->arraydesc->dimension >= 255) {
892 log_text("Creating array of dimension >255");
896 desc->dimension = compvftbl->arraydesc->dimension + 1;
897 desc->elementtype = compvftbl->arraydesc->elementtype;
900 desc->elementvftbl = compvftbl;
902 desc->elementtype = ARRAYTYPE_OBJECT;
906 /* c is an array of a primitive type */
907 switch (c->name->text[1]) {
909 desc->arraytype = ARRAYTYPE_BOOLEAN;
910 desc->dataoffset = OFFSET(java_booleanarray,data);
911 desc->componentsize = sizeof(u1);
915 desc->arraytype = ARRAYTYPE_BYTE;
916 desc->dataoffset = OFFSET(java_bytearray,data);
917 desc->componentsize = sizeof(u1);
921 desc->arraytype = ARRAYTYPE_CHAR;
922 desc->dataoffset = OFFSET(java_chararray,data);
923 desc->componentsize = sizeof(u2);
927 desc->arraytype = ARRAYTYPE_DOUBLE;
928 desc->dataoffset = OFFSET(java_doublearray,data);
929 desc->componentsize = sizeof(double);
933 desc->arraytype = ARRAYTYPE_FLOAT;
934 desc->dataoffset = OFFSET(java_floatarray,data);
935 desc->componentsize = sizeof(float);
939 desc->arraytype = ARRAYTYPE_INT;
940 desc->dataoffset = OFFSET(java_intarray,data);
941 desc->componentsize = sizeof(s4);
945 desc->arraytype = ARRAYTYPE_LONG;
946 desc->dataoffset = OFFSET(java_longarray,data);
947 desc->componentsize = sizeof(s8);
951 desc->arraytype = ARRAYTYPE_SHORT;
952 desc->dataoffset = OFFSET(java_shortarray,data);
953 desc->componentsize = sizeof(s2);
957 *exceptionptr = new_noclassdeffounderror(c->name);
961 desc->componentvftbl = NULL;
962 desc->elementvftbl = NULL;
964 desc->elementtype = desc->arraytype;
971 /* linker_compute_subclasses ***************************************************
975 *******************************************************************************/
977 static void linker_compute_subclasses(classinfo *c)
979 #if defined(USE_THREADS)
980 #if defined(NATIVE_THREADS)
987 if (!(c->flags & ACC_INTERFACE)) {
992 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
993 c->nextsub = c->super.cls->sub;
994 c->super.cls->sub = c;
999 /* compute class values */
1001 linker_compute_class_values(class_java_lang_Object);
1003 #if defined(USE_THREADS)
1004 #if defined(NATIVE_THREADS)
1013 /* linker_compute_class_values *************************************************
1017 *******************************************************************************/
1019 static void linker_compute_class_values(classinfo *c)
1023 c->vftbl->baseval = ++classvalue;
1028 linker_compute_class_values(subs);
1030 subs = subs->nextsub;
1033 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1037 /* linker_addinterface *********************************************************
1039 Is needed by link_class for adding a VTBL to a class. All
1040 interfaces implemented by ic are added as well.
1042 *******************************************************************************/
1044 static void linker_addinterface(classinfo *c, classinfo *ic)
1048 vftbl_t *v = c->vftbl;
1050 if (i >= v->interfacetablelength) {
1051 log_text("Inernal error: interfacetable overflow");
1055 if (v->interfacetable[-i])
1058 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1059 v->interfacevftbllength[i] = 1;
1060 v->interfacetable[-i] = MNEW(methodptr, 1);
1061 v->interfacetable[-i][0] = NULL;
1064 v->interfacevftbllength[i] = ic->methodscount;
1065 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1067 #if defined(STATISTICS)
1069 count_vftbl_len += sizeof(methodptr) *
1070 (ic->methodscount + (ic->methodscount == 0));
1073 for (j = 0; j < ic->methodscount; j++) {
1077 for (m = 0; m < sc->methodscount; m++) {
1078 methodinfo *mi = &(sc->methods[m]);
1080 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1081 v->interfacetable[-i][j] = v->table[mi->vftblindex];
1092 for (j = 0; j < ic->interfacescount; j++)
1093 linker_addinterface(c, ic->interfaces[j].cls);
1097 /* class_highestinterface ******************************************************
1099 Used by the function link_class to determine the amount of memory
1100 needed for the interface table.
1102 *******************************************************************************/
1104 static s4 class_highestinterface(classinfo *c)
1110 /* check for ACC_INTERFACE bit already done in link_class_intern */
1114 for (i = 0; i < c->interfacescount; i++) {
1115 h2 = class_highestinterface(c->interfaces[i].cls);
1126 * These are local overrides for various environment variables in Emacs.
1127 * Please do not remove this and leave it at the end of the file, where
1128 * Emacs will automagically detect them.
1129 * ---------------------------------------------------------------------
1132 * indent-tabs-mode: t