Index: libjava/classpath/ChangeLog =================================================================== --- libjava/classpath/ChangeLog (revision 140746) +++ libjava/classpath/ChangeLog (working copy) @@ -1,15 +1,15 @@ 2008-09-14 Andrew John Hughes - * examples/Makefile.am: + * examples/Makefile.am: Check lib directly as well as glibj.zip for boot classes. - * m4/acinclude.m4: + * m4/acinclude.m4: Only require the class files to be built to allow the tools and examples to be built, not the installation of glibj.zip. - * tools/Makefile.am: - Check lib directly as well as glibj.zip - for boot classes. + * tools/Makefile.am: + Check lib directly as well as glibj.zip + for boot classes. 2008-09-13 Andrew John Hughes @@ -26,6 +26,16 @@ * tools/Makefile.am: Add GCJ rules. +2007-08-23 Daniel Frampton + + * AUTHORS: Added. + * java/lang/InheritableThreadLocal.java, + * java/lang/Thread.java, + * java/lang/ThreadLocal.java: + Modified to use java.lang.ThreadLocalMap. + * java/lang/ThreadLocalMap.java: + New cheaper ThreadLocal-specific WeakHashMap. + 2008-02-07 Ian Rogers * java/util/zip/ZipEntry.java: Index: libjava/classpath/lib/java/lang/Thread.class =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libjava/classpath/lib/java/lang/ThreadLocal.class =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libjava/classpath/lib/java/lang/InheritableThreadLocal.class =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: libjava/classpath/java/lang/Thread.java =================================================================== --- libjava/classpath/java/lang/Thread.java (revision 140746) +++ libjava/classpath/java/lang/Thread.java (working copy) @@ -159,7 +159,7 @@ /** Thread local storage. Package accessible for use by * InheritableThreadLocal. */ - WeakIdentityHashMap locals; + final ThreadLocalMap locals; /** The uncaught exception handler. */ UncaughtExceptionHandler exceptionHandler; @@ -367,6 +367,7 @@ this.name = name.toString(); this.runnable = target; this.stacksize = size; + this.locals = new ThreadLocalMap(); synchronized (Thread.class) { @@ -398,6 +399,7 @@ */ Thread(VMThread vmThread, String name, int priority, boolean daemon) { + this.locals = new ThreadLocalMap(); this.vmThread = vmThread; this.runnable = null; if (name == null) @@ -1063,21 +1065,15 @@ { group.removeThread(this); vmThread = null; - locals = null; + locals.clear(); } /** * Returns the map used by ThreadLocal to store the thread local values. */ - static Map getThreadLocals() + static ThreadLocalMap getThreadLocals() { - Thread thread = currentThread(); - Map locals = thread.locals; - if (locals == null) - { - locals = thread.locals = new WeakIdentityHashMap(); - } - return locals; + return currentThread().locals; } /** Index: libjava/classpath/java/lang/InheritableThreadLocal.java =================================================================== --- libjava/classpath/java/lang/InheritableThreadLocal.java (revision 140746) +++ libjava/classpath/java/lang/InheritableThreadLocal.java (working copy) @@ -37,10 +37,6 @@ package java.lang; -import gnu.java.util.WeakIdentityHashMap; - -import java.util.Iterator; - /** * A ThreadLocal whose value is inherited by child Threads. The value of the * InheritableThreadLocal associated with the (parent) Thread is copied to @@ -97,24 +93,6 @@ { // The currentThread is the parent of the new thread. Thread parentThread = Thread.currentThread(); - if (parentThread.locals != null) - { - Iterator keys = parentThread.locals.keySet().iterator(); - while (keys.hasNext()) - { - Object key = keys.next(); - if (key instanceof InheritableThreadLocal) - { - InheritableThreadLocal local = (InheritableThreadLocal)key; - Object parentValue = parentThread.locals.get(key); - Object childValue = local.childValue(parentValue == sentinel - ? null : parentValue); - if (childThread.locals == null) - childThread.locals = new WeakIdentityHashMap(); - childThread.locals.put(key, (childValue == null - ? sentinel : childValue)); - } - } - } + childThread.locals.inherit(parentThread.locals); } } Index: libjava/classpath/java/lang/ThreadLocal.java =================================================================== --- libjava/classpath/java/lang/ThreadLocal.java (revision 140746) +++ libjava/classpath/java/lang/ThreadLocal.java (working copy) @@ -37,9 +37,6 @@ package java.lang; -import java.util.Map; - - /** * ThreadLocal objects have a different state associated with every * Thread that accesses them. Every access to the ThreadLocal object @@ -93,13 +90,31 @@ * user. Do not expose this to the public. Package visible for use by * InheritableThreadLocal */ - static final Object sentinel = new Object(); + static final Object notFound = new Object(); /** + * The base for the computation of the next hash for a thread local. + */ + private static int nextHashBase = 1; + + /** + * Allocate a new hash. + */ + private synchronized int computeNextHash() { + return nextHashBase++ * 6709; + } + + /** + * Hash code computed for ThreadLocalMap + */ + final int fastHash; + + /** * Creates a ThreadLocal object without associating any value to it yet. */ public ThreadLocal() { + fastHash = computeNextHash(); } /** @@ -125,16 +140,16 @@ */ public T get() { - Map,T> map = (Map,T>) Thread.getThreadLocals(); + ThreadLocalMap map = Thread.getThreadLocals(); // Note that we don't have to synchronize, as only this thread will // ever modify the map. - T value = map.get(this); - if (value == null) + T value = (T) map.get(this); + if (value == notFound) { value = initialValue(); - map.put(this, (T) (value == null ? sentinel : value)); + map.set(this, value); } - return value == (T) sentinel ? null : value; + return value; } /** @@ -147,10 +162,10 @@ */ public void set(T value) { - Map map = Thread.getThreadLocals(); + ThreadLocalMap map = Thread.getThreadLocals(); // Note that we don't have to synchronize, as only this thread will // ever modify the map. - map.put(this, value == null ? sentinel : value); + map.set(this, value); } /** @@ -160,7 +175,7 @@ */ public void remove() { - Map map = Thread.getThreadLocals(); + ThreadLocalMap map = Thread.getThreadLocals(); map.remove(this); } } Index: libjava/gcj/javaprims.h =================================================================== --- libjava/gcj/javaprims.h (revision 140746) +++ libjava/gcj/javaprims.h (working copy) @@ -240,6 +240,8 @@ class ThreadDeath; class ThreadGroup; class ThreadLocal; + class ThreadLocalMap; + class ThreadLocalMap$Entry; class Throwable; class Throwable$StaticData; class TypeNotPresentException; Index: libjava/java/lang/Thread.h =================================================================== --- libjava/java/lang/Thread.h (revision 140746) +++ libjava/java/lang/Thread.h (working copy) @@ -18,13 +18,6 @@ class RawData; class RawDataManaged; } - namespace java - { - namespace util - { - class WeakIdentityHashMap; - } - } } } @@ -100,7 +93,7 @@ void initialize_native(); static ::java::lang::String * gen_name(); public: // actually package-private - static ::java::util::Map * getThreadLocals(); + static ::java::lang::ThreadLocalMap * getThreadLocals(); public: virtual void setUncaughtExceptionHandler(::java::lang::Thread$UncaughtExceptionHandler *); virtual ::java::lang::Thread$UncaughtExceptionHandler * getUncaughtExceptionHandler(); @@ -135,7 +128,7 @@ static jlong totalThreadsCreated; static ::java::lang::Thread$UncaughtExceptionHandler * defaultHandler; public: // actually package-private - ::gnu::java::util::WeakIdentityHashMap * locals; + ::java::lang::ThreadLocalMap * locals; ::java::lang::Thread$UncaughtExceptionHandler * exceptionHandler; private: ::java::lang::Object * parkBlocker; Index: libjava/java/lang/ThreadLocal.h =================================================================== --- libjava/java/lang/ThreadLocal.h (revision 140746) +++ libjava/java/lang/ThreadLocal.h (working copy) @@ -21,6 +21,7 @@ class java::lang::ThreadLocal : public ::java::lang::Object { + jint computeNextHash(); public: ThreadLocal(); public: // actually protected @@ -44,7 +45,11 @@ public: // actually package-private static ::java::lang::Object * sentinel; private: - ::gnu::gcj::RawData * __attribute__((aligned(__alignof__( ::java::lang::Object)))) TLSPointer; + static jint nextHashBase; +public: // actually package-private + jint __attribute__((aligned(__alignof__( ::java::lang::Object)))) fastHash; +private: + ::gnu::gcj::RawData * TLSPointer; public: static ::java::lang::Class class$; }; Index: libjava/java/lang/Thread.java =================================================================== --- libjava/java/lang/Thread.java (revision 140746) +++ libjava/java/lang/Thread.java (working copy) @@ -160,7 +160,7 @@ /** Thread local storage. Package accessible for use by * InheritableThreadLocal. */ - WeakIdentityHashMap locals; + ThreadLocalMap locals; /** The uncaught exception handler. */ UncaughtExceptionHandler exceptionHandler; @@ -1019,13 +1019,13 @@ /** * Returns the map used by ThreadLocal to store the thread local values. */ - static Map getThreadLocals() + static ThreadLocalMap getThreadLocals() { Thread thread = currentThread(); - Map locals = thread.locals; + ThreadLocalMap locals = thread.locals; if (locals == null) { - locals = thread.locals = new WeakIdentityHashMap(); + locals = thread.locals = new ThreadLocalMap(); } return locals; } Index: libjava/java/lang/ThreadLocal.java =================================================================== --- libjava/java/lang/ThreadLocal.java (revision 140746) +++ libjava/java/lang/ThreadLocal.java (working copy) @@ -96,11 +96,30 @@ static final Object sentinel = new Object(); /** + * The base for the computation of the next hash for a thread local. + */ + private static int nextHashBase = 1; + + /** + * Allocate a new hash. + */ + private synchronized int computeNextHash() + { + return nextHashBase++ * 6709; + } + + /** + * Hash code computed for ThreadLocalMap + */ + final int fastHash; + + /** * Creates a ThreadLocal object without associating any value to it yet. */ public ThreadLocal() { constructNative(); + fastHash = computeNextHash(); } /** @@ -128,16 +147,16 @@ private final Object internalGet() { - Map,T> map = (Map,T>) Thread.getThreadLocals(); + ThreadLocalMap map = Thread.getThreadLocals(); // Note that we don't have to synchronize, as only this thread will // ever modify the map. - T value = map.get(this); - if (value == null) + T value = (T) map.get(this); + if (value == sentinel) { value = initialValue(); - map.put(this, (T) (value == null ? sentinel : value)); + map.set(this, value); } - return value == (T) sentinel ? null : value; + return value; } /** @@ -152,10 +171,10 @@ private final void internalSet(Object value) { - Map map = Thread.getThreadLocals(); + ThreadLocalMap map = Thread.getThreadLocals(); // Note that we don't have to synchronize, as only this thread will // ever modify the map. - map.put(this, value == null ? sentinel : value); + map.set(this, value); } /** @@ -167,7 +186,7 @@ private final void internalRemove() { - Map map = Thread.getThreadLocals(); + ThreadLocalMap map = Thread.getThreadLocals(); map.remove(this); }