1 /* src/vmcore/linker.c - class linker functions
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: linker.c 8299 2007-08-13 08:41:18Z michi $
36 #include "mm/memory.h"
38 #include "native/native.h"
40 #include "threads/lock-common.h"
42 #include "toolbox/logging.h"
44 #include "vm/access.h"
45 #include "vm/exceptions.h"
46 #include "vm/primitive.h"
47 #include "vm/stringlocal.h"
50 #include "vm/jit_interface.h"
52 #include "vmcore/class.h"
53 #include "vmcore/classcache.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
56 #include "vmcore/rt-timing.h"
58 /* #include "vm/resolve.h" */
59 /* copied prototype to avoid bootstrapping problem: */
60 classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
62 #if defined(ENABLE_STATISTICS)
63 # include "vmcore/statistics.h"
66 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
67 #define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
69 #define INLINELOG(code)
73 /* global variables ***********************************************************/
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 java_object_t *linker_classrenumber_lock;
81 /* private functions **********************************************************/
83 static classinfo *link_class_intern(classinfo *c);
84 static arraydescriptor *link_array(classinfo *c);
85 static void linker_compute_class_values(classinfo *c);
86 static void linker_compute_subclasses(classinfo *c);
87 static bool linker_addinterface(classinfo *c, classinfo *ic);
88 static s4 class_highestinterface(classinfo *c);
91 /* dummy structures for alinment checks ***************************************/
93 typedef struct dummy_alignment_long_t dummy_alignment_long_t;
94 typedef struct dummy_alignment_double_t dummy_alignment_double_t;
96 struct dummy_alignment_long_t {
101 struct dummy_alignment_double_t {
107 /* linker_init *****************************************************************
109 Initializes the linker subsystem.
111 *******************************************************************************/
113 bool linker_init(void)
115 /* Check for if alignment for long and double matches what we
116 assume for the current architecture. */
118 #if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__))
119 if (OFFSET(dummy_alignment_long_t, l) != 4)
120 vm_abort("linker_init: long alignment is different from what assumed: %d != %d",
121 OFFSET(dummy_alignment_long_t, l), 4);
123 if (OFFSET(dummy_alignment_double_t, d) != 4)
124 vm_abort("linker_init: double alignment is different from what assumed: %d != %d",
125 OFFSET(dummy_alignment_double_t, d), 4);
127 if (OFFSET(dummy_alignment_long_t, l) != 8)
128 vm_abort("linker_init: long alignment is different from what assumed: %d != %d",
129 OFFSET(dummy_alignment_long_t, l), 8);
131 if (OFFSET(dummy_alignment_double_t, d) != 8)
132 vm_abort("linker_init: double alignment is different from what assumed: %d != %d",
133 OFFSET(dummy_alignment_double_t, d), 8);
136 /* reset interface index */
140 #if defined(ENABLE_THREADS)
141 /* create the global lock object */
143 linker_classrenumber_lock = NEW(java_object_t);
145 LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
148 /* link java.lang.Class as first class of the system, because we
149 need it's vftbl for all other classes so we can use a class as
152 if (!link_class(class_java_lang_Class))
155 /* now set the header.vftbl of all classes which were created
156 before java.lang.Class was linked */
158 class_postset_header_vftbl();
161 /* link important system classes */
163 if (!link_class(class_java_lang_Object))
166 if (!link_class(class_java_lang_String))
169 #if defined(ENABLE_JAVASE)
170 if (!link_class(class_java_lang_Cloneable))
173 if (!link_class(class_java_io_Serializable))
177 /* link classes for wrapping primitive types */
179 #if defined(ENABLE_JAVASE)
180 if (!link_class(class_java_lang_Void))
184 if (!link_class(class_java_lang_Boolean))
187 if (!link_class(class_java_lang_Byte))
190 if (!link_class(class_java_lang_Character))
193 if (!link_class(class_java_lang_Short))
196 if (!link_class(class_java_lang_Integer))
199 if (!link_class(class_java_lang_Long))
202 if (!link_class(class_java_lang_Float))
205 if (!link_class(class_java_lang_Double))
209 /* load some other important classes */
211 #if defined(ENABLE_JAVASE)
212 if (!link_class(class_java_lang_ClassLoader))
215 if (!link_class(class_java_lang_SecurityManager))
219 if (!link_class(class_java_lang_System))
222 if (!link_class(class_java_lang_Thread))
225 #if defined(ENABLE_JAVASE)
226 if (!link_class(class_java_lang_ThreadGroup))
230 #if defined(WITH_CLASSPATH_GNU)
231 if (!link_class(class_java_lang_VMSystem))
234 if (!link_class(class_java_lang_VMThread))
239 /* some classes which may be used more often */
241 #if defined(ENABLE_JAVASE)
242 if (!link_class(class_java_lang_StackTraceElement))
245 if (!link_class(class_java_lang_reflect_Constructor))
248 if (!link_class(class_java_lang_reflect_Field))
251 if (!link_class(class_java_lang_reflect_Method))
254 if (!link_class(class_java_security_PrivilegedAction))
257 if (!link_class(class_java_util_Vector))
260 # if defined(WITH_CLASSPATH_SUN)
261 if (!link_class(class_sun_reflect_MagicAccessorImpl))
265 if (!link_class(arrayclass_java_lang_Object))
270 /* create pseudo classes used by the typechecker */
272 /* pseudo class for Arraystubs (extends java.lang.Object) */
274 pseudo_class_Arraystub =
275 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
276 pseudo_class_Arraystub->state |= CLASS_LOADED;
277 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
279 #if defined(ENABLE_JAVASE)
280 pseudo_class_Arraystub->interfacescount = 2;
281 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
282 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
283 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
284 #elif defined(ENABLE_JAVAME_CLDC1_1)
285 pseudo_class_Arraystub->interfacescount = 0;
286 pseudo_class_Arraystub->interfaces = NULL;
289 if (!classcache_store_unique(pseudo_class_Arraystub)) {
290 log_text("could not cache pseudo_class_Arraystub");
294 if (!link_class(pseudo_class_Arraystub))
297 /* pseudo class representing the null type */
299 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
300 pseudo_class_Null->state |= CLASS_LOADED;
301 pseudo_class_Null->super.cls = class_java_lang_Object;
303 if (!classcache_store_unique(pseudo_class_Null))
304 vm_abort("linker_init: could not cache pseudo_class_Null");
306 if (!link_class(pseudo_class_Null))
309 /* pseudo class representing new uninitialized objects */
311 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
312 pseudo_class_New->state |= CLASS_LOADED;
313 pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
314 pseudo_class_New->super.cls = class_java_lang_Object;
316 if (!classcache_store_unique(pseudo_class_New))
317 vm_abort("linker_init: could not cache pseudo_class_New");
319 /* Correct vftbl-entries (retarded loading and linking of class
320 java/lang/String). */
322 stringtable_update();
328 /* link_class ******************************************************************
330 Wrapper function for link_class_intern to ease monitor enter/exit
331 and exception handling.
333 *******************************************************************************/
335 classinfo *link_class(classinfo *c)
338 #if defined(ENABLE_RT_TIMING)
339 struct timespec time_start, time_end;
342 RT_TIMING_GET_TIME(time_start);
345 exceptions_throw_nullpointerexception();
349 LOCK_MONITOR_ENTER(c);
351 /* maybe the class is already linked */
353 if (c->state & CLASS_LINKED) {
354 LOCK_MONITOR_EXIT(c);
359 #if defined(ENABLE_STATISTICS)
362 if (opt_getcompilingtime)
363 compilingtime_stop();
365 if (opt_getloadingtime)
369 /* call the internal function */
371 r = link_class_intern(c);
373 /* if return value is NULL, we had a problem and the class is not linked */
376 c->state &= ~CLASS_LINKING;
378 #if defined(ENABLE_STATISTICS)
381 if (opt_getloadingtime)
384 if (opt_getcompilingtime)
385 compilingtime_start();
388 LOCK_MONITOR_EXIT(c);
390 RT_TIMING_GET_TIME(time_end);
392 RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
398 /* linker_overwrite_method *****************************************************
400 Overwrite a method with another one, update method flags and check
404 mg................the general method being overwritten
405 ms................the overwriting (more specialized) method
406 wl................worklist where to add invalidated methods
409 true..............everything ok
410 false.............an exception has been thrown
412 *******************************************************************************/
414 static bool linker_overwrite_method(methodinfo *mg,
416 method_worklist **wl)
424 /* overriding a final method is illegal */
426 if (mg->flags & ACC_FINAL) {
427 exceptions_throw_verifyerror(mg, "Overriding final method");
431 /* method ms overwrites method mg */
433 #if defined(ENABLE_VERIFIER)
434 /* Add loading constraints (for the more general types of method mg). */
435 /* Not for <init>, as it is not invoked virtually. */
437 if ((ms->name != utf_init)
438 && !classcache_add_constraints_for_params(
439 cs->classloader, cg->classloader, mg))
445 /* inherit the vftbl index, and record the overwriting */
447 ms->vftblindex = mg->vftblindex;
450 /* update flags and check assumptions */
451 /* <init> methods are a special case, as they are never dispatched dynamically */
453 if ((ms->flags & ACC_METHOD_IMPLEMENTED) && ms->name != utf_init) {
455 if (mg->flags & ACC_METHOD_IMPLEMENTED) {
456 /* this adds another implementation */
458 mg->flags &= ~ACC_METHOD_MONOMORPHIC;
460 INLINELOG( printf("becomes polymorphic: "); method_println(mg); );
462 method_break_assumption_monomorphic(mg, wl);
465 /* this is the first implementation */
467 mg->flags |= ACC_METHOD_IMPLEMENTED;
469 INLINELOG( printf("becomes implemented: "); method_println(mg); );
474 } while (mg != NULL);
481 /* link_class_intern ***********************************************************
483 Tries to link a class. The function calculates the length in bytes
484 that an instance of this class requires as well as the VTBL for
485 methods and interface methods.
487 *******************************************************************************/
489 static classinfo *link_class_intern(classinfo *c)
491 classinfo *super; /* super class */
492 classinfo *tc; /* temporary class variable */
493 s4 supervftbllength; /* vftbllegnth of super class */
494 s4 vftbllength; /* vftbllength of current class */
495 s4 interfacetablelength; /* interface table length */
496 vftbl_t *v; /* vftbl of current class */
497 s4 i; /* interface/method/field counter */
498 arraydescriptor *arraydesc; /* descriptor for array classes */
499 method_worklist *worklist; /* worklist for recompilation */
500 #if defined(ENABLE_RT_TIMING)
501 struct timespec time_start, time_resolving, time_compute_vftbl,
502 time_abstract, time_compute_iftbl, time_fill_vftbl,
503 time_offsets, time_fill_iftbl, time_finalizer,
507 RT_TIMING_GET_TIME(time_start);
509 /* the class is already linked */
511 if (c->state & CLASS_LINKED)
516 log_message_class("Linking class: ", c);
519 /* the class must be loaded */
521 /* XXX should this be a specific exception? */
522 assert(c->state & CLASS_LOADED);
524 /* cache the self-reference of this class */
525 /* we do this for cases where the defining loader of the class */
526 /* has not yet been recorded as an initiating loader for the class */
527 /* this is needed so subsequent code can assume that self-refs */
528 /* will always resolve lazily */
529 /* No need to do it for the bootloader - it is always registered */
530 /* as initiating loader for the classes it loads. */
532 classcache_store(c->classloader,c,false);
534 /* this class is currently linking */
536 c->state |= CLASS_LINKING;
541 /* check interfaces */
543 for (i = 0; i < c->interfacescount; i++) {
544 /* resolve this super interface */
546 if ((tc = resolve_classref_or_classinfo_eager(c->interfaces[i], true)) == NULL)
549 c->interfaces[i].cls = tc;
551 /* detect circularity */
554 exceptions_throw_classcircularityerror(c);
558 assert(tc->state & CLASS_LOADED);
560 if (!(tc->flags & ACC_INTERFACE)) {
561 exceptions_throw_incompatibleclasschangeerror(tc,
562 "Implementing class");
566 if (!(tc->state & CLASS_LINKED))
571 /* check super class */
575 if (c->super.any == NULL) { /* class java.lang.Object */
577 c->instancesize = sizeof(java_object_t);
579 vftbllength = supervftbllength = 0;
584 /* resolve super class */
586 if ((super = resolve_classref_or_classinfo_eager(c->super, true)) == NULL)
589 c->super.cls = super;
591 /* detect circularity */
594 exceptions_throw_classcircularityerror(c);
598 assert(super->state & CLASS_LOADED);
600 if (super->flags & ACC_INTERFACE) {
601 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
602 log_text("Interface specified as super class");
606 /* Don't allow extending final classes */
608 if (super->flags & ACC_FINAL) {
609 exceptions_throw_verifyerror(NULL,
610 "Cannot inherit from final class");
614 /* link the superclass if necessary */
616 if (!(super->state & CLASS_LINKED))
617 if (!link_class(super))
620 /* OR the ACC_CLASS_HAS_POINTERS and the ACC_CLASS_REFERENCE_*
623 c->flags |= (super->flags &
624 (ACC_CLASS_HAS_POINTERS | ACC_CLASS_REFERENCE_MASK));
626 /* handle array classes */
628 if (c->name->text[0] == '[')
629 if (!(arraydesc = link_array(c)))
632 if (c->flags & ACC_INTERFACE)
633 c->index = interfaceindex++;
635 c->index = super->index + 1;
637 c->instancesize = super->instancesize;
639 vftbllength = supervftbllength = super->vftbl->vftbllength;
641 c->finalizer = super->finalizer;
643 RT_TIMING_GET_TIME(time_resolving);
646 /* compute vftbl length */
648 for (i = 0; i < c->methodscount; i++) {
649 methodinfo *m = &(c->methods[i]);
651 if (!(m->flags & ACC_STATIC)) { /* is instance method */
657 for (j = 0; j < tc->methodscount; j++) {
658 if (method_canoverwrite(m, &(tc->methods[j]))) {
659 if (tc->methods[j].flags & ACC_PRIVATE)
660 goto notfoundvftblindex;
662 /* package-private methods in other packages */
663 /* must not be overridden */
664 /* (see Java Language Specification 8.4.8.1) */
665 if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
666 && !SAME_PACKAGE(c,tc) )
668 goto notfoundvftblindex;
671 if (!linker_overwrite_method(&(tc->methods[j]), m, &worklist))
674 goto foundvftblindex;
682 m->vftblindex = (vftbllength++);
687 RT_TIMING_GET_TIME(time_compute_vftbl);
690 /* Check all interfaces of an abstract class (maybe be an
691 interface too) for unimplemented methods. Such methods are
692 called miranda-methods and are marked with the ACC_MIRANDA
693 flag. VMClass.getDeclaredMethods does not return such
696 if (c->flags & ACC_ABSTRACT) {
699 s4 abstractmethodscount;
703 abstractmethodscount = 0;
705 /* check all interfaces of the abstract class */
707 for (i = 0; i < c->interfacescount; i++) {
708 ic = c->interfaces[i].cls;
710 for (j = 0; j < ic->methodscount; j++) {
711 im = &(ic->methods[j]);
713 /* skip `<clinit>' and `<init>' */
715 if ((im->name == utf_clinit) || (im->name == utf_init))
718 for (tc = c; tc != NULL; tc = tc->super.cls) {
719 for (k = 0; k < tc->methodscount; k++) {
720 if (method_canoverwrite(im, &(tc->methods[k])))
721 goto noabstractmethod;
725 abstractmethodscount++;
732 if (abstractmethodscount > 0) {
735 /* reallocate methods memory */
737 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
738 c->methodscount + abstractmethodscount);
740 for (i = 0; i < c->interfacescount; i++) {
741 ic = c->interfaces[i].cls;
743 for (j = 0; j < ic->methodscount; j++) {
744 im = &(ic->methods[j]);
746 /* skip `<clinit>' and `<init>' */
748 if ((im->name == utf_clinit) || (im->name == utf_init))
751 for (tc = c; tc != NULL; tc = tc->super.cls) {
752 for (k = 0; k < tc->methodscount; k++) {
753 if (method_canoverwrite(im, &(tc->methods[k])))
754 goto noabstractmethod2;
758 /* Copy the method found into the new c->methods
759 array and tag it as miranda-method. */
761 am = &(c->methods[c->methodscount]);
764 MCOPY(am, im, methodinfo, 1);
766 am->vftblindex = (vftbllength++);
768 am->flags |= ACC_MIRANDA;
776 RT_TIMING_GET_TIME(time_abstract);
779 #if defined(ENABLE_STATISTICS)
782 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
785 /* compute interfacetable length */
787 interfacetablelength = 0;
789 for (tc = c; tc != NULL; tc = tc->super.cls) {
790 for (i = 0; i < tc->interfacescount; i++) {
791 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
793 if (h > interfacetablelength)
794 interfacetablelength = h;
797 RT_TIMING_GET_TIME(time_compute_iftbl);
799 /* allocate virtual function table */
801 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
802 sizeof(methodptr) * (vftbllength - 1) +
803 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
804 v = (vftbl_t *) (((methodptr *) v) +
805 (interfacetablelength - 1) * (interfacetablelength > 1));
809 v->vftbllength = vftbllength;
810 v->interfacetablelength = interfacetablelength;
811 v->arraydesc = arraydesc;
813 /* store interface index in vftbl */
815 if (c->flags & ACC_INTERFACE)
816 v->baseval = -(c->index);
818 /* copy virtual function table of super class */
820 for (i = 0; i < supervftbllength; i++)
821 v->table[i] = super->vftbl->table[i];
823 /* Fill the remaining vftbl slots with the AbstractMethodError
824 stub (all after the super class slots, because they are already
827 for (; i < vftbllength; i++) {
828 #if defined(ENABLE_JIT)
829 # if defined(ENABLE_INTRP)
831 v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
834 v->table[i] = (methodptr) (ptrint) &asm_abstractmethoderror;
836 v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
840 /* add method stubs into virtual function table */
842 for (i = 0; i < c->methodscount; i++) {
843 methodinfo *m = &(c->methods[i]);
845 assert(m->stubroutine == NULL);
847 /* Don't create a compiler stub for abstract methods as they
848 throw an AbstractMethodError with the default stub in the
849 vftbl. This entry is simply copied by sub-classes. */
851 if (m->flags & ACC_ABSTRACT)
854 #if defined(ENABLE_JIT)
855 # if defined(ENABLE_INTRP)
857 m->stubroutine = intrp_createcompilerstub(m);
860 m->stubroutine = codegen_generate_stub_compiler(m);
862 m->stubroutine = intrp_createcompilerstub(m);
865 /* static methods are not in the vftbl */
867 if (m->flags & ACC_STATIC)
870 /* insert the stubroutine into the vftbl */
872 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
874 RT_TIMING_GET_TIME(time_fill_vftbl);
876 /* compute instance size and offset of each field */
878 for (i = 0; i < c->fieldscount; i++) {
880 fieldinfo *f = &(c->fields[i]);
882 if (!(f->flags & ACC_STATIC)) {
883 dsize = descriptor_typesize(f->parseddesc);
885 #if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__))
886 /* On i386 and ARM we align double and s8 fields to
887 4-bytes. This matches what GCC does for struct
888 members. We must do the same as gcc here because the
889 offsets in native header structs like java_lang_Double
890 must match the offsets of the Java fields
891 (eg. java.lang.Double.value). */
893 c->instancesize = MEMORY_ALIGN(c->instancesize, 4);
895 c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
898 f->offset = c->instancesize;
899 c->instancesize += dsize;
902 RT_TIMING_GET_TIME(time_offsets);
904 /* initialize interfacetable and interfacevftbllength */
906 v->interfacevftbllength = MNEW(s4, interfacetablelength);
908 #if defined(ENABLE_STATISTICS)
910 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
913 for (i = 0; i < interfacetablelength; i++) {
914 v->interfacevftbllength[i] = 0;
915 v->interfacetable[-i] = NULL;
920 for (tc = c; tc != NULL; tc = tc->super.cls)
921 for (i = 0; i < tc->interfacescount; i++)
922 if (!linker_addinterface(c, tc->interfaces[i].cls))
925 RT_TIMING_GET_TIME(time_fill_iftbl);
927 /* add finalizer method (not for java.lang.Object) */
932 fi = class_findmethod(c, utf_finalize, utf_void__void);
935 if (!(fi->flags & ACC_STATIC))
938 RT_TIMING_GET_TIME(time_finalizer);
942 linker_compute_subclasses(c);
944 RT_TIMING_GET_TIME(time_subclasses);
946 /* revert the linking state and class is linked */
948 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
952 /* XXX must this also be done in case of exception? */
954 while (worklist != NULL) {
955 method_worklist *wi = worklist;
957 worklist = worklist->next;
959 INLINELOG( printf("MUST BE RECOMPILED: "); method_println(wi->m); );
960 jit_invalidate_code(wi->m);
962 /* XXX put worklist into dump memory? */
963 FREE(wi, method_worklist);
968 log_message_class("Linking done class: ", c);
971 RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
972 RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
973 RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
974 RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
975 RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
976 RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
977 RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
978 RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
979 RT_TIMING_TIME_DIFF(time_finalizer ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
981 /* just return c to show that we didn't had a problem */
987 /* link_array ******************************************************************
989 This function is called by link_class to create the arraydescriptor
992 This function returns NULL if the array cannot be linked because
993 the component type has not been linked yet.
995 *******************************************************************************/
997 static arraydescriptor *link_array(classinfo *c)
1001 arraydescriptor *desc;
1006 namelen = c->name->blength;
1008 /* Check the component type */
1010 switch (c->name->text[1]) {
1012 /* c is an array of arrays. */
1013 u = utf_new(c->name->text + 1, namelen - 1);
1014 if (!(comp = load_class_from_classloader(u, c->classloader)))
1019 /* c is an array of objects. */
1020 u = utf_new(c->name->text + 2, namelen - 3);
1021 if (!(comp = load_class_from_classloader(u, c->classloader)))
1026 /* If the component type has not been linked, link it now */
1028 assert(!comp || (comp->state & CLASS_LOADED));
1030 if (comp && !(comp->state & CLASS_LINKED))
1031 if (!link_class(comp))
1034 /* Allocate the arraydescriptor */
1036 desc = NEW(arraydescriptor);
1039 /* c is an array of references */
1040 desc->arraytype = ARRAYTYPE_OBJECT;
1041 desc->componentsize = sizeof(void*);
1042 desc->dataoffset = OFFSET(java_objectarray, data);
1044 compvftbl = comp->vftbl;
1047 log_text("Component class has no vftbl");
1051 desc->componentvftbl = compvftbl;
1053 if (compvftbl->arraydesc) {
1054 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1056 if (compvftbl->arraydesc->dimension >= 255) {
1057 log_text("Creating array of dimension >255");
1061 desc->dimension = compvftbl->arraydesc->dimension + 1;
1062 desc->elementtype = compvftbl->arraydesc->elementtype;
1065 desc->elementvftbl = compvftbl;
1066 desc->dimension = 1;
1067 desc->elementtype = ARRAYTYPE_OBJECT;
1071 /* c is an array of a primitive type */
1072 switch (c->name->text[1]) {
1074 desc->arraytype = ARRAYTYPE_BOOLEAN;
1075 desc->dataoffset = OFFSET(java_booleanarray,data);
1076 desc->componentsize = sizeof(u1);
1080 desc->arraytype = ARRAYTYPE_BYTE;
1081 desc->dataoffset = OFFSET(java_bytearray,data);
1082 desc->componentsize = sizeof(u1);
1086 desc->arraytype = ARRAYTYPE_CHAR;
1087 desc->dataoffset = OFFSET(java_chararray,data);
1088 desc->componentsize = sizeof(u2);
1092 desc->arraytype = ARRAYTYPE_DOUBLE;
1093 desc->dataoffset = OFFSET(java_doublearray,data);
1094 desc->componentsize = sizeof(double);
1098 desc->arraytype = ARRAYTYPE_FLOAT;
1099 desc->dataoffset = OFFSET(java_floatarray,data);
1100 desc->componentsize = sizeof(float);
1104 desc->arraytype = ARRAYTYPE_INT;
1105 desc->dataoffset = OFFSET(java_intarray,data);
1106 desc->componentsize = sizeof(s4);
1110 desc->arraytype = ARRAYTYPE_LONG;
1111 desc->dataoffset = OFFSET(java_longarray,data);
1112 desc->componentsize = sizeof(s8);
1116 desc->arraytype = ARRAYTYPE_SHORT;
1117 desc->dataoffset = OFFSET(java_shortarray,data);
1118 desc->componentsize = sizeof(s2);
1122 exceptions_throw_noclassdeffounderror(c->name);
1126 desc->componentvftbl = NULL;
1127 desc->elementvftbl = NULL;
1128 desc->dimension = 1;
1129 desc->elementtype = desc->arraytype;
1136 /* linker_compute_subclasses ***************************************************
1140 ATTENTION: DO NOT REMOVE ANY OF THE LOCKING MECHANISMS BELOW:
1141 This function needs to take the class renumber lock and stop the
1142 world during class renumbering. The lock is used in C code which
1143 is not that performance critical. Whereas JIT code uses critical
1144 sections to atomically access the class values.
1146 *******************************************************************************/
1148 static void linker_compute_subclasses(classinfo *c)
1150 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
1152 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
1153 threads_stopworld();
1156 if (!(c->flags & ACC_INTERFACE)) {
1161 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1162 c->nextsub = c->super.cls->sub;
1163 c->super.cls->sub = c;
1168 /* compute class values */
1170 linker_compute_class_values(class_java_lang_Object);
1172 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
1174 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
1175 threads_startworld();
1180 /* linker_compute_class_values *************************************************
1184 *******************************************************************************/
1186 static void linker_compute_class_values(classinfo *c)
1190 c->vftbl->baseval = ++classvalue;
1195 linker_compute_class_values(subs);
1197 subs = subs->nextsub;
1200 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1204 /* linker_addinterface *********************************************************
1206 Is needed by link_class for adding a VTBL to a class. All
1207 interfaces implemented by ic are added as well.
1210 true.........everything ok
1211 false........an exception has been thrown
1213 *******************************************************************************/
1215 static bool linker_addinterface(classinfo *c, classinfo *ic)
1226 if (i >= v->interfacetablelength)
1227 vm_abort("Internal error: interfacetable overflow");
1229 /* if this interface has already been added, return immediately */
1231 if (v->interfacetable[-i] != NULL)
1234 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1235 v->interfacevftbllength[i] = 1;
1236 v->interfacetable[-i] = MNEW(methodptr, 1);
1237 v->interfacetable[-i][0] = NULL;
1240 v->interfacevftbllength[i] = ic->methodscount;
1241 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1243 #if defined(ENABLE_STATISTICS)
1245 count_vftbl_len += sizeof(methodptr) *
1246 (ic->methodscount + (ic->methodscount == 0));
1249 for (j = 0; j < ic->methodscount; j++) {
1250 for (sc = c; sc != NULL; sc = sc->super.cls) {
1251 for (k = 0; k < sc->methodscount; k++) {
1252 m = &(sc->methods[k]);
1254 if (method_canoverwrite(m, &(ic->methods[j]))) {
1255 /* method m overwrites the (abstract) method */
1256 #if defined(ENABLE_VERIFIER)
1257 /* Add loading constraints (for the more
1258 general types of the method
1260 if (!classcache_add_constraints_for_params(
1261 c->classloader, ic->classloader,
1268 /* XXX taken from gcj */
1269 /* check for ACC_STATIC: IncompatibleClassChangeError */
1271 /* check for !ACC_PUBLIC: IllegalAccessError */
1273 /* check for ACC_ABSTRACT: AbstracMethodError,
1274 not sure about that one */
1276 v->interfacetable[-i][j] = v->table[m->vftblindex];
1282 /* If no method was found, insert the AbstractMethodError
1285 #if defined(ENABLE_JIT)
1286 # if defined(ENABLE_INTRP)
1288 v->interfacetable[-i][j] =
1289 (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
1292 v->interfacetable[-i][j] =
1293 (methodptr) (ptrint) &asm_abstractmethoderror;
1295 v->interfacetable[-i][j] =
1296 (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
1304 /* add superinterfaces of this interface */
1306 for (j = 0; j < ic->interfacescount; j++)
1307 if (!linker_addinterface(c, ic->interfaces[j].cls))
1316 /* class_highestinterface ******************************************************
1318 Used by the function link_class to determine the amount of memory
1319 needed for the interface table.
1321 *******************************************************************************/
1323 static s4 class_highestinterface(classinfo *c)
1329 /* check for ACC_INTERFACE bit already done in link_class_intern */
1333 for (i = 0; i < c->interfacescount; i++) {
1334 h2 = class_highestinterface(c->interfaces[i].cls);
1345 * These are local overrides for various environment variables in Emacs.
1346 * Please do not remove this and leave it at the end of the file, where
1347 * Emacs will automagically detect them.
1348 * ---------------------------------------------------------------------
1351 * indent-tabs-mode: t
1355 * vim:noexpandtab:sw=4:ts=4: