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
34 #include "mm/memory.h"
36 #include "native/native.h"
38 #include "threads/lock-common.h"
40 #include "toolbox/logging.h"
42 #include "vm/access.h"
44 #include "vm/exceptions.h"
45 #include "vm/primitive.h"
46 #include "vm/stringlocal.h"
49 #include "vm/jit_interface.h"
51 #include "vmcore/class.h"
52 #include "vmcore/classcache.h"
53 #include "vmcore/loader.h"
54 #include "vmcore/options.h"
55 #include "vmcore/rt-timing.h"
57 /* #include "vm/resolve.h" */
58 /* copied prototype to avoid bootstrapping problem: */
59 classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
61 #if defined(ENABLE_STATISTICS)
62 # include "vmcore/statistics.h"
65 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
66 #define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
68 #define INLINELOG(code)
72 /* global variables ***********************************************************/
74 static s4 interfaceindex; /* sequential numbering of interfaces */
77 java_object_t *linker_classrenumber_lock;
80 /* private functions **********************************************************/
82 static classinfo *link_class_intern(classinfo *c);
83 static arraydescriptor *link_array(classinfo *c);
84 static void linker_compute_class_values(classinfo *c);
85 static void linker_compute_subclasses(classinfo *c);
86 static bool linker_addinterface(classinfo *c, classinfo *ic);
87 static s4 class_highestinterface(classinfo *c);
90 /* dummy structures for alinment checks ***************************************/
92 typedef struct dummy_alignment_long_t dummy_alignment_long_t;
93 typedef struct dummy_alignment_double_t dummy_alignment_double_t;
95 struct dummy_alignment_long_t {
100 struct dummy_alignment_double_t {
106 /* linker_init *****************************************************************
108 Initializes the linker subsystem.
110 *******************************************************************************/
112 bool linker_init(void)
114 /* Check for if alignment for long and double matches what we
115 assume for the current architecture. */
117 #if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__))
118 if (OFFSET(dummy_alignment_long_t, l) != 4)
119 vm_abort("linker_init: long alignment is different from what assumed: %d != %d",
120 OFFSET(dummy_alignment_long_t, l), 4);
122 if (OFFSET(dummy_alignment_double_t, d) != 4)
123 vm_abort("linker_init: double alignment is different from what assumed: %d != %d",
124 OFFSET(dummy_alignment_double_t, d), 4);
126 if (OFFSET(dummy_alignment_long_t, l) != 8)
127 vm_abort("linker_init: long alignment is different from what assumed: %d != %d",
128 OFFSET(dummy_alignment_long_t, l), 8);
130 if (OFFSET(dummy_alignment_double_t, d) != 8)
131 vm_abort("linker_init: double alignment is different from what assumed: %d != %d",
132 OFFSET(dummy_alignment_double_t, d), 8);
135 /* reset interface index */
139 #if defined(ENABLE_THREADS)
140 /* create the global lock object */
142 linker_classrenumber_lock = NEW(java_object_t);
144 LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
147 /* link java.lang.Class as first class of the system, because we
148 need it's vftbl for all other classes so we can use a class as
151 if (!link_class(class_java_lang_Class))
154 /* now set the header.vftbl of all classes which were created
155 before java.lang.Class was linked */
157 class_postset_header_vftbl();
160 /* link important system classes */
162 if (!link_class(class_java_lang_Object))
165 if (!link_class(class_java_lang_String))
168 #if defined(ENABLE_JAVASE)
169 if (!link_class(class_java_lang_Cloneable))
172 if (!link_class(class_java_io_Serializable))
176 /* link classes for wrapping primitive types */
178 #if defined(ENABLE_JAVASE)
179 if (!link_class(class_java_lang_Void))
183 if (!link_class(class_java_lang_Boolean))
186 if (!link_class(class_java_lang_Byte))
189 if (!link_class(class_java_lang_Character))
192 if (!link_class(class_java_lang_Short))
195 if (!link_class(class_java_lang_Integer))
198 if (!link_class(class_java_lang_Long))
201 if (!link_class(class_java_lang_Float))
204 if (!link_class(class_java_lang_Double))
208 /* load some other important classes */
210 #if defined(ENABLE_JAVASE)
211 if (!link_class(class_java_lang_ClassLoader))
214 if (!link_class(class_java_lang_SecurityManager))
218 if (!link_class(class_java_lang_System))
221 if (!link_class(class_java_lang_Thread))
224 #if defined(ENABLE_JAVASE)
225 if (!link_class(class_java_lang_ThreadGroup))
229 #if defined(WITH_CLASSPATH_GNU)
230 if (!link_class(class_java_lang_VMSystem))
233 if (!link_class(class_java_lang_VMThread))
238 /* some classes which may be used more often */
240 #if defined(ENABLE_JAVASE)
241 if (!link_class(class_java_lang_StackTraceElement))
244 if (!link_class(class_java_lang_reflect_Constructor))
247 if (!link_class(class_java_lang_reflect_Field))
250 if (!link_class(class_java_lang_reflect_Method))
253 if (!link_class(class_java_security_PrivilegedAction))
256 if (!link_class(class_java_util_Vector))
259 # if defined(WITH_CLASSPATH_SUN)
260 if (!link_class(class_sun_reflect_MagicAccessorImpl))
264 if (!link_class(arrayclass_java_lang_Object))
269 /* create pseudo classes used by the typechecker */
271 /* pseudo class for Arraystubs (extends java.lang.Object) */
273 pseudo_class_Arraystub =
274 class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
275 pseudo_class_Arraystub->state |= CLASS_LOADED;
276 pseudo_class_Arraystub->super.cls = class_java_lang_Object;
278 #if defined(ENABLE_JAVASE)
279 pseudo_class_Arraystub->interfacescount = 2;
280 pseudo_class_Arraystub->interfaces = MNEW(classref_or_classinfo, 2);
281 pseudo_class_Arraystub->interfaces[0].cls = class_java_lang_Cloneable;
282 pseudo_class_Arraystub->interfaces[1].cls = class_java_io_Serializable;
283 #elif defined(ENABLE_JAVAME_CLDC1_1)
284 pseudo_class_Arraystub->interfacescount = 0;
285 pseudo_class_Arraystub->interfaces = NULL;
288 if (!classcache_store_unique(pseudo_class_Arraystub)) {
289 log_text("could not cache pseudo_class_Arraystub");
293 if (!link_class(pseudo_class_Arraystub))
296 /* pseudo class representing the null type */
298 pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
299 pseudo_class_Null->state |= CLASS_LOADED;
300 pseudo_class_Null->super.cls = class_java_lang_Object;
302 if (!classcache_store_unique(pseudo_class_Null))
303 vm_abort("linker_init: could not cache pseudo_class_Null");
305 if (!link_class(pseudo_class_Null))
308 /* pseudo class representing new uninitialized objects */
310 pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
311 pseudo_class_New->state |= CLASS_LOADED;
312 pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
313 pseudo_class_New->super.cls = class_java_lang_Object;
315 if (!classcache_store_unique(pseudo_class_New))
316 vm_abort("linker_init: could not cache pseudo_class_New");
318 /* Correct vftbl-entries (retarded loading and linking of class
319 java/lang/String). */
321 stringtable_update();
327 /* link_class ******************************************************************
329 Wrapper function for link_class_intern to ease monitor enter/exit
330 and exception handling.
332 *******************************************************************************/
334 classinfo *link_class(classinfo *c)
337 #if defined(ENABLE_RT_TIMING)
338 struct timespec time_start, time_end;
341 RT_TIMING_GET_TIME(time_start);
344 exceptions_throw_nullpointerexception();
348 LOCK_MONITOR_ENTER(c);
350 /* Maybe the class is currently linking or is already linked.*/
352 if ((c->state & CLASS_LINKING) || (c->state & CLASS_LINKED)) {
353 LOCK_MONITOR_EXIT(c);
358 #if defined(ENABLE_STATISTICS)
361 if (opt_getcompilingtime)
362 compilingtime_stop();
364 if (opt_getloadingtime)
368 /* call the internal function */
370 r = link_class_intern(c);
372 /* If return value is NULL, we had a problem and the class is not
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);
511 log_message_class("Linking class: ", c);
514 /* the class must be loaded */
516 /* XXX should this be a specific exception? */
517 assert(c->state & CLASS_LOADED);
519 /* This is check in link_class. */
521 assert(!(c->state & CLASS_LINKED));
523 /* cache the self-reference of this class */
524 /* we do this for cases where the defining loader of the class */
525 /* has not yet been recorded as an initiating loader for the class */
526 /* this is needed so subsequent code can assume that self-refs */
527 /* will always resolve lazily */
528 /* No need to do it for the bootloader - it is always registered */
529 /* as initiating loader for the classes it loads. */
531 classcache_store(c->classloader,c,false);
533 /* this class is currently linking */
535 c->state |= CLASS_LINKING;
540 /* check interfaces */
542 for (i = 0; i < c->interfacescount; i++) {
543 /* resolve this super interface */
545 if ((tc = resolve_classref_or_classinfo_eager(c->interfaces[i], true)) == NULL)
548 c->interfaces[i].cls = tc;
550 /* detect circularity */
553 exceptions_throw_classcircularityerror(c);
557 assert(tc->state & CLASS_LOADED);
559 if (!(tc->flags & ACC_INTERFACE)) {
560 exceptions_throw_incompatibleclasschangeerror(tc,
561 "Implementing class");
565 if (!(tc->state & CLASS_LINKED))
570 /* check super class */
574 if (c->super.any == NULL) { /* class java.lang.Object */
576 c->instancesize = sizeof(java_object_t);
578 vftbllength = supervftbllength = 0;
584 /* Resolve super class. */
586 super = resolve_classref_or_classinfo_eager(c->super, true);
591 c->super.cls = super;
593 /* Detect circularity. */
596 exceptions_throw_classcircularityerror(c);
600 assert(super->state & CLASS_LOADED);
602 if (super->flags & ACC_INTERFACE) {
603 /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
604 log_text("Interface specified as super class");
608 /* Don't allow extending final classes */
610 if (super->flags & ACC_FINAL) {
611 exceptions_throw_verifyerror(NULL,
612 "Cannot inherit from final class");
616 /* link the superclass if necessary */
618 if (!(super->state & CLASS_LINKED))
619 if (!link_class(super))
622 /* OR the ACC_CLASS_HAS_POINTERS and the ACC_CLASS_REFERENCE_*
625 c->flags |= (super->flags &
626 (ACC_CLASS_HAS_POINTERS | ACC_CLASS_REFERENCE_MASK));
628 /* handle array classes */
630 if (c->name->text[0] == '[')
631 if (!(arraydesc = link_array(c)))
634 if (c->flags & ACC_INTERFACE)
635 c->index = interfaceindex++;
637 c->index = super->index + 1;
639 c->instancesize = super->instancesize;
641 vftbllength = supervftbllength = super->vftbl->vftbllength;
643 c->finalizer = super->finalizer;
645 RT_TIMING_GET_TIME(time_resolving);
648 /* compute vftbl length */
650 for (i = 0; i < c->methodscount; i++) {
651 methodinfo *m = &(c->methods[i]);
653 if (!(m->flags & ACC_STATIC)) { /* is instance method */
659 for (j = 0; j < tc->methodscount; j++) {
660 if (method_canoverwrite(m, &(tc->methods[j]))) {
661 if (tc->methods[j].flags & ACC_PRIVATE)
662 goto notfoundvftblindex;
664 /* package-private methods in other packages */
665 /* must not be overridden */
666 /* (see Java Language Specification 8.4.8.1) */
667 if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
668 && !SAME_PACKAGE(c,tc) )
670 goto notfoundvftblindex;
673 if (!linker_overwrite_method(&(tc->methods[j]), m, &worklist))
676 goto foundvftblindex;
684 m->vftblindex = (vftbllength++);
689 RT_TIMING_GET_TIME(time_compute_vftbl);
692 /* Check all interfaces of an abstract class (maybe be an
693 interface too) for unimplemented methods. Such methods are
694 called miranda-methods and are marked with the ACC_MIRANDA
695 flag. VMClass.getDeclaredMethods does not return such
698 if (c->flags & ACC_ABSTRACT) {
701 s4 abstractmethodscount;
705 abstractmethodscount = 0;
707 /* check all interfaces of the abstract class */
709 for (i = 0; i < c->interfacescount; i++) {
710 ic = c->interfaces[i].cls;
712 for (j = 0; j < ic->methodscount; j++) {
713 im = &(ic->methods[j]);
715 /* skip `<clinit>' and `<init>' */
717 if ((im->name == utf_clinit) || (im->name == utf_init))
720 for (tc = c; tc != NULL; tc = tc->super.cls) {
721 for (k = 0; k < tc->methodscount; k++) {
722 if (method_canoverwrite(im, &(tc->methods[k])))
723 goto noabstractmethod;
727 abstractmethodscount++;
734 if (abstractmethodscount > 0) {
737 /* reallocate methods memory */
739 c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
740 c->methodscount + abstractmethodscount);
742 for (i = 0; i < c->interfacescount; i++) {
743 ic = c->interfaces[i].cls;
745 for (j = 0; j < ic->methodscount; j++) {
746 im = &(ic->methods[j]);
748 /* skip `<clinit>' and `<init>' */
750 if ((im->name == utf_clinit) || (im->name == utf_init))
753 for (tc = c; tc != NULL; tc = tc->super.cls) {
754 for (k = 0; k < tc->methodscount; k++) {
755 if (method_canoverwrite(im, &(tc->methods[k])))
756 goto noabstractmethod2;
760 /* Copy the method found into the new c->methods
761 array and tag it as miranda-method. */
763 am = &(c->methods[c->methodscount]);
766 MCOPY(am, im, methodinfo, 1);
768 am->vftblindex = (vftbllength++);
770 am->flags |= ACC_MIRANDA;
778 RT_TIMING_GET_TIME(time_abstract);
781 #if defined(ENABLE_STATISTICS)
784 sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
787 /* compute interfacetable length */
789 interfacetablelength = 0;
791 for (tc = c; tc != NULL; tc = tc->super.cls) {
792 for (i = 0; i < tc->interfacescount; i++) {
793 s4 h = class_highestinterface(tc->interfaces[i].cls) + 1;
795 if (h > interfacetablelength)
796 interfacetablelength = h;
799 RT_TIMING_GET_TIME(time_compute_iftbl);
801 /* allocate virtual function table */
803 v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
804 sizeof(methodptr) * (vftbllength - 1) +
805 sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
806 v = (vftbl_t *) (((methodptr *) v) +
807 (interfacetablelength - 1) * (interfacetablelength > 1));
811 v->vftbllength = vftbllength;
812 v->interfacetablelength = interfacetablelength;
813 v->arraydesc = arraydesc;
815 /* store interface index in vftbl */
817 if (c->flags & ACC_INTERFACE)
818 v->baseval = -(c->index);
820 /* copy virtual function table of super class */
822 for (i = 0; i < supervftbllength; i++)
823 v->table[i] = super->vftbl->table[i];
825 /* Fill the remaining vftbl slots with the AbstractMethodError
826 stub (all after the super class slots, because they are already
829 for (; i < vftbllength; i++) {
830 #if defined(ENABLE_JIT)
831 # if defined(ENABLE_INTRP)
833 v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
836 v->table[i] = (methodptr) (ptrint) &asm_abstractmethoderror;
838 v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
842 /* add method stubs into virtual function table */
844 for (i = 0; i < c->methodscount; i++) {
845 methodinfo *m = &(c->methods[i]);
847 assert(m->stubroutine == NULL);
849 /* Don't create a compiler stub for abstract methods as they
850 throw an AbstractMethodError with the default stub in the
851 vftbl. This entry is simply copied by sub-classes. */
853 if (m->flags & ACC_ABSTRACT)
856 #if defined(ENABLE_JIT)
857 # if defined(ENABLE_INTRP)
859 m->stubroutine = intrp_createcompilerstub(m);
862 m->stubroutine = codegen_generate_stub_compiler(m);
864 m->stubroutine = intrp_createcompilerstub(m);
867 /* static methods are not in the vftbl */
869 if (m->flags & ACC_STATIC)
872 /* insert the stubroutine into the vftbl */
874 v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
876 RT_TIMING_GET_TIME(time_fill_vftbl);
878 /* compute instance size and offset of each field */
880 for (i = 0; i < c->fieldscount; i++) {
882 fieldinfo *f = &(c->fields[i]);
884 if (!(f->flags & ACC_STATIC)) {
885 dsize = descriptor_typesize(f->parseddesc);
887 #if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__))
888 /* On i386 and ARM we align double and s8 fields to
889 4-bytes. This matches what GCC does for struct
890 members. We must do the same as gcc here because the
891 offsets in native header structs like java_lang_Double
892 must match the offsets of the Java fields
893 (eg. java.lang.Double.value). */
895 c->instancesize = MEMORY_ALIGN(c->instancesize, 4);
897 c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
900 f->offset = c->instancesize;
901 c->instancesize += dsize;
904 RT_TIMING_GET_TIME(time_offsets);
906 /* initialize interfacetable and interfacevftbllength */
908 v->interfacevftbllength = MNEW(s4, interfacetablelength);
910 #if defined(ENABLE_STATISTICS)
912 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
915 for (i = 0; i < interfacetablelength; i++) {
916 v->interfacevftbllength[i] = 0;
917 v->interfacetable[-i] = NULL;
922 for (tc = c; tc != NULL; tc = tc->super.cls)
923 for (i = 0; i < tc->interfacescount; i++)
924 if (!linker_addinterface(c, tc->interfaces[i].cls))
927 RT_TIMING_GET_TIME(time_fill_iftbl);
929 /* add finalizer method (not for java.lang.Object) */
934 fi = class_findmethod(c, utf_finalize, utf_void__void);
937 if (!(fi->flags & ACC_STATIC))
940 RT_TIMING_GET_TIME(time_finalizer);
944 linker_compute_subclasses(c);
946 RT_TIMING_GET_TIME(time_subclasses);
948 /* revert the linking state and class is linked */
950 c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
954 /* XXX must this also be done in case of exception? */
956 while (worklist != NULL) {
957 method_worklist *wi = worklist;
959 worklist = worklist->next;
961 INLINELOG( printf("MUST BE RECOMPILED: "); method_println(wi->m); );
962 jit_invalidate_code(wi->m);
964 /* XXX put worklist into dump memory? */
965 FREE(wi, method_worklist);
970 log_message_class("Linking done class: ", c);
973 RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
974 RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
975 RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
976 RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
977 RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
978 RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
979 RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
980 RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
981 RT_TIMING_TIME_DIFF(time_finalizer ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
983 /* just return c to show that we didn't had a problem */
989 /* link_array ******************************************************************
991 This function is called by link_class to create the arraydescriptor
994 This function returns NULL if the array cannot be linked because
995 the component type has not been linked yet.
997 *******************************************************************************/
999 static arraydescriptor *link_array(classinfo *c)
1003 arraydescriptor *desc;
1008 namelen = c->name->blength;
1010 /* Check the component type */
1012 switch (c->name->text[1]) {
1014 /* c is an array of arrays. */
1015 u = utf_new(c->name->text + 1, namelen - 1);
1016 if (!(comp = load_class_from_classloader(u, c->classloader)))
1021 /* c is an array of objects. */
1022 u = utf_new(c->name->text + 2, namelen - 3);
1023 if (!(comp = load_class_from_classloader(u, c->classloader)))
1028 /* If the component type has not been linked, link it now */
1030 assert(!comp || (comp->state & CLASS_LOADED));
1032 if (comp && !(comp->state & CLASS_LINKED))
1033 if (!link_class(comp))
1036 /* Allocate the arraydescriptor */
1038 desc = NEW(arraydescriptor);
1041 /* c is an array of references */
1042 desc->arraytype = ARRAYTYPE_OBJECT;
1043 desc->componentsize = sizeof(void*);
1044 desc->dataoffset = OFFSET(java_objectarray_t, data);
1046 compvftbl = comp->vftbl;
1049 log_text("Component class has no vftbl");
1053 desc->componentvftbl = compvftbl;
1055 if (compvftbl->arraydesc) {
1056 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1058 if (compvftbl->arraydesc->dimension >= 255) {
1059 log_text("Creating array of dimension >255");
1063 desc->dimension = compvftbl->arraydesc->dimension + 1;
1064 desc->elementtype = compvftbl->arraydesc->elementtype;
1067 desc->elementvftbl = compvftbl;
1068 desc->dimension = 1;
1069 desc->elementtype = ARRAYTYPE_OBJECT;
1073 /* c is an array of a primitive type */
1074 switch (c->name->text[1]) {
1076 desc->arraytype = ARRAYTYPE_BOOLEAN;
1077 desc->dataoffset = OFFSET(java_booleanarray_t,data);
1078 desc->componentsize = sizeof(u1);
1082 desc->arraytype = ARRAYTYPE_BYTE;
1083 desc->dataoffset = OFFSET(java_bytearray_t,data);
1084 desc->componentsize = sizeof(u1);
1088 desc->arraytype = ARRAYTYPE_CHAR;
1089 desc->dataoffset = OFFSET(java_chararray_t,data);
1090 desc->componentsize = sizeof(u2);
1094 desc->arraytype = ARRAYTYPE_DOUBLE;
1095 desc->dataoffset = OFFSET(java_doublearray_t,data);
1096 desc->componentsize = sizeof(double);
1100 desc->arraytype = ARRAYTYPE_FLOAT;
1101 desc->dataoffset = OFFSET(java_floatarray_t,data);
1102 desc->componentsize = sizeof(float);
1106 desc->arraytype = ARRAYTYPE_INT;
1107 desc->dataoffset = OFFSET(java_intarray_t,data);
1108 desc->componentsize = sizeof(s4);
1112 desc->arraytype = ARRAYTYPE_LONG;
1113 desc->dataoffset = OFFSET(java_longarray_t,data);
1114 desc->componentsize = sizeof(s8);
1118 desc->arraytype = ARRAYTYPE_SHORT;
1119 desc->dataoffset = OFFSET(java_shortarray_t,data);
1120 desc->componentsize = sizeof(s2);
1124 exceptions_throw_noclassdeffounderror(c->name);
1128 desc->componentvftbl = NULL;
1129 desc->elementvftbl = NULL;
1130 desc->dimension = 1;
1131 desc->elementtype = desc->arraytype;
1138 /* linker_compute_subclasses ***************************************************
1142 ATTENTION: DO NOT REMOVE ANY OF THE LOCKING MECHANISMS BELOW:
1143 This function needs to take the class renumber lock and stop the
1144 world during class renumbering. The lock is used in C code which
1145 is not that performance critical. Whereas JIT code uses critical
1146 sections to atomically access the class values.
1148 *******************************************************************************/
1150 static void linker_compute_subclasses(classinfo *c)
1152 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
1154 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
1155 threads_cast_stopworld();
1158 if (!(c->flags & ACC_INTERFACE)) {
1163 if (!(c->flags & ACC_INTERFACE) && (c->super.any != NULL)) {
1164 c->nextsub = c->super.cls->sub;
1165 c->super.cls->sub = c;
1170 /* compute class values */
1172 linker_compute_class_values(class_java_lang_Object);
1174 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
1176 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
1177 threads_cast_startworld();
1182 /* linker_compute_class_values *************************************************
1186 *******************************************************************************/
1188 static void linker_compute_class_values(classinfo *c)
1192 c->vftbl->baseval = ++classvalue;
1197 linker_compute_class_values(subs);
1199 subs = subs->nextsub;
1202 c->vftbl->diffval = classvalue - c->vftbl->baseval;
1206 /* linker_addinterface *********************************************************
1208 Is needed by link_class for adding a VTBL to a class. All
1209 interfaces implemented by ic are added as well.
1212 true.........everything ok
1213 false........an exception has been thrown
1215 *******************************************************************************/
1217 static bool linker_addinterface(classinfo *c, classinfo *ic)
1228 if (i >= v->interfacetablelength)
1229 vm_abort("Internal error: interfacetable overflow");
1231 /* if this interface has already been added, return immediately */
1233 if (v->interfacetable[-i] != NULL)
1236 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1237 v->interfacevftbllength[i] = 1;
1238 v->interfacetable[-i] = MNEW(methodptr, 1);
1239 v->interfacetable[-i][0] = NULL;
1242 v->interfacevftbllength[i] = ic->methodscount;
1243 v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1245 #if defined(ENABLE_STATISTICS)
1247 count_vftbl_len += sizeof(methodptr) *
1248 (ic->methodscount + (ic->methodscount == 0));
1251 for (j = 0; j < ic->methodscount; j++) {
1252 for (sc = c; sc != NULL; sc = sc->super.cls) {
1253 for (k = 0; k < sc->methodscount; k++) {
1254 m = &(sc->methods[k]);
1256 if (method_canoverwrite(m, &(ic->methods[j]))) {
1257 /* method m overwrites the (abstract) method */
1258 #if defined(ENABLE_VERIFIER)
1259 /* Add loading constraints (for the more
1260 general types of the method
1262 if (!classcache_add_constraints_for_params(
1263 c->classloader, ic->classloader,
1270 /* XXX taken from gcj */
1271 /* check for ACC_STATIC: IncompatibleClassChangeError */
1273 /* check for !ACC_PUBLIC: IllegalAccessError */
1275 /* check for ACC_ABSTRACT: AbstracMethodError,
1276 not sure about that one */
1278 v->interfacetable[-i][j] = v->table[m->vftblindex];
1284 /* If no method was found, insert the AbstractMethodError
1287 #if defined(ENABLE_JIT)
1288 # if defined(ENABLE_INTRP)
1290 v->interfacetable[-i][j] =
1291 (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
1294 v->interfacetable[-i][j] =
1295 (methodptr) (ptrint) &asm_abstractmethoderror;
1297 v->interfacetable[-i][j] =
1298 (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
1306 /* add superinterfaces of this interface */
1308 for (j = 0; j < ic->interfacescount; j++)
1309 if (!linker_addinterface(c, ic->interfaces[j].cls))
1318 /* class_highestinterface ******************************************************
1320 Used by the function link_class to determine the amount of memory
1321 needed for the interface table.
1323 *******************************************************************************/
1325 static s4 class_highestinterface(classinfo *c)
1331 /* check for ACC_INTERFACE bit already done in link_class_intern */
1335 for (i = 0; i < c->interfacescount; i++) {
1336 h2 = class_highestinterface(c->interfaces[i].cls);
1347 * These are local overrides for various environment variables in Emacs.
1348 * Please do not remove this and leave it at the end of the file, where
1349 * Emacs will automagically detect them.
1350 * ---------------------------------------------------------------------
1353 * indent-tabs-mode: t
1357 * vim:noexpandtab:sw=4:ts=4: