Re: [cp-patches] [PATCH] Fix raw type references in AnnotationInvocationHandler
On 12 October 2011 03:52, Mark Wielaard m...@klomp.org wrote: On Wed, 2011-10-12 at 10:29 +0300, Pekka Enberg wrote: On Wed, Oct 12, 2011 at 1:28 AM, Dr Andrew John Hughes ahug...@redhat.com wrote: If we're going to change that, it should happen after the next release and with plenty of discussion / heads up for VMs. Right. I guess I could send patches for JamVM, CACAO, and Jato as well. Are there other VMs we care about? JikesRVM and GCJ of course! Although they only use part of the VM interface at this time. There is a somewhat full list at: https://www.gnu.org/software/classpath/stories.html#jvm Some of those are somewhat in hibernation though. Heay, and JATO is missing... And if we are going to extend/adapt the VM interface anyway, it would not harm to work on the Common Virtual Machine Interface (CVMI) project http://icedtea.classpath.org/wiki/CVMIDiscussion (Heay, I can dream :) Cheers, Mark Jikes RVM is woefully out-of-date wrt Classpath, MRP (http://mrp.codehaus.org/) isn't :-) Regards, Ian
Re: netif.h present but unusable on Mac
Hi Richard, Jikes RVM is using an older version of Classpath than what is current. MRP [1] (derived from Jikes RVM) uses the latest GNU Classpath. You may want to try this as an alternative, although currently you'll need to download MRP using git. Regards, Ian [1] http://mrp.codehaus.org/ 2009/11/22 Richard O'Keefe o...@cs.otago.ac.nz: The host is an Intel Core 2 Duo processor running Mac OS X version 10.5.7 I downloaded the JikesRVM version 3.1.0 and having checked that ia32-osx was supported set out to build it. The manual says that it needs GNU Classpath, and that I should download and install that by doing ant -f build/components/classpath.xml, which I did. [exec] checking ifaddrs.h usability... yes [exec] checking ifaddrs.h presence... yes [exec] checking for ifaddrs.h... yes [exec] checking netinet/in_systm.h usability... yes [exec] checking netinet/in_systm.h presence... yes [exec] checking for netinet/in_systm.h... yes [exec] checking netinet/ip.h usability... yes [exec] checking netinet/ip.h presence... yes [exec] checking for netinet/ip.h... yes [exec] checking net/if.h usability... no [exec] checking net/if.h presence... yes [exec] configure: WARNING: net/if.h: present but cannot be compiled [exec] configure: WARNING: net/if.h: check for missing prerequisite headers? [exec] configure: WARNING: net/if.h: see the Autoconf documentation [exec] configure: WARNING: net/if.h: section Present But Cannot Be Compiled [exec] configure: WARNING: net/if.h: proceeding with the preprocessor's result [exec] configure: WARNING: net/if.h: in the future, the compiler will take precedence [exec] configure: WARNING: ## ## [exec] configure: WARNING: ## Report this to classpath@gnu.org ## [exec] configure: WARNING: ## ## [exec] checking for net/if.h... yes There was a further problem later down where the Ant script said [exec] configure: error: The Java compiler /home/cshome/o/ok/Desktop/jikesrvm-3.1.0/components/ecj/3.2/ecj-3.2/ecj failed (see config.log, check the CLASSPATH?) [exec] checking if /home/cshome/o/ok/Desktop/jikesrvm-3.1.0/components/ecj/3.2/ecj-3.2/ecj works... Since ...components/ecj doesn't exist, it's not surprising that it doesn't work. This leads me to suspect a problem with the Ant script.
Re: [cp-patches] FYI: Add VM updates in 0.98
Hi, I've attached a revision for the reflection classes that is applied to Jikes RVM and has been updated for 0.98. This patch removes the messy backlink mechanism in reflection and better supports eliminating reflection overhead in Jikes RVM. Due to the problems it would cause to VMs thought is needed before applying the patch. Regards, Ian 2009/2/9 Nicolas Geoffray nicolas.geoff...@menlina.com: Hi Andrew, Andrew John Hughes wrote: This updates NEWS with the VM updates in 0.98. 2009-02-05 Andrew John Hughes ahug...@redhat.com * NEWS: Add VM updates. So I guess it's too late now, but forgot to talk about VMField, VMMethod and VMConstructor which I think are new in 0.98. Cheers, Nicolas Index: java/lang/reflect/Constructor.java === RCS file: /sources/classpath/classpath/java/lang/reflect/Constructor.java,v retrieving revision 1.10 diff -u -r1.10 Constructor.java --- java/lang/reflect/Constructor.java 23 Jun 2008 20:59:35 - 1.10 +++ java/lang/reflect/Constructor.java 18 Aug 2008 17:14:28 - @@ -95,7 +95,6 @@ Constructor(VMConstructor cons) { this.cons = cons; -cons.cons = this; } private Constructor() @@ -316,7 +315,7 @@ { // Inescapable as the VM layer is 1.4 based. @SuppressWarnings(unchecked) - T ins = (T) cons.construct(args); + T ins = (T) cons.construct(args, this); return ins; } Index: java/lang/reflect/Field.java === RCS file: /sources/classpath/classpath/java/lang/reflect/Field.java,v retrieving revision 1.10 diff -u -r1.10 Field.java --- java/lang/reflect/Field.java 23 Jun 2008 20:59:35 - 1.10 +++ java/lang/reflect/Field.java 18 Aug 2008 17:14:28 - @@ -96,7 +96,6 @@ Field(VMField f) { this.f = f; -f.f = this; } /** @@ -257,7 +256,7 @@ public Object get(Object o) throws IllegalAccessException { -return f.get(o); +return f.get(this, o); } /** @@ -280,7 +279,7 @@ public boolean getBoolean(Object o) throws IllegalAccessException { -return f.getBoolean(o); +return f.getBoolean(this, o); } /** @@ -303,7 +302,7 @@ public byte getByte(Object o) throws IllegalAccessException { -return f.getByte(o); +return f.getByte(this, o); } /** @@ -324,7 +323,7 @@ public char getChar(Object o) throws IllegalAccessException { -return f.getChar(o); +return f.getChar(this, o); } /** @@ -347,7 +346,7 @@ public short getShort(Object o) throws IllegalAccessException { -return f.getShort(o); +return f.getShort(this, o); } /** @@ -370,7 +369,7 @@ public int getInt(Object o) throws IllegalAccessException { -return f.getInt(o); +return f.getInt(this, o); } /** @@ -393,7 +392,7 @@ public long getLong(Object o) throws IllegalAccessException { -return f.getLong(o); +return f.getLong(this, o); } /** @@ -416,7 +415,7 @@ public float getFloat(Object o) throws IllegalAccessException { -return f.getFloat(o); +return f.getFloat(this, o); } /** @@ -440,7 +439,7 @@ public double getDouble(Object o) throws IllegalAccessException { -return f.getDouble(o); +return f.getDouble(this, o); } /** @@ -491,7 +490,7 @@ public void set(Object o, Object value) throws IllegalAccessException { -f.set(o, value); +f.set(this, o, value); } /** @@ -514,7 +513,7 @@ public void setBoolean(Object o, boolean value) throws IllegalAccessException { -f.setBoolean(o, value); +f.setBoolean(this, o, value); } /** @@ -537,7 +536,7 @@ public void setByte(Object o, byte value) throws IllegalAccessException { -f.setByte(o, value); +f.setByte(this, o, value); } /** @@ -560,7 +559,7 @@ public void setChar(Object o, char value) throws IllegalAccessException { -f.setChar(o, value); +f.setChar(this, o, value); } /** @@ -583,7 +582,7 @@ public void setShort(Object o, short value) throws IllegalAccessException { -f.setShort(o, value); +f.setShort(this, o, value); } /** @@ -606,7 +605,7 @@ public void setInt(Object o, int value) throws IllegalAccessException { -f.setInt(o, value); +f.setInt(this, o, value); } /** @@ -629,7 +628,7 @@ public void setLong(Object o, long value) throws IllegalAccessException { -f.setLong(o, value); +f.setLong(this, o, value); } /** @@ -652,7 +651,7 @@ public void setFloat(Object o, float value) throws IllegalAccessException { -f.setFloat(o, value); +f.setFloat(this, o, value); } /** @@ -675,7 +674,7 @@ public void setDouble(Object o, double value) throws IllegalAccessException { -f.setDouble(o, value); +f.setDouble(this, o, value);
Problems with Jikes RVM and Ubuntu 8.10
Hi, has anyone else tried running Classpath on Ubuntu 8.10? When I run DaCapo antlr I'm getting a problem that a test of File.exists and then File.canWrite (apologies if these aren't the exact method names) is failing. I believe the error is the call to exists is giving a false positive and then the call to canWrite fails as the file doesn't exist. One cause may be that the errno value is 0. This affliction may be Jikes RVM specific as we're compiling Classpath with -m32 on Intel 64bit (the platform I'm testing). Before digging too deep I thought I'd ask if any one else had solved the same problem? Thanks, Ian Rogers -- http://www.cs.man.ac.uk/~irogers/
Jikes RVM 3.0.1 released
Jikes RVM version 3.0.1 has been released and is available for download at _http://downloads.sourceforge.net/jikesrvm/jikesrvm-3.0.1.tar.bz2_ http://downloads.sourceforge.net/jikesrvm/jikesrvm-3.0.1.tar.bz2 The detailed release notes for major changes since 3.0.0 can be found below or in JIRA (_http://jira.codehaus.org/browse/RVM/fixforversion/14378_ http://jira.codehaus.org/browse/RVM/fixforversion/14378). ** New Feature * [RVM-507] - Initial prototype of TuningFork trace generation in Jikes RVM * [RVM-515] - Make boot image writer traversal of object graph configurable * [RVM-517] - Reflection optimization * [RVM-528] - Support for eclipse-project with Harmony class libraries * [RVM-634] - Add RuntimePure annotation to indicate when a Pure annotation should only be respected at runtime * [RVM-673] - Implement Inline.When.AssertionsDisabled pragma ** Improvement * [RVM-291] - Immortal objects with address based hashing should set their hashed bit during boot image writing * [RVM-443] - Avoid back references in java.lang.reflect VMXXX classes * [RVM-476] - Make lock allocation thread-model-agnostic. * [RVM-627] - Use java.nio for writing boot image * [RVM-632] - Space improvements of RVMClass.objectCache * [RVM-633] - Avoid the use of Reflection to invoke Object.finalize() * [RVM-644] - Reduce copying of char[] in java.lang.reflect.Proxy * [RVM-650] - Ask users to submit bug reports on Jikes RVM crashes ** Bug * [RVM-172] - Failing DaCapo benchmarks on PPC 32 OS X * [RVM-288] - Assertion failure in inline oracle * [RVM-318] - java.util.Scanner is unimplemented * [RVM-346] - SPECjvm98: Invalid runs should not be SUCCESSes * [RVM-410] - Problem with changes to stack walk * [RVM-440] - Poisoned tests failing in finalizer thread * [RVM-471] - Stack frame alignment broken for Intel on OS/X * [RVM-605] - Possible fix for FreeListPageResource.releasePages() * [RVM-606] - Problems with OSR guarded inlining of invokeinterface * [RVM-614] - BaseBasePoisoned build segfaults during VM bootup on pcc64-linux * [RVM-617] - DaCapo bloat fails with Apache Harmony class library * [RVM-619] - DaCapo eclipse fails with Apache Harmony class library * [RVM-621] - DaCapo xalan fails with Apache Harmony class library * [RVM-623] - Intel 16bit operations with immediate operands in some cases generate 32bit immediate operands rather than 16bit * [RVM-631] - Bug in new Finalization code * [RVM-636] - Crash in reflection during JSR-166 TCK * [RVM-643] - Invalid InstructionFormat usage in Simplifier, but real bug is that IR is semantically malformed * [RVM-645] - Bug in LiveAnalysis related to modeling of dataflow through Exception edges in the FCFG * [RVM-646] - Immix defrag broken * [RVM-652] - build failure on IA32 OS X 10.5 (Leopard) ** Tasks and Sub-task * [RVM-651] - Add support to Intel assembler for REX prefix byte * [RVM-667] - Modify the implementation of table switch * [RVM-669] - Build/boot image runner support for x86 64 * [RVM-671] - Fix spill location size estimates
Re: [cp-patches] FYI: ThreadLocal optimisation
Andrew Haley wrote: Andrew John Hughes wrote: Daniel's copyright assignment is finally through, so I'm committing this patch which optimises the use of ThreadLocals by replacing the use of the generic java.util.WeakHashMap with a ThreadLocal-specific implementation. It's slightly weird to be doing this in pure Java: all POSIX- compatible systems have thread-local variables, and the glibc implementation is very fast. Still, I'm sure this patch is an improvement. Andrew. Hi Andrew, I agree with what you say for static compilation. I think there's room for improvement in the pthread interfaces for getting thread locals especially if you want to have JIT compiled code that accesses them. For example, I use the below to compute a static thread local's offset and it is x86 specific: #include stdio.h static __thread char *hello; int main(int argc, char **argv) { int offset; asm (mov [EMAIL PROTECTED], %0 : =r(offset)); hello = hello; printf(%p %s %d,hello, hello, offset); } As the patch comes from Jikes RVM it should be no surprise we addressed solving the performance problem in a metacircular manner. I imagine DaCapo jython is a lot faster on Classpath runtimes now. Regards, Ian
[cp-patches] RFC: Try to reduce char[] copying in jlr.Proxy
Hi, the attached patch is trying to continue Andrew's good work and reduce the amount of redundant array copying, in this case in jlr.Proxy. There is a TODO in that we have no back door to turn a char[] in to a String without copying. Thanks, Ian Index: java/lang/reflect/Proxy.java === RCS file: /sources/classpath/classpath/java/lang/reflect/Proxy.java,v retrieving revision 1.30 diff -u -r1.30 Proxy.java --- java/lang/reflect/Proxy.java16 Mar 2008 22:04:51 - 1.30 +++ java/lang/reflect/Proxy.java29 Aug 2008 11:01:45 - @@ -1402,7 +1402,12 @@ { String utf8 = toUtf8(str); int len = utf8.length(); - return poolIndex(\1 + (char) (len 8) + (char) (len 0xff) + utf8); + CPStringBuilder buf = new CPStringBuilder(len+3); + buf.append('\1'); + buf.append((char) (len 8)); + buf.append((char) (len 0xff)); + buf.append(utf8); + return poolIndex(buf.toString()); } /** @@ -1416,7 +1421,7 @@ { char index = utf8Info(name); char[] c = {7, (char) (index 8), (char) (index 0xff)}; - return poolIndex(new String(c)); + return poolIndex(stringFromCharArray(c)); } /** @@ -1452,7 +1457,7 @@ char[] c = {(char) (structure + 8), (char) (cindex 8), (char) (cindex 0xff), (char) (ntindex 8), (char) (ntindex 0xff)}; - return poolIndex(new String(c)); + return poolIndex(stringFromCharArray(c)); } /** @@ -1469,7 +1474,7 @@ char tindex = utf8Info(type); char[] c = {12, (char) (nindex 8), (char) (nindex 0xff), (char) (tindex 8), (char) (tindex 0xff)}; - return poolIndex(new String(c)); + return poolIndex(stringFromCharArray(c)); } /** @@ -1541,5 +1546,19 @@ } return (char) i.intValue(); } + +/** + * Return a String wrapping the char array avoiding copying the char array + * if possible + * + * @param c the char array + * @return the String + */ +private String stringFromCharArray(char[] c) +{ + // TODO: we need some back door like VMCPStringBuilder to avoid copying + // the character array in this situation + return new String(c); +} } // class ClassFactory }
[cp-patches] State of Jikes RVM patches waiting to go into Classpath
Hi, currently there are 3 patches waiting to go into GNU Classpath from Jikes RVM: 1) Thread Local improvements: http://jira.codehaus.org/browse/RVM-185 http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/build/components/patches/classpath-cvs.RVM-185.patch?revision=13369view=markup I believe this is stalled waiting for Daniel's FSF paper work. This patch would be a big performance win for many VMs. 2) ZipEntry improvements: http://jira.codehaus.org/browse/RVM-392 http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/build/components/patches/classpath-cvs.RVM-392.patch?revision=14005view=markup This patch cleans up the use of Calendar in ZipEntry and avoids unnecessary bouncing between UNIX and DOS time formats. Possible bootstrap issues were raised by Tom Tromey, so the patch is still pending. Here's the e-mail thread: http://www.nabble.com/RFC%3A-tweaks-to-java.util.zip.ZipEntry-to15289313.html#a15289313 3) AIX build fix: http://jira.codehaus.org/browse/RVM-526 http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/build/components/patches/classpath-cvs.RVM-526.patch?revision=14551view=markup This is a small patch that fixes a problem for builds on AIX, I believe it would be safe to commit it. I'd like to push these patches up stream. For 2 and 3 please could people complain if they think they are an issue for their VM, I believe they are both steps in the right direction. For 1 could someone chase up the paper work? Thanks, Ian Rogers
[cp-patches] RFC: AIX build fix - paths too long in check_jni.sh
Dave Grove fixed an AIX build issue for the Jikes RVM with the attached patch. Jikes RVM tracker here: http://jira.codehaus.org/browse/RVM-526 Regards, Ian Rogers Index: scripts/check_jni_methods.sh.in === RCS file: /sources/classpath/classpath/scripts/check_jni_methods.sh.in,v retrieving revision 1.5 diff -u -r1.5 check_jni_methods.sh.in --- scripts/check_jni_methods.sh.in 11 Jun 2008 21:37:49 - 1.5 +++ scripts/check_jni_methods.sh.in 23 Jun 2008 20:03:20 - @@ -6,12 +6,16 @@ TMPFILE=/tmp/check-jni-methods.$$.1 TMPFILE2=/tmp/check-jni-methods.$$.2 TMPFILE3=/tmp/check-jni-methods.$$.3 +TMPFILE4=/tmp/check-jni-methods.$$.4 # Find all methods defined in the header files generated # from the java source files. -grep -h '^JNIEXPORT .* Java_' @abs_top_builddir@/include/*.h @abs_top_srcdir@/include/*.h | \ -LC_ALL=C sed -e 's,.*JNICALL \(Java_[a-z_A-Z0-9]*\).*$,\1,' | \ - sort -u $TMPFILE +grep -h '^JNIEXPORT .* Java_' @abs_top_srcdir@/include/*.h | \ +LC_ALL=C sed -e 's,.*JNICALL \(Java_[a-z_A-Z0-9]*\).*$,\1,' $TMPFILE +grep -h '^JNIEXPORT .* Java_' @abs_top_builddir@/include/*.h | \ +LC_ALL=C sed -e 's,.*JNICALL \(Java_[a-z_A-Z0-9]*\).*$,\1,' $TMPFILE +sort -u $TMPFILE $TMPFILE4 +mv $TMPFILE4 $TMPFILE # Find all methods in the JNI C source files. find @abs_top_srcdir@/native/jni -name \*.c | \
Re: [cp-patches] [rvm-core] State of Jikes RVM patches waiting to go into Classpath
Andrew John Hughes wrote: On 18/08/2008, Ian Rogers [EMAIL PROTECTED] wrote: Thanks Andrew, Andrew John Hughes wrote: On 18/08/2008, Ian Rogers [EMAIL PROTECTED] wrote: Hi, currently there are 3 patches waiting to go into GNU Classpath from Jikes RVM: Note that 0.98 is very imminent i.e. I'd like it to be released this week and most of it has already been merged to GCJ. 1) Thread Local improvements: http://jira.codehaus.org/browse/RVM-185 http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/build/components/patches/classpath-cvs.RVM-185.patch?revision=13369view=markup I believe this is stalled waiting for Daniel's FSF paper work. This patch would be a big performance win for many VMs. The assignment is still pending. The last e-mail I have is Daniel's assignment form on 11th June. I've pinged to see what's going on. Great! Getting this into 0.98 would be a real feature. I hope your luck's in then and the assignment has been done... :) 2) ZipEntry improvements: http://jira.codehaus.org/browse/RVM-392 http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/build/components/patches/classpath-cvs.RVM-392.patch?revision=14005view=markup This patch cleans up the use of Calendar in ZipEntry and avoids unnecessary bouncing between UNIX and DOS time formats. Possible bootstrap issues were raised by Tom Tromey, so the patch is still pending. Here's the e-mail thread: http://www.nabble.com/RFC%3A-tweaks-to-java.util.zip.ZipEntry-to15289313.html#a15289313 I'm sceptical about committing this one for 0.98 if there may be issues. I assume the gain is it not using a synchronized method to initialise the Calendar? Have you considered the initialization on demand holder idiom instead? http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom It's also mentioned in the JSR166 book by Doug Lea et. al. I can see why initialising Calendar as a prerequisite for zip support might cause a lot of problems and I don't think we have time to test it well enough for this release. Sorry, this change is a bit more involved than initialization on demand. Basically the normal use for a ZipEntry is for reading. In the current code to read an entry we must also convert the date (that is in DOS form in a ZIP) into a canonical unix time form, hence the requirement for a Calendar (and boot strap problems if the Calendar is in the zip). The main point of the patch is that we only really need the canonical time if we are writing the ZipEntry or if someone is querying it, in such a circumstance calling Calendar.getInstance() is fine and any caching can be done there. The patch is necessary for Jikes RVM as it avoids a boot strap issue (we don't need a Calendar to be in the boot image before we start reading a zip). I *really* don't want Calendars in Jikes RVM's boot image as I have to hand code conversion code between the different JDK and Classpath formats, hence initialization on demand is definitely not a solution. This patch is a good thing in my opinion and hasn't caused any issues for Jikes RVM, I would like to see it included in 0.98. It will help other VMs with the same bootstrap issue. Your discussion made no sense at first, until I realised you were linking to your first attempt at a patch. The real one is completely different: http://www.nabble.com/Re%3A-RFC%3A-tweaks-to-java.util.zip.ZipEntry-p15331002.html and now your comments make sense... ;) Have you tested with any other VMs? Sorry about that, it's the same thread just at the end rather than the initial patch. What are these other VMs you speak of ;-) Can I apply it and see if something somewhere falls over then fix it, rather than pre-emptively finding things out about VMs I don't use. 3) AIX build fix: http://jira.codehaus.org/browse/RVM-526 http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/build/components/patches/classpath-cvs.RVM-526.patch?revision=14551view=markup This is a small patch that fixes a problem for builds on AIX, I believe it would be safe to commit it. I think I've seen this before. Seems fine. Can you forward it for discussion on cp-patches? Maybe Dave can, he's assigned the issue to himself. The patch seems trivial enough, just breaking the process up presumably due to resource constraints on AIX. But I don't think it has been posted to the Classpath list at all so far. Posted. Thanks, Ian
[cp-patches] RFC: Avoid back references in java.lang.reflect VMXXX classes
This patch is part of Jikes RVM JIRA issue 443: http://jira.codehaus.org/browse/RVM-443 committed here: http://jikesrvm.svn.sourceforge.net/viewvc/jikesrvm?view=revrevision=14905 The patch avoids back references in java.lang.reflect.VM* classes and instead passes the parent object as a parameter. This means that constant parents can be propagated rather than in the current code where the parent must be loaded from a non-final field (breaking potential optimization without pointer analysis). The patch changes the internal reflection API and therefore would need a number of changes in other Classpath VMs to match the interface. Regards, Ian Index: java/lang/reflect/Constructor.java === RCS file: /sources/classpath/classpath/java/lang/reflect/Constructor.java,v retrieving revision 1.10 diff -u -r1.10 Constructor.java --- java/lang/reflect/Constructor.java 23 Jun 2008 20:59:35 - 1.10 +++ java/lang/reflect/Constructor.java 18 Aug 2008 17:14:28 - @@ -95,7 +95,6 @@ Constructor(VMConstructor cons) { this.cons = cons; -cons.cons = this; } private Constructor() @@ -316,7 +315,7 @@ { // Inescapable as the VM layer is 1.4 based. @SuppressWarnings(unchecked) - T ins = (T) cons.construct(args); + T ins = (T) cons.construct(args, this); return ins; } Index: java/lang/reflect/Field.java === RCS file: /sources/classpath/classpath/java/lang/reflect/Field.java,v retrieving revision 1.10 diff -u -r1.10 Field.java --- java/lang/reflect/Field.java23 Jun 2008 20:59:35 - 1.10 +++ java/lang/reflect/Field.java18 Aug 2008 17:14:28 - @@ -96,7 +96,6 @@ Field(VMField f) { this.f = f; -f.f = this; } /** @@ -257,7 +256,7 @@ public Object get(Object o) throws IllegalAccessException { -return f.get(o); +return f.get(this, o); } /** @@ -280,7 +279,7 @@ public boolean getBoolean(Object o) throws IllegalAccessException { -return f.getBoolean(o); +return f.getBoolean(this, o); } /** @@ -303,7 +302,7 @@ public byte getByte(Object o) throws IllegalAccessException { -return f.getByte(o); +return f.getByte(this, o); } /** @@ -324,7 +323,7 @@ public char getChar(Object o) throws IllegalAccessException { -return f.getChar(o); +return f.getChar(this, o); } /** @@ -347,7 +346,7 @@ public short getShort(Object o) throws IllegalAccessException { -return f.getShort(o); +return f.getShort(this, o); } /** @@ -370,7 +369,7 @@ public int getInt(Object o) throws IllegalAccessException { -return f.getInt(o); +return f.getInt(this, o); } /** @@ -393,7 +392,7 @@ public long getLong(Object o) throws IllegalAccessException { -return f.getLong(o); +return f.getLong(this, o); } /** @@ -416,7 +415,7 @@ public float getFloat(Object o) throws IllegalAccessException { -return f.getFloat(o); +return f.getFloat(this, o); } /** @@ -440,7 +439,7 @@ public double getDouble(Object o) throws IllegalAccessException { -return f.getDouble(o); +return f.getDouble(this, o); } /** @@ -491,7 +490,7 @@ public void set(Object o, Object value) throws IllegalAccessException { -f.set(o, value); +f.set(this, o, value); } /** @@ -514,7 +513,7 @@ public void setBoolean(Object o, boolean value) throws IllegalAccessException { -f.setBoolean(o, value); +f.setBoolean(this, o, value); } /** @@ -537,7 +536,7 @@ public void setByte(Object o, byte value) throws IllegalAccessException { -f.setByte(o, value); +f.setByte(this, o, value); } /** @@ -560,7 +559,7 @@ public void setChar(Object o, char value) throws IllegalAccessException { -f.setChar(o, value); +f.setChar(this, o, value); } /** @@ -583,7 +582,7 @@ public void setShort(Object o, short value) throws IllegalAccessException { -f.setShort(o, value); +f.setShort(this, o, value); } /** @@ -606,7 +605,7 @@ public void setInt(Object o, int value) throws IllegalAccessException { -f.setInt(o, value); +f.setInt(this, o, value); } /** @@ -629,7 +628,7 @@ public void setLong(Object o, long value) throws IllegalAccessException { -f.setLong(o, value); +f.setLong(this, o, value); } /** @@ -652,7 +651,7 @@ public void setFloat(Object o, float value) throws IllegalAccessException { -f.setFloat(o, value); +f.setFloat(this, o, value); } /** @@ -675,7 +674,7 @@ public void setDouble(Object o, double value) throws IllegalAccessException { -f.setDouble(o, value); +f.setDouble(this, o, value); } /** Index:
Jikes RVM 3.0.0 released
We're very happy to announce the release of Jikes RVM version 3.0.0. The road towards 3.0 began just about two years ago and a large number of people, both on the core team and from our user community at large, have contributed to making it a success. Thank You! The release is available for download at http://downloads.sourceforge.net/jikesrvm/jikesrvm-3.0.0.tar.bz2 The detailed release notes for major changes since 2.9.3 can be found below or in JIRA (http://jira.codehaus.org/browse/RVM/fixforversion/13530), but we'd like to highlight some of the larger themes that went into the 3.0 release (many of which have already been released in the 2.9.x releases we've made along the way). ** Normalization of source code and build process *** Complete rewrite of the build/test systems to use ant. *** Jikes RVM can be developed in Eclipse using the JDT *** Extensive restructuring of package structure *** Removal of VM_ and OPT_ prefixes from all source files. ** Increased system stability and performance *** A new continuous testing system (http://jikesrvm.anu.edu.au/cattrack) *** Concerted stability and performance drives ** Java 5 support *** Support for Java 5 language features *** Use of Java 5 language features throughout the code base. Detailed list (89 issues closed in the 3 months since 2.9.3) ** New Feature * [RVM-358] - Initial support for Apache Harmony class library * [RVM-480] - Spec JVM 2008 regression test * [RVM-534] - MMTk Test harness * [RVM-540] - Implement java.lang.Compiler * [RVM-591] - Support for jdocs.com javadoc * [RVM-592] - Checks on creating ObjectReferences ** Improvement] * [RVM-72] - NonMoving annotations for classes instances of which should be allocated to the immortal heap * [RVM-273] - Remove VM_ prefix from all VM classes * [RVM-275] - Remove VMOpt prefix from opt compiler classes that go into bootimage * [RVM-282] - Make dumpVirtualMachine more defensive * [RVM-329] - Specialize IA32 assembler for lister vs. non-lister * [RVM-333] - Annotations used for VM Pragmas (NoInline, Uninterruptible, etc) probably should not be as closed linked to classloaders * [RVM-445] - Clean up handling of JTOC * [RVM-449] - Handle instanceof and checkcast in ShortArray scalar replacer * [RVM-477] - Gather new compiler DNA * [RVM-501] - BuildWithAllClasses is (practically) unused * [RVM-502] - Dead code elimination of pure calls) * [RVM-505] - Eliminate calls to VM_Class.getClass..FromStackFrame when stack frame is determinable * [RVM-508] - Have hash map where entries are completely immutable saving references from boot image root set * [RVM-510] - Create top level common directory to make it easier to split out and share useful components from rvm and MMTk * [RVM-511] - Split out MMTk option processing support * [RVM-512] - Experiment with freezing bucket array in VM_HashMap/VM_HashSet * [RVM-513] - Large arrays in boot image cause memory leak * [RVM-525] - Upgrade to GNU classpath 0.97.2 * [RVM-537] - Implement inline mustImplementInterface sequence for invokeinterface in baseline compilers * [RVM-538] - Inline checkcast/instanceof sequences in baseline compiler for simple cases * [RVM-572] - Remove OSR_ and BC_ prefixes from OnStackReplacement code * [RVM-593] - Extra checks on references being traced in rvm * [RVM-603] - Improve intel baseline prologue/epilogue/call by use push/pop instead of mov [sp] * [RVM-594] - Naming of MM_Interface ** Bug * [RVM-46] - CaffieneMark failures on AIX/PPC * [RVM-47] - DaCapo regressions on AIX/PPC * [RVM-58] - Linker errors under AIX/ppc * [RVM-105] - sysNetSelect doesnt seem to be avoiding the syswrap select * [RVM-187] - VM_OptGenericMapIterator: findGCMapIndex failed * [RVM-221] - Specialized scanning broken on ppc64-aix? * [RVM-234] - Annotation issues: not implemented via proxy classes, support for serialization * [RVM-269] - unresolved invokeinterface on null should force classloading before rasiing NPE * [RVM-271] - Timeouts for stress are not correct * [RVM-303] - Cannot modify accessible final instance fields * [RVM-325] - Spec JVM 98 jack failing with OOMs * [RVM-327] - Performance degredation in IA32 assembler * [RVM-332] - Eclipse 3.2 fails to run on the RVM * [RVM-369] - PPC32-OSX - Crash in GC when a stack contains native frames * [RVM-372] - Integer overflow in sysNanoTime * [RVM-423] - Fop performance strangeness * [RVM-442] - All poisoned tests fail PPC 32 * [RVM-454] - The sub-test TestAnnotationInheritance of the basic tests is excluded until it can be fixed * [RVM-458] - Poisoned bit test highlights JNI problem * [RVM-469] - Fix IA32 assembler to use Address instead of Offset for absolute addressing * [RVM-482] - Crash when running Production_Opt0_perf portion of compiler-dna test run * [RVM-483] - Conditionalize fsqrt generation on PowerPC *
Re: Savannah has Mercurial!
Andrew John Hughes wrote: I just noticed this announcement when submitting the news announcement for 0.97.2. What do people think to the idea of switching? Maybe post 0.98? Hi, just to give a different perspective. For Jikes RVM there's been no choice to use Mercurial as SourceForge don't provide it, this may actually have been no bad thing. There are lots of different version control tools, but both Mercurial and GIT support pulling and pushing to a SVN repository. Clearly using SVN with SVN isn't a problem and CVS is out-of-date anyway. So in summary, having a central repository that's an SVN repository can be a good thing as it supports the maximum number of version control tools. We have a list of different tools for working with our repository (hg, git, svn, svk, darcs, svm, rsync) and how to set them up with Jikes RVM here: http://jikesrvm.org/Using+Distributed+And+Local+Version+Control+Tools I may be talking rubbish as I'm not a version control guru. Regards, Ian -- http://www.cs.man.ac.uk/~irogers/
Re: [cp-patches] RFC: changes to java.lang.Integer, Long...
Andrew Haley wrote: Ian Rogers wrote: please give your comments on the attached patch. It tries to reduce the size of char[] for strings used to hold numbers. It changes Float/Double equals to use bit based comparisons rather than division. It increases the use of valueOf methods. It adds a cache of values from -128 to 127 for Long. It adds a cache of the values of zero and one to Float and Double. The string size is an estimate. For decimal numbers it will divide the value repeatedly by 8, causing the string length to be over estimated by a character for values like 999. This string size is still better than the current estimate of 33 characters. It also avoids the use of division (shifts are used) and/or lookup tables. I am really not convinced by the cache of values from -128 to 127. It's a significant overhead for the startup time, and I find it hard to imagine a justification for it. Andrew. Sorry, I replied to this off-list accidentally. One alternative is to move the class initialization into an inner class by placing the cache in an inner class. That way the cache is only built when valueOf a cached value is called. This approach would prompt similar changes in the other Number valueOf methods. Ian -- http://www.cs.man.ac.uk/~irogers/
[cp-patches] RFC: Change to ArrayList.ensureCapacity
This patch changes the array list size increase to ~50% rather than doubling in line with what OpenJDK does. OpenJDK still doubles the size of vectors, as that's documented behavior. Feedback appreciated, Ian -- http://www.cs.man.ac.uk/~irogers/ --- components/classpath/97.1p6/classpath/java/util/ArrayList.java 2008-05-19 09:28:13.0 +0100 +++ libraryInterface/GNUClasspath/LGPL/src/java/util/ArrayList.java 2008-05-27 11:24:58.0 +0100 @@ -173,7 +173,7 @@ if (minCapacity current) { -E[] newData = (E[]) new Object[Math.max(current * 2, minCapacity)]; +E[] newData = (E[]) new Object[Math.max((current * 3) / 2 + 1, minCapacity)]; System.arraycopy(data, 0, newData, 0, size); data = newData; }
Re: Classpath 0.98
Andrew John Hughes wrote: Dear all, I think it's about time we started to consider another (major) release. My personal wishlist of things to finish for this release is: * java.util.regex 1.6 support * java.util.Scanner import (dependent on the above) * import of javax.activation Another possibility is to also import gjdoc; our options there are: * Add GJDoc for 0.98 * Add GJDoc post-release (ending up in 0.99) * Don't add it at all It would obviously be an optional build. Does anyone have any other suggestions for things that should make this release? Please highlight any regressions you know of as well. PR36199 that twisti just filed seems like it should be fixed, for example. Thanks, It'd be great if SPEC jvm 2008 were known to run. There are issues on Cacao and Jikes RVM related to Classpath. Thanks, Ian
SPEC jvm 2008 successes?
Hi, I was wondering what success people have had running SPEC jvm 2008 [1]. My experiences are here [2] and I'd like to get further. If anyone succeeds I'd be interested to know. Thanks, Ian [1] http://www.spec.org/jvm2008/ [2] http://jira.codehaus.org/browse/RVM-480 -- Third International Workshop on Implementation, Compilation, Optimization of Object-Oriented Languages, Programs and Systems (ICOOOLPS 2008) Submissions/Notification/Conference: May 12th/May 19th/July 7th Paphos (Cyprus) http://icoolps.loria.fr
Re: [cp-patches] RFC: Move exception handling out of common case: java.util.Vector/ArrayList
patch applied. Ian -- Third International Workshop on Implementation, Compilation, Optimization of Object-Oriented Languages, Programs and Systems (ICOOOLPS 2008) July 7, Paphos (Cyprus) http://icoolps.loria.fr http://icooolps.loria.fr/
[commit-cp] classpath ChangeLog java/util/ArrayList.java ja...
CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers08/04/26 16:46:47 Modified files: . : ChangeLog java/util : ArrayList.java Vector.java Log message: 2008-04-26 Ian Rogers [EMAIL PROTECTED] * java/util/ArrayList (raiseBoundsError): new method to raise bound exceptions in uncommon case. (checkBoundInclusive): use raiseBoundsError. (checkBoundExclusive): likewise. * java/util/ArrayList (raiseBoundsError): new method to raise bound exceptions in uncommon case. (checkBoundInclusive): use raiseBoundsError. (checkBoundExclusive): likewise. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/ChangeLog?cvsroot=classpathr1=1.9581r2=1.9582 http://cvs.savannah.gnu.org/viewcvs/classpath/java/util/ArrayList.java?cvsroot=classpathr1=1.31r2=1.32 http://cvs.savannah.gnu.org/viewcvs/classpath/java/util/Vector.java?cvsroot=classpathr1=1.31r2=1.32
[cp-patches] RFC: Move exception handling out of common case: java.util.Vector/ArrayList
Hi, the attached patch moves exception handling code out of the common case for elementAt of both java.util.Vector and java.util.elementAt, this helps JIT compilation inline the common non-exception throwing case (and avoid expense incurred by considering StringBuilders, etc.). Other than fixing coding convention issues, are there any objections to this change? Thanks, Ian -- http://www.cs.man.ac.uk/~irogers/ Index: java/util/ArrayList.java === RCS file: /sources/classpath/classpath/java/util/ArrayList.java,v retrieving revision 1.31 diff -u -r1.31 ArrayList.java --- java/util/ArrayList.java10 Dec 2006 20:25:46 - 1.31 +++ java/util/ArrayList.java23 Apr 2008 14:17:43 - @@ -472,8 +472,7 @@ // use of a negative index will cause an ArrayIndexOutOfBoundsException, // a subclass of the required exception, with no effort on our part. if (index size) - throw new IndexOutOfBoundsException(Index: + index + , Size: - + size); + raiseBoundsError(index); } /** @@ -488,11 +487,23 @@ // use of a negative index will cause an ArrayIndexOutOfBoundsException, // a subclass of the required exception, with no effort on our part. if (index = size) - throw new IndexOutOfBoundsException(Index: + index + , Size: - + size); + raiseBoundsError(index); } /** + * Raise the ArrayIndexOfOutBoundsException. + * @param index the index of the access + * @throws IndexOutOfBoundsException unconditionally + */ + private void raiseBoundsError(int index) + { + // Implementaion note: put in a separate method to make the JITs job easier + // (separate common from uncommon code at method boundaries when trivial to do so). + throw new IndexOutOfBoundsException(Index: + index + , Size: + size); + } + + + /** * Remove from this list all elements contained in the given collection. * This is not public, due to Sun's API, but this performs in linear * time while the default behavior of AbstractList would be quadratic. Index: java/util/Vector.java === RCS file: /sources/classpath/classpath/java/util/Vector.java,v retrieving revision 1.31 diff -u -r1.31 Vector.java --- java/util/Vector.java 12 Mar 2008 23:39:51 - 1.31 +++ java/util/Vector.java 23 Apr 2008 14:17:43 - @@ -909,7 +909,7 @@ // use of a negative index will cause an ArrayIndexOutOfBoundsException // with no effort on our part. if (index elementCount) - throw new ArrayIndexOutOfBoundsException(index ++ elementCount); + raiseBoundsError(index, ); } /** @@ -924,10 +924,23 @@ // use of a negative index will cause an ArrayIndexOutOfBoundsException // with no effort on our part. if (index = elementCount) - throw new ArrayIndexOutOfBoundsException(index + = + elementCount); + raiseBoundsError(index, = ); } /** + * Raise the ArrayIndexOfOutBoundsException. + * @param index the index of the access + * @param operator the operator to include in the error message + * @throws IndexOutOfBoundsException unconditionally + */ + private void raiseBoundsError(int index, String operator) + { + // Implementaion note: put in a separate method to make the JITs job easier + // (separate common from uncommon code at method boundaries when trivial to do so). + throw new ArrayIndexOutOfBoundsException(index + operator + elementCount); + } + + /** * Serializes this object to the given stream. * * @param s the stream to write to
Re: [cp-patches] RFC: Move exception handling out of common case: java.util.Vector/ArrayList
Andrew John Hughes wrote: Looks okay, overlooking the obvious formatting issues. Is there an overhead to the method call or would most VMs inline this? So, most code shouldn't access an element beyond the length of the Vector or ArrayList - so the exception handling code will never normally be executed in any benchmarks, so the method calling overhead isn't important. If the method call were to become hot, the Jikes RVM would inline it, but this is very unlikely to happen. This patch is being applied against the Jikes RVM currently to gain performance in particular on SpecJVM 98. I'd like to include the patch in Classpath to minimize points where the Jikes RVM and Classpath libraries differ. Thanks, Ian
[cp-patches] Re: RFC: changes to java.nio buffers
Committed. 2008-04-18 Ian Rogers [EMAIL PROTECTED] * java/nio/Buffer.java (cap): make field private and final. (address): make field final. (Buffer): add address argument to package protected constructor thereby allowing it to be made final. * java/nio/ByteBuffer.java (backing_buffer): make field final. (array_offset): make field final. (ByteBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/ByteBufferImpl.java (readOnly): make field final. (ByteBufferImpl): modify call to super class constructor to pass backing_buffer and array_offset. * java/nio/CharBuffer.java (array_offset): make field final. (backing_buffer): make field final. (CharBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/CharBufferImpl.java (readOnly): make field final. (CharBufferImpl): modify call to super class constructor to pass backing_buffer and array_offset. (CharBufferImpl(CharBufferImpl)): likewise. * java/nio/CharSequenceBuffer.java (charSequence): make field final. (CharSequenceBuffer): modify call to super class constructor, allowing fields to be made final. (duplicate): use capacity call rather than cap, to allow better encapsulation. * java/nio/CharViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (CharViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/DirectByteBufferImpl.java: modify calls to super class constructors, allowing fields to be made final. * java/nio/DoubleBuffer.java (array_offset): make field final. (backing_buffer): make field final. (DoubleBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/DoubleBufferImpl.java (readOnly): make field final. (DoubleBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/DoubleViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (DoubleViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/FloatBuffer.java (array_offset): make field final. (backing_buffer): make field final. (FloatBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/FloatBufferImpl.java (readOnly): make field final. (FloatBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/FloatViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (FloatViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/IntBuffer.java (array_offset): make field final. (backing_buffer): make field final. (IntBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/IntBufferImpl.java (readOnly): make field final. (IntBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/IntViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (IntViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/LongBuffer.java (array_offset): make field final. (backing_buffer): make field final. (LongBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/LongBufferImpl.java (readOnly): make field final. (LongBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio
[commit-cp] classpath ChangeLog java/lang/Byte.java java/la...
CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers08/04/18 21:00:12 Modified files: . : ChangeLog java/lang : Byte.java Character.java Double.java Float.java Integer.java Long.java Short.java Log message: 2008-04-18 Ian Rogers [EMAIL PROTECTED] * java/lang/Byte.java (static): initialize byteCache. (valueOf(String,int)): use valueOf(byte) rather than new. (valueOf(String)): likewise. (valueOf(byte)): Switch from lazy initialization of cached values to initialization at class initialization time. This removes the need for synchronization in the common case. (decode): use valueOf(byte) rather than new. * java/lang/Character.java (static): initialize charCache. (valueOf): Switch from lazy initialization of cached values to initialization at class initialization time. This removes the need for synchronization in the common case. * java/lang/Double.java (ZERO): new private field. (ONE): likewise. (valueOf(double)): don't create new doubles for the case of 0 and 1. (valueOf(String)): use valueOf(double) rather than new. (equals): use raw bits for comparison to avoid division. * java/lang/Float.java (ZERO): new private field. (ONE): likewise. (valueOf(float)): don't create new floats for the case of 0 and 1. (valueOf(String)): use valueOf(float) rather than new. (equals): use raw bits for comparison to avoid division. * java/lang/Integer.java (static): initialize intCache. (stringSize): new private method to estimate size of string for an int. (toString): reuse digits for single character strings, for multiple character strings estimate their length using string size method. (valueOf(String,int)): use valueOf(int) rather than new. (valueOf(String)): likewise. (valueOf(int)): Switch from lazy initialization of cached values to initialization at class initialization time. This removes the need for synchronization in the common case. (getInteger): use valueOf(int) rather than new. (decode): use valueOf(int) rather than new. (signum): use shift and subtract to compute value. (toUnsignedString): calculate string size rather than using 32 chars. * java/lang/Long.java (longCache): new private field. (stringSize): new private method to estimate size of string for a long. (toString): reuse digits for single character strings, for multiple character strings estimate their length using string size method. (valueOf(String,int)): use valueOf(long) rather than new. (valueOf(String)): likewise. (valueOf(long)): use cache of values. (decode): use valueOf(long) rather than new. (signum): use shift and subtract to compute value. (toUnsignedString): calculate string size rather than using 64 chars. * java/lang/Short.java (static): initialize shortCache. (valueOf(String,int)): use valueOf(short) rather than new. (valueOf(String)): likewise. (valueOf(short)): Switch from lazy initialization of cached values to initialization at class initialization time. This removes the need for synchronization in the common case. (decode): use valueOf(short) rather than new. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/ChangeLog?cvsroot=classpathr1=1.9577r2=1.9578 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Byte.java?cvsroot=classpathr1=1.26r2=1.27 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Character.java?cvsroot=classpathr1=1.48r2=1.49 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Double.java?cvsroot=classpathr1=1.45r2=1.46 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Float.java?cvsroot=classpathr1=1.39r2=1.40 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Integer.java?cvsroot=classpathr1=1.36r2=1.37 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Long.java?cvsroot=classpathr1=1.25r2=1.26 http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Short.java?cvsroot=classpathr1=1.20r2=1.21
[commit-cp] classpath ChangeLog java/nio/Buffer.java java/n...
CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers08/04/18 23:23:34 Modified files: . : ChangeLog java/nio : Buffer.java ByteBuffer.java ByteBufferImpl.java CharBuffer.java CharBufferImpl.java CharSequenceBuffer.java CharViewBufferImpl.java DirectByteBufferImpl.java DoubleBuffer.java DoubleBufferImpl.java DoubleViewBufferImpl.java FloatBuffer.java FloatBufferImpl.java FloatViewBufferImpl.java IntBuffer.java IntBufferImpl.java IntViewBufferImpl.java LongBuffer.java LongBufferImpl.java LongViewBufferImpl.java MappedByteBuffer.java MappedByteBufferImpl.java ShortBuffer.java ShortBufferImpl.java ShortViewBufferImpl.java Log message: 2008-04-18 Ian Rogers [EMAIL PROTECTED] * java/nio/Buffer.java (cap): make field private and final. (address): make field final. (Buffer): add address argument to package protected constructor thereby allowing it to be made final. * java/nio/ByteBuffer.java (backing_buffer): make field final. (array_offset): make field final. (ByteBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/ByteBufferImpl.java (readOnly): make field final. (ByteBufferImpl): modify call to super class constructor to pass backing_buffer and array_offset. * java/nio/CharBuffer.java (array_offset): make field final. (backing_buffer): make field final. (CharBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/CharBufferImpl.java (readOnly): make field final. (CharBufferImpl): modify call to super class constructor to pass backing_buffer and array_offset. (CharBufferImpl(CharBufferImpl)): likewise. * java/nio/CharSequenceBuffer.java (charSequence): make field final. (CharSequenceBuffer): modify call to super class constructor, allowing fields to be made final. (duplicate): use capacity call rather than cap, to allow better encapsulation. * java/nio/CharViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (CharViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/DirectByteBufferImpl.java: modify calls to super class constructors, allowing fields to be made final. * java/nio/DoubleBuffer.java (array_offset): make field final. (backing_buffer): make field final. (DoubleBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/DoubleBufferImpl.java (readOnly): make field final. (DoubleBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/DoubleViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (DoubleViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/FloatBuffer.java (array_offset): make field final. (backing_buffer): make field final. (FloatBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final. * java/nio/FloatBufferImpl.java (readOnly): make field final. (FloatBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/FloatViewBufferImpl.java (offset): make field final. (bb): likewise. (readOnly): likewise. (endian): likewise. (FloatViewBufferImpl): modify call to super class constructor, allowing fields to be made final. * java/nio/IntBuffer.java (array_offset): make field final. (backing_buffer): make field final. (IntBuffer): add address, backing_buffer and array_offset to constructor, allowing fields to be made final
[cp-patches] RFC: changes to java.lang.Integer, Long...
Hi, please give your comments on the attached patch. It tries to reduce the size of char[] for strings used to hold numbers. It changes Float/Double equals to use bit based comparisons rather than division. It increases the use of valueOf methods. It adds a cache of values from -128 to 127 for Long. It adds a cache of the values of zero and one to Float and Double. The string size is an estimate. For decimal numbers it will divide the value repeatedly by 8, causing the string length to be over estimated by a character for values like 999. This string size is still better than the current estimate of 33 characters. It also avoids the use of division (shifts are used) and/or lookup tables. Regards, Ian Index: ChangeLog === RCS file: /sources/classpath/classpath/ChangeLog,v retrieving revision 1.9572 diff -u -r1.9572 ChangeLog --- ChangeLog 9 Apr 2008 20:23:11 - 1.9572 +++ ChangeLog 14 Apr 2008 13:54:25 - @@ -1,3 +1,50 @@ +2008-04-14 Ian Rogers [EMAIL PROTECTED] + + * java/lang/Byte.java (static): initialize byteCache. + (valueOf(String,int)): use valueOf(byte) rather than new. + (valueOf(String)): likewise. + (valueOf(byte)): remove synchronization. + (decode): use valueOf(byte) rather than new. + * java/lang/Character.java (static): initialize charCache. + (valueOf): remove synchronization. + * java/lang/Double.java (ZERO): new private field. + (ONE): likewise. + (valueOf(double)): don't create new doubles for the case of 0 and 1. + (valueOf(String)): use valueOf(double) rather than new. + (equals): use raw bits for comparison to avoid division. +* java/lang/Float.java (ZERO): new private field. +(ONE): likewise. +(valueOf(double)): don't create new floats for the case of 0 and 1. +(valueOf(String)): use valueOf(float) rather than new. +(equals): use raw bits for comparison to avoid division. + * java/lang/Integer.java (static): initialize intCache. + (stringSize): new private method to estimate size of string for an int. + (toString): reuse digits for single character strings, for multiple + character strings estimate their length using string size method. + (valueOf(String,int)): use valueOf(int) rather than new. + (valueOf(String)): likewise. + (valueOf(int)): remove synchronization. + (getInteger): use valueOf(int) rather than new. + (decode): use valueOf(int) rather than new. + (signum): use shift and subtract to compute value. + (toUnsignedString): calculate string size rather than using 32 chars. +* java/lang/Long.java (longCache): new private field. +(stringSize): new private method to estimate size of string for a long. +(toString): reuse digits for single character strings, for multiple +character strings estimate their length using string size method. +(valueOf(String,int)): use valueOf(long) rather than new. +(valueOf(String)): likewise. +(valueOf(long)): use cache. +(decode): use valueOf(long) rather than new. + (getLong): likewise. +(signum): use shift and subtract to compute value. + (toUnsignedString): calculate string size rather than using 64 chars. + * java/lang/Short.java (static): initialize shortCache. +(valueOf(String,int)): use valueOf(short) rather than new. +(valueOf(String)): likewise. +(valueOf(short)): remove synchronization. +(decode): use valueOf(short) rather than new. + 2008-04-09 Mario Torre [EMAIL PROTECTED] * java/io/File.java (canWrite): use canWriteDirectory(String). Index: java/lang/Byte.java === RCS file: /sources/classpath/classpath/java/lang/Byte.java,v retrieving revision 1.26 diff -u -r1.26 Byte.java --- java/lang/Byte.java 10 Dec 2006 20:25:44 - 1.26 +++ java/lang/Byte.java 14 Apr 2008 13:54:25 - @@ -88,6 +88,11 @@ // This caches Byte values, and is used by boxing conversions via // valueOf(). We're required to cache all possible values here. private static Byte[] byteCache = new Byte[MAX_VALUE - MIN_VALUE + 1]; + static + { +for (byte i=MIN_VALUE; i = MAX_VALUE; i++) + byteCache[i - MIN_VALUE] = new Byte(i); + } /** @@ -185,7 +190,7 @@ */ public static Byte valueOf(String s, int radix) { -return new Byte(parseByte(s, radix)); +return valueOf(parseByte(s, radix)); } /** @@ -201,7 +206,7 @@ */ public static Byte valueOf(String s) { -return new Byte(parseByte(s, 10)); +return valueOf(parseByte(s, 10)); } /** @@ -214,12 +219,7 @@ */ public static Byte valueOf(byte val) { -synchronized (byteCache) - { - if (byteCache[val - MIN_VALUE] == null) - byteCache[val - MIN_VALUE
Re: [cp-patches] RFC: changes to java.lang.Integer, Long...
David Daney wrote: Ian Rogers wrote: Hi, please give your comments on the attached patch. It tries to reduce the size of char[] for strings used to hold numbers. It changes Float/Double equals to use bit based comparisons rather than division. It increases the use of valueOf methods. It adds a cache of values from -128 to 127 for Long. It adds a cache of the values of zero and one to Float and Double. The string size is an estimate. For decimal numbers it will divide the value repeatedly by 8, causing the string length to be over estimated by a character for values like 999. This string size is still better than the current estimate of 33 characters. It also avoids the use of division (shifts are used) and/or lookup tables. I would like to know your motivation for doing this. Do you have any evidence that this will reduce memory usage and speed up real applications? That said, in our gcj-3.4 based application, we had to create a cache of Integers because we were creating large numbers of them all with a small set of values. So in principle this could be a good approach, but I don't know if we can assume that there is universal benefit from a patch like this. Can you point to any benchmarks where this helps? Thanks, David Daney Hi David, I'm having a crack down on wasted memory in the Jikes RVM. For DaCapo fop (single iteration) there are 270 and 977 occurrences of Double 0 and 1 and 20 occurrences of other Doubles. On the other hand DaCapo bloat has very few 0 and 1 values. My motivation to cache these, other than fop, is that they exist as bytecodes (fconst0/fconst1 and dconst0/dconst1, although I'm ignoring fconst2 and dconst2). We already cache Integers in the intCache. I do extend this concept to Long, as is done in OpenJDK, and to Float and Double. Currently we always allocated 33 char arrays to hold the string value, this is 4.625 the size of the minimum object in the RVM. In the case of a single character string, 18.86% of Integer strings in DaCapo bloat, this code doesn't allocate any char arrays. For other integers the char array is reduced to either the exact or (20% of the time for decimal values) 1 character longer char arrays. This is at the cost of up to 32 compares, branches and shifts. For DaCapo bloat a little under 50% of integer strings created are for values between -128 and 127. So the trade offs in the code are, slower Float/Double valueOf code, but fewer Float and Double objects (hopefully improving GC). A small time to calculate string sizes vs smaller strings and less GC pressure. For the Jikes RVM we measure performance 4 times a day [1], I introduced this patch in r14113 and there are no peaks or troughs that appear at this point. Given the patch is performance neutral but saves memory (although not improving GC performance for the RVM markedly) I think it's worth including. GC is less than 6% of execution time, so time saved may be difficult to measure in the bigger picture (unless it pushes you under or over a particular threshold). Regards, Ian [1] http://jikesrvm.anu.edu.au/cattrack/results/rvmx86lnx32.anu.edu.au/perf/3437/performance_report
Re: [cp-patches] RFC: File bug Fix and small VM interface change
Hi Mario, this looks like a good patch so +1 from me. Just to note that we've been discussing the VMFile interface in a Jikes RVM tracker [1] and that on IRC MJW pointed out that GCJ's implementation appeared to vary from that of Classpath [2] [3] [4]. Regards, Ian [1] http://jira.codehaus.org/browse/RVM-427 [2] http://gcc.gnu.org/viewcvs/*checkout*/trunk/libjava/java/io/File.java [3] http://gcc.gnu.org/viewcvs/*checkout*/trunk/libjava/java/io/natFileWin32.cc [4] http://gcc.gnu.org/viewcvs/*checkout*/trunk/libjava/java/io/natFilePosix.cc Mario Torre wrote: Hello all! I would like to submit this fix. The problem is that to detect if a file is writable we actually open it for writing... Even worse, in the case of a directory, we write to it a temp file! There are a number of issues that I see wrong here, but what worries me most is that these operations can kill filesystem that reside on compact flash memories and other devices that have a limited number of write. The current fix does two things. 1. introduce a new method, native, canWriteDirectory(String path) This method is meant to be implemented by whoever implements the VM interface, so that it can do nice things with their target environment. The default implementation works on Linux and should work on any *nix operating systems. I've left canWriteDirectory(File file) for backward compatibility, but I guess no one uses this anyway (it defer to the native method). 2. Change the implementation of Java_java_io_VMFile_canWrite and Java_java_io_VMFile_canRead so that they use cpio_checkAccess now, instead of doing the old The lazy man's way out (which is also more code, btw...) I'm going to submit this today if no one complains, any ideas? Ah, before I forget, there are a number of unrelated fixes like indentation and all the function signature now reflect the fact that these methods are static (jclass instead of jobject). It would be handy here to use mercurial (hg record) to separate patchsets. Mario 2008-04-09 Mario Torre [EMAIL PROTECTED] * java/io/File.java (canWrite): use canWriteDirectory(String). * vm/reference/java/io/VMFile.java (canWriteDirectory): new native method. * native/jni/java-io/java_io_VMFile.c: correct indentation, sync function names with header file definition. (Java_java_io_VMFile_canRead): use cpio_checkAccess to get access permission. Removed unused variable. (Java_java_io_VMFile_canWrite): likewise. (Java_java_io_VMFile_canWriteDirectory): new function.
[cp-patches] RFC: changes to java.nio buffers
Hi, the attached patch makes more fields in java.nio final, restructuring constructors to enable this. This simplifies the code sufficiently that it aids the Jikes RVM's escape analysis so that it can remove memory allocations associated with buffers in certain key areas. When some fields could be made private rather than package protected they were. Thanks, Ian --- java/nio/Buffer.java2007-04-12 22:13:22.0 +0100 +++ java/nio/Buffer.java2008-04-08 20:33:49.0 +0100 @@ -45,19 +45,21 @@ */ public abstract class Buffer { - int cap = 0; - int limit = 0; - int pos = 0; - int mark = -1; - Pointer address; + private final int cap; + int limit; + int pos; + int mark; + final Pointer address; /** * Creates a new Buffer. * * Should be package private. */ - Buffer (int capacity, int limit, int position, int mark) + Buffer (int capacity, int limit, int position, int mark, Pointer address) { +this.address = address; + if (capacity 0) throw new IllegalArgumentException (); @@ -72,6 +74,10 @@ this.mark = mark; } +else +{ + this.mark = -1; +} } /** --- java/nio/ByteBufferImpl.java2006-05-13 18:20:35.0 +0100 +++ java/nio/ByteBufferImpl.java2008-04-08 16:14:43.0 +0100 @@ -43,13 +43,11 @@ */ final class ByteBufferImpl extends ByteBuffer { - private boolean readOnly; + private final boolean readOnly; ByteBufferImpl (byte[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly) { -super (capacity, limit, position, mark); -this.backing_buffer = buffer; -this.array_offset = offset; +super (capacity, limit, position, mark, null, buffer, offset); this.readOnly = readOnly; } --- java/nio/ByteBuffer.java2006-12-10 20:25:45.0 + +++ java/nio/ByteBuffer.java2008-04-08 20:34:19.0 +0100 @@ -38,6 +38,8 @@ package java.nio; +import gnu.classpath.Pointer; + /** * @since 1.4 */ @@ -45,13 +47,14 @@ implements ComparableByteBuffer { ByteOrder endian = ByteOrder.BIG_ENDIAN; + final byte[] backing_buffer; + final int array_offset; - int array_offset; - byte[] backing_buffer; - - ByteBuffer (int capacity, int limit, int position, int mark) + ByteBuffer (int capacity, int limit, int position, int mark, Pointer address, byte[] backing_buffer, int array_offset) { -super (capacity, limit, position, mark); +super (capacity, limit, position, mark, address); +this.backing_buffer = backing_buffer; +this.array_offset = array_offset; } /** --- java/nio/CharBufferImpl.java2006-05-01 23:41:20.0 +0100 +++ java/nio/CharBufferImpl.java2008-04-08 16:20:20.0 +0100 @@ -43,7 +43,7 @@ */ final class CharBufferImpl extends CharBuffer { - private boolean readOnly; + private final boolean readOnly; CharBufferImpl (int capacity) { @@ -52,18 +52,14 @@ CharBufferImpl (char[] buffer, int offset, int capacity, int limit, int position, int mark, boolean readOnly) { -super (capacity, limit, position, mark); -this.backing_buffer = buffer; -this.array_offset = offset; +super (capacity, limit, position, mark, null, buffer, offset); this.readOnly = readOnly; } public CharBufferImpl (CharBufferImpl copy) { -super (copy.capacity (), copy.limit (), copy.position (), 0); -backing_buffer = copy.backing_buffer; -array_offset = copy.array_offset; -readOnly = copy.isReadOnly (); +super (copy.capacity (), copy.limit (), copy.position (), 0, null, copy.backing_buffer, copy.array_offset); +this.readOnly = copy.isReadOnly (); } public boolean isReadOnly () --- java/nio/CharBuffer.java2007-04-12 21:35:33.0 +0100 +++ java/nio/CharBuffer.java2008-04-08 20:34:47.0 +0100 @@ -39,6 +39,7 @@ package java.nio; import java.io.IOException; +import gnu.classpath.Pointer; /** * @since 1.4 @@ -46,13 +47,14 @@ public abstract class CharBuffer extends Buffer implements ComparableCharBuffer, CharSequence, Readable, Appendable { - int array_offset; - char[] backing_buffer; + final int array_offset; + final char[] backing_buffer; - CharBuffer (int capacity, int limit, int position, int mark) + CharBuffer (int capacity, int limit, int position, int mark, Pointer address, char[] backing_buffer, int array_offset) { -super (capacity, limit, position, mark); -array_offset = 0; +super (capacity, limit, position, mark, address); +this.backing_buffer = backing_buffer; +this.array_offset = array_offset; } /** --- java/nio/CharSequenceBuffer.java2007-04-12 21:35:33.0 +0100 +++ java/nio/CharSequenceBuffer.java2008-04-08 16:22:51.0 +0100 @@ -48,7 +48,7 @@ /** * The wrapped char sequence. */ - private CharSequence charSequence; + private final
Re: Inconvertible types error in EnumSet.java
Trevor Harmon wrote: On Mar 16, 2008, at 5:33 PM, Andrew John Hughes wrote: Version 1.5 of Sun's javac is broken. Please use an alternate compiler, such as ecj, or a newer version of javac, such as OpenJDK javac or the version that comes with JDK 1.6. What about jikes? I guess the 0.97.1 release no longer works with jikes? Trevor The jikes Java to bytecode compiler only supports Java 1.4 and has been unable to build Classpath since the introduction of generics in release 0.95 (April 23rd 2007). Jikes RVM builds Classpath with ECJ version 3.2 (version 3.3 generates invalid bytecode when compiling Classpath - this is fixed in the first milestone after ECJ 3.3, but most Linux distributions ship with the broken ECJ). The broken javac problem is also present in other 1.5 JDKs (e.g. BEA, IBM), and is actually a different bug with the initial 1.5 releases. Regards, Ian Rogers -- http://www.cs.man.ac.uk/~irogers
Re: brandweg hacking session on friday
Dalibor Topic wrote: I'll be in Brussels from 12h on. So I'd either suggest meeting at Hotel Barry at 12:30, or that we meet at Brussels Centraal train station, (my train from Luxembourg arrives 11:47), grab some food, and move over to Hotel Barry to hack on BrandWeg afterwards, until 5pm, and then to move over to BXL. cheers, dalibor topic Hi, well the hotel barry is pretty (very) basic but the wifi seems ok (just used it for a skype conversation without any noticeable break up). I'm in room xx and my phone number is +44 xxx xxx . Is the centraal train station the midi train station? If so, I should be able to find my way there and loiter at about noon. I like to eat food too, so I'd suggest we meet, eat and then hack. Just FYI I have a few objectives that I'd like to work towards from the hacking: 1) get a Jikes RVM build configuration that can work with BrandWeg 2) test ECJ and x10c with BrandWeg 3) look at making the java.math configuration of BrandWeg pluggable between the Classpath and OpenJDK versions (a couple of benchmarks hit java.math code and it would be nice to rule it out as a source of performance loss). I imagine this could spark some conversation on how we track code in BrandWeg, acknowledgements, how to configure choices like this. 4) think of any other problems like number 3 Regards, Ian
Re: brandweg hacking session on friday
Dalibor Topic wrote: Andrew John Hughes wrote: Thanks for organising this. I should arrive in Brussels around 4pm on the Friday, so will probably be available around an hour from then I guess (given time to find the hotel and check in, etc.). My preference would be for somewhere with food and drink, but depends on the time we have and the ease of finding such a place. I'll leave that up to those who know Brussels better than I... ;) Should we meet at the BXL at Grand Place from 5pm on? I take it that someone has a laptop or something, if we want this to be a practical session? Sure, I'll bring mine along, and a checkout of the classpath, openjdk and brandweg trees. ;) Hi, apologies for my delay in responding. I will be available all day Friday, so I'd suggest we start earlier (I'm coming to Brussels on the Thursday). I should have wifi access in the Hotel Barry. Could we meet in the morning, maybe at the Hotel Barry? Thanks, Ian
Re: [cp-patches] RFC: Double.doubleToLongBits simplified
Dalibor Topic wrote: Hi all, I've implemented doubleToLongBits without requring a VMDouble method of the same name. It would let us remove one method from the VM interface for the next version, and the corresoponding native code. OK to commit? (I'd do the equivalent patch for Float, too). * java/lang/Double.java (doubleToLongBits): Simplified. cheers, dalibor topic Hi, if this life makes things easier for you then its a good thing. The Jikes RVM already does this at the VMDouble level, and just has a doubleAsRawLongBits magic/native method. So, I'm not sure if this change shouldn't be pushed down into VMDouble, or at least if it is done in Double the obsolete doubleToLongBits call in VMDouble should be removed. Thanks, Ian
Re: [cp-patches] RFC: use helper method to clone char array in java.lang.String
Tom Tromey wrote: Ian == Ian Rogers [EMAIL PROTECTED] writes: Ian Please let me know if you think this patch is suitable for Ian inclusion. It looks fine. I do have one nit, which is that we put spaces around operators... this problem is pervasive in the patch, but here's one example: Ian +newStr[x-offset] = newChar; That should read newStr[x - offset] = newChar; Tom Thanks Tom, here is a revised patch that if there are no other problems I'd like to commit today. Regards, Ian Index: ChangeLog === RCS file: /sources/classpath/classpath/ChangeLog,v retrieving revision 1.9481 diff -u -r1.9481 ChangeLog --- ChangeLog 6 Feb 2008 19:00:44 - 1.9481 +++ ChangeLog 7 Feb 2008 09:21:01 - @@ -1,3 +1,8 @@ +2008-02-07 Ian Rogers [EMAIL PROTECTED] + + * java/lang/String.java + Only copy live portion of String. Use array copies in preference to clone. + 2008-02-05 Ian Rogers [EMAIL PROTECTED] * gnu/java/lang/reflect/TypeSignature.java Index: java/lang/String.java === RCS file: /sources/classpath/classpath/java/lang/String.java,v retrieving revision 1.87 diff -u -r1.87 String.java --- java/lang/String.java 23 Nov 2007 15:04:25 - 1.87 +++ java/lang/String.java 7 Feb 2008 09:21:01 - @@ -1303,13 +1303,13 @@ break; if (i 0) return this; -char[] newStr = (char[]) value.clone(); -newStr[x] = newChar; +char[] newStr = toCharArray(); +newStr[x - offset] = newChar; while (--i = 0) if (value[++x] == oldChar) -newStr[x] = newChar; +newStr[x - offset] = newChar; // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } /** @@ -1450,23 +1450,25 @@ // Now we perform the conversion. Fortunately, there are no multi-character // lowercase expansions in Unicode 3.0.0. -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); do { char ch = value[x]; // Hardcoded special case. if (ch != '\u0049') { -newStr[x++] = Character.toLowerCase(ch); +newStr[x - offset] = Character.toLowerCase(ch); } else { -newStr[x++] = '\u0131'; +newStr[x - offset] = '\u0131'; } +x++; } while (--i = 0); // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } /** @@ -1504,16 +1506,18 @@ // Now we perform the conversion. Fortunately, there are no // multi-character lowercase expansions in Unicode 3.0.0. -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); do { char ch = value[x]; // Hardcoded special case. -newStr[x++] = Character.toLowerCase(ch); +newStr[x - offset] = Character.toLowerCase(ch); +x++; } while (--i = 0); // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } } @@ -1557,22 +1561,24 @@ i = count; if (expand == 0) { -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); while (--i = 0) { char ch = value[x]; // Hardcoded special case. if (ch != '\u0069') { -newStr[x++] = Character.toUpperCase(ch); +newStr[x - offset] = Character.toUpperCase(ch); } else { -newStr[x++] = '\u0130'; +newStr[x - offset] = '\u0130'; } +x++; } // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } // Expansion is necessary. @@ -1642,14 +1648,16 @@ i = count; if (expand == 0) { -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count - (x - offset)); while (--i = 0) { char ch = value[x]; -newStr[x++] = Character.toUpperCase(ch); +newStr[x - offset] = Character.toUpperCase(ch
Re: [cp-patches] RFC: tweaks to java.util.zip.ZipEntry
Mark Wielaard wrote: On Tue, 2008-02-05 at 06:07 -0700, Tom Tromey wrote: Ian == Ian Rogers [EMAIL PROTECTED] writes: Ian the attached patch stops the lazy initialization of a Calendar object Ian in ZipEntry and instead uses a static final one. I thought this could lead to odd results sometimes, when the calendrical data is in a zip. But it is hard to remember. Maybe a bit of archaeology is in order -- looking through the cvs logs or the list archives to see why the code is the way it is. (That info should be in comments, of course...) I don't remember all the details, but here are some pointers: http://gcc.gnu.org/ml/java-patches/2002-q4/msg00294.html http://gcc.gnu.org/ml/java/2003-03/msg00253.html http://gcc.gnu.org/ml/java/2003-11/msg00105.html Sorry for being lazy myself... Cheers, Mark Here's a revision to my original patch that only uses the copy constructor in the case the class is a regular ZipEntry. As Mark pointed out, the normal case for a ZipEntry is that we just read it, its therefore only when writing out we may need to convert between the DOS and millisecond time representations. Having a global shared Calendar causes bootstrap issues, so what the patch does is just uses a locally created Calendar in the case we must convert from DOS to millisecond time or vice versa. The time value is cached so that we only take the hit of using Calendar once per conversion, as opposed to frequently in some cases before. The net result is to push up the size of a ZipEntry, avoid boot strap issues, possibly speed up some patterns of getting and setting the entry's time but take a hit in creating a Calendar instance when a conversion is necessary (ie potentially when writing out zip entries). I think this is what we probably want, but would welcome feedback. Thanks, Ian Index: java/util/zip/ZipEntry.java === RCS file: /sources/classpath/classpath/java/util/zip/ZipEntry.java,v retrieving revision 1.20 diff -u -r1.20 ZipEntry.java --- java/util/zip/ZipEntry.java 7 Oct 2007 18:48:46 - 1.20 +++ java/util/zip/ZipEntry.java 7 Feb 2008 10:09:38 - @@ -50,23 +50,39 @@ */ public class ZipEntry implements ZipConstants, Cloneable { - private static final int KNOWN_SIZE = 1; - private static final int KNOWN_CSIZE = 2; - private static final int KNOWN_CRC= 4; - private static final int KNOWN_TIME = 8; - private static final int KNOWN_EXTRA = 16; - - private static Calendar cal; - - private String name; + private static final byte KNOWN_SIZE= 1; + private static final byte KNOWN_CSIZE = 2; + private static final byte KNOWN_CRC = 4; + private static final byte KNOWN_TIME= 8; + private static final byte KNOWN_DOSTIME = 16 + private static final byte KNOWN_EXTRA = 32; + + /** Immutable name of the entry */ + private final String name; + /** Uncompressed size */ private int size; + /** Compressed size */ private long compressedSize = -1; + /** CRC of uncompressed data */ private int crc; + /** Comment or null if none */ + private String comment = null; + /** The compression method. Either DEFLATED or STORED, by default -1. */ + private byte method = -1; + /** Flags specifying what we know about this entry */ + private byte known = 0; + /** + * The 32bit DOS encoded format for the time of this entry. Only valid if + * KNOWN_DOSTIME is set in known. + */ private int dostime; - private short known = 0; - private short method = -1; + /** + * The 64bit Java encoded millisecond time since the beginning of the epoch. + * Only valid if KNOWN_TIME is set in known. + */ + private long time; + /** Extra data */ private byte[] extra = null; - private String comment = null; int flags; /* used by ZipOutputStream */ int offset; /* used by ZipFile and ZipOutputStream */ @@ -113,6 +129,7 @@ compressedSize = e.compressedSize; crc = e.crc; dostime = e.dostime; +time = e.time; method = e.method; extra = e.extra; comment = e.comment; @@ -121,37 +138,60 @@ final void setDOSTime(int dostime) { this.dostime = dostime; -known |= KNOWN_TIME; +known |= KNOWN_DOSTIME; +known = ~KNOWN_TIME; } final int getDOSTime() { -if ((known KNOWN_TIME) == 0) - return 0; -else +if ((known KNOWN_DOSTIME) != 0) return dostime; +else if ((known KNOWN_TIME) != 0) + { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(time); + dostime = (cal.get(Calendar.YEAR) - 1980 0x7f) 25 + | (cal.get(Calendar.MONTH) + 1) 21 + | (cal.get(Calendar.DAY_OF_MONTH)) 16 + | (cal.get(Calendar.HOUR_OF_DAY)) 11 + | (cal.get(Calendar.MINUTE)) 5 + | (cal.get(Calendar.SECOND)) 1; + known |= KNOWN_DOSTIME; + return dostime; + } +else
[cp-patches] FYI: changes of StringBuffer to StringBuilder, new Number(x) to Number.valueOf(x), add final to a few private fields and avoid creating Integer objects for the sake of comparison
Apologies this was committed yesterday and I should have posted the patch here earlier. Ian CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers 08/02/05 14:59:06 Modified files: gnu/java/lang/reflect: TypeSignature.java java/io: BufferedReader.java DataInputStream.java java/lang : StackTraceElement.java Throwable.java java/lang/reflect: Proxy.java java/net : URI.java URLClassLoader.java URLEncoder.java java/text : SimpleDateFormat.java java/util : AbstractMap.java Calendar.java Date.java Hashtable.java Log message: 2008-02-05 Ian Rogers [EMAIL PROTECTED] * gnu/java/lang/reflect/TypeSignature.java * java/io/BufferedReader.java * java/io/DataInputStream.java * java/lang/StackTraceElement.java * java/lang/Throwable.java * java/lang/reflect/Proxy.java * java/net/URI.java * java/net/URLClassLoader.java * java/net/URLEncoder.java * java/text/SimpleDateFormat.java * java/util/AbstractMap.java * java/util/Calendar.java * java/util/Date.java * java/util/Hashtable.java Use StringBuilder in preference to StringBuffer * java/util/Calendar.java * java/util/Hashtable.java Make private fields that can be final, final * java/net/URI.java Avoid creating Integer objects for the sake of comparison * java/lang/reflect/Proxy.java * java/text/SimpleDateFormat.java Swap use of new Character/Integer to use of valueOf methods Index: gnu/java/lang/reflect/TypeSignature.java === RCS file: /sources/classpath/classpath/gnu/java/lang/reflect/TypeSignature.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- gnu/java/lang/reflect/TypeSignature.java2 Jul 2005 20:32:12 - 1.14 +++ gnu/java/lang/reflect/TypeSignature.java5 Feb 2008 14:59:04 - 1.15 @@ -239,7 +239,7 @@ public static String getEncodingOfMethod(Method m) { Class[] paramTypes = m.getParameterTypes(); -StringBuffer buf = new StringBuffer().append('('); +StringBuilder buf = new StringBuilder((); for (int i = 0; i paramTypes.length; i++) buf.append(getEncodingOfClass(paramTypes[i].getName(), true)); buf.append(')').append(getEncodingOfClass(m.getReturnType().getName(), @@ -261,7 +261,7 @@ public static String getEncodingOfConstructor(Constructor c) { Class[] paramTypes = c.getParameterTypes(); -StringBuffer buf = new StringBuffer().append('('); +StringBuilder buf = new StringBuilder((); for (int i = 0; i paramTypes.length; i++) buf.append(getEncodingOfClass(paramTypes[i].getName(), true)); buf.append()V); Index: java/io/BufferedReader.java === RCS file: /sources/classpath/classpath/java/io/BufferedReader.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- java/io/BufferedReader.java 2 Jul 2005 20:32:37 - 1.27 +++ java/io/BufferedReader.java 5 Feb 2008 14:59:04 - 1.28 @@ -89,11 +89,6 @@ static final int DEFAULT_BUFFER_SIZE = 8192; /** - * The line buffer for codereadLine/code. - */ - private StringBuffer sbuf = null; - - /** * Create a new codeBufferedReader/code that will read from the * specified subordinate stream with a default buffer size of 8192 chars. * @@ -455,10 +450,7 @@ pos++; return str; } -if (sbuf == null) - sbuf = new StringBuffer(200); -else - sbuf.setLength(0); +StringBuilder sbuf = new StringBuilder(200); sbuf.append(buffer, pos, i - pos); pos = i; // We only want to return null when no characters were read before Index: java/io/DataInputStream.java === RCS file: /sources/classpath/classpath/java/io/DataInputStream.java,v retrieving revision 1.32 retrieving revision 1.33 diff -u -r1.32 -r1.33 --- java/io/DataInputStream.java29 Jan 2008 22:30:44 - 1.32 +++ java/io/DataInputStream.java5 Feb 2008 14:59:04 - 1.33 @@ -350,7 +350,7 @@ */ public final String readLine() throws IOException { -StringBuffer strb = new StringBuffer(); +StringBuilder strb = new StringBuilder(); while (true) { @@ -747,7 +747,7 @@ { // Give StringBuffer an initial estimated size to avoid // enlarge buffer frequently -StringBuffer strbuf = new StringBuffer (buf.length / 2 + 2); +StringBuilder strbuf
[commit-cp] classpath ChangeLog
CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers08/02/06 19:00:46 Modified files: . : ChangeLog Log message: Changelog missed from last commit CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/ChangeLog?cvsroot=classpathr1=1.9480r2=1.9481
Re: [cp-patches] RFC: use helper method to clone char array in java.lang.String
Robert Lougher wrote: Hi, On 2/4/08, Ian Rogers [EMAIL PROTECTED] wrote: Hi, xalan performs 1.4 million char array clones per iteration of the normal size DaCapo benchmark. All of the character array clones are coming from java.lang.String. The attached patch changes the use of char[].clone (which maps to java.lang.Object.clone) to a helper method that allocates the character array and then array copies from the source to the new array. On the Jikes RVM I get the following performance results from 10 iterations of DaCapo using the large data set size: current java.lang.String using char[].clone: run 1: 99157ms run 2: 98700ms run 3: 97927ms patched java.lang.String using the helper routine: run 1: 97710ms run 2: 97406ms run 3: 96762ms The speed up is between 0.22% and 1.2%. Do people think using the helper is a sensible change? I would like to see evidence that this is a win, or at least has no slowdown on other VMs (i.e. it is VM independent). I think it would be inappropriate if it was only to address implementation issues in JikesRVM. For example, why is the helper faster than clone? Surely all clone() should be doing is an alloc and then an arraycopy? Rob. Hi Rob, Twisti, Tromey, so what happens in the case of the clone is: 1) call into clone 2) determine that this is a clone of an array 3) create array of same length as that which we're cloning (we inline as far as here in the case of Jikes RVM) 4) call into array copy 5) determine type of array we're copying 6) check for overlaps 7) copy arrays 8) leave array copy and clone 9) check that the resulting array casts back to a char[] in the case of the helper method: 1) call into helper method 2) create array of same length as that which we're cloning 3) call into array copy 4) determine type of array we're copying 5) check for overlaps 6) copy arrays (we inline as far as here in the case of Jikes RVM) 7) leave array copy and helper method The Jikes RVM is performing a lot of partial evaluation to determine that a lot of bounds checks, casts, instanceof tests are unnecessary and the result is code that just allocates the array and performs a copy without checks. In the case of clone our partial evaluation breaks down because we need the results of runtime reflection calls or to know that these calls are analogous to bytecodes when the arguments are constant. I plan to do optimizations in this direction, but I don't want to flatter the optimizations when they probably only effect a small number of situations and alternate view is that code may have been written in a slightly esoteric manner. I think the Jikes RVM is performing more optimizations than other Classpath VMs, so its likely the performance win will be less marked for those VMs (if there's any win at all). I think Tromey's point is valid and I'll try to write a better patch to address it. Once I have posted the new patch maybe we can return to the question as to whether to make the change. Thanks for all the feedback! Ian
[cp-patches] RFC: tweaks to java.util.zip.ZipEntry
Hi, the attached patch stops the lazy initialization of a Calendar object in ZipEntry and instead uses a static final one. It also modifies the clone method to instead of using Object.clone to use the ZipEntry's own copy constructor. This patch has implications to bootstrapping and subtly changes ZipEntry's behavior. I welcome feedback prior to committing. Thanks, Ian --- java/util/zip/ZipEntry.java 2007-10-07 19:48:46.0 +0100 +++ java/util/zip/ZipEntry.java 2008-02-05 12:32:22.0 + @@ -56,9 +56,10 @@ private static final int KNOWN_TIME = 8; private static final int KNOWN_EXTRA = 16; - private static Calendar cal; + /** Calendar used for time computations */ + private static final Calendar cal = Calendar.getInstance(); - private String name; + private final String name; private int size; private long compressedSize = -1; private int crc; @@ -140,18 +141,13 @@ */ public Object clone() { -try - { - // The JCL says that the `extra' field is also copied. - ZipEntry clone = (ZipEntry) super.clone(); - if (extra != null) - clone.extra = (byte[]) extra.clone(); - return clone; - } -catch (CloneNotSupportedException ex) +ZipEntry clone = new ZipEntry(this); +if (extra != null) { - throw new InternalError(); + clone.extra = new byte[extra.length]; + System.arraycopy(extra, 0, clone.extra, 0, extra.length); } +return clone; } /** @@ -169,7 +165,6 @@ */ public void setTime(long time) { -Calendar cal = getCalendar(); synchronized (cal) { cal.setTimeInMillis(time); @@ -204,7 +199,6 @@ try { - cal = getCalendar(); synchronized (cal) { cal.set(year, mon, day, hrs, min, sec); @@ -219,14 +213,6 @@ } } - private static synchronized Calendar getCalendar() - { -if (cal == null) - cal = Calendar.getInstance(); - -return cal; - } - /** * Sets the size of the uncompressed data. * @exception IllegalArgumentException if size is not in 0..0xL
Re: [cp-patches] RFC: use helper method to clone char array in java.lang.String
Hello all, here's a revised patch that removes the use of clone in preference to just array copying the live portion of the String. Here are the DaCapo xalan figures: run 1: 97972ms run 2: 97837ms run 3: 95290ms which represents anything from a 0.04% slow down to a 2.8% speed up. There will also be a space saving as we're not cloning whole arrays any more. Please let me know if you think this patch is suitable for inclusion. Thanks, Ian --- java/lang/String.java 2008-01-23 09:01:02.0 + +++ java/lang/String.java 2008-02-05 10:07:56.0 + @@ -1303,13 +1303,13 @@ break; if (i 0) return this; -char[] newStr = (char[]) value.clone(); -newStr[x] = newChar; +char[] newStr = toCharArray(); +newStr[x-offset] = newChar; while (--i = 0) if (value[++x] == oldChar) -newStr[x] = newChar; +newStr[x-offset] = newChar; // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } /** @@ -1450,23 +1450,25 @@ // Now we perform the conversion. Fortunately, there are no multi-character // lowercase expansions in Unicode 3.0.0. -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count-(x-offset)); do { char ch = value[x]; // Hardcoded special case. if (ch != '\u0049') { -newStr[x++] = Character.toLowerCase(ch); +newStr[x-offset] = Character.toLowerCase(ch); } else { -newStr[x++] = '\u0131'; +newStr[x-offset] = '\u0131'; } +x++; } while (--i = 0); // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } /** @@ -1504,16 +1506,18 @@ // Now we perform the conversion. Fortunately, there are no // multi-character lowercase expansions in Unicode 3.0.0. -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count-(x-offset)); do { char ch = value[x]; // Hardcoded special case. -newStr[x++] = Character.toLowerCase(ch); +newStr[x-offset] = Character.toLowerCase(ch); +x++; } while (--i = 0); // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } } @@ -1557,22 +1561,24 @@ i = count; if (expand == 0) { -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count-(x-offset)); while (--i = 0) { char ch = value[x]; // Hardcoded special case. if (ch != '\u0069') { -newStr[x++] = Character.toUpperCase(ch); +newStr[x-offset] = Character.toUpperCase(ch); } else { -newStr[x++] = '\u0130'; +newStr[x-offset] = '\u0130'; } +x++; } // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } // Expansion is necessary. @@ -1642,14 +1648,16 @@ i = count; if (expand == 0) { -char[] newStr = (char[]) value.clone(); +char[] newStr = new char[count]; +VMSystem.arraycopy(value, offset, newStr, 0, count-(x-offset)); while (--i = 0) { char ch = value[x]; -newStr[x++] = Character.toUpperCase(ch); +newStr[x-offset] = Character.toUpperCase(ch); +x++; } // Package constructor avoids an array copy. -return new String(newStr, offset, count, true); +return new String(newStr, 0, count, true); } // Expansion is necessary. @@ -1730,9 +1738,6 @@ */ public char[] toCharArray() { -if (count == value.length) - return (char[]) value.clone(); - char[] copy = new char[count]; VMSystem.arraycopy(value, offset, copy, 0, count); return copy;
[cp-patches] RFC: use helper method to clone char array in java.lang.String
Hi, xalan performs 1.4 million char array clones per iteration of the normal size DaCapo benchmark. All of the character array clones are coming from java.lang.String. The attached patch changes the use of char[].clone (which maps to java.lang.Object.clone) to a helper method that allocates the character array and then array copies from the source to the new array. On the Jikes RVM I get the following performance results from 10 iterations of DaCapo using the large data set size: current java.lang.String using char[].clone: run 1: 99157ms run 2: 98700ms run 3: 97927ms patched java.lang.String using the helper routine: run 1: 97710ms run 2: 97406ms run 3: 96762ms The speed up is between 0.22% and 1.2%. Do people think using the helper is a sensible change? Thanks, Ian --- java/lang/String.java 2008-01-23 09:01:02.0 + +++ java/lang/String.java 2008-02-04 13:43:02.0 + @@ -1284,6 +1284,13 @@ return new String(newStr, 0, newStr.length, true); } + private static char[] cloneCharArray(char[] src) + { +char[] copy = new char[src.length]; +VMSystem.arraycopy(src, 0, copy, 0, src.length); +return copy; + } + /** * Replaces every instance of a character in this String with a new * character. If no replacements occur, this is returned. @@ -1303,7 +1310,7 @@ break; if (i 0) return this; -char[] newStr = (char[]) value.clone(); +char[] newStr = cloneCharArray(value); newStr[x] = newChar; while (--i = 0) if (value[++x] == oldChar) @@ -1450,7 +1457,7 @@ // Now we perform the conversion. Fortunately, there are no multi-character // lowercase expansions in Unicode 3.0.0. -char[] newStr = (char[]) value.clone(); +char[] newStr = cloneCharArray(value); do { char ch = value[x]; @@ -1504,7 +1511,7 @@ // Now we perform the conversion. Fortunately, there are no // multi-character lowercase expansions in Unicode 3.0.0. -char[] newStr = (char[]) value.clone(); +char[] newStr = cloneCharArray(value); do { char ch = value[x]; @@ -1557,7 +1564,7 @@ i = count; if (expand == 0) { -char[] newStr = (char[]) value.clone(); +char[] newStr = cloneCharArray(value); while (--i = 0) { char ch = value[x]; @@ -1642,7 +1649,7 @@ i = count; if (expand == 0) { -char[] newStr = (char[]) value.clone(); +char[] newStr = cloneCharArray(value); while (--i = 0) { char ch = value[x]; @@ -1731,7 +1738,7 @@ public char[] toCharArray() { if (count == value.length) - return (char[]) value.clone(); + return cloneCharArray(value); char[] copy = new char[count]; VMSystem.arraycopy(value, offset, copy, 0, count);
Re: [cp-patches] FYI: more CopyOnWriteArrayList fixlets
Mario Torre wrote: I'm committing this one, that fixes a couple of woops! I did in the last patch, as well as some other methods that were already broken (read: not my fault :) Now it should pass all the public domain tck166 tests, except for subList. Thanks, Mario This is great! The Jikes RVM has gone from passing 41 out of 56 JSR166 TCK tests to passing 43 out of 56: Pre-patch: http://www.cs.man.ac.uk/~irogers/jsr166-old/ Current status: http://www.cs.man.ac.uk/~irogers/jsr166/ Looking at the current status, TimeUnitTest looks to be failing as the version of JSR166 in the external directory is old enough not to be declaring TimeUnit.MILLISECONDS: http://www.cs.man.ac.uk/~irogers/jsr166/production/jsr166-tck/TimeUnitTest.default-output.txt I wonder if some of the other failures could be down to an old JSR 166. What's the protocol to update the code in the external directory? Thanks, Ian
[commit-cp] classpath AUTHORS
CVSROOT:/cvsroot/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 14:38:58 Modified files: . : AUTHORS Log message: add myself CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/AUTHORS?cvsroot=classpathr1=1.41r2=1.42
[commit-cp] classpath/java/lang Long.java
CVSROOT:/cvsroot/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 14:50:53 Modified files: java/lang : Long.java Log message: Remove unnecessary synchronized from Long.valueOf(long) CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/Long.java?cvsroot=classpathr1=1.24r2=1.25
[commit-cp] classpath/java io/FileOutputStream.java io/Prin...
CVSROOT:/cvsroot/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 14:58:14 Modified files: java/io: FileOutputStream.java PrintStream.java java/util : Locale.java Log message: Make private fields that can be final, final. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/java/io/FileOutputStream.java?cvsroot=classpathr1=1.38r2=1.39 http://cvs.savannah.gnu.org/viewcvs/classpath/java/io/PrintStream.java?cvsroot=classpathr1=1.29r2=1.30 http://cvs.savannah.gnu.org/viewcvs/classpath/java/util/Locale.java?cvsroot=classpathr1=1.39r2=1.40
[commit-cp] classpath/java/lang String.java
CVSROOT:/cvsroot/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 15:04:25 Modified files: java/lang : String.java Log message: Separate Turkish case conversion into their own routines. Switch from using String.equals to == for the language detection as Locale's language is interned. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/java/lang/String.java?cvsroot=classpathr1=1.86r2=1.87
[commit-cp] classpath/gnu/java/nio/charset ByteCharset.java...
CVSROOT:/cvsroot/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 15:12:17 Modified files: gnu/java/nio/charset: ByteCharset.java Cp424.java Cp437.java Cp737.java Cp775.java Cp850.java Cp852.java Cp855.java Cp857.java Cp860.java Cp861.java Cp862.java Cp863.java Cp864.java Cp865.java Cp866.java Cp869.java Cp874.java EncodingHelper.java ISO_8859_1.java ISO_8859_13.java ISO_8859_15.java ISO_8859_2.java ISO_8859_3.java ISO_8859_4.java ISO_8859_5.java ISO_8859_6.java ISO_8859_7.java ISO_8859_8.java ISO_8859_9.java KOI_8.java MS874.java MacCentralEurope.java MacCroatian.java MacCyrillic.java MacDingbat.java MacGreek.java MacIceland.java MacRoman.java MacRomania.java MacSymbol.java MacThai.java MacTurkish.java Provider.java US_ASCII.java Windows1250.java Windows1251.java Windows1252.java Windows1253.java Windows1254.java Windows1255.java Windows1256.java Windows1257.java Windows1258.java Log message: Addition of array optimized encoding/decoding for byte character sets, US_ASCII and ISO_8859_1. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ByteCharset.java?cvsroot=classpathr1=1.6r2=1.7 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp424.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp437.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp737.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp775.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp850.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp852.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp855.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp857.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp860.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp861.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp862.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp863.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp864.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp865.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp866.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp869.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/Cp874.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/EncodingHelper.java?cvsroot=classpathr1=1.4r2=1.5 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_1.java?cvsroot=classpathr1=1.7r2=1.8 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_13.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_15.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_2.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_3.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_4.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_5.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_6.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_7.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ISO_8859_8.java?cvsroot=classpathr1=1.2r2=1.3 http://cvs.savannah.gnu.org/viewcvs
Re: [cp-patches] Streamline String.toUpper/LowerCase
Committed. Ian Rogers wrote: Hi, the attached patch separates out the special case of making a string upper and lower case for the Turkish Locale. As Locale's language should be interned, the tr.equals test is replaced with tr ==. Thanks, Ian
Re: [cp-patches] Fix for GTk peers with Classpath 0.96.1
Committed. Ian Rogers wrote: Hi, attached is a patch required to make JNI GTk peers work on 32bit architectures. Regards, Ian
Re: [cp-patches] Patch to gnu.java.nio.charset
Committed. Ian Rogers wrote: Hi, the attached patch adds efficient support for array encoding/decoding character sets to all ByteCharsets, US_ASCII and ISO_8859_1. It does this by using 2 package private helper classes. The patch also makes fields and classes that can be final, final. The patch also adds the use of generic types where appropriate. Thanks, Ian
Re: [cp-patches] Make fields that aren't final, final
committed. Ian Rogers wrote: Hi, the attached patch makes a few fields that could be final, final. Thanks, Ian
[cp-patches] FYI: java.lang.Long remove unnecessary synchronized
Hi, Committed. Regards, Ian Index: Long.java === RCS file: /cvsroot/classpath/classpath/java/lang/Long.java,v retrieving revision 1.24 diff -u -r1.24 Long.java --- Long.java 10 Dec 2006 20:25:44 - 1.24 +++ Long.java 23 Nov 2007 14:49:12 - @@ -296,7 +296,7 @@ * @return the codeLong/code * @since 1.5 */ - public static synchronized Long valueOf(long val) + public static Long valueOf(long val) { // We aren't required to cache here. We could, though perhaps we // ought to consider that as an empirical question.
Re: New GNU Classpath developer Ian Rogers
Mark Wielaard wrote: Hi all, I am happy to announce that Ian is now one of our active hackers with commit access. Ian has been pushing useful patches for a long time now and is one of the JikesRVM hackers. Ian, even though you have been contributing to GNU Classpath in the past you name is missing in the AUTHORS file. Please post a patch and ChangeLog entry to add yourself to the AUTHORS file to the classpath-patches mailinglist. You can consider that patch pre-approved so feel free to commit it immediately as a test of your new powers. But remember that with power comes responsibility! (*) Thanks, Mark (*) http://www.gnu.org/software/classpath/docs/hacking.html Hi Mark and everyone, thanks for the welcome. I've used my powers and added myself to the AUTHORS list. Thanks again, Ian
[commit-cp] classpath/gnu/java/nio/charset ByteEncodeLoopHe...
CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 16:11:17 Added files: gnu/java/nio/charset: ByteEncodeLoopHelper.java ByteDecodeLoopHelper.java Log message: Helper classes for array optimized byte character set encoding/decoding CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ByteEncodeLoopHelper.java?cvsroot=classpathrev=1.1 http://cvs.savannah.gnu.org/viewcvs/classpath/gnu/java/nio/charset/ByteDecodeLoopHelper.java?cvsroot=classpathrev=1.1
[commit-cp] classpath ChangeLog
CVSROOT:/sources/classpath Module name:classpath Changes by: Ian Rogers irogers07/11/23 17:06:57 Modified files: . : ChangeLog Log message: 2007-11-23 Ian Rogers [EMAIL PROTECTED] * java/io/FileOutputStream.java, * java/io/PrintStream.java, * java/util/Locale.java: Make fields that can be final, final. * gnu/java/nio/charset/ByteCharset.java, * gnu/java/nio/charset/Cp424.java, * gnu/java/nio/charset/Cp437.java, * gnu/java/nio/charset/Cp737.java, * gnu/java/nio/charset/Cp775.java, * gnu/java/nio/charset/Cp850.java, * gnu/java/nio/charset/Cp852.java, * gnu/java/nio/charset/Cp855.java, * gnu/java/nio/charset/Cp857.java, * gnu/java/nio/charset/Cp860.java, * gnu/java/nio/charset/Cp861.java, * gnu/java/nio/charset/Cp862.java, * gnu/java/nio/charset/Cp863.java, * gnu/java/nio/charset/Cp864.java, * gnu/java/nio/charset/Cp865.java, * gnu/java/nio/charset/Cp866.java, * gnu/java/nio/charset/Cp869.java, * gnu/java/nio/charset/Cp874.java, * gnu/java/nio/charset/EncodingHelper.java, * gnu/java/nio/charset/ISO_8859_13.java, * gnu/java/nio/charset/ISO_8859_15.java, * gnu/java/nio/charset/ISO_8859_1.java, * gnu/java/nio/charset/ISO_8859_2.java, * gnu/java/nio/charset/ISO_8859_3.java, * gnu/java/nio/charset/ISO_8859_4.java, * gnu/java/nio/charset/ISO_8859_5.java, * gnu/java/nio/charset/ISO_8859_6.java, * gnu/java/nio/charset/ISO_8859_7.java, * gnu/java/nio/charset/ISO_8859_8.java, * gnu/java/nio/charset/ISO_8859_9.java, * gnu/java/nio/charset/KOI_8.java, * gnu/java/nio/charset/MacCentralEurope.java, * gnu/java/nio/charset/MacCroatian.java, * gnu/java/nio/charset/MacCyrillic.java, * gnu/java/nio/charset/MacDingbat.java, * gnu/java/nio/charset/MacGreek.java, * gnu/java/nio/charset/MacIceland.java, * gnu/java/nio/charset/MacRomania.java, * gnu/java/nio/charset/MacRoman.java, * gnu/java/nio/charset/MacSymbol.java, * gnu/java/nio/charset/MacThai.java, * gnu/java/nio/charset/MacTurkish.java, * gnu/java/nio/charset/MS874.java, * gnu/java/nio/charset/Provider.java, * gnu/java/nio/charset/US_ASCII.java, * gnu/java/nio/charset/Windows1250.java, * gnu/java/nio/charset/Windows1251.java, * gnu/java/nio/charset/Windows1252.java, * gnu/java/nio/charset/Windows1253.java, * gnu/java/nio/charset/Windows1254.java, * gnu/java/nio/charset/Windows1255.java, * gnu/java/nio/charset/Windows1256.java, * gnu/java/nio/charset/Windows1257.java, * gnu/java/nio/charset/Windows1258.java, * gnu/java/nio/charset/ByteDecodeLoopHelper.java, * gnu/java/nio/charset/ByteEncodeLoopHelper.java: Optimize for array based buffers. * native/jni/gtk-peer/gtkpeer.c: Make 32bit pointer a global JNI reference. * java/lang/String: (toLowerCaseTurkish): new method. (toUpperCaseTurkish): new method. (toLowerCase): special case Turkish (toUpperCase): likewise. * java/lang/Long: (valueOf): remove unnecessary synchronized. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/ChangeLog?cvsroot=classpathr1=1.9436r2=1.9437
[cp-patches] Greater use of StringBuilder rather than StringBuffer
Hi, the attached patch increases the use of StringBuilder in Classpath rather than StringBuffer. Thanks, Ian Index: gnu/java/lang/reflect/TypeSignature.java === RCS file: /sources/classpath/classpath/gnu/java/lang/reflect/TypeSignature.java,v retrieving revision 1.14 diff -u -r1.14 TypeSignature.java --- gnu/java/lang/reflect/TypeSignature.java2 Jul 2005 20:32:12 - 1.14 +++ gnu/java/lang/reflect/TypeSignature.java20 Oct 2007 11:10:50 - @@ -239,7 +239,7 @@ public static String getEncodingOfMethod(Method m) { Class[] paramTypes = m.getParameterTypes(); -StringBuffer buf = new StringBuffer().append('('); +StringBuilder buf = new StringBuilder((); for (int i = 0; i paramTypes.length; i++) buf.append(getEncodingOfClass(paramTypes[i].getName(), true)); buf.append(')').append(getEncodingOfClass(m.getReturnType().getName(), @@ -261,7 +261,7 @@ public static String getEncodingOfConstructor(Constructor c) { Class[] paramTypes = c.getParameterTypes(); -StringBuffer buf = new StringBuffer().append('('); +StringBuilder buf = new StringBuilder((); for (int i = 0; i paramTypes.length; i++) buf.append(getEncodingOfClass(paramTypes[i].getName(), true)); buf.append()V); Index: java/io/BufferedReader.java === RCS file: /sources/classpath/classpath/java/io/BufferedReader.java,v retrieving revision 1.27 diff -u -r1.27 BufferedReader.java --- java/io/BufferedReader.java 2 Jul 2005 20:32:37 - 1.27 +++ java/io/BufferedReader.java 20 Oct 2007 11:10:50 - @@ -89,11 +89,6 @@ static final int DEFAULT_BUFFER_SIZE = 8192; /** - * The line buffer for codereadLine/code. - */ - private StringBuffer sbuf = null; - - /** * Create a new codeBufferedReader/code that will read from the * specified subordinate stream with a default buffer size of 8192 chars. * @@ -455,10 +450,7 @@ pos++; return str; } -if (sbuf == null) - sbuf = new StringBuffer(200); -else - sbuf.setLength(0); +StringBuilder sbuf = new StringBuilder(200); sbuf.append(buffer, pos, i - pos); pos = i; // We only want to return null when no characters were read before Index: java/io/DataInputStream.java === RCS file: /sources/classpath/classpath/java/io/DataInputStream.java,v retrieving revision 1.31 diff -u -r1.31 DataInputStream.java --- java/io/DataInputStream.java2 Jul 2005 20:32:37 - 1.31 +++ java/io/DataInputStream.java20 Oct 2007 11:10:50 - @@ -349,7 +349,7 @@ */ public final String readLine() throws IOException { -StringBuffer strb = new StringBuffer(); +StringBuilder strb = new StringBuilder(); while (true) { @@ -703,7 +703,7 @@ { // Give StringBuffer an initial estimated size to avoid // enlarge buffer frequently -StringBuffer strbuf = new StringBuffer (buf.length / 2 + 2); +StringBuilder strbuf = new StringBuilder (buf.length / 2 + 2); for (int i = 0; i buf.length; ) { Index: java/lang/StackTraceElement.java === RCS file: /sources/classpath/classpath/java/lang/StackTraceElement.java,v retrieving revision 1.9 diff -u -r1.9 StackTraceElement.java --- java/lang/StackTraceElement.java8 Apr 2006 11:02:12 - 1.9 +++ java/lang/StackTraceElement.java20 Oct 2007 11:10:50 - @@ -202,7 +202,7 @@ */ public String toString() { -StringBuffer sb = new StringBuffer(); +StringBuilder sb = new StringBuilder(); if (declaringClass != null) { sb.append(declaringClass); Index: java/lang/Throwable.java === RCS file: /sources/classpath/classpath/java/lang/Throwable.java,v retrieving revision 1.30 diff -u -r1.30 Throwable.java --- java/lang/Throwable.java2 Jul 2005 20:32:39 - 1.30 +++ java/lang/Throwable.java20 Oct 2007 11:10:50 - @@ -411,7 +411,7 @@ // different threads to get mixed up when written to the same PrintWriter. private String stackTraceString() { -StringBuffer sb = new StringBuffer(); +StringBuilder sb = new StringBuilder(); // Main stacktrace StackTraceElement[] stack = getStackTrace(); @@ -455,7 +455,7 @@ // Adds to the given StringBuffer a line containing the name and // all stacktrace elements minus the last equal ones. - private static void stackTraceStringBuffer(StringBuffer sb, String name, + private static void stackTraceStringBuffer(StringBuilder sb, String name, StackTraceElement[] stack, int equal) { String nl = StaticData.nl; Index: java/lang/reflect/Proxy.java
[cp-patches] Greater use of Number.valueOf rather than new Number
Hi, the attached patch increases the use of Number.valueOf rather than new Number. Thanks, Ian Index: java/beans/PropertyChangeSupport.java === RCS file: /sources/classpath/classpath/java/beans/PropertyChangeSupport.java,v retrieving revision 1.15 diff -u -r1.15 PropertyChangeSupport.java --- java/beans/PropertyChangeSupport.java 12 Feb 2006 13:53:54 - 1.15 +++ java/beans/PropertyChangeSupport.java 20 Oct 2007 11:16:49 - @@ -346,8 +346,8 @@ { if (oldVal != newVal) firePropertyChange(new PropertyChangeEvent(source, propertyName, - new Integer(oldVal), - new Integer(newVal))); + Integer.valueOf(oldVal), + Integer.valueOf(newVal))); } /** Index: java/beans/VetoableChangeSupport.java === RCS file: /sources/classpath/classpath/java/beans/VetoableChangeSupport.java,v retrieving revision 1.13 diff -u -r1.13 VetoableChangeSupport.java --- java/beans/VetoableChangeSupport.java 28 Jun 2006 14:13:40 - 1.13 +++ java/beans/VetoableChangeSupport.java 20 Oct 2007 11:16:49 - @@ -349,8 +349,8 @@ { if (oldVal != newVal) fireVetoableChange(new PropertyChangeEvent(source, propertyName, - new Integer(oldVal), - new Integer(newVal))); + Integer.valueOf(oldVal), + Integer.valueOf(newVal))); } /** Index: java/io/ObjectStreamClass.java === RCS file: /sources/classpath/classpath/java/io/ObjectStreamClass.java,v retrieving revision 1.49 diff -u -r1.49 ObjectStreamClass.java --- java/io/ObjectStreamClass.java 21 Jun 2007 06:19:27 - 1.49 +++ java/io/ObjectStreamClass.java 20 Oct 2007 11:16:49 - @@ -812,7 +812,7 @@ } if (loadedByBootOrApplicationClassLoader(cl)) - uidCache.put(cl,new Long(result)); + uidCache.put(cl,Long.valueOf(result)); } return result; } Index: java/lang/reflect/Array.java === RCS file: /sources/classpath/classpath/java/lang/reflect/Array.java,v retrieving revision 1.17 diff -u -r1.17 Array.java --- java/lang/reflect/Array.java21 Jun 2007 05:39:50 - 1.17 +++ java/lang/reflect/Array.java20 Oct 2007 11:16:49 - @@ -209,19 +209,19 @@ if (array instanceof boolean[]) return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; if (array instanceof byte[]) - return new Byte(((byte[]) array)[index]); + return Byte.valueOf(((byte[]) array)[index]); if (array instanceof char[]) - return new Character(((char[]) array)[index]); + return Character.valueOf(((char[]) array)[index]); if (array instanceof short[]) - return new Short(((short[]) array)[index]); + return Short.valueOf(((short[]) array)[index]); if (array instanceof int[]) - return new Integer(((int[]) array)[index]); + return Integer.valueOf(((int[]) array)[index]); if (array instanceof long[]) - return new Long(((long[]) array)[index]); + return Long.valueOf(((long[]) array)[index]); if (array instanceof float[]) - return new Float(((float[]) array)[index]); + return Float.valueOf(((float[]) array)[index]); if (array instanceof double[]) - return new Double(((double[]) array)[index]); + return Double.valueOf(((double[]) array)[index]); if (array == null) throw new NullPointerException(); throw new IllegalArgumentException(); Index: java/net/DatagramSocket.java === RCS file: /sources/classpath/classpath/java/net/DatagramSocket.java,v retrieving revision 1.50 diff -u -r1.50 DatagramSocket.java --- java/net/DatagramSocket.java17 Nov 2006 15:09:05 - 1.50 +++ java/net/DatagramSocket.java20 Oct 2007 11:16:49 - @@ -403,7 +403,7 @@ if (timeout 0) throw new IllegalArgumentException(Invalid timeout: + timeout); -getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); +getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); } /** @@ -450,7 +450,7 @@ if (size 0) throw new IllegalArgumentException(Buffer size is less than 0); -getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size)); +getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); } /** @@ -497,7 +497,7 @@ if (size 0) throw new
[cp-patches] Make fields that aren't final, final
Hi, the attached patch makes a few fields that could be final, final. Thanks, Ian Index: java/io/FileOutputStream.java === RCS file: /sources/classpath/classpath/java/io/FileOutputStream.java,v retrieving revision 1.38 diff -u -r1.38 FileOutputStream.java --- java/io/FileOutputStream.java 17 Sep 2006 07:31:42 - 1.38 +++ java/io/FileOutputStream.java 20 Oct 2007 11:21:59 - @@ -59,7 +59,7 @@ { private FileDescriptor fd; - private FileChannelImpl ch; + private final FileChannelImpl ch; /** * This method initializes a codeFileOutputStream/code object to write Index: java/io/PrintStream.java === RCS file: /sources/classpath/classpath/java/io/PrintStream.java,v retrieving revision 1.29 diff -u -r1.29 PrintStream.java --- java/io/PrintStream.java10 Dec 2006 20:25:44 - 1.29 +++ java/io/PrintStream.java20 Oct 2007 11:21:59 - @@ -76,7 +76,7 @@ /** * Encoding name */ - private String encoding; + private final String encoding; /** * This boolean indicates whether or not an error has ever occurred @@ -88,7 +88,7 @@ * This is codetrue/code if auto-flush is enabled, * codefalse/code otherwise */ - private boolean auto_flush; + private final boolean auto_flush; /** * This method initializes a new codePrintStream/code object to write @@ -185,16 +185,17 @@ public PrintStream (OutputStream out, boolean auto_flush) { super (out); - +String encoding; try { - this.encoding = SystemProperties.getProperty(file.encoding); + encoding = SystemProperties.getProperty(file.encoding); } catch (SecurityException e){ - this.encoding = ISO8859_1; + encoding = ISO8859_1; } catch (IllegalArgumentException e){ - this.encoding = ISO8859_1; + encoding = ISO8859_1; } catch (NullPointerException e){ - this.encoding = ISO8859_1; + encoding = ISO8859_1; } +this.encoding = encoding; this.auto_flush = auto_flush; } Index: java/util/Locale.java === RCS file: /sources/classpath/classpath/java/util/Locale.java,v retrieving revision 1.38 diff -u -r1.38 Locale.java --- java/util/Locale.java 2 Jan 2007 21:40:20 - 1.38 +++ java/util/Locale.java 20 Oct 2007 11:21:59 - @@ -178,21 +178,21 @@ * * @serial the languange, possibly */ - private String language; + private final String language; /** * The country code, as returned by getCountry(). * * @serial the country, possibly */ - private String country; + private final String country; /** * The variant code, as returned by getVariant(). * * @serial the variant, possibly */ - private String variant; + private final String variant; /** * This is the cached hashcode. When writing to stream, we write -1. @@ -324,13 +324,12 @@ // default locale. if (defaultLocale != null) { -language = convertLanguage(language).intern(); -country = country.toUpperCase().intern(); -variant = variant.intern(); - } -this.language = language; -this.country = country; -this.variant = variant; +language = convertLanguage(language); +country = country.toUpperCase(); + } +this.language = language.intern(); +this.country = country.intern(); +this.variant = variant.intern(); hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode(); } @@ -1022,9 +1021,6 @@ throws IOException, ClassNotFoundException { s.defaultReadObject(); -language = language.intern(); -country = country.intern(); -variant = variant.intern(); hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode(); } } // class Locale
[cp-patches] Streamline String.toUpper/LowerCase
Hi, the attached patch separates out the special case of making a string upper and lower case for the Turkish Locale. As Locale's language should be interned, the tr.equals test is replaced with tr ==. Thanks, Ian Index: java/lang/String.java === RCS file: /sources/classpath/classpath/java/lang/String.java,v retrieving revision 1.86 diff -u -r1.86 String.java --- java/lang/String.java 2 Jan 2007 00:51:01 - 1.86 +++ java/lang/String.java 20 Oct 2007 11:44:55 - @@ -1431,27 +1431,18 @@ } /** - * Lowercases this String according to a particular locale. This uses - * Unicode's special case mappings, as applied to the given Locale, so the - * resulting string may be a different length. - * - * @param loc locale to use - * @return new lowercased String, or this if no characters were lowercased - * @throws NullPointerException if loc is null - * @see #toUpperCase(Locale) - * @since 1.1 + * Convert string to lower case for a Turkish locale that requires special + * handling of '\u0049' */ - public String toLowerCase(Locale loc) + private String toLowerCaseTurkish() { // First, see if the current string is already lower case. -boolean turkish = tr.equals(loc.getLanguage()); int i = count; int x = offset - 1; while (--i = 0) { char ch = value[++x]; -if ((turkish ch == '\u0049') -|| ch != Character.toLowerCase(ch)) +if ((ch == '\u0049') || ch != Character.toLowerCase(ch)) break; } if (i 0) @@ -1464,8 +1455,14 @@ { char ch = value[x]; // Hardcoded special case. -newStr[x++] = (turkish ch == '\u0049') ? '\u0131' - : Character.toLowerCase(ch); +if (ch != '\u0049') + { +newStr[x++] = Character.toLowerCase(ch); + } +else + { +newStr[x++] = '\u0131'; + } } while (--i = 0); // Package constructor avoids an array copy. @@ -1473,6 +1470,54 @@ } /** + * Lowercases this String according to a particular locale. This uses + * Unicode's special case mappings, as applied to the given Locale, so the + * resulting string may be a different length. + * + * @param loc locale to use + * @return new lowercased String, or this if no characters were lowercased + * @throws NullPointerException if loc is null + * @see #toUpperCase(Locale) + * @since 1.1 + */ + public String toLowerCase(Locale loc) + { +// First, see if the current string is already lower case. + +// Is loc turkish? String equality test is ok as Locale.language is interned +if (tr == loc.getLanguage()) + { +return toLowerCaseTurkish(); + } +else + { +int i = count; +int x = offset - 1; +while (--i = 0) + { +char ch = value[++x]; +if (ch != Character.toLowerCase(ch)) + break; + } +if (i 0) + return this; + +// Now we perform the conversion. Fortunately, there are no +// multi-character lowercase expansions in Unicode 3.0.0. +char[] newStr = (char[]) value.clone(); +do + { +char ch = value[x]; +// Hardcoded special case. +newStr[x++] = Character.toLowerCase(ch); + } +while (--i = 0); +// Package constructor avoids an array copy. +return new String(newStr, offset, count, true); + } + } + + /** * Lowercases this String. This uses Unicode's special case mappings, as * applied to the platform's default Locale, so the resulting string may * be a different length. @@ -1487,21 +1532,12 @@ } /** - * Uppercases this String according to a particular locale. This uses - * Unicode's special case mappings, as applied to the given Locale, so the - * resulting string may be a different length. - * - * @param loc locale to use - * @return new uppercased String, or this if no characters were uppercased - * @throws NullPointerException if loc is null - * @see #toLowerCase(Locale) - * @since 1.1 + * Uppercase this string for a Turkish locale */ - public String toUpperCase(Locale loc) + private String toUpperCaseTurkish() { // First, see how many characters we have to grow by, as well as if the // current string is already upper case. -boolean turkish = tr.equals(loc.getLanguage()); int expand = 0; boolean unchanged = true; int i = count; @@ -1511,7 +1547,7 @@ char ch = value[--x]; expand += upperCaseExpansion(ch); unchanged = (unchanged expand == 0 - ! (turkish ch == '\u0069') + ch != '\u0069' ch == Character.toUpperCase(ch)); } if (unchanged) @@ -1526,8 +1562,14 @@ {
[cp-patches] Patch to java.io.OutputStreamWriter
Hi, the attached patch makes fields of OutputStreamWriter that can be final, final. Thanks, Ian --- java/io/OutputStreamWriter.java 2007-10-12 13:01:47.0 +0100 +++ java/io/OutputStreamWriter.java 2007-10-19 15:46:37.0 +0100 @@ -91,17 +91,17 @@ /** * The charset encoder. */ - private CharsetEncoder encoder; + private final CharsetEncoder encoder; /** * java.io canonical name of the encoding. */ - private String encodingName; + private final String encodingName; /** * Buffer output before character conversion as it has costly overhead. */ - private CharBuffer outputBuffer; + private final CharBuffer outputBuffer; private final static int BUFFER_SIZE = 1024; /** @@ -120,8 +120,10 @@ public OutputStreamWriter (OutputStream out, String encoding_scheme) throws UnsupportedEncodingException { +CharsetEncoder encoder; +String encodingName; this.out = out; - outputBuffer = CharBuffer.allocate(BUFFER_SIZE); +outputBuffer = CharBuffer.allocate(BUFFER_SIZE); try { @@ -130,42 +132,44 @@ { encodingName = ISO8859_1; encoder = null; - return; } - - /* -* Workaround for encodings with a byte-order-mark. -* We only want to write it once per stream. -*/ - try - { - if(encoding_scheme.equalsIgnoreCase(UnicodeBig) || - encoding_scheme.equalsIgnoreCase(UTF-16) || - encoding_scheme.equalsIgnoreCase(UTF16)) + else + { + /* +* Workaround for encodings with a byte-order-mark. +* We only want to write it once per stream. +*/ +try + { + if(encoding_scheme.equalsIgnoreCase(UnicodeBig) || +encoding_scheme.equalsIgnoreCase(UTF-16) || +encoding_scheme.equalsIgnoreCase(UTF16)) + { + encoding_scheme = UTF-16BE; +out.write((byte)0xFE); +out.write((byte)0xFF); + } + else if(encoding_scheme.equalsIgnoreCase(UnicodeLittle)) + { + encoding_scheme = UTF-16LE; + out.write((byte)0xFF); + out.write((byte)0xFE); + } + } + catch(IOException ioe) { - encoding_scheme = UTF-16BE; - out.write((byte)0xFE); - out.write((byte)0xFF); - } - else if(encoding_scheme.equalsIgnoreCase(UnicodeLittle)){ - encoding_scheme = UTF-16LE; - out.write((byte)0xFF); - out.write((byte)0xFE); - } - } - catch(IOException ioe) - { - } + } - Charset cs = EncodingHelper.getCharset(encoding_scheme); - if(cs == null) - throw new UnsupportedEncodingException(Encoding +encoding_scheme+ - unknown); - encoder = cs.newEncoder(); - encodingName = EncodingHelper.getOldCanonical(cs.name()); - - encoder.onMalformedInput(CodingErrorAction.REPLACE); - encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + Charset cs = EncodingHelper.getCharset(encoding_scheme); + if(cs == null) + throw new UnsupportedEncodingException(Encoding +encoding_scheme+ + unknown); +encoder = cs.newEncoder(); + encodingName = EncodingHelper.getOldCanonical(cs.name()); + + encoder.onMalformedInput(CodingErrorAction.REPLACE); + encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + } } catch(RuntimeException e) { @@ -174,6 +178,8 @@ encoder = null; encodingName = ISO8859_1; } +this.encoder = encoder; +this.encodingName = encodingName; } /** @@ -184,8 +190,10 @@ */ public OutputStreamWriter (OutputStream out) { +CharsetEncoder encoder; +String encodingName; this.out = out; - outputBuffer = CharBuffer.allocate(BUFFER_SIZE); +outputBuffer = CharBuffer.allocate(BUFFER_SIZE); try { String encoding = System.getProperty(file.encoding); @@ -204,6 +212,8 @@ encoder.onMalformedInput(CodingErrorAction.REPLACE); encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); } +this.encoder = encoder; +this.encodingName = encodingName; } /**
[cp-patches] Fix for GTk peers with Classpath 0.96.1
Hi, attached is a patch required to make JNI GTk peers work on 32bit architectures. Regards, Ian --- native/jni/gtk-peer/gtkpeer.c 2007-05-08 01:00:54.0 +0100 +++ native/jni/gtk-peer/gtkpeer.c 2007-10-17 10:49:25.0 +0100 @@ -102,11 +102,13 @@ #else #if SIZEOF_VOID_P == 4 pointerClass = (*env)-FindClass(env, gnu/classpath/Pointer32); - pointerDataFID = (*env)-GetFieldID(env, pointerClass, data, I); - - /* Find the Pointer32 constructor. */ - pointerConstructorMID = (*env)-GetMethodID(env, pointerClass, init, - (I)V); + if (pointerClass != NULL) +{ + pointerClass = (*env)-NewGlobalRef (env, pointerClass); + pointerDataFID = (*env)-GetFieldID (env, pointerClass, data, I); + pointerConstructorMID = (*env)-GetMethodID (env, pointerClass, init, + (I)V); +} #else #error Pointer size is not supported. #endif /* SIZEOF_VOID_P == 4 */
[cp-patches] Fix for GTk peers and portable native sync
Hi, this patch removes a call to atexit from GtkToolkit. The comment didn't give sufficient detail as to why the atexit call was necessary and the failure I witnessed in the Jikes RVM was as follows: 1) VM runs some AWT code that causes the atexit routine in GtkToolkit to be registered 2) VM shuts down, stopping all of its services (GC...) 3) VM calls exit that calls atexit routines 4) gdk_threads_enter is called via atexit, this then calls JNI monitor enter in the shutdown VM the shutdown VM can't handle the JNI call and locks up. There is an assumption in the Jikes RVM that atexit routines won't exist that call JNI functions. Thanks, Ian --- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c 2007-04-04 12:30:32.0 +0100 +++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c 2007-09-27 13:48:41.0 +0100 @@ -182,10 +182,6 @@ gtk_widget_set_default_colormap (gdk_rgb_get_colormap ()); - /* Make sure queued calls don't get sent to GTK/GDK while - we're shutting down. */ - atexit (gdk_threads_enter); - if ((homedir = getenv (HOME))) { rcpath = (char *) g_malloc (strlen (homedir) + strlen (RC_FILE) + 2);
Re: [Jikesrvm-core] [cp-patches] Changes to ThreadLocal
Hi, here is a revision of Daniel's patch, from Daniel, that revises a bug with InheritableThreadLocals not calling childValue. This bug was found through the JSR 166 TCK, which now passes its thread local tests. Thanks, Ian Daniel Frampton wrote: In order to tease out where the performance differences were coming from, I implemented a map specialized for thread locals (ThreadLocalMap.java) and found that the performance is essentially the same as the version Ian posted earlier that stores ThreadLocal data in a per-thread direct indexed array. Steve ran the numbers for first and third iteration performance (-1 and -3). http://cs.anu.edu.au/people/Steve.Blackburn/jikesrvm/vole-2007-08-22-Wed -213259-1.txt http://cs.anu.edu.au/people/Steve.Blackburn/jikesrvm/vole-2007-08-22-Wed -213259-3.txt All numbers are from JikesRVM and listed from left to right are the original (WeakIdentityHashMap) the array version suggested by Ian, and the ThreadLocalMap version. The implementation is essentially a map of weak references to values that are lazily cleaned up as the map is manipulated. I think this is a good balance of performance and design, but I am open to suggestions. To allow other VMs to benefit from this I have made all these changes within classpath (patch attached). The job still remains to improve the WeakIdentityHashMap so it does not perform allocation as it searches the buckets in the fast case for a simple get(), but I believe that optimizing the ThreadLocal case is worthwhile regardless as in some benchmarks they are performance critical. Thanks Regards, Daniel Frampton. --- java/lang/Thread.java 2006-12-11 10:06:55.0 +1100 +++ java/lang/Thread.java 2007-08-22 19:20:32.0 +1000 @@ -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; } /** --- java/lang/ThreadLocal.java 2006-12-11 07:25:44.0 +1100 +++ java/lang/ThreadLocal.java 2007-08-22 18:45:24.0 +1000 @@ -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() { -MapThreadLocalT,T map = (MapThreadLocalT,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 ==
Re: [cp-patches] Changes to ThreadLocal
Jeroen Frijters wrote: No, any VM that implements the spec is vulnerable. Here's an example of a possible attack: class Attacker { static ArrayListThreadLocal resurrected; ArrayListThreadLocal list = new ArrayListThreadLocal(); Attacker() { for (int i = 0; i 1000; i++) { list.add(new ThreadLocal()); } } protected void finalize() { resurrected = list; } static void attack() { new Attacker(); System.gc(); System.runFinalization(); runSomeHighTrustCodeThatWillAllocateThreadLocal(); for (ThreadLocal t : resurrected) { if (t.get() != null) { System.out.println(We've stolen the object: + t.get()); } } } } I hope this clarifies the problem with finalizers. A PhantomReference doesn't suffer from this problem, because it only gets enqueued after the object *really* is gone. For another example of this bug in GNU Classpath see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29499 Thanks Jeroen, it's clear now. The problem with a phantom reference is that when we collect the thread local we should also really make collectable all of the values set to thread locals. A phantom reference won't do this and so introduces a memory leak until something can run over the queue of phantom references freeing all the allocated thread local slots. As you say, we can use phantom references, wouldn't another way be to implement say our own system weak reference, with a guarantee there are no references and weak references to the object? Having a thread that polls a normally empty queue seems undesirable both for this and Classpath bug 29499. Thanks again, Ian
Re: [cp-patches] Changes to ThreadLocal
Jeroen Frijters wrote: Ian Rogers wrote: the attached patch modifies ThreadLocal to use an array of Objects hung off Thread rather than a weak hash map hung off Thread. On DaCapo's Jython benchmark this can improve the performance of the Jikes RVM by more than 10%. It also improves other DaCapo benchmark performance. GCJ already has a similar mechanism to use pthread thread locals. This patch looks wrong to me: 1) Values are strongly reachable, which means they potentially won't be garbage collected. 2) Value slots are reused without clearing them, which means potential security hole. Regards, Jeroen Thanks Jeroen, you're of course right. Without reinventing extra indirections in the locals it strikes me that the easiest way to solve these problems is with a finalizer (groan) in the thread local that iterates over every thread reverting the slot location to the sentinel value. I'll test and revise the patch. Regards, Ian
Re: [cp-patches] Changes to ThreadLocal
Andrew Haley wrote: Ian Rogers writes: Jeroen Frijters wrote: Ian Rogers wrote: the attached patch modifies ThreadLocal to use an array of Objects hung off Thread rather than a weak hash map hung off Thread. On DaCapo's Jython benchmark this can improve the performance of the Jikes RVM by more than 10%. It also improves other DaCapo benchmark performance. GCJ already has a similar mechanism to use pthread thread locals. This patch looks wrong to me: 1) Values are strongly reachable, which means they potentially won't be garbage collected. 2) Value slots are reused without clearing them, which means potential security hole. you're of course right. Without reinventing extra indirections in the locals it strikes me that the easiest way to solve these problems is with a finalizer (groan) in the thread local that iterates over every thread reverting the slot location to the sentinel value. I'll test and revise the patch. In the gcj pthreads version I keep the WeakIdentityHashMap but I have a look-aside cache that's used by get(). set() is slow by get() is fast. Like this: java::lang::ThreadLocal::get (void) { if (TLSPointer == NULL) return internalGet (); // Slow version, creates the ThreadLocal and updates the HashMap tls_t* tls = (tls_t*)TLSPointer; void *obj = pthread_getspecific(tls-key); // A fast lookup in an area of memory the garbage collector doesn't scan. if (obj) return (::java::lang::Object *)obj; ::java::lang::Object *value = internalGet (); // Slow version again. Garbage collection isn't affected because the use of the HashMap is exactly the same as in the previous Classpath version, and the gc doesn't scan the pthreads memory area used for thread locals. This gets the fast path (the usual case) down to a few instructions. I suppose it's only really an advantage on VMs with very low overhead native calls. Andrew. Hi all, here is the revised patch. The get and set methods are deliberately about as short as they can be, they are very very hot in benchmarks and need to be tight, ie read/write the variable and catch cases where the thread local data structure isn't set up yet via a bound check failure. When a thread local is garbage collected a finalizer object runs over every thread making sure we free up the thread local storage and then mark the local as being available again. The use of weak references that must be atomically nulled and not sharing locals avoids a lot of synchronization. I believe the only inefficiency of this code compared to the old code is that the amount of local storage can't shrink as thread locals become unreachable in memory unless new threads are created, and there's a possible issue of fragmentation (similar as to would exist in the hash maps backing store). I think the patch makes a sensible compromise in ignoring this to boost the performance of get and set. For the Jikes RVM on DaCapo's Jython benchmark (large size for 3 iterations) the time taken changes from ~62 seconds to just under 51 seconds. The use of a finalizer object is due to not wanting to over ride the finalize method on thread local, because of potential complications. One bug in the current implementation is that if the thread local overrides hashcode and/or equal it can be made to collide with other thread locals. I think the revised code would also make a good revision for GCJ. It's possible that avoiding the use of pthread calls will boost efficiency, but if not it would provide a more efficient place to look on cache misses. Thanks, Ian diff -u java/lang/InheritableThreadLocal.java java/lang/InheritableThreadLocal.java --- java/lang/InheritableThreadLocal.java 2007-08-21 12:01:24.0 +0100 +++ java/lang/InheritableThreadLocal.java 2007-08-21 11:55:49.0 +0100 @@ -37,9 +37,9 @@ package java.lang; -import gnu.java.util.WeakIdentityHashMap; - -import java.util.Iterator; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Arrays; /** * A ThreadLocal whose value is inherited by child Threads. The value of the @@ -56,12 +56,22 @@ * @author Eric Blake ([EMAIL PROTECTED]) * @author Tom Tromey ([EMAIL PROTECTED]) * @author Andrew John Hughes ([EMAIL PROTECTED]) + * @author Ian Rogers ([EMAIL PROTECTED]) * @see ThreadLocal * @since 1.2 * @status updated to 1.4 */ public class InheritableThreadLocalT extends ThreadLocalT { + + + /** + * Map of owners of local index to inheritable thread local. Weak references + * allow thread locals to be collected when no longer in use. + */ + private static final HashMapInteger,WeakReferenceInheritableThreadLocal? + owners = new HashMapInteger,WeakReferenceInheritableThreadLocal?(); + /** * Creates a new InheritableThreadLocal that has no values associated @@ -69,6 +79,8 @@ */ public InheritableThreadLocal() { +super
Re: [cp-patches] Changes to ThreadLocal
Jeroen Frijters wrote: Ian Rogers wrote: here is the revised patch. + int arraySize = group.activeCount(); + Thread[] threadList = new Thread[arraySize]; + int filled = group.enumerate(threadList); + while (filled == arraySize) + { +arraySize *= 2; +threadList = new Thread[arraySize]; +filled = group.enumerate(threadList); + } Shouldn't the initial array be arraySize + 1, to avoid always having to enumerate twice? This code is taken from Thread.getAllStackTraces so the problem should effect both. A bigger problem is that the ThreadLocal can be resurrected after the finalizer has run, so you need to either make localIndex in ThreadLocal volatile and set it to -1 in the finalizer, or use a PhantomReference and a ReferenceQueue to do the clean up. How can then the thread local be resurrected after the finalizer is run? All the references in ThreadLocal and InheritableThreadLocal are weak and will be atomically cleared prior to the finalizer being run. All other references must be dead for the finalizer to have been run. The finalizer doesn't use the ThreadLocal it just clears all references to the slot it used to reference prior to saying that slot can be reused. Given that thread locals normally only die when the VM shuts down or by class unloading, its quite tempting just to ignore the situation of reclaiming their storage - its certainly a much smaller problem than the performance of get and set. Thanks, Ian
Re: [cp-patches] Changes to ThreadLocal
Jeroen Frijters wrote: This is not true. Once an object becomes finalizer reachable the finalizer can run, but that doesn't mean all references are gone. Any object with a finalizer can still have references to objects that have already been finalized. In its finalizer it will be able to resurrect these objects. This is a well known attack vector and the reason that PhantomReferences were introduced to do post-mortem cleanup. In normal use it would be so hard to do this, but you're right that in theory someone could try to use a thread local after its been finalized in their own finalizer using the finalizer I wrote. I've changed the patch as you suggested to make the localIndex an invalid value after finalization to prevent this attack. It's unfortunate as the change stops localIndex being a prime candidate for final field chasing or caching in a register. This seems better than using a phantom reference and polling a queue though. Thanks, Ian diff -u java/lang/InheritableThreadLocal.java java/lang/InheritableThreadLocal.java --- java/lang/InheritableThreadLocal.java 2007-08-21 12:01:24.0 +0100 +++ java/lang/InheritableThreadLocal.java 2007-08-21 11:55:49.0 +0100 @@ -37,9 +37,9 @@ package java.lang; -import gnu.java.util.WeakIdentityHashMap; - -import java.util.Iterator; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Arrays; /** * A ThreadLocal whose value is inherited by child Threads. The value of the @@ -56,12 +56,22 @@ * @author Eric Blake ([EMAIL PROTECTED]) * @author Tom Tromey ([EMAIL PROTECTED]) * @author Andrew John Hughes ([EMAIL PROTECTED]) + * @author Ian Rogers ([EMAIL PROTECTED]) * @see ThreadLocal * @since 1.2 * @status updated to 1.4 */ public class InheritableThreadLocalT extends ThreadLocalT { + + + /** + * Map of owners of local index to inheritable thread local. Weak references + * allow thread locals to be collected when no longer in use. + */ + private static final HashMapInteger,WeakReferenceInheritableThreadLocal? + owners = new HashMapInteger,WeakReferenceInheritableThreadLocal?(); + /** * Creates a new InheritableThreadLocal that has no values associated @@ -69,6 +79,8 @@ */ public InheritableThreadLocal() { +super(); +owners.put(localIndex, new WeakReferenceInheritableThreadLocal?(this)); } /** @@ -97,24 +109,25 @@ { // 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)); - } +if (parentThread.locals != null) { + childThread.locals = new Object[parentThread.locals.length]; + Arrays.fill(childThread.locals, sentinel); + for (int i=0; i parentThread.locals.length; i++) { +WeakReference ref = owners.get(i); +if (ref != null) { + InheritableThreadLocal local = (InheritableThreadLocal)ref.get(); + if (local != null) { +Object parentValue = parentThread.locals[i]; +Object childValue; +if (parentValue == sentinel) { + childValue = sentinel; +} else { + childValue = local.childValue(parentValue); +} +childThread.locals[i] = childValue; } +} } +} } } diff -u java/lang/Thread.java java/lang/Thread.java --- java/lang/Thread.java 2007-08-21 12:01:24.0 +0100 +++ java/lang/Thread.java 2007-08-21 11:55:14.0 +0100 @@ -39,14 +39,11 @@ package java.lang; import gnu.classpath.VMStackWalker; -import gnu.java.util.WeakIdentityHashMap; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; - import java.security.Permission; - import java.util.HashMap; import java.util.Map; @@ -90,6 +87,7 @@ * @author John Keiser * @author Eric Blake ([EMAIL PROTECTED]) * @author Andrew John Hughes ([EMAIL PROTECTED]) + * @author Ian Rogers ([EMAIL PROTECTED]) * @see Runnable * @see Runtime#exit(int) * @see #run() @@ -156,10 +154,11 @@ /** The default exception handler
Re: [cp-patches] Changes to ThreadLocal
Ian Rogers wrote: Jeroen Frijters wrote: This is not true. Once an object becomes finalizer reachable the finalizer can run, but that doesn't mean all references are gone. Any object with a finalizer can still have references to objects that have already been finalized. In its finalizer it will be able to resurrect these objects. This is a well known attack vector and the reason that PhantomReferences were introduced to do post-mortem cleanup. In normal use it would be so hard to do this, but you're right that in theory someone could try to use a thread local after its been finalized in their own finalizer using the finalizer I wrote. I've changed the patch as you suggested to make the localIndex an invalid value after finalization to prevent this attack. It's unfortunate as the change stops localIndex being a prime candidate for final field chasing or caching in a register. This seems better than using a phantom reference and polling a queue though. The more I think about this the less happy I am about the solution to not make the local index final. What my hope had been was that the locals would be something amenable to caching in a register for a thread. The local index as a final would also be amenable to constant propagation and access to a thread local would, in the best case, be an indexed register load away. The problem with escaping references, in this situation, doesn't effect the Jikes RVM. This is because all weak references that become finalizable are queued onto the finalizer thread. A thread local queued on the finalizer thread would only be able to look at the thread local variables of the finalizer thread. So the scenario of a secret thread running then an untrusted thread running and stealing data from the secret via the thread local can't occur. The secret thread would have to put data into the finalizer thread's thread local for the untrusted thread then to steal; I can't see how this can occur without the secret thread being complicit in trying to leak data to the untrusted thread - if the secret thread is being complicit with the untrusted thread then aren't all bets off? Anyway, this design decision seems to hang off how weak references are finalized. If they are finalized on their own finalizer thread then the final local index design is fine and preferable imo to the volatile design or a weak identity hash map (however cached or stream lined) - I think an indexed register load is the shortest bit of code you could produce for this. If finalizable objects are finalized as part of tearing down threads then a leak is possible and for correctness the volatile should be used. So this comes down to a question of how Classpath using VMs are finalizing objects? One simple idea is to palm off the implementation decision to the VMThread and make the reference implementation use a volatile - this way the Jikes RVM, I believe, can get its optimal code sequence. Currently the whole issue of caching these values in registers for the Jikes RVM is a mute one as optimizations to reduce redundant loads are disabled. Thanks, Ian
[cp-patches] Changes to ThreadLocal
Hi, the attached patch modifies ThreadLocal to use an array of Objects hung off Thread rather than a weak hash map hung off Thread. On DaCapo's Jython benchmark this can improve the performance of the Jikes RVM by more than 10%. It also improves other DaCapo benchmark performance. GCJ already has a similar mechanism to use pthread thread locals. Regards, Ian diff -u java/lang/InheritableThreadLocal.java java/lang/InheritableThreadLocal.java --- java/lang/InheritableThreadLocal.java 2006-12-10 20:25:44.0 + +++ java/lang/InheritableThreadLocal.java 2007-08-20 16:41:23.0 +0100 @@ -37,9 +37,7 @@ package java.lang; -import gnu.java.util.WeakIdentityHashMap; - -import java.util.Iterator; +import java.util.Arrays; /** * A ThreadLocal whose value is inherited by child Threads. The value of the @@ -56,6 +54,7 @@ * @author Eric Blake ([EMAIL PROTECTED]) * @author Tom Tromey ([EMAIL PROTECTED]) * @author Andrew John Hughes ([EMAIL PROTECTED]) + * @author Ian Rogers ([EMAIL PROTECTED]) * @see ThreadLocal * @since 1.2 * @status updated to 1.4 @@ -93,29 +92,28 @@ * @param childThread the newly created thread, to inherit from this thread * @see Thread#Thread(ThreadGroup, Runnable, String) */ - static void newChildThread(Thread childThread) + static T void newChildThread(Thread childThread) { // 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)); - } +if (parentThread.locals != null) { + childThread.locals = new Object[parentThread.locals.length]; + Arrays.fill(childThread.locals, sentinel); + for (int i=0; i parentThread.locals.length; i++) { +ThreadLocal? tl = owners.get(i).get(); +if (tl != null tl instanceof InheritableThreadLocal) { + InheritableThreadLocal local = (InheritableThreadLocal)tl; + Object parentValue = parentThread.locals[i]; + Object childValue; + if (parentValue == sentinel) { +childValue = sentinel; + } else { +childValue = local.childValue(parentValue); } + childThread.locals[i] = childValue; +} } +} } } diff -u java/lang/Thread.java java/lang/Thread.java --- java/lang/Thread.java 2006-12-10 23:06:55.0 + +++ java/lang/Thread.java 2007-08-20 16:59:52.0 +0100 @@ -39,14 +39,11 @@ package java.lang; import gnu.classpath.VMStackWalker; -import gnu.java.util.WeakIdentityHashMap; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; - import java.security.Permission; - import java.util.HashMap; import java.util.Map; @@ -90,6 +87,7 @@ * @author John Keiser * @author Eric Blake ([EMAIL PROTECTED]) * @author Andrew John Hughes ([EMAIL PROTECTED]) + * @author Ian Rogers ([EMAIL PROTECTED]) * @see Runnable * @see Runtime#exit(int) * @see #run() @@ -156,10 +154,11 @@ /** The default exception handler. */ private static UncaughtExceptionHandler defaultHandler; - /** Thread local storage. Package accessible for use by -* InheritableThreadLocal. -*/ - WeakIdentityHashMap locals; + /** Default value for a thread with no locals. */ + private static final Object[] noLocals = new Object[0]; + + /** Where thread local storage is hung by ThreadLocal. */ + Object[] locals = noLocals; /** The uncaught exception handler. */ UncaughtExceptionHandler exceptionHandler; @@ -1066,20 +1065,6 @@ locals = null; } - /** - * Returns the map used by ThreadLocal to store the thread local values. - */ - static Map getThreadLocals() - { -Thread thread = currentThread(); -Map locals = thread.locals; -if (locals == null) - { -locals = thread.locals = new WeakIdentityHashMap(); - } -return locals; - } - /** * Assigns the given codeUncaughtExceptionHandler/code to this * thread. This will then be called if the thread terminates due diff -u java/lang/ThreadLocal.java java/lang/ThreadLocal.java --- java/lang
Re: [cp-patches] Float/Double compare
Here's a revised version of the patch following suggestions from Andrew Haley. Ian --- java/lang/Float.java2006-12-10 15:25:44.0 -0500 +++ java/lang/Float.java2007-07-02 12:17:29.0 -0400 @@ -596,16 +596,25 @@ */ public static int compare(float x, float y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinities and try again -if (x == 0 y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; + // handle the easy cases: + if (x y) + return -1; + if (x y) + return 1; -return x y ? 1 : -1; + // handle equality respecting that 0.0 != -0.0 (hence not using x == y): + int ix = floatToRawIntBits(x); + int iy = floatToRawIntBits(y); + if (ix == iy) + return 0; + + // handle NaNs: + if (x != x) + return (y != y) ? 0 : 1; + else if (y != y) + return -1; + + // handle +/- 0.0 + return (ix iy) ? -1 : 1; } } --- java/lang/Double.java 2006-12-10 15:25:44.0 -0500 +++ java/lang/Double.java 2007-07-02 12:18:36.0 -0400 @@ -587,16 +587,25 @@ */ public static int compare(double x, double y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinites and try again -if (x == 0 y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; + // handle the easy cases: + if (x y) + return -1; + if (x y) + return 1; -return x y ? 1 : -1; + // handle equality respecting that 0.0 != -0.0 (hence not using x == y): + long lx = doubleToRawLongBits(x); + long ly = doubleToRawLongBits(y); + if (lx == ly) + return 0; + + // handle NaNs: + if (x != x) + return (y != y) ? 0 : 1; + else if (y != y) + return -1; + + // handle +/- 0.0 + return (lx ly) ? -1 : 1; } }
Re: Float/Double compare
Andrew Haley wrote: We know that any calculation involving NaN returns false, right? So, simple cases can be done first without the (possibly expensive) move out of the FPU: if (x y) return -1; if (x y) return 1; then you can do the doubleToLongBits: long lx = doubleAsLongBits(x); long ly = doubleAsLongBits(y); if (lx == ly) return 0; At this point we know they're unequal. Also, either one of them is NaN, or one of them is -0 and the other +0. Java's doubleToLongBits alwayse uses the canonical NaN, so we know that they can't both be NaN. if (lx ly) return -1; return 1; Hi Andrew, this is great. I'd forgotten about the NaN test buried in doubleToLongBits, and I like the logic to push the and tests to the top. Using these insights I've tried to figure if there's a better way than this and I just wonder whether as the long bits conversions do a NaN test is the following cheaper: // handle the easy cases: if (x y) return -1; if (x y) return 1; // handle equality respecting that 0.0 != -0.0 (hence not using x == y): int ix = floatToRawIntBits(x); int iy = floatToRawIntBits(y); if (ix == iy) return 0; // handle NaNs: if (x != x) return (y != y) ? 0 : 1; else if (y != y) return -1; // handle +/- 0.0 return (ix iy) ? -1 : 1; Although its almost certain a VM can do better with a VM specific implementation. For example, on Intel you can reuse the fact that a floating point compare gives you unordered information (in fact in many cases you need to test for this anyway). I imagine GCC is better at doing this kind of machine specific optimization than most JITs are. Regards, Ian
Re: Float/Double compare
Hi Mark, Mark Wielaard wrote: Hi Ian, On Sat, 2007-06-30 at 15:25 -0400, Ian Rogers wrote: public static int compare(float x, float y) { int ix = floatAsIntBits(x); int iy = floatAsIntBits(y); if (ix == iy) return 0; if (isNaN(x)) return 1; if (isNaN(y)) return -1; int ix_sign = ix31; int iy_sign = iy31; if (ix_sign == iy_sign) { return x y ? 1 : -1; } else { return ix_sign - iy_sign; } } I am not really comfortable with writing this as is since unless the compiler is smart you will do a multiple isNaN() and floatToIntBits() calls even if not necessary. Could we try to do something smarter and factor some of this out like: // First check for NaNs if (x != x || y != y) { int ix = floatToIntBits(x); int iy = floatToIntBits(y); if (ix == iy) return 0; if (x != x) return 1; if (y != y) return -1; } else { // Normal cases, or positive/negative zeros if (x y) return 1; if (y x) return -1; // Either equal or positive/negative zeros if (x == 0 y == 0) { int ix = floatToIntBits(x); int iy = floatToIntBits(y); int ix_sign = ix 31; int iy_sign = iy 31; return ix_sign - iy_sign; } return 0; } But maybe I am not giving the compiler/jit enough credit for actually producing such an optimized version in the first place. And this isn't actually the same as your code since I moved the NaN checks first again. The above assumes the NaN test (x != x) is relatively cheap since NaN is a canonical value is java. That might be a wrong assumption. You might be able to do something more clever with the actual ordering of floats according to (since if any argument is NaN or both are zero it evaluates to false) or with the ordering of floatToIntBits, but my head was spinning trying to keep all the corner cases right (this calls for expanding the Mauve Float.compareTo() test). Thanks for the feedback. I think your code may well be better. I think its good to have identified that there is at least an ~8% potential speed up on IA32 with my code, and potentially better with yours. There is of course a big dependence on what values are being compared and on the architecture. For the arrays of floats I'm seeing in the Jikes RVM a lot of the values are identical (either 0.0 or 1.0). With your code that has a path of 6 compares to get through. With mine its just one compare, but because a floating point compare of 0.0 and -0.0 will yield that they are identical I'm forced into doing it on their int bit representation to keep the 0.0 case sane. Here's my hand wavy costing of the now 3 ways we have a doing things: Case: x == y neither are NaN or 0.0 Newer Cost: 5 float compares New Cost: 2 float as ints, 1 int compare Old Cost: 5 float compares Case: x y and different sign Newer Cost: 4 float compares New Cost: 2 float as ints, 2 int compares, 2 float compares, 2 shifts, one subtract Old Cost: 6 float compares Case: x y and same sign Newer Cost: 4 float compares New Cost: 2 float as ints, 2 int compares, 3 float compares, 2 shifts Old Cost: 6 float compares Case: x is NaN Newer Cost: 2 float compares (I think you could reuse the original code which is slightly cheaper than yours) New Cost: 2 float as ints, 1 int compare, 1 float compare Old Cost: 2 float compares Case: y is NaN Newer Cost: 2 float compares (again assuming reuse of the original code) New Cost: 2 float as ints, 1 int compare, 2 float compares Old Cost: 2 float compares Case: x == 0.0 and y == 0.0 Newer Cost: 2 float as ints, 6 float compares, 2 shifts, one subtract New Cost: either 2 float as ints, 1 int compare or 2 float as ints, 2 int compares, 2 float compares, 2 shifts, one subtract Old Cost: 4 float compares, 2 float divides, 1 float subtract, 1 float to int So I think the cases where the different ways win out are: most values are / then the newer way has the shortest path, most values are == then the new way has the shortest path, for two zeros (common in Jikes RVM :-( ) the new way wins out, and no one really cares about NaNs :-) I agree about the desirable properties of your code, and I think they also address Pinski's concern, that floatToIntBits on the common path seems bad. I also agree that its good to have a short and path. Possibly the only redeeming feature of the new code was that it made == cheap (depending on the floatToIntBits cost). So my variant of your code would be: // First check for NaNs if (x != x) { if (y != y) return 0; else return 1; } else if (y != y) { return -1; } else { // Normal cases, or positive/negative zeros if (x y) return 1; if (y x) return -1; // Either equal or positive/negative zeros if (x == 0 y == 0) { int ix = floatToIntBits(x); int iy = floatToIntBits(y); int ix_sign = ix 31; int iy_sign = iy 31; return ix_sign
[cp-patches] Float/Double compare
Attached is a patch that improves the performance of an Float/Double compare by exploiting information carried in their bit integer/long versions sign bit. It removes one comparison from the normal path, as well as making other compares with ints/longs. When sorting an array of floats this can yield a little under a 8% speed up on a Pentium 4. There's a thread discussing whether this is a good or bad idea on the main mailing list, but so far I'm merrily talking to myself :-) Ian --- java/lang/Double.java 2006-12-10 20:25:44.0 + +++ java/lang/Double.java 2007-06-30 22:21:39.98610 +0100 @@ -587,16 +587,17 @@ */ public static int compare(double x, double y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinites and try again -if (x == 0 y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; - -return x y ? 1 : -1; +long lx = doubleToLongBits(x); +long ly = doubleToLongBits(y); +if (lx == ly) return 0; +if (isNaN(x)) return 1; +if (isNaN(y)) return -1; +int lx_sign = (int)(lx63); +int ly_sign = (int)(ly63); +if (lx_sign == ly_sign) { + return x y ? 1 : -1; +} else { + return lx_sign - ly_sign; +} } } --- java/lang/Float.java2006-12-10 20:25:44.0 + +++ java/lang/Float.java2007-06-30 22:10:46.099648000 +0100 @@ -596,16 +596,17 @@ */ public static int compare(float x, float y) { -if (isNaN(x)) - return isNaN(y) ? 0 : 1; -if (isNaN(y)) - return -1; -// recall that 0.0 == -0.0, so we convert to infinities and try again -if (x == 0 y == 0) - return (int) (1 / x - 1 / y); -if (x == y) - return 0; - -return x y ? 1 : -1; +int ix = floatToIntBits(x); +int iy = floatToIntBits(y); +if (ix == iy) return 0; +if (isNaN(x)) return 1; +if (isNaN(y)) return -1; +int ix_sign = ix31; +int iy_sign = iy31; +if (ix_sign == iy_sign) { + return x y ? 1 : -1; +} else { + return ix_sign - iy_sign; +} } }
Re: [cp-patches] Float/Double compare
Andrew Pinski wrote: On 6/30/07, Ian Rogers [EMAIL PROTECTED] wrote: Attached is a patch that improves the performance of an Float/Double compare by exploiting information carried in their bit integer/long versions sign bit. It removes one comparison from the normal path, as well as making other compares with ints/longs. When sorting an array of floats this can yield a little under a 8% speed up on a Pentium 4. There's a thread discussing whether this is a good or bad idea on the main mailing list, but so far I'm merrily talking to myself :-) This is going to slow down this function for PowerPC (except for Power6+) where you have to take a huge hit to transfer between register sets via the stack. For an example on the Cell, this is going to be an extra 40-100 cycle hit. I guess there are a lot of factors to do with the underlying architecture. My feeling is that we should move the code to VMFloat/VMDouble and then the VM can choose the appropriate version. Having the regular version optimized for Intel would make sense to me. Its not straight forward for me to benchmark the code on non-IA32 architectures, in particular Cell. I'll try to do a Jikes RVM benchmark on a PowerPC I have access to in the week. My feeling is that the performance may not be as bad as you imagine, but it's hard to predict - and this may not be an architecture you care about anyway. Regards, Ian
Float/Double compare
Hi everyone, I was tracking a bug and came across the code in Float.compare which is very similar to Double.compare. It just so happened that the bug was being caused by sorting arrays containing lots of floating point 0s. This occurs quite frequently in the Jikes RVM when we have an array of branch profile data. So the current code looks like: public static int compare(float x, float y) { if (isNaN(x)) return isNaN(y) ? 0 : 1; if (isNaN(y)) return -1; // recall that 0.0 == -0.0, so we convert to infinities and try again if (x == 0 y == 0) return (int) (1 / x - 1 / y); if (x == y) return 0; return x y ? 1 : -1; } When comparing 0 with 0 we do two NaN tests, two tests with 0, two floating point divides, floating point subtract and a float to int. An alternate way of coding the case of (x == 0 y == 0) would be: if (x == 0 y == 0) return (floatAsIntBits(x)31) - (floatAsIntBits(y) 31) The shift basically turns the ints being subtracted into 0 or -1, 0 in the case the value is +ve and -1 when it's negative. This changes the cost of 2 float divides, float subtract and float to int, into a cost of 2 float as ints, 2 int shifts, 1 int subtract. On x86 the float to int is expensive (set and restore control bits yadda yadda), where as a float as int is just a float store and then int load. I think the latter pattern could be quite a lot cheaper. In any case, it seems that this code is quite performance important and possibly the VM could do some clever optimizations. I wonder if it wouldn't be better to move compare into VMFloat and VMDouble? Regards, Ian
Re: Float/Double compare
Ian Rogers wrote: public static int compare(float x, float y) { if (isNaN(x)) return isNaN(y) ? 0 : 1; if (isNaN(y)) return -1; // recall that 0.0 == -0.0, so we convert to infinities and try again if (x == 0 y == 0) return (int) (1 / x - 1 / y); if (x == y) return 0; return x y ? 1 : -1; } Below is a variant of the compare code and a comparison with the cost of the current compare code: public static int compare(float x, float y) { int ix = floatAsIntBits(x); int iy = floatAsIntBits(y); if (ix == iy) return 0; if (isNaN(x)) return 1; if (isNaN(y)) return -1; int ix_sign = ix31; int iy_sign = iy31; if (ix_sign == iy_sign) { return x y ? 1 : -1; } else { return ix_sign - iy_sign; } } Case: x == y neither are NaN or 0.0 New Cost: 2 float as ints, 1 int compare Old Cost: 5 float compares Case: x y and different sign New Cost: 2 float as ints, 2 int compares, 2 float compares, 2 shifts, one subtract Old Cost: 6 float compares Case: x y and same sign New Cost: 2 float as ints, 2 int compares, 3 float compares, 2 shifts Old Cost: 6 float compares Case: x is NaN New Cost: 2 float as ints, 1 int compare, 1 float compare Old Cost: 2 float compares Case: y is NaN New Cost: 2 float as ints, 1 int compare, 2 float compares Old Cost: 2 float compares Case: x == 0.0 and y == 0.0 New Cost: either 2 float as ints, 1 int compare or 2 float as ints, 2 int compares, 2 float compares, 2 shifts, one subtract Old Cost: 4 float compares, 2 float divides, 1 float subtract, 1 float to int The same code but for doubles would be: public static int compare(double x, double y) { long lx = doubleAsLongBits(x); long ly = doubleAsLongBits(y); if (lx == ly) return 0; if (isNaN(x)) return 1; if (isNaN(y)) return -1; int lx_sign = (int)(lx63); int ly_sign = (int)(ly63); if (lx_sign == ly_sign) { return x y ? 1 : -1; } else { return lx_sign - ly_sign; } } So the case when y is a NaN is slower with the new code but I think all of the more common cases are similar or faster. Of course it depends on the speed of all the operations. If you cared about a CPU with no floating point, the new code is a lot faster. If you've got great floating point and a lot of cases of y being a NaN the old code will be better. My guess is that in the general case the new code wins out. There may be a bug I can't see in this code :-) Regards, Ian
Re: Float/Double compare
In terms of performance I just tried sorting an array of floats with the new code (floatAsIntBits should have been floatToIntBits, sorry). The test was to initialize an array of floats backwards and then sort it to be ascending. Running a large enough array and enough iterations to get a ~4 second run, using the Jikes RVM's optimizing compiler, the speed up was around 7.77% on a Pentium 4 Linux box. Ian
Migration to generics opens up exciting optimization opportunities from annotations
Hi, I believe there are some interesting optimization opportunities that flow from the move to generics that enables the proper use of annotations. For example a code sequence such as: static final int specialValue = 123; void foo() { Integer bar1 = Integer.valueOf(specialValue); invoke some methods ... Integer bar2 = Integer.valueOf(specialValue); ... } could be optimized to: static final int specialValue = 123; void foo() { Integer bar1 = Integer.valueOf(specialValue); invoke some methods ... Integer bar2 = bar1; ... } if we knew that the intCache were holding an immutable value. Actually there are more exciting optimizations discussed in this paper by Igor Pechtchanski and Vivek Sarkar, in particular because of the immutability of Strings: http://citeseer.ist.psu.edu/pechtchanski02immutability.html I'm interested in adding these optimization to the Jikes RVM, but clearly the annotations need adding to Classpath. I was wondering what kind of response this would get? I can imagine a gnu.pragma or gnu.compilerhint package containing such annotations. It could also contain similar compiler hints to those found in GCC attributes. The Jikes RVM uses a package called org.vmmagic.pragma for some other compiler tricks. Interested in your responses, thanks, Ian Rogers -- http://www.cs.man.ac.uk/~irogers
Re: Trouble building x86 32-bit classpath on an x86-64 machine
Hi Adam, really the only important flag to build Classpath for x86 rather than x86-64 on an x86-64 system is -m32 as a compiler flag. The default x86-64 config file for the Jikes RVM does this by defining CC and CPLUS to have -m32 at the end. Alternatively compiler flags can be specified with the environment variables CFLAGS and CXXFLAGS. I have been trying to capture information on building the Jikes RVM in the wiki: http://jikesrvm.sourceforge.net/wiki/index.php/Building I would welcome help and contributions. Thanks, Ian Rogers
[cp-patches] Problem in native/jni/classpath/jcl.c
There's a bug in the Classpath CVS head that's crashing the Jikes RVM (thanks to Mark for helping me to find it). It's in jcl.c where we delete a global ref which is actually only a local ref. The following fixes it. Thanks, Ian Rogers Index: native/jni/classpath/jcl.c === RCS file: /sources/classpath/classpath/native/jni/classpath/jcl.c,v retrieving revision 1.25 diff -u -r1.25 jcl.c --- native/jni/classpath/jcl.c 17 Sep 2006 19:13:01 - 1.25 +++ native/jni/classpath/jcl.c 27 Sep 2006 09:34:32 - @@ -75,7 +75,6 @@ { jclass tmp = rawDataClass; rawDataClass = (*env)-NewGlobalRef (env, rawDataClass); - (*env)-DeleteGlobalRef (env, tmp); } if (rawDataClass != NULL) @@ -90,7 +89,6 @@ { jclass tmp = rawDataClass; rawDataClass = (*env)-NewGlobalRef (env, rawDataClass); - (*env)-DeleteGlobalRef (env, tmp); } if (rawDataClass != NULL)
Re: [cp-patches] Revise threading description in vmintegration.texinfo
Hi, I'm resending this updated patch with a hope that someone will commit it now that I've got all the FSF paper work through. Thanks, Ian Rogers Ian Rogers wrote: Hi, this patch revises the discussion of threading in the VM integration guide, as well as fixing a link to the Jikes RVM. A discussion was had on classpath@gnu.org on the 29/03/06 under the heading Green threads - some experience. The VM integration guide should now be up-to-date on this subject, although maybe my description of the problems is a little verbose. Regards, Ian Rogers -- http://www.cs.man.ac.uk/~irogers Index: doc/vmintegration.texinfo === RCS file: /sources/classpath/classpath/doc/vmintegration.texinfo,v retrieving revision 1.40 diff -u -r1.40 vmintegration.texinfo --- doc/vmintegration.texinfo 22 Jul 2006 19:59:14 - 1.40 +++ doc/vmintegration.texinfo 18 Aug 2006 15:22:43 - @@ -144,7 +144,7 @@ pure GNU Classpath; it is emerging as the preferred platform for quickly testing a new build of GNU Classpath. Licensed under the GPL. [EMAIL PROTECTED] @uref{http://oss.software.ibm.com/jikesrvm,Jikes RVM} [EMAIL PROTECTED] @uref{http://jikesrvm.sourceforge.net/,Jikes RVM} A free runtime environment for Java, written in Java. Works out-of-the-box with pure GNU Classpath. Features an optimizing JIT. Runs on the x86 and PowerPC architectures, on the AIX, Linux, and Mac @@ -1859,8 +1859,7 @@ Classpath currently uses only JNI 1.1, except for one JNI 1.2 function in the JNI Invocation API: GetEnv(). And GetEnv() is only used in the -``portable native sync'' code, so it's only actually used by Jikes RVM -and Kaffe. +now deprecated ``portable native sync'' code. A future direction will probably be to require that all VMs provide JNI 1.2. If this poses problems, please raise them on the classpath @@ -1870,42 +1869,95 @@ @comment node-name, next, previous, up @section VM Threading Model -Classpath's AWT peers use GTK+. GTK+ uses GLIB. Normally, Classpath -will initialize GLIB's @dfn{gthreads} to use -the platform's native threading [EMAIL PROTECTED] native threading -model is pthreads on Linux and AIX, the two platforms Classpath -currently runs on.} - -If the Java runtime doesn't use the native threading model, then you -will want Classpath to tell GLIB to use the Java threading primitives -instead. Otherwise, GLIB would use the native threading model to -perform operations such as creating thread-local data, and that just -doesn't work on systems (such as Kaffe in some configurations, and -such as Jikes RVM) that use @i{m}:@i{n} threading. - -Historically, enabling the Java threading primitives had been done at -build time, by configuring classpath with the [EMAIL PROTECTED] option. This had bad consequences, -though -- it meant that the prebuild GNU Classpath package distributed -with Debian GNU/Linux would not be usable with VMs that could -otherwise have used it. Instead, we encourage -the use of the Java system property [EMAIL PROTECTED] A VM that wants -GLIB to use the Java threading primitives should modify [EMAIL PROTECTED]()} to include code like the -following: - [EMAIL PROTECTED] -static void insertSystemProperties(Properties @var{p}) [EMAIL PROTECTED] example -... [EMAIL PROTECTED] [EMAIL PROTECTED](gnu.classpath.awt.gtk.portable.native.sync, true); [EMAIL PROTECTED] example - -So, the configure option [EMAIL PROTECTED] is deprecated, and should go away in a -subsequent release of GNU Classpath. +VM authors can implement a number of different threading models. When +native code is also threaded there is the potential for one threading +model to deadlock the other. The [EMAIL PROTECTED]://java.sun.com/docs/books/jni/html/other.html#29406,Java +Native Interface Programmer's Guide and Specification} suggests +consulting VM documentation in such situations. Classpath uses +existing libraries, for example the AWT peers can use the GTK+ +graphics library. As these libraries assume a different threading +model, there is the potential for the native code to deadlock a VM. + +The different threading models available to a VM author are: [EMAIL PROTECTED] [EMAIL PROTECTED] [EMAIL PROTECTED] threads}: Map a Java thread to an underlying operating system +thread (normally a POSIX compatible pthread). This approach reduces +the potential for deadlock as there is only one thread scheduling +mechanism. [EMAIL PROTECTED] [EMAIL PROTECTED] threads 1}: Green threads are threads scheduled by the VM, +typically by switching swapping registers. In early VMs green threads +were seen as advantageous as they didn't require the operating system +to resechedule, save and swap all of a threads registers. The green +thread 1 model switches thread on an externally created event, such as +a timer interrupt. An example of a VM using this approach is Kaffe +configured with its jthreads model. [EMAIL PROTECTED] [EMAIL PROTECTED] threads 2
Re: Q: userland threads and system calls
Hi Casey, there were a series of e-mails on green threads a while ago: http://developer.classpath.org/pipermail/classpath/2006-March/000712.html For the Jikes RVM we assume that most system and library calls are fine, but we special case a few in the syswrap.C file: http://svn.sourceforge.net/viewvc/jikesrvm/rvmroot/trunk/rvm/src/tools/bootImageRunner/syswrap.C?view=markup We actually special case very few as we replace the standard socket library with our own non-blocking variant (which is also slightly problematic). The special cases we have are: select and poll, to support IO pthread_mutex_lock and pthread_cond_wait, to avoid these waiting on a lock already held by the current pthread (and instead calling a Java thread yield) Currently we're thinking of dropping green threads in favor of pthreads as it would remove our IO problems, but this is a fairly fundamental change to the runtime. It strikes me that mileages will also vary whether you have a green threads 1 or 2 model (see my previous post). We have a green thread 2 model, which can't schedule another Java thread unless the current Java thread hangs itself up. I will repost the patch I wrote the VM integration guide describing this too. Regards, Ian Rogers Casey Marshall wrote: This is a general question for those using Classpath with VMs that support UNIXy C implementations of native methods, but who use userland (green) threads as opposed to native threads. My understanding is that the core issue is that you can't become blocked in a system call, because that will block all threads from running. So is this restriction *exclusively* for system calls that might block? accept() and read() clearly may block, so we should provide wrappers around them that can be replaced with a userland thread-friendly version, but bind(), getsockopt(), etc. don't seem like they would (they won't, for example, ever return EAGAIN or EINTR, according to the man pages). So do fast system calls like this need to be wrapped for user threads, or will it suffice to just call them directly? I also realize that the assumption foo() will not block, because the docs say so may not be valid everywhere, since UNIX operating systems are a minefield of subtle incompatibilities. Some of these functions *should* just be copying kernel structures into the arguments, but do any syscalls block, when we should assume that they won't? Thanks.
[cp-patches] Revise threading description in vmintegration.texinfo
Hi, this patch revises the discussion of threading in the VM integration guide, as well as fixing a link to the Jikes RVM. A discussion was had on classpath@gnu.org on the 29/03/06 under the heading Green threads - some experience. The VM integration guide should now be up-to-date on this subject, although maybe my description of the problems is a little verbose. Regards, Ian Rogers -- http://www.cs.man.ac.uk/~irogers Index: vmintegration.texinfo === RCS file: /sources/classpath/classpath/doc/vmintegration.texinfo,v retrieving revision 1.27 diff -u -r1.27 vmintegration.texinfo --- vmintegration.texinfo 17 Apr 2006 12:22:19 - 1.27 +++ vmintegration.texinfo 19 Apr 2006 10:56:55 - @@ -143,7 +143,7 @@ pure GNU Classpath; it is emerging as the preferred platform for quickly testing a new build of GNU Classpath. Licensed under the GPL. [EMAIL PROTECTED] @uref{http://oss.software.ibm.com/jikesrvm,Jikes RVM} [EMAIL PROTECTED] @uref{http://jikesrvm.sourceforge.net/,Jikes RVM} A free runtime environment for Java, written in Java. Works out-of-the-box with pure GNU Classpath. Features an optimizing JIT. Runs on the x86 and PowerPC architectures, on the AIX, Linux, and Mac @@ -1426,8 +1426,7 @@ Classpath currently uses only JNI 1.1, except for one JNI 1.2 function in the JNI Invocation API: GetEnv(). And GetEnv() is only used in the -``portable native sync'' code, so it's only actually used by Jikes RVM -and Kaffe. +now deprecated ``portable native sync'' code. A future direction will probably be to require that all VMs provide JNI 1.2. If this poses problems, please raise them on the classpath @@ -1437,42 +1436,95 @@ @comment node-name, next, previous, up @section VM Threading Model -Classpath's AWT peers use GTK+. GTK+ uses GLIB. Normally, Classpath -will initialize GLIB's @dfn{gthreads} to use -the platform's native threading [EMAIL PROTECTED] native threading -model is pthreads on Linux and AIX, the two platforms Classpath -currently runs on.} - -If the Java runtime doesn't use the native threading model, then you -will want Classpath to tell GLIB to use the Java threading primitives -instead. Otherwise, GLIB would use the native threading model to -perform operations such as creating thread-local data, and that just -doesn't work on systems (such as Kaffe in some configurations, and -such as Jikes RVM) that use @i{m}:@i{n} threading. - -Historically, enabling the Java threading primitives had been done at -build time, by configuring classpath with the [EMAIL PROTECTED] option. This had bad consequences, -though -- it meant that the prebuild GNU Classpath package distributed -with Debian GNU/Linux would not be usable with VMs that could -otherwise have used it. Instead, we encourage -the use of the Java system property [EMAIL PROTECTED] A VM that wants -GLIB to use the Java threading primitives should modify [EMAIL PROTECTED]()} to include code like the -following: - [EMAIL PROTECTED] -static void insertSystemProperties(Properties @var{p}) [EMAIL PROTECTED] example -... [EMAIL PROTECTED] [EMAIL PROTECTED](gnu.classpath.awt.gtk.portable.native.sync, true); [EMAIL PROTECTED] example - -So, the configure option [EMAIL PROTECTED] is deprecated, and should go away in a -subsequent release of GNU Classpath. +VM authors can implement a number of different threading models. When +native code is also threaded there is the potential for one threading +model to deadlock the other. The [EMAIL PROTECTED]://java.sun.com/docs/books/jni/html/other.html#29406,Java +Native Interface Programmer's Guide and Specification} suggests +consulting VM documentation in such situations. Classpath uses +existing libraries, for example the AWT peers can use the GTK+ +graphics library. As these libraries assume a different threading +model, there is the potential for the native code to deadlock a VM. + +The different threading models available to a VM author are: [EMAIL PROTECTED] [EMAIL PROTECTED] [EMAIL PROTECTED] threads}: Map a Java thread to an underlying operating system +thread (normally a POSIX compatible pthread). This approach reduces +the potential for deadlock as there is only one thread scheduling +mechanism. [EMAIL PROTECTED] [EMAIL PROTECTED] threads 1}: Green threads are threads scheduled by the VM, +typically by switching swapping registers. In early VMs green threads +were seen as advantageous as they didn't require the operating system +to resechedule, save and swap all of a threads registers. The green +thread 1 model switches thread on an externally created event, such as +a timer interrupt. An example of a VM using this approach is Kaffe +configured with its jthreads model. [EMAIL PROTECTED] [EMAIL PROTECTED] threads 2}: The essential difference with this model is to +not switch threads on an event, but at fixed points in the code being +executed by the VM. Points chosen could be backward branches (loops
[cp-patches] Patch: Reduce number of compilation warnings
Hi, the attached patch reduces the number of warnings emitted when compiling classpath with jikes (in particular as part of the Jikes RVM build process). The warnings were: 1) by a negative amount - this was in the code to achieve a rotate. To make the code readable the patch adds a rotate method which is called instead. As the rotate method is private it should be an excellent candidate for inlining and not impact on performance. 2) final fields that could have been static weren't - so I made them static :-) 3) reference of a static field from an instance rather than from the class - made to reference the class instead 4) the inner class EditorContainer of DefaultTreeCellEditor had a method whose name matched that of being constructor but it wasn't a constructor - the comments in the code suggested this method shouldn't be there, so I removed it The only remaining warning was with ./gnu/java/rmi/registry/RegistryImpl_Stub.java that contains private methods whose names begin with $ and that could possibly (but quite unlikely) create a naming conflict with an automatically generated class/field. This class is automatically generated by rmic, and I couldn't see in rmic where the $ signs were creeping in :-( The patch is just a suggestion, but it cleans up watching a build for me, which could potentially help spot new bugs in the future. Regards, Ian Rogers -- http://www.cs.man.ac.uk/~irogers Index: external/sax/org/xml/sax/helpers/ParserAdapter.java === RCS file: /sources/classpath/classpath/external/sax/org/xml/sax/helpers/ParserAdapter.java,v retrieving revision 1.1 diff -u -r1.1 ParserAdapter.java --- external/sax/org/xml/sax/helpers/ParserAdapter.java 23 Dec 2004 22:38:42 - 1.1 +++ external/sax/org/xml/sax/helpers/ParserAdapter.java 13 Apr 2006 15:23:57 - @@ -561,7 +561,7 @@ // note funky case: localname can be null // when declaring the default prefix, and // yet the uri isn't null. - atts.addAttribute (nsSupport.XMLNS, prefix, + atts.addAttribute (NamespaceSupport.XMLNS, prefix, attQName.intern(), type, value); else atts.addAttribute (, , Index: gnu/java/security/hash/MD4.java === RCS file: /sources/classpath/classpath/gnu/java/security/hash/MD4.java,v retrieving revision 1.1 diff -u -r1.1 MD4.java --- gnu/java/security/hash/MD4.java 26 Jan 2006 02:25:10 - 1.1 +++ gnu/java/security/hash/MD4.java 13 Apr 2006 15:23:58 - @@ -222,107 +222,115 @@ dd = d; aa += ((bb cc) | ((~bb) dd)) + X0; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X1; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X2; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X3; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb cc) | ((~bb) dd)) + X4; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X5; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X6; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X7; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb cc) | ((~bb) dd)) + X8; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X9; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X10; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X11; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb cc) | ((~bb) dd)) + X12; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X13; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X14; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X15; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb (cc | dd)) | (cc dd)) + X0 + 0x5a827999; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa (bb | cc)) | (bb cc)) + X4 + 0x5a827999; -dd = dd 5 | dd -5; +dd = rotate(dd, 5); cc += ((dd (aa | bb)) | (aa bb)) + X8 + 0x5a827999; -cc = cc 9 | cc -9; +cc = rotate(cc, 9); bb += ((cc (dd | aa)) | (dd aa)) + X12 + 0x5a827999; -bb = bb 13 | bb -13; +bb = rotate(bb, 13); aa += ((bb (cc | dd)) | (cc dd)) + X1 + 0x5a827999; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa (bb | cc)) | (bb cc)) + X5 + 0x5a827999; -dd = dd 5 | dd -5; +dd = rotate(dd, 5); cc += ((dd (aa | bb)) | (aa bb)) + X9 + 0x5a827999; -cc = cc 9 | cc -9; +cc = rotate(cc, 9); bb += ((cc (dd | aa)) | (dd aa)) + X13 + 0x5a827999; -bb
Re: [cp-patches] Patch: Reduce number of compilation warnings
Thanks Tom, I thought I'd fix all the warnings and wait for people to complain. I agree with what you say and I've attached a fixed patch for just MD4 and MD5, any idea on how to stop the $ symbols being generated by rmic? They are on private fields so altering the names shouldn't matter. Ian Tom Tromey wrote: Ian + private static int rotate(int x, int y) { Ian +return (x y) | (x -y); Ian + } Coding style... open brace goes on its own line. Tom Index: gnu/java/security/hash/MD4.java === RCS file: /sources/classpath/classpath/gnu/java/security/hash/MD4.java,v retrieving revision 1.1 diff -u -r1.1 MD4.java --- gnu/java/security/hash/MD4.java 26 Jan 2006 02:25:10 - 1.1 +++ gnu/java/security/hash/MD4.java 13 Apr 2006 18:59:37 - @@ -222,107 +222,116 @@ dd = d; aa += ((bb cc) | ((~bb) dd)) + X0; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X1; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X2; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X3; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb cc) | ((~bb) dd)) + X4; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X5; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X6; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X7; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb cc) | ((~bb) dd)) + X8; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X9; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X10; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X11; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb cc) | ((~bb) dd)) + X12; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa bb) | ((~aa) cc)) + X13; -dd = dd 7 | dd -7; +dd = rotate(dd, 7); cc += ((dd aa) | ((~dd) bb)) + X14; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += ((cc dd) | ((~cc) aa)) + X15; -bb = bb 19 | bb -19; +bb = rotate(bb, 19); aa += ((bb (cc | dd)) | (cc dd)) + X0 + 0x5a827999; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa (bb | cc)) | (bb cc)) + X4 + 0x5a827999; -dd = dd 5 | dd -5; +dd = rotate(dd, 5); cc += ((dd (aa | bb)) | (aa bb)) + X8 + 0x5a827999; -cc = cc 9 | cc -9; +cc = rotate(cc, 9); bb += ((cc (dd | aa)) | (dd aa)) + X12 + 0x5a827999; -bb = bb 13 | bb -13; +bb = rotate(bb, 13); aa += ((bb (cc | dd)) | (cc dd)) + X1 + 0x5a827999; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa (bb | cc)) | (bb cc)) + X5 + 0x5a827999; -dd = dd 5 | dd -5; +dd = rotate(dd, 5); cc += ((dd (aa | bb)) | (aa bb)) + X9 + 0x5a827999; -cc = cc 9 | cc -9; +cc = rotate(cc, 9); bb += ((cc (dd | aa)) | (dd aa)) + X13 + 0x5a827999; -bb = bb 13 | bb -13; +bb = rotate(bb, 13); aa += ((bb (cc | dd)) | (cc dd)) + X2 + 0x5a827999; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa (bb | cc)) | (bb cc)) + X6 + 0x5a827999; -dd = dd 5 | dd -5; +dd = rotate(dd, 5); cc += ((dd (aa | bb)) | (aa bb)) + X10 + 0x5a827999; -cc = cc 9 | cc -9; +cc = rotate(cc, 9); bb += ((cc (dd | aa)) | (dd aa)) + X14 + 0x5a827999; -bb = bb 13 | bb -13; +bb = rotate(bb, 13); aa += ((bb (cc | dd)) | (cc dd)) + X3 + 0x5a827999; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += ((aa (bb | cc)) | (bb cc)) + X7 + 0x5a827999; -dd = dd 5 | dd -5; +dd = rotate(dd, 5); cc += ((dd (aa | bb)) | (aa bb)) + X11 + 0x5a827999; -cc = cc 9 | cc -9; +cc = rotate(cc, 9); bb += ((cc (dd | aa)) | (dd aa)) + X15 + 0x5a827999; -bb = bb 13 | bb -13; +bb = rotate(bb, 13); aa += (bb ^ cc ^ dd) + X0 + 0x6ed9eba1; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += (aa ^ bb ^ cc) + X8 + 0x6ed9eba1; -dd = dd 9 | dd -9; +dd = rotate(dd, 9); cc += (dd ^ aa ^ bb) + X4 + 0x6ed9eba1; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += (cc ^ dd ^ aa) + X12 + 0x6ed9eba1; -bb = bb 15 | bb -15; +bb = rotate(bb, 15); aa += (bb ^ cc ^ dd) + X2 + 0x6ed9eba1; -aa = aa 3 | aa -3; +aa = rotate(aa, 3); dd += (aa ^ bb ^ cc) + X10 + 0x6ed9eba1; -dd = dd 9 | dd -9; +dd = rotate(dd, 9); cc += (dd ^ aa ^ bb) + X6 + 0x6ed9eba1; -cc = cc 11 | cc -11; +cc = rotate(cc, 11); bb += (cc ^ dd ^ aa) + X14 + 0x6ed9eba1; -bb = bb 15 | bb -15; +bb = rotate(bb, 15); aa += (bb ^ cc ^ dd) + X1 +
Re: [cp-patches] Patch: Reduce number of compilation warnings
Hi Audrius, Wouldn't it be better to regenerate the sources rather than manually remove the $ signs? I don't know how the RMI compiler generated the sources. I'm happy to modify the files by hand otherwise. Thanks! Ian Audrius Meskauskas wrote: any idea on how to stop the $ symbols being generated by rmic? They are on private fields so altering the names shouldn't matter. I would say, just rename these private fields to match our coding standard. I see no reason to use the reserved characters there. This class is not generated during the each build and can be edited like any other. Our RMI source code generator in RMIC package is currently configured to follow the standard Classpath naming rules and would not use the dollar sign for the names of the private fields. Regards Audrius.
Re: Green threads - some experience
Archie Cobbs wrote: IMHO using POSIX threads is the only right answer for a multi-platform JVM. You have no other choice except to leave it up to the specific platform to then implement POSIX threads efficiently. For example, on Linux where each POSIX thread is a cloned process, it's Linux's fault (not the JVM's fault) if that doesn't scale well. For example, other OS's don't have such heavyweight threads. FreeBSD's KSE's are an example of a better tradeoff using M:N user:kernel threading. I agree with you. I think it's always the case that Java threads are going to be better than POSIX threads though, as with some commodity processors, in particular I'm thinking of Cell, you no longer have a shared memory model. In such a situation you could use a distributed JVM, such as JESSICA2 - that's built on top of Kaffe :-). So whilst implementing a JVM assuming POSIX threads is a good idea to run on many platforms, there are legitimate reasons why you may want to be flexible and not assume a 1-to-1 mapping of Java threads to POSIX threads, and of course avoid native code. Regards, Ian
Green threads - some experience
Hi, I'd just like to describe my experiences of getting m-to-n threading going with classpath gtk peers and the Jikes RVM. It could possibly be instructive for developers and/or other JVMs. There are different models of threading: 1) native threads: map Java threads to native pthreads - talking to people suggests this is the preferred method by classpath developers and is in the widest use 2) green threads 1: run Java threads as a single thread then on timer switch the running thread. This method is used by Kaffe's jthreads. 3) green threads 2: run Java threads as a single thread, on a timer interrupt set a flag indicating a yield is desired. At points in the code test this flag and yield if necessary. 4) m-to-n: run m green Java threads on n native threads. This approach is adopted in the Jikes RVM with green threads 2. The biggest problem is: Java threads can call into native code. This native code can call out to Java code. Not all native code will return to Java code or call out to Java code (e.g. gtk_main). If your JVM uses the green threads 2 model this presents a problem scheduling other threads. The Jikes RVM solves this problem by having a back up thread that non-blocked Java threads can be switched onto. The original Java thread continues to be blocked on the native thread. However, if the back up thread becomes blocked there's a problem. To reduce and optimise this problem the Jikes RVM replaces some system calls with non-blocking alternatives. The AWT peer problems were caused primarily by pthread mechanisms being used by GTK. These are wrapped in a library called gthreads. A Java thread would: 1) enter some native code that acquired a pthread mutex 2) call back into the JVM 3) the JVM would switch Java thread 4) the Java thread would call code that required the original mutex and block in native code not allowing other threads to get scheduled To solve this there is the portable native sync option with classpath. This option swaps the gthread mechanisms with ones that call back into the JVM. Unfortunately it is broken, will only work for GTK code and won't work if there is already GTK code using the gthread library (for example, if the JVM is a plugin). Another option is to modify classpath so that at the points where mutexs are acquired, if a mutex is busy then call back into the JVM. However, this option isn't desirable as its not required for a lot of JVMs. Another option is to try to stop the Java threads entering native code if on that native thread a Java thread is already in native code. This proved to be buggy and slow, it is likely the scheduler needs work with this option. So the simplest solution[1] was to hijack the pthread mutex locking and waiting calls and replace them with versions that call back into the JVM. This works well but the final implementation isn't quite bug free. [1] changing the threading model to using native threads wasn't considered simple. The current Jikes RVM CVS head is using this mechanism and is no longer using portable native sync. It is very likely that this code is now redundant. The JNI spec. and programmers guide section 8.1.5: http://java.sun.com/docs/books/jni/html/other.html#29406 describes consulting JVM documentation before embarking on threaded native code. Regards, Ian Rogers --- http://www.cs.man.ac.uk/~irogers/
Re: Green threads - some experience
Hi Nic, I think the long term view is to switch to POSIX threads. Having used the Jikes RVM for an OS like project, relying on native threads wouldn't have been desirable. In theory green thread context switches should be possible in a few instructions whereas a full context switch takes a few hundred. I guess its all down to the situation the JVM is trying to optimise for. Microsoft's Singularity OS makes an advantage out of not requiring full context switches. If you have as many hardware contexts as threads, then green threads would be an unnecessary overhead. Ian Nic wrote: Intersting post Ian. Maybe I'm linux 2.6 biased... but wouldn't simply using POSIX threads be so much better? NPTL is so nice. Nic
Re: [cp-patches] RFC: gnu.java.math.MPN optimizations
I have created a project to benchmark the java.math library (and these proposed changes). From looking at GMP it is amazing how complex these libraries can be made. The benchmark project is at http://bigintbench.sourceforge.net/. My first goal is to port some of the gmp benchmark programs. Interest welcomed. Many thanks, Ian Rogers -- http://www.cs.man.ac.uk/~irogers/
[cp-patches] RFC: gnu.java.math.MPN optimizations
Hi, sorry for not really knowing what the etiquette should be here. This patch alters the MPN class so that when performing adds and subtracts it avoids the use of longs. This is possible by an unsigned_less_than operation that itself uses longs, but any tree pattern matcher (such as those produced by iburg) should be able to convert into an unsigned integer comparison. ie match: boolcmp: BOOLEAN_CMP_INT(LONG_AND(register, INT_CONSTANT), LONG_AND(register, INT_CONSTANT)) where the INT_CONSTANTs are both 0xL the boolean operation is less than and the emitted code just does an unsigned integer compare on the two registers. In any case the revised code has fewer long/int operations, I believe. I've also not tested the code, so I'm really just putting it here to generate discussion. Thanks, Ian Rogers -- http://www.cs.man.ac.uk/~irogers --- MPN.java 2005-07-02 21:32:13.0 +0100 +++ MPN.hack 2006-03-22 10:55:05.0 + @@ -47,68 +47,66 @@ * (at least on platforms that use 32-bit limbs). */ public class MPN { + /** + * Perform an unsigned less than comparison on two signed integers + */ + private static boolean unsigned_less_than(int x, int y) + { + return ((long)x 0xL) ((long)y 0xL); + } /** Add x[0:size-1] and y, and write the size least * significant words of the result to dest. * Return carry, either 0 or 1. * All values are unsigned. * This is basically the same as gmp's mpn_add_1. */ public static int add_1 (int[] dest, int[] x, int size, int y) { -long carry = (long) y 0xL; -for (int i = 0; i size; i++) - { - carry += ((long) x[i] 0xL); - dest[i] = (int) carry; - carry = 32; - } -return (int) carry; + boolean carry = false; + for (int i = 0; i size; i++) { + int result = x[i] + y + (carry ? 1 : 0); + carry = unsigned_less_than(result, x[i]); + dest[i] = result; + } + return carry ? 1 : 0; } /** Add x[0:len-1] and y[0:len-1] and write the len least * significant words of the result to dest[0:len-1]. * All words are treated as unsigned. * @return the carry, either 0 or 1 * This function is basically the same as gmp's mpn_add_n. */ public static int add_n (int dest[], int[] x, int[] y, int len) { -long carry = 0; -for (int i = 0; i len; i++) - { - carry += ((long) x[i] 0xL) - + ((long) y[i] 0xL); - dest[i] = (int) carry; - carry = 32; - } -return (int) carry; + boolean carry = false; + for (int i = 0; i size; i++) { + int result = x[i] + y[i] + (carry ? 1 : 0); + carry = unsigned_less_than(result, x[i]); + dest[i] = result; + } + return carry ? 1 : 0; } /** Subtract Y[0:size-1] from X[0:size-1], and write * the size least significant words of the result to dest[0:size-1]. * Return borrow, either 0 or 1. * This is basically the same as gmp's mpn_sub_n function. */ - public static int sub_n (int[] dest, int[] X, int[] Y, int size) + public static int sub_n (int[] dest, int[] x, int[] y, int size) { -int cy = 0; -for (int i = 0; i size; i++) - { - int y = Y[i]; - int x = X[i]; - y += cy; /* add previous carry to subtrahend */ - // Invert the high-order bit, because: (unsigned) X (unsigned) Y - // iff: (int) (X^0x8000) (int) (Y^0x8000). - cy = (y^0x8000) (cy^0x8000) ? 1 : 0; - y = x - y; - cy += (y^0x8000) (x ^ 0x8000) ? 1 : 0; - dest[i] = y; - } -return cy; + boolean borrow = false; + for (int i = 0; i size; i++) { + int subtrahend = y[i] + (borrow ? 1 : 0); + int result = x[i] - subtrahend; + borrow = unsigned_less_than(x[i], subtrahend); + dest[i] = result; + } + return borrow ? 1 : 0; } /** Multiply x[0:len-1] by y, and write the len least * significant words of the product to dest[0:len-1]. * Return the most significant word of the product.
Re: JNI calls that don't return
Hi David, I agree the quote is from a book and that book isn't a specification. As core library writers people can do what they want with the JNI specification and just claim the JVM is broken if it has green threads. The book which is targetting application writers who must writer code to tackle green or native threaded JVMs doesn't have this luxury, and as such is advising using a single thread as a caution in this situation. I don't think this distracts from my points. Classpath can either: 1) only work with native threaded JVMs 2) rely upon the portable native sync code to allow gtk peers to work (albeit this system needs fixing) in situations where the JVM isn't a plugin 3) be written to the same JNI standard as would be required for an application targetting both green and native threaded code I think a --enable-green-thread-support configure option and following choice 3 would be more appropriate than choices 1 or 2, I am however not keen to develop my own branch of classpath :-). I think you back option 1, so is it inappropriate for classpath to currently have the portable native sync code in it? The other issue of java threads that have called into non-returning JNI code tying up native threads in green threaded JVMs is a separate related issue and possibly one that can be handled by a system property. For example, a property could be called gnu.classpath.jni.prefer.java.thread.yield which is a hint that non-returning JNI code either calls into java.lang.Thread.yield intermittently or avoids using purely native functions (as shown in the changes of my first e-mail on this thread). Thanks, Ian Rogers David Daney wrote: Ian Rogers wrote: The JNI provides mappings to monitor entry and exit. From google I found this document: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniref.html#thrd That is some tutorial. Not a specification on how JNI, JVMs or threading systems work. I quote: You may find that in cases where you want access to a local system resource like a MFC window handle or message queue, it is better to use one Java |Thread| and access the local threaded native event queue or messaging system from within the native code. So, it would seem to me that this is recommending using a single Java thread to access a local system resource which would avoid M-to-N threading issues as M would be 1. In classpath we are currently using multiple Java threads to access gtk. Whilst the quote is short of saying what to do with threading and JNI, I think it is a strong hint to programmers that this is a fairly murky area, probably because of the mixing of threading models. It is only a recommendation from a tutorial writer. The JVM and runtime libraries can do whatever they want within the constraints of the specifications. . . . I hope this clears up my point-of-view. Thanks,
Re: JNI calls that don't return
Andrew Haley wrote: Currently, to the best of my knowledge, classpath's gtk peer code isn't working with any JVM with M-to-N threading. No, that's not true, is it? Surely it works correctly if blocking system calls are correctly hooked by the thread library. Andrew. According to: http://sourceforge.net/tracker/index.php?func=detailaid=1147592group_id=128805atid=712768 (Jikes RVM bug #1147592) for the only JVM that I know that has M-to-N threading and uses classpath, this has been broken since 2004-12-20. I was surprised to find this to be the case but if anyone can correct me then I'm happy to be wrong. In any case there are problems to hooking the thread library which prevent it being used as an approach for JVM plugins. Thanks, Ian
Re: JNI calls that don't return
Andrew Haley wrote: Maybe you know something I don't. Is there any wordage in the JNI spec that forbids blocking calls, or suggests that this might be problematic? Is there any wordage in the JNI spec that allows the Jikes RVM to behave in the way that it does with repect to blocking calls? Andrew, I am concerned about green threads and problems caused on JVMs using them by classpath - the issues with blocking threads and synchronization have been highlighted. As I understand the JNI spec. it is designed to explain how to access Java objects, invoke Java methods from native code. It is a specification of an API and doesn't state what is valid native code - it would have to address a large number of APIs to do that. The book Advanced Programming for the Java 2 Platform that I quoted from does shed some light on what programmers using the JNI API can do, and they recommend that JNI programmers accessing MFC in their example but GTK for us, should use a single Java thread. I would argue their reasoning for this is that it avoids green threading problems. I don't believe we should use a single thread to handle GTK peer code, but we need to address the problems the current GTK peer code has with green threaded JVMs. This leads to 3 solutions: 1) declare green threaded JVMs unsuitable for use with parts of classpath 2) try to fix the portable native sync code - which has issues that I keep repeating 3) have conditionally compiled/run code that makes the code behave better in the situation of a green threaded JVM My reasons for posting was to see what people believe is the correct route from these 3 alternatives. Thanks, Ian
Re: JNI calls that don't return
Thanks for the replies. I have worked further on this and the particular issue isn't with GC barriers but with M-to-N threading. In theory if 1 of the M threads becomes blocked in a JNI call then the other threads should be moved onto another of the N underlying native threads. Unfortunately, as it's possible to call back into the JVM, the JVM's yield code can schedule another thread on the same native thread before realising the 1st thread is blocked and now its possibly handling a second blocked thread but now on the same native thread. Scheduling blocked 2 native threads running on the same native thread requires a rewrite to the underlying native thread library. For the gtk peers this is done by enabling the portable native sync code, but my experience is that this is currently broken (and using it is not advised as it would inhibit the using JVM from being used as a plugin in a gthreaded application). In any case having a fixed number of N underlying threads will probably also become a problem. Anyway, I have a small proposed change to gdk_threads_enter for JVMs with M-to-N threading (in gtkpeer.h): #define M_TO_N_JAVA_THREADING 1 #if M_TO_N_JAVA_THREADING #define gdk_threads_enter() \ {\ JNIEnv *env = cp_gtk_gdk_env();\ while(g_mutex_trylock(gdk_threads_mutex) == FALSE){ \ jclass thread_class = (*env)-FindClass (env, java/lang/Thread); \ jmethodID thread_yield_mth = (*env)-GetStaticMethodID (env, thread_class, yield, ()V); \ (*env)-CallStaticVoidMethod (env, thread_class, thread_yield_mth); \ } \ g_mutex_unlock(gdk_threads_mutex); \ gdk_threads_enter(); \ } #endif it prevents 2 java threads on the same native thread becoming deadlocked on the gdk_threads_mutex. Unfortunately the gdk_threads_mutex is supposed to be private, but I think accessing it here is suitable. I think removing the portable native sync code and having specific fixes for M-to-N threading is an appropriate change. What are others opinions? As part of this would it be possible to have versions of JNI routines that don't return that at least call Java yield in the case of being on a M-to-N threaded JVM? Thanks, Ian Rogers
Re: JNI calls that don't return
Currently, to the best of my knowledge, classpath's gtk peer code isn't working with any JVM with M-to-N threading. The problem with gdk_threads_enter is that it will block if it can't enter the threaded code. If, for example, you are mapping the gtk threads to 1 native thread then all the threads will quickly block waiting to enter gdk_threads_enter. The solution to this is for the gtk peer code not to block or to fix the portable native sync code - both require changes to classpath and there are reasons not to use portable native syncing. Whilst switching to the classpath 1-to-1 thread mapping is a desirable change to the JVM it requires a substantial amout of work with no developer currently working on it. A compromise could be to supply/apply a patch when building classpath with this JVM, but I thought the issues raised were of a more generic nature - they'd effect other JVMs that implemented M-to-N threading. Thanks, Ian Rogers Andrew Haley wrote: Ian Rogers writes: Thanks for the replies. I have worked further on this and the particular issue isn't with GC barriers but with M-to-N threading. It's possible that I'm completely missing the point here, but cannot we simply conclude from this that M-to-N threading in this JVM is broken? Andrew.
Re: JNI calls that don't return
The JNI provides mappings to monitor entry and exit. From google I found this document: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniref.html#thrd I quote: You may find that in cases where you want access to a local system resource like a MFC window handle or message queue, it is better to use one Java |Thread| and access the local threaded native event queue or messaging system from within the native code. So, it would seem to me that this is recommending using a single Java thread to access a local system resource which would avoid M-to-N threading issues as M would be 1. In classpath we are currently using multiple Java threads to access gtk. Whilst the quote is short of saying what to do with threading and JNI, I think it is a strong hint to programmers that this is a fairly murky area, probably because of the mixing of threading models. The code doesn't necessarily have to be blocked in a system call. It could be spinning on a mutex and then calling pthread yield. A system call is a valid GC point in the JVM, and I'm less worried about them than I was previously. Unfortunately blocked system calls do cause some pressure within the system and aren't desirable. Each blocked thread consumes a thread and there's a fixed number (possibly 1) to be consumed - which needs to be addressed :-) So the situation is that I have 2 threads on 1 pthread. The first thread has the gdk threads mutex. The 2nd thread wants the mutex but can't get it so calls pthread (not j.l.Thread) yield which yields back to this thread and we make no progress. Hijacking the yield and pointing it at j.l.Thread.yield is possible (this is done by the portable native sync code) but in the case the JVM has been created inside another application, for example as a plugin, hijacking the thread yield isn't possible. From my investigations, the portable native sync code is broken and it doesn't seem clear to me that fixing it will produce the best outcome - due to the plugin problem and that this approach will never work for anything but code that uses gthreads. I think having a modified version of the gtk peer code that addresses M-to-N threading issue could be desirable but I wouldn't say it has to be the compile time default. It's also possible to say that parts of classpath only work for 1-to-1 threaded JVMs. I hope this clears up my point-of-view. Thanks, Ian Rogers
JNI calls that don't return
Hi, There is at least one JNI call that is designed not to return. This is that gtkMain native method in gnu.java.awt.peer.gtk.GtkToolkit. Some VMs require all Java threads to run upto a garbage collection barrier before garbage collection can be performed. If a Java thread never leaves JNI code then this will never happen and the VM deadlocks. A solution to this is to rewrite the gtkMain loop to something like what follows: in GtkTookit.java: public static void gtkMain() { try { while(true) { while(gtkEventsPending()) { gtkMainIteration(); } Thread.sleep(10); } } catch(InterruptedException e){} } public static native void gtkMainIteration(); private static native boolean gtkEventsPending(); in gnu_java_awt_peer_gtk_GtkToolkit.c (NB regenerate the JNI header files): JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMainIteration (JNIEnv *env __attribute__((unused)), jclass obj __attribute__((unused))) { gdk_threads_enter (); gtk_main_iteration (); gdk_threads_leave (); } JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkEventsPending (JNIEnv *env __attribute__((unused)), jclass obj __attribute__((unused))) { gboolean pending; gdk_threads_enter (); pending = gtk_events_pending (); gdk_threads_leave (); return pending == TRUE ? JNI_TRUE : JNI_FALSE; } For performance the nested while loop could be moved into the JNI code. Is having all JNI code return an option for classpath? Thanks, Ian Rogers
java.util.zip
Hi, I'm trying to build the current cvs tree and can't due to dependencies between java.util.jar and java.util.zip. It seems there are some source files still to be checked in for java.util.zip. I can't e-mail the maintainer directly so I thought I'd ask here if anyone knows when the missing files will be added to java.util.zip? The web site says things are nearly complete. TIA, Ian Rogers ___ Classpath mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/classpath
Re: Why catch (NullPointerException e)?
Hi, I think this is a very interesting subject. So far two solutions have been proposed: (a) if (sm != null) { sm.XXX(); } (b) try { sm.XXX(); } catch (NullPointerException e){} I'd like to propose a third solution. It requires more programming and results in a larger binary, but on a JIT compiler (such as the one I'm working on) it may yield the fastest translated code with the lowest translation/optimisation overhead. Instead of initialising sm to null I'd like to propose that sm is initialised to a default object that is a sub class of SecurityManager. This object doesn't do anything it's merely there to clear up the confusion caused by having a null object. The reason this may yield better results is from inlining within the JIT. If we assume inlining of virtual methods produces code that looks like a switch statement: switch (sm){ case null: throw new NullPointerException(); case sm1: { /* body of method XXX for SecurityManager of type sm1 */ ... break; } case sm2: { /* body of method XXX for SecurityManager of type sm2 */ ... break; } ... } then for (a) we get: if (sm != null) { switch (sm){ case null: ... } } further analysis could remove the double comparison. for (b) we get: try { switch (sm){ case null:... } } catch (NullPointerException e) {} further analysis could place the body of the exception handler in the null case. for the third solution we get: switch (sm){ case null: throw new NullPointerException(); case sm1: ... case sm2: ... case default_sm: { /* The empty body of the new default method */ } ... } This immediately gives the default case an empty body, unlike (b) which requires an optimisation to do this. It also doesn't require analysis looking for double comparisons. I know this makes a lot of assumptions on the workings of a JIT and on the target JVM for Classpath. I wanted offer this solution to see what others opinions are. Cheers, -- Ian Rogers -- Dept. Of Computer Science -- The University of Manchester