United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7044725 -XX:-UnrollLimitCheck -Xcomp : Exception: String index out of range: 29488
JDK-7044725 : -XX:-UnrollLimitCheck -Xcomp : Exception: String index out of range: 29488

Details
Type:
Bug
Submit Date:
2011-05-13
Status:
Closed
Updated Date:
2011-08-02
Project Name:
JDK
Resolved Date:
2011-07-18
Component:
hotspot
OS:
generic
Sub-Component:
compiler
CPU:
generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
hs21
Fixed Versions:
hs21 (b14)

Related Reports
Backport:
Backport:
Backport:
Relates:

Sub Tasks

Description
% /java/re/jdk/7/promoted/all/b142/binaries/solaris-i586/bin/java -server -XX:+UnlockDiagnosticVMOptions -XX:-UnrollLimitCheck -Xcomp t
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 29488
	at java.lang.String.substring(String.java:1955)
	at java.io.UnixFileSystem.normalize(UnixFileSystem.java:69)
	at java.io.UnixFileSystem.normalize(UnixFileSystem.java:89)
	at java.io.File.<init>(File.java:253)
	at sun.misc.URLClassPath$JarLoader.<init>(URLClassPath.java:619)
	at sun.misc.URLClassPath$3.run(URLClassPath.java:362)
	at sun.misc.URLClassPath$3.run(URLClassPath.java:352)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.misc.URLClassPath.getLoader(URLClassPath.java:351)
	at sun.misc.URLClassPath.getLoader(URLClassPath.java:328)
	at sun.misc.URLClassPath.getResource(URLClassPath.java:194)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:358)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:410)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:472)

And with JDK6 new VM crash with -XX:-UnrollLimitCheck:

% cp /java/re/jdk/7/promoted/all/b142/binaries/solaris-i586/jre/lib/i386/server/libjvm.so /export/kvn/jdk6u25/fastdebug/jre/lib/i386/server/

% /export/kvn/jdk6u25/fastdebug/bin/java -server -XX:+UnlockDiagnosticVMOptions -XX:-UnrollLimitCheck -XX:CICompilerCount=1 -Xbatch -Xcomp t
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0xfaa6b18a, pid=20822, tid=2
#
# JRE version: 6.0_25-b03
# Java VM: Java HotSpot(TM) Server VM (21.0-b12 compiled mode solaris-x86 )
# Problematic frame:
# J  java.io.UnixFileSystem.normalize(Ljava/lang/String;)Ljava/lang/String;
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /export/kvn/VM/hs_err_pid20822.log

                                    

Comments
EVALUATION

New range check elimination code is broken. And old RCE implementation was also broken by changes for 5091921. Must fix for jdk7.
                                     
2011-05-14
EVALUATION

http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/38569792a45a
                                     
2011-05-17
PUBLIC COMMENTS

The main problem in new RCE code was in case when stride and scale have different sign. In that case new main_loop limit was calculated as
min(old_main_limit, X) where X=(min_int+1 - (offset+1))/scale. With offset 0 and scale == -1, X value is min_int since min_int/-1 = min_int. So the new main loop limit is min_int. New unrolling code correctly handles such case by skipping main loop. Old code did ((limit -init)/stride) with stride == 1 and init == 1 (value after increment in preloop). So new limit for unrolled loop become (min_int-1) == max_int. I solve this by replacing positive (offset+1) with 0 and avoiding underflow in X calculation. It is the same approach as one used in current code for pre_limit in case scale and stride have the same sign.

An other problem with new code is it does not generate the adjusted pre-loop limit when RangeLimitCheck is off. RCE old code did it before.

After thinking more about pre_limit guard in do_range_check() "min(pre_limit, orig_limit)" I decided to always generate it to be safe. The offset and scale in RC condition could have such values that X=(low_limit-offset)/scale will be outside of loop iterations range: max(pre_limit, X) could be > orig_limit.

I also factor out common code, replaced (stride*scale) with logical expressions to avoid overflow.

Tested with/without UnrollLimitCheck CTW, JPRT, nsk.stress, 5091921 tests.
                                     
2011-05-17



Hardware and Software, Engineered to Work Together