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