4ff12a5ac238ac2e9e95e413b1309f8f8cb05adb
[cacao.git] / src / vm / linker.c
1 /* src/vm/linker.c - class linker functions
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Andreas Krall
30             Roman Obermaiser
31             Mark Probst
32             Edwin Steiner
33             Christian Thalinger
34
35    $Id: linker.c 2169 2005-03-31 15:50:57Z twisti $
36
37 */
38
39
40 #include "mm/memory.h"
41 #include "native/native.h"
42 #include "vm/builtin.h"
43 #include "vm/class.h"
44 #include "vm/exceptions.h"
45 #include "vm/loader.h"
46 #include "vm/options.h"
47 #include "vm/statistics.h"
48 #include "vm/jit/codegen.inc.h"
49
50
51 /* global variables ***********************************************************/
52
53 static s4 interfaceindex;       /* sequential numbering of interfaces         */
54 static s4 classvalue;
55
56
57 /* primitivetype_table *********************************************************
58
59    Structure for primitive classes: contains the class for wrapping
60    the primitive type, the primitive class, the name of the class for
61    wrapping, the one character type signature and the name of the
62    primitive class.
63  
64    CAUTION: Don't change the order of the types. This table is indexed
65    by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
66
67 *******************************************************************************/
68
69 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
70         { NULL, NULL, "java/lang/Integer",   'I', "int"     , "[I", NULL, NULL },
71         { NULL, NULL, "java/lang/Long",      'J', "long"    , "[J", NULL, NULL },
72         { NULL, NULL, "java/lang/Float",     'F', "float"   , "[F", NULL, NULL },
73         { NULL, NULL, "java/lang/Double",    'D', "double"  , "[D", NULL, NULL },
74         { NULL, NULL, "java/lang/Byte",      'B', "byte"    , "[B", NULL, NULL },
75         { NULL, NULL, "java/lang/Character", 'C', "char"    , "[C", NULL, NULL },
76         { NULL, NULL, "java/lang/Short",     'S', "short"   , "[S", NULL, NULL },
77         { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" , "[Z", NULL, NULL },
78         { NULL, NULL, "java/lang/Void",      'V', "void"    , NULL, NULL, NULL }
79 };
80
81
82 /* private functions **********************************************************/
83
84 static bool link_primitivetype_table(void);
85 static classinfo *link_class_intern(classinfo *c);
86 static arraydescriptor *link_array(classinfo *c);
87 static void linker_compute_class_values(classinfo *c);
88 static void linker_compute_subclasses(classinfo *c);
89 static void linker_addinterface(classinfo *c, classinfo *ic);
90 static s4 class_highestinterface(classinfo *c);
91
92
93 /* linker_init *****************************************************************
94
95    Initializes the linker subsystem.
96
97 *******************************************************************************/
98
99 bool linker_init(void)
100 {
101         /* reset interface index */
102
103         interfaceindex = 0;
104
105         /* link important system classes */
106
107         if (!link_class(class_java_lang_Object))
108                 return false;
109
110         if (!link_class(class_java_lang_String))
111                 return false;
112
113         if (!link_class(class_java_lang_Cloneable))
114                 return false;
115
116         if (!link_class(class_java_io_Serializable))
117                 return false;
118
119
120         /* link classes for wrapping primitive types */
121
122         if (!link_class(class_java_lang_Void))
123                 return false;
124
125         if (!link_class(class_java_lang_Boolean))
126                 return false;
127
128         if (!link_class(class_java_lang_Byte))
129                 return false;
130
131         if (!link_class(class_java_lang_Character))
132                 return false;
133
134         if (!link_class(class_java_lang_Short))
135                 return false;
136
137         if (!link_class(class_java_lang_Integer))
138                 return false;
139
140         if (!link_class(class_java_lang_Long))
141                 return false;
142
143         if (!link_class(class_java_lang_Float))
144                 return false;
145
146         if (!link_class(class_java_lang_Double))
147                 return false;
148
149
150         /* create pseudo classes used by the typechecker */
151
152     /* pseudo class for Arraystubs (extends java.lang.Object) */
153     
154         pseudo_class_Arraystub->loaded = true;
155     pseudo_class_Arraystub->super = class_java_lang_Object;
156     pseudo_class_Arraystub->interfacescount = 2;
157     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
158     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
159     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
160
161     if (!link_class(pseudo_class_Arraystub))
162                 return false;
163
164     /* pseudo class representing the null type */
165     
166         pseudo_class_Null->loaded = true;
167     pseudo_class_Null->super = class_java_lang_Object;
168
169         if (!link_class(pseudo_class_Null))
170                 return false;
171
172     /* pseudo class representing new uninitialized objects */
173     
174         pseudo_class_New->loaded = true;
175         pseudo_class_New->linked = true;
176         pseudo_class_New->super = class_java_lang_Object;
177
178
179         /* create classes representing primitive types */
180
181         if (!link_primitivetype_table())
182                 return false;
183
184
185         /* Correct vftbl-entries (retarded loading and linking of class           */
186         /* java/lang/String).                                                     */
187
188         stringtable_update();
189
190         return true;
191 }
192
193
194 /* link_primitivetype_table ****************************************************
195
196    Create classes representing primitive types.
197
198 *******************************************************************************/
199
200 static bool link_primitivetype_table(void)
201 {  
202         classinfo *c;
203         s4 i;
204
205         for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
206                 /* create primitive class */
207                 c = class_new_intern(utf_new_char(primitivetype_table[i].name));
208                 c->classUsed = NOTUSED; /* not used initially CO-RT */
209                 c->impldBy = NULL;
210                 
211                 /* prevent loader from loading primitive class */
212                 c->loaded = true;
213                 if (!link_class(c))
214                         return false;
215
216                 primitivetype_table[i].class_primitive = c;
217
218                 /* create class for wrapping the primitive type */
219                 c = class_new_intern(utf_new_char(primitivetype_table[i].wrapname));
220                 primitivetype_table[i].class_wrap = c;
221                 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
222                 primitivetype_table[i].class_wrap->impldBy = NULL;
223
224                 /* create the primitive array class */
225                 if (primitivetype_table[i].arrayname) {
226                         c = class_new_intern(utf_new_char(primitivetype_table[i].arrayname));
227                         primitivetype_table[i].arrayclass = c;
228                         c->loaded = true;
229                         if (!c->linked)
230                                 if (!link_class(c))
231                                         return false;
232                         primitivetype_table[i].arrayvftbl = c->vftbl;
233                 }
234         }
235
236         return true;
237 }
238
239
240 /* link_class ******************************************************************
241
242    Wrapper function for link_class_intern to ease monitor enter/exit
243    and exception handling.
244
245 *******************************************************************************/
246
247 classinfo *link_class(classinfo *c)
248 {
249         classinfo *r;
250
251 #if defined(USE_THREADS)
252         /* enter a monitor on the class */
253
254         builtin_monitorenter((java_objectheader *) c);
255 #endif
256
257         /* maybe the class is already linked */
258         if (c->linked) {
259 #if defined(USE_THREADS)
260                 builtin_monitorexit((java_objectheader *) c);
261 #endif
262
263                 return c;
264         }
265
266 #if defined(STATISTICS)
267         /* measure time */
268
269         if (getcompilingtime)
270                 compilingtime_stop();
271
272         if (getloadingtime)
273                 loadingtime_start();
274 #endif
275
276         /* call the internal function */
277         r = link_class_intern(c);
278
279         /* if return value is NULL, we had a problem and the class is not linked */
280         if (!r)
281                 c->linked = false;
282
283 #if defined(STATISTICS)
284         /* measure time */
285
286         if (getloadingtime)
287                 loadingtime_stop();
288
289         if (getcompilingtime)
290                 compilingtime_start();
291 #endif
292
293 #if defined(USE_THREADS)
294         /* leave the monitor */
295
296         builtin_monitorexit((java_objectheader *) c);
297 #endif
298
299         return r;
300 }
301
302
303 /* link_class_intern ***********************************************************
304
305    Tries to link a class. The function calculates the length in bytes
306    that an instance of this class requires as well as the VTBL for
307    methods and interface methods.
308         
309 *******************************************************************************/
310
311 static classinfo *link_class_intern(classinfo *c)
312 {
313         classinfo *super;             /* super class                              */
314         classinfo *tc;                /* temporary class variable                 */
315         s4 supervftbllength;          /* vftbllegnth of super class               */
316         s4 vftbllength;               /* vftbllength of current class             */
317         s4 interfacetablelength;      /* interface table length                   */
318         vftbl_t *v;                   /* vftbl of current class                   */
319         s4 i;                         /* interface/method/field counter           */
320         arraydescriptor *arraydesc;   /* descriptor for array classes             */
321
322         /* maybe the class is already linked */
323         if (c->linked)
324                 return c;
325
326         /* the class must be loaded */
327         if (!c->loaded)
328                 throw_cacao_exception_exit(string_java_lang_InternalError,
329                                                                    "Trying to link unloaded class");
330
331         if (linkverbose)
332                 log_message_class("Linking class: ", c);
333
334         /* ok, this class is somewhat linked */
335         c->linked = true;
336
337         arraydesc = NULL;
338
339         /* check interfaces */
340
341         for (i = 0; i < c->interfacescount; i++) {
342                 tc = c->interfaces[i];
343
344                 /* detect circularity */
345
346                 if (tc == c) {
347                         *exceptionptr =
348                                 new_exception_utfmessage(string_java_lang_ClassCircularityError,
349                                                                                  c->name);
350                         return NULL;
351                 }
352
353                 if (!tc->loaded)
354                         if (!load_class_from_classloader(tc, c->classloader))
355                                 return NULL;
356
357                 if (!(tc->flags & ACC_INTERFACE)) {
358                         *exceptionptr =
359                                 new_exception_message(string_java_lang_IncompatibleClassChangeError,
360                                                                           "Implementing class");
361                         return NULL;
362                 }
363
364                 if (!tc->linked)
365                         if (!link_class(tc))
366                                 return NULL;
367         }
368         
369         /* check super class */
370
371         super = c->super;
372
373         if (super == NULL) {          /* class java.lang.Object */
374                 c->index = 0;
375         c->classUsed = USED;     /* Object class is always used CO-RT*/
376                 c->impldBy = NULL;
377                 c->instancesize = sizeof(java_objectheader);
378                 
379                 vftbllength = supervftbllength = 0;
380
381                 c->finalizer = NULL;
382
383         } else {
384                 /* detect circularity */
385                 if (super == c) {
386                         *exceptionptr =
387                                 new_exception_utfmessage(string_java_lang_ClassCircularityError,
388                                                                                  c->name);
389                         return NULL;
390                 }
391
392                 if (!super->loaded)
393                         if (!load_class_from_classloader(super, c->classloader))
394                                 return NULL;
395
396                 if (super->flags & ACC_INTERFACE) {
397                         /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
398                         panic("Interface specified as super class");
399                 }
400
401                 /* Don't allow extending final classes */
402                 if (super->flags & ACC_FINAL) {
403                         *exceptionptr =
404                                 new_exception_message(string_java_lang_VerifyError,
405                                                                           "Cannot inherit from final class");
406                         return NULL;
407                 }
408                 
409                 if (!super->linked)
410                         if (!link_class(super))
411                                 return NULL;
412
413                 /* handle array classes */
414                 if (c->name->text[0] == '[')
415                         if (!(arraydesc = link_array(c)))
416                                 return NULL;
417
418                 if (c->flags & ACC_INTERFACE)
419                         c->index = interfaceindex++;
420                 else
421                         c->index = super->index + 1;
422                 
423                 c->instancesize = super->instancesize;
424                 
425                 vftbllength = supervftbllength = super->vftbl->vftbllength;
426                 
427                 c->finalizer = super->finalizer;
428         }
429
430
431         /* compute vftbl length */
432
433         for (i = 0; i < c->methodscount; i++) {
434                 methodinfo *m = &(c->methods[i]);
435
436                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
437                         tc = super;
438
439                         while (tc) {
440                                 s4 j;
441
442                                 for (j = 0; j < tc->methodscount; j++) {
443                                         if (method_canoverwrite(m, &(tc->methods[j]))) {
444                                                 if (tc->methods[j].flags & ACC_PRIVATE)
445                                                         goto notfoundvftblindex;
446
447                                                 if (tc->methods[j].flags & ACC_FINAL) {
448                                                         /* class a overrides final method . */
449                                                         *exceptionptr =
450                                                                 new_exception(string_java_lang_VerifyError);
451                                                         return NULL;
452                                                 }
453
454                                                 m->vftblindex = tc->methods[j].vftblindex;
455                                                 goto foundvftblindex;
456                                         }
457                                 }
458
459                                 tc = tc->super;
460                         }
461
462                 notfoundvftblindex:
463                         m->vftblindex = (vftbllength++);
464                 foundvftblindex:
465                         ;
466                 }
467         }       
468
469
470         /* check interfaces of ABSTRACT class for unimplemented methods */
471
472         if (c->flags & ACC_ABSTRACT) {
473                 classinfo  *ic;
474                 methodinfo *im;
475                 s4 abstractmethodscount;
476                 s4 j;
477                 s4 k;
478
479                 abstractmethodscount = 0;
480
481                 for (i = 0; i < c->interfacescount; i++) {
482                         ic = c->interfaces[i];
483
484                         for (j = 0; j < ic->methodscount; j++) {
485                                 im = &(ic->methods[j]);
486
487                                 /* skip `<clinit>' and `<init>' */
488
489                                 if (im->name == utf_clinit || im->name == utf_init)
490                                         continue;
491
492                                 tc = c;
493
494                                 while (tc) {
495                                         for (k = 0; k < tc->methodscount; k++) {
496                                                 if (method_canoverwrite(im, &(tc->methods[k])))
497                                                         goto noabstractmethod;
498                                         }
499
500                                         tc = tc->super;
501                                 }
502
503                                 abstractmethodscount++;
504
505                         noabstractmethod:
506                                 ;
507                         }
508                 }
509
510                 if (abstractmethodscount > 0) {
511                         methodinfo *am;
512
513                         /* reallocate methods memory */
514
515                         c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
516                                                                   c->methodscount + abstractmethodscount);
517
518                         for (i = 0; i < c->interfacescount; i++) {
519                                 ic = c->interfaces[i];
520
521                                 for (j = 0; j < ic->methodscount; j++) {
522                                         im = &(ic->methods[j]);
523
524                                         /* skip `<clinit>' and `<init>' */
525
526                                         if (im->name == utf_clinit || im->name == utf_init)
527                                                 continue;
528
529                                         tc = c;
530
531                                         while (tc) {
532                                                 for (k = 0; k < tc->methodscount; k++) {
533                                                         if (method_canoverwrite(im, &(tc->methods[k])))
534                                                                 goto noabstractmethod2;
535                                                 }
536
537                                                 tc = tc->super;
538                                         }
539
540                                         am = &(c->methods[c->methodscount]);
541                                         c->methodscount++;
542
543                                         MCOPY(am, im, methodinfo, 1);
544
545                                         am->vftblindex = (vftbllength++);
546                                         am->class = c;
547
548                                 noabstractmethod2:
549                                         ;
550                                 }
551                         }
552                 }
553         }
554
555
556 #if defined(STATISTICS)
557         if (opt_stat)
558                 count_vftbl_len +=
559                         sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
560 #endif
561
562         /* compute interfacetable length */
563
564         interfacetablelength = 0;
565         tc = c;
566         while (tc) {
567                 for (i = 0; i < tc->interfacescount; i++) {
568                         s4 h = class_highestinterface(tc->interfaces[i]) + 1;
569                         if (h > interfacetablelength)
570                                 interfacetablelength = h;
571                 }
572                 tc = tc->super;
573         }
574
575         /* allocate virtual function table */
576
577         v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
578                                                           sizeof(methodptr) * (vftbllength - 1) +
579                                                           sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
580         v = (vftbl_t *) (((methodptr *) v) +
581                                          (interfacetablelength - 1) * (interfacetablelength > 1));
582         c->header.vftbl = c->vftbl = v;
583         v->class = c;
584         v->vftbllength = vftbllength;
585         v->interfacetablelength = interfacetablelength;
586         v->arraydesc = arraydesc;
587
588         /* store interface index in vftbl */
589
590         if (c->flags & ACC_INTERFACE)
591                 v->baseval = -(c->index);
592
593         /* copy virtual function table of super class */
594
595         for (i = 0; i < supervftbllength; i++) 
596                 v->table[i] = super->vftbl->table[i];
597         
598         /* add method stubs into virtual function table */
599
600         for (i = 0; i < c->methodscount; i++) {
601                 methodinfo *m = &(c->methods[i]);
602
603                 /* Methods in ABSTRACT classes from interfaces maybe already have a   */
604                 /* stubroutine.                                                       */
605
606                 if (!m->stubroutine) {
607                         if (!(m->flags & ACC_NATIVE)) {
608                                 m->stubroutine = createcompilerstub(m);
609
610                         } else {
611                                 functionptr f = native_findfunction(c->name,
612                                                                                 m->name,
613                                                                                 m->descriptor,
614                                                                                 (m->flags & ACC_STATIC));
615 #if defined(STATIC_CLASSPATH)
616                                 if (f)
617 #endif
618                                         m->stubroutine = createnativestub(f, m);
619                         }
620                 }
621
622                 if (!(m->flags & ACC_STATIC))
623                         v->table[m->vftblindex] = m->stubroutine;
624         }
625
626         /* compute instance size and offset of each field */
627         
628         for (i = 0; i < c->fieldscount; i++) {
629                 s4 dsize;
630                 fieldinfo *f = &(c->fields[i]);
631                 
632                 if (!(f->flags & ACC_STATIC)) {
633                         dsize = desc_typesize(f->descriptor);
634                         c->instancesize = ALIGN(c->instancesize, dsize);
635                         f->offset = c->instancesize;
636                         c->instancesize += dsize;
637                 }
638         }
639
640         /* initialize interfacetable and interfacevftbllength */
641         
642         v->interfacevftbllength = MNEW(s4, interfacetablelength);
643
644 #if defined(STATISTICS)
645         if (opt_stat)
646                 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
647 #endif
648
649         for (i = 0; i < interfacetablelength; i++) {
650                 v->interfacevftbllength[i] = 0;
651                 v->interfacetable[-i] = NULL;
652         }
653         
654         /* add interfaces */
655         
656         for (tc = c; tc != NULL; tc = tc->super)
657                 for (i = 0; i < tc->interfacescount; i++)
658                         linker_addinterface(c, tc->interfaces[i]);
659
660         /* add finalizer method (not for java.lang.Object) */
661
662         if (super) {
663                 methodinfo *fi;
664
665                 fi = class_findmethod(c, utf_finalize, utf_void__void);
666
667                 if (fi)
668                         if (!(fi->flags & ACC_STATIC))
669                                 c->finalizer = fi;
670         }
671
672         /* final tasks */
673
674         linker_compute_subclasses(c);
675
676         if (linkverbose)
677                 log_message_class("Linking done class: ", c);
678
679         /* just return c to show that we didn't had a problem */
680
681         return c;
682 }
683
684
685 /* link_array ******************************************************************
686
687    This function is called by link_class to create the arraydescriptor
688    for an array class.
689
690    This function returns NULL if the array cannot be linked because
691    the component type has not been linked yet.
692
693 *******************************************************************************/
694
695 static arraydescriptor *link_array(classinfo *c)
696 {
697         classinfo *comp = NULL;
698         s4 namelen = c->name->blength;
699         arraydescriptor *desc;
700         vftbl_t *compvftbl;
701
702         /* Check the component type */
703         switch (c->name->text[1]) {
704         case '[':
705                 /* c is an array of arrays. */
706                 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
707                 if (!comp)
708                         panic("Could not find component array class.");
709                 break;
710
711         case 'L':
712                 /* c is an array of objects. */
713                 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
714                 if (!comp)
715                         panic("Could not find component class.");
716                 break;
717         }
718
719         /* If the component type has not been linked, link it now */
720         if (comp && !comp->linked) {
721                 if (!comp->loaded)
722                         if (!load_class_from_classloader(comp, c->classloader))
723                                 return NULL;
724
725                 if (!link_class(comp))
726                         return NULL;
727         }
728
729         /* Allocate the arraydescriptor */
730         desc = NEW(arraydescriptor);
731
732         if (comp) {
733                 /* c is an array of references */
734                 desc->arraytype = ARRAYTYPE_OBJECT;
735                 desc->componentsize = sizeof(void*);
736                 desc->dataoffset = OFFSET(java_objectarray, data);
737                 
738                 compvftbl = comp->vftbl;
739                 if (!compvftbl)
740                         panic("Component class has no vftbl");
741                 desc->componentvftbl = compvftbl;
742                 
743                 if (compvftbl->arraydesc) {
744                         desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
745                         if (compvftbl->arraydesc->dimension >= 255)
746                                 panic("Creating array of dimension >255");
747                         desc->dimension = compvftbl->arraydesc->dimension + 1;
748                         desc->elementtype = compvftbl->arraydesc->elementtype;
749
750                 } else {
751                         desc->elementvftbl = compvftbl;
752                         desc->dimension = 1;
753                         desc->elementtype = ARRAYTYPE_OBJECT;
754                 }
755
756         } else {
757                 /* c is an array of a primitive type */
758                 switch (c->name->text[1]) {
759                 case 'Z':
760                         desc->arraytype = ARRAYTYPE_BOOLEAN;
761                         desc->dataoffset = OFFSET(java_booleanarray,data);
762                         desc->componentsize = sizeof(u1);
763                         break;
764
765                 case 'B':
766                         desc->arraytype = ARRAYTYPE_BYTE;
767                         desc->dataoffset = OFFSET(java_bytearray,data);
768                         desc->componentsize = sizeof(u1);
769                         break;
770
771                 case 'C':
772                         desc->arraytype = ARRAYTYPE_CHAR;
773                         desc->dataoffset = OFFSET(java_chararray,data);
774                         desc->componentsize = sizeof(u2);
775                         break;
776
777                 case 'D':
778                         desc->arraytype = ARRAYTYPE_DOUBLE;
779                         desc->dataoffset = OFFSET(java_doublearray,data);
780                         desc->componentsize = sizeof(double);
781                         break;
782
783                 case 'F':
784                         desc->arraytype = ARRAYTYPE_FLOAT;
785                         desc->dataoffset = OFFSET(java_floatarray,data);
786                         desc->componentsize = sizeof(float);
787                         break;
788
789                 case 'I':
790                         desc->arraytype = ARRAYTYPE_INT;
791                         desc->dataoffset = OFFSET(java_intarray,data);
792                         desc->componentsize = sizeof(s4);
793                         break;
794
795                 case 'J':
796                         desc->arraytype = ARRAYTYPE_LONG;
797                         desc->dataoffset = OFFSET(java_longarray,data);
798                         desc->componentsize = sizeof(s8);
799                         break;
800
801                 case 'S':
802                         desc->arraytype = ARRAYTYPE_SHORT;
803                         desc->dataoffset = OFFSET(java_shortarray,data);
804                         desc->componentsize = sizeof(s2);
805                         break;
806
807                 default:
808                         panic("Invalid array class name");
809                 }
810                 
811                 desc->componentvftbl = NULL;
812                 desc->elementvftbl = NULL;
813                 desc->dimension = 1;
814                 desc->elementtype = desc->arraytype;
815         }
816
817         return desc;
818 }
819
820
821 /* linker_compute_subclasses ***************************************************
822
823    XXX
824
825 *******************************************************************************/
826
827 static void linker_compute_subclasses(classinfo *c)
828 {
829 #if defined(USE_THREADS)
830 #if defined(NATIVE_THREADS)
831         compiler_lock();
832 #else
833         intsDisable();
834 #endif
835 #endif
836
837         if (!(c->flags & ACC_INTERFACE)) {
838                 c->nextsub = 0;
839                 c->sub = 0;
840         }
841
842         if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
843                 c->nextsub = c->super->sub;
844                 c->super->sub = c;
845         }
846
847         classvalue = 0;
848
849         /* this is the java.lang.Object special case */
850
851         if (!class_java_lang_Object) {
852                 linker_compute_class_values(c);
853
854         } else {
855                 linker_compute_class_values(class_java_lang_Object);
856         }
857
858 #if defined(USE_THREADS)
859 #if defined(NATIVE_THREADS)
860         compiler_unlock();
861 #else
862         intsRestore();
863 #endif
864 #endif
865 }
866
867
868 /* linker_compute_class_values *************************************************
869
870    XXX
871
872 *******************************************************************************/
873
874 static void linker_compute_class_values(classinfo *c)
875 {
876         classinfo *subs;
877
878         c->vftbl->baseval = ++classvalue;
879
880         subs = c->sub;
881
882         while (subs) {
883                 linker_compute_class_values(subs);
884
885                 subs = subs->nextsub;
886         }
887
888         c->vftbl->diffval = classvalue - c->vftbl->baseval;
889 }
890
891
892 /* linker_addinterface *********************************************************
893
894    Is needed by link_class for adding a VTBL to a class. All
895    interfaces implemented by ic are added as well.
896
897 *******************************************************************************/
898
899 static void linker_addinterface(classinfo *c, classinfo *ic)
900 {
901         s4     j, m;
902         s4     i   = ic->index;
903         vftbl_t *v = c->vftbl;
904
905         if (i >= v->interfacetablelength)
906                 panic ("Inernal error: interfacetable overflow");
907
908         if (v->interfacetable[-i])
909                 return;
910
911         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
912                 v->interfacevftbllength[i] = 1;
913                 v->interfacetable[-i] = MNEW(methodptr, 1);
914                 v->interfacetable[-i][0] = NULL;
915
916         } else {
917                 v->interfacevftbllength[i] = ic->methodscount;
918                 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
919
920 #if defined(STATISTICS)
921                 if (opt_stat)
922                         count_vftbl_len += sizeof(methodptr) *
923                                 (ic->methodscount + (ic->methodscount == 0));
924 #endif
925
926                 for (j = 0; j < ic->methodscount; j++) {
927                         classinfo *sc = c;
928
929                         while (sc) {
930                                 for (m = 0; m < sc->methodscount; m++) {
931                                         methodinfo *mi = &(sc->methods[m]);
932
933                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
934                                                 v->interfacetable[-i][j] = v->table[mi->vftblindex];
935                                                 goto foundmethod;
936                                         }
937                                 }
938                                 sc = sc->super;
939                         }
940                 foundmethod:
941                         ;
942                 }
943         }
944
945         for (j = 0; j < ic->interfacescount; j++) 
946                 linker_addinterface(c, ic->interfaces[j]);
947 }
948
949
950 /* class_highestinterface ******************************************************
951
952    Used by the function link_class to determine the amount of memory
953    needed for the interface table.
954
955 *******************************************************************************/
956
957 static s4 class_highestinterface(classinfo *c)
958 {
959         s4 h;
960         s4 h2;
961         s4 i;
962         
963     /* check for ACC_INTERFACE bit already done in link_class_intern */
964
965     h = c->index;
966
967         for (i = 0; i < c->interfacescount; i++) {
968                 h2 = class_highestinterface(c->interfaces[i]);
969
970                 if (h2 > h)
971                         h = h2;
972         }
973
974         return h;
975 }
976
977
978 /*
979  * These are local overrides for various environment variables in Emacs.
980  * Please do not remove this and leave it at the end of the file, where
981  * Emacs will automagically detect them.
982  * ---------------------------------------------------------------------
983  * Local variables:
984  * mode: c
985  * indent-tabs-mode: t
986  * c-basic-offset: 4
987  * tab-width: 4
988  * End:
989  */