diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-25 03:47:08 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-25 03:47:08 +0000 |
commit | a4ccc41f9a5f050d518b8c30739a647f67756f9e (patch) | |
tree | 477abdf83653e20b0e74447d6ca47eb67b0511b8 /libjava | |
parent | 2f3c6e08b9d664df3e416a186fd2938de188e706 (diff) | |
download | gcc-a4ccc41f9a5f050d518b8c30739a647f67756f9e.tar.gz |
* Merged gcj-abi-2-dev-branch to trunk.
(Actual changes too large to list in the commit message;
see ChangeLog.)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@91270 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
50 files changed, 5500 insertions, 3035 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 94442652db4..add3919e8fa 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,758 @@ +2004-11-24 Tom Tromey <tromey@redhat.com> + + * Merged gcj-abi-2-dev-branch to trunk. + +2004-11-16 Tom Tromey <tromey@redhat.com> + + * include/java-interp.h (_Jv_DefineClass): Updated. + * java/lang/natVMClassLoader.cc (defineClass): Pass protection + domain to class reader. + * defineclass.cc (parse): Use print_class_loaded. + Include ProtectionDomain.h. + (_Jv_DefineClass): Added ProtectionDomain argument. + (_Jv_ClassReader): Likewise. + * include/jvm.h (_Jv_Linker::print_class_loaded): Declare. + * link.cc: Include CodeSource.h. + (print_class_loaded): New function. + (wait_for_state): Use it. + +2004-11-16 Andrew Haley <aph@redhat.com> + + * gnu/gcj/util/Debug.java (print): Add RawDataManaged. + +2004-11-16 Andrew Haley <aph@redhat.com> + + * configure.ac (LIBGCJ_LD_SYMBOLIC): AC_SUBST this definition. + * configure.host: Define libgcj_ld_symbolic for Linux hosts. + * Makefile.am (lib_*_la_LDFLAGS): Add LIBGCJ_LD_SYMBOLIC. + * configure: Regenerate. + * Makefile.in: Regenerate. + +2004-11-15 Andrew Haley <aph@redhat.com> + + * boehm.cc (_Jv_GCRegisterDisappearingLink): Check that *objp is a + gc-allocated object. + +2004-11-15 Andrew Haley <aph@redhat.com> + + * java/net/URLClassLoader.java + (URLLoader.getClassPath): New method. + (JarURLLoader.JarURLLoader): Read mainfest to parse "Class-Path" + attribute and add URLs for each entry. + (JarURLLoader.classPath): New field. + (JarURLLoader.getClassPath): New method. + (addURLImpl): Scan through the list of extraUrls in the new + loader, adding them to our urlinfos. + (definePackage, findURLResource, findResources): Use + urlinfos.size(), not urls.size(). + +2004-11-11 Tom Tromey <tromey@redhat.com> + + * gnu/gcj/runtime/natSharedLibLoader.cc (ensureSupersLinked): New + method. + * gnu/gcj/runtime/SharedLibHelper.java (findClass): Ensure supers + linked. + (ensureSupersLinked): Declare. + * java/lang/natVMClassLoader.cc (loadClass): Ensure supers + linked. + +2004-11-10 Tom Tromey <tromey@redhat.com> + + * gij.cc (main): Treat -verbose the same as -verbose:class. + (help): Document -verbose and -verbose:class. + + * link.cc (verbose_class_flag): Declare. + (wait_for_state): Print message when handling precompiled class. + * java/lang/natClass.cc (verbose_class_flag): Moved to link.cc. + +2004-11-09 Tom Tromey <tromey@redhat.com> + + * testsuite/libjava.lang/assign2.out: New file. + * testsuite/libjava.lang/assign2.java: New file. + + * java/lang/natRuntime.cc (insertSystemProperties): Set + java.version to 1.4.2 and java.specification.version to 1.4. Set + java.runtime.version. + +2004-11-08 Tom Tromey <tromey@redhat.com> + + * java/lang/natClass.cc (_Jv_IsAssignableFromSlow): Ensure + supers installed. + * link.cc (verify_type_assertions): Don't link supers. + + * include/jvm.h (_Jv_Linker::search_method_in_class): Declare. + * include/java-interp.h (class _Jv_InterpClass) + <_Jv_PrepareMissingMethods>: No longer `friend'. + * java/lang/Class.h (_Jv_SearchMethodInClass): No longer + `friend'. + (_Jv_PrepareMissingMethods, _Jv_PrepareCompiledClass, + _Jv_GetInterfaces, _Jv_GenerateITable, _Jv_FindIIndex, + _Jv_AppendPartialITable, _Jv_LinkSymbolTable, + _Jv_LayoutInterfaceMethods, _Jv_SetVTableEntries, _Jv_MakeVTable, + _Jv_linkExceptionClassTable, _Jv_WaitForState): Likewise. + * link.cc (search_method_in_class): Renamed from + _Jv_SearchMethodInClass. + (resolve_pool_entry): Updated. + + * include/jvm.h (_Jv_CheckAssignment): Removed. + * java/lang/natClass.cc (_Jv_CheckAssignment): Removed. + +2004-11-05 Tom Tromey <tromey@redhat.com> + + * link.cc (verify_type_assertions): Ensure classes have supers + linked. Strip off array types first. + +2004-11-05 Bryce McKinlay <mckinlay@redhat.com> + + * link.cc: Include VerifyError.h. + (_Jv_Linker::verify_type_assertions): New. Read and evaluate entries + in the type assertion table. + * include/execution.h (_Jv_CompiledEngine::do_verify): Use + verify_type_assertions. + * include/jvm.h (_Jv_Linker::verify_type_assertions): declare. + * java/lang/Class.h (JV_ASSERT_END_OF_TABLE, + JV_ASSERT_TYPES_COMPATIBLE, JV_ASSERT_IS_INSTANTIABLE): Declare + assertion code values. + (struct _Jv_TypeAssertion): Declare. + (assertion_table): New class field. + (verify): Remove class field. + +2004-11-05 Andrew Haley <aph@redhat.com> + + * Makefile.am: Move jv_dbtool.java to + gnu/gcj/tools/gcj_dbtool/Main.java. + * Makefile.in: Rebuild. + * java/lang/VMCompiler.java: Rename property + "gnu.gcj.precompiled.db" to "gnu.gcj.precompiled.db.path". + * gnu/gcj/tools/gcj_dbtool/Main.java: moved here from + jv_dbtool.java. + +2004-11-05 Andrew Haley <aph@redhat.com> + + * jv_dbtool.java (main): Allow the user to specify the size of the + database. Display the capacity and the size. + (usage): Show the new option. + +2004-11-04 Tom Tromey <tromey@redhat.com> + + * include/jvm.h (_Jv_Linker::set_vtable_entries): Updated. + * link.cc (make_vtable): Use correct index when searching for + missing method's name. Don't use `flags'. + (set_vtable_entries): Removed `flags' argument. Don't recurse + into superclasses. + (link_symbol_table): Ensure target class method table is + complete. Ensure target fields are laid out before entering + loop. + + * java/lang/natClass.cc (_Jv_getInterfaceMethod): Indentation + fix. + + * interpret.cc (do_verify): Don't verify abstract methods. + +2004-11-01 Tom Tromey <tromey@redhat.com> + + * link.cc (wait_for_state): Call verify_class. + + * verify.cc (state::check_no_uninitialized_objects): Removed. + (push_jump): Updated. + (push_exception_jump): Likewise. + (handle_ret_insn): Likewise. + (handle_jsr_insn): Likewise. + +2004-10-28 Andrew Haley <aph@redhat.com> + + * gnu/gcj/runtime/PersistentByteMap.java: New file. + * jv_dbtool.java: New file. + * Makefile.am (bin_PROGRAMS): Add jv-dbtool + (jv_dbtool_SOURCES, jv_dbtool_LDFLAGS, jv_dbtool_LINK) + (jv_dbtool_LDADD, jv_dbtool_DEPENDENCIES): New. + * Makefile.in: Regenerate, + * java/lang/VMCompiler.java: Import NoSuchAlgorithmException, + Enumeration, StringTokenizer, Vector, PersistentByteMap. + (precompiledMapFiles): New variable. + (VMCompiler static intializer): Read "gnu.gcj.precompiled.db" to + initialize precompiledMapFiles. + (compileClass): Look at the database of precompiled class files + before firing up gcj. + + * gnu/gcj/runtime/VMClassLoader.java (findClass): Fix comment. + +2004-10-27 Andrew Haley <aph@redhat.com> + + * java/lang/VMCompiler.java (compileClass): try looking for + precompiledMapFiles. + * gnu/gcj/runtime/PersistentByteMap.java: New file. + +2004-10-27 Tom Tromey <tromey@redhat.com> + + * link.cc (ensure_class_linked): Only resolve classes for + compiled classes. + (add_miranda_methods): Ensure interface supers are installed. + (resolve_pool_entry): Better error message. + +2004-10-25 Tom Tromey <tromey@redhat.com> + + * boehm.cc (_Jv_MarkObj): Test aux_info before dereferencing it. + + * java/util/ResourceBundle.java (tryBundle): Use + Class.isAssignableFrom rather than catching ClassCastException. + + * java/util/zip/InflaterInputStream.java (fill): Don't throw an + exception if we hit EOF of `in'. + (read): Handle case where inflating returns -1. + + * gnu/java/text/WordBreakIterator.java (WordBreakIterator): Don't + initialize `iter'. + * gnu/java/text/SentenceBreakIterator.java + (SentenceBreakIterator): Don't initialize `iter'. + * gnu/java/text/LineBreakIterator.java (LineBreakIterator): Don't + initialize `iter'. + * gnu/java/text/CharacterBreakIterator.java + (CharacterBreakIterator): Don't initialize `iter'. + * gnu/java/text/BaseBreakIterator.java (BaseBreakIterator): New + constructor. + * java/text/BreakIterator.java: Updated documentation. + +2004-10-20 Tom Tromey <tromey@redhat.com> + + * java/util/ResourceBundle.java (tryBundle): Also ignore + ClassCastException. + +2004-10-18 Tom Tromey <tromey@redhat.com> + + * interpret.cc (do_post_miranda_hook): New method. + * include/execution.h (_Jv_ExecutionEngine::post_miranda_hook): + New field. + (_Jv_CompiledEngine::do_post_miranda_hook): New method. + (_Jv_CompiledEngine): Initialize new field. + (_Jv_InterpreterEngine::do_post_miranda_hook): Declare. + (_Jv_InterpreterEngine): Initialize new field. + * link.cc (resolve_pool_entry): Put Miranda methods in target + class. + (ensure_method_table_complete): Call post_miranda_hook. + * java/lang/natVMClassLoader.cc (defineClass): Don't set class' + aux_info. + * defineclass.cc (read_one_method_attribute): Use _Jv_AllocBytes. + (parse): Set class' aux_info here. + + * boehm.cc (_Jv_MarkObj): Mark `throws'. + + * boehm.cc: Re-merged with trunk. + +2004-10-18 Andrew Haley <aph@redhat.com> + + PR java/18036: + * gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Reorganize + and correct logic used to find interpreter. + +2004-10-13 Andrew Haley <aph@redhat.com> + + * interpret.cc (_Jv_InterpMethod::run): Initialize + _Jv_StartOfInterpreter. + (_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Functions removed. + (_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): New variables. + * gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Use + _Unwind_FindEnclosingFunction to discover whether PC is within the + interpreter. + +2004-10-13 Tom Tromey <tromey@redhat.com> + + * link.cc (find_iindex): Copy correct number of slots to new + ioffsets. + +2004-10-12 Tom Tromey <tromey@redhat.com> + + * testsuite/libjava.loader/loader.exp (gcj_object_file_name): New + proc. + (gcj_loader_test_one): Use it. + (gcj_loader_run): Likewise. + + * prims.cc: Don't include FirstThread.h. + +2004-10-06 Tom Tromey <tromey@redhat.com> + + * link.cc (ensure_method_table_complete): Ensure superclass + Miranda methods installed. + + * include/java-interp.h (class _Jv_JNIMethod): Added + JV_MARKOBJ_DECL as a friend. + * interpret.cc (ncode): Allocate jni_arg_types field with GC. + * boehm.cc (_Jv_MarkObj): Skip abstract methods when marking + interpreter method structures. Mark jni_arg_types of JNI + methods. + + * defineclass.cc (parse): Use JV_STATE_READ. + * java/lang/Class.h (JV_STATE_READ): New enum value. + +2004-10-05 Tom Tromey <tromey@redhat.com> + + * link.cc (resolve_pool_entry): Add signature info to missing + method's information. + + * gnu/gcj/util/Debug.java (Debug(int,boolean)): New constructor. + * gnu/gcj/util/natDebug.cc (_Jv_StaticDeepDebug): New function. + +2004-10-04 Tom Tromey <tromey@redhat.com> + + * boehm.cc (_Jv_MarkObj): Correctly indicate base pointer when + marking IDT. + +2004-09-29 Tom Tromey <tromey@redhat.com> + + * Makefile.am (libgcj_la_SOURCES): Mention link.cc, not + resolve.cc. + * include/jvm.h (class _Jv_Linker): Renamed from _Jv_Resolver. + * jni.cc: Use _Jv_Linker. + * interpret.cc: Use _Jv_Linker. + * java/lang/reflect/natField.cc (getType): Use _Jv_Linker. + * java/lang/natClassLoader.cc: Use _Jv_Linker. + * java/lang/natVMClassLoader.cc (resolveClass): Use _Jv_Linker. + * java/lang/Class.h: Use _Jv_Linker. + * java/lang/natClass.cc (initializeClass): Use _Jv_Linker. + * resolve.cc: Renamed ... + * link.cc: ... here. Use _Jv_Linker. + * defineclass.cc (checkExtends): Use _Jv_Linker. + +2004-09-17 Tom Tromey <tromey@redhat.com> + + * defineclass.cc (handleCodeAttribute): Don't reference + `deferred'. + (handleMethodsEnd): Likewise. + * include/java-interp.h (_Jv_MethodBase::deferred): Removed + field. + (_Jv_Defer_Resolution): Don't declare or define. + * interpret.cc (do_create_ncode): Don't resolve deferred method + pointers. + * java/lang/Class.h (_Jv_Defer_Resolution): Don't declare. + * resolve.cc (link_symbol_table): No need to defer resolution. + +2004-09-14 Tom Tromey <tromey@redhat.com> + + * boehm.cc (MAYBE_MARK): Remove unused `Exit' argument. + (_Jv_MarkObj): Updated. + (_Jv_MarkArray): Likewise. + + * include/jvm.h (StringClass): Removed. + * jni.cc (_Jv_JNI_ThrowNew): Don't use StringClass. + * interpret.cc (_Jv_InitField): Don't use StringClass. + * java/lang/natString.cc (_Jv_StringFindSlot): Don't use + StringClass. + (rehash): Likewise + (intern): Likewise. + (_Jv_FinalizeString): Likewise. + (_Jv_NewStringUtf8Const): Likewise. + (equals): Likewise. + * prims.cc (JvConvertArgv): Don't use StringClass. + + * gcj/field.h (struct _Jv_Field): Don't mention COMPACT_FIELDS. + * resolve.cc (ensure_fields_laid_out): Don't mention + COMPACT_FIELDS. + * defineclass.cc (handleField): Don't mention COMPACT_FIELDS. + * boehm.cc (_Jv_MarkObj): Don't mention COMPACT_FIELDS. + + * java/lang/reflect/natField.cc (getType): Use resolve_field. + * java/lang/natVMClassLoader.cc (resolveClass): New native + implementation. + (linkClass0): Removed. + (markClassErrorState0): Likewise. + * java/lang/natClassLoader.cc: Include execution.h. Moved class + preparation code to resolve.cc. + (_Jv_RegisterClassHookDefault): Set class's execution engine if + not already set. + (_Jv_FindClass): Use wait_for_state. + (_Jv_NewArrayClass): Likewise. Simplified permissions setting. + * java/lang/natClass.cc (_Jv_IsInstanceOf): Include execution.h. + Moved interface table and class preparation code to resolve.cc. + (finalize): Rewrote. + (initializeClass): Simplified locking and class preparation. + * java/lang/VMClassLoader.java (linkClass0): Removed. + (markClassErrorState0): Likewise. + (resolveClass): Now native. + (transformException): New method. + * java/lang/Class.h (getSuperclass): Don't try to resolve super + reference. + (getInterface): Likewise. + (size): Likewise. + (set_state): New method. + (Class): Updated friend declarations. + (verify): Field now private. + (engine): New field. + * include/jvm.h (class _Jv_Resolver): New class declaration. + (_Jv_ResolveField): Removed declaration. + (_Jv_CheckAccessNoInit): Likewise. + (_Jv_isBinaryCompatible): Removed. + * include/java-interp.h (class _Jv_MethodBase): Updated friend + declarations. + (class _Jv_InterpMethod): Likewise. + (class _Jv_InterpClass): Likewise. + (class _Jv_JNIMethod): Likewise. + * include/execution.h: New file. + * gnu/gcj/runtime/natSharedLibLoader.cc: Include execution.h. + (_Jv_sharedlib_register_hook): Set `engine' on loaded class. + Register class after setting fields. + * resolve.cc: Include execution.h, VerifyError.h. Moved + interpreter-specific code to interpret.cc. + (uaddr): New location. + (struct aligner): Likewise. + (ALIGNOF): Likewise. + (INITIAL_IOFFSETS_LEN): Interface dispatch code moved here. + (INITIAL_IFACES_LEN): Likewise. + (null_idt): Likewise. + (_Jv_GetMethodString): Likewise. + (_Jv_ThrowNoSuchMethodError): Likewise. + (_Jv_abstractMethodError): Likewise. + (_Jv_Resolver::get_alignment_from_class): Renamed. + (_Jv_Resolver::resolve_field): Likewise. + (_Jv_Resolver::resolve_pool_entry): Likewise. + (_Jv_Resolver::resolve_class_ref): Likewise. + (_Jv_Resolver::prepare_constant_time_tables): Likewise. + (_Jv_Resolver::indexof): Likewise. + (_Jv_Resolver::get_interfaces): Likewise. + (_Jv_Resolver::generate_itable): Likewise. + (_Jv_Resolver::append_partial_itable): Likewise. + (_Jv_Resolver::find_iindex): Likewise. + (_Jv_Resolver::link_symbol_table): Likewise. + (_Jv_Resolver::link_exception_table): Likewise. + (_Jv_Resolver::layout_interface_methods): Likewise. + (_Jv_Resolver::layout_vtable_methods): Likewise. + (_Jv_Resolver::set_vtable_entries): Likewise. + (_Jv_Resolver::make_vtable): Likewise. + (_Jv_Resolver::ensure_fields_laid_out): Likewise. + (_Jv_Resolver::ensure_class_linked): Likewise. + (_Jv_Resolver::ensure_supers_installed): Likewise. + (_Jv_Resolver::add_miranda_methods): Likewise. + (_Jv_Resolver::ensure_method_table_complete): Likewise. + (_Jv_Resolver::verify_class): Likewise. + (_Jv_Resolver::wait_for_state): Likewise. + * prims.cc (_Jv_soleCompiledEngine): New global. + (_Jv_CheckAccess): Use _Jv_IsAssignableFromSlow. + (_Jv_CheckAccessNoInit): Removed. + * jni.cc (_Jv_JNI_GetAnyFieldID): Use resolve_field. + * interpret.cc: Include platform.h, ClassFormatError.h, + Modifier.h, execution.h. + (_Jv_soleInterpreterEngine): New global. + (compile): Use resolve_pool_entry. + (run): Likewise. + (_Jv_InitField): New location. + (skip_one_type): Likewise. + (get_ffi_type_from_signature): Likewise. + (_Jv_count_arguments): Likewise. + (init_cif): Likewise. + (ncode_closure): Likewise. + (ffi_closure_fun): Likewise. + (ncode): Likewise. + (throw_class_format_error): Likewise. + (throw_class_format_error): Likewise. + (_Jv_InterpreterEngine::do_verify): New method. + (_Jv_InterpreterEngine::do_create_ncode): Likewise. + (_Jv_InterpreterEngine::do_allocate_static_fields): Likewise. + (_Jv_InterpreterEngine::do_resolve_method): Likewise. + * defineclass.cc: Include execution.h. + (_Jv_ClassReader): Initialize size_in_bytes, vtable_method_count, + engine. + (checkExtends): Ensure superclass has supers installed. + (_Jv_ClassNameSamePackage): Clarify usage constraints. + * boehm.cc (GC_enable, GC_disable): Declare at top of file. + (_Jv_MarkObj): Unconditionally mark vtable. Mark interface + dispatch tables. + +2004-09-13 Tom Tromey <tromey@redhat.com> + + * mauve-libgcj: List some classes we don't have. + +2004-09-10 Andrew Haley <aph@redhat.com> + + * java/lang/Class.h (_Jv_getInterfaceMethod(): new friend. + * java/lang/natClass.cc (initializeClass): Check itable. + (_Jv_getInterfaceMethod): New. + (_Jv_LinkSymbolTable): Rewrite code that handles inerface calls. + Check that an interface method isn't called with invokevirtual. + + * java/lang/natClass.cc (_Jv_LayoutVTableMethods): Make sure + super_meth is virtual. + +2004-09-01 Tom Tromey <tromey@redhat.com> + + * java/lang/Class.h (_Jv_CheckAccessNoInit): Declare as friend. + * java/lang/natClass.cc (_Jv_LayoutVTableMethods): Use + _Jv_CheckAccessNoInit. + * include/jvm.h (_Jv_CheckAccessNoInit): Declare. + * prims.cc (_Jv_CheckAccessNoInit): New method. + + * java/lang/reflect/natMethod.cc (invoke): Check access against + declaring class, not object's class. + * java/lang/natClass.cc (_Jv_LookupDeclaredMethod): Added another + argument. + (_Jv_LayoutVTableMethods): Perform checks of accessibility of + overridden method. + * java/lang/Class.h (_Jv_LookupDeclaredMethod): Added another + argument. + +2004-08-30 Andrew Haley <aph@redhat.com> + + * java/lang/natClass.cc (_Jv_CheckAssignment): Catch + ClassNotFoundException. + Throw NoClassDefFoundError. + + * java/lang/natClassLoader.cc (_Jv_FindClassInCache): Remove call + to klass->verify() from here ... + (_Jv_PrepareCompiledClass): ...and put it here. + +2004-08-27 Andrew Haley <aph@redhat.com> + + * java/lang/natClassLoader.cc (_Jv_FindClassInCache): Call + klass->verify(). + * java/lang/natClass.cc (_Jv_LinkSymbolTable): Add debugging. + (_Jv_LinkSymbolTable): Call Jv_LayoutClass on target class. + +2004-08-27 Tom Tromey <tromey@redhat.com> + + * java/lang/Class.h (_Jv_IsAssignableFromSlow): Declare as + friend. + * java/lang/natClass.cc (_Jv_CheckAssignment): New function. + (_Jv_IsAssignableFromSlow): New function. + Include VerifyError.h. + * include/jvm.h (_Jv_CheckAssignment): Declare. + +2004-08-18 Andrew Haley <aph@redhat.com> + + * java/lang/VMCompiler.java (loadSharedLibrary): Add className + argument. Pass it to findClass instead of fileName. + (compileClass): Pass class name to loadSharedLibrary. + +2004-06-22 Andrew Haley <aph@redhat.com> + + * testsuite/libjava.compile/compile.exp: Force indirect dispatch. + +2004-06-15 Andrew Haley <aph@redhat.com> + + * java/lang/natSystem.cc (getenv0): Don't assume environment + variable is Latin 1 coded. + +2004-06-07 Andrew Haley <aph@redhat.com> + + * java/lang/System.java: (getenv0): New method. + (getenv): Add security check. Do the right thing. + * java/lang/natSystem.cc (getenv0): New method. + +2004-04-19 Andrew Haley <aph@redhat.com> + + * gnu/gcj/runtime/NameFinder.java: Call waitFor() on the processes + we destroy. + + * gnu/java/net/natPlainSocketImplPosix.cc (read): The value byte + is returned as an int in the range 0 to 255. + +2004-08-13 Tom Tromey <tromey@redhat.com> + + * java/lang/natClass.cc (_Jv_LinkSymbolTable): Prepare the target + class if it is interpreted. + +2004-08-12 Tom Tromey <tromey@redhat.com> + + * java/lang/natClassLoader.cc (_Jv_WaitForState): Updated. + * java/lang/Class.h (_Jv_ResolveClassRef): Updated declaration. + (Class::getSuperclass): Updated. + (Class::getInterfaces): Likewise. + (Class::size): Updated. + (_Jv_LayoutClass): Updated declaration. + * java/lang/natClass.cc (_Jv_ResolveClassRef): Changed interface. + Synchronize on class. + (_Jv_LayoutClass): Changed interface. + (initializeClass): Updated. + (_Jv_LinkSymbolTable): Likewise. + + * java/lang/Class.h (Class::_Jv_isBinaryCompatible): Declare as + friend. + * java/lang/natClassLoader.cc (_Jv_WaitForState): Use + _Jv_isBinaryCompatible. + * java/lang/natClass.cc (initializeClass): Use + _Jv_isBinaryCompatible. + (_Jv_LinkSymbolTable): Likewise. + * include/jvm.h (_Jv_isBinaryCompatible): New function. + +2004-08-11 Tom Tromey <tromey@redhat.com> + + * gcj/javaprims.h: Regenerated. + * java/lang/natClassLoader.cc (getClassLoader0): Removed. + (_registerClass): Likewise. + * Makefile.in: Rebuilt. + * Makefile.am (core_java_source_files): Added VMCompiler. + * java/lang/Compiler.java: Rewrote in terms of VMCompiler. + * java/lang/VMCompiler.java: New file. + * gnu/gcj/runtime/SharedLibHelper.java (findClass): Removed + `verbose' code. + (copyFile): Don't use fully-qualified name. + (h): Removed. + * java/lang/natVMClassLoader.cc: Include VMCompiler.h. + (defineClass): Use VMCompiler. + * java/lang/ClassLoader.java (defineClass): Removed jit + compilation code and `verbose' code. + (getClassLoader0): Removed. + (_registerClass): Likewise. + (SharedLibHelpers): Removed. + +2004-08-10 Tom Tromey <tromey@redhat.com> + + * java/net/URLClassLoader.java (URLLoader(URLClassLoader, URL, + URL)): New constructor. + (SoURLLoader): Likewise. + (JarURLLoader): Create SoURLLoader with override URL. + +2004-08-10 Mark Wielaard <mark@klomp.org> + + * Makefile.in: Rebuilt. + * Makefile.am (interpret.lo): New rule. + +2004-08-05 Andrew Haley <aph@redhat.com> + + * java/net/URLClassLoader.java (JarURLLoader.JarURLLoader): Look + aside for "GCJLIBS" in directory where jarfiles are loaded. + (JarURLLoader.getClass): New method. + (JarURLLoader.toString): New method. + (FileResource.toString): New method. + * java/lang/natClassLoader.cc (_Jv_RegisterClassHookDefault): + Remove "Duplicate class registration: " bug. + (_registerClass): New method. + * java/lang/natClass.cc (_Jv_LinkSymbolTable): Check method index. + (_Jv_LinkSymbolTable): Call _Jv_LayoutClass(). + Add debugging. + (_Jv_LayoutClass): Use getSuperclass() rather than directly + accessing the field. + * java/lang/ClassLoader.java (SharedLibHelpers): New variable. + (defineClass): Call gcj to JIT-compile a class. + (_registerClass): New method. + * gnu/gcj/runtime/SharedLibHelper.java (findHelper): A shared + library name can refer to more than one loaded library, so use a + Set of SharedLibHelpers. + If a shared library is already loaded, take a copy. + (copyFile): New function. + + * testsuite/libjava.compile/compile.exp: Force + -findirect-dispatch. + + * java/security/BasicPermission.java: Remove bogus checks. + + * java/lang/System.java (getenv0): New method. + * java/lang/natSystem.cc (getenv0): New method. + +2004-05-24 Andrew Haley <aph@redhat.com> + + * java/lang/natClass.cc (_Jv_LayoutClass): Remove warning message. + +2004-04-20 Bryce McKinlay <mckinlay@redhat.com> + + * Merged with HEAD as of 20040514. Diff against + gcj-abi-2-merge-20040514. + +2004-04-16 Andrew Haley <aph@redhat.com> + + * java/lang/natClassLoader.cc (_Jv_WaitForState): Call + _Jv_LayoutClass. + (_Jv_PrepareCompiledClass): Cast address to uaddr for comparison. + (_Jv_PrepareCompiledClass): If we throw an exception during + preparation, restore state. + (ClassLoader::getClassLoader0): New method. + + * java/lang/natClass.cc (get_alignment_from_class): Moved here + from resolve.cc. + (ALIGNOF): Use offsetof, not __alignof__. + (_Jv_ResolveClassRef): Resolve a reference to a class in a + constant pool. + (getInterfaces): Emit debug output if interface hasn't been + resolved. + (initializeClass): Call _Jv_LayoutClass. + (_Jv_LinkSymbolTable): Add debugging output. + (_Jv_LinkSymbolTable): NoClassDefFoundError if target_class isn't + found. + (_Jv_LinkSymbolTable): Call _Jv_PrepareClass. + (_Jv_LinkSymbolTable): Pass the real class loader to + _Jv_FindClass. + (_Jv_linkExceptionClassTable): Don't throw if we fail to find an + exception class. + (_Jv_LinkSymbolTable): Assert if we find a static field reference + to an interpreted class. + (_Jv_LayoutVTableMethods): Use klass->getSuperclass to get the + superclass. + (_Jv_LayoutClass): Moved here; it was part of _Jv_PrepareClass in + resolve.cc. + + * java/lang/VMSecurityManager.java: Check for the system class + loader as well as loader != null. + + * java/lang/SecurityManager.java (checkPermission): Remove + security check. + (checkRead): Likewise. + (checkConnect): Likewise. + + * java/lang/ClassLoader.java (loadClass): Include all class + loaders in stack trace string. + Look for class in "gcjlib.so" in the same directory. + (getSystemClassLoader) Use getClassLoader0. + (getClassLoader0): New native method. + + * java/lang/Class.h (getSuperclass): New method. + (getInterface): New method. + (size): Lay out class if needed. + (firstMethodIndex): New method. + (Jv_ResolveClassRef): New declaration. + (_Jv_LinkSymbolTable): New declaration. + + * java/io/ObjectOutputStream.java: Add DEBUG statements + everywhere. + (dumpElementln): New method. + (depth): New field. + * java/io/ObjectInputStream.java (MyIOException): new, for + debugging. + Everywhere: use MyIOException rather than IOException. + Indent debugging output to make nesting visible. + (currentClassLoader): Make native + (callersClassLoader): New field. + (depth): New field. + * java/io/natObjectInputStream.cc (getCallersClassLoader): New + method. + + (readObject): ENDBLOCKDATA is generated if the class has a write + method, not if it has a read method. + + * include/jvm.h (_Jv_CallAnyMethodA): Add new arg, iface. + + * gnu/javax/rmi/CORBA/DelegateFactory.java: Use the + getContextClassLoader form the current thread after our own class + loader. + + * gnu/gcj/runtime/SharedLibHelper.java (findClass): Class loader + debugging. + (toString): New method. + + * verify.cc (class _Jv_BytecodeVerifier): Don't directly access + interfaces array. + + * resolve.cc (_Jv_PrepareMissingMethods): If interface looks like + a constant pool entry, resolve it now. + (_Jv_PrepareClass): Break out part of this function to Jv_LayoutClass + in natClass.cc. + Move get_alignment_from_class to natClass.cc. + + * prims.cc (_Jv_AllocObjectNoFinalizer): Use size field from class. + (_Jv_AllocObjectNoInitNoFinalizer): Likewise. + + * defineclass.cc (checkExtends): Don't access superclass field + directly. + + * Makefile.in: regenerate. + + * gnu/gcj/util/natDebug.cc: New + * gnu/gcj/util/Debug.java: New. + + * Makefile.am (java/io/ObjectInputStream.lo): Use + -fno-optimize-sibling-calls. + + * java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Use + _Jv_LookupInterfaceMethodIdx to calculate the address of a method + in an interface. + * include/jvm.h (_Jv_CallAnyMethodA): Add new arg: iface. + 2004-11-24 Kelley Cook <kcook@gcc.gnu.org> * configure: Regenerate for libtool change. diff --git a/libjava/Makefile.am b/libjava/Makefile.am index 192845f2cc5..0b07288b148 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -124,7 +124,7 @@ propdir = $(libdir) ## For now, only on native systems. FIXME. if NATIVE -bin_PROGRAMS = jv-convert gij grmic grmiregistry +bin_PROGRAMS = jv-convert gij grmic grmiregistry gcj-dbtool endif bin_SCRIPTS = addr2name.awk @@ -207,7 +207,7 @@ libgij_la_LIBADD = libgcj.la libgij_la_DEPENDENCIES = libgcj.la libgcj.spec libgcj_la_SOURCES = prims.cc jni.cc exception.cc \ - resolve.cc defineclass.cc interpret.cc verify.cc \ + link.cc defineclass.cc interpret.cc verify.cc \ $(nat_source_files) $(math_c_source_files) $(java_source_files) \ $(built_java_source_files) \ $(BOEHMGC_SRC) $(NOGC_SRC) \ @@ -363,7 +363,7 @@ lib_gnu_java_awt_peer_gtk_la_LIBADD = $(GTK_LIBS) $(GLIB_LIBS) $(LIBART_LIBS) $( lib_gnu_java_awt_peer_gtk_la_DEPENDENCIES = $(gtk_jni_headers) libgcj-@gcc_version@.jar libgcj.la libgcj.spec ## The mysterious backslash in the grep pattern is consumed by make. lib_gnu_java_awt_peer_gtk_la_LDFLAGS = \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_gnu_java_awt_peer_gtk_la_LINK = $(LIBLINK) lib_org_ietf_jgss_la_SOURCES = \ @@ -384,7 +384,7 @@ lib_org_ietf_jgss_la_LIBADD = -L$(here)/.libs $(jgss_propertyo_files) \ ## The mysterious backslash in the grep pattern is consumed by make. lib_org_ietf_jgss_la_LDFLAGS = -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_org_w3c_dom_la_SOURCES = org/w3c/dom/Attr.java \ org/w3c/dom/CDATASection.java \ @@ -415,7 +415,7 @@ org/w3c/dom/traversal/TreeWalker.java lib_org_w3c_dom_la_LIBADD = -L$(here)/.libs libgcj.la ## The mysterious backslash in the grep pattern is consumed by make. lib_org_w3c_dom_la_LDFLAGS = -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_org_xml_sax_la_SOURCES = org/xml/sax/ext/DeclHandler.java \ org/xml/sax/ext/LexicalHandler.java \ @@ -451,7 +451,7 @@ org/xml/sax/XMLReader.java lib_org_xml_sax_la_LIBADD = -L$(here)/.libs libgcj.la ## The mysterious backslash in the grep pattern is consumed by make. lib_org_xml_sax_la_LDFLAGS = -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_gnu_awt_xlib_la_SOURCES = \ $(xlib_java_source_files) \ @@ -467,7 +467,7 @@ lib_gnu_awt_xlib_la_CPPFLAGS = \ lib_gnu_awt_xlib_la_LDFLAGS = ../libstdc++-v3/src/libstdc++.la \ @X_PRE_LIBS@ @X_LIBS@ -lX11 @X_EXTRA_LIBS@ \ -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_gnu_awt_xlib_la_LINK = $(LIBLINK) all_java_source_files = \ @@ -945,6 +945,25 @@ jv_convert_LDADD = -L$(here)/.libs libgcj.la ## linking this program. jv_convert_DEPENDENCIES = libgcj.la libgcj.spec +gcj_dbtool_SOURCES = gnu/gcj/tools/gcj_dbtool/Main.java +## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We +## need this because we are explicitly using libtool to link using the +## `.la' file. +gcj_dbtool_LDFLAGS = --main=gnu.gcj.tools.gcj_dbtool.Main \ + -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS) +gcj_dbtool_LINK = $(GCJLINK) +## We don't explicitly link in the libraries we need; libgcj.la brings +## in all dependencies. We need the -L so that gcj can find libgcj +## with `-lgcj', but it must come first, otherwise the -L flags +## brought in from libgcj.la would cause the install directories to be +## searched before the build-tree ones, and we'd get errors because of +## different libraries with the same SONAME from picky linkers such as +## Solaris'. FIXME: should be _libs on some systems. +gcj_dbtool_LDADD = -L$(here)/.libs libgcj.la +## Depend on the spec file to make sure it is up to date before +## linking this program. +gcj_dbtool_DEPENDENCIES = libgcj.la libgcj.spec + gij_SOURCES = ## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'. We ## need this because we are explicitly using libtool to link using the @@ -2140,65 +2159,35 @@ javax/print/attribute/SupportedValuesAttribute.java \ javax/print/attribute/TextSyntax.java \ javax/print/attribute/UnmodifiableSetException.java \ javax/print/attribute/URISyntax.java \ -javax/print/attribute/standard/ColorSupported.java \ -javax/print/attribute/standard/Compression.java \ javax/print/attribute/standard/Copies.java \ -javax/print/attribute/standard/CopiesSupported.java \ javax/print/attribute/standard/DateTimeAtCompleted.java \ javax/print/attribute/standard/DateTimeAtCreation.java \ javax/print/attribute/standard/DateTimeAtProcessing.java \ javax/print/attribute/standard/DocumentName.java \ -javax/print/attribute/standard/Fidelity.java \ -javax/print/attribute/standard/Finishings.java \ javax/print/attribute/standard/JobHoldUntil.java \ javax/print/attribute/standard/JobImpressions.java \ javax/print/attribute/standard/JobImpressionsCompleted.java \ -javax/print/attribute/standard/JobImpressionsSupported.java \ javax/print/attribute/standard/JobKOctets.java \ javax/print/attribute/standard/JobKOctetsProcessed.java \ -javax/print/attribute/standard/JobKOctetsSupported.java \ javax/print/attribute/standard/JobMediaSheets.java \ javax/print/attribute/standard/JobMediaSheetsCompleted.java \ -javax/print/attribute/standard/JobMediaSheetsSupported.java \ javax/print/attribute/standard/JobMessageFromOperator.java \ javax/print/attribute/standard/JobName.java \ javax/print/attribute/standard/JobOriginatingUserName.java \ javax/print/attribute/standard/JobPriority.java \ javax/print/attribute/standard/JobPrioritySupported.java \ -javax/print/attribute/standard/JobSheets.java \ -javax/print/attribute/standard/JobState.java \ -javax/print/attribute/standard/JobStateReason.java \ -javax/print/attribute/standard/JobStateReasons.java \ -javax/print/attribute/standard/Media.java \ -javax/print/attribute/standard/MediaSizeName.java \ -javax/print/attribute/standard/MultipleDocumentHandling.java \ javax/print/attribute/standard/NumberOfDocuments.java \ javax/print/attribute/standard/NumberOfInterveningJobs.java \ javax/print/attribute/standard/NumberUp.java \ -javax/print/attribute/standard/NumberUpSupported.java \ -javax/print/attribute/standard/OrientationRequested.java \ javax/print/attribute/standard/OutputDeviceAssigned.java \ -javax/print/attribute/standard/PDLOverrideSupported.java \ -javax/print/attribute/standard/PageRanges.java \ javax/print/attribute/standard/PagesPerMinute.java \ javax/print/attribute/standard/PagesPerMinuteColor.java \ -javax/print/attribute/standard/PresentationDirection.java \ -javax/print/attribute/standard/PrintQuality.java \ javax/print/attribute/standard/PrinterInfo.java \ -javax/print/attribute/standard/PrinterIsAcceptingJobs.java \ javax/print/attribute/standard/PrinterLocation.java \ javax/print/attribute/standard/PrinterMakeAndModel.java \ javax/print/attribute/standard/PrinterMessageFromOperator.java \ -javax/print/attribute/standard/PrinterMoreInfo.java \ -javax/print/attribute/standard/PrinterMoreInfoManufacturer.java \ javax/print/attribute/standard/PrinterName.java \ -javax/print/attribute/standard/PrinterResolution.java \ -javax/print/attribute/standard/PrinterState.java \ -javax/print/attribute/standard/PrinterStateReason.java \ -javax/print/attribute/standard/PrinterStateReasons.java \ -javax/print/attribute/standard/PrinterURI.java \ javax/print/attribute/standard/QueuedJobCount.java \ -javax/print/attribute/standard/ReferenceUriSchemesSupported.java \ javax/print/attribute/standard/RequestingUserName.java \ javax/print/attribute/standard/Severity.java \ javax/print/attribute/standard/SheetCollate.java \ @@ -2379,6 +2368,7 @@ java/lang/UnsupportedOperationException.java \ java/lang/VerifyError.java \ java/lang/VirtualMachineError.java \ java/lang/VMClassLoader.java \ +java/lang/VMCompiler.java \ java/lang/VMSecurityManager.java \ java/lang/VMThrowable.java \ java/lang/Void.java \ @@ -2567,11 +2557,13 @@ gnu/gcj/runtime/FinalizerThread.java \ gnu/gcj/runtime/JNIWeakRef.java \ gnu/gcj/runtime/MethodRef.java \ gnu/gcj/runtime/NameFinder.java \ +gnu/gcj/runtime/PersistentByteMap.java \ gnu/gcj/runtime/SharedLibHelper.java \ gnu/gcj/runtime/SharedLibLoader.java \ gnu/gcj/runtime/StackTrace.java \ gnu/gcj/runtime/StringBuffer.java \ gnu/gcj/runtime/VMClassLoader.java \ +gnu/gcj/util/Debug.java \ gnu/java/io/ASN1ParsingException.java \ gnu/java/io/Base64InputStream.java \ gnu/java/io/ClassLoaderObjectInputStream.java \ @@ -3282,6 +3274,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \ gnu/gcj/runtime/natStackTrace.cc \ gnu/gcj/runtime/natStringBuffer.cc \ gnu/gcj/runtime/natVMClassLoader.cc \ +gnu/gcj/util/natDebug.cc \ gnu/java/lang/natMainThread.cc \ gnu/java/net/natPlainDatagramSocketImpl.cc \ gnu/java/net/natPlainSocketImpl.cc \ diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 31032fc6f02..60161a4bee9 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -17,7 +17,7 @@ -SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) $(lib_gnu_java_awt_peer_gtk_la_SOURCES) $(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) $(lib_org_xml_sax_la_SOURCES) $(libgcj_la_SOURCES) $(libgij_la_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) $(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES) +SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) $(lib_gnu_java_awt_peer_gtk_la_SOURCES) $(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) $(lib_org_xml_sax_la_SOURCES) $(libgcj_la_SOURCES) $(libgij_la_SOURCES) $(gcj_dbtool_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) $(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -43,7 +43,8 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @NATIVE_TRUE@bin_PROGRAMS = jv-convert$(EXEEXT) gij$(EXEEXT) \ -@NATIVE_TRUE@ grmic$(EXEEXT) grmiregistry$(EXEEXT) +@NATIVE_TRUE@ grmic$(EXEEXT) grmiregistry$(EXEEXT) \ +@NATIVE_TRUE@ gcj-dbtool$(EXEEXT) @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@noinst_PROGRAMS = \ @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gen-from-JIS$(EXEEXT) DIST_COMMON = README $(am__configure_deps) $(srcdir)/../compile \ @@ -371,7 +372,7 @@ lib_org_xml_sax_la_OBJECTS = $(am_lib_org_xml_sax_la_OBJECTS) am__DEPENDENCIES_4 = gnu/regexp/MessagesBundle.properties.lo \ gnu/regexp/MessagesBundle_fr.properties.lo am__DEPENDENCIES_5 = $(am__DEPENDENCIES_4) -am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \ +am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc link.cc \ defineclass.cc interpret.cc verify.cc gnu/gcj/natCore.cc \ gnu/gcj/convert/JIS0208_to_Unicode.cc \ gnu/gcj/convert/JIS0212_to_Unicode.cc \ @@ -386,7 +387,7 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \ gnu/gcj/runtime/natSharedLibLoader.cc \ gnu/gcj/runtime/natStackTrace.cc \ gnu/gcj/runtime/natStringBuffer.cc \ - gnu/gcj/runtime/natVMClassLoader.cc \ + gnu/gcj/runtime/natVMClassLoader.cc gnu/gcj/util/natDebug.cc \ gnu/java/lang/natMainThread.cc \ gnu/java/net/natPlainDatagramSocketImpl.cc \ gnu/java/net/natPlainSocketImpl.cc \ @@ -481,9 +482,9 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \ java/lang/UnsupportedClassVersionError.java \ java/lang/UnsupportedOperationException.java \ java/lang/VerifyError.java java/lang/VirtualMachineError.java \ - java/lang/VMClassLoader.java java/lang/VMSecurityManager.java \ - java/lang/VMThrowable.java java/lang/Void.java \ - java/io/BufferedInputStream.java \ + java/lang/VMClassLoader.java java/lang/VMCompiler.java \ + java/lang/VMSecurityManager.java java/lang/VMThrowable.java \ + java/lang/Void.java java/io/BufferedInputStream.java \ java/io/BufferedOutputStream.java java/io/BufferedReader.java \ java/io/BufferedWriter.java java/io/ByteArrayInputStream.java \ java/io/ByteArrayOutputStream.java \ @@ -597,11 +598,12 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \ gnu/gcj/runtime/FinalizerThread.java \ gnu/gcj/runtime/JNIWeakRef.java gnu/gcj/runtime/MethodRef.java \ gnu/gcj/runtime/NameFinder.java \ + gnu/gcj/runtime/PersistentByteMap.java \ gnu/gcj/runtime/SharedLibHelper.java \ gnu/gcj/runtime/SharedLibLoader.java \ gnu/gcj/runtime/StackTrace.java \ gnu/gcj/runtime/StringBuffer.java \ - gnu/gcj/runtime/VMClassLoader.java \ + gnu/gcj/runtime/VMClassLoader.java gnu/gcj/util/Debug.java \ gnu/java/io/ASN1ParsingException.java \ gnu/java/io/Base64InputStream.java \ gnu/java/io/ClassLoaderObjectInputStream.java \ @@ -2174,65 +2176,35 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \ javax/print/attribute/TextSyntax.java \ javax/print/attribute/UnmodifiableSetException.java \ javax/print/attribute/URISyntax.java \ - javax/print/attribute/standard/ColorSupported.java \ - javax/print/attribute/standard/Compression.java \ javax/print/attribute/standard/Copies.java \ - javax/print/attribute/standard/CopiesSupported.java \ javax/print/attribute/standard/DateTimeAtCompleted.java \ javax/print/attribute/standard/DateTimeAtCreation.java \ javax/print/attribute/standard/DateTimeAtProcessing.java \ javax/print/attribute/standard/DocumentName.java \ - javax/print/attribute/standard/Fidelity.java \ - javax/print/attribute/standard/Finishings.java \ javax/print/attribute/standard/JobHoldUntil.java \ javax/print/attribute/standard/JobImpressions.java \ javax/print/attribute/standard/JobImpressionsCompleted.java \ - javax/print/attribute/standard/JobImpressionsSupported.java \ javax/print/attribute/standard/JobKOctets.java \ javax/print/attribute/standard/JobKOctetsProcessed.java \ - javax/print/attribute/standard/JobKOctetsSupported.java \ javax/print/attribute/standard/JobMediaSheets.java \ javax/print/attribute/standard/JobMediaSheetsCompleted.java \ - javax/print/attribute/standard/JobMediaSheetsSupported.java \ javax/print/attribute/standard/JobMessageFromOperator.java \ javax/print/attribute/standard/JobName.java \ javax/print/attribute/standard/JobOriginatingUserName.java \ javax/print/attribute/standard/JobPriority.java \ javax/print/attribute/standard/JobPrioritySupported.java \ - javax/print/attribute/standard/JobSheets.java \ - javax/print/attribute/standard/JobState.java \ - javax/print/attribute/standard/JobStateReason.java \ - javax/print/attribute/standard/JobStateReasons.java \ - javax/print/attribute/standard/Media.java \ - javax/print/attribute/standard/MediaSizeName.java \ - javax/print/attribute/standard/MultipleDocumentHandling.java \ javax/print/attribute/standard/NumberOfDocuments.java \ javax/print/attribute/standard/NumberOfInterveningJobs.java \ javax/print/attribute/standard/NumberUp.java \ - javax/print/attribute/standard/NumberUpSupported.java \ - javax/print/attribute/standard/OrientationRequested.java \ javax/print/attribute/standard/OutputDeviceAssigned.java \ - javax/print/attribute/standard/PDLOverrideSupported.java \ - javax/print/attribute/standard/PageRanges.java \ javax/print/attribute/standard/PagesPerMinute.java \ javax/print/attribute/standard/PagesPerMinuteColor.java \ - javax/print/attribute/standard/PresentationDirection.java \ - javax/print/attribute/standard/PrintQuality.java \ javax/print/attribute/standard/PrinterInfo.java \ - javax/print/attribute/standard/PrinterIsAcceptingJobs.java \ javax/print/attribute/standard/PrinterLocation.java \ javax/print/attribute/standard/PrinterMakeAndModel.java \ javax/print/attribute/standard/PrinterMessageFromOperator.java \ - javax/print/attribute/standard/PrinterMoreInfo.java \ - javax/print/attribute/standard/PrinterMoreInfoManufacturer.java \ javax/print/attribute/standard/PrinterName.java \ - javax/print/attribute/standard/PrinterResolution.java \ - javax/print/attribute/standard/PrinterState.java \ - javax/print/attribute/standard/PrinterStateReason.java \ - javax/print/attribute/standard/PrinterStateReasons.java \ - javax/print/attribute/standard/PrinterURI.java \ javax/print/attribute/standard/QueuedJobCount.java \ - javax/print/attribute/standard/ReferenceUriSchemesSupported.java \ javax/print/attribute/standard/RequestingUserName.java \ javax/print/attribute/standard/Severity.java \ javax/print/attribute/standard/SheetCollate.java \ @@ -2337,7 +2309,7 @@ am__objects_6 = gnu/gcj/natCore.lo \ gnu/gcj/runtime/natSharedLibLoader.lo \ gnu/gcj/runtime/natStackTrace.lo \ gnu/gcj/runtime/natStringBuffer.lo \ - gnu/gcj/runtime/natVMClassLoader.lo \ + gnu/gcj/runtime/natVMClassLoader.lo gnu/gcj/util/natDebug.lo \ gnu/java/lang/natMainThread.lo \ gnu/java/net/natPlainDatagramSocketImpl.lo \ gnu/java/net/natPlainSocketImpl.lo \ @@ -2428,11 +2400,11 @@ am__objects_9 = java/lang/AbstractMethodError.lo \ java/lang/UnsupportedClassVersionError.lo \ java/lang/UnsupportedOperationException.lo \ java/lang/VerifyError.lo java/lang/VirtualMachineError.lo \ - java/lang/VMClassLoader.lo java/lang/VMSecurityManager.lo \ - java/lang/VMThrowable.lo java/lang/Void.lo \ - java/io/BufferedInputStream.lo java/io/BufferedOutputStream.lo \ - java/io/BufferedReader.lo java/io/BufferedWriter.lo \ - java/io/ByteArrayInputStream.lo \ + java/lang/VMClassLoader.lo java/lang/VMCompiler.lo \ + java/lang/VMSecurityManager.lo java/lang/VMThrowable.lo \ + java/lang/Void.lo java/io/BufferedInputStream.lo \ + java/io/BufferedOutputStream.lo java/io/BufferedReader.lo \ + java/io/BufferedWriter.lo java/io/ByteArrayInputStream.lo \ java/io/ByteArrayOutputStream.lo java/io/CharArrayReader.lo \ java/io/CharArrayWriter.lo java/io/CharConversionException.lo \ java/io/DataInput.lo java/io/DataInputStream.lo \ @@ -3435,65 +3407,35 @@ am__objects_13 = javax/accessibility/Accessible.lo \ javax/print/attribute/TextSyntax.lo \ javax/print/attribute/UnmodifiableSetException.lo \ javax/print/attribute/URISyntax.lo \ - javax/print/attribute/standard/ColorSupported.lo \ - javax/print/attribute/standard/Compression.lo \ javax/print/attribute/standard/Copies.lo \ - javax/print/attribute/standard/CopiesSupported.lo \ javax/print/attribute/standard/DateTimeAtCompleted.lo \ javax/print/attribute/standard/DateTimeAtCreation.lo \ javax/print/attribute/standard/DateTimeAtProcessing.lo \ javax/print/attribute/standard/DocumentName.lo \ - javax/print/attribute/standard/Fidelity.lo \ - javax/print/attribute/standard/Finishings.lo \ javax/print/attribute/standard/JobHoldUntil.lo \ javax/print/attribute/standard/JobImpressions.lo \ javax/print/attribute/standard/JobImpressionsCompleted.lo \ - javax/print/attribute/standard/JobImpressionsSupported.lo \ javax/print/attribute/standard/JobKOctets.lo \ javax/print/attribute/standard/JobKOctetsProcessed.lo \ - javax/print/attribute/standard/JobKOctetsSupported.lo \ javax/print/attribute/standard/JobMediaSheets.lo \ javax/print/attribute/standard/JobMediaSheetsCompleted.lo \ - javax/print/attribute/standard/JobMediaSheetsSupported.lo \ javax/print/attribute/standard/JobMessageFromOperator.lo \ javax/print/attribute/standard/JobName.lo \ javax/print/attribute/standard/JobOriginatingUserName.lo \ javax/print/attribute/standard/JobPriority.lo \ javax/print/attribute/standard/JobPrioritySupported.lo \ - javax/print/attribute/standard/JobSheets.lo \ - javax/print/attribute/standard/JobState.lo \ - javax/print/attribute/standard/JobStateReason.lo \ - javax/print/attribute/standard/JobStateReasons.lo \ - javax/print/attribute/standard/Media.lo \ - javax/print/attribute/standard/MediaSizeName.lo \ - javax/print/attribute/standard/MultipleDocumentHandling.lo \ javax/print/attribute/standard/NumberOfDocuments.lo \ javax/print/attribute/standard/NumberOfInterveningJobs.lo \ javax/print/attribute/standard/NumberUp.lo \ - javax/print/attribute/standard/NumberUpSupported.lo \ - javax/print/attribute/standard/OrientationRequested.lo \ javax/print/attribute/standard/OutputDeviceAssigned.lo \ - javax/print/attribute/standard/PDLOverrideSupported.lo \ - javax/print/attribute/standard/PageRanges.lo \ javax/print/attribute/standard/PagesPerMinute.lo \ javax/print/attribute/standard/PagesPerMinuteColor.lo \ - javax/print/attribute/standard/PresentationDirection.lo \ - javax/print/attribute/standard/PrintQuality.lo \ javax/print/attribute/standard/PrinterInfo.lo \ - javax/print/attribute/standard/PrinterIsAcceptingJobs.lo \ javax/print/attribute/standard/PrinterLocation.lo \ javax/print/attribute/standard/PrinterMakeAndModel.lo \ javax/print/attribute/standard/PrinterMessageFromOperator.lo \ - javax/print/attribute/standard/PrinterMoreInfo.lo \ - javax/print/attribute/standard/PrinterMoreInfoManufacturer.lo \ javax/print/attribute/standard/PrinterName.lo \ - javax/print/attribute/standard/PrinterResolution.lo \ - javax/print/attribute/standard/PrinterState.lo \ - javax/print/attribute/standard/PrinterStateReason.lo \ - javax/print/attribute/standard/PrinterStateReasons.lo \ - javax/print/attribute/standard/PrinterURI.lo \ javax/print/attribute/standard/QueuedJobCount.lo \ - javax/print/attribute/standard/ReferenceUriSchemesSupported.lo \ javax/print/attribute/standard/RequestingUserName.lo \ javax/print/attribute/standard/Severity.lo \ javax/print/attribute/standard/SheetCollate.lo \ @@ -3585,10 +3527,11 @@ am__objects_14 = $(am__objects_9) gnu/classpath/ServiceFactory.lo \ gnu/gcj/runtime/FinalizerThread.lo \ gnu/gcj/runtime/JNIWeakRef.lo gnu/gcj/runtime/MethodRef.lo \ gnu/gcj/runtime/NameFinder.lo \ + gnu/gcj/runtime/PersistentByteMap.lo \ gnu/gcj/runtime/SharedLibHelper.lo \ gnu/gcj/runtime/SharedLibLoader.lo \ gnu/gcj/runtime/StackTrace.lo gnu/gcj/runtime/StringBuffer.lo \ - gnu/gcj/runtime/VMClassLoader.lo \ + gnu/gcj/runtime/VMClassLoader.lo gnu/gcj/util/Debug.lo \ gnu/java/io/ASN1ParsingException.lo \ gnu/java/io/Base64InputStream.lo \ gnu/java/io/ClassLoaderObjectInputStream.lo \ @@ -4151,7 +4094,7 @@ am__objects_16 = java/lang/ConcreteProcess.lo \ @USING_POSIX_THREADS_TRUE@am__objects_24 = posix-threads.lo @USING_WIN32_THREADS_TRUE@am__objects_25 = win32-threads.lo @USING_NO_THREADS_TRUE@am__objects_26 = no-threads.lo -am_libgcj_la_OBJECTS = prims.lo jni.lo exception.lo resolve.lo \ +am_libgcj_la_OBJECTS = prims.lo jni.lo exception.lo link.lo \ defineclass.lo interpret.lo verify.lo $(am__objects_6) \ $(am__objects_7) $(am__objects_15) $(am__objects_16) \ $(am__objects_17) $(am__objects_18) $(am__objects_19) \ @@ -4163,6 +4106,8 @@ am_libgij_la_OBJECTS = gij.lo libgij_la_OBJECTS = $(am_libgij_la_OBJECTS) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am_gcj_dbtool_OBJECTS = gnu/gcj/tools/gcj_dbtool/Main.$(OBJEXT) +gcj_dbtool_OBJECTS = $(am_gcj_dbtool_OBJECTS) am__gen_from_JIS_SOURCES_DIST = gnu/gcj/convert/gen-from-JIS.c \ gnu/gcj/convert/make-trie.c @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@am_gen_from_JIS_OBJECTS = gnu/gcj/convert/gen-from-JIS.$(OBJEXT) \ @@ -4206,15 +4151,16 @@ SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) \ $(lib_gnu_java_awt_peer_gtk_la_SOURCES) \ $(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) \ $(lib_org_xml_sax_la_SOURCES) $(libgcj_la_SOURCES) \ - $(libgij_la_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) \ - $(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES) + $(libgij_la_SOURCES) $(gcj_dbtool_SOURCES) \ + $(gen_from_JIS_SOURCES) $(gij_SOURCES) $(grmic_SOURCES) \ + $(grmiregistry_SOURCES) $(jv_convert_SOURCES) DIST_SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) \ $(am__lib_gnu_java_awt_peer_gtk_la_SOURCES_DIST) \ $(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) \ $(lib_org_xml_sax_la_SOURCES) $(am__libgcj_la_SOURCES_DIST) \ - $(libgij_la_SOURCES) $(am__gen_from_JIS_SOURCES_DIST) \ - $(gij_SOURCES) $(grmic_SOURCES) $(grmiregistry_SOURCES) \ - $(jv_convert_SOURCES) + $(libgij_la_SOURCES) $(gcj_dbtool_SOURCES) \ + $(am__gen_from_JIS_SOURCES_DIST) $(gij_SOURCES) \ + $(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ @@ -4314,6 +4260,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@ LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@ LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@ LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@ +LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@ LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBOBJS = @LIBOBJS@ @@ -4546,7 +4493,7 @@ libgij_la_SOURCES = gij.cc libgij_la_LIBADD = libgcj.la libgij_la_DEPENDENCIES = libgcj.la libgcj.spec libgcj_la_SOURCES = prims.cc jni.cc exception.cc \ - resolve.cc defineclass.cc interpret.cc verify.cc \ + link.cc defineclass.cc interpret.cc verify.cc \ $(nat_source_files) $(math_c_source_files) $(java_source_files) \ $(built_java_source_files) \ $(BOEHMGC_SRC) $(NOGC_SRC) \ @@ -4686,7 +4633,7 @@ lib_gnu_java_awt_peer_gtk_la_GCJFLAGS = $(AM_GCJFLAGS) -fjni lib_gnu_java_awt_peer_gtk_la_LIBADD = $(GTK_LIBS) $(GLIB_LIBS) $(LIBART_LIBS) $(CAIRO_LIBS) $(PANGOFT2_LIBS) lib_gnu_java_awt_peer_gtk_la_DEPENDENCIES = $(gtk_jni_headers) libgcj-@gcc_version@.jar libgcj.la libgcj.spec lib_gnu_java_awt_peer_gtk_la_LDFLAGS = \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_gnu_java_awt_peer_gtk_la_LINK = $(LIBLINK) lib_org_ietf_jgss_la_SOURCES = \ @@ -4706,7 +4653,7 @@ lib_org_ietf_jgss_la_LIBADD = -L$(here)/.libs $(jgss_propertyo_files) \ libgcj.la lib_org_ietf_jgss_la_LDFLAGS = -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_org_w3c_dom_la_SOURCES = org/w3c/dom/Attr.java \ org/w3c/dom/CDATASection.java \ @@ -4736,7 +4683,7 @@ org/w3c/dom/traversal/TreeWalker.java lib_org_w3c_dom_la_LIBADD = -L$(here)/.libs libgcj.la lib_org_w3c_dom_la_LDFLAGS = -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_org_xml_sax_la_SOURCES = org/xml/sax/ext/DeclHandler.java \ org/xml/sax/ext/LexicalHandler.java \ @@ -4771,7 +4718,7 @@ org/xml/sax/XMLReader.java lib_org_xml_sax_la_LIBADD = -L$(here)/.libs libgcj.la lib_org_xml_sax_la_LDFLAGS = -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_gnu_awt_xlib_la_SOURCES = \ $(xlib_java_source_files) \ @@ -4787,7 +4734,7 @@ lib_gnu_awt_xlib_la_CPPFLAGS = \ lib_gnu_awt_xlib_la_LDFLAGS = ../libstdc++-v3/src/libstdc++.la \ @X_PRE_LIBS@ @X_LIBS@ -lX11 @X_EXTRA_LIBS@ \ -rpath $(toolexeclibdir) \ - -version-info `grep -v '^\#' $(srcdir)/libtool-version` + -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC) lib_gnu_awt_xlib_la_LINK = $(LIBLINK) all_java_source_files = \ @@ -4851,6 +4798,13 @@ jv_convert_LDFLAGS = --main=gnu.gcj.convert.Convert \ jv_convert_LINK = $(GCJLINK) jv_convert_LDADD = -L$(here)/.libs libgcj.la jv_convert_DEPENDENCIES = libgcj.la libgcj.spec +gcj_dbtool_SOURCES = gnu/gcj/tools/gcj_dbtool/Main.java +gcj_dbtool_LDFLAGS = --main=gnu.gcj.tools.gcj_dbtool.Main \ + -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS) + +gcj_dbtool_LINK = $(GCJLINK) +gcj_dbtool_LDADD = -L$(here)/.libs libgcj.la +gcj_dbtool_DEPENDENCIES = libgcj.la libgcj.spec gij_SOURCES = gij_LDFLAGS = -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS) gij_LINK = $(GCJLINK) @@ -6022,65 +5976,35 @@ javax/print/attribute/SupportedValuesAttribute.java \ javax/print/attribute/TextSyntax.java \ javax/print/attribute/UnmodifiableSetException.java \ javax/print/attribute/URISyntax.java \ -javax/print/attribute/standard/ColorSupported.java \ -javax/print/attribute/standard/Compression.java \ javax/print/attribute/standard/Copies.java \ -javax/print/attribute/standard/CopiesSupported.java \ javax/print/attribute/standard/DateTimeAtCompleted.java \ javax/print/attribute/standard/DateTimeAtCreation.java \ javax/print/attribute/standard/DateTimeAtProcessing.java \ javax/print/attribute/standard/DocumentName.java \ -javax/print/attribute/standard/Fidelity.java \ -javax/print/attribute/standard/Finishings.java \ javax/print/attribute/standard/JobHoldUntil.java \ javax/print/attribute/standard/JobImpressions.java \ javax/print/attribute/standard/JobImpressionsCompleted.java \ -javax/print/attribute/standard/JobImpressionsSupported.java \ javax/print/attribute/standard/JobKOctets.java \ javax/print/attribute/standard/JobKOctetsProcessed.java \ -javax/print/attribute/standard/JobKOctetsSupported.java \ javax/print/attribute/standard/JobMediaSheets.java \ javax/print/attribute/standard/JobMediaSheetsCompleted.java \ -javax/print/attribute/standard/JobMediaSheetsSupported.java \ javax/print/attribute/standard/JobMessageFromOperator.java \ javax/print/attribute/standard/JobName.java \ javax/print/attribute/standard/JobOriginatingUserName.java \ javax/print/attribute/standard/JobPriority.java \ javax/print/attribute/standard/JobPrioritySupported.java \ -javax/print/attribute/standard/JobSheets.java \ -javax/print/attribute/standard/JobState.java \ -javax/print/attribute/standard/JobStateReason.java \ -javax/print/attribute/standard/JobStateReasons.java \ -javax/print/attribute/standard/Media.java \ -javax/print/attribute/standard/MediaSizeName.java \ -javax/print/attribute/standard/MultipleDocumentHandling.java \ javax/print/attribute/standard/NumberOfDocuments.java \ javax/print/attribute/standard/NumberOfInterveningJobs.java \ javax/print/attribute/standard/NumberUp.java \ -javax/print/attribute/standard/NumberUpSupported.java \ -javax/print/attribute/standard/OrientationRequested.java \ javax/print/attribute/standard/OutputDeviceAssigned.java \ -javax/print/attribute/standard/PDLOverrideSupported.java \ -javax/print/attribute/standard/PageRanges.java \ javax/print/attribute/standard/PagesPerMinute.java \ javax/print/attribute/standard/PagesPerMinuteColor.java \ -javax/print/attribute/standard/PresentationDirection.java \ -javax/print/attribute/standard/PrintQuality.java \ javax/print/attribute/standard/PrinterInfo.java \ -javax/print/attribute/standard/PrinterIsAcceptingJobs.java \ javax/print/attribute/standard/PrinterLocation.java \ javax/print/attribute/standard/PrinterMakeAndModel.java \ javax/print/attribute/standard/PrinterMessageFromOperator.java \ -javax/print/attribute/standard/PrinterMoreInfo.java \ -javax/print/attribute/standard/PrinterMoreInfoManufacturer.java \ javax/print/attribute/standard/PrinterName.java \ -javax/print/attribute/standard/PrinterResolution.java \ -javax/print/attribute/standard/PrinterState.java \ -javax/print/attribute/standard/PrinterStateReason.java \ -javax/print/attribute/standard/PrinterStateReasons.java \ -javax/print/attribute/standard/PrinterURI.java \ javax/print/attribute/standard/QueuedJobCount.java \ -javax/print/attribute/standard/ReferenceUriSchemesSupported.java \ javax/print/attribute/standard/RequestingUserName.java \ javax/print/attribute/standard/Severity.java \ javax/print/attribute/standard/SheetCollate.java \ @@ -6255,6 +6179,7 @@ java/lang/UnsupportedOperationException.java \ java/lang/VerifyError.java \ java/lang/VirtualMachineError.java \ java/lang/VMClassLoader.java \ +java/lang/VMCompiler.java \ java/lang/VMSecurityManager.java \ java/lang/VMThrowable.java \ java/lang/Void.java \ @@ -6437,11 +6362,13 @@ gnu/gcj/runtime/FinalizerThread.java \ gnu/gcj/runtime/JNIWeakRef.java \ gnu/gcj/runtime/MethodRef.java \ gnu/gcj/runtime/NameFinder.java \ +gnu/gcj/runtime/PersistentByteMap.java \ gnu/gcj/runtime/SharedLibHelper.java \ gnu/gcj/runtime/SharedLibLoader.java \ gnu/gcj/runtime/StackTrace.java \ gnu/gcj/runtime/StringBuffer.java \ gnu/gcj/runtime/VMClassLoader.java \ +gnu/gcj/util/Debug.java \ gnu/java/io/ASN1ParsingException.java \ gnu/java/io/Base64InputStream.java \ gnu/java/io/ClassLoaderObjectInputStream.java \ @@ -7147,6 +7074,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \ gnu/gcj/runtime/natStackTrace.cc \ gnu/gcj/runtime/natStringBuffer.cc \ gnu/gcj/runtime/natVMClassLoader.cc \ +gnu/gcj/util/natDebug.cc \ gnu/java/lang/natMainThread.cc \ gnu/java/net/natPlainDatagramSocketImpl.cc \ gnu/java/net/natPlainSocketImpl.cc \ @@ -8042,6 +7970,14 @@ gnu/gcj/runtime/natStringBuffer.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) gnu/gcj/runtime/natVMClassLoader.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) +gnu/gcj/util/$(am__dirstamp): + @$(mkdir_p) gnu/gcj/util + @: > gnu/gcj/util/$(am__dirstamp) +gnu/gcj/util/$(DEPDIR)/$(am__dirstamp): + @$(mkdir_p) gnu/gcj/util/$(DEPDIR) + @: > gnu/gcj/util/$(DEPDIR)/$(am__dirstamp) +gnu/gcj/util/natDebug.lo: gnu/gcj/util/$(am__dirstamp) \ + gnu/gcj/util/$(DEPDIR)/$(am__dirstamp) gnu/java/lang/$(am__dirstamp): @$(mkdir_p) gnu/java/lang @: > gnu/java/lang/$(am__dirstamp) @@ -8456,6 +8392,8 @@ java/lang/VirtualMachineError.lo: java/lang/$(am__dirstamp) \ java/lang/$(DEPDIR)/$(am__dirstamp) java/lang/VMClassLoader.lo: java/lang/$(am__dirstamp) \ java/lang/$(DEPDIR)/$(am__dirstamp) +java/lang/VMCompiler.lo: java/lang/$(am__dirstamp) \ + java/lang/$(DEPDIR)/$(am__dirstamp) java/lang/VMSecurityManager.lo: java/lang/$(am__dirstamp) \ java/lang/$(DEPDIR)/$(am__dirstamp) java/lang/VMThrowable.lo: java/lang/$(am__dirstamp) \ @@ -8852,6 +8790,8 @@ gnu/gcj/runtime/MethodRef.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) gnu/gcj/runtime/NameFinder.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) +gnu/gcj/runtime/PersistentByteMap.lo: gnu/gcj/runtime/$(am__dirstamp) \ + gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) gnu/gcj/runtime/SharedLibHelper.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) gnu/gcj/runtime/SharedLibLoader.lo: gnu/gcj/runtime/$(am__dirstamp) \ @@ -8862,6 +8802,8 @@ gnu/gcj/runtime/StringBuffer.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) gnu/gcj/runtime/VMClassLoader.lo: gnu/gcj/runtime/$(am__dirstamp) \ gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) +gnu/gcj/util/Debug.lo: gnu/gcj/util/$(am__dirstamp) \ + gnu/gcj/util/$(DEPDIR)/$(am__dirstamp) gnu/java/io/$(am__dirstamp): @$(mkdir_p) gnu/java/io @: > gnu/java/io/$(am__dirstamp) @@ -13836,18 +13778,9 @@ javax/print/attribute/standard/$(am__dirstamp): javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp): @$(mkdir_p) javax/print/attribute/standard/$(DEPDIR) @: > javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/ColorSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/Compression.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/Copies.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/CopiesSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/DateTimeAtCompleted.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) @@ -13860,12 +13793,6 @@ javax/print/attribute/standard/DateTimeAtProcessing.lo: \ javax/print/attribute/standard/DocumentName.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/Fidelity.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/Finishings.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/JobHoldUntil.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) @@ -13875,27 +13802,18 @@ javax/print/attribute/standard/JobImpressions.lo: \ javax/print/attribute/standard/JobImpressionsCompleted.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobImpressionsSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/JobKOctets.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/JobKOctetsProcessed.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobKOctetsSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/JobMediaSheets.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/JobMediaSheetsCompleted.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobMediaSheetsSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/JobMessageFromOperator.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) @@ -13911,27 +13829,6 @@ javax/print/attribute/standard/JobPriority.lo: \ javax/print/attribute/standard/JobPrioritySupported.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobSheets.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobState.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobStateReason.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/JobStateReasons.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/Media.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/MediaSizeName.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/MultipleDocumentHandling.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/NumberOfDocuments.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) @@ -13941,39 +13838,18 @@ javax/print/attribute/standard/NumberOfInterveningJobs.lo: \ javax/print/attribute/standard/NumberUp.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/NumberUpSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/OrientationRequested.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/OutputDeviceAssigned.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PDLOverrideSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PageRanges.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/PagesPerMinute.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/PagesPerMinuteColor.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PresentationDirection.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrintQuality.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/PrinterInfo.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterIsAcceptingJobs.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/PrinterLocation.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) @@ -13983,36 +13859,12 @@ javax/print/attribute/standard/PrinterMakeAndModel.lo: \ javax/print/attribute/standard/PrinterMessageFromOperator.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterMoreInfo.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterMoreInfoManufacturer.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/PrinterName.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterResolution.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterState.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterStateReason.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterStateReasons.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/PrinterURI.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/QueuedJobCount.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) -javax/print/attribute/standard/ReferenceUriSchemesSupported.lo: \ - javax/print/attribute/standard/$(am__dirstamp) \ - javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) javax/print/attribute/standard/RequestingUserName.lo: \ javax/print/attribute/standard/$(am__dirstamp) \ javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp) @@ -14379,6 +14231,18 @@ clean-noinstPROGRAMS: echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done +gnu/gcj/tools/gcj_dbtool/$(am__dirstamp): + @$(mkdir_p) gnu/gcj/tools/gcj_dbtool + @: > gnu/gcj/tools/gcj_dbtool/$(am__dirstamp) +gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp): + @$(mkdir_p) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) + @: > gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp) +gnu/gcj/tools/gcj_dbtool/Main.$(OBJEXT): \ + gnu/gcj/tools/gcj_dbtool/$(am__dirstamp) \ + gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp) +gcj-dbtool$(EXEEXT): $(gcj_dbtool_OBJECTS) $(gcj_dbtool_DEPENDENCIES) + @rm -f gcj-dbtool$(EXEEXT) + $(gcj_dbtool_LINK) $(gcj_dbtool_LDFLAGS) $(gcj_dbtool_OBJECTS) $(gcj_dbtool_LDADD) $(LIBS) gnu/gcj/convert/gen-from-JIS.$(OBJEXT): \ gnu/gcj/convert/$(am__dirstamp) \ gnu/gcj/convert/$(DEPDIR)/$(am__dirstamp) @@ -14549,6 +14413,8 @@ mostlyclean-compile: -rm -f gnu/gcj/runtime/MethodRef.lo -rm -f gnu/gcj/runtime/NameFinder.$(OBJEXT) -rm -f gnu/gcj/runtime/NameFinder.lo + -rm -f gnu/gcj/runtime/PersistentByteMap.$(OBJEXT) + -rm -f gnu/gcj/runtime/PersistentByteMap.lo -rm -f gnu/gcj/runtime/SharedLibHelper.$(OBJEXT) -rm -f gnu/gcj/runtime/SharedLibHelper.lo -rm -f gnu/gcj/runtime/SharedLibLoader.$(OBJEXT) @@ -14571,6 +14437,11 @@ mostlyclean-compile: -rm -f gnu/gcj/runtime/natStringBuffer.lo -rm -f gnu/gcj/runtime/natVMClassLoader.$(OBJEXT) -rm -f gnu/gcj/runtime/natVMClassLoader.lo + -rm -f gnu/gcj/tools/gcj_dbtool/Main.$(OBJEXT) + -rm -f gnu/gcj/util/Debug.$(OBJEXT) + -rm -f gnu/gcj/util/Debug.lo + -rm -f gnu/gcj/util/natDebug.$(OBJEXT) + -rm -f gnu/gcj/util/natDebug.lo -rm -f gnu/gcj/xlib/Clip.$(OBJEXT) -rm -f gnu/gcj/xlib/Clip.lo -rm -f gnu/gcj/xlib/Colormap.$(OBJEXT) @@ -16531,6 +16402,8 @@ mostlyclean-compile: -rm -f java/lang/UnsupportedOperationException.lo -rm -f java/lang/VMClassLoader.$(OBJEXT) -rm -f java/lang/VMClassLoader.lo + -rm -f java/lang/VMCompiler.$(OBJEXT) + -rm -f java/lang/VMCompiler.lo -rm -f java/lang/VMSecurityManager.$(OBJEXT) -rm -f java/lang/VMSecurityManager.lo -rm -f java/lang/VMThrowable.$(OBJEXT) @@ -18259,14 +18132,8 @@ mostlyclean-compile: -rm -f javax/print/attribute/URISyntax.lo -rm -f javax/print/attribute/UnmodifiableSetException.$(OBJEXT) -rm -f javax/print/attribute/UnmodifiableSetException.lo - -rm -f javax/print/attribute/standard/ColorSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/ColorSupported.lo - -rm -f javax/print/attribute/standard/Compression.$(OBJEXT) - -rm -f javax/print/attribute/standard/Compression.lo -rm -f javax/print/attribute/standard/Copies.$(OBJEXT) -rm -f javax/print/attribute/standard/Copies.lo - -rm -f javax/print/attribute/standard/CopiesSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/CopiesSupported.lo -rm -f javax/print/attribute/standard/DateTimeAtCompleted.$(OBJEXT) -rm -f javax/print/attribute/standard/DateTimeAtCompleted.lo -rm -f javax/print/attribute/standard/DateTimeAtCreation.$(OBJEXT) @@ -18275,30 +18142,20 @@ mostlyclean-compile: -rm -f javax/print/attribute/standard/DateTimeAtProcessing.lo -rm -f javax/print/attribute/standard/DocumentName.$(OBJEXT) -rm -f javax/print/attribute/standard/DocumentName.lo - -rm -f javax/print/attribute/standard/Fidelity.$(OBJEXT) - -rm -f javax/print/attribute/standard/Fidelity.lo - -rm -f javax/print/attribute/standard/Finishings.$(OBJEXT) - -rm -f javax/print/attribute/standard/Finishings.lo -rm -f javax/print/attribute/standard/JobHoldUntil.$(OBJEXT) -rm -f javax/print/attribute/standard/JobHoldUntil.lo -rm -f javax/print/attribute/standard/JobImpressions.$(OBJEXT) -rm -f javax/print/attribute/standard/JobImpressions.lo -rm -f javax/print/attribute/standard/JobImpressionsCompleted.$(OBJEXT) -rm -f javax/print/attribute/standard/JobImpressionsCompleted.lo - -rm -f javax/print/attribute/standard/JobImpressionsSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobImpressionsSupported.lo -rm -f javax/print/attribute/standard/JobKOctets.$(OBJEXT) -rm -f javax/print/attribute/standard/JobKOctets.lo -rm -f javax/print/attribute/standard/JobKOctetsProcessed.$(OBJEXT) -rm -f javax/print/attribute/standard/JobKOctetsProcessed.lo - -rm -f javax/print/attribute/standard/JobKOctetsSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobKOctetsSupported.lo -rm -f javax/print/attribute/standard/JobMediaSheets.$(OBJEXT) -rm -f javax/print/attribute/standard/JobMediaSheets.lo -rm -f javax/print/attribute/standard/JobMediaSheetsCompleted.$(OBJEXT) -rm -f javax/print/attribute/standard/JobMediaSheetsCompleted.lo - -rm -f javax/print/attribute/standard/JobMediaSheetsSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobMediaSheetsSupported.lo -rm -f javax/print/attribute/standard/JobMessageFromOperator.$(OBJEXT) -rm -f javax/print/attribute/standard/JobMessageFromOperator.lo -rm -f javax/print/attribute/standard/JobName.$(OBJEXT) @@ -18309,74 +18166,30 @@ mostlyclean-compile: -rm -f javax/print/attribute/standard/JobPriority.lo -rm -f javax/print/attribute/standard/JobPrioritySupported.$(OBJEXT) -rm -f javax/print/attribute/standard/JobPrioritySupported.lo - -rm -f javax/print/attribute/standard/JobSheets.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobSheets.lo - -rm -f javax/print/attribute/standard/JobState.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobState.lo - -rm -f javax/print/attribute/standard/JobStateReason.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobStateReason.lo - -rm -f javax/print/attribute/standard/JobStateReasons.$(OBJEXT) - -rm -f javax/print/attribute/standard/JobStateReasons.lo - -rm -f javax/print/attribute/standard/Media.$(OBJEXT) - -rm -f javax/print/attribute/standard/Media.lo - -rm -f javax/print/attribute/standard/MediaSizeName.$(OBJEXT) - -rm -f javax/print/attribute/standard/MediaSizeName.lo - -rm -f javax/print/attribute/standard/MultipleDocumentHandling.$(OBJEXT) - -rm -f javax/print/attribute/standard/MultipleDocumentHandling.lo -rm -f javax/print/attribute/standard/NumberOfDocuments.$(OBJEXT) -rm -f javax/print/attribute/standard/NumberOfDocuments.lo -rm -f javax/print/attribute/standard/NumberOfInterveningJobs.$(OBJEXT) -rm -f javax/print/attribute/standard/NumberOfInterveningJobs.lo -rm -f javax/print/attribute/standard/NumberUp.$(OBJEXT) -rm -f javax/print/attribute/standard/NumberUp.lo - -rm -f javax/print/attribute/standard/NumberUpSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/NumberUpSupported.lo - -rm -f javax/print/attribute/standard/OrientationRequested.$(OBJEXT) - -rm -f javax/print/attribute/standard/OrientationRequested.lo -rm -f javax/print/attribute/standard/OutputDeviceAssigned.$(OBJEXT) -rm -f javax/print/attribute/standard/OutputDeviceAssigned.lo - -rm -f javax/print/attribute/standard/PDLOverrideSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/PDLOverrideSupported.lo - -rm -f javax/print/attribute/standard/PageRanges.$(OBJEXT) - -rm -f javax/print/attribute/standard/PageRanges.lo -rm -f javax/print/attribute/standard/PagesPerMinute.$(OBJEXT) -rm -f javax/print/attribute/standard/PagesPerMinute.lo -rm -f javax/print/attribute/standard/PagesPerMinuteColor.$(OBJEXT) -rm -f javax/print/attribute/standard/PagesPerMinuteColor.lo - -rm -f javax/print/attribute/standard/PresentationDirection.$(OBJEXT) - -rm -f javax/print/attribute/standard/PresentationDirection.lo - -rm -f javax/print/attribute/standard/PrintQuality.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrintQuality.lo -rm -f javax/print/attribute/standard/PrinterInfo.$(OBJEXT) -rm -f javax/print/attribute/standard/PrinterInfo.lo - -rm -f javax/print/attribute/standard/PrinterIsAcceptingJobs.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterIsAcceptingJobs.lo -rm -f javax/print/attribute/standard/PrinterLocation.$(OBJEXT) -rm -f javax/print/attribute/standard/PrinterLocation.lo -rm -f javax/print/attribute/standard/PrinterMakeAndModel.$(OBJEXT) -rm -f javax/print/attribute/standard/PrinterMakeAndModel.lo -rm -f javax/print/attribute/standard/PrinterMessageFromOperator.$(OBJEXT) -rm -f javax/print/attribute/standard/PrinterMessageFromOperator.lo - -rm -f javax/print/attribute/standard/PrinterMoreInfo.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterMoreInfo.lo - -rm -f javax/print/attribute/standard/PrinterMoreInfoManufacturer.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterMoreInfoManufacturer.lo -rm -f javax/print/attribute/standard/PrinterName.$(OBJEXT) -rm -f javax/print/attribute/standard/PrinterName.lo - -rm -f javax/print/attribute/standard/PrinterResolution.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterResolution.lo - -rm -f javax/print/attribute/standard/PrinterState.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterState.lo - -rm -f javax/print/attribute/standard/PrinterStateReason.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterStateReason.lo - -rm -f javax/print/attribute/standard/PrinterStateReasons.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterStateReasons.lo - -rm -f javax/print/attribute/standard/PrinterURI.$(OBJEXT) - -rm -f javax/print/attribute/standard/PrinterURI.lo -rm -f javax/print/attribute/standard/QueuedJobCount.$(OBJEXT) -rm -f javax/print/attribute/standard/QueuedJobCount.lo - -rm -f javax/print/attribute/standard/ReferenceUriSchemesSupported.$(OBJEXT) - -rm -f javax/print/attribute/standard/ReferenceUriSchemesSupported.lo -rm -f javax/print/attribute/standard/RequestingUserName.$(OBJEXT) -rm -f javax/print/attribute/standard/RequestingUserName.lo -rm -f javax/print/attribute/standard/Severity.$(OBJEXT) @@ -19490,12 +19303,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gij.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interpret.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jni.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/no-threads.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nogc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posix-threads.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prims.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32-threads.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32.Plo@am__quote@ @@ -19564,6 +19377,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/JNIWeakRef.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/MethodRef.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/NameFinder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/PersistentByteMap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/SharedLibHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/SharedLibLoader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/StackTrace.Plo@am__quote@ @@ -19575,6 +19389,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natStackTrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natStringBuffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natVMClassLoader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/Main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/Debug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/natDebug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/Clip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/Colormap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/Display.Plo@am__quote@ @@ -20555,6 +20372,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/UnsupportedClassVersionError.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/UnsupportedOperationException.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMClassLoader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMCompiler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMSecurityManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMThrowable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VerifyError.Plo@am__quote@ @@ -21419,65 +21237,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/$(DEPDIR)/TextSyntax.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/$(DEPDIR)/URISyntax.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/$(DEPDIR)/UnmodifiableSetException.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/ColorSupported.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Compression.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Copies.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/CopiesSupported.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DateTimeAtCompleted.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DateTimeAtCreation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DateTimeAtProcessing.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DocumentName.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Fidelity.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Finishings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobHoldUntil.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobImpressions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobImpressionsCompleted.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobImpressionsSupported.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobKOctets.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobKOctetsProcessed.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobKOctetsSupported.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMediaSheets.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMediaSheetsCompleted.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMediaSheetsSupported.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMessageFromOperator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobName.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobOriginatingUserName.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobPriority.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobPrioritySupported.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobSheets.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobState.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobStateReason.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobStateReasons.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Media.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/MediaSizeName.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/MultipleDocumentHandling.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberOfDocuments.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberOfInterveningJobs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberUp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberUpSupported.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/OrientationRequested.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/OutputDeviceAssigned.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PDLOverrideSupported.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PageRanges.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PagesPerMinute.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PagesPerMinuteColor.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PresentationDirection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrintQuality.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterInfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterIsAcceptingJobs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterLocation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMakeAndModel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMessageFromOperator.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMoreInfo.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMoreInfoManufacturer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterName.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterResolution.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterState.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterStateReason.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterStateReasons.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterURI.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/QueuedJobCount.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/ReferenceUriSchemesSupported.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/RequestingUserName.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Severity.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/SheetCollate.Plo@am__quote@ @@ -22857,6 +22645,7 @@ clean-libtool: -rm -rf gnu/gcj/convert/.libs gnu/gcj/convert/_libs -rm -rf gnu/gcj/io/.libs gnu/gcj/io/_libs -rm -rf gnu/gcj/runtime/.libs gnu/gcj/runtime/_libs + -rm -rf gnu/gcj/util/.libs gnu/gcj/util/_libs -rm -rf gnu/gcj/xlib/.libs gnu/gcj/xlib/_libs -rm -rf gnu/java/awt/.libs gnu/java/awt/_libs -rm -rf gnu/java/awt/image/.libs gnu/java/awt/image/_libs @@ -23358,6 +23147,10 @@ distclean-generic: -rm -f gnu/gcj/io/$(am__dirstamp) -rm -f gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp) -rm -f gnu/gcj/runtime/$(am__dirstamp) + -rm -f gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp) + -rm -f gnu/gcj/tools/gcj_dbtool/$(am__dirstamp) + -rm -f gnu/gcj/util/$(DEPDIR)/$(am__dirstamp) + -rm -f gnu/gcj/util/$(am__dirstamp) -rm -f gnu/gcj/xlib/$(DEPDIR)/$(am__dirstamp) -rm -f gnu/gcj/xlib/$(am__dirstamp) -rm -f gnu/java/awt/$(DEPDIR)/$(am__dirstamp) @@ -23646,7 +23439,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \ distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR) + -rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-local distclean-tags @@ -23676,7 +23469,7 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR) + -rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/libjava/aclocal.m4 b/libjava/aclocal.m4 index 3afc98f67d2..ffc535707c8 100644 --- a/libjava/aclocal.m4 +++ b/libjava/aclocal.m4 @@ -417,7 +417,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # 02111-1307, USA. AC_DEFUN([AM_PROG_GCJ],[ -AC_CHECK_PROGS(GCJ, [gcj gcj-3.2 gcj-3.1 gcj-3.0 gcj-2.95], gcj) +AC_CHECK_PROGS(GCJ, gcj, gcj) test -z "$GCJ" && AC_MSG_ERROR([no acceptable gcj found in \$PATH]) if test "x${GCJFLAGS-unset}" = xunset; then GCJFLAGS="-g -O2" diff --git a/libjava/boehm.cc b/libjava/boehm.cc index c2a93a57b04..d2902326e81 100644 --- a/libjava/boehm.cc +++ b/libjava/boehm.cc @@ -1,6 +1,7 @@ // boehm.cc - interface between libjava and Boehm GC. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation This file is part of libgcj. @@ -10,6 +11,21 @@ details. */ #include <config.h> +#include <stdio.h> +#include <limits.h> + +#include <jvm.h> +#include <gcj/cni.h> + +#include <java/lang/Class.h> +#include <java/lang/reflect/Modifier.h> +#include <java-interp.h> + +// More nastiness: the GC wants to define TRUE and FALSE. We don't +// need the Java definitions (themselves a hack), so we undefine them. +#undef TRUE +#undef FALSE + extern "C" { #include <gc_config.h> @@ -27,26 +43,20 @@ extern "C" # define GC_REDIRECT_TO_LOCAL # include <gc_local_alloc.h> #endif -}; -#include <stdio.h> -#include <limits.h> - -#include <jvm.h> -#include <gcj/cni.h> - -#include <java/lang/Class.h> -#include <java/lang/reflect/Modifier.h> -#include <java-interp.h> + // From boehm's misc.c + void GC_enable(); + void GC_disable(); +}; -#define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \ - Top=GC_MARK_AND_PUSH((GC_PTR)Obj, Top, Limit, (GC_PTR *)Source) +#define MAYBE_MARK(Obj, Top, Limit, Source) \ + Top=GC_MARK_AND_PUSH((GC_PTR) Obj, Top, Limit, (GC_PTR *) Source) // `kind' index used when allocating Java arrays. static int array_kind_x; // Freelist used for Java arrays. -static void * *array_free_list; +static void **array_free_list; @@ -54,7 +64,7 @@ static void * *array_free_list; // object. We use `void *' arguments and return, and not what the // Boehm GC wants, to avoid pollution in our headers. void * -_Jv_MarkObj (void *addr, void *msp, void *msl, void * env) +_Jv_MarkObj (void *addr, void *msp, void *msl, void *env) { struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp; struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl; @@ -78,11 +88,11 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) # ifndef JV_HASH_SYNCHRONIZATION // Every object has a sync_info pointer. p = (GC_PTR) obj->sync_info; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o1label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); # endif // Mark the object's class. p = (GC_PTR) klass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); if (__builtin_expect (klass == &java::lang::Class::class$, false)) { @@ -101,33 +111,35 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) jclass c = (jclass) addr; p = (GC_PTR) c->name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c3label); + 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, c4label); + 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, c5label); + 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, c5alabel); + 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, c5blabel); - p = (GC_PTR) c->vtable; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel); + 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; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + // If the class is an array, then the methods field holds a // pointer to the element class. If the class is primitive, // then the methods field holds a pointer to the array class. p = (GC_PTR) c->methods; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c6label); + 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 @@ -143,34 +155,35 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) 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, - cm1label); + 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, - cm2label); + 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, c8label); + 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]; -#ifndef COMPACT_FIELDS p = (GC_PTR) field->name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8alabel); -#endif + 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, c8blabel); + 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, c8clabel); + 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 @@ -180,69 +193,110 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) { jobject val = *(jobject*) field->u.addr; p = (GC_PTR) val; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, - c, c8elabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); } } } p = (GC_PTR) c->vtable; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c9label); + 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, cAlabel); + 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, cClabel); + 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, cBlabel); + 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->arrayclass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cDlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->protectionDomain; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cPlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->hack_signers; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cSlabel); + 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, cTlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); #ifdef INTERPRETER - if (_Jv_IsInterpretedClass (c)) + 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, cElabel); + 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, \ - cFlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - // Mark the direct-threaded code. - if ((c->methods[i].accflags - & java::lang::reflect::Modifier::NATIVE) == 0) + 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->prepared; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \ - cFlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); } } - - // 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, - cm3label); } p = (GC_PTR) ic->field_initializers; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cGlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); } #endif @@ -269,8 +323,7 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) { jobject val = JvGetObjectField (obj, field); p = (GC_PTR) val; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, - obj, elabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); } field = field->getNextField (); } @@ -285,7 +338,7 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) // array (of objects). We use `void *' arguments and return, and not // what the Boehm GC wants, to avoid pollution in our headers. void * -_Jv_MarkArray (void *addr, void *msp, void *msl, void * env) +_Jv_MarkArray (void *addr, void *msp, void *msl, void *env) { struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp; struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl; @@ -306,17 +359,17 @@ _Jv_MarkArray (void *addr, void *msp, void *msl, void * env) # ifndef JV_HASH_SYNCHRONIZATION // Every object has a sync_info pointer. p = (GC_PTR) array->sync_info; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e1label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); # endif // Mark the object's class. p = (GC_PTR) klass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas), o2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas)); for (int i = 0; i < JvGetArrayLength (array); ++i) { jobject obj = elements (array)[i]; p = (GC_PTR) obj; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); } return mark_stack_ptr; @@ -364,7 +417,7 @@ _Jv_BuildGCDescr(jclass self) // If we find a field outside the range of our bitmap, // fall back to procedure marker. The bottom 2 bits are // reserved. - if (off >= (unsigned)bits_per_word - 2) + if (off >= (unsigned) bits_per_word - 2) return (void *) (GCJ_DEFAULT_DESCR); desc |= 1ULL << (bits_per_word - off - 1); } @@ -514,10 +567,6 @@ _Jv_GCSetMaximumHeapSize (size_t size) GC_set_max_heap_size ((GC_word) size); } -// From boehm's misc.c -extern "C" void GC_enable(); -extern "C" void GC_disable(); - void _Jv_DisableGC (void) { @@ -585,7 +634,7 @@ _Jv_InitGC (void) proc = GC_new_proc((GC_mark_proc)_Jv_MarkArray); array_kind_x = GC_new_kind(array_free_list, GC_MAKE_PROC (proc, 0), 0, 1); - /* Arrange to have the GC print Java class names in backtraces, etc. */ + // Arrange to have the GC print Java class names in backtraces, etc. GC_register_describe_type_fn(GC_gcj_kind, gcj_describe_type_fn); GC_register_describe_type_fn(GC_gcj_debug_kind, gcj_describe_type_fn); } @@ -640,7 +689,11 @@ _Jv_GCInitializeFinalizers (void (*notifier) (void)) void _Jv_GCRegisterDisappearingLink (jobject *objp) { - GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp); + // This test helps to ensure that we meet a precondition of + // GC_general_register_disappearing_link, viz. "Obj must be a + // pointer to the first word of an object we allocated." + if (GC_base(*objp)) + GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp); } jboolean diff --git a/libjava/configure b/libjava/configure index 5929c250c52..cf52939df11 100755 --- a/libjava/configure +++ b/libjava/configure @@ -310,7 +310,7 @@ ac_includes_default="\ # include <unistd.h> #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS libgcj_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical LN_S mkinstalldirs CC ac_ct_CC EXEEXT OBJEXT CXX ac_ct_CXX CFLAGS CXXFLAGS LDFLAGS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBGCJ_CFLAGS LIBGCJ_CXXFLAGS LIBGCJ_JAVAFLAGS INCLTDL LIBLTDL DIRLTDL LIBTOOL CXXCPP CPPFLAGS GCJ GCJFLAGS GCJDEPMODE am__fastdepGCJ_TRUE am__fastdepGCJ_FALSE subdirs COMPPATH TESTSUBDIR_TRUE TESTSUBDIR_FALSE ONESTEP_TRUE ONESTEP_FALSE LIBGCJDEBUG INTERPRETER LIBFFI LIBFFIINCS PLATFORM_INNER_NAT_HDRS CPP EGREP USING_WIN32_PLATFORM_TRUE USING_WIN32_PLATFORM_FALSE USING_POSIX_PLATFORM_TRUE USING_POSIX_PLATFORM_FALSE USING_ECOS_PLATFORM_TRUE USING_ECOS_PLATFORM_FALSE USING_DARWIN_CRT_TRUE USING_DARWIN_CRT_FALSE SYSTEMSPEC LIBGCJTESTSPEC ZLIBSPEC ZLIBTESTSPEC X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS TOOLKIT XLIB_AWT_TRUE XLIB_AWT_FALSE GTK_AWT_TRUE GTK_AWT_FALSE GTK_CAIRO_TRUE GTK_CAIRO_FALSE PKG_CONFIG CAIRO_CFLAGS CAIRO_LIBS PANGOFT2_CFLAGS PANGOFT2_LIBS GCLIBS GCINCS GCDEPS GCSPEC JC1GCSPEC GCTESTSPEC USING_BOEHMGC_TRUE USING_BOEHMGC_FALSE USING_NOGC_TRUE USING_NOGC_FALSE THREADLIBS THREADINCS THREADDEPS THREADSPEC THREADLDFLAGS THREADCXXFLAGS USING_POSIX_THREADS_TRUE USING_POSIX_THREADS_FALSE USING_WIN32_THREADS_TRUE USING_WIN32_THREADS_FALSE USING_NO_THREADS_TRUE USING_NO_THREADS_FALSE HASH_SYNC_SPEC USING_GCC_TRUE USING_GCC_FALSE tool_include_dir gcc_version LIBICONV LTLIBICONV GTK_CFLAGS GTK_LIBS GLIB_CFLAGS GLIB_LIBS LIBART_CFLAGS LIBART_LIBS SUPPLY_BACKTRACE_TRUE SUPPLY_BACKTRACE_FALSE GCJH ZIP CLASSPATH_SEPARATOR ac_ct_GCJ ZLIBS SYS_ZLIBS ZINCS DIVIDESPEC CHECKREFSPEC EXCEPTIONSPEC IEEESPEC NATIVE_TRUE NATIVE_FALSE NEEDS_DATA_START_TRUE NEEDS_DATA_START_FALSE GCC_UNWIND_INCLUDE toolexecdir toolexecmainlibdir toolexeclibdir GCJVERSION ALLOCA PERL BACKTRACESPEC SYSDEP_SOURCES here LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS libgcj_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical LN_S mkinstalldirs CC ac_ct_CC EXEEXT OBJEXT CXX ac_ct_CXX CFLAGS CXXFLAGS LDFLAGS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBGCJ_CFLAGS LIBGCJ_CXXFLAGS LIBGCJ_JAVAFLAGS LIBGCJ_LD_SYMBOLIC INCLTDL LIBLTDL DIRLTDL LIBTOOL CXXCPP CPPFLAGS GCJ GCJFLAGS GCJDEPMODE am__fastdepGCJ_TRUE am__fastdepGCJ_FALSE subdirs COMPPATH TESTSUBDIR_TRUE TESTSUBDIR_FALSE ONESTEP_TRUE ONESTEP_FALSE LIBGCJDEBUG INTERPRETER LIBFFI LIBFFIINCS PLATFORM_INNER_NAT_HDRS CPP EGREP USING_WIN32_PLATFORM_TRUE USING_WIN32_PLATFORM_FALSE USING_POSIX_PLATFORM_TRUE USING_POSIX_PLATFORM_FALSE USING_ECOS_PLATFORM_TRUE USING_ECOS_PLATFORM_FALSE USING_DARWIN_CRT_TRUE USING_DARWIN_CRT_FALSE SYSTEMSPEC LIBGCJTESTSPEC ZLIBSPEC ZLIBTESTSPEC X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS TOOLKIT XLIB_AWT_TRUE XLIB_AWT_FALSE GTK_AWT_TRUE GTK_AWT_FALSE GTK_CAIRO_TRUE GTK_CAIRO_FALSE PKG_CONFIG CAIRO_CFLAGS CAIRO_LIBS PANGOFT2_CFLAGS PANGOFT2_LIBS GCLIBS GCINCS GCDEPS GCSPEC JC1GCSPEC GCTESTSPEC USING_BOEHMGC_TRUE USING_BOEHMGC_FALSE USING_NOGC_TRUE USING_NOGC_FALSE THREADLIBS THREADINCS THREADDEPS THREADSPEC THREADLDFLAGS THREADCXXFLAGS USING_POSIX_THREADS_TRUE USING_POSIX_THREADS_FALSE USING_WIN32_THREADS_TRUE USING_WIN32_THREADS_FALSE USING_NO_THREADS_TRUE USING_NO_THREADS_FALSE HASH_SYNC_SPEC USING_GCC_TRUE USING_GCC_FALSE tool_include_dir gcc_version LIBICONV LTLIBICONV GTK_CFLAGS GTK_LIBS GLIB_CFLAGS GLIB_LIBS LIBART_CFLAGS LIBART_LIBS SUPPLY_BACKTRACE_TRUE SUPPLY_BACKTRACE_FALSE GCJH ZIP CLASSPATH_SEPARATOR ac_ct_GCJ ZLIBS SYS_ZLIBS ZINCS DIVIDESPEC CHECKREFSPEC EXCEPTIONSPEC IEEESPEC NATIVE_TRUE NATIVE_FALSE NEEDS_DATA_START_TRUE NEEDS_DATA_START_FALSE GCC_UNWIND_INCLUDE toolexecdir toolexecmainlibdir toolexeclibdir GCJVERSION ALLOCA PERL BACKTRACESPEC SYSDEP_SOURCES here LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -3983,6 +3983,8 @@ libgcj_javaflags= LIBGCJ_CFLAGS="${libgcj_cflags}" LIBGCJ_CXXFLAGS="${libgcj_cxxflags}" LIBGCJ_JAVAFLAGS="${libgcj_javaflags}" +LIBGCJ_LD_SYMBOLIC="${libgcj_ld_symbolic}" + @@ -4741,7 +4743,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic" case $host in *-*-irix6*) # Find out which ABI we are using. - echo '#line 4744 "configure"' > conftest.$ac_ext + echo '#line 4746 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -5772,7 +5774,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then : else cat > conftest.$ac_ext << EOF -#line 5775 "configure" +#line 5777 "configure" struct S { ~S(); }; void bar(); void foo() @@ -17182,6 +17184,7 @@ s,@MAINT@,$MAINT,;t t s,@LIBGCJ_CFLAGS@,$LIBGCJ_CFLAGS,;t t s,@LIBGCJ_CXXFLAGS@,$LIBGCJ_CXXFLAGS,;t t s,@LIBGCJ_JAVAFLAGS@,$LIBGCJ_JAVAFLAGS,;t t +s,@LIBGCJ_LD_SYMBOLIC@,$LIBGCJ_LD_SYMBOLIC,;t t s,@INCLTDL@,$INCLTDL,;t t s,@LIBLTDL@,$LIBLTDL,;t t s,@DIRLTDL@,$DIRLTDL,;t t diff --git a/libjava/configure.ac b/libjava/configure.ac index 269b64a3e6c..43156b7f68d 100644 --- a/libjava/configure.ac +++ b/libjava/configure.ac @@ -134,9 +134,11 @@ libgcj_javaflags= LIBGCJ_CFLAGS="${libgcj_cflags}" LIBGCJ_CXXFLAGS="${libgcj_cxxflags}" LIBGCJ_JAVAFLAGS="${libgcj_javaflags}" +LIBGCJ_LD_SYMBOLIC="${libgcj_ld_symbolic}" AC_SUBST(LIBGCJ_CFLAGS) AC_SUBST(LIBGCJ_CXXFLAGS) AC_SUBST(LIBGCJ_JAVAFLAGS) +AC_SUBST(LIBGCJ_LD_SYMBOLIC) AC_CONFIG_HEADERS([include/config.h gcj/libgcj-config.h]) diff --git a/libjava/configure.host b/libjava/configure.host index 437566a3079..e1eaa1bab1e 100644 --- a/libjava/configure.host +++ b/libjava/configure.host @@ -173,6 +173,7 @@ case "${host}" in hppa*-linux* | \ sh-linux* | sh[34]*-linux*) can_unwind_signal=yes + libgcj_ld_symbolic='-Wl,-Bsymbolic' if test x$slow_pthread_self = xyes \ && test x$cross_compiling != xyes; then cat > conftest.c <<EOF @@ -226,7 +227,6 @@ EOF mips*-*-linux* ) sysdeps_dir=mips can_unwind_signal=yes - libgcj_interpreter=yes libgcj_flags="${libgcj_flags} -mxgot" DIVIDESPEC=-fno-use-divide-subroutine case "${host}" in diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc index 86df0d2aa72..1a0c4e4da60 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 Free Software Foundation +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -26,6 +26,7 @@ details. */ #include <stdio.h> #include <java-cpool.h> #include <gcj/cni.h> +#include <execution.h> #include <java/lang/Class.h> #include <java/lang/Float.h> @@ -38,6 +39,7 @@ details. */ #include <java/lang/ClassCircularityError.h> #include <java/lang/IncompatibleClassChangeError.h> #include <java/lang/reflect/Modifier.h> +#include <java/security/ProtectionDomain.h> using namespace gcj; @@ -216,7 +218,8 @@ struct _Jv_ClassReader { throw_class_format_error ("erroneous type descriptor"); } - _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length) + _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length, + java::security::ProtectionDomain *pd) { if (klass == 0 || length < 0 || offset+length > data->length) throw_internal_error ("arguments to _Jv_DefineClass"); @@ -226,7 +229,10 @@ struct _Jv_ClassReader { len = length; pos = 0; def = klass; - def_interp = (_Jv_InterpClass *) def->aux_info; + def->size_in_bytes = -1; + def->vtable_method_count = -1; + def->engine = &_Jv_soleInterpreterEngine; + def->protectionDomain = pd; } /** and here goes the parser members defined out-of-line */ @@ -273,9 +279,10 @@ struct _Jv_ClassReader { }; void -_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length) +_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length, + java::security::ProtectionDomain *pd) { - _Jv_ClassReader reader (klass, data, offset, length); + _Jv_ClassReader reader (klass, data, offset, length, pd); reader.parse(); /* that's it! */ @@ -311,8 +318,13 @@ _Jv_ClassReader::parse () handleClassBegin (access_flags, this_class, super_class); + // 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_interp = (_Jv_InterpClass *) def->aux_info; + int interfaces_count = read2u (); - + handleInterfacesBegin (interfaces_count); for (int i = 0; i < interfaces_count; i++) @@ -335,12 +347,11 @@ _Jv_ClassReader::parse () if (pos != len) throw_class_format_error ("unused data before end of file"); - // tell everyone we're done. - def->state = JV_STATE_LOADED; + // Tell everyone we're done. + def->state = JV_STATE_READ; if (gcj::verbose_class_flag) - fprintf (stderr, "[Loaded (bytecode) %s]\n", def->name->chars()); + _Jv_Linker::print_class_loaded (def); def->notifyAll (); - } void _Jv_ClassReader::read_constpool () @@ -517,30 +528,20 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index) throw_class_format_error ("only one Exceptions attribute allowed per method"); int num_exceptions = read2u (); - // We use malloc here because the GC won't scan the method - // objects. FIXME this means a memory leak if we GC a class. - // (Currently we never do.) _Jv_Utf8Const **exceptions = - (_Jv_Utf8Const **) _Jv_Malloc ((num_exceptions + 1) * sizeof (_Jv_Utf8Const *)); + (_Jv_Utf8Const **) _Jv_AllocBytes ((num_exceptions + 1) + * sizeof (_Jv_Utf8Const *)); int out = 0; _Jv_word *pool_data = def->constants.data; for (int i = 0; i < num_exceptions; ++i) { - try + int ndx = read2u (); + // JLS 2nd Ed. 4.7.5 requires that the tag not be 0. + if (ndx != 0) { - int ndx = read2u (); - // JLS 2nd Ed. 4.7.5 requires that the tag not be 0. - if (ndx != 0) - { - check_tag (ndx, JV_CONSTANT_Class); - exceptions[out++] = pool_data[ndx].utf8; - } - } - catch (java::lang::Throwable *exc) - { - _Jv_Free (exceptions); - throw exc; + check_tag (ndx, JV_CONSTANT_Class); + exceptions[out++] = pool_data[ndx].utf8; } } exceptions[out] = NULL; @@ -854,8 +855,7 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag) void -_Jv_ClassReader::handleClassBegin - (int access_flags, int this_class, int super_class) +_Jv_ClassReader::handleClassBegin (int access_flags, int this_class, int super_class) { using namespace java::lang::reflect; @@ -950,23 +950,25 @@ _Jv_ClassReader::handleClassBegin def->notifyAll (); } -///// implements the checks described in sect. 5.3.5.3 +///// Implements the checks described in sect. 5.3.5.3 void _Jv_ClassReader::checkExtends (jclass sub, jclass super) { using namespace java::lang::reflect; - // having an interface or a final class as a superclass is no good + _Jv_Linker::wait_for_state (super, JV_STATE_LOADING); + + // Having an interface or a final class as a superclass is no good. if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0) { throw_incompatible_class_change_error (sub->getName ()); } - // if the super class is not public, we need to check some more + // If the super class is not public, we need to check some more. if ((super->accflags & Modifier::PUBLIC) == 0) { - // With package scope, the classes must have the same - // class loader. + // With package scope, the classes must have the same class + // loader. if ( sub->loader != super->loader || !_Jv_ClassNameSamePackage (sub->name, super->name)) { @@ -974,7 +976,7 @@ _Jv_ClassReader::checkExtends (jclass sub, jclass super) } } - for (; super != 0; super = super->superclass) + for (; super != 0; super = super->getSuperclass ()) { if (super == sub) throw_class_circularity_error (sub->getName ()); @@ -1072,11 +1074,7 @@ void _Jv_ClassReader::handleField (int field_no, _Jv_Field *field = &def->fields[field_no]; _Jv_Utf8Const *field_name = pool_data[name].utf8; -#ifndef COMPACT_FIELDS field->name = field_name; -#else - field->nameIndex = name; -#endif // Ignore flags we don't know about. field->flags = flags & Modifier::ALL_FLAGS; @@ -1234,7 +1232,7 @@ void _Jv_ClassReader::handleMethod // ignore unknown flags method->accflags = accflags & Modifier::ALL_FLAGS; - // intialize... + // Initialize... method->ncode = 0; method->throws = NULL; @@ -1276,7 +1274,6 @@ void _Jv_ClassReader::handleCodeAttribute _Jv_InterpMethod *method = (_Jv_InterpMethod*) (_Jv_AllocBytes (size)); - method->deferred = NULL; method->max_stack = max_stack; method->max_locals = max_locals; method->code_length = code_length; @@ -1335,7 +1332,6 @@ void _Jv_ClassReader::handleMethodsEnd () m->self = method; m->function = NULL; def_interp->interpreted_methods[i] = m; - m->deferred = NULL; if ((method->accflags & Modifier::STATIC)) { @@ -1626,7 +1622,7 @@ _Jv_VerifyClassName (_Jv_Utf8Const *name) } /* Returns true, if NAME1 and NAME2 represent classes in the same - package. */ + package. Neither NAME2 nor NAME2 may name an array type. */ bool _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2) { diff --git a/libjava/gcj/Makefile.in b/libjava/gcj/Makefile.in index b4c32fb9ea1..b40dd2a398a 100644 --- a/libjava/gcj/Makefile.in +++ b/libjava/gcj/Makefile.in @@ -146,6 +146,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@ LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@ LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@ LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@ +LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@ LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBOBJS = @LIBOBJS@ diff --git a/libjava/gcj/field.h b/libjava/gcj/field.h index bd6b2c38046..8421bc7e046 100644 --- a/libjava/gcj/field.h +++ b/libjava/gcj/field.h @@ -1,6 +1,6 @@ // field.h - Header file for fieldID instances. -*- c++ -*- -/* Copyright (C) 1998, 1999, 2000 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation This file is part of libgcj. @@ -21,9 +21,7 @@ details. */ struct _Jv_Field { -#ifndef COMPACT_FIELDS struct _Jv_Utf8Const* name; -#endif /* The type of the field, if isResolved(). If !isResolved(): The fields's signature as a (Utf8Const*). */ @@ -31,11 +29,7 @@ struct _Jv_Field _Jv_ushort flags; -#ifdef COMPACT_FIELDS - jshort nameIndex; /* offset in class's name table */ -#else _Jv_ushort bsize; /* not really needed ... */ -#endif union { jint boffset; /* offset in bytes for instance field */ @@ -91,13 +85,8 @@ struct _Jv_Field return flags & java::lang::reflect::Modifier::ALL_FLAGS; } -#ifdef COMPACT_FIELDS - _Jv_Utf8Const * getNameUtf8Const (jclass cls) - { return clas->fieldNames + nameIndex; } -#else _Jv_Utf8Const * getNameUtf8Const (jclass) { return name; } #endif -#endif }; #ifdef __cplusplus diff --git a/libjava/gcj/javaprims.h b/libjava/gcj/javaprims.h index 3120184650f..53c26fe1a8e 100644 --- a/libjava/gcj/javaprims.h +++ b/libjava/gcj/javaprims.h @@ -1,5 +1,6 @@ // javaprims.h - Main external header file for libgcj. -*- c++ -*- + /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation @@ -84,6 +85,7 @@ extern "Java" class LineNumberInputStream; class LineNumberReader; class MemberComparator; + class MyIOException; class NotActiveException; class NotSerializableException; class ObjectInput; @@ -214,6 +216,7 @@ extern "Java" class UnsupportedClassVersionError; class UnsupportedOperationException; class VMClassLoader; + class VMCompiler; class VMSecurityManager; class VMThrowable; class VerifyError; diff --git a/libjava/gij.cc b/libjava/gij.cc index 8c75fa6db7a..64457857a13 100644 --- a/libjava/gij.cc +++ b/libjava/gij.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -35,6 +35,7 @@ help () printf (" -X print help on supported -X options, then exit\n"); printf (" --ms=NUMBER set initial heap size\n"); printf (" --mx=NUMBER set maximum heap size\n"); + printf (" --verbose[:class] print information about class loading\n"); printf (" --showversion print version number, then keep going\n"); printf (" --version print version number, then exit\n"); printf ("\nOptions can be specified with `-' or `--'.\n"); @@ -133,7 +134,7 @@ main (int argc, const char **argv) // correct behavior. _Jv_Jar_Class_Path = argv[++i]; } - else if (! strcmp (arg, "-verbose:class")) + else if (! strcmp (arg, "-verbose") || ! strcmp (arg, "-verbose:class")) gcj::verbose_class_flag = true; else if (arg[1] == 'X') { diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap.java b/libjava/gnu/gcj/runtime/PersistentByteMap.java new file mode 100644 index 00000000000..90b7d33a8f4 --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap.java @@ -0,0 +1,484 @@ +/* Copyright (C) 2004 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + + + +/* A PersistentByteMap maps a byte array to another byte array. It +uses a file that does not need to be serialized but may be +memory-mapped and read in-place. So, even if there are many instances +of gcj applications running, the can share PersistentByteMaps. + +The idea is to make searches as fast as possible: opening a +PersistentByteMap is cheap and search time doesn't grow with the +number of entries in the table. On the other hand, enumerating the +map is slow, but that is a relatively uncommon operation. + +The main use of this class is to provide a way to map the +MessageDigest of a class file to the location of a DSO that contains +the compiled version of that class. It is up the the installer of an +application to keep the DSO up to date with the jar. + +USAGE: + MessageDigest md = MessageDigest.getInstance("MD5"); + digest = md.digest(bytes); + + PersistentByteMap map + = new PersistentByteMap + (fileName, PersistentByteMap.AccessMode.READ_ONLY); + + byte[] soName = map.get(digest); + if (soName) + { + String SharedLibraryName = new String(soName); + +BUGS/FEATURES: + remove() isn't written yet. + + we can't change the capacity of a PersistentByteMap. + + 0x12345678 is a bad choice for the magic number. + + capacity is fixed once the map has been created. + + We use linear probing to resolve collisions. It might be + better to use a scheme that results in fewer probes to + determine that an item isn't found. However, even when the + table is half full there are only on average 1.5 probes for a + successful search and 2.5 probes for an unsuccessful one. + + We don't use unique strings. This wastes space. + + capacity should probably be prime, but we don't check that. + + we don't do any locking at all: adding to a PersistentByteMap + at runtime is possible, but it requires filesystem locks + around get(), put(), and remove(). +*/ + +package gnu.gcj.runtime; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.*; +import java.security.MessageDigest; + +public class PersistentByteMap +{ + private MappedByteBuffer buf; + + static private final int MAGIC = 0; + static private final int VERSION = 4; + static private final int CAPACITY = 8; + static private final int TABLE_BASE = 12; + static private final int STRING_BASE = 16; + static private final int STRING_SIZE = 20; + static private final int FILE_SIZE = 24; + static private final int ELEMENTS = 28; + + static private final int INT_SIZE = 4; + + static private final int TABLE_ENTRY_SIZE = 2 * INT_SIZE; + + private int capacity; // number of entries + private int table_base; // offset from start of file, in bytes + private int string_base; // offset from start of file, in bytes + private int string_size; // size of string table, in bytes + private int file_size; // size of file, in bytes; + private int elements; // number of elements in table + + private long length; // the length of the underlying file + + static private final int UNUSED_ENTRY = -1; + + static public final int KEYS = 0; + static public final int VALUES = 1; + static public final int ENTRIES = 2; + + static final public class AccessMode + { + private final FileChannel.MapMode mapMode; + + static + { + READ_ONLY = new AccessMode(FileChannel.MapMode.READ_ONLY); + READ_WRITE = new AccessMode(FileChannel.MapMode.READ_WRITE); + } + + public static final AccessMode READ_ONLY; + public static final AccessMode READ_WRITE; + + private AccessMode(FileChannel.MapMode mode) + { + this.mapMode = mode; + } + } + + private PersistentByteMap() + { + } + + public PersistentByteMap(String filename, AccessMode mode) + throws IOException + { + this(new File(filename), mode); + } + + public PersistentByteMap(File f, AccessMode mode) + throws IOException + { + FileChannel fc; + + if (mode == AccessMode.READ_ONLY) + { + FileInputStream fis = new FileInputStream(f); + fc = fis.getChannel(); + } + else + { + RandomAccessFile fos = new RandomAccessFile(f, "rw"); + fc = fos.getChannel(); + } + + length = fc.size(); + buf = fc.map(mode.mapMode, 0, length); + + int magic = getWord (MAGIC); + if (magic != 0x12345678) + throw new IllegalArgumentException(f.getName()); + + table_base = getWord (TABLE_BASE); + capacity = getWord (CAPACITY); + string_base = getWord (STRING_BASE); + string_size = getWord (STRING_SIZE); + file_size = getWord (FILE_SIZE); + elements = getWord (ELEMENTS); + + // FIXME: Insert a bunch of sanity checks here + } + + private void init (PersistentByteMap m, File f, int capacity, int strtabSize) + throws IOException + { + f.createNewFile(); + RandomAccessFile raf = new RandomAccessFile(f, "rw"); + + this.capacity = capacity; + table_base = 64; + string_base = table_base + capacity * TABLE_ENTRY_SIZE; + string_size = 0; + file_size = string_base; + elements = 0; + + int totalFileSize = string_base + strtabSize; + + // Create the file; this rounds up the size of the file to a fixed + // number of 4k pages. + byte[] _4k = new byte[4096]; + for (long i = 0; i < totalFileSize; i+= 4096) + raf.write(_4k); + + FileChannel fc = raf.getChannel(); + buf = fc.map(FileChannel.MapMode.READ_WRITE, 0, raf.length()); + + for (int i = 0; i < capacity; i++) + putKeyPos(UNUSED_ENTRY, i); + + putWord(0x12345678, MAGIC); + putWord(0x01, VERSION); + putWord(capacity, CAPACITY); + putWord(table_base, TABLE_BASE); + putWord(string_base, STRING_BASE); + putWord(file_size, FILE_SIZE); + putWord(elements, ELEMENTS); + buf.force(); + } + + static public PersistentByteMap emptyPersistentByteMap(String filename, + int capacity, int strtabSize) + throws IOException + { + File f = new File(filename); + PersistentByteMap m = new PersistentByteMap(); + m.init(m, f, capacity, strtabSize); + return m; + } + + private int getWord (int index) + { + buf.position(index); + byte[] wordBuf = new byte[4]; + buf.get(wordBuf); + + int result = (int)wordBuf[0]&0xff; + result += ((int)wordBuf[1]&0xff) << 8; + result += ((int)wordBuf[2]&0xff) << 16; + result += ((int)wordBuf[3]&0xff) << 24; + return result; + } + + private void putWord (int word, int index) + { + buf.position(index); + byte[] wordBuf = new byte[4]; + wordBuf[0] = (byte)(word); + wordBuf[1] = (byte)(word >>> 8); + wordBuf[2] = (byte)(word >>> 16); + wordBuf[3] = (byte)(word >>> 24); + buf.put(wordBuf); + } + + public Set entrySet() + { + return null; + } + + private int getBucket(int n) + { + return table_base + (2*n * INT_SIZE); + } + + private int getKeyPos(int n) + { + return getWord(getBucket(n)); + } + + private int getValuePos(int n) + { + return getWord(getBucket(n) + INT_SIZE); + } + + private void putKeyPos(int index, int n) + { + putWord(index, getBucket(n)); + } + + private void putValuePos(int index, int n) + { + putWord(index, getBucket(n) + INT_SIZE); + } + + private byte[] getBytes(int n) + { + int len = getWord (string_base + n); + int base = string_base + n + INT_SIZE; + byte[] key = new byte[len]; + buf.position(base); + buf.get(key, 0, len); + return key; + } + + private int hash (byte[] b) + { + // We assume that the message digest is evenly distributed, so we + // only need to use a few bytes of it as the hash function. + long hashIndex + = ((b[0]&0xffL) + + ((b[1]&0xffL)<<8) + + ((b[2]&0xffL)<<16) + + ((b[3]&0xffL)<<24)); + long result = hashIndex % (long)capacity; + return (int)result; + } + + public byte[] get(byte[] digest) + { + int hashIndex = hash(digest); + + do + { + int k = getKeyPos(hashIndex); + if (k == UNUSED_ENTRY) + return null; + + if (Arrays.equals ((byte[])digest, getBytes(k))) + return getBytes(getValuePos(hashIndex)); + + // Use linear probing to resolve hash collisions. This may + // not be theoretically as good as open addressing, but it has + // good cache behviour. + hashIndex++; + hashIndex %= capacity; + } + while (true); + } + + public void put(byte[] digest, byte[] value) + throws IllegalAccessException + { + int hashIndex = hash(digest); + + // With the the table 2/3 full there will be on average 2 probes + // for a successful search and 5 probes for an unsuccessful one. + if (elements >= capacity * 2/3) + throw new IllegalAccessException("Table Full: " + elements); + + do + { + int k = getKeyPos(hashIndex); + if (k == UNUSED_ENTRY) + { + int newKey = addBytes(digest); + putKeyPos(newKey, hashIndex); + int newValue = addBytes(value); + putValuePos(newValue, hashIndex); + elements++; + putWord(elements, ELEMENTS); + return; + } + else if (Arrays.equals (digest, getBytes(k))) + { + int newValue = addBytes((byte[])value); + putValuePos(newValue, hashIndex); + return; + } + + hashIndex++; + hashIndex %= capacity; + } + while (true); + } + + private int addBytes (byte[] data) + throws IllegalAccessException + { + if (data.length + INT_SIZE >= this.length) + throw new IllegalAccessException("String table Full"); + + int extent = string_base+string_size; + int top = extent; + putWord(data.length, extent); + extent += INT_SIZE; + buf.position(extent); + buf.put(data, 0, data.length); + extent += data.length; + extent += INT_SIZE-1; + extent &= ~(INT_SIZE-1); // align + string_size = extent - string_base; + file_size = extent; + putWord (string_size, STRING_SIZE); + putWord (file_size, FILE_SIZE); + + return top - string_base; + } + + public Iterator iterator(int type) + { + return new HashIterator(type); + } + + public int size() + { + return elements; + } + + public int capacity() + { + return capacity; + } + + private final class HashIterator implements Iterator + { + /** Current index in the physical hash table. */ + + private int idx; + private int count; + private final int type; + + /** + * Construct a new HashIterator with the supplied type. + * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES} + */ + HashIterator(int type) + { + this.type = type; + count = elements; + idx = 0; + } + + /** + * Returns true if the Iterator has more elements. + * @return true if there are more elements + * @throws ConcurrentModificationException if the HashMap was modified + */ + public boolean hasNext() + { + return count > 0; + } + + /** + * Returns the next element in the Iterator's sequential view. + * @return the next element + * @throws ConcurrentModificationException if the HashMap was modified + * @throws NoSuchElementException if there is none + */ + public Object next() + { + count--; + for (int i = idx; i < capacity; i++) + if (getKeyPos(i) != UNUSED_ENTRY) + { + idx = i+1; + if (type == VALUES) + return getBytes(getValuePos(i)); + if (type == KEYS) + return getBytes(getKeyPos(i)); + return new MapEntry(i, + getBytes(getKeyPos(i)), + getBytes(getValuePos(i))); + } + return null; + } + + /** + * Remove from the underlying collection the last element returned + * by next (optional operation). This method can be called only + * once after each call to <code>next()</code>. It does not affect + * what will be returned by subsequent calls to next. + * + * @throws IllegalStateException if next has not yet been called + * or remove has already been called since the last call + * to next. + * @throws UnsupportedOperationException if this Iterator does not + * support the remove operation. + */ + public void remove() + { + throw new UnsupportedOperationException(); + } + } + + static public final class MapEntry + { + private final Object key; + private final Object value; + private final int bucket; + + public MapEntry(int bucket, Object newKey, Object newValue) + { + this.key = newKey; + this.value = newValue; + this.bucket = bucket; + } + + public final Object getKey() + { + return key; + } + + public final Object getValue() + { + return value; + } + + public final int getBucket() + { + return bucket; + } + } +} diff --git a/libjava/gnu/gcj/runtime/SharedLibHelper.java b/libjava/gnu/gcj/runtime/SharedLibHelper.java index 9e170a120be..a0bfe68b83c 100644 --- a/libjava/gnu/gcj/runtime/SharedLibHelper.java +++ b/libjava/gnu/gcj/runtime/SharedLibHelper.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2003 Free Software Foundation +/* Copyright (C) 2001, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -13,6 +13,12 @@ import java.net.MalformedURLException; import java.util.HashMap; import java.security.*; import gnu.gcj.Core; +import java.util.Set; +import java.util.Iterator; +import java.util.HashSet; +import java.util.HashMap; +import java.nio.channels.FileChannel; +import java.io.*; public class SharedLibHelper { @@ -36,34 +42,82 @@ public class SharedLibHelper { synchronized (map) { - WeakReference ref = (WeakReference) map.get(libname); - if (ref != null) - return (SharedLibHelper) ref.get(); + Set s = (Set)map.get(libname); + if (s == null) + return null; + for (Iterator i=s.iterator(); i.hasNext();) + { + WeakReference ref = (WeakReference)i.next(); + if (ref != null) + return (SharedLibHelper) ref.get(); + } return null; } } + static void copyFile (File in, File out) throws IOException + { + FileChannel source = new FileInputStream(in).getChannel(); + FileChannel destination = new FileOutputStream(out).getChannel(); + source.transferTo(0, source.size(), destination); + source.close(); + destination.close(); + } + public static SharedLibHelper findHelper (ClassLoader loader, String libname, CodeSource source) { synchronized (map) { SharedLibHelper result; - WeakReference ref = (WeakReference) map.get(libname); - if (ref != null) + Set s = (Set)map.get(libname); + if (s == null) + { + s = new HashSet(); + map.put(libname, s); + } + else { - result = (SharedLibHelper) ref.get(); - if (result != null) + for (Iterator i=s.iterator(); i.hasNext();) { - if (result.loader != loader) - // FIXME - throw new UnknownError(); - return result; + WeakReference ref = (WeakReference)i.next(); + if (ref != null) + { + result = (SharedLibHelper) ref.get(); + if (result != null) + { + // A match succeeds if the library is already + // loaded by LOADER or any of its ancestors. + ClassLoader l = loader; + do + { + if (result.loader == l) + return result; + l = l.getParent(); + } + while (l != null); + } + } } - } + // Oh dear. We've already mapped this shared library, but + // with a different class loader. We need to copy it. + try + { + File copy + = File.createTempFile(new File(libname).getName(), + ".so", new File ("/tmp")); + File src = new File(libname); + copyFile (src, copy); + libname = copy.getPath(); + } + catch (IOException e) + { + return null; + } + } result = new SharedLibHelper(libname, loader, source, 0); - map.put(libname, new WeakReference(result)); + s.add(new WeakReference(result)); return result; } } @@ -73,7 +127,15 @@ public class SharedLibHelper public Class findClass(String name) { ensureInit(); - return (Class) classMap.get(name); + Class result = (Class) classMap.get(name); + if (result != null) + { + // We never want to return a class without its supers linked. + // It isn't clear from the spec, but this is what other + // implementations do in practice. + ensureSupersLinked(result); + } + return result; } public URL findResource (String name) @@ -106,6 +168,12 @@ public class SharedLibHelper native boolean hasResource(String name); native void init(); + native void ensureSupersLinked(Class k); + + public String toString () + { + return "shared object " + baseName; + } /** Called during dlopen's processing of the init section. */ void registerClass(String name, Class cls) diff --git a/libjava/gnu/gcj/runtime/VMClassLoader.java b/libjava/gnu/gcj/runtime/VMClassLoader.java index 1fc7081bb78..f9ef872b30a 100644 --- a/libjava/gnu/gcj/runtime/VMClassLoader.java +++ b/libjava/gnu/gcj/runtime/VMClassLoader.java @@ -105,7 +105,8 @@ public final class VMClassLoader extends java.net.URLClassLoader /** This is overridden to search the internal hash table, which * will only search existing linked-in classes. This will make * the default implementation of loadClass (in ClassLoader) work right. - * The implementation of this method is in java/lang/natClassLoader.cc. + * The implementation of this method is in + * gnu/gcj/runtime/natVMClassLoader.cc. */ protected native Class findClass(String name) throws java.lang.ClassNotFoundException; diff --git a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc index 46eef755a09..184692e1040 100644 --- a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc +++ b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc @@ -1,6 +1,6 @@ // natSharedLibLoader.cc - Implementation of SharedLibHelper native methods. -/* Copyright (C) 2001, 2003 Free Software Foundation +/* Copyright (C) 2001, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -12,6 +12,8 @@ details. */ #include <gcj/cni.h> #include <jvm.h> +#include <execution.h> + #include <gnu/gcj/runtime/SharedLibHelper.h> #include <java/io/IOException.h> #include <java/lang/UnsupportedOperationException.h> @@ -30,9 +32,10 @@ typedef void (*CoreHookFunc) (_Jv_core_chain *); void _Jv_sharedlib_register_hook (jclass cls) { - curHelper->registerClass(cls->getName(), cls); cls->protectionDomain = curHelper->domain; cls->loader = curLoader; + cls->engine = &_Jv_soleCompiledEngine; + curHelper->registerClass(cls->getName(), cls); } static void @@ -122,3 +125,9 @@ gnu::gcj::runtime::SharedLibHelper::finalize() dlclose (handler); #endif } + +void +gnu::gcj::runtime::SharedLibHelper::ensureSupersLinked(jclass k) +{ + _Jv_Linker::wait_for_state (k, JV_STATE_LOADING); +} diff --git a/libjava/gnu/gcj/tools/gcj_dbtool/Main.java b/libjava/gnu/gcj/tools/gcj_dbtool/Main.java new file mode 100644 index 00000000000..a478f934297 --- /dev/null +++ b/libjava/gnu/gcj/tools/gcj_dbtool/Main.java @@ -0,0 +1,272 @@ +/* Copyright (C) 2004 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.gcj.tools.gcj_dbtool; + + +import gnu.gcj.runtime.PersistentByteMap; +import java.io.*; +import java.util.*; +import java.util.jar.*; +import java.security.MessageDigest; +import java.math.BigInteger; + +public class Main +{ + public static void main (String[] s) + { + insist (s.length >= 1); + if (s[0].equals("-v")) + { + insist (s.length == 1); + System.out.println("jv-dbtool (" + + System.getProperty("java.vm.name") + + ") " + + System.getProperty("java.vm.version")); + System.out.println(); + System.out.println("Copyright 2004 Free Software Foundation, Inc."); + System.out.println("This is free software; see the source for copying conditions. There is NO"); + System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."); + return; + } + + if (s[0].equals("-n")) + { + insist (s.length >= 2 && s.length <= 3); + + int capacity = 32749; + + if (s.length == 3) + { + // The user has explicitly provided a size for the table. + // We're going to make that size prime. This isn't + // strictly necessary but it can't hurt. + + BigInteger size = new BigInteger(s[2], 10); + BigInteger two = BigInteger.ONE.add(BigInteger.ONE); + + if (size.getLowestSetBit() != 0) // A hard way to say isEven() + size = size.add(BigInteger.ONE); + + while (! size.isProbablePrime(10)) + size = size.add(two); + + capacity = size.intValue(); + + if (capacity <= 2) + { + usage(); + System.exit(1); + } + } + + try + { + PersistentByteMap b + = PersistentByteMap.emptyPersistentByteMap (s[1], capacity, capacity*64); + } + catch (Exception e) + { + System.err.println ("error: could not create " + + s[1] + ": " + e.toString()); + System.exit(2); + } + return; + } + + if (s[0].equals("-a")) + { + try + { + insist (s.length == 4); + File jar = new File(s[2]); + PersistentByteMap b + = new PersistentByteMap(new File(s[1]), + PersistentByteMap.AccessMode.READ_WRITE); + File soFile = new File(s[3]); + if (! soFile.isFile()) + throw new IllegalArgumentException(s[3] + " is not a file"); + + addJar(jar, b, soFile); + } + catch (Exception e) + { + System.err.println ("error: could not update " + s[1] + + ": " + e.toString()); + System.exit(2); + } + return; + } + + if (s[0].equals("-t")) + { + try + { + insist (s.length == 2); + PersistentByteMap b + = new PersistentByteMap(new File(s[1]), + PersistentByteMap.AccessMode.READ_ONLY); + Iterator iterator = b.iterator(PersistentByteMap.ENTRIES); + + while (iterator.hasNext()) + { + PersistentByteMap.MapEntry entry + = (PersistentByteMap.MapEntry)iterator.next(); + byte[] key = (byte[])entry.getKey(); + byte[] value = (byte[])b.get(key); + if (! Arrays.equals (value, (byte[])entry.getValue())) + { + String err + = ("Key " + bytesToString(key) + " at bucket " + + entry.getBucket()); + + throw new RuntimeException(err); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + System.exit(3); + } + return; + } + + if (s[0].equals("-l")) + { + insist (s.length == 2); + try + { + PersistentByteMap b + = new PersistentByteMap(new File(s[1]), + PersistentByteMap.AccessMode.READ_ONLY); + + System.out.println ("Capacity: " + b.capacity()); + System.out.println ("Size: " + b.size()); + System.out.println (); + + System.out.println ("Elements: "); + Iterator iterator = b.iterator(PersistentByteMap.ENTRIES); + + while (iterator.hasNext()) + { + PersistentByteMap.MapEntry entry + = (PersistentByteMap.MapEntry)iterator.next(); + byte[] digest = (byte[])entry.getKey(); + System.out.print ("[" + entry.getBucket() + "] " + + bytesToString(digest) + + " -> "); + System.out.println (new String((byte[])entry.getValue())); + } + } + catch (Exception e) + { + System.err.println ("error: could not list " + + s[1] + ": " + e.toString()); + System.exit(2); + } + return; + } + + if (s[0].equals("-d")) + { + insist (s.length == 2); + try + { + MessageDigest md = MessageDigest.getInstance("MD5"); + PersistentByteMap b + = new PersistentByteMap(new File(s[1]), + PersistentByteMap.AccessMode.READ_WRITE); + int N = b.capacity(); + byte[] bytes = new byte[1]; + byte digest[] = md.digest(bytes); + for (int i = 0; i < N; i++) + { + digest = md.digest(digest); + b.put(digest, digest); + } + } + catch (Exception e) + { + e.printStackTrace(); + System.exit(3); + } + return; + } + + usage(); + System.exit(1); + } + + private static void insist(boolean ok) + { + if (! ok) + { + usage(); + System.exit(1); + } + } + + private static void usage() + { + System.err.println + ("jv-dbtool: Manipulate gcj map database files\n" + + "\n" + + " Usage: \n" + + " jv-dbtool -n file.gcjdb [size] - Create a new gcj map database\n" + + " jv-dbtool -a file.gcjdb file.jar file.so\n" + + " - Add the contents of file.jar to the database\n" + + " jv-dbtool -t file.gcjdb - Test a gcj map database\n" + + " jv-dbtool -l file.gcjdb - List a gcj map database\n"); + } + + + private static void addJar(File f, PersistentByteMap b, File soFile) + throws Exception + { + MessageDigest md = MessageDigest.getInstance("MD5"); + + JarFile jar = new JarFile (f); + Enumeration entries = jar.entries(); + + while (entries.hasMoreElements()) + { + JarEntry classfile = (JarEntry)entries.nextElement(); + if (classfile.getName().endsWith(".class")) + { + InputStream str = jar.getInputStream(classfile); + long length = classfile.getSize(); + if (length == -1) + throw new EOFException(); + + byte[] data = new byte[length]; + int pos = 0; + while (length - pos > 0) + { + int len = str.read(data, pos, (int)(length - pos)); + if (len == -1) + throw new EOFException("Not enough data reading from: " + + classfile.getName()); + pos += len; + } + b.put(md.digest(data), + soFile.getCanonicalPath().getBytes()); + } + } + } + + static String bytesToString(byte[] b) + { + StringBuffer hexBytes = new StringBuffer(); + int length = b.length; + for (int i = 0; i < length; ++i) + hexBytes.append(Integer.toHexString(b[i] & 0xff)); + return hexBytes.toString(); + } +} + diff --git a/libjava/include/Makefile.in b/libjava/include/Makefile.in index 426f958b262..82cef6f29a2 100644 --- a/libjava/include/Makefile.in +++ b/libjava/include/Makefile.in @@ -145,6 +145,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@ LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@ LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@ LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@ +LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@ LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBOBJS = @LIBOBJS@ diff --git a/libjava/include/execution.h b/libjava/include/execution.h new file mode 100644 index 00000000000..b8f47468fc7 --- /dev/null +++ b/libjava/include/execution.h @@ -0,0 +1,146 @@ +// execution.h - Execution engines. -*- c++ -*- + +/* Copyright (C) 2004 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#ifndef __JAVA_EXECUTION_H__ +#define __JAVA_EXECUTION_H__ + +// This represents one execution engine. Note that we use function +// pointers and not virtual methods to avoid calls to +// __cxa_call_unexpected and the like. +struct _Jv_ExecutionEngine +{ + public: + + void (*unregister) (jclass); + // FIXME: probably should handle this elsewhere, see how + // interpreter does it. + bool (*need_resolve_string_fields) (); + void (*verify) (jclass); + void (*allocate_static_fields) (jclass, int); + void (*create_ncode) (jclass); + _Jv_ResolvedMethod *(*resolve_method) (_Jv_Method *, jclass, + jboolean, jint); + void (*post_miranda_hook) (jclass); +}; + +// This handles all gcj-compiled code, including BC ABI. +struct _Jv_CompiledEngine : public _Jv_ExecutionEngine +{ + public: + + static void do_unregister (jclass) + { + } + + static bool do_need_resolve_string_fields () + { + return true; + } + + static void do_verify (jclass klass) + { + _Jv_Linker::verify_type_assertions (klass); + } + + static _Jv_ResolvedMethod *do_resolve_method (_Jv_Method *, jclass, + jboolean, jint) + { + return NULL; + } + + static void do_allocate_static_fields (jclass, int) + { + // Compiled classes don't need this. + } + + static void do_create_ncode (jclass) + { + // Not needed. + } + + static void do_post_miranda_hook (jclass) + { + // Not needed. + } + + _Jv_CompiledEngine () + { + unregister = do_unregister; + need_resolve_string_fields = do_need_resolve_string_fields; + verify = do_verify; + allocate_static_fields = do_allocate_static_fields; + create_ncode = do_create_ncode; + resolve_method = do_resolve_method; + post_miranda_hook = do_post_miranda_hook; + } + + // These operators make it so we don't have to link in libstdc++. + void *operator new (size_t bytes) + { + return _Jv_Malloc(bytes); + } + + void operator delete (void *mem) + { + _Jv_Free(mem); + } +}; + +// This handles interpreted code. +class _Jv_InterpreterEngine : public _Jv_ExecutionEngine +{ + public: + + static void do_verify (jclass); + static void do_allocate_static_fields (jclass, int); + static void do_create_ncode (jclass); + static _Jv_ResolvedMethod *do_resolve_method (_Jv_Method *, jclass, + jboolean, jint); + + static bool do_need_resolve_string_fields () + { + return false; + } + + static void do_unregister(jclass klass) + { + _Jv_UnregisterClass(klass); + } + + static void do_post_miranda_hook (jclass); + + _Jv_InterpreterEngine () + { + unregister = do_unregister; + need_resolve_string_fields = do_need_resolve_string_fields; + verify = do_verify; + allocate_static_fields = do_allocate_static_fields; + create_ncode = do_create_ncode; + resolve_method = do_resolve_method; + post_miranda_hook = do_post_miranda_hook; + } + + // These operators make it so we don't have to link in libstdc++. + void *operator new (size_t bytes) + { + return _Jv_Malloc(bytes); + } + + void operator delete (void *mem) + { + _Jv_Free(mem); + } +}; + + +extern _Jv_InterpreterEngine _Jv_soleInterpreterEngine; +extern _Jv_CompiledEngine _Jv_soleCompiledEngine; + +#endif // __JAVA_EXECUTION_H__ diff --git a/libjava/include/java-interp.h b/libjava/include/java-interp.h index 12bc21f2436..c8e041ae387 100644 --- a/libjava/include/java-interp.h +++ b/libjava/include/java-interp.h @@ -1,6 +1,6 @@ // java-interp.h - Header file for the bytecode interpreter. -*- c++ -*- -/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -36,7 +36,8 @@ _Jv_IsInterpretedClass (jclass c) struct _Jv_ResolvedMethod; void _Jv_InitInterpreter (); -void _Jv_DefineClass (jclass, jbyteArray, jint, jint); +void _Jv_DefineClass (jclass, jbyteArray, jint, jint, + java::security::ProtectionDomain *); void _Jv_InitField (jobject, jclass, int); void * _Jv_AllocMethodInvocation (jsize size); @@ -88,11 +89,7 @@ protected: // Size of raw arguments. _Jv_ushort args_raw_size; - // Chain of addresses to fill in. See _Jv_Defer_Resolution. - void *deferred; - - friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **); - friend void _Jv_PrepareClass(jclass); + friend class _Jv_InterpreterEngine; public: _Jv_Method *get_method () @@ -150,10 +147,9 @@ class _Jv_InterpMethod : public _Jv_MethodBase friend class _Jv_BytecodeVerifier; friend class gnu::gcj::runtime::NameFinder; friend class gnu::gcj::runtime::StackTrace; + friend class _Jv_InterpreterEngine; - friend void _Jv_PrepareClass(jclass); - #ifdef JV_MARKOBJ_DECL friend JV_MARKOBJ_DECL; #endif @@ -166,43 +162,15 @@ class _Jv_InterpClass friend class _Jv_ClassReader; friend class _Jv_InterpMethod; - friend void _Jv_PrepareClass(jclass); - friend void _Jv_PrepareMissingMethods (jclass base2, jclass iface_class); + friend class _Jv_InterpreterEngine; friend void _Jv_InitField (jobject, jclass, int); #ifdef JV_MARKOBJ_DECL friend JV_MARKOBJ_DECL; #endif friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass); - friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **); }; -// We have an interpreted class CL and we're trying to find the -// address of the ncode of a method METH. That interpreted class -// hasn't yet been prepared, so we defer fixups until they are ready. -// To do this, we create a chain of fixups that will be resolved by -// _Jv_PrepareClass. -extern inline void -_Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **address) -{ - int i; - jclass self = (jclass) cl; - _Jv_InterpClass *interp_cl = (_Jv_InterpClass*) self->aux_info; - - for (i = 0; i < self->method_count; i++) - { - _Jv_Method *m = &self->methods[i]; - if (m == meth) - { - _Jv_MethodBase *imeth = interp_cl->interpreted_methods[i]; - *address = imeth->deferred; - imeth->deferred = address; - return; - } - } - return; -} - extern inline _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass) { @@ -240,7 +208,11 @@ class _Jv_JNIMethod : public _Jv_MethodBase void *ncode (); friend class _Jv_ClassReader; - friend void _Jv_PrepareClass(jclass); + friend class _Jv_InterpreterEngine; + +#ifdef JV_MARKOBJ_DECL + friend JV_MARKOBJ_DECL; +#endif public: // FIXME: this is ugly. diff --git a/libjava/include/java-stack.h b/libjava/include/java-stack.h new file mode 100644 index 00000000000..6c3103ce056 --- /dev/null +++ b/libjava/include/java-stack.h @@ -0,0 +1,84 @@ +// java-stack.h - Definitions for unwinding & inspecting the call stack. + +/* Copyright (C) 2003 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#ifndef __JV_STACKTRACE_H__ +#define __JV_STACKTRACE_H__ + +#include <unwind.h> + +#include <gcj/cni.h> +#include <gcj/javaprims.h> + +#include <java-interp.h> + +#include <java/lang/Class.h> +#include <java/lang/StackTraceElement.h> +#include <java/lang/Throwable.h> + +#include <gnu/gcj/runtime/NameFinder.h> + +using namespace gnu::gcj::runtime; + +enum _Jv_FrameType +{ + frame_native, + frame_interpreter +}; + +#ifdef INTERPRETER +struct _Jv_InterpFrameInfo +{ + _Jv_InterpMethod *meth; + pc_t pc; +}; +#endif + +union _Jv_FrameInfo +{ +}; + +struct _Jv_StackFrame +{ + _Jv_FrameType type; /* Native or interpreted. */ + union { +#ifdef INTERPRETER + _Jv_InterpFrameInfo interp; +#endif + void *ip; + }; +// _Jv_FrameInfo info; /* Frame-type specific data. */ + jclass klass; + _Jv_Method *meth; +}; + +class _Jv_StackTrace +{ +private: + int length; + _Jv_StackFrame frames[]; + + static void UpdateNCodeMap (); + static jclass ClassForIP (void *ip, void **ncode); + static void FillInFrameInfo (_Jv_StackFrame *frame); + static void getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder, + jstring *sourceFileName, jint *lineNum); + + static _Unwind_Reason_Code UnwindTraceFn (struct _Unwind_Context *context, + void *state_ptr); + +public: + static _Jv_StackTrace *GetStackTrace (void); + static JArray< ::java::lang::StackTraceElement *>* + GetStackTraceElements (_Jv_StackTrace *trace, + java::lang::Throwable *throwable); + static jclass GetCallingClass (void); +}; + +#endif /* __JV_STACKTRACE_H__ */ diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 55799515c05..a3d06e7b09f 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 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -231,9 +231,6 @@ inline _Jv_TempUTFString::~_Jv_TempUTFString () char utfstr##_buf[utfstr##_len <= 256 ? utfstr##_len : 0]; \ _Jv_TempUTFString utfstr(utfstr##thejstr, sizeof(utfstr##_buf)==0 ? 0 : utfstr##_buf) -// FIXME: remove this define. -#define StringClass java::lang::String::class$ - namespace gcj { /* Some constants used during lookup of special class methods. */ @@ -249,6 +246,43 @@ namespace gcj extern bool verbose_class_flag; } +// This class handles all aspects of class preparation and linking. +class _Jv_Linker +{ +private: + static void prepare_constant_time_tables(jclass); + static jshort get_interfaces(jclass, _Jv_ifaces *); + static void link_symbol_table(jclass); + static void link_exception_table(jclass); + static void layout_interface_methods(jclass); + static void layout_vtable_methods(jclass); + static void set_vtable_entries(jclass, _Jv_VTable *); + static void make_vtable(jclass); + static void ensure_fields_laid_out(jclass); + static void ensure_class_linked(jclass); + static void ensure_supers_installed(jclass); + static void add_miranda_methods(jclass, jclass); + static void ensure_method_table_complete(jclass); + static void verify_class(jclass); + static jshort find_iindex(jclass *, jshort *, jshort); + static jshort indexof(void *, void **, jshort); + static int get_alignment_from_class(jclass); + static void generate_itable(jclass, _Jv_ifaces *, jshort *); + static jshort append_partial_itable(jclass, jclass, void **, jshort); + static _Jv_Method *search_method_in_class (jclass, jclass, + _Jv_Utf8Const *, + _Jv_Utf8Const *); + +public: + + static void print_class_loaded (jclass); + static void resolve_class_ref (jclass, jclass *); + static void wait_for_state(jclass, int); + static _Jv_word resolve_pool_entry (jclass, int); + static void resolve_field (_Jv_Field *, java::lang::ClassLoader *); + static void verify_type_assertions (jclass); +}; + /* Type of pointer used as finalizer. */ typedef void _Jv_FinalizerFunc (jobject); @@ -416,7 +450,6 @@ extern "C" void _Jv_RegisterClasses_Counted (const jclass *classes, size_t count); extern "C" void _Jv_RegisterResource (void *vptr); extern void _Jv_UnregisterClass (_Jv_Utf8Const*, java::lang::ClassLoader*); -extern void _Jv_ResolveField (_Jv_Field *, java::lang::ClassLoader*); extern jclass _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader); diff --git a/libjava/interpret.cc b/libjava/interpret.cc index 0446c729623..91d4b194774 100644 --- a/libjava/interpret.cc +++ b/libjava/interpret.cc @@ -11,6 +11,7 @@ details. */ /* Author: Kresten Krab Thorup <krab@gnu.org> */ #include <config.h> +#include <platform.h> // Define this to get the direct-threaded interpreter. If undefined, // we revert to a basic bytecode interpreter. The former is faster @@ -38,9 +39,15 @@ details. */ #include <java/lang/Thread.h> #include <java-insns.h> #include <java-signal.h> +#include <java/lang/ClassFormatError.h> +#include <execution.h> +#include <java/lang/reflect/Modifier.h> #ifdef INTERPRETER +// Execution engine for interpreted code. +_Jv_InterpreterEngine _Jv_soleInterpreterEngine; + #include <stdlib.h> using namespace gcj; @@ -54,6 +61,11 @@ static void throw_null_pointer_exception () __attribute__ ((__noreturn__)); #endif +static void throw_class_format_error (jstring msg) + __attribute__ ((__noreturn__)); +static void throw_class_format_error (char *msg) + __attribute__ ((__noreturn__)); + #ifdef DIRECT_THREADED // Lock to ensure that methods are not compiled concurrently. // We could use a finer-grained lock here, however it is not safe to use @@ -765,8 +777,9 @@ _Jv_InterpMethod::compile (const void * const *insn_targets) exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]]; exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]]; exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]]; - jclass handler = (_Jv_ResolvePoolEntry (defining_class, - exc[i].handler_type.i)).clazz; + jclass handler + = (_Jv_Linker::resolve_pool_entry (defining_class, + exc[i].handler_type.i)).clazz; exc[i].handler_type.p = handler; } @@ -1113,13 +1126,14 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) { int index = GET2U (); - /* _Jv_ResolvePoolEntry returns immediately if the value already - * is resolved. If we want to clutter up the code here to gain - * a little performance, then we can check the corresponding bit - * JV_CONSTANT_ResolvedFlag in the tag directly. For now, I - * don't think it is worth it. */ + /* _Jv_Linker::resolve_pool_entry returns immediately if the + * value already is resolved. If we want to clutter up the + * code here to gain a little performance, then we can check + * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag + * directly. For now, I don't think it is worth it. */ - rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; + rmeth = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).rmethod; sp -= rmeth->stack_item_count; // We don't use NULLCHECK here because we can't rely on that @@ -2409,7 +2423,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) insn_getstatic: { jint fieldref_index = GET2U (); - _Jv_ResolvePoolEntry (defining_class, fieldref_index); + _Jv_Linker::resolve_pool_entry (defining_class, fieldref_index); _Jv_Field *field = pool_data[fieldref_index].field; if ((field->flags & Modifier::STATIC) == 0) @@ -2496,7 +2510,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) insn_getfield: { jint fieldref_index = GET2U (); - _Jv_ResolvePoolEntry (defining_class, fieldref_index); + _Jv_Linker::resolve_pool_entry (defining_class, fieldref_index); _Jv_Field *field = pool_data[fieldref_index].field; if ((field->flags & Modifier::STATIC) != 0) @@ -2612,7 +2626,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) insn_putstatic: { jint fieldref_index = GET2U (); - _Jv_ResolvePoolEntry (defining_class, fieldref_index); + _Jv_Linker::resolve_pool_entry (defining_class, fieldref_index); _Jv_Field *field = pool_data[fieldref_index].field; jclass type = field->type; @@ -2699,7 +2713,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) insn_putfield: { jint fieldref_index = GET2U (); - _Jv_ResolvePoolEntry (defining_class, fieldref_index); + _Jv_Linker::resolve_pool_entry (defining_class, fieldref_index); _Jv_Field *field = pool_data[fieldref_index].field; jclass type = field->type; @@ -2825,7 +2839,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) { int index = GET2U (); - rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; + rmeth = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).rmethod; sp -= rmeth->stack_item_count; @@ -2863,7 +2878,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) { int index = GET2U (); - rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; + rmeth = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).rmethod; sp -= rmeth->stack_item_count; @@ -2892,7 +2908,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) { int index = GET2U (); - rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; + rmeth = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).rmethod; sp -= rmeth->stack_item_count; @@ -2935,7 +2952,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) insn_new: { int index = GET2U (); - jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; + jclass klass = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).clazz; jobject res = _Jv_AllocObject (klass); PUSHA (res); @@ -2968,7 +2986,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) insn_anewarray: { int index = GET2U (); - jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; + jclass klass = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).clazz; int size = POPI(); jobject result = _Jv_NewObjectArray (size, klass, 0); PUSHA (result); @@ -3010,7 +3029,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) { jobject value = POPA(); jint index = GET2U (); - jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; + jclass to = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).clazz; if (value != NULL && ! to->isInstance (value)) throw new java::lang::ClassCastException (to->getName()); @@ -3040,7 +3060,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) { jobject value = POPA(); jint index = GET2U (); - jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; + jclass to = (_Jv_Linker::resolve_pool_entry (defining_class, + index)).clazz; PUSHI (to->isInstance (value)); #ifdef DIRECT_THREADED @@ -3102,7 +3123,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) int dim = GET1U (); jclass type - = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz; + = (_Jv_Linker::resolve_pool_entry (defining_class, + kind_index)).clazz; jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim); for (int i = dim - 1; i >= 0; i--) @@ -3203,8 +3225,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args) #else jclass handler = NULL; if (exc[i].handler_type.i != 0) - handler = (_Jv_ResolvePoolEntry (defining_class, - exc[i].handler_type.i)).clazz; + handler = (_Jv_Linker::resolve_pool_entry (defining_class, + exc[i].handler_type.i)).clazz; #endif /* DIRECT_THREADED */ if (handler == NULL || handler->isAssignableFrom (exc_class)) @@ -3250,4 +3272,547 @@ throw_null_pointer_exception () } #endif +/** Do static initialization for fields with a constant initializer */ +void +_Jv_InitField (jobject obj, jclass klass, int index) +{ + using namespace java::lang::reflect; + + if (obj != 0 && klass == 0) + klass = obj->getClass (); + + if (!_Jv_IsInterpretedClass (klass)) + return; + + _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info; + + _Jv_Field * field = (&klass->fields[0]) + index; + + if (index > klass->field_count) + throw_internal_error ("field out of range"); + + int init = iclass->field_initializers[index]; + if (init == 0) + return; + + _Jv_Constants *pool = &klass->constants; + int tag = pool->tags[init]; + + if (! field->isResolved ()) + throw_internal_error ("initializing unresolved field"); + + if (obj==0 && ((field->flags & Modifier::STATIC) == 0)) + throw_internal_error ("initializing non-static field with no object"); + + void *addr = 0; + + if ((field->flags & Modifier::STATIC) != 0) + addr = (void*) field->u.addr; + else + addr = (void*) (((char*)obj) + field->u.boffset); + + switch (tag) + { + case JV_CONSTANT_String: + { + jstring str; + str = _Jv_NewStringUtf8Const (pool->data[init].utf8); + pool->data[init].string = str; + pool->tags[init] = JV_CONSTANT_ResolvedString; + } + /* fall through */ + + case JV_CONSTANT_ResolvedString: + if (! (field->type == &java::lang::String::class$ + || field->type == &java::lang::Class::class$)) + throw_class_format_error ("string initialiser to non-string field"); + + *(jstring*)addr = pool->data[init].string; + break; + + case JV_CONSTANT_Integer: + { + int value = pool->data[init].i; + + if (field->type == JvPrimClass (boolean)) + *(jboolean*)addr = (jboolean)value; + + else if (field->type == JvPrimClass (byte)) + *(jbyte*)addr = (jbyte)value; + + else if (field->type == JvPrimClass (char)) + *(jchar*)addr = (jchar)value; + + else if (field->type == JvPrimClass (short)) + *(jshort*)addr = (jshort)value; + + else if (field->type == JvPrimClass (int)) + *(jint*)addr = (jint)value; + + else + throw_class_format_error ("erroneous field initializer"); + } + break; + + case JV_CONSTANT_Long: + if (field->type != JvPrimClass (long)) + throw_class_format_error ("erroneous field initializer"); + + *(jlong*)addr = _Jv_loadLong (&pool->data[init]); + break; + + case JV_CONSTANT_Float: + if (field->type != JvPrimClass (float)) + throw_class_format_error ("erroneous field initializer"); + + *(jfloat*)addr = pool->data[init].f; + break; + + case JV_CONSTANT_Double: + if (field->type != JvPrimClass (double)) + throw_class_format_error ("erroneous field initializer"); + + *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]); + break; + + default: + throw_class_format_error ("erroneous field initializer"); + } +} + +inline static unsigned char* +skip_one_type (unsigned char* ptr) +{ + int ch = *ptr++; + + while (ch == '[') + { + ch = *ptr++; + } + + if (ch == 'L') + { + do { ch = *ptr++; } while (ch != ';'); + } + + return ptr; +} + +static ffi_type* +get_ffi_type_from_signature (unsigned char* ptr) +{ + switch (*ptr) + { + case 'L': + case '[': + return &ffi_type_pointer; + break; + + case 'Z': + // On some platforms a bool is a byte, on others an int. + if (sizeof (jboolean) == sizeof (jbyte)) + return &ffi_type_sint8; + else + { + JvAssert (sizeof (jbyte) == sizeof (jint)); + return &ffi_type_sint32; + } + break; + + case 'B': + return &ffi_type_sint8; + break; + + case 'C': + return &ffi_type_uint16; + break; + + case 'S': + return &ffi_type_sint16; + break; + + case 'I': + return &ffi_type_sint32; + break; + + case 'J': + return &ffi_type_sint64; + break; + + case 'F': + return &ffi_type_float; + break; + + case 'D': + return &ffi_type_double; + break; + + case 'V': + return &ffi_type_void; + break; + } + + throw_internal_error ("unknown type in signature"); +} + +/* this function yields the number of actual arguments, that is, if the + * function is non-static, then one is added to the number of elements + * found in the signature */ + +int +_Jv_count_arguments (_Jv_Utf8Const *signature, + jboolean staticp) +{ + unsigned char *ptr = (unsigned char*) signature->chars(); + int arg_count = staticp ? 0 : 1; + + /* first, count number of arguments */ + + // skip '(' + ptr++; + + // count args + while (*ptr != ')') + { + ptr = skip_one_type (ptr); + arg_count += 1; + } + + return arg_count; +} + +/* This beast will build a cif, given the signature. Memory for + * the cif itself and for the argument types must be allocated by the + * caller. + */ + +static int +init_cif (_Jv_Utf8Const* signature, + int arg_count, + jboolean staticp, + ffi_cif *cif, + ffi_type **arg_types, + ffi_type **rtype_p) +{ + unsigned char *ptr = (unsigned char*) signature->chars(); + + int arg_index = 0; // arg number + int item_count = 0; // stack-item count + + // setup receiver + if (!staticp) + { + arg_types[arg_index++] = &ffi_type_pointer; + item_count += 1; + } + + // skip '(' + ptr++; + + // assign arg types + while (*ptr != ')') + { + arg_types[arg_index++] = get_ffi_type_from_signature (ptr); + + if (*ptr == 'J' || *ptr == 'D') + item_count += 2; + else + item_count += 1; + + ptr = skip_one_type (ptr); + } + + // skip ')' + ptr++; + ffi_type *rtype = get_ffi_type_from_signature (ptr); + + ptr = skip_one_type (ptr); + if (ptr != (unsigned char*)signature->chars() + signature->len()) + throw_internal_error ("did not find end of signature"); + + if (ffi_prep_cif (cif, FFI_DEFAULT_ABI, + arg_count, rtype, arg_types) != FFI_OK) + throw_internal_error ("ffi_prep_cif failed"); + + if (rtype_p != NULL) + *rtype_p = rtype; + + return item_count; +} + +#if FFI_NATIVE_RAW_API +# define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure +# define FFI_RAW_SIZE ffi_raw_size +#else +# define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure +# define FFI_RAW_SIZE ffi_java_raw_size +#endif + +/* we put this one here, and not in interpret.cc because it + * calls the utility routines _Jv_count_arguments + * which are static to this module. The following struct defines the + * layout we use for the stubs, it's only used in the ncode method. */ + +typedef struct { + ffi_raw_closure closure; + ffi_cif cif; + ffi_type *arg_types[0]; +} ncode_closure; + +typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*); + +void * +_Jv_InterpMethod::ncode () +{ + using namespace java::lang::reflect; + + if (self->ncode != 0) + return self->ncode; + + jboolean staticp = (self->accflags & Modifier::STATIC) != 0; + int arg_count = _Jv_count_arguments (self->signature, staticp); + + ncode_closure *closure = + (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) + + arg_count * sizeof (ffi_type*)); + + init_cif (self->signature, + arg_count, + staticp, + &closure->cif, + &closure->arg_types[0], + NULL); + + ffi_closure_fun fun; + + args_raw_size = FFI_RAW_SIZE (&closure->cif); + + JvAssert ((self->accflags & Modifier::NATIVE) == 0); + + if ((self->accflags & Modifier::SYNCHRONIZED) != 0) + { + if (staticp) + fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class; + else + fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; + } + else + { + if (staticp) + fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class; + else + fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal; + } + + FFI_PREP_RAW_CLOSURE (&closure->closure, + &closure->cif, + fun, + (void*)this); + + self->ncode = (void*)closure; + return self->ncode; +} + +void * +_Jv_JNIMethod::ncode () +{ + using namespace java::lang::reflect; + + if (self->ncode != 0) + return self->ncode; + + jboolean staticp = (self->accflags & Modifier::STATIC) != 0; + int arg_count = _Jv_count_arguments (self->signature, staticp); + + ncode_closure *closure = + (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) + + arg_count * sizeof (ffi_type*)); + + ffi_type *rtype; + init_cif (self->signature, + arg_count, + staticp, + &closure->cif, + &closure->arg_types[0], + &rtype); + + ffi_closure_fun fun; + + args_raw_size = FFI_RAW_SIZE (&closure->cif); + + // Initialize the argument types and CIF that represent the actual + // underlying JNI function. + int extra_args = 1; + if ((self->accflags & Modifier::STATIC)) + ++extra_args; + jni_arg_types = (ffi_type **) _Jv_AllocBytes ((extra_args + arg_count) + * sizeof (ffi_type *)); + int offset = 0; + jni_arg_types[offset++] = &ffi_type_pointer; + if ((self->accflags & Modifier::STATIC)) + jni_arg_types[offset++] = &ffi_type_pointer; + memcpy (&jni_arg_types[offset], &closure->arg_types[0], + arg_count * sizeof (ffi_type *)); + + if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi, + extra_args + arg_count, rtype, + jni_arg_types) != FFI_OK) + throw_internal_error ("ffi_prep_cif failed for JNI function"); + + JvAssert ((self->accflags & Modifier::NATIVE) != 0); + + // FIXME: for now we assume that all native methods for + // interpreted code use JNI. + fun = (ffi_closure_fun) &_Jv_JNIMethod::call; + + FFI_PREP_RAW_CLOSURE (&closure->closure, + &closure->cif, + fun, + (void*) this); + + self->ncode = (void *) closure; + return self->ncode; +} + +static void +throw_class_format_error (jstring msg) +{ + throw (msg + ? new java::lang::ClassFormatError (msg) + : new java::lang::ClassFormatError); +} + +static void +throw_class_format_error (char *msg) +{ + throw_class_format_error (JvNewStringLatin1 (msg)); +} + + + +void +_Jv_InterpreterEngine::do_verify (jclass klass) +{ + _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; + for (int i = 0; i < klass->method_count; i++) + { + using namespace java::lang::reflect; + _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; + _Jv_ushort accflags = klass->methods[i].accflags; + if ((accflags & (Modifier::NATIVE | Modifier::ABSTRACT)) == 0) + { + _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); + _Jv_VerifyMethod (im); + } + } +} + +void +_Jv_InterpreterEngine::do_create_ncode (jclass klass) +{ + _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; + for (int i = 0; i < klass->method_count; i++) + { + // Just skip abstract methods. This is particularly important + // because we don't resize the interpreted_methods array when + // miranda methods are added to it. + if ((klass->methods[i].accflags + & java::lang::reflect::Modifier::ABSTRACT) + != 0) + continue; + + _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; + + if ((klass->methods[i].accflags & java::lang::reflect::Modifier::NATIVE) + != 0) + { + // You might think we could use a virtual `ncode' method in + // the _Jv_MethodBase and unify the native and non-native + // cases. Well, we can't, because we don't allocate these + // objects using `new', and thus they don't get a vtable. + _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth); + klass->methods[i].ncode = jnim->ncode (); + } + else if (imeth != 0) // it could be abstract + { + _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); + klass->methods[i].ncode = im->ncode (); + } + } +} + +void +_Jv_InterpreterEngine::do_allocate_static_fields (jclass klass, + int static_size) +{ + _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; + + char *static_data = (char *) _Jv_AllocBytes (static_size); + memset (static_data, 0, static_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) + { + 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); + } + } + } + + // Now we don't need the field_initializers anymore, so let the + // collector get rid of it. + iclass->field_initializers = 0; +} + +_Jv_ResolvedMethod * +_Jv_InterpreterEngine::do_resolve_method (_Jv_Method *method, jclass klass, + jboolean staticp, jint vtable_index) +{ + int arg_count = _Jv_count_arguments (method->signature, staticp); + + _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*) + _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod) + + arg_count*sizeof (ffi_type*)); + + result->stack_item_count + = init_cif (method->signature, + arg_count, + staticp, + &result->cif, + &result->arg_types[0], + NULL); + + result->vtable_index = vtable_index; + result->method = method; + result->klass = klass; + + return result; +} + +void +_Jv_InterpreterEngine::do_post_miranda_hook (jclass klass) +{ + _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info; + for (int i = 0; i < klass->method_count; i++) + { + // Just skip abstract methods. This is particularly important + // because we don't resize the interpreted_methods array when + // miranda methods are added to it. + if ((klass->methods[i].accflags + & java::lang::reflect::Modifier::ABSTRACT) + != 0) + continue; + // Miranda method additions mean that the `methods' array moves. + // We cache a pointer into this array, so we have to update. + iclass->interpreted_methods[i]->self = &klass->methods[i]; + } +} + #endif // INTERPRETER diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java index 646eaebe4c7..0c79d332700 100644 --- a/libjava/java/io/ObjectInputStream.java +++ b/libjava/java/io/ObjectInputStream.java @@ -121,15 +121,15 @@ public class ObjectInputStream extends InputStream */ public final Object readObject() throws ClassNotFoundException, IOException { - if (callersClassLoader == null) - { - callersClassLoader = getCallersClassLoader (); - if (Configuration.DEBUG && dump) - { - dumpElementln ("CallersClassLoader = " + callersClassLoader); - } - } - + if (callersClassLoader == null) + { + callersClassLoader = getCallersClassLoader (); + if (Configuration.DEBUG && dump) + { + dumpElementln ("CallersClassLoader = " + callersClassLoader); + } + } + if (this.useSubclassMethod) return readObjectOverride(); @@ -271,7 +271,7 @@ public class ObjectInputStream extends InputStream readArrayElements(array, componentType); if(dump) for (int i = 0, len = Array.getLength(array); i < len; i++) - dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); + dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); ret_val = processResolution(null, array, handle); break; } @@ -398,6 +398,8 @@ public class ObjectInputStream extends InputStream setBlockDataMode(old_mode); this.isDeserializing = was_deserializing; + + depth -= 2; depth -= 2; @@ -1806,6 +1808,7 @@ public class ObjectInputStream extends InputStream * @param sm SecurityManager instance which should be called. * @return The current class loader in the calling stack. */ + private static native ClassLoader currentClassLoader (SecurityManager sm); private native ClassLoader getCallersClassLoader(); @@ -1875,7 +1878,7 @@ public class ObjectInputStream extends InputStream private int depth = 0; private void dumpElement (String msg) - { + { System.out.print(msg); } diff --git a/libjava/java/io/ObjectOutputStream.java b/libjava/java/io/ObjectOutputStream.java index 6a5eed7a24c..3482225232a 100644 --- a/libjava/java/io/ObjectOutputStream.java +++ b/libjava/java/io/ObjectOutputStream.java @@ -347,8 +347,8 @@ public class ObjectOutputStream extends OutputStream fieldsAlreadyWritten = false; if (currentObjectStreamClass.hasWriteMethod()) { - if (dump) - dumpElementln ("WRITE METHOD CALLED FOR: " + obj); + if (dump) + dumpElementln ("WRITE METHOD CALLED FOR: " + obj); setBlockDataMode(true); callWriteMethod(obj, currentObjectStreamClass); setBlockDataMode(false); @@ -358,10 +358,10 @@ public class ObjectOutputStream extends OutputStream } else { - if (dump) - dumpElementln ("WRITE FIELDS CALLED FOR: " + obj); - writeFields(obj, currentObjectStreamClass); - } + if (dump) + dumpElementln ("WRITE FIELDS CALLED FOR: " + obj); + writeFields(obj, currentObjectStreamClass); + } } this.currentObject = prevObject; diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index a60e80a22d9..320b09965d0 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -42,13 +42,15 @@ enum JV_STATE_PRELOADING = 1, // Can do _Jv_FindClass. JV_STATE_LOADING = 3, // Has super installed. - JV_STATE_COMPILED = 5, // This was a compiled class. + JV_STATE_READ = 4, // Has been completely defined. + JV_STATE_LOADED = 5, // Has Miranda methods defined. + + JV_STATE_COMPILED = 6, // This was a compiled class. - JV_STATE_LOADED = 6, // Is complete. JV_STATE_PREPARED = 7, // Layout & static init done. JV_STATE_LINKED = 9, // Strings interned. - JV_STATE_IN_PROGRESS = 10, // <Clinit> running. + JV_STATE_IN_PROGRESS = 10, // <clinit> running. JV_STATE_ERROR = 12, @@ -59,6 +61,9 @@ struct _Jv_Field; struct _Jv_VTable; union _Jv_word; struct _Jv_ArrayVTable; +class _Jv_ExecutionEngine; +class _Jv_CompiledEngine; +class _Jv_InterpreterEngine; struct _Jv_Constants { @@ -106,7 +111,7 @@ union _Jv_IDispatchTable } iface; }; -// Used by _Jv_GetInterfaces () +// Used by _Jv_Linker::get_interfaces () struct _Jv_ifaces { jclass *list; @@ -139,6 +144,23 @@ struct _Jv_CatchClass _Jv_Utf8Const *classname; }; +// Possible values for the assertion_code field in the type assertion table. +enum +{ + JV_ASSERT_END_OF_TABLE = 0, + JV_ASSERT_TYPES_COMPATIBLE = 1, + JV_ASSERT_IS_INSTANTIABLE = 2 +}; + +// Entry in the type assertion table, used to validate type constraints +// for binary compatibility. +struct _Jv_TypeAssertion +{ + jint assertion_code; + _Jv_Utf8Const *op1; + _Jv_Utf8Const *op2; +}; + #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1) #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas) @@ -149,11 +171,11 @@ struct _Jv_CatchClass _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature); jboolean _Jv_IsAssignableFrom (jclass, jclass); +jboolean _Jv_IsAssignableFromSlow (jclass, jclass); jboolean _Jv_InterfaceAssignableFrom (jclass, jclass); -void _Jv_InitClass (jclass klass); _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, - _Jv_Utf8Const*); + _Jv_Utf8Const*, jclass * = NULL); jfieldID JvGetFirstInstanceField (jclass); jint JvNumInstanceFields (jclass); jfieldID JvGetFirstStaticField (jclass); @@ -183,10 +205,6 @@ class java::io::ObjectOutputStream; class java::io::ObjectInputStream; class java::io::ObjectStreamClass; -void _Jv_WaitForState (jclass, int); -void _Jv_RegisterClasses (const jclass *classes); -void _Jv_RegisterClasses_Counted (const jclass *classes, - size_t count); void _Jv_RegisterClassHookDefault (jclass klass); void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*); void _Jv_UnregisterClass (jclass); @@ -205,19 +223,7 @@ void _Jv_InitNewClassFields (jclass klass); // Friend functions and classes in prims.cc void _Jv_InitPrimClass (jclass, char *, char, int); -void _Jv_PrepareCompiledClass (jclass); -void _Jv_PrepareConstantTimeTables (jclass); -jshort _Jv_GetInterfaces (jclass, _Jv_ifaces *); -void _Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *); jstring _Jv_GetMethodString (jclass, _Jv_Utf8Const *); -jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort); -jshort _Jv_FindIIndex (jclass *, jshort *, jshort); -void _Jv_LinkSymbolTable (jclass); -void _Jv_LayoutInterfaceMethods (jclass); -void _Jv_LayoutVTableMethods (jclass klass); -void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *); -void _Jv_MakeVTable (jclass); -void _Jv_linkExceptionClassTable (jclass); jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags); @@ -225,25 +231,14 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader); #ifdef INTERPRETER jboolean _Jv_IsInterpretedClass (jclass); -void _Jv_InitField (jobject, jclass, _Jv_Field*); void _Jv_InitField (jobject, jclass, int); -_Jv_word _Jv_ResolvePoolEntry (jclass, int); -_Jv_Method *_Jv_SearchMethodInClass (jclass cls, jclass klass, - _Jv_Utf8Const *method_name, - _Jv_Utf8Const *method_signature); -void _Jv_PrepareClass (jclass); -void _Jv_PrepareMissingMethods (jclass base, jclass iface_class); - -void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **); - class _Jv_ClassReader; class _Jv_InterpClass; class _Jv_InterpMethod; #endif class _Jv_BytecodeVerifier; -class _Jv_StackTrace; class gnu::gcj::runtime::StackTrace; class java::io::VMObjectStreamClass; @@ -316,9 +311,14 @@ public: void setSigners(JArray<jobject> *); inline jclass getSuperclass (void) - { - return superclass; - } + { + return superclass; + } + + inline jclass getInterface (jint n) + { + return interfaces[n]; + } inline jboolean isArray (void) { @@ -351,9 +351,16 @@ public: // FIXME: this probably shouldn't be public. jint size (void) - { - return size_in_bytes; - } + { + return size_in_bytes; + } + + // The index of the first method we declare ourself (as opposed to + // inheriting). + inline jint firstMethodIndex (void) + { + return vtable_method_count - method_count; + } // finalization void finalize (); @@ -372,10 +379,17 @@ private: static jstring getPackagePortion (jstring); + void set_state (jint nstate) + { + state = nstate; + notifyAll (); + } + // Friend functions implemented in natClass.cc. friend _Jv_Method *::_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature); friend jboolean (::_Jv_IsAssignableFrom) (jclass, jclass); + friend jboolean (::_Jv_IsAssignableFromSlow) (jclass, jclass); friend jboolean (::_Jv_InterfaceAssignableFrom) (jclass, jclass); friend void *::_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx); @@ -383,7 +397,7 @@ private: friend void ::_Jv_InitClass (jclass klass); friend _Jv_Method* ::_Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, - _Jv_Utf8Const*); + _Jv_Utf8Const*, jclass *); friend jfieldID (::JvGetFirstInstanceField) (jclass); friend jint (::JvNumInstanceFields) (jclass); friend jfieldID (::JvGetFirstStaticField) (jclass); @@ -413,7 +427,6 @@ private: friend class java::io::ObjectInputStream; friend class java::io::ObjectStreamClass; - friend void ::_Jv_WaitForState (jclass, int); friend void ::_Jv_RegisterClasses (const jclass *classes); friend void ::_Jv_RegisterClasses_Counted (const jclass *classes, size_t count); @@ -436,40 +449,22 @@ private: // in prims.cc friend void ::_Jv_InitPrimClass (jclass, char *, char, int); - friend void ::_Jv_PrepareCompiledClass (jclass); - friend void ::_Jv_PrepareConstantTimeTables (jclass); - friend jshort (::_Jv_GetInterfaces) (jclass, _Jv_ifaces *); - friend void ::_Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *); friend jstring (::_Jv_GetMethodString) (jclass, _Jv_Utf8Const *); - friend jshort (::_Jv_AppendPartialITable) (jclass, jclass, void **, jshort); - friend jshort (::_Jv_FindIIndex) (jclass *, jshort *, jshort); - friend void ::_Jv_LinkSymbolTable (jclass); - friend void ::_Jv_LayoutInterfaceMethods (jclass); - friend void ::_Jv_LayoutVTableMethods (jclass klass); - friend void ::_Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *); - friend void ::_Jv_MakeVTable (jclass); - friend void ::_Jv_linkExceptionClassTable (jclass); friend jboolean (::_Jv_CheckAccess) (jclass self_klass, jclass other_klass, jint flags); + + friend bool _Jv_getInterfaceMethod(jclass, jclass&, int&, + const _Jv_Utf8Const*, + const _Jv_Utf8Const*); friend jclass (::_Jv_GetArrayClass) (jclass klass, java::lang::ClassLoader *loader); #ifdef INTERPRETER friend jboolean (::_Jv_IsInterpretedClass) (jclass); - friend void ::_Jv_InitField (jobject, jclass, _Jv_Field*); friend void ::_Jv_InitField (jobject, jclass, int); - friend _Jv_word (::_Jv_ResolvePoolEntry) (jclass, int); - friend _Jv_Method *::_Jv_SearchMethodInClass (jclass cls, jclass klass, - _Jv_Utf8Const *method_name, - _Jv_Utf8Const *method_signature); - friend void ::_Jv_PrepareClass (jclass); - friend void ::_Jv_PrepareMissingMethods (jclass base, jclass iface_class); - - friend void ::_Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **); - friend class ::_Jv_ClassReader; friend class ::_Jv_InterpClass; friend class ::_Jv_InterpMethod; @@ -480,10 +475,14 @@ private: #endif friend class ::_Jv_BytecodeVerifier; - friend class ::_Jv_StackTrace; friend class gnu::gcj::runtime::StackTrace; friend class java::io::VMObjectStreamClass; + friend class _Jv_Linker; + friend class _Jv_ExecutionEngine; + friend class _Jv_CompiledEngine; + friend class _Jv_InterpreterEngine; + friend void ::_Jv_sharedlib_register_hook (jclass klass); // Chain for class pool. @@ -518,8 +517,12 @@ private: _Jv_OffsetTable *otable; // Offset table symbols. _Jv_MethodSymbol *otable_syms; + // Address table _Jv_AddressTable *atable; _Jv_MethodSymbol *atable_syms; + // Interface table + _Jv_AddressTable *itable; + _Jv_MethodSymbol *itable_syms; _Jv_CatchClass *catch_classes; // Interfaces implemented by this class. jclass *interfaces; @@ -542,13 +545,17 @@ private: jclass arrayclass; // Security Domain to which this class belongs (or null). java::security::ProtectionDomain *protectionDomain; + // Pointer to the type assertion table for this class. + _Jv_TypeAssertion *assertion_table; // Signers of this class (or null). JArray<jobject> *hack_signers; // Used by Jv_PopClass and _Jv_PushClass to communicate with StackTrace. jclass chain; - // Additional data, specific to the generator (JIT, native, interpreter) of this - // class. + // Additional data, specific to the generator (JIT, native, + // interpreter) of this class. void *aux_info; + // Execution engine. + _Jv_ExecutionEngine *engine; }; // Inline functions that are friends of java::lang::Class diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java index 75f07169f39..648afca5435 100644 --- a/libjava/java/lang/ClassLoader.java +++ b/libjava/java/lang/ClassLoader.java @@ -288,6 +288,8 @@ public abstract class ClassLoader if (c != null) return c; + ClassNotFoundException ex = null; + // Can the class be loaded by a parent? try { @@ -304,9 +306,20 @@ public abstract class ClassLoader } catch (ClassNotFoundException e) { + ex = e; } // Still not found, we have to do it ourself. - c = findClass(name); + try + { + c = findClass(name); + } + catch (ClassNotFoundException cause) + { + if (ex != null) + throw new ClassNotFoundException(ex.toString(), cause); + else + throw cause; + } if (resolve) resolveClass(c); return c; @@ -435,8 +448,9 @@ public abstract class ClassLoader domain = defaultProtectionDomain; if (! initialized) throw new SecurityException("attempt to define class from uninitialized class loader"); + Class retval = VMClassLoader.defineClass(this, name, data, - offset, len, domain); + offset, len, domain); loadedClasses.put(retval.getName(), retval); return retval; } diff --git a/libjava/java/lang/Compiler.java b/libjava/java/lang/Compiler.java index f520a7e0dda..858f63ee993 100644 --- a/libjava/java/lang/Compiler.java +++ b/libjava/java/lang/Compiler.java @@ -1,5 +1,5 @@ /* Compiler.java -- placeholder for Java-to-native runtime compilers - Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2001, 2002, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -76,8 +76,7 @@ public final class Compiler */ public static boolean compileClass(Class oneClass) { - // Never succeed. - return false; + return VMCompiler.compileClass(oneClass); } /** @@ -90,8 +89,7 @@ public final class Compiler */ public static boolean compileClasses(String classNames) { - // Note the incredibly lame interface. Always fail. - return false; + return VMCompiler.compileClasses(classNames); } /** @@ -105,8 +103,7 @@ public final class Compiler */ public static Object command(Object arg) { - // Our implementation defines this to a no-op. - return null; + return VMCompiler.command(arg); } /** @@ -116,6 +113,7 @@ public final class Compiler */ public static void enable() { + VMCompiler.enable(); } /** @@ -124,5 +122,6 @@ public final class Compiler */ public static void disable() { + VMCompiler.disable(); } } diff --git a/libjava/java/lang/SecurityManager.java b/libjava/java/lang/SecurityManager.java index 2e82a475b5f..972b312d943 100644 --- a/libjava/java/lang/SecurityManager.java +++ b/libjava/java/lang/SecurityManager.java @@ -324,7 +324,7 @@ public class SecurityManager public void checkPermission(Permission perm) { // XXX Should be: AccessController.checkPermission(perm); - throw new SecurityException("Operation not allowed"); + //.throw new SecurityException("Operation not allowed"); } /** @@ -553,7 +553,7 @@ public class SecurityManager // throw new SecurityException("Missing context"); // AccessControlContext ac = (AccessControlContext) context; // ac.checkPermission(new FilePermission(filename, "read")); - throw new SecurityException("Cannot read files via file names."); + // throw new SecurityException("Cannot read files via file names."); } /** @@ -677,7 +677,7 @@ public class SecurityManager // // Use the toString() hack to do the null check. // ac.checkPermission(new SocketPermission(host.toString + ":" +port, // "connect")); - throw new SecurityException("Cannot make network connections."); + // throw new SecurityException("Cannot make network connections."); } /** diff --git a/libjava/java/lang/VMClassLoader.java b/libjava/java/lang/VMClassLoader.java index ac7a05e3cd9..8f78f9bb666 100644 --- a/libjava/java/lang/VMClassLoader.java +++ b/libjava/java/lang/VMClassLoader.java @@ -97,44 +97,31 @@ final class VMClassLoader ProtectionDomain pd) throws ClassFormatError; - static final native void linkClass0 (Class klass); - static final native void markClassErrorState0 (Class klass); - /** * Helper to resolve all references to other classes from this class. * * @param c the class to resolve */ - static final void resolveClass(Class clazz) + static final native void resolveClass(Class clazz); + + static final void transformException(Class clazz, Throwable x) { - synchronized (clazz) + LinkageError e; + if (x instanceof LinkageError) + e = (LinkageError) x; + else if (x instanceof ClassNotFoundException) { - try - { - linkClass0 (clazz); - } - catch (Throwable x) - { - markClassErrorState0 (clazz); - - LinkageError e; - if (x instanceof LinkageError) - e = (LinkageError) x; - else if (x instanceof ClassNotFoundException) - { - e = new NoClassDefFoundError("while resolving class: " - + clazz.getName()); - e.initCause (x); - } - else - { - e = new LinkageError ("unexpected exception during linking: " - + clazz.getName()); - e.initCause (x); - } - throw e; - } + e = new NoClassDefFoundError("while resolving class: " + + clazz.getName()); + e.initCause (x); + } + else + { + e = new LinkageError ("unexpected exception during linking: " + + clazz.getName()); + e.initCause (x); } + throw e; } /** diff --git a/libjava/java/lang/VMCompiler.java b/libjava/java/lang/VMCompiler.java new file mode 100644 index 00000000000..98efc7ee44f --- /dev/null +++ b/libjava/java/lang/VMCompiler.java @@ -0,0 +1,332 @@ +/* VMClassLoader.java -- Reference implementation of compiler interface + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.security.MessageDigest; +import java.security.ProtectionDomain; +import java.security.NoSuchAlgorithmException; +import java.util.WeakHashMap; +import java.util.HashSet; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; +import gnu.gcj.runtime.SharedLibHelper; +import gnu.gcj.runtime.PersistentByteMap; + +/** + * This class is just a per-VM reflection of java.lang.Compiler. + * All methods are defined identically. + */ +final class VMCompiler +{ + // True if we want to use gcj-jit. + public static boolean useCompiler = true; + + // True if we're able to use gcj-jit. + public static final boolean canUseCompiler; + + // Compiler to use. + public static String gcjJitCompiler; + + // Compiler options. + public static String gcjJitCompilerOptions; + + // Temporary directory to use. + public static String gcjJitTmpdir; + + // This maps a ClassLoader to a set of SharedLibHelper objects that + // it has used. We do things this way to ensure that a + // SharedLibHelper is collected if and only if the ClassLoader is. + private static WeakHashMap sharedHelperMap = new WeakHashMap(); + + private static Vector precompiledMapFiles; + + static + { + gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler"); + if (gcjJitCompiler == null) + canUseCompiler = false; + else + { + gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options", + "-g"); + gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir"); + // Note that we *don't* choose java.io.tmpdir as a default -- + // that would allow easy attacks against the VM. + if (gcjJitTmpdir == null) + canUseCompiler = false; + else + canUseCompiler = true; + } + + String prop = System.getProperty ("gnu.gcj.precompiled.db.path"); + if (prop != null) + { + precompiledMapFiles = new Vector(); + // Add the + StringTokenizer st + = new StringTokenizer (prop, + System.getProperty ("path.separator", ":")); + { + while (st.hasMoreElements ()) + { + String e = st.nextToken (); + try + { + PersistentByteMap map + = new PersistentByteMap + (e, PersistentByteMap.AccessMode.READ_ONLY); + precompiledMapFiles.add(map); + } + catch (IllegalArgumentException _) + { + // Not a map file + } + catch (java.io.IOException _) + { + } + } + } + } + } + + /** + * Don't allow new `Compiler's to be made. + */ + private VMCompiler() + { + } + + private static Class loadSharedLibrary(ClassLoader loader, + String fileName, + ProtectionDomain domain, + String className) + { + Class c = null; + SharedLibHelper helper + = SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource()); + c = helper.findClass (className); + if (c != null) + { + HashSet hs = (HashSet) sharedHelperMap.get(loader); + if (hs == null) + { + hs = new HashSet(); + sharedHelperMap.put(loader, hs); + } + hs.add(helper); + } + return c; + } + + /** + * Compile a class given the bytes for it. Returns the Class, or + * null if compilation failed or otherwise could not be done. + */ + public static Class compileClass(ClassLoader loader, + String name, byte[] data, + int offset, int len, + ProtectionDomain domain) + { + if (precompiledMapFiles == null + && (! useCompiler || ! canUseCompiler)) + return null; + + byte digest[]; + + try + { + MessageDigest md = MessageDigest.getInstance("MD5"); + digest = md.digest(data); + } + catch (NoSuchAlgorithmException _) + { + return null; + } + + // We use lookaside cache files to determine whether these bytes + // correspond to a class file that is part of a precompiled DSO. + if (precompiledMapFiles != null) + { + try + { + Enumeration elements = precompiledMapFiles.elements(); + while (elements.hasMoreElements()) + { + PersistentByteMap map = (PersistentByteMap)elements.nextElement(); + byte[] soName = map.get(digest); + if (soName != null) + return loadSharedLibrary(loader, + new String(soName), + domain, name); + } + } + catch (Exception _) + { + } + } + + if (! useCompiler || ! canUseCompiler) + return null; + + try + { + // FIXME: Make sure that the class represented by the + // bytes in DATA really is the class named in NAME. Make + // sure it's not "java.*". + StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir); + hexBytes.append(File.separatorChar); + int digestLength = digest.length; + for (int i = 0; i < digestLength; ++i) + hexBytes.append(Integer.toHexString(digest[i] & 0xff)); + + // FIXME: use System.mapLibraryName? + // I'm thinking we should use that, plus a class specified + // via a property that determines lookup policy. + File soFile = new File(hexBytes + ".so"); + if (soFile.isFile()) + return loadSharedLibrary (loader, soFile.toString(), domain, + name); + + File classFile = new File(hexBytes + ".class"); + classFile.delete(); + if (classFile.createNewFile() != true) + return null; + + FileOutputStream f = new FileOutputStream (classFile); + // FIXME: race condition if bytes change... ? + f.write(data, offset, len); + + // Invoke the compiler. + StringBuffer command = new StringBuffer(gcjJitCompiler); + command.append(" "); + command.append(classFile); + command.append(" "); + command.append(gcjJitCompilerOptions); + // These options are required. + command.append(" -findirect-dispatch -fjni -shared -fPIC -o "); + command.append(soFile); + Process p = Runtime.getRuntime().exec(command.toString()); + + // Read the process' stderr into a string. + StringBuffer err = new StringBuffer(); + InputStreamReader stderr = new InputStreamReader (p.getErrorStream()); + char[] inBuf = new char[500]; + int bytesRead; + while ((bytesRead = stderr.read (inBuf)) != -1) + err.append(inBuf, 0, bytesRead); + + if (p.waitFor() != 0) + { + // FIXME: we could log err.toString() somewhere... + return null; + } + + return loadSharedLibrary(loader, soFile.toString(), domain, name); + } + catch (Exception _) + { + return null; + } + } + + /** + * Compile the class named by <code>oneClass</code>. + * + * @param oneClass the class to compile + * @return <code>false</code> if no compiler is available or + * compilation failed, <code>true</code> if compilation succeeded + * @throws NullPointerException if oneClass is null + */ + public static boolean compileClass(Class oneClass) + { + // Never succeed. + return false; + } + + /** + * Compile the classes whose name matches <code>classNames</code>. + * + * @param classNames the name of classes to compile + * @return <code>false</code> if no compiler is available or + * compilation failed, <code>true</code> if compilation succeeded + * @throws NullPointerException if classNames is null + */ + public static boolean compileClasses(String classNames) + { + // Note the incredibly lame interface. Always fail. + return false; + } + + /** + * This method examines the argument and performs an operation + * according to the compilers documentation. No specific operation + * is required. + * + * @param arg a compiler-specific argument + * @return a compiler-specific value, including null + * @throws NullPointerException if the compiler doesn't like a null arg + */ + public static Object command(Object arg) + { + // Our implementation defines this to a no-op. + return null; + } + + /** + * Calling <code>Compiler.enable()</code> will cause the compiler + * to resume operation if it was previously disabled; provided that a + * compiler even exists. + */ + public static void enable() + { + useCompiler = true; + } + + /** + * Calling <code>Compiler.disable()</code> will cause the compiler + * to be suspended; provided that a compiler even exists. + */ + public static void disable() + { + useCompiler = false; + } +} diff --git a/libjava/java/lang/VMSecurityManager.java b/libjava/java/lang/VMSecurityManager.java index f6f0645ac75..604f8ecb428 100644 --- a/libjava/java/lang/VMSecurityManager.java +++ b/libjava/java/lang/VMSecurityManager.java @@ -54,11 +54,12 @@ class VMSecurityManager // The docs above are wrong. See the online docs. // FIXME this implementation is a bit wrong too -- the docs say we // must also consider ancestors of the system class loader. + ClassLoader systemClassLoader = VMClassLoader.getSystemClassLoader(); Class[] classStack = getClassContext (); for (int i = 0; i < classStack.length; i++) { ClassLoader loader = classStack[i].getClassLoader(); - if (loader != null) + if (loader != null && loader != systemClassLoader) return loader; } diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 920245cd586..0e9c26c7b4f 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -14,6 +14,7 @@ details. */ #include <limits.h> #include <string.h> #include <stddef.h> +#include <stdio.h> #pragma implementation "Class.h" @@ -56,16 +57,17 @@ details. */ #include <gcj/method.h> #include <gnu/gcj/runtime/MethodRef.h> #include <gnu/gcj/RawData.h> +#include <java/lang/VerifyError.h> #include <java-cpool.h> #include <java-interp.h> +#include <java-assert.h> +#include <execution.h> using namespace gcj; -bool gcj::verbose_class_flag; - jclass java::lang::Class::forName (jstring className, jboolean initialize, java::lang::ClassLoader *loader) @@ -485,7 +487,12 @@ java::lang::Class::getInterfaces (void) jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL); jobject *data = elements (r); for (int i = 0; i < interface_count; ++i) - data[i] = interfaces[i]; + { + typedef unsigned int uaddr __attribute__ ((mode (pointer))); + data[i] = interfaces[i]; + if ((uaddr)data[i] < (uaddr)constants.size) + fprintf (stderr, "ERROR !!!\n"); + } return reinterpret_cast<JArray<jclass> *> (r); } @@ -495,7 +502,8 @@ java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types) jstring partial_sig = getSignature (param_types, false); jint p_len = partial_sig->length(); _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name); - for (Class *klass = this; klass; klass = klass->getSuperclass()) + + for (Class *klass = this; klass; klass = klass->getSuperclass()) { int i = klass->isPrimitive () ? 0 : klass->method_count; while (--i >= 0) @@ -699,10 +707,7 @@ java::lang::Class::newInstance (void) void java::lang::Class::finalize (void) { -#ifdef INTERPRETER - JvAssert (_Jv_IsInterpretedClass (this)); - _Jv_UnregisterClass (this); -#endif + engine->unregister(this); } // This implements the initialization process for a class. From Spec @@ -710,67 +715,37 @@ java::lang::Class::finalize (void) void java::lang::Class::initializeClass (void) { - // short-circuit to avoid needless locking. + // Short-circuit to avoid needless locking. if (state == JV_STATE_DONE) return; - // Step 1. - _Jv_MonitorEnter (this); + // Step 1. We introduce a new scope so we can synchronize more + // easily. + { + JvSynchronize sync (this); - if (state < JV_STATE_LINKED) - { -#ifdef INTERPRETER - if (_Jv_IsInterpretedClass (this)) - { - // this can throw exceptions, so exit the monitor as a precaution. - _Jv_MonitorExit (this); - java::lang::VMClassLoader::resolveClass (this); - _Jv_MonitorEnter (this); - } - else -#endif - { - _Jv_PrepareCompiledClass (this); - } - } - - // Step 2. - java::lang::Thread *self = java::lang::Thread::currentThread(); - // FIXME: `self' can be null at startup. Hence this nasty trick. - self = (java::lang::Thread *) ((long) self | 1); - while (state == JV_STATE_IN_PROGRESS && thread && thread != self) - wait (); - - // Steps 3 & 4. - if (state == JV_STATE_DONE) - { - _Jv_MonitorExit (this); - return; - } - if (state == JV_STATE_IN_PROGRESS) - { - _Jv_MonitorExit (this); + if (state < JV_STATE_LINKED) + java::lang::VMClassLoader::resolveClass (this); - /* Initialization in progress. The class is linked now, - so ensure internal tables are built. */ - _Jv_PrepareConstantTimeTables (this); - _Jv_MakeVTable(this); - _Jv_LinkSymbolTable(this); + // Step 2. + java::lang::Thread *self = java::lang::Thread::currentThread(); + self = (java::lang::Thread *) ((long) self | 1); + while (state == JV_STATE_IN_PROGRESS && thread && thread != self) + wait (); + // Steps 3 & 4. + if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS) return; - } - // Step 5. - if (state == JV_STATE_ERROR) - { - _Jv_MonitorExit (this); + // Step 5. + if (state == JV_STATE_ERROR) throw new java::lang::NoClassDefFoundError (getName()); - } - // Step 6. - thread = self; - state = JV_STATE_IN_PROGRESS; - _Jv_MonitorExit (this); + // Step 6. + thread = self; + _Jv_Linker::wait_for_state (this, JV_STATE_LINKED); + state = JV_STATE_IN_PROGRESS; + } // Step 7. if (! isInterface () && superclass) @@ -782,24 +757,13 @@ java::lang::Class::initializeClass (void) catch (java::lang::Throwable *except) { // Caught an exception. - _Jv_MonitorEnter (this); + JvSynchronize sync (this); state = JV_STATE_ERROR; notifyAll (); - _Jv_MonitorExit (this); throw except; } } - _Jv_PrepareConstantTimeTables (this); - - if (vtable == NULL) - _Jv_MakeVTable(this); - - if (otable || atable) - _Jv_LinkSymbolTable(this); - - _Jv_linkExceptionClassTable (this); - // Steps 8, 9, 10, 11. try { @@ -821,17 +785,91 @@ java::lang::Class::initializeClass (void) except = t; } } - _Jv_MonitorEnter (this); + + JvSynchronize sync (this); state = JV_STATE_ERROR; notifyAll (); - _Jv_MonitorExit (this); throw except; } - _Jv_MonitorEnter (this); + JvSynchronize sync (this); state = JV_STATE_DONE; notifyAll (); - _Jv_MonitorExit (this); +} + +// Only used by serialization +java::lang::reflect::Field * +java::lang::Class::getPrivateField (jstring name) +{ + int hash = name->hashCode (); + + java::lang::reflect::Field* rfield; + for (int i = 0; i < field_count; i++) + { + _Jv_Field *field = &fields[i]; + if (! _Jv_equal (field->name, name, hash)) + continue; + rfield = new java::lang::reflect::Field (); + rfield->offset = (char*) field - (char*) fields; + rfield->declaringClass = this; + rfield->name = name; + return rfield; + } + jclass superclass = getSuperclass(); + if (superclass == NULL) + return NULL; + rfield = superclass->getPrivateField(name); + for (int i = 0; i < interface_count && rfield == NULL; ++i) + rfield = interfaces[i]->getPrivateField (name); + return rfield; +} + +// Only used by serialization +java::lang::reflect::Method * +java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types) +{ + jstring partial_sig = getSignature (param_types, false); + jint p_len = partial_sig->length(); + _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name); + for (Class *klass = this; klass; klass = klass->getSuperclass()) + { + int i = klass->isPrimitive () ? 0 : klass->method_count; + while (--i >= 0) + { + if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name) + && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)) + { + // Found it. + using namespace java::lang::reflect; + + Method *rmethod = new Method (); + rmethod->offset = ((char *) (&klass->methods[i]) + - (char *) klass->methods); + rmethod->declaringClass = klass; + return rmethod; + } + } + } + throw new java::lang::NoSuchMethodException (name); +} + +// Private accessor method for Java code to retrieve the protection domain. +java::security::ProtectionDomain * +java::lang::Class::getProtectionDomain0 () +{ + return protectionDomain; +} + +JArray<jobject> * +java::lang::Class::getSigners() +{ + return hack_signers; +} + +void +java::lang::Class::setSigners(JArray<jobject> *s) +{ + hack_signers = s; } @@ -857,14 +895,19 @@ _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name, _Jv_Method * _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name, - _Jv_Utf8Const *signature) + _Jv_Utf8Const *signature, + jclass *declarer_result) { for (; klass; klass = klass->getSuperclass()) { _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature); if (meth) - return meth; + { + if (declarer_result) + *declarer_result = klass; + return meth; + } } return NULL; @@ -886,7 +929,7 @@ _Jv_FindMethodInCache (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature) { - int index = name->hash16() & MCACHE_SIZE; + int index = name->hash16 () & MCACHE_SIZE; _Jv_mcache *mc = method_cache + index; _Jv_Method *m = mc->method; @@ -904,7 +947,7 @@ _Jv_AddMethodToCache (jclass klass, { _Jv_MonitorEnter (&java::lang::Class::class$); - int index = method->name->hash16() & MCACHE_SIZE; + int index = method->name->hash16 () & MCACHE_SIZE; method_cache[index].method = method; method_cache[index].klass = klass; @@ -1085,898 +1128,104 @@ _Jv_CheckArrayStore (jobject arr, jobject obj) } } -#define INITIAL_IOFFSETS_LEN 4 -#define INITIAL_IFACES_LEN 4 - -static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} }; - -// Generate tables for constant-time assignment testing and interface -// method lookup. This implements the technique described by Per Bothner -// <per@bothner.com> on the java-discuss mailing list on 1999-09-02: -// http://gcc.gnu.org/ml/java/1999-q3/msg00377.html -void -_Jv_PrepareConstantTimeTables (jclass klass) -{ - if (klass->isPrimitive () || klass->isInterface ()) - return; - - // Short-circuit in case we've been called already. - if ((klass->idt != NULL) || klass->depth != 0) - return; - - // Calculate the class depth and ancestor table. The depth of a class - // is how many "extends" it is removed from Object. Thus the depth of - // java.lang.Object is 0, but the depth of java.io.FilterOutputStream - // is 2. Depth is defined for all regular and array classes, but not - // interfaces or primitive types. - - jclass klass0 = klass; - jboolean has_interfaces = 0; - while (klass0 != &java::lang::Object::class$) - { - has_interfaces += klass0->interface_count; - klass0 = klass0->superclass; - klass->depth++; - } - - // We do class member testing in constant time by using a small table - // of all the ancestor classes within each class. The first element is - // 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. - - klass->ancestors = (jclass *) _Jv_Malloc (klass->depth * sizeof (jclass)); - klass0 = klass; - for (int index = 0; index < klass->depth; index++) - { - klass->ancestors[index] = klass0; - klass0 = klass0->superclass; - } - - if (java::lang::reflect::Modifier::isAbstract (klass->accflags)) - return; - - // Optimization: If class implements no interfaces, use a common - // predefined interface table. - if (!has_interfaces) - { - klass->idt = &null_idt; - return; - } - - klass->idt = - (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); - - _Jv_ifaces ifaces; - - ifaces.count = 0; - ifaces.len = INITIAL_IFACES_LEN; - ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *)); - - int itable_size = _Jv_GetInterfaces (klass, &ifaces); - - if (ifaces.count > 0) - { - klass->idt->cls.itable = - (void **) _Jv_Malloc (itable_size * sizeof (void *)); - klass->idt->cls.itable_length = itable_size; - - jshort *itable_offsets = - (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort)); - - _Jv_GenerateITable (klass, &ifaces, itable_offsets); - - jshort cls_iindex = - _Jv_FindIIndex (ifaces.list, itable_offsets, ifaces.count); - - for (int i=0; i < ifaces.count; i++) - { - ifaces.list[i]->idt->iface.ioffsets[cls_iindex] = - itable_offsets[i]; - } - - klass->idt->cls.iindex = cls_iindex; - - _Jv_Free (ifaces.list); - _Jv_Free (itable_offsets); - } - else - { - klass->idt->cls.iindex = SHRT_MAX; - } -} - -// Return index of item in list, or -1 if item is not present. -inline jshort -_Jv_IndexOf (void *item, void **list, jshort list_len) +jboolean +_Jv_IsAssignableFromSlow (jclass target, jclass source) { - for (int i=0; i < list_len; i++) + // First, strip arrays. + while (target->isArray ()) { - if (list[i] == item) - return i; + // If target is array, source must be as well. + if (! source->isArray ()) + return false; + target = target->getComponentType (); + source = source->getComponentType (); } - return -1; -} -// Find all unique interfaces directly or indirectly implemented by klass. -// Returns the size of the interface dispatch table (itable) for klass, which -// is the number of unique interfaces plus the total number of methods that -// those interfaces declare. May extend ifaces if required. -jshort -_Jv_GetInterfaces (jclass klass, _Jv_ifaces *ifaces) -{ - jshort result = 0; - - for (int i=0; i < klass->interface_count; i++) - { - jclass iface = klass->interfaces[i]; - - /* Make sure interface is linked. */ - _Jv_WaitForState(iface, JV_STATE_LINKED); + // Quick success. + if (target == &java::lang::Object::class$) + return true; - if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1) - { - if (ifaces->count + 1 >= ifaces->len) - { - /* Resize ifaces list */ - ifaces->len = ifaces->len * 2; - ifaces->list = (jclass *) _Jv_Realloc (ifaces->list, - ifaces->len * sizeof(jclass)); - } - ifaces->list[ifaces->count] = iface; - ifaces->count++; + // Ensure that the classes have their supers installed. + _Jv_Linker::wait_for_state (source, JV_STATE_LOADING); + _Jv_Linker::wait_for_state (target, JV_STATE_LOADING); - result += _Jv_GetInterfaces (klass->interfaces[i], ifaces); - } - } - - if (klass->isInterface()) - { - result += klass->method_count + 1; - } - else + do { - if (klass->superclass) - { - result += _Jv_GetInterfaces (klass->superclass, ifaces); - } + if (source == target) + return true; + + if (target->isPrimitive () || source->isPrimitive ()) + return false; + + if (target->isInterface ()) + { + for (int i = 0; i < source->interface_count; ++i) + { + // We use a recursive call because we also need to + // check superinterfaces. + if (_Jv_IsAssignableFromSlow (target, source->getInterface (i))) + return true; + } + } + source = source->getSuperclass (); } - return result; -} - -// Fill out itable in klass, resolving method declarations in each ifaces. -// itable_offsets is filled out with the position of each iface in itable, -// such that itable[itable_offsets[n]] == ifaces.list[n]. -void -_Jv_GenerateITable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets) -{ - void **itable = klass->idt->cls.itable; - jshort itable_pos = 0; - - for (int i=0; i < ifaces->count; i++) - { - jclass iface = ifaces->list[i]; - itable_offsets[i] = itable_pos; - itable_pos = _Jv_AppendPartialITable (klass, iface, itable, itable_pos); - - /* Create interface dispatch table for iface */ - if (iface->idt == NULL) - { - iface->idt = - (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); - - // The first element of ioffsets is its length (itself included). - jshort *ioffsets = - (jshort *) _Jv_Malloc (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; - } - } -} - -// Format method name for use in error messages. -jstring -_Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name) -{ - jstring r = klass->name->toString(); - r = r->concat (JvNewStringUTF (".")); - r = r->concat (name->toString()); - return r; -} - -void -_Jv_ThrowNoSuchMethodError () -{ - throw new java::lang::NoSuchMethodError; -} - -// Each superinterface of a class (i.e. each interface that the class -// directly or indirectly implements) has a corresponding "Partial -// Interface Dispatch Table" whose size is (number of methods + 1) words. -// The first word is a pointer to the interface (i.e. the java.lang.Class -// instance for that interface). The remaining words are pointers to the -// actual methods that implement the methods declared in the interface, -// in order of declaration. -// -// Append partial interface dispatch table for "iface" to "itable", at -// position itable_pos. -// Returns the offset at which the next partial ITable should be appended. -jshort -_Jv_AppendPartialITable (jclass klass, jclass iface, void **itable, - jshort pos) -{ - using namespace java::lang::reflect; - - itable[pos++] = (void *) iface; - _Jv_Method *meth; - - for (int j=0; j < iface->method_count; j++) - { - meth = NULL; - for (jclass cl = klass; cl; cl = cl->getSuperclass()) - { - meth = _Jv_GetMethodLocal (cl, iface->methods[j].name, - iface->methods[j].signature); - - if (meth) - break; - } + while (source != NULL); - if (meth && (meth->name->first() == '<')) - { - // leave a placeholder in the itable for hidden init methods. - itable[pos] = NULL; - } - else if (meth) - { - if (Modifier::isStatic(meth->accflags)) - throw new java::lang::IncompatibleClassChangeError - (_Jv_GetMethodString (klass, meth->name)); - if (Modifier::isAbstract(meth->accflags)) - throw new java::lang::AbstractMethodError - (_Jv_GetMethodString (klass, meth->name)); - if (! Modifier::isPublic(meth->accflags)) - throw new java::lang::IllegalAccessError - (_Jv_GetMethodString (klass, meth->name)); - - itable[pos] = meth->ncode; - } - else - { - // The method doesn't exist in klass. Binary compatibility rules - // permit this, so we delay the error until runtime using a pointer - // to a method which throws an exception. - itable[pos] = (void *) _Jv_ThrowNoSuchMethodError; - } - pos++; - } - - return pos; + return false; } -static _Jv_Mutex_t iindex_mutex; -static bool iindex_mutex_initialized = false; - -// We need to find the correct offset in the Class Interface Dispatch -// Table for a given interface. Once we have that, invoking an interface -// method just requires combining the Method's index in the interface -// (known at compile time) to get the correct method. Doing a type test -// (cast or instanceof) is the same problem: Once we have a possible Partial -// 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. +// Lookup an interface method by name. This is very similar to +// purpose to _getMethod, but the interfaces are quite different. It +// might be a good idea for _getMethod to call this function. // -// Calculate and return iindex for a new class. -// ifaces is a vector of num interfaces that the class implements. -// offsets[j] is the offset in the interface dispatch table for the -// interface corresponding to ifaces[j]. -// May extend the interface ioffsets if required. -jshort -_Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num) -{ - int i; - int j; - - // Acquire a global lock to prevent itable corruption in case of multiple - // classes that implement an intersecting set of interfaces being linked - // simultaneously. We can assume that the mutex will be initialized - // single-threaded. - if (! iindex_mutex_initialized) - { - _Jv_MutexInit (&iindex_mutex); - iindex_mutex_initialized = true; - } - - _Jv_MutexLock (&iindex_mutex); - - for (i=1;; i++) /* each potential position in ioffsets */ - { - for (j=0;; j++) /* each iface */ - { - if (j >= num) - goto found; - if (i >= ifaces[j]->idt->iface.ioffsets[0]) - continue; - int ioffset = ifaces[j]->idt->iface.ioffsets[i]; - /* We can potentially share this position with another class. */ - if (ioffset >= 0 && ioffset != offsets[j]) - break; /* Nope. Try next i. */ - } - } - found: - for (j = 0; j < num; j++) - { - int len = ifaces[j]->idt->iface.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; - jshort *new_ioffsets = (jshort *) _Jv_Realloc (old_ioffsets, - newlen * sizeof(jshort)); - new_ioffsets[0] = newlen; - - while (len < newlen) - new_ioffsets[len++] = -1; - - ifaces[j]->idt->iface.ioffsets = new_ioffsets; - } - ifaces[j]->idt->iface.ioffsets[i] = offsets[j]; - } - - _Jv_MutexUnlock (&iindex_mutex); - - return i; -} - -// Only used by serialization -java::lang::reflect::Field * -java::lang::Class::getPrivateField (jstring name) +// Return true of the method is found, with the class in FOUND_CLASS +// and the index in INDEX. +bool +_Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index, + const _Jv_Utf8Const *utf_name, + const _Jv_Utf8Const *utf_sig) { - int hash = name->hashCode (); - - java::lang::reflect::Field* rfield; - for (int i = 0; i < field_count; i++) + for (jclass klass = search_class; klass; klass = klass->getSuperclass()) { - _Jv_Field *field = &fields[i]; - if (! _Jv_equal (field->name, name, hash)) - continue; - rfield = new java::lang::reflect::Field (); - rfield->offset = (char*) field - (char*) fields; - rfield->declaringClass = this; - rfield->name = name; - return rfield; - } - jclass superclass = getSuperclass(); - if (superclass == NULL) - return NULL; - rfield = superclass->getPrivateField(name); - for (int i = 0; i < interface_count && rfield == NULL; ++i) - rfield = interfaces[i]->getPrivateField (name); - return rfield; -} - -// Only used by serialization -java::lang::reflect::Method * -java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types) -{ - jstring partial_sig = getSignature (param_types, false); - jint p_len = partial_sig->length(); - _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name); - for (Class *klass = this; klass; klass = klass->getSuperclass()) - { - int i = klass->isPrimitive () ? 0 : klass->method_count; + // FIXME: Throw an exception? + if (!klass->isInterface ()) + return false; + + int i = klass->method_count; while (--i >= 0) { if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name) - && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)) + && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig)) { // Found it. using namespace java::lang::reflect; - Method *rmethod = new Method (); - rmethod->offset = ((char *) (&klass->methods[i]) - - (char *) klass->methods); - rmethod->declaringClass = klass; - return rmethod; - } - } - } - throw new java::lang::NoSuchMethodException (name); -} - -// Private accessor method for Java code to retrieve the protection domain. -java::security::ProtectionDomain * -java::lang::Class::getProtectionDomain0 () -{ - return protectionDomain; -} - -JArray<jobject> * -java::lang::Class::getSigners() -{ - return hack_signers; -} - -void -java::lang::Class::setSigners(JArray<jobject> *s) -{ - hack_signers = s; -} - -// Functions for indirect dispatch (symbolic virtual binding) support. - -// There are two tables, atable and otable. atable is an array of -// addresses, and otable is an array of offsets, and these are used -// for static and virtual members respectively. - -// {a,o}table_syms is an array of _Jv_MethodSymbols. Each such symbol -// is a tuple of {classname, member name, signature}. -// _Jv_LinkSymbolTable() scans these two arrays and fills in the -// corresponding atable and otable with the addresses of static -// members and the offsets of virtual members. - -// The offset (in bytes) for each resolved method or field is placed -// at the corresponding position in the virtual method offset table -// (klass->otable). - -// The same otable and atable may be shared by many classes. - -void -_Jv_LinkSymbolTable(jclass klass) -{ - //// FIXME: Need to lock the tables //// - - int index = 0; - _Jv_MethodSymbol sym; - if (klass->otable == NULL - || klass->otable->state != 0) - goto atable; - - klass->otable->state = 1; - - for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++) - { - // FIXME: Why are we passing NULL as the class loader? - jclass target_class = _Jv_FindClass (sym.class_name, NULL); - _Jv_Method *meth = NULL; - - const _Jv_Utf8Const *signature = sym.signature; - - { - static char *bounce = (char *)_Jv_ThrowNoSuchMethodError; - ptrdiff_t offset = (char *)(klass->vtable) - bounce; - klass->otable->offsets[index] = offset; - } - - if (target_class == NULL) - continue; - - if (target_class->isInterface()) - { - // FIXME: This does not yet fully conform to binary compatibility - // rules. It will break if a declaration is moved into a - // superinterface. - for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ()) - { - for (int i=0; i < cls->method_count; i++) - { - meth = &cls->methods[i]; - if (_Jv_equalUtf8Consts (sym.name, meth->name) - && _Jv_equalUtf8Consts (signature, meth->signature)) - { - klass->otable->offsets[index] = i + 1; - goto found; - } - } - - } - found: - continue; - } - - // We're looking for a field or a method, and we can tell - // which is needed by looking at the signature. - 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 - // it out now. - if (target_class->vtable_method_count == -1) - { - JvSynchronize sync (target_class); - _Jv_LayoutVTableMethods (target_class); - } - - meth = _Jv_LookupDeclaredMethod(target_class, sym.name, - sym.signature); - - if (meth != NULL) - { - klass->otable->offsets[index] = - _Jv_VTable::idx_to_offset (meth->index); - } - - continue; - } - - // try fields - { - _Jv_Field *the_field = NULL; - - for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ()) - { - for (int i = 0; i < cls->field_count; i++) - { - _Jv_Field *field = &cls->fields[i]; - if (! _Jv_equalUtf8Consts (field->name, sym.name)) - continue; - - // FIXME: What access checks should we perform here? -// if (_Jv_CheckAccess (klass, cls, field->flags)) -// { - - if (!field->isResolved ()) - _Jv_ResolveField (field, cls->loader); - -// if (field_type != 0 && field->type != field_type) -// throw new java::lang::LinkageError -// (JvNewStringLatin1 -// ("field type mismatch with different loaders")); - - the_field = field; - goto end_of_field_search; - } - } - end_of_field_search: - if (the_field != NULL) - { - if (the_field->flags & 0x0008 /* Modifier::STATIC */) - { - throw new java::lang::IncompatibleClassChangeError; - } - else - { - klass->otable->offsets[index] = the_field->u.boffset; - } - } - else - { - throw new java::lang::NoSuchFieldError - (_Jv_NewStringUtf8Const (sym.name)); - } - } - } - - atable: - if (klass->atable == NULL - || klass->atable->state != 0) - return; - - klass->atable->state = 1; - - for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++) - { - // FIXME: Why are we passing NULL as the class loader? - jclass target_class = _Jv_FindClass (sym.class_name, NULL); - _Jv_Method *meth = NULL; - const _Jv_Utf8Const *signature = sym.signature; - - // ??? Setting this pointer to null will at least get us a - // NullPointerException - klass->atable->addresses[index] = NULL; - - if (target_class == NULL) - continue; - - // 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) - { - // 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 - // it out now. - if (target_class->vtable_method_count == -1) - { - JvSynchronize sync (target_class); - _Jv_LayoutVTableMethods (target_class); - } - - meth = _Jv_LookupDeclaredMethod(target_class, sym.name, - sym.signature); - - if (meth != NULL) - { - if (meth->ncode) // Maybe abstract? - klass->atable->addresses[index] = meth->ncode; -#ifdef INTERPRETER - else if (_Jv_IsInterpretedClass (target_class)) - _Jv_Defer_Resolution (target_class, meth, - &klass->atable->addresses[index]); -#endif - } - else - klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError; - - continue; - } - - // try fields - { - _Jv_Field *the_field = NULL; - - for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ()) - { - for (int i = 0; i < cls->field_count; i++) - { - _Jv_Field *field = &cls->fields[i]; - if (! _Jv_equalUtf8Consts (field->name, sym.name)) - continue; - - // FIXME: What access checks should we perform here? -// if (_Jv_CheckAccess (klass, cls, field->flags)) -// { - - if (!field->isResolved ()) - _Jv_ResolveField (field, cls->loader); - -// if (field_type != 0 && field->type != field_type) -// throw new java::lang::LinkageError -// (JvNewStringLatin1 -// ("field type mismatch with different loaders")); - - the_field = field; - goto end_of_static_field_search; - } - } - end_of_static_field_search: - if (the_field != NULL) - { - if (the_field->flags & 0x0008 /* Modifier::STATIC */) - { - klass->atable->addresses[index] = the_field->u.addr; - } - else - { - throw new java::lang::IncompatibleClassChangeError; - } - } - else - { - throw new java::lang::NoSuchFieldError - (_Jv_NewStringUtf8Const (sym.name)); - } - } - } -} - - -// For each catch_record in the list of caught classes, fill in the -// address field. -void -_Jv_linkExceptionClassTable (jclass self) -{ - struct _Jv_CatchClass *catch_record = self->catch_classes; - if (!catch_record || catch_record->classname) - return; - catch_record++; - while (catch_record->classname) - { - jclass target_class = _Jv_FindClass (catch_record->classname, - self->getClassLoaderInternal ()); - *catch_record->address = target_class; - catch_record++; - } - self->catch_classes->classname = (_Jv_Utf8Const *)-1; -} - -// This is put in empty vtable slots. -static void -_Jv_abstractMethodError (void) -{ - throw new java::lang::AbstractMethodError(); -} - -// Set itable method indexes for members of interface IFACE. -void -_Jv_LayoutInterfaceMethods (jclass iface) -{ - if (! iface->isInterface()) - return; - - // itable indexes start at 1. - // FIXME: Static initalizers currently get a NULL placeholder entry in the - // itable so they are also assigned an index here. - for (int i = 0; i < iface->method_count; i++) - iface->methods[i].index = i + 1; -} - -// Prepare virtual method declarations in KLASS, and any superclasses as -// required, by determining their vtable index, setting method->index, and -// finally setting the class's vtable_method_count. Must be called with the -// lock for KLASS held. -void -_Jv_LayoutVTableMethods (jclass klass) -{ - if (klass->vtable != NULL || klass->isInterface() - || klass->vtable_method_count != -1) - return; - - jclass superclass = klass->superclass; - - typedef unsigned int uaddr __attribute__ ((mode (pointer))); + // FIXME: Method must be public. Throw an exception? + if (! Modifier::isPublic (klass->methods[i].accflags)) + break; - // If superclass looks like a constant pool entry, - // resolve it now. - if ((uaddr) superclass < (uaddr) klass->constants.size) - { - if (klass->state < JV_STATE_LINKED) - { - _Jv_Utf8Const *name = klass->constants.data[(uaddr) superclass].utf8; - superclass = _Jv_FindClass (name, klass->loader); - if (! superclass) - { - throw new java::lang::NoClassDefFoundError (name->toString()); + found_class = klass; + // Interface method indexes count from 1. + index = i+1; + return true; } } - else - superclass = klass->constants.data[(uaddr) superclass].clazz; - } - - if (superclass != NULL && superclass->vtable_method_count == -1) - { - JvSynchronize sync (superclass); - _Jv_LayoutVTableMethods (superclass); - } - - int index = (superclass == NULL ? 0 : superclass->vtable_method_count); - - for (int i = 0; i < klass->method_count; ++i) - { - _Jv_Method *meth = &klass->methods[i]; - _Jv_Method *super_meth = NULL; - - if (! _Jv_isVirtualMethod (meth)) - continue; - - // FIXME: Must check that we don't override: - // - Package-private method where superclass is in different package. - // - Final or less-accessible declaration in superclass (check binary - // spec, do we allocate new vtable entry or put throw node in vtable?) - // - Static or private method in superclass. - - if (superclass != NULL) - { - super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, - meth->signature); - } - - if (super_meth) - meth->index = super_meth->index; - else - meth->index = index++; - } - - klass->vtable_method_count = index; -} - -// Set entries in VTABLE for virtual methods declared in KLASS. If -// KLASS has an immediate abstract parent, recursively do its methods -// first. FLAGS is used to determine which slots we've actually set. -void -_Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags) -{ - using namespace java::lang::reflect; - - jclass superclass = klass->getSuperclass(); - - if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT)) - _Jv_SetVTableEntries (superclass, vtable, flags); - - for (int i = klass->method_count - 1; i >= 0; i--) - { - _Jv_Method *meth = &klass->methods[i]; - if (meth->index == (_Jv_ushort) -1) - continue; - if ((meth->accflags & Modifier::ABSTRACT)) - { - vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError); - flags[meth->index] = false; - } - else - { - vtable->set_method(meth->index, meth->ncode); - flags[meth->index] = true; - } } -} - -// Allocate and lay out the virtual method table for KLASS. This will also -// cause vtables to be generated for any non-abstract superclasses, and -// virtual method layout to occur for any abstract superclasses. Must be -// called with monitor lock for KLASS held. -void -_Jv_MakeVTable (jclass klass) -{ - using namespace java::lang::reflect; - if (klass->vtable != NULL || klass->isInterface() - || (klass->accflags & Modifier::ABSTRACT)) - return; - - // Class must be laid out before we can create a vtable. - if (klass->vtable_method_count == -1) - _Jv_LayoutVTableMethods (klass); - - // Allocate the new vtable. - _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count); - klass->vtable = vtable; - - jboolean flags[klass->vtable_method_count]; - for (int i = 0; i < klass->vtable_method_count; ++i) - flags[i] = false; - - // Copy the vtable of the closest non-abstract superclass. - jclass superclass = klass->superclass; - if (superclass != NULL) + // If we haven't found a match, and this class is an interface, then + // check all the superinterfaces. + if (search_class->isInterface()) { - while ((superclass->accflags & Modifier::ABSTRACT) != 0) - superclass = superclass->superclass; - - if (superclass->vtable == NULL) - { - JvSynchronize sync (superclass); - _Jv_MakeVTable (superclass); - } - - for (int i = 0; i < superclass->vtable_method_count; ++i) + for (int i = 0; i < search_class->interface_count; ++i) { - vtable->set_method (i, superclass->vtable->get_method (i)); - flags[i] = true; + using namespace java::lang::reflect; + bool found = _Jv_getInterfaceMethod (search_class->interfaces[i], + found_class, index, + utf_name, utf_sig); + if (found) + return true; } } - // Set the class pointer and GC descriptor. - vtable->clas = klass; - vtable->gc_descr = _Jv_BuildGCDescr (klass); - - // For each virtual declared in klass and any immediate abstract - // superclasses, set new vtable entry or override an old one. - _Jv_SetVTableEntries (klass, vtable, flags); - - // It is an error to have an abstract method in a concrete class. - if (! (klass->accflags & Modifier::ABSTRACT)) - { - for (int i = 0; i < klass->vtable_method_count; ++i) - if (! flags[i]) - { - using namespace java::lang; - while (klass != NULL) - { - for (int j = 0; j < klass->method_count; ++j) - { - if (klass->methods[i].index == i) - { - StringBuffer *buf = new StringBuffer (); - buf->append (_Jv_NewStringUtf8Const (klass->methods[i].name)); - buf->append ((jchar) ' '); - buf->append (_Jv_NewStringUtf8Const (klass->methods[i].signature)); - throw new AbstractMethodError (buf->toString ()); - } - } - klass = klass->getSuperclass (); - } - // Couldn't find the name, which is weird. - // But we still must throw the error. - throw new AbstractMethodError (); - } - } + return false; } diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index 5a0898a93c4..dd5cd463cfa 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -18,6 +18,7 @@ details. */ #include <gcj/cni.h> #include <jvm.h> +#include <execution.h> #include <java-threads.h> #include <java-interp.h> @@ -33,6 +34,7 @@ details. */ #include <java/lang/ClassNotFoundException.h> #include <java/lang/ClassCircularityError.h> #include <java/lang/IncompatibleClassChangeError.h> +#include <java/lang/ClassFormatError.h> #include <java/lang/VirtualMachineError.h> #include <java/lang/VMClassLoader.h> #include <java/lang/reflect/Modifier.h> @@ -41,156 +43,6 @@ details. */ #include <java/io/Serializable.h> #include <java/lang/Cloneable.h> -void -_Jv_WaitForState (jclass klass, int state) -{ - if (klass->state >= state) - return; - - _Jv_MonitorEnter (klass) ; - - if (klass->state == JV_STATE_COMPILED) - { - klass->state = JV_STATE_LOADED; - if (gcj::verbose_class_flag) - fprintf (stderr, "[Loaded (pre-compiled) %s]\n", klass->name->chars()); - } - if (state == JV_STATE_LINKED) - { - // Must call _Jv_PrepareCompiledClass while holding the class - // mutex. -#ifdef INTERPRETER - if (_Jv_IsInterpretedClass (klass)) - _Jv_PrepareClass (klass); -#endif - _Jv_PrepareCompiledClass (klass); - _Jv_MonitorExit (klass); - return; - } - - java::lang::Thread *self = java::lang::Thread::currentThread(); - - // this is similar to the strategy for class initialization. - // if we already hold the lock, just leave. - while (klass->state <= state - && klass->thread - && klass->thread != self) - klass->wait (); - - _Jv_MonitorExit (klass); - - if (klass->state == JV_STATE_ERROR) - throw new java::lang::LinkageError; -} - -typedef unsigned int uaddr __attribute__ ((mode (pointer))); - -/** This function does class-preparation for compiled classes. - NOTE: It contains replicated functionality from - _Jv_ResolvePoolEntry, and this is intentional, since that function - lives in resolve.cc which is entirely conditionally compiled. - */ -void -_Jv_PrepareCompiledClass (jclass klass) -{ - jint state = klass->state; - if (state >= JV_STATE_LINKED) - return; - - // Short-circuit, so that mutually dependent classes are ok. - klass->state = JV_STATE_LINKED; - - _Jv_Constants *pool = &klass->constants; - - // Resolve class constants first, since other constant pool - // entries may rely on these. - for (int index = 1; index < pool->size; ++index) - { - if (pool->tags[index] == JV_CONSTANT_Class) - { - _Jv_Utf8Const *name = pool->data[index].utf8; - - jclass found; - if (name->first() == '[') - found = _Jv_FindClassFromSignature (name->chars(), - klass->loader); - else - found = _Jv_FindClass (name, klass->loader); - - if (! found) - { - jstring str = name->toString(); - throw new java::lang::NoClassDefFoundError (str); - } - - pool->data[index].clazz = found; - pool->tags[index] |= JV_CONSTANT_ResolvedFlag; - } - } - - // If superclass looks like a constant pool entry, - // resolve it now. - if ((uaddr) klass->superclass < 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] < pool->size) - klass->interfaces[i] = pool->data[(uaddr) klass->interfaces[i]].clazz; - - // Resolve the remaining constant pool entries. - for (int index = 1; index < pool->size; ++index) - { - if (pool->tags[index] == JV_CONSTANT_String) - { - jstring str; - - str = _Jv_NewStringUtf8Const (pool->data[index].utf8); - pool->data[index].o = str; - pool->tags[index] |= JV_CONSTANT_ResolvedFlag; - } - } - -#ifdef INTERPRETER - // FIXME: although the comment up top says that this function is - // only called for compiled classes, it is actually called for every - // class. - if (! _Jv_IsInterpretedClass (klass)) - { -#endif /* INTERPRETER */ - jfieldID f = JvGetFirstStaticField (klass); - for (int n = JvNumStaticFields (klass); n > 0; --n) - { - int mod = f->getModifiers (); - // If we have a static String field with a non-null initial - // value, we know it points to a Utf8Const. - _Jv_ResolveField(f, klass->loader); - if (f->getClass () == &java::lang::String::class$ - && java::lang::reflect::Modifier::isStatic (mod)) - { - jstring *strp = (jstring *) f->u.addr; - if (*strp) - *strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp); - } - f = f->getNextField (); - } -#ifdef INTERPRETER - } -#endif /* INTERPRETER */ - - if (klass->isInterface ()) - _Jv_LayoutInterfaceMethods (klass); - - if (state == JV_STATE_COMPILED && gcj::verbose_class_flag) - fprintf (stderr, "[Loaded (pre-compiled) %s]\n", - klass->name->chars()); - - klass->notifyAll (); - - _Jv_PushClass (klass); -} - - // // A single class can have many "initiating" class loaders, // and a single "defining" class loader. The Defining @@ -221,6 +73,8 @@ static _Jv_LoaderInfo *initiated_classes[HASH_LEN]; static jclass loaded_classes[HASH_LEN]; // This is the root of a linked list of classes +static jclass stack_head; + @@ -323,11 +177,6 @@ _Jv_RegisterClasses (const jclass *classes) jclass klass = *classes; (*_Jv_RegisterClassHook) (klass); - - // registering a compiled class causes - // it to be immediately "prepared". - if (klass->state == JV_STATE_NOTHING) - klass->state = JV_STATE_COMPILED; } } @@ -341,11 +190,6 @@ _Jv_RegisterClasses_Counted (const jclass * classes, size_t count) jclass klass = classes[i]; (*_Jv_RegisterClassHook) (klass); - - // registering a compiled class causes - // it to be immediately "prepared". - if (klass->state == JV_STATE_NOTHING) - klass->state = JV_STATE_COMPILED; } } @@ -354,8 +198,10 @@ _Jv_RegisterClassHookDefault (jclass klass) { jint hash = HASH_UTF (klass->name); - jclass check_class = loaded_classes[hash]; - + // The BC ABI makes this check unnecessary: we always resolve all + // data references via the appropriate class loader, so the kludge + // that required this check has gone. +#if 0 // If the class is already registered, don't re-register it. while (check_class != NULL) { @@ -381,7 +227,11 @@ _Jv_RegisterClassHookDefault (jclass klass) check_class = check_class->next; } +#endif + // FIXME: this is really bogus! + if (! klass->engine) + klass->engine = &_Jv_soleCompiledEngine; klass->next = loaded_classes[hash]; loaded_classes[hash] = klass; } @@ -442,7 +292,7 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader) { // we need classes to be in the hash while // we're loading, so that they can refer to themselves. - _Jv_WaitForState (klass, JV_STATE_LOADED); + _Jv_Linker::wait_for_state (klass, JV_STATE_LOADED); } return klass; @@ -555,7 +405,7 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader, // cache one and reuse it. It is not necessary to synchronize this. if (!array_idt) { - _Jv_PrepareConstantTimeTables (array_class); + _Jv_Linker::wait_for_state(array_class, JV_STATE_PREPARED); array_idt = array_class->idt; array_depth = array_class->depth; array_ancestors = array_class->ancestors; @@ -569,19 +419,19 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader, using namespace java::lang::reflect; { - // Array classes are "abstract final"... - _Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT; - // ... and inherit accessibility from element type, per vmspec 5.3.3.2 - accflags |= (element->accflags & Modifier::PUBLIC); - accflags |= (element->accflags & Modifier::PROTECTED); - accflags |= (element->accflags & Modifier::PRIVATE); + // Array classes are "abstract final" and inherit accessibility + // from element type, per vmspec 5.3.3.2 + _Jv_ushort accflags = (Modifier::FINAL | Modifier::ABSTRACT + | (element->accflags + & (Modifier::PUBLIC | Modifier::PROTECTED + | Modifier::PRIVATE))); array_class->accflags = accflags; } // An array class has no visible instance fields. "length" is invisible to // reflection. - // say this class is initialized and ready to go! + // Say this class is initialized and ready to go! array_class->state = JV_STATE_DONE; // vmspec, section 5.3.3 describes this @@ -591,8 +441,6 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader, element->arrayclass = array_class; } -static jclass stack_head; - // These two functions form a stack of classes. When a class is loaded // it is pushed onto the stack by the class loader; this is so that // StackTrace can quickly determine which classes have been loaded. diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc index 1e57f50113d..332f2c7b625 100644 --- a/libjava/java/lang/natRuntime.cc +++ b/libjava/java/lang/natRuntime.cc @@ -1,6 +1,6 @@ // natRuntime.cc - Implementation of native side of Runtime class. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -388,8 +388,11 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops) newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val)) // A mixture of the Java Product Versioning Specification - // (introduced in 1.2), and earlier versioning properties. - SET ("java.version", GCJVERSION); + // (introduced in 1.2), and earlier versioning properties. Some + // programs rely on seeing values that they expect, so we claim to + // be a 1.4-ish VM for their sake. + SET ("java.version", "1.4.2"); + SET ("java.runtime.version", "1.4.2"); SET ("java.vendor", "Free Software Foundation, Inc."); SET ("java.vendor.url", "http://gcc.gnu.org/java/"); SET ("java.class.version", "46.0"); @@ -399,7 +402,7 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops) SET ("java.vm.version", __VERSION__); SET ("java.vm.vendor", "Free Software Foundation, Inc."); SET ("java.vm.name", "GNU libgcj"); - SET ("java.specification.version", "1.3"); + SET ("java.specification.version", "1.4"); SET ("java.specification.name", "Java(tm) Platform API Specification"); SET ("java.specification.vendor", "Sun Microsystems Inc."); diff --git a/libjava/java/lang/natString.cc b/libjava/java/lang/natString.cc index cba0976bd95..e2558f4f747 100644 --- a/libjava/java/lang/natString.cc +++ b/libjava/java/lang/natString.cc @@ -1,7 +1,6 @@ // natString.cc - Implementation of java.lang.String native methods. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -57,7 +56,7 @@ static int strhash_size = 0; /* Number of slots available in strhash. jstring* _Jv_StringFindSlot (jchar* data, jint len, jint hash) { - JvSynchronize sync (&StringClass); + JvSynchronize sync (&java::lang::String::class$); int start_index = hash & (strhash_size - 1); int deleted_index = -1; @@ -120,7 +119,7 @@ _Jv_StringGetSlot (jstring str) static void rehash () { - JvSynchronize sync (&StringClass); + JvSynchronize sync (&java::lang::String::class$); if (strhash == NULL) { @@ -167,7 +166,7 @@ rehash () jstring java::lang::String::intern() { - JvSynchronize sync (&StringClass); + JvSynchronize sync (&java::lang::String::class$); if (3 * strhash_count >= 2 * strhash_size) rehash(); jstring* ptr = _Jv_StringGetSlot(this); @@ -194,7 +193,7 @@ java::lang::String::intern() void _Jv_FinalizeString (jobject obj) { - JvSynchronize sync (&StringClass); + JvSynchronize sync (&java::lang::String::class$); // We might not actually have intern()d any strings at all, if // we're being called from Reference. @@ -286,9 +285,9 @@ _Jv_NewStringUtf8Const (Utf8Const* str) } chrs -= length; - JvSynchronize sync (&StringClass); + JvSynchronize sync (&java::lang::String::class$); if (3 * strhash_count >= 2 * strhash_size) - rehash (); + rehash(); jstring* ptr = _Jv_StringFindSlot (chrs, length, hash); if (*ptr != NULL && *ptr != DELETED_STRING) return (jstring) UNMASK_PTR (*ptr); @@ -527,7 +526,7 @@ java::lang::String::equals(jobject anObject) return false; if (anObject == this) return true; - if (anObject->getClass() != &StringClass) + if (anObject->getClass() != &java::lang::String::class$) return false; jstring other = (jstring) anObject; if (count != other->count) diff --git a/libjava/java/lang/natVMClassLoader.cc b/libjava/java/lang/natVMClassLoader.cc index 1ed3851fbb3..841b3e0789e 100644 --- a/libjava/java/lang/natVMClassLoader.cc +++ b/libjava/java/lang/natVMClassLoader.cc @@ -22,6 +22,7 @@ details. */ #include <java-interp.h> #include <java/lang/VMClassLoader.h> +#include <java/lang/VMCompiler.h> #include <gnu/gcj/runtime/VMClassLoader.h> #include <java/lang/ClassLoader.h> #include <java/lang/Class.h> @@ -29,6 +30,21 @@ details. */ #include <java/security/ProtectionDomain.h> #include <java/lang/ClassFormatError.h> +void +java::lang::VMClassLoader::resolveClass (jclass klass) +{ + JvSynchronize sync (klass); + try + { + _Jv_Linker::wait_for_state (klass, JV_STATE_LINKED); + } + catch (java::lang::Throwable *x) + { + klass->set_state(JV_STATE_ERROR); + transformException(klass, x); + } +} + java::lang::Class * java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader, jstring name, @@ -37,72 +53,61 @@ java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader, jint length, java::security::ProtectionDomain *pd) { -#ifdef INTERPRETER - jclass klass; - klass = new java::lang::Class (); - klass->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass)); - - // Synchronize on the class, so that it is not attempted initialized - // until we're done loading. - JvSynchronize sync (klass); - - // Record the defining loader. For the system class loader, we - // record NULL. - if (loader != java::lang::ClassLoader::getSystemClassLoader()) - klass->loader = loader; - - if (name != 0) - { - _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name); - - if (! _Jv_VerifyClassName (name2)) - throw new java::lang::ClassFormatError - (JvNewStringLatin1 ("erroneous class name")); - - klass->name = name2; - } + jclass klass = VMCompiler::compileClass(loader, name, data, + offset, length, pd); - try + if (klass != NULL) { - _Jv_DefineClass (klass, data, offset, length); + JvSynchronize sync (&java::lang::Class::class$); + _Jv_RegisterClass (klass); } - catch (java::lang::Throwable *ex) +#ifdef INTERPRETER + else { - klass->state = JV_STATE_ERROR; - klass->notifyAll (); - - _Jv_UnregisterClass (klass); - - // If EX is not a ClassNotFoundException, that's ok, because we - // account for the possibility in defineClass(). - throw ex; + klass = new java::lang::Class (); + + // Synchronize on the class, so that it is not attempted initialized + // until we're done loading. + JvSynchronize sync (klass); + + // Record the defining loader. For the system class loader, we + // record NULL. + if (loader != java::lang::ClassLoader::getSystemClassLoader()) + klass->loader = loader; + + if (name != 0) + { + _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name); + + if (! _Jv_VerifyClassName (name2)) + throw new java::lang::ClassFormatError + (JvNewStringLatin1 ("erroneous class name")); + + klass->name = name2; + } + + try + { + _Jv_DefineClass (klass, data, offset, length, pd); + } + catch (java::lang::Throwable *ex) + { + klass->state = JV_STATE_ERROR; + klass->notifyAll (); + + _Jv_UnregisterClass (klass); + + // If EX is not a ClassNotFoundException, that's ok, because we + // account for the possibility in defineClass(). + throw ex; + } + + // if everything proceeded sucessfully, we're loaded. + JvAssert (klass->state == JV_STATE_LOADED); } - - klass->protectionDomain = pd; - - // if everything proceeded sucessfully, we're loaded. - JvAssert (klass->state == JV_STATE_LOADED); +#endif // INTERPRETER return klass; - -#else // INTERPRETER - - return 0; -#endif -} - -// Finish linking a class. Only called from ClassLoader::resolveClass. -void -java::lang::VMClassLoader::linkClass0 (java::lang::Class *klass) -{ - _Jv_WaitForState (klass, JV_STATE_LINKED); -} - -void -java::lang::VMClassLoader::markClassErrorState0 (java::lang::Class *klass) -{ - klass->state = JV_STATE_ERROR; - klass->notifyAll (); } java::lang::ClassLoader * @@ -125,9 +130,16 @@ jclass java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve) { _Jv_Utf8Const *utf = _Jv_makeUtf8Const (name); - // FIXME: we culd make _Jv_FindClassFromSignature a template. jclass klass = _Jv_FindClassInCache (utf, NULL); - if (klass && resolve) - _Jv_InitClass (klass); + if (klass) + { + // We never want to return a class without its supers linked. + // It isn't clear from the spec, but this is what other + // implementations do in practice. + if (resolve) + _Jv_InitClass (klass); + else + _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING); + } return klass; } diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc index 469cf74de8e..7eb032227ab 100644 --- a/libjava/java/lang/reflect/natField.cc +++ b/libjava/java/lang/reflect/natField.cc @@ -1,6 +1,6 @@ // natField.cc - Implementation of java.lang.reflect.Field native methods. -/* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -47,7 +47,7 @@ java::lang::reflect::Field::getType () { jfieldID fld = _Jv_FromReflectedField (this); JvSynchronize sync (declaringClass); - _Jv_ResolveField (fld, declaringClass->getClassLoaderInternal ()); + _Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ()); return fld->type; } diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc index 8c6efc487cd..b194067300b 100644 --- a/libjava/java/lang/reflect/natMethod.cc +++ b/libjava/java/lang/reflect/natMethod.cc @@ -1,6 +1,6 @@ // natMethod.cc - Native code for Method class. -/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003, 2004 Free Software Foundation This file is part of libgcj. @@ -149,7 +149,6 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) getType (); jmethodID meth = _Jv_FromReflectedMethod (this); - jclass objClass; if (Modifier::isStatic(meth->accflags)) { @@ -157,12 +156,10 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) // here and not in _Jv_CallAnyMethodA because JNI initializes a // class whenever a method lookup is done. _Jv_InitClass (declaringClass); - objClass = declaringClass; } else { - objClass = JV_CLASS (obj); - + jclass objClass = JV_CLASS (obj); if (! _Jv_IsAssignableFrom (declaringClass, objClass)) throw new java::lang::IllegalArgumentException; } @@ -184,7 +181,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) { } - if (! _Jv_CheckAccess(caller, objClass, meth->accflags)) + if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags)) throw new IllegalAccessException; } diff --git a/libjava/java/net/URLClassLoader.java b/libjava/java/net/URLClassLoader.java index 4ffd4c532db..3efc5dca76f 100644 --- a/libjava/java/net/URLClassLoader.java +++ b/libjava/java/net/URLClassLoader.java @@ -54,6 +54,8 @@ import java.security.SecureClassLoader; import java.security.cert.Certificate; import java.util.Enumeration; import java.util.HashMap; +import java.util.Iterator; +import java.util.StringTokenizer; import java.util.Vector; import java.util.jar.Attributes; import java.util.jar.JarEntry; @@ -144,9 +146,10 @@ public class URLClassLoader extends SecureClassLoader private final Vector urls = new Vector(); /** - * Store pre-parsed information for each url into this vector - * each element is a URL loader, corresponding to the URL of - * the same index in "urls" + * Store pre-parsed information for each url into this vector: each + * element is a URL loader. A jar file has its own class-path + * attribute which adds to the URLs that will be searched, but this + * does not add to the list of urls. */ private final Vector urlinfos = new Vector(); @@ -189,9 +192,14 @@ public class URLClassLoader extends SecureClassLoader URLLoader(URLClassLoader classloader, URL baseURL) { + this(classloader, baseURL, baseURL); + } + + URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL) + { this.classloader = classloader; this.baseURL = baseURL; - this.noCertCodeSource = new CodeSource(baseURL, null); + this.noCertCodeSource = new CodeSource(overrideURL, null); } /** @@ -221,6 +229,11 @@ public class URLClassLoader extends SecureClassLoader { return null; } + + Vector getClassPath() + { + return null; + } } /** @@ -290,6 +303,10 @@ public class URLClassLoader extends SecureClassLoader final JarFile jarfile; // The jar file for this url final URL baseJarURL; // Base jar: url for all resources loaded from jar + Vector classPath; // The "Class-Path" attribute of this Jar's manifest + + SoURLLoader soURLLoader; + public JarURLLoader(URLClassLoader classloader, URL baseURL) { super(classloader, baseURL); @@ -302,25 +319,87 @@ public class URLClassLoader extends SecureClassLoader sb.append("!/"); String jarURL = sb.toString(); + this.soURLLoader = null; + this.classPath = null; URL baseJarURL = null; JarFile jarfile = null; try - { - baseJarURL = - new URL(null, jarURL, classloader.getURLStreamHandler("jar")); - - jarfile = - ((JarURLConnection) baseJarURL.openConnection()).getJarFile(); - } + { + baseJarURL + = new URL(null, jarURL, classloader.getURLStreamHandler("jar")); + jarfile + = ((JarURLConnection) baseJarURL.openConnection()).getJarFile(); + + if (jarfile != null) + { + String fileName = baseURL.getFile(); + if (fileName != null) + { + File f = new File(fileName); + String libDirName = f.getCanonicalFile().getParent() + + File.separator + "GCJLIBS"; + File libDir = new File(libDirName); + if (libDir != null && (libDir.isDirectory())) + { + File soFile = new File (libDirName + + File.separator + f.getName() + + ".so"); + if (soFile != null && soFile.isFile()) + this.soURLLoader + = new SoURLLoader (classloader, soFile.toURL(), + baseURL); + } + } + + Manifest manifest; + Attributes attributes; + String classPathString; + + if ((manifest = jarfile.getManifest()) != null + && (attributes = manifest.getMainAttributes()) != null + && ((classPathString + = attributes.getValue(Attributes.Name.CLASS_PATH)) + != null)) + { + this.classPath = new Vector(); + + StringTokenizer st + = new StringTokenizer + (classPathString, + System.getProperty ("path.separator", ":")); + + while (st.hasMoreElements ()) + { + String e = st.nextToken (); + try + { + URL url = new URL(baseURL, e); + this.classPath.add(url); + } + catch (java.net.MalformedURLException xx) + { + // Give up + } + } + } + } + } catch (IOException ioe) { - /* ignored */ + /* ignored */ } this.baseJarURL = baseJarURL; this.jarfile = jarfile; } + Class getClass(String className) + { + if (soURLLoader != null) + return soURLLoader.getClass(className); + return null; + } + /** get resource with the name "name" in the jar url */ Resource getResource(String name) { @@ -337,6 +416,11 @@ public class URLClassLoader extends SecureClassLoader return null; } + public String toString () + { + return "jarfile " + jarfile.getName(); + } + Manifest getManifest() { try @@ -348,6 +432,11 @@ public class URLClassLoader extends SecureClassLoader return null; } } + + Vector getClassPath() + { + return classPath; + } } static final class JarURLResource extends Resource @@ -486,7 +575,12 @@ public class URLClassLoader extends SecureClassLoader SoURLLoader(URLClassLoader classloader, URL url) { - super(classloader, url); + this(classloader, url, url); + } + + SoURLLoader(URLClassLoader classloader, URL url, URL overrideURL) + { + super(classloader, url, overrideURL); helper = SharedLibHelper.findHelper(classloader, url.getFile(), noCertCodeSource); } @@ -577,6 +671,11 @@ public class URLClassLoader extends SecureClassLoader return (int) file.length(); } + public String toString () + { + return "file " +file.getAbsolutePath(); + } + public URL getURL() { try @@ -729,6 +828,7 @@ public class URLClassLoader extends SecureClassLoader */ protected void addURL(URL newUrl) { + urls.add(newUrl); addURLImpl(newUrl); } @@ -761,8 +861,21 @@ public class URLClassLoader extends SecureClassLoader urlloaders.put(newUrl, loader); } - urls.add(newUrl); - urlinfos.add(loader); + urlinfos.add(loader); + + Vector extraUrls = loader.getClassPath(); + if (extraUrls != null) + { + Iterator it = extraUrls.iterator(); + while (it.hasNext()) + { + URL url = (URL)it.next(); + URLLoader extraLoader = (URLLoader) urlloaders.get(url); + if (! urlinfos.contains (extraLoader)) + addURLImpl(url); + } + } + } } @@ -773,7 +886,7 @@ public class URLClassLoader extends SecureClassLoader private void addURLs(URL[] newUrls) { for (int i = 0; i < newUrls.length; i++) - addURLImpl(newUrls[i]); + addURL(newUrls[i]); } /** @@ -830,7 +943,7 @@ public class URLClassLoader extends SecureClassLoader { // Just try to find the resource by the (almost) same name String resourceName = className.replace('.', '/') + ".class"; - int max = urls.size(); + int max = urlinfos.size(); Resource resource = null; for (int i = 0; i < max && resource == null; i++) { @@ -939,7 +1052,7 @@ public class URLClassLoader extends SecureClassLoader */ private Resource findURLResource(String resourceName) { - int max = urls.size(); + int max = urlinfos.size(); for (int i = 0; i < max; i++) { URLLoader loader = (URLLoader) urlinfos.elementAt(i); @@ -1010,7 +1123,7 @@ public class URLClassLoader extends SecureClassLoader throws IOException { Vector resources = new Vector(); - int max = urls.size(); + int max = urlinfos.size(); for (int i = 0; i < max; i++) { URLLoader loader = (URLLoader) urlinfos.elementAt(i); diff --git a/libjava/jni.cc b/libjava/jni.cc index 6bfc4812d96..6138334ebaf 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -563,11 +563,12 @@ _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message) NULL); jclass *elts = elements (argtypes); - elts[0] = &StringClass; + elts[0] = &java::lang::String::class$; Constructor *cons = clazz->getConstructor (argtypes); - jobjectArray values = JvNewObjectArray (1, &StringClass, NULL); + jobjectArray values = JvNewObjectArray (1, &java::lang::String::class$, + NULL); jobject *velts = elements (values); velts[0] = JvNewStringUTF (message); @@ -1204,7 +1205,7 @@ _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz, // The field might be resolved or it might not be. It // is much simpler to always resolve it. - _Jv_ResolveField (field, loader); + _Jv_Linker::resolve_field (field, loader); if (_Jv_equalUtf8Consts (f_name, a_name) && field->getClass() == field_class) return field; diff --git a/libjava/link.cc b/libjava/link.cc new file mode 100644 index 00000000000..39ade1481a3 --- /dev/null +++ b/libjava/link.cc @@ -0,0 +1,1764 @@ +// link.cc - Code for linking and resolving classes and pool entries. + +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +/* Author: Kresten Krab Thorup <krab@gnu.org> */ + +#include <config.h> +#include <platform.h> + +#include <java-interp.h> + +#include <jvm.h> +#include <gcj/cni.h> +#include <string.h> +#include <java-cpool.h> +#include <execution.h> +#include <java/lang/Class.h> +#include <java/lang/String.h> +#include <java/lang/StringBuffer.h> +#include <java/lang/Thread.h> +#include <java/lang/InternalError.h> +#include <java/lang/VirtualMachineError.h> +#include <java/lang/VerifyError.h> +#include <java/lang/NoSuchFieldError.h> +#include <java/lang/NoSuchMethodError.h> +#include <java/lang/ClassFormatError.h> +#include <java/lang/IllegalAccessError.h> +#include <java/lang/AbstractMethodError.h> +#include <java/lang/NoClassDefFoundError.h> +#include <java/lang/IncompatibleClassChangeError.h> +#include <java/lang/VerifyError.h> +#include <java/lang/VMClassLoader.h> +#include <java/lang/reflect/Modifier.h> +#include <java/security/CodeSource.h> + +using namespace gcj; + +// When true, print debugging information about class loading. +bool gcj::verbose_class_flag; + +typedef unsigned int uaddr __attribute__ ((mode (pointer))); + +template<typename T> +struct aligner +{ + char c; + T field; +}; + +#define ALIGNOF(TYPE) (offsetof (aligner<TYPE>, field)) + +// This returns the alignment of a type as it would appear in a +// structure. This can be different from the alignment of the type +// itself. For instance on x86 double is 8-aligned but struct{double} +// is 4-aligned. +int +_Jv_Linker::get_alignment_from_class (jclass klass) +{ + if (klass == JvPrimClass (byte)) + return ALIGNOF (jbyte); + else if (klass == JvPrimClass (short)) + return ALIGNOF (jshort); + else if (klass == JvPrimClass (int)) + return ALIGNOF (jint); + else if (klass == JvPrimClass (long)) + return ALIGNOF (jlong); + else if (klass == JvPrimClass (boolean)) + return ALIGNOF (jboolean); + else if (klass == JvPrimClass (char)) + return ALIGNOF (jchar); + else if (klass == JvPrimClass (float)) + return ALIGNOF (jfloat); + else if (klass == JvPrimClass (double)) + return ALIGNOF (jdouble); + else + return ALIGNOF (jobject); +} + +void +_Jv_Linker::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader) +{ + if (! field->isResolved ()) + { + _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type; + field->type = _Jv_FindClassFromSignature (sig->chars(), loader); + field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG; + } +} + +_Jv_word +_Jv_Linker::resolve_pool_entry (jclass klass, int index) +{ + using namespace java::lang::reflect; + + _Jv_Constants *pool = &klass->constants; + + if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0) + return pool->data[index]; + + switch (pool->tags[index]) + { + case JV_CONSTANT_Class: + { + _Jv_Utf8Const *name = pool->data[index].utf8; + + jclass found; + if (name->first() == '[') + found = _Jv_FindClassFromSignature (name->chars(), + klass->loader); + else + found = _Jv_FindClass (name, klass->loader); + + if (! found) + throw new java::lang::NoClassDefFoundError (name->toString()); + + // Check accessibility, but first strip array types as + // _Jv_ClassNameSamePackage can't handle arrays. + jclass check; + for (check = found; + check && check->isArray(); + check = check->getComponentType()) + ; + if ((found->accflags & Modifier::PUBLIC) == Modifier::PUBLIC + || (_Jv_ClassNameSamePackage (check->name, + klass->name))) + { + pool->data[index].clazz = found; + pool->tags[index] |= JV_CONSTANT_ResolvedFlag; + } + else + { + java::lang::StringBuffer *sb = new java::lang::StringBuffer (); + sb->append(klass->getName()); + sb->append(JvNewStringLatin1(" can't access class ")); + sb->append(found->getName()); + throw new java::lang::IllegalAccessError(sb->toString()); + } + } + break; + + case JV_CONSTANT_String: + { + jstring str; + str = _Jv_NewStringUtf8Const (pool->data[index].utf8); + pool->data[index].o = str; + pool->tags[index] |= JV_CONSTANT_ResolvedFlag; + } + break; + + case JV_CONSTANT_Fieldref: + { + _Jv_ushort class_index, name_and_type_index; + _Jv_loadIndexes (&pool->data[index], + class_index, + name_and_type_index); + jclass owner = (resolve_pool_entry (klass, class_index)).clazz; + + if (owner != klass) + _Jv_InitClass (owner); + + _Jv_ushort name_index, type_index; + _Jv_loadIndexes (&pool->data[name_and_type_index], + name_index, + type_index); + + _Jv_Utf8Const *field_name = pool->data[name_index].utf8; + _Jv_Utf8Const *field_type_name = pool->data[type_index].utf8; + + // FIXME: The implementation of this function + // (_Jv_FindClassFromSignature) will generate an instance of + // _Jv_Utf8Const for each call if the field type is a class name + // (Lxx.yy.Z;). This may be too expensive to do for each and + // every fieldref being resolved. For now, we fix the problem by + // only doing it when we have a loader different from the class + // declaring the field. + + jclass field_type = 0; + + if (owner->loader != klass->loader) + field_type = _Jv_FindClassFromSignature (field_type_name->chars(), + klass->loader); + + _Jv_Field* the_field = 0; + + for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ()) + { + for (int i = 0; i < cls->field_count; i++) + { + _Jv_Field *field = &cls->fields[i]; + if (! _Jv_equalUtf8Consts (field->name, field_name)) + continue; + + if (_Jv_CheckAccess (klass, cls, field->flags)) + { + // Resolve the field using the class' own loader if + // necessary. + + if (!field->isResolved ()) + resolve_field (field, cls->loader); + + if (field_type != 0 && field->type != field_type) + throw new java::lang::LinkageError + (JvNewStringLatin1 + ("field type mismatch with different loaders")); + + the_field = field; + goto end_of_field_search; + } + else + { + java::lang::StringBuffer *sb + = new java::lang::StringBuffer (); + sb->append(klass->getName()); + sb->append(JvNewStringLatin1(": ")); + sb->append(cls->getName()); + sb->append(JvNewStringLatin1(".")); + sb->append(_Jv_NewStringUtf8Const (field_name)); + throw new java::lang::IllegalAccessError(sb->toString()); + } + } + } + + end_of_field_search: + if (the_field == 0) + { + java::lang::StringBuffer *sb = new java::lang::StringBuffer(); + sb->append(JvNewStringLatin1("field ")); + sb->append(owner->getName()); + sb->append(JvNewStringLatin1(".")); + sb->append(_Jv_NewStringUTF(field_name->chars())); + sb->append(JvNewStringLatin1(" was not found.")); + throw + new java::lang::IncompatibleClassChangeError (sb->toString()); + } + + pool->data[index].field = the_field; + pool->tags[index] |= JV_CONSTANT_ResolvedFlag; + } + break; + + case JV_CONSTANT_Methodref: + case JV_CONSTANT_InterfaceMethodref: + { + _Jv_ushort class_index, name_and_type_index; + _Jv_loadIndexes (&pool->data[index], + class_index, + name_and_type_index); + jclass owner = (resolve_pool_entry (klass, class_index)).clazz; + + if (owner != klass) + _Jv_InitClass (owner); + + _Jv_ushort name_index, type_index; + _Jv_loadIndexes (&pool->data[name_and_type_index], + name_index, + type_index); + + _Jv_Utf8Const *method_name = pool->data[name_index].utf8; + _Jv_Utf8Const *method_signature = pool->data[type_index].utf8; + + _Jv_Method *the_method = 0; + jclass found_class = 0; + + // We're going to cache a pointer to the _Jv_Method object + // when we find it. So, to ensure this doesn't get moved from + // beneath us, we first put all the needed Miranda methods + // into the target class. + wait_for_state (klass, JV_STATE_LOADED); + + // First search the class itself. + the_method = search_method_in_class (owner, klass, + method_name, method_signature); + + if (the_method != 0) + { + found_class = owner; + goto end_of_method_search; + } + + // If we are resolving an interface method, search the + // interface's superinterfaces (A superinterface is not an + // interface's superclass - a superinterface is implemented by + // the interface). + if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref) + { + _Jv_ifaces ifaces; + ifaces.count = 0; + ifaces.len = 4; + ifaces.list = (jclass *) _Jv_Malloc (ifaces.len + * sizeof (jclass *)); + + get_interfaces (owner, &ifaces); + + for (int i = 0; i < ifaces.count; i++) + { + jclass cls = ifaces.list[i]; + the_method = search_method_in_class (cls, klass, method_name, + method_signature); + if (the_method != 0) + { + found_class = cls; + break; + } + } + + _Jv_Free (ifaces.list); + + if (the_method != 0) + goto end_of_method_search; + } + + // Finally, search superclasses. + for (jclass cls = owner->getSuperclass (); cls != 0; + cls = cls->getSuperclass ()) + { + the_method = search_method_in_class (cls, klass, method_name, + method_signature); + if (the_method != 0) + { + found_class = cls; + break; + } + } + + end_of_method_search: + + // FIXME: if (cls->loader != klass->loader), then we + // must actually check that the types of arguments + // correspond. That is, for each argument type, and + // the return type, doing _Jv_FindClassFromSignature + // with either loader should produce the same result, + // i.e., exactly the same jclass object. JVMS 5.4.3.3 + + if (the_method == 0) + { + java::lang::StringBuffer *sb = new java::lang::StringBuffer(); + sb->append(JvNewStringLatin1("method ")); + sb->append(owner->getName()); + sb->append(JvNewStringLatin1(".")); + sb->append(_Jv_NewStringUTF(method_name->chars())); + sb->append(JvNewStringLatin1(" with signature ")); + sb->append(_Jv_NewStringUTF(method_signature->chars())); + sb->append(JvNewStringLatin1(" was not found.")); + 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); + pool->tags[index] |= JV_CONSTANT_ResolvedFlag; + } + break; + } + return pool->data[index]; +} + +// This function is used to lazily locate superclasses and +// superinterfaces. This must be called with the class lock held. +void +_Jv_Linker::resolve_class_ref (jclass klass, jclass *classref) +{ + jclass ret = *classref; + + // If superclass looks like a constant pool entry, resolve it now. + if (ret && (uaddr) ret < (uaddr) klass->constants.size) + { + if (klass->state < JV_STATE_LINKED) + { + _Jv_Utf8Const *name = klass->constants.data[(uaddr) *classref].utf8; + ret = _Jv_FindClass (name, klass->loader); + if (! ret) + { + throw new java::lang::NoClassDefFoundError (name->toString()); + } + } + else + ret = klass->constants.data[(uaddr) classref].clazz; + *classref = ret; + } +} + +// Find a method declared in the cls that is referenced from klass and +// perform access checks. +_Jv_Method * +_Jv_Linker::search_method_in_class (jclass cls, jclass klass, + _Jv_Utf8Const *method_name, + _Jv_Utf8Const *method_signature) +{ + using namespace java::lang::reflect; + + for (int i = 0; i < cls->method_count; i++) + { + _Jv_Method *method = &cls->methods[i]; + if ( (!_Jv_equalUtf8Consts (method->name, + method_name)) + || (!_Jv_equalUtf8Consts (method->signature, + method_signature))) + continue; + + if (_Jv_CheckAccess (klass, cls, method->accflags)) + return method; + else + { + java::lang::StringBuffer *sb = new java::lang::StringBuffer(); + sb->append(klass->getName()); + sb->append(JvNewStringLatin1(": ")); + sb->append(cls->getName()); + sb->append(JvNewStringLatin1(".")); + sb->append(_Jv_NewStringUTF(method_name->chars())); + sb->append(_Jv_NewStringUTF(method_signature->chars())); + throw new java::lang::IllegalAccessError (sb->toString()); + } + } + return 0; +} + + +#define INITIAL_IOFFSETS_LEN 4 +#define INITIAL_IFACES_LEN 4 + +static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} }; + +// Generate tables for constant-time assignment testing and interface +// method lookup. This implements the technique described by Per Bothner +// <per@bothner.com> on the java-discuss mailing list on 1999-09-02: +// http://gcc.gnu.org/ml/java/1999-q3/msg00377.html +void +_Jv_Linker::prepare_constant_time_tables (jclass klass) +{ + if (klass->isPrimitive () || klass->isInterface ()) + return; + + // Short-circuit in case we've been called already. + if ((klass->idt != NULL) || klass->depth != 0) + return; + + // Calculate the class depth and ancestor table. The depth of a class + // is how many "extends" it is removed from Object. Thus the depth of + // java.lang.Object is 0, but the depth of java.io.FilterOutputStream + // is 2. Depth is defined for all regular and array classes, but not + // interfaces or primitive types. + + jclass klass0 = klass; + jboolean has_interfaces = 0; + while (klass0 != &java::lang::Object::class$) + { + has_interfaces += klass0->interface_count; + klass0 = klass0->superclass; + klass->depth++; + } + + // We do class member testing in constant time by using a small table + // of all the ancestor classes within each class. The first element is + // 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. + + // FIXME: _Jv_AllocBytes + klass->ancestors = (jclass *) _Jv_Malloc (klass->depth + * sizeof (jclass)); + klass0 = klass; + for (int index = 0; index < klass->depth; index++) + { + klass->ancestors[index] = klass0; + klass0 = klass0->superclass; + } + + if ((klass->accflags & java::lang::reflect::Modifier::ABSTRACT) != 0) + return; + + // Optimization: If class implements no interfaces, use a common + // predefined interface table. + if (!has_interfaces) + { + klass->idt = &null_idt; + return; + } + + // FIXME: _Jv_AllocBytes + klass->idt = + (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); + + _Jv_ifaces ifaces; + ifaces.count = 0; + ifaces.len = INITIAL_IFACES_LEN; + ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *)); + + int itable_size = get_interfaces (klass, &ifaces); + + 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; + + jshort *itable_offsets = + (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort)); + + generate_itable (klass, &ifaces, itable_offsets); + + jshort cls_iindex = find_iindex (ifaces.list, itable_offsets, + ifaces.count); + + for (int i = 0; i < ifaces.count; i++) + { + ifaces.list[i]->idt->iface.ioffsets[cls_iindex] = + itable_offsets[i]; + } + + klass->idt->cls.iindex = cls_iindex; + + _Jv_Free (ifaces.list); + _Jv_Free (itable_offsets); + } + else + { + klass->idt->cls.iindex = SHRT_MAX; + } +} + +// Return index of item in list, or -1 if item is not present. +inline jshort +_Jv_Linker::indexof (void *item, void **list, jshort list_len) +{ + for (int i=0; i < list_len; i++) + { + if (list[i] == item) + return i; + } + return -1; +} + +// Find all unique interfaces directly or indirectly implemented by klass. +// Returns the size of the interface dispatch table (itable) for klass, which +// is the number of unique interfaces plus the total number of methods that +// those interfaces declare. May extend ifaces if required. +jshort +_Jv_Linker::get_interfaces (jclass klass, _Jv_ifaces *ifaces) +{ + jshort result = 0; + + for (int i = 0; i < klass->interface_count; i++) + { + jclass iface = klass->interfaces[i]; + + /* Make sure interface is linked. */ + wait_for_state(iface, JV_STATE_LINKED); + + if (indexof (iface, (void **) ifaces->list, ifaces->count) == -1) + { + if (ifaces->count + 1 >= ifaces->len) + { + /* Resize ifaces list */ + ifaces->len = ifaces->len * 2; + ifaces->list + = (jclass *) _Jv_Realloc (ifaces->list, + ifaces->len * sizeof(jclass)); + } + ifaces->list[ifaces->count] = iface; + ifaces->count++; + + result += get_interfaces (klass->interfaces[i], ifaces); + } + } + + if (klass->isInterface()) + result += klass->method_count + 1; + else if (klass->superclass) + result += get_interfaces (klass->superclass, ifaces); + return result; +} + +// Fill out itable in klass, resolving method declarations in each ifaces. +// itable_offsets is filled out with the position of each iface in itable, +// such that itable[itable_offsets[n]] == ifaces.list[n]. +void +_Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, + jshort *itable_offsets) +{ + void **itable = klass->idt->cls.itable; + jshort itable_pos = 0; + + for (int i = 0; i < ifaces->count; i++) + { + jclass iface = ifaces->list[i]; + 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) + { + // 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)); + ioffsets[0] = INITIAL_IOFFSETS_LEN; + for (int i = 1; i < INITIAL_IOFFSETS_LEN; i++) + ioffsets[i] = -1; + + iface->idt->iface.ioffsets = ioffsets; + } + } +} + +// Format method name for use in error messages. +jstring +_Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name) +{ + jstring r = klass->name->toString(); + r = r->concat (JvNewStringUTF (".")); + r = r->concat (name->toString()); + return r; +} + +void +_Jv_ThrowNoSuchMethodError () +{ + throw new java::lang::NoSuchMethodError; +} + +// Each superinterface of a class (i.e. each interface that the class +// directly or indirectly implements) has a corresponding "Partial +// Interface Dispatch Table" whose size is (number of methods + 1) words. +// The first word is a pointer to the interface (i.e. the java.lang.Class +// instance for that interface). The remaining words are pointers to the +// actual methods that implement the methods declared in the interface, +// in order of declaration. +// +// Append partial interface dispatch table for "iface" to "itable", at +// position itable_pos. +// 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) +{ + using namespace java::lang::reflect; + + itable[pos++] = (void *) iface; + _Jv_Method *meth; + + for (int j=0; j < iface->method_count; j++) + { + meth = NULL; + for (jclass cl = klass; cl; cl = cl->getSuperclass()) + { + meth = _Jv_GetMethodLocal (cl, iface->methods[j].name, + iface->methods[j].signature); + + if (meth) + break; + } + + if (meth && (meth->name->first() == '<')) + { + // leave a placeholder in the itable for hidden init methods. + itable[pos] = NULL; + } + else if (meth) + { + if ((meth->accflags & Modifier::STATIC) != 0) + throw new java::lang::IncompatibleClassChangeError + (_Jv_GetMethodString (klass, meth->name)); + if ((meth->accflags & Modifier::ABSTRACT) != 0) + throw new java::lang::AbstractMethodError + (_Jv_GetMethodString (klass, meth->name)); + if ((meth->accflags & Modifier::PUBLIC) == 0) + throw new java::lang::IllegalAccessError + (_Jv_GetMethodString (klass, meth->name)); + + itable[pos] = meth->ncode; + } + else + { + // The method doesn't exist in klass. Binary compatibility rules + // permit this, so we delay the error until runtime using a pointer + // to a method which throws an exception. + itable[pos] = (void *) _Jv_ThrowNoSuchMethodError; + } + pos++; + } + + return pos; +} + +static _Jv_Mutex_t iindex_mutex; +static bool iindex_mutex_initialized = false; + +// We need to find the correct offset in the Class Interface Dispatch +// Table for a given interface. Once we have that, invoking an interface +// method just requires combining the Method's index in the interface +// (known at compile time) to get the correct method. Doing a type test +// (cast or instanceof) is the same problem: Once we have a possible Partial +// 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. +// +// Calculate and return iindex for a new class. +// ifaces is a vector of num interfaces that the class implements. +// offsets[j] is the offset in the interface dispatch table for the +// interface corresponding to ifaces[j]. +// May extend the interface ioffsets if required. +jshort +_Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) +{ + int i; + int j; + + // Acquire a global lock to prevent itable corruption in case of multiple + // classes that implement an intersecting set of interfaces being linked + // simultaneously. We can assume that the mutex will be initialized + // single-threaded. + if (! iindex_mutex_initialized) + { + _Jv_MutexInit (&iindex_mutex); + iindex_mutex_initialized = true; + } + + _Jv_MutexLock (&iindex_mutex); + + for (i=1;; i++) /* each potential position in ioffsets */ + { + for (j=0;; j++) /* each iface */ + { + if (j >= num) + goto found; + if (i >= ifaces[j]->idt->iface.ioffsets[0]) + continue; + int ioffset = ifaces[j]->idt->iface.ioffsets[i]; + /* We can potentially share this position with another class. */ + if (ioffset >= 0 && ioffset != offsets[j]) + break; /* Nope. Try next i. */ + } + } + found: + for (j = 0; j < num; j++) + { + int len = ifaces[j]->idt->iface.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)); + memcpy (&new_ioffsets[1], &old_ioffsets[1], + (len - 1) * sizeof (jshort)); + new_ioffsets[0] = newlen; + + while (len < newlen) + new_ioffsets[len++] = -1; + + ifaces[j]->idt->iface.ioffsets = new_ioffsets; + } + ifaces[j]->idt->iface.ioffsets[i] = offsets[j]; + } + + _Jv_MutexUnlock (&iindex_mutex); + + return i; +} + + +// Functions for indirect dispatch (symbolic virtual binding) support. + +// There are three tables, atable otable and itable. atable is an +// array of addresses, and otable is an array of offsets, and these +// are used for static and virtual members respectively. itable is an +// array of pairs {address, index} where each address is a pointer to +// an interface. + +// {a,o,i}table_syms is an array of _Jv_MethodSymbols. Each such +// symbol is a tuple of {classname, member name, signature}. + +// Set this to true to enable debugging of indirect dispatch tables/linking. +static bool debug_link = false; + +// link_symbol_table() scans these two arrays and fills in the +// corresponding atable and otable with the addresses of static +// members and the offsets of virtual members. + +// The offset (in bytes) for each resolved method or field is placed +// at the corresponding position in the virtual method offset table +// (klass->otable). + +// The same otable and atable may be shared by many classes. + +// This must be called while holding the class lock. + +void +_Jv_Linker::link_symbol_table (jclass klass) +{ + int index = 0; + _Jv_MethodSymbol sym; + if (klass->otable == NULL + || klass->otable->state != 0) + goto atable; + + klass->otable->state = 1; + + if (debug_link) + fprintf (stderr, "Fixing up otable in %s:\n", klass->name->chars()); + for (index = 0; + (sym = klass->otable_syms[index]).class_name != NULL; + ++index) + { + jclass target_class = _Jv_FindClass (sym.class_name, klass->loader); + _Jv_Method *meth = NULL; + + _Jv_Utf8Const *signature = sym.signature; + + { + static char *bounce = (char *)_Jv_ThrowNoSuchMethodError; + ptrdiff_t offset = (char *)(klass->vtable) - bounce; + klass->otable->offsets[index] = offset; + } + + if (target_class == NULL) + throw new java::lang::NoClassDefFoundError + (_Jv_NewStringUTF (sym.class_name->chars())); + + // We're looking for a field or a method, and we can tell + // which is needed by looking at the signature. + if (signature->first() == '(' && signature->len() >= 2) + { + // Looks like someone is trying to invoke an interface method + if (target_class->isInterface()) + { + using namespace java::lang; + StringBuffer *sb = new StringBuffer(); + sb->append(JvNewStringLatin1("found interface ")); + sb->append(target_class->getName()); + sb->append(JvNewStringLatin1(" when searching for a class")); + throw new VerifyError(sb->toString()); + } + + // 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 + // it out now. + wait_for_state(target_class, JV_STATE_PREPARED); + + meth = _Jv_LookupDeclaredMethod(target_class, sym.name, + sym.signature); + + if (meth != NULL) + { + int offset = _Jv_VTable::idx_to_offset (meth->index); + if (offset == -1) + JvFail ("Bad method index"); + JvAssert (meth->index < target_class->vtable_method_count); + klass->otable->offsets[index] = offset; + } + if (debug_link) + fprintf (stderr, " offsets[%d] = %d (class %s@%p : %s(%s))\n", + (int)index, + (int)klass->otable->offsets[index], + (const char*)target_class->name->chars(), + target_class, + (const char*)sym.name->chars(), + (const char*)signature->chars()); + continue; + } + + // try fields + { + _Jv_Field *the_field = NULL; + + wait_for_state(target_class, JV_STATE_PREPARED); + for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ()) + { + for (int i = 0; i < cls->field_count; i++) + { + _Jv_Field *field = &cls->fields[i]; + if (! _Jv_equalUtf8Consts (field->name, sym.name)) + continue; + + // FIXME: What access checks should we perform here? +// if (_Jv_CheckAccess (klass, cls, field->flags)) +// { + + if (!field->isResolved ()) + resolve_field (field, cls->loader); + +// if (field_type != 0 && field->type != field_type) +// throw new java::lang::LinkageError +// (JvNewStringLatin1 +// ("field type mismatch with different loaders")); + + the_field = field; + if (debug_link) + fprintf (stderr, " offsets[%d] = %d (class %s@%p : %s)\n", + (int)index, + (int)field->u.boffset, + (const char*)cls->name->chars(), + cls, + (const char*)field->name->chars()); + goto end_of_field_search; + } + } + end_of_field_search: + if (the_field != NULL) + { + if ((the_field->flags & java::lang::reflect::Modifier::STATIC)) + throw new java::lang::IncompatibleClassChangeError; + else + klass->otable->offsets[index] = the_field->u.boffset; + } + else + { + throw new java::lang::NoSuchFieldError + (_Jv_NewStringUtf8Const (sym.name)); + } + } + } + + atable: + if (klass->atable == NULL || klass->atable->state != 0) + goto itable; + + klass->atable->state = 1; + + for (index = 0; + (sym = klass->atable_syms[index]).class_name != NULL; + ++index) + { + jclass target_class = _Jv_FindClass (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 (target_class == NULL) + throw new java::lang::NoClassDefFoundError + (_Jv_NewStringUTF (sym.class_name->chars())); + + // 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) + { + // 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 + // it out now. + wait_for_state (target_class, JV_STATE_PREPARED); + + // Interface methods cannot have bodies. + if (target_class->isInterface()) + { + using namespace java::lang; + StringBuffer *sb = new StringBuffer(); + sb->append(JvNewStringLatin1("class ")); + sb->append(target_class->getName()); + sb->append(JvNewStringLatin1(" is an interface: " + "class expected")); + throw new VerifyError(sb->toString()); + } + + meth = _Jv_LookupDeclaredMethod(target_class, sym.name, + sym.signature); + + if (meth != NULL) + { + if (meth->ncode) // Maybe abstract? + { + klass->atable->addresses[index] = meth->ncode; + if (debug_link) + fprintf (stderr, " addresses[%d] = %p (class %s@%p : %s(%s))\n", + index, + &klass->atable->addresses[index], + (const char*)target_class->name->chars(), + klass, + (const char*)sym.name->chars(), + (const char*)signature->chars()); + } + } + else + klass->atable->addresses[index] + = (void *)_Jv_ThrowNoSuchMethodError; + + continue; + } + + // try fields + { + _Jv_Field *the_field = NULL; + + wait_for_state(target_class, JV_STATE_PREPARED); + for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ()) + { + for (int i = 0; i < cls->field_count; i++) + { + _Jv_Field *field = &cls->fields[i]; + if (! _Jv_equalUtf8Consts (field->name, sym.name)) + continue; + + // FIXME: What access checks should we perform here? +// if (_Jv_CheckAccess (klass, cls, field->flags)) +// { + + if (!field->isResolved ()) + resolve_field (field, cls->loader); + +// if (field_type != 0 && field->type != field_type) +// throw new java::lang::LinkageError +// (JvNewStringLatin1 +// ("field type mismatch with different loaders")); + + the_field = field; + goto end_of_static_field_search; + } + } + end_of_static_field_search: + if (the_field != NULL) + { + if ((the_field->flags & java::lang::reflect::Modifier::STATIC)) + klass->atable->addresses[index] = the_field->u.addr; + else + throw new java::lang::IncompatibleClassChangeError; + } + else + { + throw new java::lang::NoSuchFieldError + (_Jv_NewStringUtf8Const (sym.name)); + } + } + } + + itable: + if (klass->itable == NULL + || klass->itable->state != 0) + return; + + klass->itable->state = 1; + + for (index = 0; + (sym = klass->itable_syms[index]).class_name != NULL; + ++index) + { + jclass target_class = _Jv_FindClass (sym.class_name, klass->loader); + _Jv_Utf8Const *signature = sym.signature; + + jclass cls; + int i; + + wait_for_state(target_class, JV_STATE_LOADED); + bool found = _Jv_getInterfaceMethod (target_class, cls, i, + sym.name, sym.signature); + + if (found) + { + klass->itable->addresses[index * 2] = cls; + klass->itable->addresses[index * 2 + 1] = (void *)(intptr_t) i; + if (debug_link) + { + fprintf (stderr, " interfaces[%d] = %p (interface %s@%p : %s(%s))\n", + index, + klass->itable->addresses[index * 2], + (const char*)cls->name->chars(), + cls, + (const char*)sym.name->chars(), + (const char*)signature->chars()); + fprintf (stderr, " [%d] = offset %d\n", + index + 1, + (int)(intptr_t)klass->itable->addresses[index * 2 + 1]); + } + + } + else + throw new java::lang::IncompatibleClassChangeError; + } + +} + +// For each catch_record in the list of caught classes, fill in the +// address field. +void +_Jv_Linker::link_exception_table (jclass self) +{ + struct _Jv_CatchClass *catch_record = self->catch_classes; + if (!catch_record || catch_record->classname) + return; + catch_record++; + while (catch_record->classname) + { + try + { + jclass target_class + = _Jv_FindClass (catch_record->classname, + self->getClassLoaderInternal ()); + *catch_record->address = target_class; + } + catch (::java::lang::Throwable *t) + { + // FIXME: We need to do something better here. + *catch_record->address = 0; + } + catch_record++; + } + self->catch_classes->classname = (_Jv_Utf8Const *)-1; +} + +// This is put in empty vtable slots. +static void +_Jv_abstractMethodError (void) +{ + throw new java::lang::AbstractMethodError(); +} + +// Set itable method indexes for members of interface IFACE. +void +_Jv_Linker::layout_interface_methods (jclass iface) +{ + if (! iface->isInterface()) + return; + + // itable indexes start at 1. + // FIXME: Static initalizers currently get a NULL placeholder entry in the + // itable so they are also assigned an index here. + for (int i = 0; i < iface->method_count; i++) + iface->methods[i].index = i + 1; +} + +// Prepare virtual method declarations in KLASS, and any superclasses +// as required, by determining their vtable index, setting +// method->index, and finally setting the class's vtable_method_count. +// Must be called with the lock for KLASS held. +void +_Jv_Linker::layout_vtable_methods (jclass klass) +{ + if (klass->vtable != NULL || klass->isInterface() + || klass->vtable_method_count != -1) + return; + + jclass superclass = klass->getSuperclass(); + + if (superclass != NULL && superclass->vtable_method_count == -1) + { + JvSynchronize sync (superclass); + layout_vtable_methods (superclass); + } + + int index = (superclass == NULL ? 0 : superclass->vtable_method_count); + + for (int i = 0; i < klass->method_count; ++i) + { + _Jv_Method *meth = &klass->methods[i]; + _Jv_Method *super_meth = NULL; + + if (! _Jv_isVirtualMethod (meth)) + continue; + + if (superclass != NULL) + { + jclass declarer; + super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, + meth->signature, &declarer); + // See if this method actually overrides the other method + // we've found. + if (super_meth) + { + if (! _Jv_isVirtualMethod (super_meth) + || ! _Jv_CheckAccess (klass, declarer, + super_meth->accflags)) + super_meth = NULL; + else if ((super_meth->accflags + & java::lang::reflect::Modifier::FINAL) != 0) + { + using namespace java::lang; + StringBuffer *sb = new StringBuffer(); + sb->append(JvNewStringLatin1("method ")); + sb->append(_Jv_GetMethodString(klass, meth->name)); + sb->append(JvNewStringLatin1(" overrides final method ")); + sb->append(_Jv_GetMethodString(declarer, super_meth->name)); + throw new VerifyError(sb->toString()); + } + } + } + + if (super_meth) + meth->index = super_meth->index; + else + meth->index = index++; + } + + klass->vtable_method_count = index; +} + +// Set entries in VTABLE for virtual methods declared in KLASS. +void +_Jv_Linker::set_vtable_entries (jclass klass, _Jv_VTable *vtable) +{ + for (int i = klass->method_count - 1; i >= 0; i--) + { + using namespace java::lang::reflect; + + _Jv_Method *meth = &klass->methods[i]; + if (meth->index == (_Jv_ushort) -1) + continue; + if ((meth->accflags & Modifier::ABSTRACT)) + vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError); + else + vtable->set_method(meth->index, meth->ncode); + } +} + +// Allocate and lay out the virtual method table for KLASS. This will +// also cause vtables to be generated for any non-abstract +// superclasses, and virtual method layout to occur for any abstract +// superclasses. Must be called with monitor lock for KLASS held. +void +_Jv_Linker::make_vtable (jclass klass) +{ + using namespace java::lang::reflect; + + // If the vtable exists, or for interface classes, do nothing. All + // other classes, including abstract classes, need a vtable. + if (klass->vtable != NULL || klass->isInterface()) + return; + + // Ensure all the `ncode' entries are set. + klass->engine->create_ncode(klass); + + // Class must be laid out before we can create a vtable. + if (klass->vtable_method_count == -1) + layout_vtable_methods (klass); + + // Allocate the new vtable. + _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count); + klass->vtable = vtable; + + // Copy the vtable of the closest superclass. + jclass superclass = klass->superclass; + { + JvSynchronize sync (superclass); + make_vtable (superclass); + } + for (int i = 0; i < superclass->vtable_method_count; ++i) + vtable->set_method (i, superclass->vtable->get_method (i)); + + // Set the class pointer and GC descriptor. + vtable->clas = klass; + vtable->gc_descr = _Jv_BuildGCDescr (klass); + + // For each virtual declared in klass, set new vtable entry or + // override an old one. + set_vtable_entries (klass, vtable); + + // It is an error to have an abstract method in a concrete class. + if (! (klass->accflags & Modifier::ABSTRACT)) + { + for (int i = 0; i < klass->vtable_method_count; ++i) + if (vtable->get_method(i) == (void *) &_Jv_abstractMethodError) + { + using namespace java::lang; + while (klass != NULL) + { + for (int j = 0; j < klass->method_count; ++j) + { + if (klass->methods[j].index == i) + { + StringBuffer *buf = new StringBuffer (); + buf->append (_Jv_NewStringUtf8Const (klass->methods[j].name)); + buf->append ((jchar) ' '); + buf->append (_Jv_NewStringUtf8Const (klass->methods[j].signature)); + throw new AbstractMethodError (buf->toString ()); + } + } + klass = klass->getSuperclass (); + } + // Couldn't find the name, which is weird. + // But we still must throw the error. + throw new AbstractMethodError (); + } + } +} + +// Lay out the class, allocating space for static fields and computing +// offsets of instance fields. The class lock must be held by the +// caller. +void +_Jv_Linker::ensure_fields_laid_out (jclass klass) +{ + if (klass->size_in_bytes != -1) + return; + + // Compute the alignment for this type by searching through the + // superclasses and finding the maximum required alignment. We + // could consider caching this in the Class. + int max_align = __alignof__ (java::lang::Object); + jclass super = klass->getSuperclass(); + while (super != NULL) + { + // Ensure that our super has its super installed before + // recursing. + wait_for_state(super, JV_STATE_LOADING); + ensure_fields_laid_out(super); + int num = JvNumInstanceFields (super); + _Jv_Field *field = JvGetFirstInstanceField (super); + while (num > 0) + { + int field_align = get_alignment_from_class (field->type); + if (field_align > max_align) + max_align = field_align; + ++field; + --num; + } + super = super->getSuperclass(); + } + + int instance_size; + int static_size = 0; + + // Although java.lang.Object is never interpreted, an interface can + // have a null superclass. Note that we have to lay out an + // interface because it might have static fields. + if (klass->superclass) + instance_size = klass->superclass->size(); + else + instance_size = java::lang::Object::class$.size(); + + for (int i = 0; i < klass->field_count; i++) + { + int field_size; + int field_align; + + _Jv_Field *field = &klass->fields[i]; + + if (! field->isRef ()) + { + // 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); + } + else + { + field_size = sizeof (jobject); + field_align = __alignof__ (jobject); + } + + field->bsize = field_size; + + if ((field->flags & java::lang::reflect::Modifier::STATIC)) + { + if (field->u.addr == NULL) + { + // This computes an offset into a region we'll allocate + // shortly, and then add this offset to the start + // address. + static_size = ROUND (static_size, field_align); + field->u.boffset = static_size; + static_size += field_size; + } + } + else + { + instance_size = ROUND (instance_size, field_align); + field->u.boffset = instance_size; + instance_size += field_size; + if (field_align > max_align) + max_align = field_align; + } + } + + if (static_size != 0) + klass->engine->allocate_static_fields (klass, static_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 + // with our current ABI. + instance_size = ROUND (instance_size, max_align); + klass->size_in_bytes = instance_size; +} + +// This takes the class to state JV_STATE_LINKED. The class lock must +// be held when calling this. +void +_Jv_Linker::ensure_class_linked (jclass klass) +{ + if (klass->state >= JV_STATE_LINKED) + return; + + int state = klass->state; + try + { + // Short-circuit, so that mutually dependent classes are ok. + klass->state = JV_STATE_LINKED; + + _Jv_Constants *pool = &klass->constants; + + // Compiled classes require that their class constants be + // resolved here. However, interpreted classes need their + // constants to be resolved lazily. If we resolve an + // interpreted class' constants eagerly, we can end up with + // spurious IllegalAccessErrors when the constant pool contains + // a reference to a class we can't access. This can validly + // occur in an obscure case involving the InnerClasses + // attribute. + if (! _Jv_IsInterpretedClass (klass)) + { + // Resolve class constants first, since other constant pool + // entries may rely on these. + for (int index = 1; index < pool->size; ++index) + { + if (pool->tags[index] == JV_CONSTANT_Class) + resolve_pool_entry (klass, index); + } + } + +#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) + { + if (pool->tags[index] == JV_CONSTANT_String) + { + jstring str; + + str = _Jv_NewStringUtf8Const (pool->data[index].utf8); + pool->data[index].o = str; + pool->tags[index] |= JV_CONSTANT_ResolvedFlag; + } + } + + if (klass->engine->need_resolve_string_fields()) + { + jfieldID f = JvGetFirstStaticField (klass); + for (int n = JvNumStaticFields (klass); n > 0; --n) + { + 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$ + && (mod & java::lang::reflect::Modifier::STATIC) != 0) + { + jstring *strp = (jstring *) f->u.addr; + if (*strp) + *strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp); + } + f = f->getNextField (); + } + } + + klass->notifyAll (); + + _Jv_PushClass (klass); + } + catch (java::lang::Throwable *t) + { + klass->state = state; + throw t; + } +} + +// This ensures that symbolic superclass and superinterface references +// are resolved for the indicated class. This must be called with the +// class lock held. +void +_Jv_Linker::ensure_supers_installed (jclass klass) +{ + resolve_class_ref (klass, &klass->superclass); + // An interface won't have a superclass. + if (klass->superclass) + wait_for_state (klass->superclass, JV_STATE_LOADING); + + for (int i = 0; i < klass->interface_count; ++i) + { + resolve_class_ref (klass, &klass->interfaces[i]); + wait_for_state (klass->interfaces[i], JV_STATE_LOADING); + } +} + +// This adds missing `Miranda methods' to a class. +void +_Jv_Linker::add_miranda_methods (jclass base, jclass iface_class) +{ + // Note that at this point, all our supers, and the supers of all + // our superclasses and superinterfaces, will have been installed. + + for (int i = 0; i < iface_class->interface_count; ++i) + { + jclass interface = iface_class->interfaces[i]; + + for (int j = 0; j < interface->method_count; ++j) + { + _Jv_Method *meth = &interface->methods[j]; + // Don't bother with <clinit>. + if (meth->name->first() == '<') + continue; + _Jv_Method *new_meth = _Jv_LookupDeclaredMethod (base, meth->name, + meth->signature); + if (! new_meth) + { + // We assume that such methods are very unlikely, so we + // just reallocate the method array each time one is + // found. This greatly simplifies the searching -- + // otherwise we have to make sure that each such method + // 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); + memcpy (new_m, base->methods, + sizeof (_Jv_Method) * base->method_count); + + // Add new method. + new_m[base->method_count] = *meth; + new_m[base->method_count].index = (_Jv_ushort) -1; + new_m[base->method_count].accflags + |= java::lang::reflect::Modifier::INVISIBLE; + + base->methods = new_m; + base->method_count = new_count; + } + } + + wait_for_state (interface, JV_STATE_LOADED); + add_miranda_methods (base, interface); + } +} + +// This ensures that the class' method table is "complete". This must +// be called with the class lock held. +void +_Jv_Linker::ensure_method_table_complete (jclass klass) +{ + if (klass->vtable != NULL || klass->isInterface()) + return; + + // We need our superclass to have its own Miranda methods installed. + wait_for_state (klass->getSuperclass (), JV_STATE_LOADED); + + // A class might have so-called "Miranda methods". This is a method + // that is declared in an interface and not re-declared in an + // abstract class. Some compilers don't emit declarations for such + // methods in the class; this will give us problems since we expect + // a declaration for any method requiring a vtable entry. We handle + // this here by searching for such methods and constructing new + // internal declarations for them. Note that we do this + // unconditionally, and not just for abstract classes, to correctly + // account for cases where a class is modified to be concrete and + // still incorrectly inherits an abstract method. + int pre_count = klass->method_count; + add_miranda_methods (klass, klass); + + // Let the execution engine know that we've added methods. + if (klass->method_count != pre_count) + klass->engine->post_miranda_hook(klass); +} + +// Verify a class. Must be called with class lock held. +void +_Jv_Linker::verify_class (jclass klass) +{ + klass->engine->verify(klass); +} + +// Check the assertions contained in the type assertion table for KLASS. +// This is the equivilent of bytecode verification for native, BC-ABI code. +void +_Jv_Linker::verify_type_assertions (jclass klass) +{ + if (debug_link) + fprintf (stderr, "Evaluating type assertions for %s:\n", + klass->name->chars()); + + if (klass->assertion_table == NULL) + return; + + for (int i = 0;; i++) + { + int assertion_code = klass->assertion_table[i].assertion_code; + _Jv_Utf8Const *op1 = klass->assertion_table[i].op1; + _Jv_Utf8Const *op2 = klass->assertion_table[i].op2; + + if (assertion_code == JV_ASSERT_END_OF_TABLE) + return; + else if (assertion_code == JV_ASSERT_TYPES_COMPATIBLE) + { + if (debug_link) + { + fprintf (stderr, " code=%i, operand A=%s B=%s\n", + assertion_code, op1->chars(), op2->chars()); + } + + // The operands are class signatures. op1 is the source, + // op2 is the target. + jclass cl1 = _Jv_FindClassFromSignature (op1->chars(), + klass->getClassLoaderInternal()); + jclass cl2 = _Jv_FindClassFromSignature (op2->chars(), + klass->getClassLoaderInternal()); + + // If the class doesn't exist, ignore the assertion. An exception + // will be thrown later if an attempt is made to actually + // instantiate the class. + if (cl1 == NULL || cl2 == NULL) + continue; + + if (! _Jv_IsAssignableFromSlow (cl2, cl1)) + { + jstring s = JvNewStringUTF ("Incompatible types: In class "); + s = s->concat (klass->getName()); + s = s->concat (JvNewStringUTF (": ")); + s = s->concat (cl1->getName()); + s = s->concat (JvNewStringUTF (" is not assignable to ")); + s = s->concat (cl2->getName()); + throw new java::lang::VerifyError (s); + } + } + else if (assertion_code == JV_ASSERT_IS_INSTANTIABLE) + { + // TODO: Implement this. + } + // Unknown assertion codes are ignored, for forwards-compatibility. + } +} + +void +_Jv_Linker::print_class_loaded (jclass klass) +{ + char *codesource = NULL; + if (klass->protectionDomain != NULL) + { + java::security::CodeSource *cs + = klass->protectionDomain->getCodeSource(); + if (cs != NULL) + { + jstring css = cs->toString(); + int len = JvGetStringUTFLength(css); + codesource = (char *) _Jv_AllocBytes(len + 1); + JvGetStringUTFRegion(css, 0, css->length(), codesource); + codesource[len] = '\0'; + } + } + if (codesource == NULL) + codesource = "<no code source>"; + + // We use a somewhat bogus test for the ABI here. + char *abi; + if (_Jv_IsInterpretedClass (klass)) + abi = "bytecode"; + else if (klass->state == JV_STATE_PRELOADING) + abi = "BC-compiled"; + else + abi = "pre-compiled"; + + fprintf (stderr, "[Loaded (%s) %s from %s]\n", abi, klass->name->chars(), + codesource); +} + +// FIXME: mention invariants and stuff. +void +_Jv_Linker::wait_for_state (jclass klass, int state) +{ + if (klass->state >= state) + return; + + JvSynchronize sync (klass); + + // This is similar to the strategy for class initialization. If we + // already hold the lock, just leave. + java::lang::Thread *self = java::lang::Thread::currentThread(); + while (klass->state <= state + && klass->thread + && klass->thread != self) + klass->wait (); + + java::lang::Thread *save = klass->thread; + klass->thread = self; + + // Print some debugging info if requested. Interpreted classes are + // handled in defineclass, so we only need to handle the two + // pre-compiled cases here. + if (gcj::verbose_class_flag + && (klass->state == JV_STATE_COMPILED + || klass->state == JV_STATE_PRELOADING) + && ! _Jv_IsInterpretedClass (klass)) + print_class_loaded (klass); + + try + { + if (state >= JV_STATE_LOADING && klass->state < JV_STATE_LOADING) + { + ensure_supers_installed (klass); + klass->set_state(JV_STATE_LOADING); + } + + if (state >= JV_STATE_LOADED && klass->state < JV_STATE_LOADED) + { + ensure_method_table_complete (klass); + klass->set_state(JV_STATE_LOADED); + } + + if (state >= JV_STATE_PREPARED && klass->state < JV_STATE_PREPARED) + { + ensure_fields_laid_out (klass); + make_vtable (klass); + layout_interface_methods (klass); + prepare_constant_time_tables (klass); + klass->set_state(JV_STATE_PREPARED); + } + + if (state >= JV_STATE_LINKED && klass->state < JV_STATE_LINKED) + { + verify_class (klass); + + ensure_class_linked (klass); + link_exception_table (klass); + link_symbol_table (klass); + klass->set_state(JV_STATE_LINKED); + } + } + catch (java::lang::Throwable *exc) + { + klass->thread = save; + klass->set_state(JV_STATE_ERROR); + throw exc; + } + + klass->thread = save; + + if (klass->state == JV_STATE_ERROR) + throw new java::lang::LinkageError; +} diff --git a/libjava/prims.cc b/libjava/prims.cc index 70ede2765cb..e3d5750cd1c 100644 --- a/libjava/prims.cc +++ b/libjava/prims.cc @@ -61,12 +61,16 @@ details. */ #include <java/lang/VirtualMachineError.h> #include <gnu/gcj/runtime/VMClassLoader.h> #include <gnu/gcj/runtime/FinalizerThread.h> +#include <execution.h> #include <gnu/java/lang/MainThread.h> #ifdef USE_LTDL #include <ltdl.h> #endif +// Execution engine for compiled code. +_Jv_CompiledEngine _Jv_soleCompiledEngine; + // We allocate a single OutOfMemoryError exception which we keep // around for use if we run out of memory. static java::lang::OutOfMemoryError *no_memory; @@ -723,7 +727,7 @@ JvConvertArgv (int argc, const char **argv) { if (argc < 0) argc = 0; - jobjectArray ar = JvNewObjectArray(argc, &StringClass, NULL); + jobjectArray ar = JvNewObjectArray(argc, &java::lang::String::class$, NULL); jobject *ptr = elements(ar); jbyteArray bytes = NULL; for (int i = 0; i < argc; i++) @@ -1204,7 +1208,7 @@ _Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags) return ((self_klass == other_klass) || ((flags & Modifier::PUBLIC) != 0) || (((flags & Modifier::PROTECTED) != 0) - && other_klass->isAssignableFrom (self_klass)) + && _Jv_IsAssignableFromSlow (other_klass, self_klass)) || (((flags & Modifier::PRIVATE) == 0) && _Jv_ClassNameSamePackage (self_klass->name, other_klass->name))); diff --git a/libjava/resolve.cc b/libjava/resolve.cc deleted file mode 100644 index 5ebefebecef..00000000000 --- a/libjava/resolve.cc +++ /dev/null @@ -1,1125 +0,0 @@ -// resolve.cc - Code for linking and resolving classes and pool entries. - -/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation - - This file is part of libgcj. - -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ - -/* Author: Kresten Krab Thorup <krab@gnu.org> */ - -#include <config.h> -#include <platform.h> - -#include <java-interp.h> - -#include <jvm.h> -#include <gcj/cni.h> -#include <string.h> -#include <java-cpool.h> -#include <java/lang/Class.h> -#include <java/lang/String.h> -#include <java/lang/StringBuffer.h> -#include <java/lang/Thread.h> -#include <java/lang/InternalError.h> -#include <java/lang/VirtualMachineError.h> -#include <java/lang/NoSuchFieldError.h> -#include <java/lang/NoSuchMethodError.h> -#include <java/lang/ClassFormatError.h> -#include <java/lang/IllegalAccessError.h> -#include <java/lang/AbstractMethodError.h> -#include <java/lang/NoClassDefFoundError.h> -#include <java/lang/IncompatibleClassChangeError.h> -#include <java/lang/VMClassLoader.h> -#include <java/lang/reflect/Modifier.h> - -using namespace gcj; - -void -_Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader) -{ - if (! field->isResolved ()) - { - _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type; - field->type = _Jv_FindClassFromSignature (sig->chars(), loader); - field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG; - } -} - -#ifdef INTERPRETER - -static void throw_internal_error (char *msg) - __attribute__ ((__noreturn__)); -static void throw_class_format_error (jstring msg) - __attribute__ ((__noreturn__)); -static void throw_class_format_error (char *msg) - __attribute__ ((__noreturn__)); - -static int get_alignment_from_class (jclass); - -static _Jv_ResolvedMethod* -_Jv_BuildResolvedMethod (_Jv_Method*, - jclass, - jboolean, - jint); - - -static void throw_incompatible_class_change_error (jstring msg) -{ - throw new java::lang::IncompatibleClassChangeError (msg); -} - -_Jv_word -_Jv_ResolvePoolEntry (jclass klass, int index) -{ - using namespace java::lang::reflect; - - _Jv_Constants *pool = &klass->constants; - - if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0) - return pool->data[index]; - - switch (pool->tags[index]) { - case JV_CONSTANT_Class: - { - _Jv_Utf8Const *name = pool->data[index].utf8; - - jclass found; - if (name->first() == '[') - found = _Jv_FindClassFromSignature (name->chars(), - klass->loader); - else - found = _Jv_FindClass (name, klass->loader); - - if (! found) - { - jstring str = name->toString(); - // This exception is specified in JLS 2nd Ed, section 5.1. - throw new java::lang::NoClassDefFoundError (str); - } - - if ((found->accflags & Modifier::PUBLIC) == Modifier::PUBLIC - || (_Jv_ClassNameSamePackage (found->name, - klass->name))) - { - pool->data[index].clazz = found; - pool->tags[index] |= JV_CONSTANT_ResolvedFlag; - } - else - { - throw new java::lang::IllegalAccessError (found->getName()); - } - } - break; - - case JV_CONSTANT_String: - { - jstring str; - str = _Jv_NewStringUtf8Const (pool->data[index].utf8); - pool->data[index].o = str; - pool->tags[index] |= JV_CONSTANT_ResolvedFlag; - } - break; - - - case JV_CONSTANT_Fieldref: - { - _Jv_ushort class_index, name_and_type_index; - _Jv_loadIndexes (&pool->data[index], - class_index, - name_and_type_index); - jclass owner = (_Jv_ResolvePoolEntry (klass, class_index)).clazz; - - if (owner != klass) - _Jv_InitClass (owner); - - _Jv_ushort name_index, type_index; - _Jv_loadIndexes (&pool->data[name_and_type_index], - name_index, - type_index); - - _Jv_Utf8Const *field_name = pool->data[name_index].utf8; - _Jv_Utf8Const *field_type_name = pool->data[type_index].utf8; - - // FIXME: The implementation of this function - // (_Jv_FindClassFromSignature) will generate an instance of - // _Jv_Utf8Const for each call if the field type is a class name - // (Lxx.yy.Z;). This may be too expensive to do for each and - // every fieldref being resolved. For now, we fix the problem by - // only doing it when we have a loader different from the class - // declaring the field. - - jclass field_type = 0; - - if (owner->loader != klass->loader) - field_type = _Jv_FindClassFromSignature (field_type_name->chars(), - klass->loader); - - _Jv_Field* the_field = 0; - - for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ()) - { - for (int i = 0; i < cls->field_count; i++) - { - _Jv_Field *field = &cls->fields[i]; - if (! _Jv_equalUtf8Consts (field->name, field_name)) - continue; - - if (_Jv_CheckAccess (klass, cls, field->flags)) - { - /* resove the field using the class' own loader - if necessary */ - - if (!field->isResolved ()) - _Jv_ResolveField (field, cls->loader); - - if (field_type != 0 && field->type != field_type) - throw new java::lang::LinkageError - (JvNewStringLatin1 - ("field type mismatch with different loaders")); - - the_field = field; - goto end_of_field_search; - } - else - { - java::lang::StringBuffer *sb - = new java::lang::StringBuffer (); - sb->append(klass->getName()); - sb->append(JvNewStringLatin1(": ")); - sb->append(cls->getName()); - sb->append(JvNewStringLatin1(".")); - sb->append(_Jv_NewStringUtf8Const (field_name)); - throw new java::lang::IllegalAccessError(sb->toString()); - } - } - } - - end_of_field_search: - if (the_field == 0) - { - java::lang::StringBuffer *sb = new java::lang::StringBuffer(); - sb->append(JvNewStringLatin1("field ")); - sb->append(owner->getName()); - sb->append(JvNewStringLatin1(".")); - sb->append(field_name->toString()); - sb->append(JvNewStringLatin1(" was not found.")); - throw_incompatible_class_change_error(sb->toString()); - } - - pool->data[index].field = the_field; - pool->tags[index] |= JV_CONSTANT_ResolvedFlag; - } - break; - - case JV_CONSTANT_Methodref: - case JV_CONSTANT_InterfaceMethodref: - { - _Jv_ushort class_index, name_and_type_index; - _Jv_loadIndexes (&pool->data[index], - class_index, - name_and_type_index); - jclass owner = (_Jv_ResolvePoolEntry (klass, class_index)).clazz; - - if (owner != klass) - _Jv_InitClass (owner); - - _Jv_ushort name_index, type_index; - _Jv_loadIndexes (&pool->data[name_and_type_index], - name_index, - type_index); - - _Jv_Utf8Const *method_name = pool->data[name_index].utf8; - _Jv_Utf8Const *method_signature = pool->data[type_index].utf8; - - _Jv_Method *the_method = 0; - jclass found_class = 0; - - // First search the class itself. - the_method = _Jv_SearchMethodInClass (owner, klass, - method_name, method_signature); - - if (the_method != 0) - { - found_class = owner; - goto end_of_method_search; - } - - // If we are resolving an interface method, search the - // interface's superinterfaces (A superinterface is not an - // interface's superclass - a superinterface is implemented by - // the interface). - if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref) - { - _Jv_ifaces ifaces; - ifaces.count = 0; - ifaces.len = 4; - ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *)); - - _Jv_GetInterfaces (owner, &ifaces); - - for (int i = 0; i < ifaces.count; i++) - { - jclass cls = ifaces.list[i]; - the_method = _Jv_SearchMethodInClass (cls, klass, method_name, - method_signature); - if (the_method != 0) - { - found_class = cls; - break; - } - } - - _Jv_Free (ifaces.list); - - if (the_method != 0) - goto end_of_method_search; - } - - // Finally, search superclasses. - for (jclass cls = owner->getSuperclass (); cls != 0; - cls = cls->getSuperclass ()) - { - the_method = _Jv_SearchMethodInClass (cls, klass, - method_name, method_signature); - if (the_method != 0) - { - found_class = cls; - break; - } - } - - end_of_method_search: - - // FIXME: if (cls->loader != klass->loader), then we - // must actually check that the types of arguments - // correspond. That is, for each argument type, and - // the return type, doing _Jv_FindClassFromSignature - // with either loader should produce the same result, - // i.e., exactly the same jclass object. JVMS 5.4.3.3 - - if (the_method == 0) - { - java::lang::StringBuffer *sb = new java::lang::StringBuffer(); - sb->append(JvNewStringLatin1("method ")); - sb->append(owner->getName()); - sb->append(JvNewStringLatin1(".")); - sb->append(method_name->toString()); - sb->append(JvNewStringLatin1(" was not found.")); - 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 = - _Jv_BuildResolvedMethod(the_method, - found_class, - (the_method->accflags & Modifier::STATIC) != 0, - vtable_index); - pool->tags[index] |= JV_CONSTANT_ResolvedFlag; - } - break; - - } - - return pool->data[index]; -} - -// Find a method declared in the cls that is referenced from klass and -// perform access checks. -_Jv_Method * -_Jv_SearchMethodInClass (jclass cls, jclass klass, - _Jv_Utf8Const *method_name, - _Jv_Utf8Const *method_signature) -{ - using namespace java::lang::reflect; - - for (int i = 0; i < cls->method_count; i++) - { - _Jv_Method *method = &cls->methods[i]; - if ( (!_Jv_equalUtf8Consts (method->name, - method_name)) - || (!_Jv_equalUtf8Consts (method->signature, - method_signature))) - continue; - - if (_Jv_CheckAccess (klass, cls, method->accflags)) - return method; - else - { - java::lang::StringBuffer *sb = new java::lang::StringBuffer(); - sb->append(klass->getName()); - sb->append(JvNewStringLatin1(": ")); - sb->append(cls->getName()); - sb->append(JvNewStringLatin1(".")); - sb->append(method_name->toString()); - sb->append(method_signature->toString()); - throw new java::lang::IllegalAccessError (sb->toString()); - } - } - return 0; -} - -// A helper for _Jv_PrepareClass. This adds missing `Miranda methods' -// to a class. -void -_Jv_PrepareMissingMethods (jclass base, jclass iface_class) -{ - _Jv_InterpClass *interp_base = (_Jv_InterpClass *) base->aux_info; - for (int i = 0; i < iface_class->interface_count; ++i) - { - for (int j = 0; j < iface_class->interfaces[i]->method_count; ++j) - { - _Jv_Method *meth = &iface_class->interfaces[i]->methods[j]; - // Don't bother with <clinit>. - if (meth->name->first() == '<') - continue; - _Jv_Method *new_meth = _Jv_LookupDeclaredMethod (base, meth->name, - meth->signature); - if (! new_meth) - { - // We assume that such methods are very unlikely, so we - // just reallocate the method array each time one is - // found. This greatly simplifies the searching -- - // otherwise we have to make sure that each such method - // 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); - memcpy (new_m, base->methods, - sizeof (_Jv_Method) * base->method_count); - - // Add new method. - new_m[base->method_count] = *meth; - new_m[base->method_count].index = (_Jv_ushort) -1; - new_m[base->method_count].accflags - |= java::lang::reflect::Modifier::INVISIBLE; - - _Jv_MethodBase **new_im - = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *) - * new_count); - memcpy (new_im, interp_base->interpreted_methods, - sizeof (_Jv_MethodBase *) * base->method_count); - - base->methods = new_m; - interp_base->interpreted_methods = new_im; - base->method_count = new_count; - } - } - - _Jv_PrepareMissingMethods (base, iface_class->interfaces[i]); - } -} - -void -_Jv_PrepareClass(jclass klass) -{ - using namespace java::lang::reflect; - - /* - * The job of this function is to: 1) assign storage to fields, and 2) - * build the vtable. static fields are assigned real memory, instance - * fields are assigned offsets. - * - * NOTE: we have a contract with the garbage collector here. Static - * reference fields must not be resolved, until after they have storage - * assigned which is the check used by the collector to see if it - * should indirect the static field reference and mark the object - * pointed to. - * - * Most fields are resolved lazily (i.e. have their class-type - * assigned) when they are accessed the first time by calling as part - * of _Jv_ResolveField, which is allways called after _Jv_PrepareClass. - * Static fields with initializers are resolved as part of this - * function, as are fields with primitive types. - */ - - if (! _Jv_IsInterpretedClass (klass)) - return; - - if (klass->state >= JV_STATE_PREPARED) - return; - - // Make sure super-class is linked. This involves taking a lock on - // the super class, so we use the Java method resolveClass, which - // will unlock it properly, should an exception happen. If there's - // no superclass, do nothing -- Object will already have been - // resolved. - - if (klass->superclass) - java::lang::VMClassLoader::resolveClass (klass->superclass); - - _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info; - - /************ PART ONE: OBJECT LAYOUT ***************/ - - // Compute the alignment for this type by searching through the - // superclasses and finding the maximum required alignment. We - // could consider caching this in the Class. - int max_align = __alignof__ (java::lang::Object); - jclass super = klass->superclass; - while (super != NULL) - { - int num = JvNumInstanceFields (super); - _Jv_Field *field = JvGetFirstInstanceField (super); - while (num > 0) - { - int field_align = get_alignment_from_class (field->type); - if (field_align > max_align) - max_align = field_align; - ++field; - --num; - } - super = super->superclass; - } - - int instance_size; - int static_size = 0; - - // Although java.lang.Object is never interpreted, an interface can - // have a null superclass. Note that we have to lay out an - // interface because it might have static fields. - if (klass->superclass) - instance_size = klass->superclass->size(); - else - instance_size = java::lang::Object::class$.size(); - - for (int i = 0; i < klass->field_count; i++) - { - int field_size; - int field_align; - - _Jv_Field *field = &klass->fields[i]; - - if (! field->isRef ()) - { - // it's safe to resolve the field here, since it's - // a primitive class, which does not cause loading to happen. - _Jv_ResolveField (field, klass->loader); - - field_size = field->type->size (); - field_align = get_alignment_from_class (field->type); - } - else - { - field_size = sizeof (jobject); - field_align = __alignof__ (jobject); - } - -#ifndef COMPACT_FIELDS - field->bsize = field_size; -#endif - - if (field->flags & Modifier::STATIC) - { - /* this computes an offset into a region we'll allocate - shortly, and then add this offset to the start address */ - - static_size = ROUND (static_size, field_align); - field->u.boffset = static_size; - static_size += field_size; - } - else - { - instance_size = ROUND (instance_size, field_align); - field->u.boffset = instance_size; - instance_size += field_size; - if (field_align > max_align) - max_align = field_align; - } - } - - // 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 - // with our current ABI. - instance_size = ROUND (instance_size, max_align); - klass->size_in_bytes = instance_size; - - // allocate static memory - if (static_size != 0) - { - char *static_data = (char*)_Jv_AllocBytes (static_size); - - memset (static_data, 0, static_size); - - for (int i = 0; i < klass->field_count; i++) - { - _Jv_Field *field = &klass->fields[i]; - - if ((field->flags & Modifier::STATIC) != 0) - { - field->u.addr = static_data + field->u.boffset; - - if (iclass->field_initializers[i] != 0) - { - _Jv_ResolveField (field, klass->loader); - _Jv_InitField (0, klass, i); - } - } - } - - // now we don't need the field_initializers anymore, so let the - // collector get rid of it! - - iclass->field_initializers = 0; - } - - /************ PART TWO: VTABLE LAYOUT ***************/ - - /* preparation: build the vtable stubs (even interfaces can) - have code -- for static constructors. */ - for (int i = 0; i < klass->method_count; i++) - { - _Jv_MethodBase *imeth = iclass->interpreted_methods[i]; - - if ((klass->methods[i].accflags & Modifier::NATIVE) != 0) - { - // You might think we could use a virtual `ncode' method in - // the _Jv_MethodBase and unify the native and non-native - // cases. Well, we can't, because we don't allocate these - // objects using `new', and thus they don't get a vtable. - _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth); - klass->methods[i].ncode = jnim->ncode (); - } - else if (imeth != 0) // it could be abstract - { - _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); - _Jv_VerifyMethod (im); - klass->methods[i].ncode = im->ncode (); - - // Resolve ctable entries pointing to this method. See - // _Jv_Defer_Resolution. - void **code = (void **)imeth->deferred; - while (code) - { - void **target = (void **)*code; - *code = klass->methods[i].ncode; - code = target; - } - } - } - - if ((klass->accflags & Modifier::INTERFACE)) - { - klass->state = JV_STATE_PREPARED; - klass->notifyAll (); - return; - } - - // A class might have so-called "Miranda methods". This is a method - // that is declared in an interface and not re-declared in an - // abstract class. Some compilers don't emit declarations for such - // methods in the class; this will give us problems since we expect - // a declaration for any method requiring a vtable entry. We handle - // this here by searching for such methods and constructing new - // internal declarations for them. We only need to do this for - // abstract classes. - if ((klass->accflags & Modifier::ABSTRACT)) - _Jv_PrepareMissingMethods (klass, klass); - - klass->vtable_method_count = -1; - _Jv_MakeVTable (klass); - - /* wooha! we're done. */ - klass->state = JV_STATE_PREPARED; - klass->notifyAll (); -} - -/** Do static initialization for fields with a constant initializer */ -void -_Jv_InitField (jobject obj, jclass klass, int index) -{ - using namespace java::lang::reflect; - - if (obj != 0 && klass == 0) - klass = obj->getClass (); - - if (!_Jv_IsInterpretedClass (klass)) - return; - - _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info; - - _Jv_Field * field = (&klass->fields[0]) + index; - - if (index > klass->field_count) - throw_internal_error ("field out of range"); - - int init = iclass->field_initializers[index]; - if (init == 0) - return; - - _Jv_Constants *pool = &klass->constants; - int tag = pool->tags[init]; - - if (! field->isResolved ()) - throw_internal_error ("initializing unresolved field"); - - if (obj==0 && ((field->flags & Modifier::STATIC) == 0)) - throw_internal_error ("initializing non-static field with no object"); - - void *addr = 0; - - if ((field->flags & Modifier::STATIC) != 0) - addr = (void*) field->u.addr; - else - addr = (void*) (((char*)obj) + field->u.boffset); - - switch (tag) - { - case JV_CONSTANT_String: - { - _Jv_MonitorEnter (klass); - jstring str; - str = _Jv_NewStringUtf8Const (pool->data[init].utf8); - pool->data[init].string = str; - pool->tags[init] = JV_CONSTANT_ResolvedString; - _Jv_MonitorExit (klass); - } - /* fall through */ - - case JV_CONSTANT_ResolvedString: - if (! (field->type == &StringClass - || field->type == &java::lang::Class::class$)) - throw_class_format_error ("string initialiser to non-string field"); - - *(jstring*)addr = pool->data[init].string; - break; - - case JV_CONSTANT_Integer: - { - int value = pool->data[init].i; - - if (field->type == JvPrimClass (boolean)) - *(jboolean*)addr = (jboolean)value; - - else if (field->type == JvPrimClass (byte)) - *(jbyte*)addr = (jbyte)value; - - else if (field->type == JvPrimClass (char)) - *(jchar*)addr = (jchar)value; - - else if (field->type == JvPrimClass (short)) - *(jshort*)addr = (jshort)value; - - else if (field->type == JvPrimClass (int)) - *(jint*)addr = (jint)value; - - else - throw_class_format_error ("erroneous field initializer"); - } - break; - - case JV_CONSTANT_Long: - if (field->type != JvPrimClass (long)) - throw_class_format_error ("erroneous field initializer"); - - *(jlong*)addr = _Jv_loadLong (&pool->data[init]); - break; - - case JV_CONSTANT_Float: - if (field->type != JvPrimClass (float)) - throw_class_format_error ("erroneous field initializer"); - - *(jfloat*)addr = pool->data[init].f; - break; - - case JV_CONSTANT_Double: - if (field->type != JvPrimClass (double)) - throw_class_format_error ("erroneous field initializer"); - - *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]); - break; - - default: - throw_class_format_error ("erroneous field initializer"); - } -} - -template<typename T> -struct aligner -{ - T field; -}; - -#define ALIGNOF(TYPE) (__alignof__ (((aligner<TYPE> *) 0)->field)) - -// This returns the alignment of a type as it would appear in a -// structure. This can be different from the alignment of the type -// itself. For instance on x86 double is 8-aligned but struct{double} -// is 4-aligned. -static int -get_alignment_from_class (jclass klass) -{ - if (klass == JvPrimClass (byte)) - return ALIGNOF (jbyte); - else if (klass == JvPrimClass (short)) - return ALIGNOF (jshort); - else if (klass == JvPrimClass (int)) - return ALIGNOF (jint); - else if (klass == JvPrimClass (long)) - return ALIGNOF (jlong); - else if (klass == JvPrimClass (boolean)) - return ALIGNOF (jboolean); - else if (klass == JvPrimClass (char)) - return ALIGNOF (jchar); - else if (klass == JvPrimClass (float)) - return ALIGNOF (jfloat); - else if (klass == JvPrimClass (double)) - return ALIGNOF (jdouble); - else - return ALIGNOF (jobject); -} - - -inline static unsigned char* -skip_one_type (unsigned char* ptr) -{ - int ch = *ptr++; - - while (ch == '[') - { - ch = *ptr++; - } - - if (ch == 'L') - { - do { ch = *ptr++; } while (ch != ';'); - } - - return ptr; -} - -static ffi_type* -get_ffi_type_from_signature (unsigned char* ptr) -{ - switch (*ptr) - { - case 'L': - case '[': - return &ffi_type_pointer; - break; - - case 'Z': - // On some platforms a bool is a byte, on others an int. - if (sizeof (jboolean) == sizeof (jbyte)) - return &ffi_type_sint8; - else - { - JvAssert (sizeof (jbyte) == sizeof (jint)); - return &ffi_type_sint32; - } - break; - - case 'B': - return &ffi_type_sint8; - break; - - case 'C': - return &ffi_type_uint16; - break; - - case 'S': - return &ffi_type_sint16; - break; - - case 'I': - return &ffi_type_sint32; - break; - - case 'J': - return &ffi_type_sint64; - break; - - case 'F': - return &ffi_type_float; - break; - - case 'D': - return &ffi_type_double; - break; - - case 'V': - return &ffi_type_void; - break; - } - - throw_internal_error ("unknown type in signature"); -} - -/* this function yields the number of actual arguments, that is, if the - * function is non-static, then one is added to the number of elements - * found in the signature */ - -int -_Jv_count_arguments (_Jv_Utf8Const *signature, - jboolean staticp) -{ - unsigned char *ptr = (unsigned char*) signature->chars(); - int arg_count = staticp ? 0 : 1; - - /* first, count number of arguments */ - - // skip '(' - ptr++; - - // count args - while (*ptr != ')') - { - ptr = skip_one_type (ptr); - arg_count += 1; - } - - return arg_count; -} - -/* This beast will build a cif, given the signature. Memory for - * the cif itself and for the argument types must be allocated by the - * caller. - */ - -static int -init_cif (_Jv_Utf8Const* signature, - int arg_count, - jboolean staticp, - ffi_cif *cif, - ffi_type **arg_types, - ffi_type **rtype_p) -{ - unsigned char *ptr = (unsigned char*) signature->chars(); - - int arg_index = 0; // arg number - int item_count = 0; // stack-item count - - // setup receiver - if (!staticp) - { - arg_types[arg_index++] = &ffi_type_pointer; - item_count += 1; - } - - // skip '(' - ptr++; - - // assign arg types - while (*ptr != ')') - { - arg_types[arg_index++] = get_ffi_type_from_signature (ptr); - - if (*ptr == 'J' || *ptr == 'D') - item_count += 2; - else - item_count += 1; - - ptr = skip_one_type (ptr); - } - - // skip ')' - ptr++; - ffi_type *rtype = get_ffi_type_from_signature (ptr); - - ptr = skip_one_type (ptr); - if (ptr != (unsigned char*)signature->chars() + signature->len()) - throw_internal_error ("did not find end of signature"); - - if (ffi_prep_cif (cif, FFI_DEFAULT_ABI, - arg_count, rtype, arg_types) != FFI_OK) - throw_internal_error ("ffi_prep_cif failed"); - - if (rtype_p != NULL) - *rtype_p = rtype; - - return item_count; -} - -#if FFI_NATIVE_RAW_API -# define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure -# define FFI_RAW_SIZE ffi_raw_size -#else -# define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure -# define FFI_RAW_SIZE ffi_java_raw_size -#endif - -/* we put this one here, and not in interpret.cc because it - * calls the utility routines _Jv_count_arguments - * which are static to this module. The following struct defines the - * layout we use for the stubs, it's only used in the ncode method. */ - -typedef struct { - ffi_raw_closure closure; - ffi_cif cif; - ffi_type *arg_types[0]; -} ncode_closure; - -typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*); - -void * -_Jv_InterpMethod::ncode () -{ - using namespace java::lang::reflect; - - if (self->ncode != 0) - return self->ncode; - - jboolean staticp = (self->accflags & Modifier::STATIC) != 0; - int arg_count = _Jv_count_arguments (self->signature, staticp); - - ncode_closure *closure = - (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) - + arg_count * sizeof (ffi_type*)); - - init_cif (self->signature, - arg_count, - staticp, - &closure->cif, - &closure->arg_types[0], - NULL); - - ffi_closure_fun fun; - - args_raw_size = FFI_RAW_SIZE (&closure->cif); - - JvAssert ((self->accflags & Modifier::NATIVE) == 0); - - if ((self->accflags & Modifier::SYNCHRONIZED) != 0) - { - if (staticp) - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class; - else - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; - } - else - { - if (staticp) - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class; - else - fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal; - } - - FFI_PREP_RAW_CLOSURE (&closure->closure, - &closure->cif, - fun, - (void*)this); - - self->ncode = (void*)closure; - return self->ncode; -} - -void * -_Jv_JNIMethod::ncode () -{ - using namespace java::lang::reflect; - - if (self->ncode != 0) - return self->ncode; - - jboolean staticp = (self->accflags & Modifier::STATIC) != 0; - int arg_count = _Jv_count_arguments (self->signature, staticp); - - ncode_closure *closure = - (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) - + arg_count * sizeof (ffi_type*)); - - ffi_type *rtype; - init_cif (self->signature, - arg_count, - staticp, - &closure->cif, - &closure->arg_types[0], - &rtype); - - ffi_closure_fun fun; - - args_raw_size = FFI_RAW_SIZE (&closure->cif); - - // Initialize the argument types and CIF that represent the actual - // underlying JNI function. - int extra_args = 1; - if ((self->accflags & Modifier::STATIC)) - ++extra_args; - jni_arg_types = (ffi_type **) _Jv_Malloc ((extra_args + arg_count) - * sizeof (ffi_type *)); - int offset = 0; - jni_arg_types[offset++] = &ffi_type_pointer; - if ((self->accflags & Modifier::STATIC)) - jni_arg_types[offset++] = &ffi_type_pointer; - memcpy (&jni_arg_types[offset], &closure->arg_types[0], - arg_count * sizeof (ffi_type *)); - - if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi, - extra_args + arg_count, rtype, - jni_arg_types) != FFI_OK) - throw_internal_error ("ffi_prep_cif failed for JNI function"); - - JvAssert ((self->accflags & Modifier::NATIVE) != 0); - - // FIXME: for now we assume that all native methods for - // interpreted code use JNI. - fun = (ffi_closure_fun) &_Jv_JNIMethod::call; - - FFI_PREP_RAW_CLOSURE (&closure->closure, - &closure->cif, - fun, - (void*) this); - - self->ncode = (void *) closure; - return self->ncode; -} - - -/* A _Jv_ResolvedMethod is what is put in the constant pool for a - * MethodRef or InterfacemethodRef. */ -static _Jv_ResolvedMethod* -_Jv_BuildResolvedMethod (_Jv_Method* method, - jclass klass, - jboolean staticp, - jint vtable_index) -{ - int arg_count = _Jv_count_arguments (method->signature, staticp); - - _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*) - _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod) - + arg_count*sizeof (ffi_type*)); - - result->stack_item_count - = init_cif (method->signature, - arg_count, - staticp, - &result->cif, - &result->arg_types[0], - NULL); - - result->vtable_index = vtable_index; - result->method = method; - result->klass = klass; - - return result; -} - - -static void -throw_class_format_error (jstring msg) -{ - throw (msg - ? new java::lang::ClassFormatError (msg) - : new java::lang::ClassFormatError); -} - -static void -throw_class_format_error (char *msg) -{ - throw_class_format_error (JvNewStringLatin1 (msg)); -} - -static void -throw_internal_error (char *msg) -{ - throw new java::lang::InternalError (JvNewStringLatin1 (msg)); -} - - -#endif /* INTERPRETER */ diff --git a/libjava/testsuite/Makefile.in b/libjava/testsuite/Makefile.in index 2e51cd9e63a..2fe07c88e31 100644 --- a/libjava/testsuite/Makefile.in +++ b/libjava/testsuite/Makefile.in @@ -134,6 +134,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@ LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@ LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@ LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@ +LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@ LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBOBJS = @LIBOBJS@ diff --git a/libjava/testsuite/libjava.lang/assign2.java b/libjava/testsuite/libjava.lang/assign2.java new file mode 100644 index 00000000000..41fdcb594d9 --- /dev/null +++ b/libjava/testsuite/libjava.lang/assign2.java @@ -0,0 +1,21 @@ +// Test for an array assignment bug we've had. + +public class assign2 +{ + public static Object[][] c () { return new Long[5][5]; } + + public static Object[] d () { return new Integer[3]; } + + public static void main(String[] args) + { + try + { + Object[][] x = c(); + x[0] = d(); + } + catch (ArrayStoreException _) + { + System.out.println("good"); + } + } +} diff --git a/libjava/testsuite/libjava.lang/assign2.out b/libjava/testsuite/libjava.lang/assign2.out new file mode 100644 index 00000000000..12799ccbe7c --- /dev/null +++ b/libjava/testsuite/libjava.lang/assign2.out @@ -0,0 +1 @@ +good diff --git a/libjava/testsuite/libjava.loader/loader.exp b/libjava/testsuite/libjava.loader/loader.exp index e306a312c83..86e518170c4 100644 --- a/libjava/testsuite/libjava.loader/loader.exp +++ b/libjava/testsuite/libjava.loader/loader.exp @@ -1,5 +1,15 @@ # Tests for ClassLoader and native library loader code. +# Compute the correct name for an object file. +# This is an awful hack. +proc gcj_object_file_name {compiler base} { + verbose "OBJECT: compiler = $compiler" + if {[string match *libtool* $compiler]} { + return $base.lo + } + return $base.o +} + # Do all the work for a single JNI test. Return 0 on failure. proc gcj_loader_test_one {srcfile} { global objdir srcdir subdir @@ -9,9 +19,9 @@ proc gcj_loader_test_one {srcfile} { regsub "^.*/(\[^/.\]+)\[.\]\[^/]*$" "$srcfile" "\\1" out set executable "${objdir}/$out.exe" - set errname [file rootname [file tail $srcfile]] - set args [libjava_arguments link] - lappend args "additional_flags=--main=[file rootname [file tail $srcfile]] $srcdir/$subdir/MyLoader.java $objdir/dummy.o" + set errname [file rootname [file tail $srcfile]] + set args [libjava_arguments link] + lappend args "additional_flags=--main=[file rootname [file tail $srcfile]] $srcdir/$subdir/MyLoader.java $objdir/[gcj_object_file_name $args dummy]" set x [libjava_prune_warnings \ [libjava_tcompile $srcfile "$executable" executable $args]] @@ -47,7 +57,7 @@ proc gcj_loader_run {} { set args [libjava_arguments compile] lappend args "additional_flags=--resource $objdir/dummy.class" set x [libjava_prune_warnings \ - [libjava_tcompile "$objdir/dummy.class" "$objdir/dummy.o" object $args]] + [libjava_tcompile "$objdir/dummy.class" "$objdir/[gcj_object_file_name $args dummy]" object $args]] if { $x != "" } { verbose "resource compilation failed: $x" 2 diff --git a/libjava/verify.cc b/libjava/verify.cc index 63857d0341e..988b5aab67e 100644 --- a/libjava/verify.cc +++ b/libjava/verify.cc @@ -553,7 +553,7 @@ private: { // We use a recursive call because we also need to // check superinterfaces. - if (is_assignable_from_slow (target, source->interfaces[i])) + if (is_assignable_from_slow (target, source->getInterface (i))) return true; } } |