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