diff options
Diffstat (limited to 'libjava/gnu/gcj')
-rw-r--r-- | libjava/gnu/gcj/convert/Convert.java | 4 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/BootClassLoader.java | 71 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/ExtensionClassLoader.java | 40 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/HelperClassLoader.java | 67 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/PersistentByteMap.java | 187 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/SharedLibHelper.java | 26 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/SharedLibLoader.java | 2 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/VMClassLoader.java | 135 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/natVMClassLoader.cc | 79 | ||||
-rw-r--r-- | libjava/gnu/gcj/tools/gcj_dbtool/Main.java | 332 | ||||
-rw-r--r-- | libjava/gnu/gcj/tools/gcj_dbtool/natMain.cc | 24 | ||||
-rw-r--r-- | libjava/gnu/gcj/xlib/XAnyEvent.java | 4 | ||||
-rw-r--r-- | libjava/gnu/gcj/xlib/natXAnyEvent.cc | 60 |
13 files changed, 740 insertions, 291 deletions
diff --git a/libjava/gnu/gcj/convert/Convert.java b/libjava/gnu/gcj/convert/Convert.java index 3b2add6ef42..5d4a314d609 100644 --- a/libjava/gnu/gcj/convert/Convert.java +++ b/libjava/gnu/gcj/convert/Convert.java @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2002 Free Software Foundation +/* Copyright (C) 1999, 2002, 2005 Free Software Foundation This file is part of libgcj. @@ -45,7 +45,7 @@ public class Convert + ") " + System.getProperty("java.vm.version")); System.out.println(); - System.out.println("Copyright (C) 2002 Free Software Foundation, Inc."); + System.out.println("Copyright (C) 2005 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."); System.exit(0); diff --git a/libjava/gnu/gcj/runtime/BootClassLoader.java b/libjava/gnu/gcj/runtime/BootClassLoader.java new file mode 100644 index 00000000000..d2091720a4f --- /dev/null +++ b/libjava/gnu/gcj/runtime/BootClassLoader.java @@ -0,0 +1,71 @@ +/* Copyright (C) 2005 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.runtime; + +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +/** + * This is a helper for the bootstrap class loader. It is a + * URLClassLoader so that we can read a class path and re-use all the + * existing code for finding classes, extracting them from jars, etc. + * However, it is never called the way that an ordinary ClassLoader is + * called. For instance, loadClass() is never used. + */ +public final class BootClassLoader extends HelperClassLoader +{ + BootClassLoader(String libdir) + { + addDirectoriesFromProperty("java.endorsed.dirs"); + addDirectoriesFromProperty("gnu.gcj.runtime.endorsed.dirs"); + + try + { + // Add core:/ to the end so any resources compiled into this + // executable may be found. + addURL(new URL("core", "", -1, "/")); + } + catch (java.net.MalformedURLException x) + { + // This should never happen. + throw new RuntimeException(x); + } + } + + public Class bootLoadClass(String name) + throws ClassNotFoundException + { + Class c = findLoadedClass(name); + if (c == null) + { + try + { + // We could hack URLClassLoader to make this more + // efficient, if it mattered. + c = findClass(name); + } + catch (ClassNotFoundException _) + { + c = null; + } + } + return c; + } + + public URL bootGetResource(String name) + { + return findResource(name); + } + + public Enumeration bootGetResources(String name) throws IOException + { + return findResources(name); + } +} diff --git a/libjava/gnu/gcj/runtime/ExtensionClassLoader.java b/libjava/gnu/gcj/runtime/ExtensionClassLoader.java new file mode 100644 index 00000000000..690143a437a --- /dev/null +++ b/libjava/gnu/gcj/runtime/ExtensionClassLoader.java @@ -0,0 +1,40 @@ +/* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005 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> */ + +package gnu.gcj.runtime; + +import java.net.URL; + +// The extension loader for libgcj. Class loader bootstrap is a bit +// tricky, see prims.cc and SystemClassLoader for some details. +public final class ExtensionClassLoader extends HelperClassLoader +{ + private ExtensionClassLoader () + { + } + + private void init() + { + addDirectoriesFromProperty("java.ext.dirs"); + } + + // This can be package-private because we only call it from native + // code during startup. + static void initialize () + { + instance.init(); + system_instance.init(); + } + + // The only ExtensionClassLoader that can exist. + static ExtensionClassLoader instance = new ExtensionClassLoader(); + // The system class loader. + static SystemClassLoader system_instance = new SystemClassLoader(instance); +} diff --git a/libjava/gnu/gcj/runtime/HelperClassLoader.java b/libjava/gnu/gcj/runtime/HelperClassLoader.java new file mode 100644 index 00000000000..9b81b522ffa --- /dev/null +++ b/libjava/gnu/gcj/runtime/HelperClassLoader.java @@ -0,0 +1,67 @@ +/* Copyright (C) 2005 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.runtime; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.StringTokenizer; + +/** + * This is a URLClassLoader that has an extra helper method for + * handling things like java.ext.dirs. + */ +class HelperClassLoader extends URLClassLoader +{ + HelperClassLoader() + { + super(new URL[0]); + } + + /** + * This is a helper method that adds all the jar and zip files from + * a given list of paths to this class loader. The paths are taken + * from a system property whose name is provided as an argument. + */ + final void addDirectoriesFromProperty(String propName) + { + StringTokenizer st + = new StringTokenizer (System.getProperty (propName, ""), + File.pathSeparator); + try + { + while (st.hasMoreElements ()) + { + String dirname = st.nextToken (); + File dir = new File (dirname); + if (dir.exists ()) + { + if (! dirname.endsWith (File.separator)) + dirname = dirname + File.separator; + String files[] = dir.list (new FilenameFilter () + { + public boolean accept (File dir, String name) + { + return name.endsWith (".jar") || name.endsWith (".zip"); + } + }); + for (int i = files.length - 1; i >= 0; i--) + addURL(new URL("file", "", -1, dirname + files[i])); + } + } + } + catch (java.net.MalformedURLException x) + { + // This should never happen. + throw new RuntimeException(x); + } + } +} diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap.java b/libjava/gnu/gcj/runtime/PersistentByteMap.java index 230d7858576..a20f5b8ab2b 100644 --- a/libjava/gnu/gcj/runtime/PersistentByteMap.java +++ b/libjava/gnu/gcj/runtime/PersistentByteMap.java @@ -39,10 +39,6 @@ USAGE: 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 @@ -51,11 +47,7 @@ BUGS/FEATURES: 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 + 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(). */ @@ -67,6 +59,7 @@ import java.nio.*; import java.nio.channels.*; import java.util.*; import java.security.MessageDigest; +import java.math.BigInteger; public class PersistentByteMap { @@ -94,12 +87,18 @@ public class PersistentByteMap private long length; // the length of the underlying file + private final File name; // The name 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; + private HashMap values; // A map of strings in the string table. + + FileChannel fc; // The underlying file channel. + static final public class AccessMode { private final FileChannel.MapMode mapMode; @@ -108,10 +107,12 @@ public class PersistentByteMap { READ_ONLY = new AccessMode(FileChannel.MapMode.READ_ONLY); READ_WRITE = new AccessMode(FileChannel.MapMode.READ_WRITE); + PRIVATE = new AccessMode(FileChannel.MapMode.PRIVATE); } public static final AccessMode READ_ONLY; public static final AccessMode READ_WRITE; + public static final AccessMode PRIVATE; private AccessMode(FileChannel.MapMode mode) { @@ -119,8 +120,9 @@ public class PersistentByteMap } } - private PersistentByteMap() + private PersistentByteMap(File name) { + this.name = name; } public PersistentByteMap(String filename, AccessMode mode) @@ -132,7 +134,7 @@ public class PersistentByteMap public PersistentByteMap(File f, AccessMode mode) throws IOException { - FileChannel fc; + name = f; if (mode == AccessMode.READ_ONLY) { @@ -149,7 +151,7 @@ public class PersistentByteMap buf = fc.map(mode.mapMode, 0, length); int magic = getWord (MAGIC); - if (magic != 0x12345678) + if (magic != 0x67636a64) /* "gcjd" */ throw new IllegalArgumentException(f.getName()); table_base = getWord (TABLE_BASE); @@ -167,8 +169,27 @@ public class PersistentByteMap { f.createNewFile(); RandomAccessFile raf = new RandomAccessFile(f, "rw"); - - this.capacity = capacity; + + { + // 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. + // + // We expand the size by 3/2 because the hash table is + // intolerably slow when more than 2/3 full. + + BigInteger size = new BigInteger(Integer.toString(capacity * 3/2)); + 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); + + this.capacity = capacity = size.intValue(); + } + table_base = 64; string_base = table_base + capacity * TABLE_ENTRY_SIZE; string_size = 0; @@ -183,13 +204,13 @@ public class PersistentByteMap for (long i = 0; i < totalFileSize; i+= 4096) raf.write(_4k); - FileChannel fc = raf.getChannel(); + 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(0x67636a64, MAGIC); putWord(0x01, VERSION); putWord(capacity, CAPACITY); putWord(table_base, TABLE_BASE); @@ -197,15 +218,17 @@ public class PersistentByteMap putWord(file_size, FILE_SIZE); putWord(elements, ELEMENTS); buf.force(); + + length = fc.size(); + string_size = 0; } - static public PersistentByteMap emptyPersistentByteMap(String filename, - int capacity, int strtabSize) + static public PersistentByteMap + emptyPersistentByteMap(File name, int capacity, int strtabSize) throws IOException { - File f = new File(filename); - PersistentByteMap m = new PersistentByteMap(); - m.init(m, f, capacity, strtabSize); + PersistentByteMap m = new PersistentByteMap(name); + m.init(m, name, capacity, strtabSize); return m; } @@ -313,9 +336,7 @@ public class PersistentByteMap { 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) + if (elements >= capacity()) throw new IllegalAccessException("Table Full: " + elements); do @@ -336,7 +357,7 @@ public class PersistentByteMap int newValue = addBytes((byte[])value); putValuePos(newValue, hashIndex); return; - } + } hashIndex++; hashIndex %= capacity; @@ -347,6 +368,33 @@ public class PersistentByteMap private int addBytes (byte[] data) throws IllegalAccessException { + if (data.length > 16) + { + // Keep track of long strings in the hope that we will be able + // to re-use them. + if (values == null) + { + values = new HashMap(); + + for (int i = 0; i < capacity; i++) + if (getKeyPos(i) != UNUSED_ENTRY) + { + int pos = getValuePos(i); + ByteWrapper bytes = new ByteWrapper(getBytes(pos)); + values.put(bytes, new Integer(pos)); + } + } + + { + Object result = values.get(new ByteWrapper(data)); + if (result != null) + { + // We already have this value in the string table + return ((Integer)result).intValue(); + } + } + } + if (data.length + INT_SIZE >= this.length) throw new IllegalAccessException("String table Full"); @@ -363,6 +411,9 @@ public class PersistentByteMap file_size = extent; putWord (string_size, STRING_SIZE); putWord (file_size, FILE_SIZE); + + if (data.length > 16) + values.put(new ByteWrapper(data), new Integer(top - string_base)); return top - string_base; } @@ -377,11 +428,68 @@ public class PersistentByteMap return elements; } + public int stringTableSize() + { + return string_size; + } + public int capacity() { - return capacity; + // 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. + return capacity * 2/3; } + public void force() + { + buf.force(); + } + + public File getFile() + { + return name; + } + + // Close the map. Once this has been done, the map can no longer be + // used. + public void close() + { + force(); + fc.close(); + } + + public void + putAll(PersistentByteMap t) + throws IllegalAccessException + { + // We can use a fast copy if the size of a map has not changed. + if (this.elements == 0 && t.capacity == this.capacity + && t.length == this.length) + { + this.buf.position(0); + t.buf.position(0); + this.buf.put(t.buf); + this.table_base = t.table_base; + this.string_base = t.string_base; + this.string_size = t.string_size; + this.file_size = t.file_size; + this.elements = t.elements; + if (t.values != null) + this.values = (HashMap)t.values.clone(); + return; + } + + // Otherwise do it the hard way. + Iterator iterator = t.iterator(PersistentByteMap.ENTRIES); + while (iterator.hasNext()) + { + PersistentByteMap.MapEntry entry + = (PersistentByteMap.MapEntry)iterator.next(); + this.put((byte[])entry.getKey(), (byte[])entry.getValue()); + } + } + + private final class HashIterator implements Iterator { /** Current index in the physical hash table. */ @@ -481,4 +589,31 @@ public class PersistentByteMap return bucket; } } + + // A wrapper class for a byte array that allows collections to be + // made. + private final class ByteWrapper + { + final byte[] bytes; + final int hash; + + public ByteWrapper (byte[] bytes) + { + int sum = 0; + this.bytes = bytes; + for (int i = 0; i < bytes.length; i++) + sum += bytes[i]; + hash = sum; + } + + public int hashCode() + { + return hash; + } + + public boolean equals(Object obj) + { + return Arrays.equals(bytes, ((ByteWrapper)obj).bytes); + } + } } diff --git a/libjava/gnu/gcj/runtime/SharedLibHelper.java b/libjava/gnu/gcj/runtime/SharedLibHelper.java index a0bfe68b83c..bdf7c0453ae 100644 --- a/libjava/gnu/gcj/runtime/SharedLibHelper.java +++ b/libjava/gnu/gcj/runtime/SharedLibHelper.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2003, 2004 Free Software Foundation +/* Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation This file is part of libgcj. @@ -28,13 +28,15 @@ public class SharedLibHelper * @parem flags passed to dlopen */ SharedLibHelper(String libname, ClassLoader parent, CodeSource source, - int flags) + ProtectionDomain domain, int flags) { // FIXME: ask security manager first. loader = parent; baseName = libname; - domain = new ProtectionDomain(source, - Policy.getPolicy().getPermissions(source)); + if (domain == null) + domain = new ProtectionDomain(source, + Policy.getPolicy().getPermissions(source)); + this.domain = domain; this.flags = flags; } @@ -65,7 +67,16 @@ public class SharedLibHelper } public static SharedLibHelper findHelper (ClassLoader loader, String libname, - CodeSource source) + CodeSource source, + boolean tryParents) + { + return findHelper (loader, libname, source, null, tryParents); + } + + public static SharedLibHelper findHelper (ClassLoader loader, String libname, + CodeSource source, + ProtectionDomain domain, + boolean tryParents) { synchronized (map) { @@ -95,7 +106,7 @@ public class SharedLibHelper return result; l = l.getParent(); } - while (l != null); + while (tryParents && l != null); } } } @@ -109,6 +120,7 @@ public class SharedLibHelper ".so", new File ("/tmp")); File src = new File(libname); copyFile (src, copy); + copy.deleteOnExit(); libname = copy.getPath(); } catch (IOException e) @@ -116,7 +128,7 @@ public class SharedLibHelper return null; } } - result = new SharedLibHelper(libname, loader, source, 0); + result = new SharedLibHelper(libname, loader, source, domain, 0); s.add(new WeakReference(result)); return result; } diff --git a/libjava/gnu/gcj/runtime/SharedLibLoader.java b/libjava/gnu/gcj/runtime/SharedLibLoader.java index 1f80bbc8289..b8e6a57de53 100644 --- a/libjava/gnu/gcj/runtime/SharedLibLoader.java +++ b/libjava/gnu/gcj/runtime/SharedLibLoader.java @@ -39,7 +39,7 @@ public class SharedLibLoader extends ClassLoader url = null; } helper = SharedLibHelper.findHelper(this, libname, - new CodeSource(url, null)); + new CodeSource(url, null), true); } /** Load a shared library, and asociate a ClassLoader with it. diff --git a/libjava/gnu/gcj/runtime/VMClassLoader.java b/libjava/gnu/gcj/runtime/VMClassLoader.java deleted file mode 100644 index 1ded892a06d..00000000000 --- a/libjava/gnu/gcj/runtime/VMClassLoader.java +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005 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> */ - -package gnu.gcj.runtime; - -import java.io.*; -import java.util.StringTokenizer; -import java.util.HashSet; -import java.net.URL; -import java.net.URLClassLoader; - -// Despite its name, this class is really the extension loader for -// libgcj. Class loader bootstrap is a bit tricky, see prims.cc and -// SystemClassLoader for some details. -public final class VMClassLoader extends URLClassLoader -{ - private VMClassLoader () - { - super (new URL[0]); - String p - = System.getProperty ("gnu.gcj.runtime.VMClassLoader.library_control", - ""); - if ("never".equals(p)) - lib_control = LIB_NEVER; - else if ("cache".equals(p)) - lib_control = LIB_CACHE; - else if ("full".equals(p)) - lib_control = LIB_FULL; - else - lib_control = LIB_CACHE; - } - - private void init() - { - // Add the contents of the extensions directories. - StringTokenizer st - = new StringTokenizer (System.getProperty ("java.ext.dirs"), - File.pathSeparator); - - try - { - while (st.hasMoreElements ()) - { - String dirname = st.nextToken (); - File dir = new File (dirname); - if (dir.exists ()) - { - if (! dirname.endsWith (File.separator)) - dirname = dirname + File.separator; - String files[] - = dir.list (new FilenameFilter () - { - public boolean accept (File dir, String name) - { - return (name.endsWith (".jar") - || name.endsWith (".zip")); - } - }); - for (int i = files.length - 1; i >= 0; i--) - addURL(new URL("file", "", -1, dirname + files[i])); - } - } - - // Add core:/ to the end so any resources compiled into this - // executable may be found. - addURL(new URL("core", "", -1, "/")); - } - catch (java.net.MalformedURLException x) - { - // This should never happen. - throw new RuntimeException(x); - } - } - - /** 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 - * gnu/gcj/runtime/natVMClassLoader.cc. - */ - protected native Class findClass(String name) - throws java.lang.ClassNotFoundException; - - // This can be package-private because we only call it from native - // code during startup. - static void initialize () - { - instance.init(); - system_instance.init(); - } - - // Define a package for something loaded natively. - void definePackageForNative(String className) - { - int lastDot = className.lastIndexOf('.'); - if (lastDot != -1) - { - String packageName = className.substring(0, lastDot); - if (getPackage(packageName) == null) - { - // FIXME: this assumes we're defining the core, which - // isn't necessarily so. We could detect this and set up - // appropriately. We could also look at a manifest file - // compiled into the .so. - definePackage(packageName, "Java Platform API Specification", - "GNU", "1.4", "gcj", "GNU", - null, // FIXME: gcj version. - null); - } - } - } - - // This keeps track of shared libraries we've already tried to load. - private HashSet tried_libraries = new HashSet(); - - // Holds one of the LIB_* constants; used to determine how shared - // library loads are done. - private int lib_control; - - // The only VMClassLoader that can exist. - static VMClassLoader instance = new VMClassLoader(); - // The system class loader. - static SystemClassLoader system_instance = new SystemClassLoader(instance); - - private static final int LIB_FULL = 0; - private static final int LIB_CACHE = 1; - private static final int LIB_NEVER = 2; -} diff --git a/libjava/gnu/gcj/runtime/natVMClassLoader.cc b/libjava/gnu/gcj/runtime/natVMClassLoader.cc deleted file mode 100644 index 7f2ee34eb32..00000000000 --- a/libjava/gnu/gcj/runtime/natVMClassLoader.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Native code for VMClassLoader - -/* Copyright (C) 2002, 2003, 2005 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. */ - -#include <config.h> - -#include <gcj/cni.h> -#include <jvm.h> - -#include <gnu/gcj/runtime/VMClassLoader.h> -#include <java/lang/Class.h> -#include <java/lang/StringBuffer.h> -#include <java/net/URLClassLoader.h> -#include <java/lang/Runtime.h> -#include <java/util/HashSet.h> - -jclass -gnu::gcj::runtime::VMClassLoader::findClass (jstring name) -{ - _Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name); - jclass klass = _Jv_FindClassInCache (name_u); - - if (! klass && lib_control != LIB_NEVER) - { - // Turn `gnu.pkg.quux' into `lib-gnu-pkg-quux'. Then search for - // a module named (eg, on Linux) `lib-gnu-pkg-quux.so', followed - // by `lib-gnu-pkg.so' and `lib-gnu.so'. If loading one of - // these causes the class to appear in the cache, then use it. - java::lang::StringBuffer *sb = new java::lang::StringBuffer (JvNewStringLatin1("lib-")); - // Skip inner classes - jstring cn; - jint ci = name->indexOf('$'); - if (ci == -1) - cn = name; - else - cn = name->substring (0, ci); - jstring so_base_name = (sb->append (cn)->toString ())->replace ('.', '-'); - - using namespace ::java::lang; - Runtime *rt = Runtime::getRuntime(); - - // Compare against `3' because that is the length of "lib". - while (! klass && so_base_name && so_base_name->length() > 3) - { - if (lib_control == LIB_CACHE) - { - // If we've already tried this name, we're done. - if (tried_libraries->contains(so_base_name)) - break; - tried_libraries->add(so_base_name); - } - - jboolean loaded = rt->loadLibraryInternal (so_base_name); - - jint nd = so_base_name->lastIndexOf ('-'); - if (nd == -1) - so_base_name = NULL; - else - so_base_name = so_base_name->substring (0, nd); - - if (loaded) - klass = _Jv_FindClassInCache (name_u); - } - } - - // Either define the package, or try loading using the interpreter. - if (klass) - definePackageForNative(name); - else - klass = java::net::URLClassLoader::findClass (name); - - return klass; -} diff --git a/libjava/gnu/gcj/tools/gcj_dbtool/Main.java b/libjava/gnu/gcj/tools/gcj_dbtool/Main.java index b9bea0e09fa..58e9720f5fb 100644 --- a/libjava/gnu/gcj/tools/gcj_dbtool/Main.java +++ b/libjava/gnu/gcj/tools/gcj_dbtool/Main.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 Free Software Foundation +/* Copyright (C) 2004, 2005 Free Software Foundation This file is part of libgcj. @@ -11,16 +11,33 @@ package gnu.gcj.tools.gcj_dbtool; import gnu.gcj.runtime.PersistentByteMap; import java.io.*; +import java.nio.channels.*; import java.util.*; import java.util.jar.*; import java.security.MessageDigest; -import java.math.BigInteger; public class Main { + static private boolean verbose = false; + public static void main (String[] s) { + boolean fileListFromStdin = false; + char filenameSeparator = ' '; + insist (s.length >= 1); + + if (s[0].equals("-") || + s[0].equals("-0")) + { + if (s[0].equals("-0")) + filenameSeparator = (char)0; + fileListFromStdin = true; + String[] newArgs = new String[s.length - 1]; + System.arraycopy(s, 1, newArgs, 0, s.length - 1); + s = newArgs; + } + if (s[0].equals("-v") || s[0].equals("--version")) { insist (s.length == 1); @@ -29,7 +46,7 @@ public class Main + ") " + System.getProperty("java.vm.version")); System.out.println(); - System.out.println("Copyright 2004 Free Software Foundation, Inc."); + System.out.println("Copyright 2005 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; @@ -42,26 +59,14 @@ public class Main if (s[0].equals("-n")) { + // Create a new database. 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(); + { + capacity = Integer.parseInt(s[2]); if (capacity <= 2) { @@ -73,7 +78,8 @@ public class Main try { PersistentByteMap b - = PersistentByteMap.emptyPersistentByteMap (s[1], capacity, capacity*64); + = PersistentByteMap.emptyPersistentByteMap(new File(s[1]), + capacity, capacity*32); } catch (Exception e) { @@ -84,20 +90,28 @@ public class Main return; } - if (s[0].equals("-a")) + if (s[0].equals("-a") || s[0].equals("-f")) { + // Add a jar file to a database, creating it if necessary. + // Copies the database, adds the jar file to the copy, and + // then renames the new database over the old. try { insist (s.length == 4); - File jar = new File(s[2]); - PersistentByteMap b - = new PersistentByteMap(new File(s[1]), - PersistentByteMap.AccessMode.READ_WRITE); + File database = new File(s[1]); + database = database.getAbsoluteFile(); + File jar = new File(s[2]); + PersistentByteMap map; + if (database.isFile()) + map = new PersistentByteMap(database, + PersistentByteMap.AccessMode.READ_ONLY); + else + map = PersistentByteMap.emptyPersistentByteMap(database, + 100, 100*32); File soFile = new File(s[3]); - if (! soFile.isFile()) + if (! s[0].equals("-f") && ! soFile.isFile()) throw new IllegalArgumentException(s[3] + " is not a file"); - - addJar(jar, b, soFile); + map = addJar(jar, map, soFile); } catch (Exception e) { @@ -110,6 +124,7 @@ public class Main if (s[0].equals("-t")) { + // Test try { insist (s.length == 2); @@ -142,8 +157,69 @@ public class Main return; } + if (s[0].equals("-m")) + { + // Merge databases. + insist (s.length >= 3 + || fileListFromStdin && s.length == 2); + try + { + File database = new File(s[1]); + database = database.getAbsoluteFile(); + File temp = File.createTempFile(database.getName(), "", + database.getParentFile()); + + int newSize = 0; + int newStringTableSize = 0; + Fileset files = getFiles(s, 2, fileListFromStdin, + filenameSeparator); + PersistentByteMap[] sourceMaps + = new PersistentByteMap[files.size()]; + + // Scan all the input files, calculating worst case string + // table and hash table use. + { + Iterator it = files.iterator(); + int i = 0; + while (it.hasNext()) + { + PersistentByteMap b + = new PersistentByteMap((File)it.next(), + PersistentByteMap.AccessMode.READ_ONLY); + newSize += b.size(); + newStringTableSize += b.stringTableSize(); + sourceMaps[i++] = b; + } + } + + newSize *= 1.5; // Scaling the new size by 1.5 results in + // fewer collisions. + PersistentByteMap map + = PersistentByteMap.emptyPersistentByteMap + (temp, newSize, newStringTableSize); + + for (int i = 0; i < sourceMaps.length; i++) + { + if (verbose) + System.err.println("adding " + sourceMaps[i].size() + + " elements from " + + sourceMaps[i].getFile()); + map.putAll(sourceMaps[i]); + } + map.close(); + temp.renameTo(database); + } + catch (Exception e) + { + e.printStackTrace(); + System.exit(3); + } + return; + } + if (s[0].equals("-l")) { + // List a database. insist (s.length == 2); try { @@ -180,6 +256,7 @@ public class Main if (s[0].equals("-d")) { + // For testing only: fill the byte map with random data. insist (s.length == 2); try { @@ -203,11 +280,29 @@ public class Main } return; } - + + if (s[0].equals("-p")) + { + insist (s.length == 1 || s.length == 2); + String result; + + if (s.length == 1) + result = System.getProperty("gnu.gcj.precompiled.db.path", ""); + else + result = (s[1] + + (s[1].endsWith(File.separator) ? "" : File.separator) + + getDbPathTail ()); + + System.out.println (result); + return; + } + usage(System.err); System.exit(1); } + private static native String getDbPathTail (); + private static void insist(boolean ok) { if (! ok) @@ -225,20 +320,55 @@ public class Main + " Usage: \n" + " gcj-dbtool -n file.gcjdb [size] - Create a new gcj map database\n" + " gcj-dbtool -a file.gcjdb file.jar file.so\n" - + " - Add the contents of file.jar to the database\n" + + " - Add the contents of file.jar to a gcj map database\n" + + " gcj-dbtool -f file.gcjdb file.jar file.so\n" + + " - Add the contents of file.jar to a gcj map database\n" + " gcj-dbtool -t file.gcjdb - Test a gcj map database\n" - + " gcj-dbtool -l file.gcjdb - List a gcj map database\n"); + + " gcj-dbtool -l file.gcjdb - List a gcj map database\n" + + " gcj-dbtool [-][-0] -m dest.gcjdb [source.gcjdb]...\n" + + " - Merge gcj map databases into dest\n" + + " Replaces dest\n" + + " To add to dest, include dest in the list of sources\n" + + " If the first arg is -, read the list from stdin\n" + + " If the first arg is -0, filenames separated by nul\n" + + " gcj-dbtool -p [LIBDIR] - Print default database name" + ); } - - private static void addJar(File f, PersistentByteMap b, File soFile) - throws Exception + // Add a jar to a map. This copies the map first and returns a + // different map that contains the data. The original map is + // closed. + + private static PersistentByteMap + addJar(File f, PersistentByteMap b, File soFile) + throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); JarFile jar = new JarFile (f); + + int count = 0; + { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) + { + JarEntry classfile = (JarEntry)entries.nextElement(); + if (classfile.getName().endsWith(".class")) + count++; + } + } + + if (verbose) + System.err.println("adding " + count + " elements from " + + f + " to " + b.getFile()); + + // Maybe resize the destination map. We're allowing plenty of + // extra space by using a loadFactor of 2. + b = resizeMap(b, (b.size() + count) * 2, true); + Enumeration entries = jar.entries(); + byte[] soFileName = soFile.getCanonicalPath().getBytes("UTF-8"); while (entries.hasMoreElements()) { JarEntry classfile = (JarEntry)entries.nextElement(); @@ -259,12 +389,41 @@ public class Main + classfile.getName()); pos += len; } - b.put(md.digest(data), - soFile.getCanonicalPath().getBytes()); + b.put(md.digest(data), soFileName); } - } + } + return b; } + // Resize a map by creating a new one with the same data and + // renaming it. If close is true, close the original map. + + static PersistentByteMap resizeMap(PersistentByteMap m, int newCapacity, boolean close) + throws IOException, IllegalAccessException + { + newCapacity = Math.max(m.capacity(), newCapacity); + File name = m.getFile(); + File copy = File.createTempFile(name.getName(), "", name.getParentFile()); + try + { + PersistentByteMap dest + = PersistentByteMap.emptyPersistentByteMap + (copy, newCapacity, newCapacity*32); + dest.putAll(m); + dest.force(); + if (close) + m.close(); + copy.renameTo(name); + return dest; + } + catch (Exception e) + { + copy.delete(); + } + return null; + } + + static String bytesToString(byte[] b) { StringBuffer hexBytes = new StringBuffer(); @@ -273,5 +432,104 @@ public class Main hexBytes.append(Integer.toHexString(b[i] & 0xff)); return hexBytes.toString(); } + + + // Return a Fileset, either from a String array or from System.in, + // depending on fileListFromStdin. + private static final Fileset getFiles(String[] s, int startPos, + boolean fileListFromStdin, + char separator) + { + if (fileListFromStdin) + return new Fileset(System.in, separator); + else + return new Fileset(s, startPos, s.length); + } +} + +// Parse a stream into tokens. The separator can be any char, and +// space is equivalent to any whitepace character. +class Tokenizer +{ + final Reader r; + final char separator; + + Tokenizer(Reader r, char separator) + { + this.r = r; + this.separator = separator; + } + + boolean isSeparator(int c) + { + if (Character.isWhitespace(separator)) + return Character.isWhitespace((char)c); + else + return c == separator; + } + + // Parse a token from the input stream. Return the empty string + // when the stream is exhausted. + String nextToken () + { + StringBuffer buf = new StringBuffer(); + int c; + try + { + while ((c = r.read()) != -1) + { + if (! isSeparator(c)) + { + buf.append((char)c); + break; + } + } + while ((c = r.read()) != -1) + { + if (isSeparator(c)) + break; + else + buf.append((char)c); + } + } + catch (java.io.IOException e) + { + } + return buf.toString(); + } +} + +// A Fileset is a container for a set of files; it can be created +// either from a string array or from an input stream, given a +// separator character. +class Fileset +{ + LinkedHashSet files = new LinkedHashSet(); + + Fileset (String[] s, int start, int end) + { + for (int i = start; i < end; i++) + { + files.add(new File(s[i])); + } + } + + Fileset (InputStream is, char separator) + { + Reader r = new BufferedReader(new InputStreamReader(is)); + Tokenizer st = new Tokenizer(r, separator); + String name; + while (! "".equals(name = st.nextToken())) + files.add(new File(name)); + } + + Iterator iterator() + { + return files.iterator(); + } + + int size() + { + return files.size(); + } } - diff --git a/libjava/gnu/gcj/tools/gcj_dbtool/natMain.cc b/libjava/gnu/gcj/tools/gcj_dbtool/natMain.cc new file mode 100644 index 00000000000..52ba0d7d13c --- /dev/null +++ b/libjava/gnu/gcj/tools/gcj_dbtool/natMain.cc @@ -0,0 +1,24 @@ +// natMain -- gcj-dbtool native code. + +/* Copyright (C) 2005 Free Software Foundation + + This file is part of gcj-dbtool. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +/* Author: Anthony Green <green@redhat.com>. */ + +#include <config.h> + +#include <gcj/cni.h> +#include <jvm.h> + +#include <gnu/gcj/tools/gcj_dbtool/Main.h> + +java::lang::String * +gnu::gcj::tools::gcj_dbtool::Main::getDbPathTail () +{ + return JvNewStringLatin1 (LIBGCJ_DEFAULT_DATABASE_PATH_TAIL); +} diff --git a/libjava/gnu/gcj/xlib/XAnyEvent.java b/libjava/gnu/gcj/xlib/XAnyEvent.java index 061d6137b17..bce3a6150ee 100644 --- a/libjava/gnu/gcj/xlib/XAnyEvent.java +++ b/libjava/gnu/gcj/xlib/XAnyEvent.java @@ -70,7 +70,8 @@ public final class XAnyEvent /** * Load next event into the event structure. */ - public native void loadNext(); + public native boolean loadNext(boolean block); + public native void interrupt(); public native int getType(); public native void setType(int type); @@ -86,6 +87,7 @@ public final class XAnyEvent public native void send(Window destination, boolean propagate, long mask); + RawData pipefds; RawData structure; Display display; diff --git a/libjava/gnu/gcj/xlib/natXAnyEvent.cc b/libjava/gnu/gcj/xlib/natXAnyEvent.cc index 439f204b373..0bef563ed2d 100644 --- a/libjava/gnu/gcj/xlib/natXAnyEvent.cc +++ b/libjava/gnu/gcj/xlib/natXAnyEvent.cc @@ -6,6 +6,12 @@ This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ +#include <config.h> +#include <platform.h> + +#include <gcj/javaprims.h> +#include <jvm.h> + #include <X11/Xlib.h> #include <gcj/cni.h> @@ -22,24 +28,72 @@ details. */ #include <gnu/gcj/xlib/XExposeEvent.h> #include <gnu/gcj/xlib/XException.h> +#include <unistd.h> +#include <posix.h> + void gnu::gcj::xlib::XAnyEvent::init() { ::XEvent* event = new ::XEvent; + int *pipes = new int[2]; + pipe(pipes); structure = reinterpret_cast<gnu::gcj::RawData*>(event); + pipefds = reinterpret_cast<gnu::gcj::RawData*>(pipes); } void gnu::gcj::xlib::XAnyEvent::finalize() { delete structure; + int *pipe = reinterpret_cast<int *>(pipefds); + close(pipe[0]); + close(pipe[1]); + delete [] pipefds; + pipefds = 0; structure = 0; } -void gnu::gcj::xlib::XAnyEvent::loadNext() +jboolean gnu::gcj::xlib::XAnyEvent::loadNext(jboolean block) { ::Display* dpy = (::Display*) display->display; ::XEvent* evt = (::XEvent*) structure; - XNextEvent(dpy, evt); - // What does XNextEvent return? + + if (XPending(dpy)) + { + XNextEvent(dpy, evt); + return true; + } + + if (!block) + return false; + + int *pipe = reinterpret_cast<int *>(pipefds); + int xfd = XConnectionNumber(dpy); + int pipefd = pipe[0]; + int n = (xfd > pipefd ? xfd : pipefd) + 1; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(xfd, &rfds); + FD_SET(pipefd, &rfds); + int sel = _Jv_select (n, &rfds, NULL, NULL, NULL); + if (sel > 0) + { + if (FD_ISSET(xfd, &rfds)) + { + XNextEvent(dpy, evt); + return true; + } + if (FD_ISSET(pipefd, &rfds)) + { + char c; + read(pipefd, &c, 1); + } + } + return false; +} + +void gnu::gcj::xlib::XAnyEvent::interrupt() +{ + int *pipe = reinterpret_cast<int *>(pipefds); + write(pipe[1], "W", 1); } jint gnu::gcj::xlib::XAnyEvent::getType() |