diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/gnu/gcj/runtime | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/gnu/gcj/runtime')
32 files changed, 2996 insertions, 0 deletions
diff --git a/libjava/gnu/gcj/runtime/BootClassLoader.h b/libjava/gnu/gcj/runtime/BootClassLoader.h new file mode 100644 index 000000000..c1d398798 --- /dev/null +++ b/libjava/gnu/gcj/runtime/BootClassLoader.h @@ -0,0 +1,53 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_BootClassLoader__ +#define __gnu_gcj_runtime_BootClassLoader__ + +#pragma interface + +#include <gnu/gcj/runtime/HelperClassLoader.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class BootClassLoader; + } + } + } + namespace java + { + namespace net + { + class URL; + class URLClassLoader; + } + } +} + +class gnu::gcj::runtime::BootClassLoader : public ::gnu::gcj::runtime::HelperClassLoader +{ + +public: // actually package-private + BootClassLoader(::java::lang::String *); +public: + ::java::lang::Class * bootLoadClass(::java::lang::String *); +private: + ::java::net::URLClassLoader * getBootURLLoader(); +public: + ::java::net::URL * bootGetResource(::java::lang::String *); + ::java::util::Enumeration * bootGetResources(::java::lang::String *); +public: // actually package-private + static ::java::lang::Class * coreHandler; +private: + jboolean __attribute__((aligned(__alignof__( ::gnu::gcj::runtime::HelperClassLoader)))) initialized; + ::java::net::URLClassLoader * bootURLLoader; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_BootClassLoader__ diff --git a/libjava/gnu/gcj/runtime/BootClassLoader.java b/libjava/gnu/gcj/runtime/BootClassLoader.java new file mode 100644 index 000000000..40f3147b7 --- /dev/null +++ b/libjava/gnu/gcj/runtime/BootClassLoader.java @@ -0,0 +1,138 @@ +/* Copyright (C) 2005, 2007 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 gnu.java.net.protocol.core.Handler; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; + +/** + * 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 +{ + // This forces the core URL handler to be included in statically + // linked executables. The line that adds core:/ to the search + // path fails otherwise. + static Class coreHandler = gnu.java.net.protocol.core.Handler.class; + + private boolean initialized; + private URLClassLoader bootURLLoader; + + BootClassLoader(String libdir) + { + // The BootClassLoader is the top of the delegation chain. It does not + // have a parent. + super((ClassLoader) null); + 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; + } + + // Parse the boot classpath and create a URLClassLoader that loads + // resources from it. This is provided for the benefit of code that + // does things like + // ClassLoader.getResourceAsStream("java/lang/Object.class") + private synchronized URLClassLoader getBootURLLoader() + { + if (initialized) + return bootURLLoader; + initialized = true; + + Vector<URL> urls = new Vector<URL>(); + String bootClasspath = System.getProperty ("sun.boot.class.path"); + StringTokenizer st = + new StringTokenizer(bootClasspath, File.pathSeparator); + while (st.hasMoreTokens()) + { + try + { + urls.add(new File(st.nextToken()).toURL()); + } + catch (java.net.MalformedURLException e) + { + } + } + + if (urls.size() > 0) + bootURLLoader = new URLClassLoader(urls.toArray(new URL[urls.size()])); + return bootURLLoader; + } + + public URL bootGetResource(String name) + { + URL url = findResource(name); + if (url != null) + return url; + + URLClassLoader loader = getBootURLLoader(); + if (loader != null) + url = loader.findResource(name); + + return url; + } + + public Enumeration bootGetResources(String name) throws IOException + { + URLClassLoader loader = getBootURLLoader(); + Enumeration[] e = + { + findResources(name), + (loader != null) ? loader.findResources(name) : null + }; + + Vector v = new Vector(); + for (Enumeration en : e) + if (en != null) + while (en.hasMoreElements()) + v.add(en.nextElement()); + + return v.elements(); + } +} diff --git a/libjava/gnu/gcj/runtime/ExtensionClassLoader.h b/libjava/gnu/gcj/runtime/ExtensionClassLoader.h new file mode 100644 index 000000000..ee17c2d84 --- /dev/null +++ b/libjava/gnu/gcj/runtime/ExtensionClassLoader.h @@ -0,0 +1,40 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_ExtensionClassLoader__ +#define __gnu_gcj_runtime_ExtensionClassLoader__ + +#pragma interface + +#include <gnu/gcj/runtime/HelperClassLoader.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class ExtensionClassLoader; + class SystemClassLoader; + } + } + } +} + +class gnu::gcj::runtime::ExtensionClassLoader : public ::gnu::gcj::runtime::HelperClassLoader +{ + + ExtensionClassLoader(); + void init(); +public: // actually package-private + static void initialize(); + static ::gnu::gcj::runtime::ExtensionClassLoader * instance; + static ::gnu::gcj::runtime::SystemClassLoader * system_instance; +public: + static ::java::lang::Class class$; + + friend class ::java::lang::ClassLoader; +}; + +#endif // __gnu_gcj_runtime_ExtensionClassLoader__ diff --git a/libjava/gnu/gcj/runtime/ExtensionClassLoader.java b/libjava/gnu/gcj/runtime/ExtensionClassLoader.java new file mode 100644 index 000000000..690143a43 --- /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/FinalizerThread.h b/libjava/gnu/gcj/runtime/FinalizerThread.h new file mode 100644 index 000000000..572f89d59 --- /dev/null +++ b/libjava/gnu/gcj/runtime/FinalizerThread.h @@ -0,0 +1,41 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_FinalizerThread__ +#define __gnu_gcj_runtime_FinalizerThread__ + +#pragma interface + +#include <java/lang/Thread.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class FinalizerThread; + } + } + } +} + +class gnu::gcj::runtime::FinalizerThread : public ::java::lang::Thread +{ + +public: + FinalizerThread(); +private: + void init(); +public: // actually package-private + static void finalizerReady(); +public: + void run(); +private: + static jboolean finalizer_ready; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_FinalizerThread__ diff --git a/libjava/gnu/gcj/runtime/FinalizerThread.java b/libjava/gnu/gcj/runtime/FinalizerThread.java new file mode 100644 index 000000000..c9a917cd2 --- /dev/null +++ b/libjava/gnu/gcj/runtime/FinalizerThread.java @@ -0,0 +1,32 @@ +// FinalizerThread.java -- Thread in which finalizers are run. + +/* Copyright (C) 2001, 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.runtime; + +/** + * @author Tom Tromey <tromey@redhat.com> + * @date October 3, 2001 + */ +public final class FinalizerThread extends Thread +{ + private static boolean finalizer_ready; + + public FinalizerThread () + { + super ("LibgcjInternalFinalizerThread"); + setDaemon (true); + finalizer_ready = false; + init(); + } + + private native void init(); + static native void finalizerReady(); + public native void run(); +} diff --git a/libjava/gnu/gcj/runtime/HelperClassLoader$1.h b/libjava/gnu/gcj/runtime/HelperClassLoader$1.h new file mode 100644 index 000000000..ee0447755 --- /dev/null +++ b/libjava/gnu/gcj/runtime/HelperClassLoader$1.h @@ -0,0 +1,38 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_HelperClassLoader$1__ +#define __gnu_gcj_runtime_HelperClassLoader$1__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class HelperClassLoader; + class HelperClassLoader$1; + } + } + } +} + +class gnu::gcj::runtime::HelperClassLoader$1 : public ::java::lang::Object +{ + +public: // actually package-private + HelperClassLoader$1(::gnu::gcj::runtime::HelperClassLoader *); +public: + virtual jboolean accept(::java::io::File *, ::java::lang::String *); +public: // actually package-private + ::gnu::gcj::runtime::HelperClassLoader * __attribute__((aligned(__alignof__( ::java::lang::Object)))) this$0; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_HelperClassLoader$1__ diff --git a/libjava/gnu/gcj/runtime/HelperClassLoader.h b/libjava/gnu/gcj/runtime/HelperClassLoader.h new file mode 100644 index 000000000..30311d3f8 --- /dev/null +++ b/libjava/gnu/gcj/runtime/HelperClassLoader.h @@ -0,0 +1,35 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_HelperClassLoader__ +#define __gnu_gcj_runtime_HelperClassLoader__ + +#pragma interface + +#include <java/net/URLClassLoader.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class HelperClassLoader; + } + } + } +} + +class gnu::gcj::runtime::HelperClassLoader : public ::java::net::URLClassLoader +{ + +public: // actually package-private + HelperClassLoader(); + HelperClassLoader(::java::lang::ClassLoader *); + virtual void addDirectoriesFromProperty(::java::lang::String *); +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_HelperClassLoader__ diff --git a/libjava/gnu/gcj/runtime/HelperClassLoader.java b/libjava/gnu/gcj/runtime/HelperClassLoader.java new file mode 100644 index 000000000..3b48da17c --- /dev/null +++ b/libjava/gnu/gcj/runtime/HelperClassLoader.java @@ -0,0 +1,72 @@ +/* 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]); + } + + HelperClassLoader(ClassLoader parent) + { + super(new URL[0], parent); + } + + /** + * 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/JNIWeakRef.h b/libjava/gnu/gcj/runtime/JNIWeakRef.h new file mode 100644 index 000000000..e23a59f6d --- /dev/null +++ b/libjava/gnu/gcj/runtime/JNIWeakRef.h @@ -0,0 +1,32 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_JNIWeakRef__ +#define __gnu_gcj_runtime_JNIWeakRef__ + +#pragma interface + +#include <java/lang/ref/WeakReference.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class JNIWeakRef; + } + } + } +} + +class gnu::gcj::runtime::JNIWeakRef : public ::java::lang::ref::WeakReference +{ + +public: + JNIWeakRef(::java::lang::Object *); + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_JNIWeakRef__ diff --git a/libjava/gnu/gcj/runtime/JNIWeakRef.java b/libjava/gnu/gcj/runtime/JNIWeakRef.java new file mode 100644 index 000000000..c0c76cdb6 --- /dev/null +++ b/libjava/gnu/gcj/runtime/JNIWeakRef.java @@ -0,0 +1,24 @@ +// JNIWeakRef.java - Wrapper class for JNI-specific weak references. + +/* Copyright (C) 2001 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.lang.ref.*; + +// This wrapper is used by the JNI implementation to keep track of +// global weak references. Each such reference is wrapped in an +// instance of this class, and automatically unwrapped when used. +public final class JNIWeakRef extends WeakReference +{ + public JNIWeakRef (Object referent) + { + super (referent); + } +} diff --git a/libjava/gnu/gcj/runtime/NameFinder$Addr2Line.h b/libjava/gnu/gcj/runtime/NameFinder$Addr2Line.h new file mode 100644 index 000000000..7d5b5a342 --- /dev/null +++ b/libjava/gnu/gcj/runtime/NameFinder$Addr2Line.h @@ -0,0 +1,39 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_NameFinder$Addr2Line__ +#define __gnu_gcj_runtime_NameFinder$Addr2Line__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class NameFinder; + class NameFinder$Addr2Line; + } + } + } +} + +class gnu::gcj::runtime::NameFinder$Addr2Line : public ::java::lang::Object +{ + +public: // actually package-private + NameFinder$Addr2Line(::gnu::gcj::runtime::NameFinder *, ::java::lang::String *); + virtual void close(); + ::java::lang::Process * __attribute__((aligned(__alignof__( ::java::lang::Object)))) proc; + ::java::io::BufferedWriter * out; + ::java::io::BufferedReader * in; + ::gnu::gcj::runtime::NameFinder * this$0; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_NameFinder$Addr2Line__ diff --git a/libjava/gnu/gcj/runtime/NameFinder.h b/libjava/gnu/gcj/runtime/NameFinder.h new file mode 100644 index 000000000..38fd98bab --- /dev/null +++ b/libjava/gnu/gcj/runtime/NameFinder.h @@ -0,0 +1,50 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_NameFinder__ +#define __gnu_gcj_runtime_NameFinder__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class NameFinder; + } + } + } +} + +class gnu::gcj::runtime::NameFinder : public ::java::lang::Object +{ + +public: // actually package-private + static jboolean showRaw(); + static jboolean removeUnknown(); +public: + NameFinder(); + virtual ::java::lang::String * getSourceFile(); + virtual jint getLineNum(); + virtual void lookup(::java::lang::String *, jlong); + static ::java::lang::String * demangleInterpreterMethod(::java::lang::String *, ::java::lang::String *); + virtual void close(); +private: + ::java::lang::String * __attribute__((aligned(__alignof__( ::java::lang::Object)))) binaryFile; + ::java::lang::String * sourceFile; + jint lineNum; + ::java::util::HashMap * procs; + static ::java::util::Set * blacklist; + static jboolean use_addr2line; + static jboolean show_raw; + static jboolean remove_unknown; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_NameFinder__ diff --git a/libjava/gnu/gcj/runtime/NameFinder.java b/libjava/gnu/gcj/runtime/NameFinder.java new file mode 100644 index 000000000..0742af193 --- /dev/null +++ b/libjava/gnu/gcj/runtime/NameFinder.java @@ -0,0 +1,341 @@ +/* NameFinder.java -- Translates addresses to StackTraceElements. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + + 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 gnu.classpath.Configuration; +import gnu.gcj.RawData; + +import java.lang.StringBuffer; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.IOException; +import java.io.File; +import java.util.Collections; +import java.util.Iterator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + + +/** + * Lookup addresses (represented as longs) to find source & line number info. + * + * The following system property is available (defaults to true): + * <li> + * <ul><code>gnu.gcj.runtime.NameFinder.use_addr2line</code> + * Whether an external process, addr2line, should be used to look up + * source file and line number info. Throwable.printStackTrace() will + * be faster if this property is set to 'false'. + * </ul> + * <ul><code>gnu.gcj.runtime.NameFinder.remove_unknown</code> + * Whether calls to unknown functions (class and method names are unknown) + * should be removed from the stack trace. </ul> + * </li> + * + * <code>close()</code> should be called to get rid of all resources. + * + * This class is used from <code>java.lang.VMThrowable</code>. + * + * @author Mark Wielaard (mark@klomp.org) + */ +public class NameFinder +{ + /** + * The name of the binary to look up. + */ + private String binaryFile; + private String sourceFile; + private int lineNum; + private HashMap procs = new HashMap(); + /** + * Set of binary files that addr2line should not be called on. + */ + private static Set blacklist = Collections.synchronizedSet(new HashSet()); + + private static boolean use_addr2line + = Boolean.valueOf(System.getProperty + ("gnu.gcj.runtime.NameFinder.use_addr2line", "true") + ).booleanValue(); + + private static boolean show_raw + = Boolean.valueOf(System.getProperty + ("gnu.gcj.runtime.NameFinder.show_raw", "false") + ).booleanValue(); + + /** + * Return true if raw addresses should be printed in stacktraces + * when no line number information is available. + */ + static final boolean showRaw() + { + return show_raw; + } + + private static final boolean remove_unknown + = Boolean.valueOf(System.getProperty + ("gnu.gcj.runtime.NameFinder.remove_unknown", "true") + ).booleanValue(); + + /** + * Return true if non-Java frames should be removed from stack + * traces. + */ + static final boolean removeUnknown() + { + return remove_unknown; + } + + class Addr2Line + { + Process proc; + BufferedWriter out; + BufferedReader in; + + Addr2Line(String binaryFile) + { + try + { + String[] exec = new String[] {"addr2line", "-e", binaryFile}; + Runtime runtime = Runtime.getRuntime(); + proc = runtime.exec(exec); + } + catch (IOException ioe) + { + } + + if (proc != null) + { + in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())); + } + } + + void close() + { + try + { + if (in != null) + in.close(); + if (out != null) + out.close(); + } + catch (IOException x) {} + if (proc != null) + proc.destroy(); + } + } + + /** + * Create a new NameFinder to lookup names in binaryFile. Call close to get rid of any + * resources created while using the <code>lookup</code> methods. + */ + public NameFinder() + { + } + + /** + * Returns the source file name if lookup() was successful. If the source file could not be + * determined, the binary name will be returned instead. + */ + public String getSourceFile() + { + String file; + if (sourceFile != null) + file = sourceFile; + else + file = binaryFile; + + return file.substring(file.lastIndexOf(File.separator) + 1, file.length()); + } + + /** + * If lookup() was successful, returns the line number of addr. If the line number could not + * be determined, -1 is returned. + */ + public int getLineNum() + { + return lineNum; + } + + public void lookup (String file, long addr) + { + binaryFile = file; + sourceFile = null; + lineNum = -1; + + if (! use_addr2line || blacklist.contains(file)) + return; + Addr2Line addr2line = (Addr2Line) procs.get(file); + if (addr2line == null) + { + addr2line = new Addr2Line(file); + procs.put(file, addr2line); + } + + if (addr2line.proc == null) + { + use_addr2line = false; + return; + } + + String hexAddr = "0x" + Long.toHexString(addr); + String name; + + try + { + addr2line.out.write(hexAddr); + addr2line.out.newLine(); + addr2line.out.flush(); + String result = addr2line.in.readLine(); + + if (result.indexOf("??") == -1) + { + int split = result.lastIndexOf(':'); + sourceFile = result.substring(0, split); + String lineNumStr = result.substring(split + 1, result.length()); + lineNum = Integer.parseInt (lineNumStr); + } + else + { + /* This binary has no debug info (assuming addr was valid). + Avoid repeat addr2line invocations. */ + blacklist.add(binaryFile); + } + } + catch (IOException ioe) + { + addr2line = null; + } + catch (NumberFormatException x) + { + } + } + + /** + * Returns human readable method name and aguments given a method type + * signature as known to the interpreter and a classname. + */ + public static String demangleInterpreterMethod(String m, String cn) + { + int index = 0; + int length = m.length(); + StringBuffer sb = new StringBuffer(length); + + // Figure out the real method name + if (m.startsWith("<init>")) + { + String className; + int i = cn.lastIndexOf('.'); + if (i < 0) + className = cn; + else + className = cn.substring(i + 1); + sb.append(className); + index += 7; + } + else + { + int i = m.indexOf('('); + if (i > 0) + { + sb.append(m.substring(0,i)); + index += i + 1; + } + } + + sb.append('('); + + // Demangle the type arguments + int arrayDepth = 0; + char c = (index < length) ? m.charAt(index) : ')'; + while (c != ')') + { + String type; + switch(c) + { + case 'B': + type = "byte"; + break; + case 'C': + type = "char"; + break; + case 'D': + type = "double"; + break; + case 'F': + type = "float"; + break; + case 'I': + type = "int"; + break; + case 'J': + type = "long"; + break; + case 'S': + type = "short"; + break; + case 'Z': + type = "boolean"; + break; + case 'L': + int i = m.indexOf(';', index); + if (i > 0) + { + type = m.substring(index+1, i); + index = i; + } + else + type = "<unknown ref>"; + break; + case '[': + type = ""; + arrayDepth++; + break; + default: + type = "<unknown " + c + '>'; + } + sb.append(type); + + // Handle arrays + if (c != '[' && arrayDepth > 0) + while (arrayDepth > 0) + { + sb.append("[]"); + arrayDepth--; + } + + index++; + char nc = (index < length) ? m.charAt(index) : ')'; + if (c != '[' && nc != ')') + sb.append(", "); + c = nc; + } + + // Stop. We are not interested in the return type. + sb.append(')'); + return sb.toString(); + } + + /** + * Releases all resources used by this NameFinder. + */ + public void close() + { + Iterator itr = procs.values().iterator(); + while (itr.hasNext()) + { + Addr2Line proc = (Addr2Line) itr.next(); + proc.close(); + } + } +} diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap$AccessMode.h b/libjava/gnu/gcj/runtime/PersistentByteMap$AccessMode.h new file mode 100644 index 000000000..2cd93fad8 --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap$AccessMode.h @@ -0,0 +1,49 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_PersistentByteMap$AccessMode__ +#define __gnu_gcj_runtime_PersistentByteMap$AccessMode__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class PersistentByteMap$AccessMode; + } + } + } + namespace java + { + namespace nio + { + namespace channels + { + class FileChannel$MapMode; + } + } + } +} + +class gnu::gcj::runtime::PersistentByteMap$AccessMode : public ::java::lang::Object +{ + + PersistentByteMap$AccessMode(::java::nio::channels::FileChannel$MapMode *); +public: // actually package-private + static ::java::nio::channels::FileChannel$MapMode * access$0(::gnu::gcj::runtime::PersistentByteMap$AccessMode *); +private: + ::java::nio::channels::FileChannel$MapMode * __attribute__((aligned(__alignof__( ::java::lang::Object)))) mapMode; +public: + static ::gnu::gcj::runtime::PersistentByteMap$AccessMode * READ_ONLY; + static ::gnu::gcj::runtime::PersistentByteMap$AccessMode * READ_WRITE; + static ::gnu::gcj::runtime::PersistentByteMap$AccessMode * PRIVATE; + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_PersistentByteMap$AccessMode__ diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap$ByteWrapper.h b/libjava/gnu/gcj/runtime/PersistentByteMap$ByteWrapper.h new file mode 100644 index 000000000..39cad37d3 --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap$ByteWrapper.h @@ -0,0 +1,42 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_PersistentByteMap$ByteWrapper__ +#define __gnu_gcj_runtime_PersistentByteMap$ByteWrapper__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class PersistentByteMap; + class PersistentByteMap$ByteWrapper; + } + } + } +} + +class gnu::gcj::runtime::PersistentByteMap$ByteWrapper : public ::java::lang::Object +{ + +public: + PersistentByteMap$ByteWrapper(::gnu::gcj::runtime::PersistentByteMap *, JArray< jbyte > *); + jint hashCode(); + jboolean equals(::java::lang::Object *); +public: // actually package-private + JArray< jbyte > * __attribute__((aligned(__alignof__( ::java::lang::Object)))) bytes; + jint hash; + ::gnu::gcj::runtime::PersistentByteMap * this$0; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_PersistentByteMap$ByteWrapper__ diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap$HashIterator.h b/libjava/gnu/gcj/runtime/PersistentByteMap$HashIterator.h new file mode 100644 index 000000000..65df6ceea --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap$HashIterator.h @@ -0,0 +1,44 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_PersistentByteMap$HashIterator__ +#define __gnu_gcj_runtime_PersistentByteMap$HashIterator__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class PersistentByteMap; + class PersistentByteMap$HashIterator; + } + } + } +} + +class gnu::gcj::runtime::PersistentByteMap$HashIterator : public ::java::lang::Object +{ + +public: // actually package-private + PersistentByteMap$HashIterator(::gnu::gcj::runtime::PersistentByteMap *, jint); +public: + jboolean hasNext(); + ::java::lang::Object * next(); + void remove(); +private: + jint __attribute__((aligned(__alignof__( ::java::lang::Object)))) idx; + jint count; + jint type; +public: // actually package-private + ::gnu::gcj::runtime::PersistentByteMap * this$0; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_PersistentByteMap$HashIterator__ diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap$MapEntry.h b/libjava/gnu/gcj/runtime/PersistentByteMap$MapEntry.h new file mode 100644 index 000000000..7cb8b63f0 --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap$MapEntry.h @@ -0,0 +1,40 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_PersistentByteMap$MapEntry__ +#define __gnu_gcj_runtime_PersistentByteMap$MapEntry__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class PersistentByteMap$MapEntry; + } + } + } +} + +class gnu::gcj::runtime::PersistentByteMap$MapEntry : public ::java::lang::Object +{ + +public: + PersistentByteMap$MapEntry(jint, ::java::lang::Object *, ::java::lang::Object *); + ::java::lang::Object * getKey(); + ::java::lang::Object * getValue(); + jint getBucket(); +private: + ::java::lang::Object * __attribute__((aligned(__alignof__( ::java::lang::Object)))) key; + ::java::lang::Object * value; + jint bucket; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_PersistentByteMap$MapEntry__ diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap.h b/libjava/gnu/gcj/runtime/PersistentByteMap.h new file mode 100644 index 000000000..1bac1d2c0 --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap.h @@ -0,0 +1,115 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_PersistentByteMap__ +#define __gnu_gcj_runtime_PersistentByteMap__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class PersistentByteMap; + class PersistentByteMap$AccessMode; + } + } + } + namespace java + { + namespace nio + { + class MappedByteBuffer; + namespace channels + { + class FileChannel; + } + } + } +} + +class gnu::gcj::runtime::PersistentByteMap : public ::java::lang::Object +{ + + PersistentByteMap(::java::io::File *); +public: + PersistentByteMap(::java::lang::String *, ::gnu::gcj::runtime::PersistentByteMap$AccessMode *); + PersistentByteMap(::java::io::File *, ::gnu::gcj::runtime::PersistentByteMap$AccessMode *); +private: + void init(::gnu::gcj::runtime::PersistentByteMap *, ::java::io::File *, jint, jint); +public: + static ::gnu::gcj::runtime::PersistentByteMap * emptyPersistentByteMap(::java::io::File *, jint, jint); +private: + jint getWord(jint); + void putWord(jint, jint); +public: + virtual ::java::util::Set * entrySet(); +private: + jint getBucket(jint); + jint getKeyPos(jint); + jint getValuePos(jint); + void putKeyPos(jint, jint); + void putValuePos(jint, jint); + JArray< jbyte > * getBytes(jint); + jint hash(JArray< jbyte > *); +public: + virtual JArray< jbyte > * get(JArray< jbyte > *); + virtual void put(JArray< jbyte > *, JArray< jbyte > *); +private: + jint addBytes(JArray< jbyte > *); +public: + virtual ::java::util::Iterator * iterator(jint); + virtual jint size(); + virtual jint stringTableSize(); + virtual jint capacity(); + virtual void force(); + virtual ::java::io::File * getFile(); + virtual void close(); + virtual void putAll(::gnu::gcj::runtime::PersistentByteMap *); +public: // actually package-private + static jint access$0(::gnu::gcj::runtime::PersistentByteMap *); + static jint access$1(::gnu::gcj::runtime::PersistentByteMap *); + static jint access$2(::gnu::gcj::runtime::PersistentByteMap *, jint); + static jint access$3(::gnu::gcj::runtime::PersistentByteMap *, jint); + static JArray< jbyte > * access$4(::gnu::gcj::runtime::PersistentByteMap *, jint); +private: + ::java::nio::MappedByteBuffer * __attribute__((aligned(__alignof__( ::java::lang::Object)))) buf; + static const jint MAGIC = 0; + static const jint VERSION = 4; + static const jint CAPACITY = 8; + static const jint TABLE_BASE = 12; + static const jint STRING_BASE = 16; + static const jint STRING_SIZE = 20; + static const jint FILE_SIZE = 24; + static const jint ELEMENTS = 28; + static const jint INT_SIZE = 4; + static const jint TABLE_ENTRY_SIZE = 8; + jint capacity__; + jint table_base; + jint string_base; + jint string_size; + jint file_size; + jint elements; + jlong length; + ::java::io::File * name; + static const jint UNUSED_ENTRY = -1; +public: + static const jint KEYS = 0; + static const jint VALUES = 1; + static const jint ENTRIES = 2; +private: + ::java::util::HashMap * values; +public: // actually package-private + ::java::nio::channels::FileChannel * fc; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_PersistentByteMap__ diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap.java b/libjava/gnu/gcj/runtime/PersistentByteMap.java new file mode 100644 index 000000000..fec30806f --- /dev/null +++ b/libjava/gnu/gcj/runtime/PersistentByteMap.java @@ -0,0 +1,619 @@ +/* Copyright (C) 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. */ + + + +/* 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, they 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. + + 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 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; +import java.math.BigInteger; + +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 + + 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; + + static + { + 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) + { + this.mapMode = mode; + } + } + + private PersistentByteMap(File name) + { + this.name = name; + } + + public PersistentByteMap(String filename, AccessMode mode) + throws IOException + { + this(new File(filename), mode); + } + + public PersistentByteMap(File f, AccessMode mode) + throws IOException + { + name = f; + + 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 != 0x67636a64) /* "gcjd" */ + 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"); + + { + // 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 and round the result because the + // hash table is intolerably slow when more than 2/3 full. + + BigInteger size = new BigInteger(Integer.toString(((capacity*3)+1)/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; + 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); + + 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(0x67636a64, 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(); + + length = fc.size(); + string_size = 0; + } + + static public PersistentByteMap + emptyPersistentByteMap(File name, int capacity, int strtabSize) + throws IOException + { + PersistentByteMap m = new PersistentByteMap(name); + m.init(m, name, 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); + + if (elements >= capacity()) + 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 > 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"); + + 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); + + if (data.length > 16) + values.put(new ByteWrapper(data), new Integer(top - string_base)); + + return top - string_base; + } + + public Iterator iterator(int type) + { + return new HashIterator(type); + } + + public int size() + { + return elements; + } + + public int stringTableSize() + { + return string_size; + } + + public int 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() throws IOException + { + 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. */ + + 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; + } + } + + // 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.h b/libjava/gnu/gcj/runtime/SharedLibHelper.h new file mode 100644 index 000000000..b2900b7e0 --- /dev/null +++ b/libjava/gnu/gcj/runtime/SharedLibHelper.h @@ -0,0 +1,76 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_SharedLibHelper__ +#define __gnu_gcj_runtime_SharedLibHelper__ + +#pragma interface + +#include <java/lang/Object.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + class Core; + class RawData; + namespace runtime + { + class SharedLibHelper; + } + } + } + namespace java + { + namespace net + { + class URL; + } + namespace security + { + class CodeSource; + class ProtectionDomain; + } + } +} + +class gnu::gcj::runtime::SharedLibHelper : public ::java::lang::Object +{ + +public: // actually package-private + SharedLibHelper(::java::lang::String *, ::java::lang::ClassLoader *, ::java::security::CodeSource *, ::java::security::ProtectionDomain *, jint); +public: + static ::gnu::gcj::runtime::SharedLibHelper * findHelper(::java::lang::String *); +public: // actually package-private + static void copyFile(::java::io::File *, ::java::io::File *); +public: + static ::gnu::gcj::runtime::SharedLibHelper * findHelper(::java::lang::ClassLoader *, ::java::lang::String *, ::java::security::CodeSource *, jboolean); + static ::gnu::gcj::runtime::SharedLibHelper * findHelper(::java::lang::ClassLoader *, ::java::lang::String *, ::java::security::CodeSource *, ::java::security::ProtectionDomain *, jboolean); + virtual void finalize(); + virtual ::java::lang::Class * findClass(::java::lang::String *); + virtual ::java::net::URL * findResource(::java::lang::String *); + virtual ::gnu::gcj::Core * findCore(::java::lang::String *); +public: // actually package-private + virtual void ensureInit(); + virtual jboolean hasResource(::java::lang::String *); + virtual void init(); + virtual void ensureSupersLinked(::java::lang::Class *); +public: + virtual ::java::lang::String * toString(); +public: // actually package-private + virtual void registerClass(::java::lang::String *, ::java::lang::Class *); + ::gnu::gcj::RawData * __attribute__((aligned(__alignof__( ::java::lang::Object)))) handler; + ::gnu::gcj::RawData * core_chain; + ::java::util::HashMap * classMap; + ::java::lang::ClassLoader * loader; + ::java::lang::String * baseName; + ::java::security::ProtectionDomain * domain; + jint flags; + jboolean initialized; + static ::java::util::HashMap * map; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_SharedLibHelper__ diff --git a/libjava/gnu/gcj/runtime/SharedLibHelper.java b/libjava/gnu/gcj/runtime/SharedLibHelper.java new file mode 100644 index 000000000..bdf7c0453 --- /dev/null +++ b/libjava/gnu/gcj/runtime/SharedLibHelper.java @@ -0,0 +1,224 @@ +/* Copyright (C) 2001, 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. */ + +package gnu.gcj.runtime; +import java.lang.ref.WeakReference; +import java.net.URL; +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 +{ + /** Load a shared library, and associate a ClassLoader with it. + * @param libname named of shared library (passed to dlopen) + * @param parent the parent ClassLoader + * @parem flags passed to dlopen + */ + SharedLibHelper(String libname, ClassLoader parent, CodeSource source, + ProtectionDomain domain, int flags) + { + // FIXME: ask security manager first. + loader = parent; + baseName = libname; + if (domain == null) + domain = new ProtectionDomain(source, + Policy.getPolicy().getPermissions(source)); + this.domain = domain; + this.flags = flags; + } + + public static SharedLibHelper findHelper (String libname) + { + synchronized (map) + { + 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, + 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) + { + SharedLibHelper result; + Set s = (Set)map.get(libname); + if (s == null) + { + s = new HashSet(); + map.put(libname, s); + } + else + { + for (Iterator i=s.iterator(); i.hasNext();) + { + 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 (tryParents && 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); + copy.deleteOnExit(); + libname = copy.getPath(); + } + catch (IOException e) + { + return null; + } + } + result = new SharedLibHelper(libname, loader, source, domain, 0); + s.add(new WeakReference(result)); + return result; + } + } + + public native void finalize (); + + public Class findClass(String name) + { + ensureInit(); + 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) + { + ensureInit(); + if (! hasResource(name)) + return null; + try + { + return new URL("gcjlib", "", -1, baseName + "!/" + name); + } + catch (MalformedURLException _) + { + } + return null; + } + + public native Core findCore (String name); + + void ensureInit() + { + synchronized (classMap) + { + if (initialized) + return; + init(); + initialized = true; + } + } + + 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) + { + classMap.put(name, cls); + } + + /** The handle returned by dlopen. */ + gnu.gcj.RawData handler; + + /** Holds a _Jv_core_chain for the loader. */ + gnu.gcj.RawData core_chain; + + /** Map classnames to Classes. */ + HashMap classMap = new HashMap(20); + + /** Class loader we're helping. */ + ClassLoader loader; + + /** Name of base file. */ + String baseName; + + /** Protection domain for loaded classes. */ + ProtectionDomain domain; + + /** Flags to pass to dlopen. FIXME: platform dependent. + 0 is always "sensible" (defined by us). */ + int flags; + + /** True if we've been initialized. */ + boolean initialized = false; + + /** Map shared library names to a helper object. This uses weak + references in the values so we don't prevent collection. */ + static HashMap map = new HashMap (); +} diff --git a/libjava/gnu/gcj/runtime/SharedLibLoader.h b/libjava/gnu/gcj/runtime/SharedLibLoader.h new file mode 100644 index 000000000..8a439d3d3 --- /dev/null +++ b/libjava/gnu/gcj/runtime/SharedLibLoader.h @@ -0,0 +1,47 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_SharedLibLoader__ +#define __gnu_gcj_runtime_SharedLibLoader__ + +#pragma interface + +#include <java/lang/ClassLoader.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class SharedLibHelper; + class SharedLibLoader; + } + } + } + namespace java + { + namespace net + { + class URL; + } + } +} + +class gnu::gcj::runtime::SharedLibLoader : public ::java::lang::ClassLoader +{ + +public: + SharedLibLoader(::java::lang::String *, ::java::lang::ClassLoader *, jint); + SharedLibLoader(::java::lang::String *); + virtual ::java::lang::Class * findClass(::java::lang::String *); + virtual ::java::net::URL * findResource(::java::lang::String *); + virtual ::java::util::Enumeration * findResources(::java::lang::String *); +public: // actually package-private + ::gnu::gcj::runtime::SharedLibHelper * __attribute__((aligned(__alignof__( ::java::lang::ClassLoader)))) helper; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_SharedLibLoader__ diff --git a/libjava/gnu/gcj/runtime/SharedLibLoader.java b/libjava/gnu/gcj/runtime/SharedLibLoader.java new file mode 100644 index 000000000..b8e6a57de --- /dev/null +++ b/libjava/gnu/gcj/runtime/SharedLibLoader.java @@ -0,0 +1,79 @@ +/* Copyright (C) 2001, 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. */ + +package gnu.gcj.runtime; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.CodeSource; +import java.util.Enumeration; +import java.util.Vector; + +/** + * A ClassLoader backed by a gcj-compiled shared library. + * @author Per Bothner <per@bothner.com>, Brainfood Inc. + */ + +public class SharedLibLoader extends ClassLoader +{ + /** Load a shared library, and associate a ClassLoader with it. + * @param libname named of shared library (passed to dlopen) + * @param parent the parent ClassLoader + * @parem flags passed to dlopen + */ + public SharedLibLoader(String libname, ClassLoader parent, int flags) + { + super(parent); + URL url; + try + { + url = new URL("file", "", libname); + } + catch (MalformedURLException _) + { + url = null; + } + helper = SharedLibHelper.findHelper(this, libname, + new CodeSource(url, null), true); + } + + /** Load a shared library, and asociate a ClassLoader with it. + * @param libname named of shared library (passed to dlopen) + */ + public SharedLibLoader(String libname) + { + this(libname, getSystemClassLoader(), 0); + } + + public Class findClass(String name) + throws ClassNotFoundException + { + Class cls = helper.findClass(name); + if (cls == null) + throw new ClassNotFoundException(name); + return cls; + } + + public URL findResource (String name) + { + return helper.findResource(name); + } + + public Enumeration findResources (String name) throws IOException + { + URL url = findResource(name); + if (url == null) + return null; + Vector v = new Vector(1); + v.add(url); + return v.elements(); + } + + /** The helper that does the work for us. */ + SharedLibHelper helper; +} diff --git a/libjava/gnu/gcj/runtime/StringBuffer.h b/libjava/gnu/gcj/runtime/StringBuffer.h new file mode 100644 index 000000000..27a3a7e30 --- /dev/null +++ b/libjava/gnu/gcj/runtime/StringBuffer.h @@ -0,0 +1,54 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_StringBuffer__ +#define __gnu_gcj_runtime_StringBuffer__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class StringBuffer; + } + } + } +} + +class gnu::gcj::runtime::StringBuffer : public ::java::lang::Object +{ + +public: + ::gnu::gcj::runtime::StringBuffer * append(jboolean); + ::gnu::gcj::runtime::StringBuffer * append(jchar); + ::gnu::gcj::runtime::StringBuffer * append(jint); + ::gnu::gcj::runtime::StringBuffer * append(jlong); + ::gnu::gcj::runtime::StringBuffer * append(jfloat); + ::gnu::gcj::runtime::StringBuffer * append(jdouble); + ::gnu::gcj::runtime::StringBuffer * append(::java::lang::Object *); + ::gnu::gcj::runtime::StringBuffer * append(::java::lang::String *); +private: + void ensureCapacity_unsynchronized(jint); +public: + StringBuffer(); + StringBuffer(jint); + StringBuffer(::java::lang::String *); + ::java::lang::String * toString(); +public: // actually package-private + jint __attribute__((aligned(__alignof__( ::java::lang::Object)))) count; + JArray< jchar > * value; +private: + static const jint DEFAULT_CAPACITY = 16; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_StringBuffer__ diff --git a/libjava/gnu/gcj/runtime/StringBuffer.java b/libjava/gnu/gcj/runtime/StringBuffer.java new file mode 100644 index 000000000..f9a433e5a --- /dev/null +++ b/libjava/gnu/gcj/runtime/StringBuffer.java @@ -0,0 +1,199 @@ +// This is a simplified copy of java.lang.StringBuffer with +// `synchronized' removed. + +/* StringBuffer.java -- Growable strings + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + +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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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 gnu.gcj.runtime; + +public final class StringBuffer +{ + /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. + * Uses <code>String.valueOf()</code> to convert to + * <code>String</code>. + * @param bool the <code>boolean</code> to convert and append. + * @return this <code>StringBuffer</code>. + * @see java.lang.String#valueOf(boolean) + */ + public StringBuffer append (boolean bool) + { + return append (bool ? "true" : "false"); + } + + /** Append the <code>char</code> to this <code>StringBuffer</code>. + * @param c the <code>char</code> to append. + * @return this <code>StringBuffer</code>. + */ + public StringBuffer append (char ch) + { + ensureCapacity_unsynchronized (count + 1); + value[count++] = ch; + return this; + } + + /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. + * Uses <code>String.valueOf()</code> to convert to + * <code>String</code>. + * @param inum the <code>int</code> to convert and append. + * @return this <code>StringBuffer</code>. + * @see java.lang.String#valueOf(int) + */ + public native StringBuffer append (int inum); + + /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. + * Uses <code>String.valueOf()</code> to convert to + * <code>String</code>. + * @param lnum the <code>long</code> to convert and append. + * @return this <code>StringBuffer</code>. + * @see java.lang.String#valueOf(long) + */ + public StringBuffer append (long lnum) + { + return append (Long.toString (lnum)); + } + + /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. + * Uses <code>String.valueOf()</code> to convert to + * <code>String</code>. + * @param fnum the <code>float</code> to convert and append. + * @return this <code>StringBuffer</code>. + * @see java.lang.String#valueOf(float) + */ + public StringBuffer append (float fnum) + { + return append (Float.toString (fnum)); + } + + /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. + * Uses <code>String.valueOf()</code> to convert to + * <code>String</code>. + * @param dnum the <code>double</code> to convert and append. + * @return this <code>StringBuffer</code>. + * @see java.lang.String#valueOf(double) + */ + public StringBuffer append (double dnum) + { + return append (Double.toString (dnum)); + } + + /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. + * Uses <code>String.valueOf()</code> to convert to + * <code>String</code>. + * @param obj the <code>Object</code> to convert and append. + * @return this <code>StringBuffer</code>. + * @see java.lang.String#valueOf(java.lang.Object) + */ + public StringBuffer append (Object obj) + { + return append (String.valueOf(obj)); + } + + /** Append the <code>String</code> to this <code>StringBuffer</code>. + * @param str the <code>String</code> to append. + * @return this <code>StringBuffer</code>. + */ + public StringBuffer append (String str) + { + if (str == null) + str = "null"; + int len = str.length(); + ensureCapacity_unsynchronized (count + len); + str.getChars(0, len, value, count); + count += len; + return this; + } + + private void ensureCapacity_unsynchronized (int minimumCapacity) + { + if (minimumCapacity > value.length) + { + minimumCapacity = Math.max (minimumCapacity, value.length * 2 + 2); + char[] nb = new char[minimumCapacity]; + System.arraycopy(value, 0, nb, 0, count); + value = nb; + } + } + + /** Create a new StringBuffer with default capacity 16. + * @see JLS 20.13.1 + */ + public StringBuffer () + { + this (DEFAULT_CAPACITY); + } + + /** Create an empty <code>StringBuffer</code> with the specified initial capacity. + * @param capacity the initial capacity. + */ + public StringBuffer (int capacity) + { + count = 0; + value = new char[capacity]; + } + + /** Create a new <code>StringBuffer</code> with the characters in the specified <code>String</code>. + * Initial capacity will be the size of the String plus 16. + * @param str the <code>String</code> to make a <code>StringBuffer</code> out of. + */ + public StringBuffer (String str) + { + if (str == null) + str = "null"; + count = str.length(); + // JLS: The initial capacity of the string buffer is 16 plus the + // length of the argument string. + value = new char[count + DEFAULT_CAPACITY]; + str.getChars(0, count, value, 0); + } + + /** Convert this <code>StringBuffer</code> to a <code>String</code>. + * @return the characters in this StringBuffer + */ + // This is native because efficient implementation requires avoiding + // the Java protection mechanism. + public native String toString (); + + // Index of next available character. Note that this has + // permissions set this way so that String can get the value. + int count; + + // The buffer. Note that this has permissions set this way so that + // String can get the value. + char[] value; + + private final static int DEFAULT_CAPACITY = 16; // JLS 20.13.1 +} diff --git a/libjava/gnu/gcj/runtime/SystemClassLoader.h b/libjava/gnu/gcj/runtime/SystemClassLoader.h new file mode 100644 index 000000000..58c709659 --- /dev/null +++ b/libjava/gnu/gcj/runtime/SystemClassLoader.h @@ -0,0 +1,40 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __gnu_gcj_runtime_SystemClassLoader__ +#define __gnu_gcj_runtime_SystemClassLoader__ + +#pragma interface + +#include <java/net/URLClassLoader.h> +extern "Java" +{ + namespace gnu + { + namespace gcj + { + namespace runtime + { + class SystemClassLoader; + } + } + } +} + +class gnu::gcj::runtime::SystemClassLoader : public ::java::net::URLClassLoader +{ + +public: // actually package-private + SystemClassLoader(::java::lang::ClassLoader *); + void addClass(::java::lang::Class *); +public: // actually protected + ::java::lang::Class * findClass(::java::lang::String *); +public: // actually package-private + void init(); +private: + ::java::util::HashMap * __attribute__((aligned(__alignof__( ::java::net::URLClassLoader)))) nativeClasses; +public: + static ::java::lang::Class class$; +}; + +#endif // __gnu_gcj_runtime_SystemClassLoader__ diff --git a/libjava/gnu/gcj/runtime/SystemClassLoader.java b/libjava/gnu/gcj/runtime/SystemClassLoader.java new file mode 100644 index 000000000..7470542cb --- /dev/null +++ b/libjava/gnu/gcj/runtime/SystemClassLoader.java @@ -0,0 +1,113 @@ +/* Copyright (C) 2005, 2006 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.*; +import java.lang.reflect.Field; +import java.util.StringTokenizer; +import java.util.HashMap; +import java.net.URL; +import java.net.URLClassLoader; + +public final class SystemClassLoader extends URLClassLoader +{ + SystemClassLoader(ClassLoader parent) + { + super(new URL[0], parent); + } + + // This holds all the "native" classes linked into the executable + // and registered with this loader. + private HashMap nativeClasses = new HashMap(); + + // This is called to register a native class which was linked into + // the application but which is registered with the system class + // loader after the VM is initialized. + void addClass(Class klass) + { + String packageName = null; + String className = klass.getName(); + int lastDot = className.lastIndexOf('.'); + if (lastDot != -1) + packageName = className.substring(0, lastDot); + if (packageName != null && getPackage(packageName) == null) + { + // Should have some way to store this information in a + // precompiled manifest. + definePackage(packageName, null, null, null, null, null, null, null); + } + + // Use reflection to access the package-private "loadedClasses" field. + nativeClasses.put(className, klass); + } + + protected native Class findClass(String name); + + // We add the URLs to the system class loader late. The reason for + // this is that during bootstrap we don't want to parse URLs or + // create URL connections, since that will result in circularities + // causing a crash. + void init() + { + String sep = File.pathSeparator; + StringTokenizer st + = new StringTokenizer (System.getProperty ("java.class.path", "."), + sep, true); + // Pretend we start with a ':', so if we see a ':' first we add + // '.'. + boolean last_was_sep = true; + while (st.hasMoreElements ()) + { + String e = st.nextToken (); + try + { + if (sep.equals(e)) + { + if (last_was_sep) + { + // We saw two separators in a row, so add ".". + addURL(new URL("file", "", -1, "./")); + last_was_sep = false; + } + else + last_was_sep = true; + continue; + } + + last_was_sep = false; + File path = new File(e); + // Ignore invalid paths. + if (!path.exists()) + continue; + if (!e.endsWith (File.separator) && path.isDirectory ()) + addURL(new URL("file", "", -1, e + File.separator)); + else + addURL(new URL("file", "", -1, e)); + } + catch (java.net.MalformedURLException x) + { + // This should never happen. + throw new RuntimeException(x); + } + } + // If we saw a trailing ":", add "." to the path. + if (last_was_sep) + { + try + { + addURL(new URL("file", "", -1, "./")); + } + catch (java.net.MalformedURLException x) + { + // This should never happen. + throw new RuntimeException(x); + } + } + } +} diff --git a/libjava/gnu/gcj/runtime/natFinalizerThread.cc b/libjava/gnu/gcj/runtime/natFinalizerThread.cc new file mode 100644 index 000000000..ec1846baf --- /dev/null +++ b/libjava/gnu/gcj/runtime/natFinalizerThread.cc @@ -0,0 +1,62 @@ +// natFinalizerThread.cc - Implementation of FinalizerThread native methods. + +/* Copyright (C) 2001, 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. */ + +#include <config.h> + +#include <gcj/cni.h> +#include <jvm.h> + +#include <gnu/gcj/runtime/FinalizerThread.h> + +#include <java-threads.h> + +static _Jv_Mutex_t mutex; +static _Jv_ConditionVariable_t condition; + +// Initialize lock & condition variable. +void +gnu::gcj::runtime::FinalizerThread::init () +{ + _Jv_MutexInit (&mutex); + _Jv_CondInit (&condition); +} + +// This is called by the GC when a finalizer is ready to be +// run. It sets a flag and wakes up the finalizer thread. Note +// that this MUST NOT aquire any Java lock, as this could result in +// the hash synchronization code being re-entered: the synchronization +// code itself might need to allocate. See PR 16478. +void +gnu::gcj::runtime::FinalizerThread::finalizerReady () +{ +#ifdef __JV_NO_THREADS__ + _Jv_RunFinalizers (); +#else + _Jv_MutexLock (&mutex); + finalizer_ready = true; + _Jv_CondNotify (&condition, &mutex); + _Jv_MutexUnlock (&mutex); +#endif +} + +// Main loop for the finalizer thread. +void +gnu::gcj::runtime::FinalizerThread::run () +{ + while (true) + { + _Jv_MutexLock (&mutex); + if (! finalizer_ready) + _Jv_CondWait (&condition, &mutex, 0, 0); + finalizer_ready = false; + _Jv_MutexUnlock (&mutex); + _Jv_RunFinalizers (); + } +} diff --git a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc new file mode 100644 index 000000000..5ae6842d6 --- /dev/null +++ b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc @@ -0,0 +1,151 @@ +// natSharedLibLoader.cc - Implementation of SharedLibHelper native methods. + +/* Copyright (C) 2001, 2003, 2004, 2005, 2006, 2010 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 <platform.h> + +#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> +#include <java/lang/UnknownError.h> + +#include <java/lang/VMClassLoader.h> + +// If we're using the Boehm GC, then we need this include to override dlopen. +#ifdef HAVE_BOEHM_GC +// Set GC_DEBUG before including gc.h! +#ifdef LIBGCJ_GC_DEBUG +# define GC_DEBUG +#endif +#include <gc.h> +#endif /* HAVE_BOEHM_GC */ + +#ifdef HAVE_DLOPEN +#include <dlfcn.h> + +/* Only used during dlopen, while having a lock on Class.class. */ +static java::lang::ClassLoader *curLoader; +static gnu::gcj::runtime::SharedLibHelper *curHelper; + +typedef void (*ClassHookFunc) (jclass); +typedef void (*CoreHookFunc) (_Jv_core_chain *); + +void +_Jv_sharedlib_register_hook (jclass cls) +{ + cls->protectionDomain = curHelper->domain; + cls->loader = curLoader; + if (! cls->engine) + cls->engine = &_Jv_soleCompiledEngine; + curHelper->registerClass(cls->getName(), cls); +} + +static void +core_hook (_Jv_core_chain *chain) +{ + chain->next = (_Jv_core_chain *) curHelper->core_chain; + curHelper->core_chain = (gnu::gcj::RawData *) chain; +} + +struct SharedLibDummy +{ + ClassHookFunc saved; + CoreHookFunc saved_core; + SharedLibDummy() + { + saved = _Jv_RegisterClassHook; + saved_core = _Jv_RegisterCoreHook; + } + ~SharedLibDummy() + { + _Jv_RegisterClassHook = saved; + _Jv_RegisterCoreHook = saved_core; + curLoader = NULL; + } +}; +#endif + +void +gnu::gcj::runtime::SharedLibHelper::init(void) +{ +#ifdef HAVE_DLOPEN + char *lname = (char *) __builtin_alloca (JvGetStringUTFLength (baseName) + + 1); + jsize total = JvGetStringUTFRegion (baseName, 0, baseName->length(), lname); + lname[total] = '\0'; + + if (flags==0) + flags = RTLD_GLOBAL | RTLD_LAZY; + JvSynchronize dummy1(&::java::lang::Class::class$); + SharedLibDummy dummy2; + curLoader = ((void*)loader == ::java::lang::VMClassLoader::bootLoader + ? NULL : loader); + curHelper = this; + _Jv_RegisterClassHook = _Jv_sharedlib_register_hook; + _Jv_RegisterCoreHook = core_hook; + void *h = dlopen(lname, flags); + if (h == NULL) + { + const char *msg = dlerror(); + throw new ::java::lang::UnknownError(JvNewStringLatin1(msg)); + } + handler = (gnu::gcj::RawData*) h; +#else + const char *msg + = "shared library class loading is not supported on this platform"; + throw new ::java::lang::UnsupportedOperationException(JvNewStringLatin1(msg)); +#endif +} + +jboolean +gnu::gcj::runtime::SharedLibHelper::hasResource (jstring name) +{ +#ifdef HAVE_DLOPEN + _Jv_core_chain *node = _Jv_FindCore ((_Jv_core_chain *) core_chain, name); + return node != NULL; +#else + return false; +#endif +} + +#ifdef HAVE_DLOPEN +extern gnu::gcj::Core *_Jv_create_core (_Jv_core_chain *node, jstring name); +#endif + +gnu::gcj::Core * +gnu::gcj::runtime::SharedLibHelper::findCore (jstring name) +{ +#ifdef HAVE_DLOPEN + ensureInit(); + return _Jv_create_core ((_Jv_core_chain *) core_chain, name); +#else + return NULL; +#endif +} + +void +gnu::gcj::runtime::SharedLibHelper::finalize() +{ + _Jv_FreeCoreChain ((_Jv_core_chain *) core_chain); +#ifdef HAVE_DLOPEN + if (handler) + 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/runtime/natStringBuffer.cc b/libjava/gnu/gcj/runtime/natStringBuffer.cc new file mode 100644 index 000000000..2777b9ed8 --- /dev/null +++ b/libjava/gnu/gcj/runtime/natStringBuffer.cc @@ -0,0 +1,36 @@ +// natStringBuffer.cc - Implementation of java.lang.StringBuffer native methods. + +/* Copyright (C) 2001 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 <gnu/gcj/runtime/StringBuffer.h> +#include <java/lang/String.h> + +gnu::gcj::runtime::StringBuffer * +gnu::gcj::runtime::StringBuffer::append (jint num) +{ + // Use an array large enough for "-2147483648"; i.e. 11 chars. + jchar buffer[11]; + int i = _Jv_FormatInt (buffer+11, num); + jint needed = count + i; + ensureCapacity_unsynchronized (needed); + jchar* dst = elements (value) + count; + jchar* src = buffer+11-i; + while (--i >= 0) + *dst++ = *src++; + count = needed; + return this; +} + +java::lang::String * +gnu::gcj::runtime::StringBuffer::toString () +{ + return new java::lang::String (this); +} diff --git a/libjava/gnu/gcj/runtime/natSystemClassLoader.cc b/libjava/gnu/gcj/runtime/natSystemClassLoader.cc new file mode 100644 index 000000000..7052bc8e8 --- /dev/null +++ b/libjava/gnu/gcj/runtime/natSystemClassLoader.cc @@ -0,0 +1,31 @@ +// natSystemClassLoader.cc - native code for system class loader + +/* Copyright (C) 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 <platform.h> + +#include <gcj/cni.h> +#include <jvm.h> +#include <execution.h> + +#include <gnu/gcj/runtime/SystemClassLoader.h> +#include <java/lang/ClassNotFoundException.h> +#include <java/util/HashMap.h> + +jclass +gnu::gcj::runtime::SystemClassLoader::findClass (jstring name) +{ + jclass result = (jclass) nativeClasses->get(name); + if (! result) + return URLClassLoader::findClass(name); + // Never return a class whose supers are not installed. + _Jv_Linker::wait_for_state (result, JV_STATE_LOADING); + return result; +} |