From: tromey Date: Wed, 8 Feb 2006 20:07:29 +0000 (+0000) Subject: PR libgcj/26063, PR libgcj/17978, PR libgcj/10598: X-Git-Tag: upstream/4.9.2~56004 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=862ad8b433732c1533f670040617716f641d3a55;p=platform%2Fupstream%2Flinaro-gcc.git PR libgcj/26063, PR libgcj/17978, PR libgcj/10598: * defineclass.cc (parse): Use _Jv_AllocRawObj. (read_constpool): Likewise. (read_one_code_attribute): Use internal function name. (handleConstantPool): Use _Jv_AllocRawObj. (handleInterfacesBegin): Likewise. (handleFieldsBegin): Likewise. (handleMethodsBegin): Likewise. (handleCodeAttribute): Likewise. (handleMethodsEnd): Likewise. * include/jvm.h (new_vtable): Use _Jv_AllocRawObj. * interpret.cc (do_allocate_static_fields): Use _Jv_AllocRawObj. Allocate reference fields separately. * link.cc (prepare_constant_time_tables): Use _Jv_AllocRawObj. (add_miranda_methods): Likewise. (generate_itable): Use _Jv_AllocBytes. (find_iindex): Likewise. (struct method_closure): New structure. (create_error_method): Use struct method_closure; allocate with _Jv_AllocBytes. (ensure_fields_laid_out): Separate reference fields from non-reference fields. * boehm.cc (_Jv_MarkObj): Mark vtable. Only mark direct fields of Class. (_Jv_MarkArray): Mark vtable. (_Jv_AllocRawObj): Don't allocate objects of size 0. * include/execution.h (_Jv_ExecutionEngine::allocate_static_fields): Added 'int' parameter. (struct _Jv_CompiledEngine): Updated. (class _Jv_InterpreterEngine): Updated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110763 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 2372781..c04f560 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,39 @@ 2006-02-08 Tom Tromey + PR libgcj/26063, PR libgcj/17978, PR libgcj/10598: + * defineclass.cc (parse): Use _Jv_AllocRawObj. + (read_constpool): Likewise. + (read_one_code_attribute): Use internal function name. + (handleConstantPool): Use _Jv_AllocRawObj. + (handleInterfacesBegin): Likewise. + (handleFieldsBegin): Likewise. + (handleMethodsBegin): Likewise. + (handleCodeAttribute): Likewise. + (handleMethodsEnd): Likewise. + * include/jvm.h (new_vtable): Use _Jv_AllocRawObj. + * interpret.cc (do_allocate_static_fields): Use _Jv_AllocRawObj. + Allocate reference fields separately. + * link.cc (prepare_constant_time_tables): Use _Jv_AllocRawObj. + (add_miranda_methods): Likewise. + (generate_itable): Use _Jv_AllocBytes. + (find_iindex): Likewise. + (struct method_closure): New structure. + (create_error_method): Use struct method_closure; allocate with + _Jv_AllocBytes. + (ensure_fields_laid_out): Separate reference fields from + non-reference fields. + * boehm.cc (_Jv_MarkObj): Mark vtable. Only mark direct fields + of Class. + (_Jv_MarkArray): Mark vtable. + (_Jv_AllocRawObj): Don't allocate objects of size 0. + * include/execution.h + (_Jv_ExecutionEngine::allocate_static_fields): Added 'int' + parameter. + (struct _Jv_CompiledEngine): Updated. + (class _Jv_InterpreterEngine): Updated. + +2006-02-08 Tom Tromey + PR java/22578: * gcj/javaprims.h: Updated. * sources.am, Makefile.in: Rebuilt. diff --git a/libjava/boehm.cc b/libjava/boehm.cc index 06b8f98..fc75bdb 100644 --- a/libjava/boehm.cc +++ b/libjava/boehm.cc @@ -1,6 +1,6 @@ // boehm.cc - interface between libjava and Boehm GC. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation This file is part of libgcj. @@ -85,6 +85,9 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void *env) jclass klass = dt->clas; GC_PTR p; + p = (GC_PTR) dt; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); + # ifndef JV_HASH_SYNCHRONIZATION // Every object has a sync_info pointer. p = (GC_PTR) obj->sync_info; @@ -114,25 +117,10 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void *env) MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->superclass; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - for (int i = 0; i < c->constants.size; ++i) - { - /* FIXME: We could make this more precise by using the tags -KKT */ - p = (GC_PTR) c->constants.data[i].p; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - } - -#ifdef INTERPRETER - if (_Jv_IsInterpretedClass (c)) - { - p = (GC_PTR) c->constants.tags; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - p = (GC_PTR) c->constants.data; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - } -#endif - // The vtable might be allocated even for compiled code. - p = (GC_PTR) c->vtable; + p = (GC_PTR) c->constants.tags; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + p = (GC_PTR) c->constants.data; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); // If the class is an array, then the methods field holds a @@ -141,101 +129,24 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void *env) p = (GC_PTR) c->methods; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - // The vtable might have been set, but the rest of the class - // could still be uninitialized. If this is the case, then - // c.isArray will SEGV. We check for this, and if it is the - // case we just return. - if (__builtin_expect (c->name == NULL, false)) - return mark_stack_ptr; - - if (! c->isArray() && ! c->isPrimitive()) - { - // Scan each method in the cases where `methods' really - // points to a methods structure. - for (int i = 0; i < c->method_count; ++i) - { - p = (GC_PTR) c->methods[i].name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - p = (GC_PTR) c->methods[i].signature; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - - // Note that we don't have to mark each individual throw - // separately, as these are stored in the constant pool. - p = (GC_PTR) c->methods[i].throws; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - } - } - - // Mark all the fields. p = (GC_PTR) c->fields; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - for (int i = 0; i < c->field_count; ++i) - { - _Jv_Field* field = &c->fields[i]; - - p = (GC_PTR) field->name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - p = (GC_PTR) field->type; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - - // For the interpreter, we also need to mark the memory - // containing static members - if ((field->flags & java::lang::reflect::Modifier::STATIC)) - { - p = (GC_PTR) field->u.addr; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - - // also, if the static member is a reference, - // mark also the value pointed to. We check for isResolved - // since marking can happen before memory is allocated for - // static members. - // Note that field->u.addr may be null if the class c is - // JV_STATE_LOADED but not JV_STATE_PREPARED (initialized). - // Note also that field->type could be NULL in some - // situations, for instance if the class has state - // JV_STATE_ERROR. - if (field->type && JvFieldIsRef (field) - && p && field->isResolved()) - { - jobject val = *(jobject*) p; - p = (GC_PTR) val; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - } - } - } + // The vtable might be allocated even for compiled code. p = (GC_PTR) c->vtable; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + p = (GC_PTR) c->interfaces; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - for (int i = 0; i < c->interface_count; ++i) - { - p = (GC_PTR) c->interfaces[i]; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - } p = (GC_PTR) c->loader; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); // The dispatch tables can be allocated at runtime. p = (GC_PTR) c->ancestors; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - if (c->idt) - { - p = (GC_PTR) c->idt; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - if (c->isInterface()) - { - p = (GC_PTR) c->idt->iface.ioffsets; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c->idt); - } - else if (! c->isPrimitive()) - { - // This field is only valid for ordinary classes. - p = (GC_PTR) c->idt->cls.itable; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c->idt); - } - } + p = (GC_PTR) c->idt; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->arrayclass; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); @@ -245,73 +156,6 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void *env) MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->aux_info; MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - -#ifdef INTERPRETER - if (_Jv_IsInterpretedClass (c) && c->aux_info) - { - _Jv_InterpClass* ic = (_Jv_InterpClass*) c->aux_info; - - p = (GC_PTR) ic->interpreted_methods; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - - p = (GC_PTR) ic->source_file_name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - - for (int i = 0; i < c->method_count; i++) - { - // The interpreter installs a heap-allocated trampoline - // here, so we'll mark it. - p = (GC_PTR) c->methods[i].ncode; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); - - using namespace java::lang::reflect; - - // Mark the direct-threaded code. Note a subtlety here: - // when we add Miranda methods to a class, we don't - // resize its interpreted_methods array. If we try to - // reference one of these methods, we may crash. - // However, we know these are all abstract, and we know - // that abstract methods have nothing useful in this - // array. So, we skip all abstract methods to avoid the - // problem. FIXME: this is pretty obscure, it may be - // better to add a methods to the execution engine and - // resize the array. - if ((c->methods[i].accflags & Modifier::ABSTRACT) != 0) - continue; - - p = (GC_PTR) ic->interpreted_methods[i]; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - - if ((c->methods[i].accflags & Modifier::NATIVE) != 0) - { - _Jv_JNIMethod *jm - = (_Jv_JNIMethod *) ic->interpreted_methods[i]; - if (jm) - { - p = (GC_PTR) jm->jni_arg_types; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, p); - } - } - else - { - _Jv_InterpMethod *im - = (_Jv_InterpMethod *) ic->interpreted_methods[i]; - if (im) - { - p = (GC_PTR) im->line_table; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - p = (GC_PTR) im->prepared; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - } - } - } - - p = (GC_PTR) ic->field_initializers; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - - } -#endif - } else { @@ -367,6 +211,9 @@ _Jv_MarkArray (void *addr, void *msp, void *msl, void *env) jclass klass = dt->clas; GC_PTR p; + p = (GC_PTR) dt; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); + # ifndef JV_HASH_SYNCHRONIZATION // Every object has a sync_info pointer. p = (GC_PTR) array->sync_info; @@ -515,7 +362,7 @@ _Jv_AllocArray (jsize size, jclass klass) void * _Jv_AllocRawObj (jsize size) { - return (void *) GC_MALLOC (size); + return (void *) GC_MALLOC (size ? size : 1); } static void diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc index 89e0636..c15cc22 100644 --- a/libjava/defineclass.cc +++ b/libjava/defineclass.cc @@ -1,6 +1,6 @@ // defineclass.cc - defining a class from .class format. -/* 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. @@ -350,7 +350,7 @@ _Jv_ClassReader::parse () // Allocate our aux_info here, after the name is set, to fulfill our // contract with the collector interface. - def->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass)); + def->aux_info = (void *) _Jv_AllocRawObj (sizeof (_Jv_InterpClass)); def_interp = (_Jv_InterpClass *) def->aux_info; int interfaces_count = read2u (); @@ -387,8 +387,7 @@ _Jv_ClassReader::parse () void _Jv_ClassReader::read_constpool () { tags = (unsigned char*) _Jv_AllocBytes (pool_count); - offsets = (unsigned int *) _Jv_AllocBytes (sizeof (int) - * pool_count) ; + offsets = (unsigned int *) _Jv_AllocBytes (sizeof (int) * pool_count) ; /** first, we scan the constant pool, collecting tags and offsets */ tags[0] = JV_CONSTANT_Undefined; @@ -656,8 +655,8 @@ void _Jv_ClassReader::read_one_code_attribute (int method_index) int table_len = read2u (); _Jv_LineTableEntry* table - = (_Jv_LineTableEntry *) JvAllocBytes (table_len - * sizeof (_Jv_LineTableEntry)); + = (_Jv_LineTableEntry *) _Jv_AllocBytes (table_len + * sizeof (_Jv_LineTableEntry)); for (int i = 0; i < table_len; i++) { table[i].bytecode_pc = read2u (); @@ -702,11 +701,10 @@ void _Jv_ClassReader::handleConstantPool () { /** now, we actually define the class' constant pool */ - // the pool is scanned explicitly by the collector jbyte *pool_tags = (jbyte*) _Jv_AllocBytes (pool_count); _Jv_word *pool_data - = (_Jv_word*) _Jv_AllocBytes (pool_count * sizeof (_Jv_word)); - + = (_Jv_word*) _Jv_AllocRawObj (pool_count * sizeof (_Jv_word)); + def->constants.tags = pool_tags; def->constants.data = pool_data; def->constants.size = pool_count; @@ -1046,7 +1044,7 @@ _Jv_ClassReader::checkExtends (jclass sub, jclass super) void _Jv_ClassReader::handleInterfacesBegin (int count) { - def->interfaces = (jclass*) _Jv_AllocBytes (count*sizeof (jclass)); + def->interfaces = (jclass*) _Jv_AllocRawObj (count*sizeof (jclass)); def->interface_count = count; } @@ -1112,11 +1110,10 @@ _Jv_ClassReader::checkImplements (jclass sub, jclass super) void _Jv_ClassReader::handleFieldsBegin (int count) { - def->fields = (_Jv_Field*) - _Jv_AllocBytes (count * sizeof (_Jv_Field)); + def->fields = (_Jv_Field*) _Jv_AllocRawObj (count * sizeof (_Jv_Field)); def->field_count = count; - def_interp->field_initializers = (_Jv_ushort*) - _Jv_AllocBytes (count * sizeof (_Jv_ushort)); + def_interp->field_initializers + = (_Jv_ushort*) _Jv_AllocRawObj (count * sizeof (_Jv_ushort)); for (int i = 0; i < count; i++) def_interp->field_initializers[i] = (_Jv_ushort) 0; } @@ -1256,11 +1253,11 @@ void _Jv_ClassReader::handleFieldsEnd () void _Jv_ClassReader::handleMethodsBegin (int count) { - def->methods = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method) * count); + def->methods = (_Jv_Method *) _Jv_AllocRawObj (sizeof (_Jv_Method) * count); def_interp->interpreted_methods - = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *) - * count); + = (_Jv_MethodBase **) _Jv_AllocRawObj (sizeof (_Jv_MethodBase *) + * count); for (int i = 0; i < count; i++) { @@ -1331,7 +1328,7 @@ void _Jv_ClassReader::handleCodeAttribute { int size = _Jv_InterpMethod::size (exc_table_length, code_length); _Jv_InterpMethod *method = - (_Jv_InterpMethod*) (_Jv_AllocBytes (size)); + (_Jv_InterpMethod*) (_Jv_AllocRawObj (size)); method->max_stack = max_stack; method->max_locals = max_locals; @@ -1390,7 +1387,7 @@ void _Jv_ClassReader::handleMethodsEnd () else { _Jv_JNIMethod *m = (_Jv_JNIMethod *) - _Jv_AllocBytes (sizeof (_Jv_JNIMethod)); + _Jv_AllocRawObj (sizeof (_Jv_JNIMethod)); m->defining_class = def; m->self = method; m->function = NULL; diff --git a/libjava/include/execution.h b/libjava/include/execution.h index b8f4746..88189f6 100644 --- a/libjava/include/execution.h +++ b/libjava/include/execution.h @@ -1,6 +1,6 @@ // execution.h - Execution engines. -*- c++ -*- -/* Copyright (C) 2004 Free Software Foundation +/* Copyright (C) 2004, 2006 Free Software Foundation This file is part of libgcj. @@ -23,7 +23,7 @@ struct _Jv_ExecutionEngine // interpreter does it. bool (*need_resolve_string_fields) (); void (*verify) (jclass); - void (*allocate_static_fields) (jclass, int); + void (*allocate_static_fields) (jclass, int, int); void (*create_ncode) (jclass); _Jv_ResolvedMethod *(*resolve_method) (_Jv_Method *, jclass, jboolean, jint); @@ -55,7 +55,7 @@ struct _Jv_CompiledEngine : public _Jv_ExecutionEngine return NULL; } - static void do_allocate_static_fields (jclass, int) + static void do_allocate_static_fields (jclass, int, int) { // Compiled classes don't need this. } @@ -99,7 +99,7 @@ class _Jv_InterpreterEngine : public _Jv_ExecutionEngine public: static void do_verify (jclass); - static void do_allocate_static_fields (jclass, int); + static void do_allocate_static_fields (jclass, int, int); static void do_create_ncode (jclass); static _Jv_ResolvedMethod *do_resolve_method (_Jv_Method *, jclass, jboolean, jint); diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index b0b3305..e5187f4 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -1,6 +1,6 @@ // jvm.h - Header file for private implementation information. -*- c++ -*- -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation This file is part of libgcj. @@ -72,6 +72,7 @@ struct _Jv_VTable { return (2 * sizeof (void *)) + (index * vtable_elt_size ()); } + static _Jv_VTable *new_vtable (int count); }; @@ -374,16 +375,12 @@ void _Jv_RunMain (jclass klass, const char *name, int argc, const char **argv, void _Jv_RunMain (struct _Jv_VMInitArgs *vm_args, jclass klass, const char *name, int argc, const char **argv, bool is_jar); -// Delayed until after _Jv_AllocBytes is declared. -// -// Note that we allocate this as unscanned memory -- the vtables -// are handled specially by the GC. - +// Delayed until after _Jv_AllocRawObj is declared. inline _Jv_VTable * _Jv_VTable::new_vtable (int count) { size_t size = sizeof(_Jv_VTable) + (count - 1) * vtable_elt_size (); - return (_Jv_VTable *) _Jv_AllocBytes (size); + return (_Jv_VTable *) _Jv_AllocRawObj (size); } // Determine if METH gets an entry in a VTable. diff --git a/libjava/interpret.cc b/libjava/interpret.cc index 87d357c..f95671d2 100644 --- a/libjava/interpret.cc +++ b/libjava/interpret.cc @@ -3877,25 +3877,30 @@ _Jv_InterpreterEngine::do_create_ncode (jclass klass) void _Jv_InterpreterEngine::do_allocate_static_fields (jclass klass, - int static_size) + int pointer_size, + int other_size) { _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; - char *static_data = (char *) _Jv_AllocBytes (static_size); + // Splitting the allocations here lets us scan reference fields and + // avoid scanning non-reference fields. + char *reference_fields = (char *) _Jv_AllocRawObj (pointer_size); + char *non_reference_fields = (char *) _Jv_AllocBytes (other_size); for (int i = 0; i < klass->field_count; i++) { _Jv_Field *field = &klass->fields[i]; - if ((field->flags & java::lang::reflect::Modifier::STATIC) != 0) + if ((field->flags & java::lang::reflect::Modifier::STATIC) == 0) + continue; + + char *base = field->isRef() ? reference_fields : non_reference_fields; + field->u.addr = base + field->u.boffset; + + if (iclass->field_initializers[i] != 0) { - field->u.addr = static_data + field->u.boffset; - - if (iclass->field_initializers[i] != 0) - { - _Jv_Linker::resolve_field (field, klass->loader); - _Jv_InitField (0, klass, i); - } + _Jv_Linker::resolve_field (field, klass->loader); + _Jv_InitField (0, klass, i); } } diff --git a/libjava/link.cc b/libjava/link.cc index 0f9f7c1..26bf898 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. @@ -588,10 +588,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++) @@ -611,9 +611,8 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) return; } - // FIXME: _Jv_AllocBytes klass->idt = - (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); + (_Jv_IDispatchTable *) _Jv_AllocRawObj (sizeof (_Jv_IDispatchTable)); _Jv_ifaces ifaces; ifaces.count = 0; @@ -624,9 +623,10 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) if (ifaces.count > 0) { + // The classes pointed to by the itable will always be reachable + // via other paths. klass->idt->cls.itable = - // FIXME: _Jv_AllocBytes - (void **) _Jv_Malloc (itable_size * sizeof (void *)); + (void **) _Jv_AllocBytes (itable_size * sizeof (void *)); klass->idt->cls.itable_length = itable_size; jshort *itable_offsets = @@ -725,14 +725,12 @@ _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, /* Create interface dispatch table for iface */ if (iface->idt == NULL) { - // FIXME: _Jv_AllocBytes iface->idt - = (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); + = (_Jv_IDispatchTable *) _Jv_AllocRawObj (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; @@ -934,9 +932,8 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) 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 *new_ioffsets = (jshort *) _Jv_AllocBytes (newlen + * sizeof(jshort)); memcpy (&new_ioffsets[1], &old_ioffsets[1], (len - 1) * sizeof (jshort)); new_ioffsets[0] = newlen; @@ -954,42 +951,47 @@ _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]; +}; + +#endif // USE_LIBFFI void * _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) { #ifdef USE_LIBFFI - // TODO: The following structs/objects are heap allocated are - // unreachable by the garbage collector: - // - cif, arg_types - - ffi_closure *closure = (ffi_closure *) _Jv_Malloc( sizeof( ffi_closure )); - ffi_cif *cif = (ffi_cif *) _Jv_Malloc( sizeof( ffi_cif )); - - // Pretends that we want to call a void (*) (void) function via - // ffi_call. - ffi_type **arg_types = (ffi_type **) _Jv_Malloc( sizeof( ffi_type * )); - 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 ( - cif, FFI_DEFAULT_ABI, 1, &ffi_type_void, arg_types) == FFI_OK - && (ffi_prep_closure ( - closure, cif, _Jv_ThrowNoClassDefFoundErrorTrampoline, - class_name) == FFI_OK)) - { - return closure; - } - else + 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(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 @@ -1484,7 +1486,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 @@ -1523,11 +1529,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 @@ -1540,8 +1555,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 @@ -1696,8 +1712,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);