X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libjava%2Flink.cc;h=4f01cb545640174c3e79f3c013a55605c3be116b;hb=c0af15194ebe49449614d0529b932f019dff6a79;hp=7070d729b4a01588caffadfee6eeed18b242e681;hpb=fb2839e8929e45aa232f760cd3485dad76513c5d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libjava/link.cc b/libjava/link.cc index 7070d729b4a..4f01cb54564 100644 --- a/libjava/link.cc +++ b/libjava/link.cc @@ -1,6 +1,6 @@ // link.cc - Code for linking and resolving classes and pool entries. -/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation This file is part of libgcj. @@ -15,8 +15,18 @@ details. */ #include +#ifdef USE_LIBFFI +#include +#endif + #include +// Set GC_DEBUG before including gc.h! +#ifdef LIBGCJ_GC_DEBUG +# define GC_DEBUG +#endif +#include + #include #include #include @@ -34,6 +44,7 @@ details. */ #include #include #include +#include #include #include #include @@ -100,7 +111,7 @@ _Jv_Linker::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader) // superclasses and interfaces. _Jv_Field * _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name, - _Jv_Utf8Const *type_name, + _Jv_Utf8Const *type_name, jclass type, jclass *declarer) { while (search) @@ -112,8 +123,26 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name, if (! _Jv_equalUtf8Consts (field->name, name)) continue; - if (! field->isResolved ()) - resolve_field (field, search->loader); + // Checks for the odd situation where we were able to retrieve the + // field's class from signature but the resolution of the field itself + // failed which means a different class was resolved. + if (type != NULL) + { + try + { + resolve_field (field, search->loader); + } + catch (java::lang::Throwable *exc) + { + java::lang::LinkageError *le = new java::lang::LinkageError + (JvNewStringLatin1 + ("field type mismatch with different loaders")); + + le->initCause(exc); + + throw le; + } + } // Note that we compare type names and not types. This is // bizarre, but we do it because we want to find a field @@ -123,7 +152,10 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name, // pass in the descriptor and check that way, because when // the field is already resolved there is no easy way to // find its descriptor again. - if (_Jv_equalUtf8Consts (type_name, field->type->name)) + if ((field->isResolved () + ? _Jv_equalUtf8Classnames (type_name, field->type->name) + : _Jv_equalUtf8Classnames (type_name, + (_Jv_Utf8Const *) field->type))) { *declarer = search; return field; @@ -134,7 +166,7 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name, for (int i = 0; i < search->interface_count; ++i) { _Jv_Field *result = find_field_helper (search->interfaces[i], name, - type_name, declarer); + type_name, type, declarer); if (result) return result; } @@ -175,13 +207,21 @@ _Jv_Linker::find_field (jclass klass, jclass owner, { // FIXME: this allocates a _Jv_Utf8Const each time. We should make // it cheaper. - jclass field_type = _Jv_FindClassFromSignature (field_type_name->chars(), - klass->loader); - if (field_type == NULL) - throw new java::lang::NoClassDefFoundError(field_name->toString()); - - _Jv_Field *the_field = find_field_helper (owner, field_name, - field_type->name, found_class); + // Note: This call will resolve the primitive type names ("Z", "B", ...) to + // their Java counterparts ("boolean", "byte", ...) if accessed via + // field_type->name later. Using these variants of the type name is in turn + // important for the find_field_helper function. However if the class + // resolution failed then we can only use the already given type name. + jclass field_type + = _Jv_FindClassFromSignatureNoException (field_type_name->chars(), + klass->loader); + + _Jv_Field *the_field + = find_field_helper (owner, field_name, + (field_type + ? field_type->name : + field_type_name ), + field_type, found_class); if (the_field == 0) { @@ -194,6 +234,12 @@ _Jv_Linker::find_field (jclass klass, jclass owner, throw new java::lang::NoSuchFieldError (sb->toString()); } + // Accept it when the field's class could not be resolved. + if (field_type == NULL) + // Silently ignore that we were not able to retrieve the type to make it + // possible to run code which does not access this field. + return the_field; + if (_Jv_CheckAccess (klass, *found_class, the_field->flags)) { // Note that the field returned by find_field_helper is always @@ -221,10 +267,25 @@ _Jv_Linker::find_field (jclass klass, jclass owner, } _Jv_word -_Jv_Linker::resolve_pool_entry (jclass klass, int index) +_Jv_Linker::resolve_pool_entry (jclass klass, int index, bool lazy) { using namespace java::lang::reflect; + if (GC_base (klass) && klass->constants.data + && ! GC_base (klass->constants.data)) + { + jsize count = klass->constants.size; + if (count) + { + _Jv_word* constants + = (_Jv_word*) _Jv_AllocRawObj (count * sizeof (_Jv_word)); + memcpy ((void*)constants, + (void*)klass->constants.data, + count * sizeof (_Jv_word)); + klass->constants.data = constants; + } + } + _Jv_Constants *pool = &klass->constants; if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0) @@ -238,13 +299,26 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index) jclass found; if (name->first() == '[') - found = _Jv_FindClassFromSignature (name->chars(), - klass->loader); - else - found = _Jv_FindClass (name, klass->loader); - + found = _Jv_FindClassFromSignatureNoException (name->chars(), + klass->loader); + else + found = _Jv_FindClassNoException (name, klass->loader); + + // If the class could not be loaded a phantom class is created. Any + // function that deals with such a class but cannot do something useful + // with it should just throw a NoClassDefFoundError with the class' + // name. if (! found) - throw new java::lang::NoClassDefFoundError (name->toString()); + if (lazy) + { + found = _Jv_NewClass(name, NULL, NULL); + found->state = JV_STATE_PHANTOM; + pool->tags[index] |= JV_CONSTANT_ResolvedFlag; + pool->data[index].clazz = found; + break; + } + else + throw new java::lang::NoClassDefFoundError (name->toString()); // Check accessibility, but first strip array types as // _Jv_ClassNameSamePackage can't handle arrays. @@ -286,7 +360,12 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index) _Jv_loadIndexes (&pool->data[index], class_index, name_and_type_index); - jclass owner = (resolve_pool_entry (klass, class_index)).clazz; + jclass owner = (resolve_pool_entry (klass, class_index, true)).clazz; + + // If a phantom class was resolved our field reference is + // unusable because of the missing class. + if (owner->state == JV_STATE_PHANTOM) + throw new java::lang::NoClassDefFoundError(owner->getName()); if (owner != klass) _Jv_InitClass (owner); @@ -417,16 +496,11 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index) throw new java::lang::NoSuchMethodError (sb->toString()); } - int vtable_index = -1; - if (pool->tags[index] != JV_CONSTANT_InterfaceMethodref) - vtable_index = (jshort)the_method->index; - pool->data[index].rmethod = klass->engine->resolve_method(the_method, found_class, ((the_method->accflags - & Modifier::STATIC) != 0), - vtable_index); + & Modifier::STATIC) != 0)); pool->tags[index] |= JV_CONSTANT_ResolvedFlag; } break; @@ -498,7 +572,7 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass, #define INITIAL_IOFFSETS_LEN 4 #define INITIAL_IFACES_LEN 4 -static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} }; +static _Jv_IDispatchTable null_idt = {SHRT_MAX, 0, {}}; // Generate tables for constant-time assignment testing and interface // method lookup. This implements the technique described by Per Bothner @@ -534,10 +608,10 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) // a pointer to the current class, and the rest are pointers to the // classes ancestors, ordered from the current class down by decreasing // depth. We do not include java.lang.Object in the table of ancestors, - // since it is redundant. + // since it is redundant. Note that the classes pointed to by + // 'ancestors' will always be reachable by other paths. - // FIXME: _Jv_AllocBytes - klass->ancestors = (jclass *) _Jv_Malloc (klass->depth + klass->ancestors = (jclass *) _Jv_AllocBytes (klass->depth * sizeof (jclass)); klass0 = klass; for (int index = 0; index < klass->depth; index++) @@ -557,10 +631,6 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) return; } - // FIXME: _Jv_AllocBytes - klass->idt = - (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); - _Jv_ifaces ifaces; ifaces.count = 0; ifaces.len = INITIAL_IFACES_LEN; @@ -570,10 +640,12 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) if (ifaces.count > 0) { - klass->idt->cls.itable = - // FIXME: _Jv_AllocBytes - (void **) _Jv_Malloc (itable_size * sizeof (void *)); - klass->idt->cls.itable_length = itable_size; + // The classes pointed to by the itable will always be reachable + // via other paths. + int idt_bytes = sizeof (_Jv_IDispatchTable) + (itable_size + * sizeof (void *)); + klass->idt = (_Jv_IDispatchTable *) _Jv_AllocBytes (idt_bytes); + klass->idt->itable_length = itable_size; jshort *itable_offsets = (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort)); @@ -585,18 +657,17 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) for (int i = 0; i < ifaces.count; i++) { - ifaces.list[i]->idt->iface.ioffsets[cls_iindex] = - itable_offsets[i]; + ifaces.list[i]->ioffsets[cls_iindex] = itable_offsets[i]; } - klass->idt->cls.iindex = cls_iindex; + klass->idt->iindex = cls_iindex; _Jv_Free (ifaces.list); _Jv_Free (itable_offsets); } else { - klass->idt->cls.iindex = SHRT_MAX; + klass->idt->iindex = SHRT_MAX; } } @@ -644,9 +715,18 @@ _Jv_Linker::get_interfaces (jclass klass, _Jv_ifaces *ifaces) result += get_interfaces (klass->interfaces[i], ifaces); } } - + if (klass->isInterface()) - result += klass->method_count + 1; + { + // We want to add 1 plus the number of interface methods here. + // But, we take special care to skip . + ++result; + for (int i = 0; i < klass->method_count; ++i) + { + if (klass->methods[i].name->first() != '<') + ++result; + } + } else if (klass->superclass) result += get_interfaces (klass->superclass, ifaces); return result; @@ -659,7 +739,7 @@ void _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets) { - void **itable = klass->idt->cls.itable; + void **itable = klass->idt->itable; jshort itable_pos = 0; for (int i = 0; i < ifaces->count; i++) @@ -668,22 +748,17 @@ _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, itable_offsets[i] = itable_pos; itable_pos = append_partial_itable (klass, iface, itable, itable_pos); - /* Create interface dispatch table for iface */ - if (iface->idt == NULL) + /* Create ioffsets table for iface */ + if (iface->ioffsets == NULL) { - // FIXME: _Jv_AllocBytes - iface->idt - = (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); - // The first element of ioffsets is its length (itself included). - // FIXME: _Jv_AllocBytes - jshort *ioffsets = (jshort *) _Jv_Malloc (INITIAL_IOFFSETS_LEN - * sizeof (jshort)); + jshort *ioffsets = (jshort *) _Jv_AllocBytes (INITIAL_IOFFSETS_LEN + * sizeof (jshort)); ioffsets[0] = INITIAL_IOFFSETS_LEN; for (int i = 1; i < INITIAL_IOFFSETS_LEN; i++) ioffsets[i] = -1; - iface->idt->iface.ioffsets = ioffsets; + iface->ioffsets = ioffsets; } } } @@ -707,12 +782,36 @@ _Jv_GetMethodString (jclass klass, _Jv_Method *meth, return buf->toString(); } -void +void _Jv_ThrowNoSuchMethodError () { throw new java::lang::NoSuchMethodError; } +#ifdef USE_LIBFFI +// A function whose invocation is prepared using libffi. It gets called +// whenever a static method of a missing class is invoked. The data argument +// holds a reference to a String denoting the missing class. +// The prepared function call is stored in a class' atable. +void +_Jv_ThrowNoClassDefFoundErrorTrampoline(ffi_cif *, + void *, + void **, + void *data) +{ + throw new java::lang::NoClassDefFoundError( + _Jv_NewStringUtf8Const((_Jv_Utf8Const *) data)); +} +#else +// A variant of the NoClassDefFoundError throwing method that can +// be used without libffi. +void +_Jv_ThrowNoClassDefFoundError() +{ + throw new java::lang::NoClassDefFoundError(); +} +#endif + // Throw a NoSuchFieldError. Called by compiler-generated code when // an otable entry is zero. OTABLE_INDEX is the index in the caller's // otable that refers to the missing field. This index may be used to @@ -723,7 +822,6 @@ _Jv_ThrowNoSuchFieldError (int /* otable_index */) throw new java::lang::NoSuchFieldError; } - // This is put in empty vtable slots. void _Jv_ThrowAbstractMethodError () @@ -744,7 +842,7 @@ _Jv_ThrowAbstractMethodError () // Returns the offset at which the next partial ITable should be appended. jshort _Jv_Linker::append_partial_itable (jclass klass, jclass iface, - void **itable, jshort pos) + void **itable, jshort pos) { using namespace java::lang::reflect; @@ -753,6 +851,10 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface, for (int j=0; j < iface->method_count; j++) { + // Skip '' here. + if (iface->methods[j].name->first() == '<') + continue; + meth = NULL; for (jclass cl = klass; cl; cl = cl->getSuperclass()) { @@ -763,12 +865,7 @@ _Jv_Linker::append_partial_itable (jclass klass, jclass iface, break; } - if (meth && (meth->name->first() == '<')) - { - // leave a placeholder in the itable for hidden init methods. - itable[pos] = NULL; - } - else if (meth) + if (meth) { if ((meth->accflags & Modifier::STATIC) != 0) throw new java::lang::IncompatibleClassChangeError @@ -806,8 +903,8 @@ static bool iindex_mutex_initialized = false; // Interface Dispatch Table, we just compare the first element to see if it // matches the desired interface. So how can we find the correct offset? // Our solution is to keep a vector of candiate offsets in each interface -// (idt->iface.ioffsets), and in each class we have an index -// (idt->cls.iindex) used to select the correct offset from ioffsets. +// (ioffsets), and in each class we have an index (idt->iindex) used to +// select the correct offset from ioffsets. // // Calculate and return iindex for a new class. // ifaces is a vector of num interfaces that the class implements. @@ -838,9 +935,9 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) { if (j >= num) goto found; - if (i >= ifaces[j]->idt->iface.ioffsets[0]) + if (i >= ifaces[j]->ioffsets[0]) continue; - int ioffset = ifaces[j]->idt->iface.ioffsets[i]; + int ioffset = ifaces[j]->ioffsets[i]; /* We can potentially share this position with another class. */ if (ioffset >= 0 && ioffset != offsets[j]) break; /* Nope. Try next i. */ @@ -849,17 +946,17 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) found: for (j = 0; j < num; j++) { - int len = ifaces[j]->idt->iface.ioffsets[0]; + int len = ifaces[j]->ioffsets[0]; if (i >= len) { // Resize ioffsets. int newlen = 2 * len; if (i >= newlen) newlen = i + 3; - jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets; - // FIXME: _Jv_AllocBytes - jshort *new_ioffsets = (jshort *) _Jv_Malloc (newlen - * sizeof(jshort)); + + jshort *old_ioffsets = ifaces[j]->ioffsets; + jshort *new_ioffsets = (jshort *) _Jv_AllocBytes (newlen + * sizeof(jshort)); memcpy (&new_ioffsets[1], &old_ioffsets[1], (len - 1) * sizeof (jshort)); new_ioffsets[0] = newlen; @@ -867,9 +964,9 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) while (len < newlen) new_ioffsets[len++] = -1; - ifaces[j]->idt->iface.ioffsets = new_ioffsets; + ifaces[j]->ioffsets = new_ioffsets; } - ifaces[j]->idt->iface.ioffsets[i] = offsets[j]; + ifaces[j]->ioffsets[i] = offsets[j]; } _Jv_MutexUnlock (&iindex_mutex); @@ -877,6 +974,60 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) return i; } +#ifdef USE_LIBFFI +// We use a structure of this type to store the closure that +// represents a missing method. +struct method_closure +{ + // This field must come first, since the address of this field will + // be the same as the address of the overall structure. This is due + // to disabling interior pointers in the GC. + ffi_closure closure; + ffi_cif cif; + ffi_type *arg_types[1]; +}; + +void * +_Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) +{ + method_closure *closure + = (method_closure *) _Jv_AllocBytes(sizeof (method_closure)); + + closure->arg_types[0] = &ffi_type_void; + + // Initializes the cif and the closure. If that worked the closure + // is returned and can be used as a function pointer in a class' + // atable. + if ( ffi_prep_cif (&closure->cif, + FFI_DEFAULT_ABI, + 1, + &ffi_type_void, + closure->arg_types) == FFI_OK + && ffi_prep_closure (&closure->closure, + &closure->cif, + _Jv_ThrowNoClassDefFoundErrorTrampoline, + class_name) == FFI_OK) + return &closure->closure; + else + { + java::lang::StringBuffer *buffer = new java::lang::StringBuffer(); + buffer->append(JvNewStringLatin1("Error setting up FFI closure" + " for static method of" + " missing class: ")); + buffer->append (_Jv_NewStringUtf8Const(class_name)); + throw new java::lang::InternalError(buffer->toString()); + } +} +#else +void * +_Jv_Linker::create_error_method (_Jv_Utf8Const *) +{ + // Codepath for platforms which do not support (or want) libffi. + // You have to accept that it is impossible to provide the name + // of the missing class then. + return (void *) _Jv_ThrowNoClassDefFoundError; +} +#endif // USE_LIBFFI // Functions for indirect dispatch (symbolic virtual binding) support. @@ -1030,21 +1181,26 @@ _Jv_Linker::link_symbol_table (jclass klass) (sym = klass->atable_syms[index]).class_name != NULL; ++index) { - jclass target_class = _Jv_FindClass (sym.class_name, klass->loader); + jclass target_class = + _Jv_FindClassNoException (sym.class_name, klass->loader); + _Jv_Method *meth = NULL; _Jv_Utf8Const *signature = sym.signature; // ??? Setting this pointer to null will at least get us a // NullPointerException klass->atable->addresses[index] = NULL; - + + // If the target class is missing we prepare a function call + // that throws a NoClassDefFoundError and store the address of + // that newly prepare method in the atable. The user can run + // code in classes where the missing class is part of the + // execution environment as long as it is never referenced. if (target_class == NULL) - throw new java::lang::NoClassDefFoundError - (_Jv_NewStringUTF (sym.class_name->chars())); - + klass->atable->addresses[index] = create_error_method(sym.class_name); // We're looking for a static field or a static method, and we // can tell which is needed by looking at the signature. - if (signature->first() == '(' && signature->len() >= 2) + else if (signature->first() == '(' && signature->len() >= 2) { // If the target class does not have a vtable_method_count yet, // then we can't tell the offsets for its methods, so we must lay @@ -1083,12 +1239,13 @@ _Jv_Linker::link_symbol_table (jclass klass) } else klass->atable->addresses[index] - = (void *)_Jv_ThrowNoSuchMethodError; + = create_error_method(sym.class_name); continue; } - // Try fields. + // Try fields only if the target class exists. + if (target_class != NULL) { wait_for_state(target_class, JV_STATE_PREPARED); jclass found_class; @@ -1356,7 +1513,11 @@ _Jv_Linker::ensure_fields_laid_out (jclass klass) } int instance_size; - int static_size = 0; + // This is the size of the 'static' non-reference fields. + int non_reference_size = 0; + // This is the size of the 'static' reference fields. We count + // these separately to make it simpler for the GC to scan them. + int reference_size = 0; // Although java.lang.Object is never interpreted, an interface can // have a null superclass. Note that we have to lay out an @@ -1366,6 +1527,8 @@ _Jv_Linker::ensure_fields_laid_out (jclass klass) else instance_size = java::lang::Object::class$.size(); + klass->engine->allocate_field_initializers (klass); + for (int i = 0; i < klass->field_count; i++) { int field_size; @@ -1378,7 +1541,6 @@ _Jv_Linker::ensure_fields_laid_out (jclass klass) // It is safe to resolve the field here, since it's a // primitive class, which does not cause loading to happen. resolve_field (field, klass->loader); - field_size = field->type->size (); field_align = get_alignment_from_class (field->type); } @@ -1395,11 +1557,20 @@ _Jv_Linker::ensure_fields_laid_out (jclass klass) if (field->u.addr == NULL) { // This computes an offset into a region we'll allocate - // shortly, and then add this offset to the start + // shortly, and then adds this offset to the start // address. - static_size = ROUND (static_size, field_align); - field->u.boffset = static_size; - static_size += field_size; + if (field->isRef()) + { + reference_size = ROUND (reference_size, field_align); + field->u.boffset = reference_size; + reference_size += field_size; + } + else + { + non_reference_size = ROUND (non_reference_size, field_align); + field->u.boffset = non_reference_size; + non_reference_size += field_size; + } } } else @@ -1412,8 +1583,9 @@ _Jv_Linker::ensure_fields_laid_out (jclass klass) } } - if (static_size != 0) - klass->engine->allocate_static_fields (klass, static_size); + if (reference_size != 0 || non_reference_size != 0) + klass->engine->allocate_static_fields (klass, reference_size, + non_reference_size); // Set the instance size for the class. Note that first we round it // to the alignment required for this object; this keeps us in sync @@ -1453,25 +1625,11 @@ _Jv_Linker::ensure_class_linked (jclass klass) for (int index = 1; index < pool->size; ++index) { if (pool->tags[index] == JV_CONSTANT_Class) - resolve_pool_entry (klass, index); + // Lazily resolve the entries. + resolve_pool_entry (klass, index, true); } } -#if 0 // Should be redundant now - // If superclass looks like a constant pool entry, - // resolve it now. - if ((uaddr) klass->superclass < (uaddr) pool->size) - klass->superclass = pool->data[(uaddr) klass->superclass].clazz; - - // Likewise for interfaces. - for (int i = 0; i < klass->interface_count; i++) - { - if ((uaddr) klass->interfaces[i] < (uaddr) pool->size) - klass->interfaces[i] - = pool->data[(uaddr) klass->interfaces[i]].clazz; - } -#endif - // Resolve the remaining constant pool entries. for (int index = 1; index < pool->size; ++index) { @@ -1493,8 +1651,13 @@ _Jv_Linker::ensure_class_linked (jclass klass) int mod = f->getModifiers (); // If we have a static String field with a non-null initial // value, we know it points to a Utf8Const. - resolve_field(f, klass->loader); - if (f->getClass () == &java::lang::String::class$ + + // Finds out whether we have to initialize a String without the + // need to resolve the field. + if ((f->isResolved() + ? (f->type == &java::lang::String::class$) + : _Jv_equalUtf8Classnames((_Jv_Utf8Const *) f->type, + java::lang::String::class$.name)) && (mod & java::lang::reflect::Modifier::STATIC) != 0) { jstring *strp = (jstring *) f->u.addr; @@ -1562,8 +1725,8 @@ _Jv_Linker::add_miranda_methods (jclass base, jclass iface_class) // found is really unique among all superinterfaces. int new_count = base->method_count + 1; _Jv_Method *new_m - = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method) - * new_count); + = (_Jv_Method *) _Jv_AllocRawObj (sizeof (_Jv_Method) + * new_count); memcpy (new_m, base->methods, sizeof (_Jv_Method) * base->method_count); @@ -1698,9 +1861,9 @@ _Jv_Linker::print_class_loaded (jclass klass) } } if (codesource == NULL) - codesource = ""; + codesource = (char *) ""; - char *abi; + const char *abi; if (_Jv_IsInterpretedClass (klass)) abi = "bytecode"; else if (_Jv_IsBinaryCompatibilityABI (klass)) @@ -1732,6 +1895,21 @@ _Jv_Linker::wait_for_state (jclass klass, int state) java::lang::Thread *save = klass->thread; klass->thread = self; + // Allocate memory for static fields and constants. + if (GC_base (klass) && klass->fields && ! GC_base (klass->fields)) + { + jsize count = klass->field_count; + if (count) + { + _Jv_Field* fields + = (_Jv_Field*) _Jv_AllocRawObj (count * sizeof (_Jv_Field)); + memcpy ((void*)fields, + (void*)klass->fields, + count * sizeof (_Jv_Field)); + klass->fields = fields; + } + } + // Print some debugging info if requested. Interpreted classes are // handled in defineclass, so we only need to handle the two // pre-compiled cases here.