aboutsummaryrefslogtreecommitdiff
path: root/libjava/gnu/gcj
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/gnu/gcj')
-rw-r--r--libjava/gnu/gcj/convert/Convert.java4
-rw-r--r--libjava/gnu/gcj/runtime/BootClassLoader.java71
-rw-r--r--libjava/gnu/gcj/runtime/ExtensionClassLoader.java40
-rw-r--r--libjava/gnu/gcj/runtime/HelperClassLoader.java67
-rw-r--r--libjava/gnu/gcj/runtime/PersistentByteMap.java187
-rw-r--r--libjava/gnu/gcj/runtime/SharedLibHelper.java26
-rw-r--r--libjava/gnu/gcj/runtime/SharedLibLoader.java2
-rw-r--r--libjava/gnu/gcj/runtime/VMClassLoader.java135
-rw-r--r--libjava/gnu/gcj/runtime/natVMClassLoader.cc79
-rw-r--r--libjava/gnu/gcj/tools/gcj_dbtool/Main.java332
-rw-r--r--libjava/gnu/gcj/tools/gcj_dbtool/natMain.cc24
-rw-r--r--libjava/gnu/gcj/xlib/XAnyEvent.java4
-rw-r--r--libjava/gnu/gcj/xlib/natXAnyEvent.cc60
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()