JDK-7044725 : -XX:-UnrollLimitCheck -Xcomp : Exception: String index out of range: 29488
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs21
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2011-05-13
  • Updated: 2011-08-02
  • Resolved: 2011-07-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 Other
7Fixed 8Fixed hs21Fixed
Related Reports
Relates :  
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
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.
17-05-2011

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

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