前一阵给sun报的bug,对jit compiler有兴趣的同学可以看一下

wkoffee 2011-01-08
在64位环境下测试:
public class OverflowTest{
	static int test( byte a[] ){
		int result =0;
		for( int i=0;i<a.length; i+=((0x7fffffff>>1)+1) ){
			result += a[i];
		}
		return result;
	}

	public static void main( String [] args ){
		byte a[] = new byte[(0x7fffffff>>1)+2];
		System.out.println( ""+test(a));
	}
}

java -Xint -Xms2000m OverflowTest
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2147483648
at OverflowTest.test(OverflowTest.java:5)
at OverflowTest.main(OverflowTest.java:12)

java -Xcomp -Xms2000m OverflowTest
0

应该是和loop opt有关,目前还没有解决

xgj1988 2011-03-18
SUN给你回复没,兄弟
wkoffee 2011-03-24
他们接受了这个bug,但是没有后续消息,好像现在最新的代码还没有解决。
RednaxelaFX 2011-07-02
wkoffee 写道
他们接受了这个bug,但是没有后续消息,好像现在最新的代码还没有解决。

话说这bug有bug ID不?是多少呢?

更新:
好吧,我知道了。此bug已fix,今年5月初修好的。
Bug ID 5091921: Sign flip issues in loop optimizer
Changeset: http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/bad7ecd0b6ed

然后还有一个后续修复:
Bug ID 7052494: Eclipse test fails on JDK 7 b142

很早之前就有人报告过这个问题:
Bug ID 6186134: Server virtual machine produces/exeutes incorrect code.
Bug ID 6890943: JVM mysteriously gives wrong result on 64-bit 1.6 VMs in hotspot mode.

具体到这帖顶楼的现象是由LoopLimitCheck参数所控制的代码修复的。可以用顶楼的代码
public class OverflowTest {
	static int test(byte[] a) {
		int result = 0;
		for (int i = 0; i < a.length; i += ((Integer.MAX_VALUE >> 1) + 1)) {
			result += a[i];
		}
		return result;
	}

	public static void main(String[] args) {
		byte[] a = new byte[(Integer.MAX_VALUE >> 1) + 2];
		System.out.println(Integer.toString(test(a)));
	}
}

这样验证:
$ java -version
java version "1.7.0-fastdebug"
Java(TM) SE Runtime Environment (build 1.7.0-fastdebug-b147)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17-fastdebug, mixed mode)
$ java -cp . -Xint -Xms2g OverflowTest
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2147483648
        at OverflowTest.test(OverflowTest.java:5)
        at OverflowTest.main(OverflowTest.java:12)
$ java -cp . -Xcomp -Xms2g OverflowTest
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2147483648
        at OverflowTest.test(OverflowTest.java:5)
        at OverflowTest.main(OverflowTest.java:12)
$ java -cp . -Xcomp -Xms2g -XX:-LoopLimitCheck OverflowTest
VM option '-LoopLimitCheck'
0

可以看到如果把LoopLimitCheck设为false的话就会表现出跟之前一样的问题。

在加入新的行为后,可以用-XX:+TraceDeoptimization -XX:+PrintOptoAssembly来了解新的编译器行为:
{method} 
 - klass: {other class}
 - this oop:          0x000000077b0a8e08
 - method holder:     'OverflowTest'
 - constants:         0x000000077b0a8a28 constant pool [50] for 'OverflowTest' cache=0x000000077b0aacd0
 - access:            0xc1000009  public static 
 - name:              'test'
 - signature:         '([B)I'
 - max stack:         3
 - max locals:        3
 - size of params:    1
 - method size:       17
 - vtable index:      -2
 - i2i entry:         0x00002aaaab349ee0
 - adapter:           0x000000000b10a170
 - compiled entry     0x00002aaaab3f8771
 - code size:         26
 - code start:        0x000000077b0a8dc0
 - code end (excl):   0x000000077b0a8dda
 - method data:       0x000000077b0ac250
 - checked ex length: 0
 - linenumber start:  0x000000077b0a8dda
 - localvar length:   3
 - localvar start:    0x000000077b0a8de2
#
#  int ( byte[int:>=0]:exact * )
#
#r018 rsi:rsi   : parm 0: byte[int:>=0]:exact *
# -- Old rsp -- Framesize: 32 --
#r089 rsp+28: pad2, in_preserve
#r088 rsp+24: pad2, in_preserve
#r087 rsp+20: pad2, in_preserve
#r086 rsp+16: pad2, in_preserve
#r085 rsp+12: pad2, in_preserve
#r084 rsp+ 8: return address
#r083 rsp+ 4: Fixed slot 1
#r082 rsp+ 0: Fixed slot 0
#
abababab   N1: #	B1 <- B13 B11 B12 B10  Freq: 1
abababab
000   B1: #	B13 B2 <- BLOCK HEAD IS JUNK   Freq: 1
000   	# stack bang
	pushq   rbp
	subq    rsp, #16	# Create frame
00c   	movl    R11, [RSI + #12 (8-bit)]	# range
010   	NullCheck RSI
010
010   B2: #	B9 B3 <- B1  Freq: 0.999999
010   	xorl    R10, R10	# int
013   	testl   R11, R11
016   	jle,s   B9  P=0.500000 C=-1.000000
016
018   B3: #	B11 B4 <- B2  Freq: 0.499999
018   	testl  R11, R11	# unsigned
01b   	jbe,us  B11  P=0.000001 C=-1.000000
01b
01d   B4: #	B11 B5 <- B3  Freq: 0.499999
01d   	movslq  R8, R11	# i2l
020   	addq    R8, #1073741823	# long
027   	andq    R8, #-1073741824	# long
02e   	movl    R8, R8	# l2i
031   	addl    R8, #-1073741824	# int
038   	cmpl    R8, R11	# unsigned
03b   	jnb,us  B11  P=0.000001 C=-1.000000
03b
03d   B5: #	B12 B6 <- B4  Freq: 0.499998
03d   	cmpl    R11, #1073741824
044   	jg,s   B12  P=0.000001 C=-1.000000
044
046   B6: #	B7 <- B5  Freq: 0.499998
046   	xorl    RAX, RAX	# int
      	nop 	# 8 bytes pad for loops and calls

050   B7: #	B7 B8 <- B6 B7 	Loop: B7-B7 inner  Freq: 4.99998
050   	movslq  R8, R10	# i2l
053   	movsbl  R8, [RSI + #16 + R8]	# byte
059   	addl    RAX, R8	# int
05c   	addl    R10, #1073741824	# int
063   	cmpl    R10, R11
066   	jl,s   B7	# loop end  P=0.900000 C=-1.000000
066
068   B8: #	B10 <- B7  Freq: 0.499998
068   	jmp,s   B10
068
06a   B9: #	B10 <- B2  Freq: 0.499999
06a   	xorl    RAX, RAX	# int
06c
06c   B10: #	N1 <- B8 B9  Freq: 0.999997
06c   	addq    rsp, 16	# Destroy frame
	popq   rbp
	testl  rax, [rip + #offset_to_poll_page]	# Safepoint: poll for GC

077   	ret
077
078   B11: #	N1 <- B4 B3  Freq: 1.00664e-06
078   	movq    RBP, RSI	# spill
07b   	movl    RSI, #-122	# int
080   	nop 	# 3 bytes pad for loops and calls
083   	call,static  wrapper for: uncommon_trap(reason='predicate' action='maybe_recompile')
        # OverflowTest::test @ bci:10  L[0]=RBP L[1]=#0 L[2]=#0
        # OopMap{rbp=Oop off=136}
088   	int3	# ShouldNotReachHere
088
095   B12: #	N1 <- B5  Freq: 5.06638e-07
095   	movq    RBP, RSI	# spill
098   	movl    RSI, #-130	# int
09d   	nop 	# 2 bytes pad for loops and calls
09f   	call,static  wrapper for: uncommon_trap(reason='loop_limit_check' action='maybe_recompile')
        # OverflowTest::test @ bci:10  L[0]=RBP L[1]=#0 L[2]=#0
        # OopMap{rbp=Oop off=164}
0a4   	int3	# ShouldNotReachHere
0a4
0b1   B13: #	N1 <- B1  Freq: 1.01328e-06
0b1   	movl    RSI, #-10	# int
0b6   	nop 	# 1 bytes pad for loops and calls
0b7   	call,static  wrapper for: uncommon_trap(reason='null_check' action='maybe_recompile')
        # OverflowTest::test @ bci:6  L[0]=_ L[1]=_ L[2]=_ STK[0]=_ STK[1]=#NULL
        # OopMap{off=188}
0bc   	int3	# ShouldNotReachHere
0bc

Uncommon trap occurred in OverflowTest::test (@0x00002aaaab488cc4) thread=1074809152 reason=loop_limit_check action=maybe_recompile unloaded_class_index=-1
DEOPT PACKING thread 0x000000000b02c000 Compiled frame (sp=0x00000000401039b0 unextended sp=0x00000000401039b0, fp=0x0000000780000000, pc=0x00002aaaab488cc4)
     nmethod   9845  361             OverflowTest::test (26 bytes)

     Virtual frames (innermost first):
        0 - frame( sp=0x00000000401039b0, unextended_sp=0x00000000401039b0, fp=0x0000000780000000, pc=0x00002aaaab488cc4)
OverflowTest.test(OverflowTest.java:5) - iload_1 @ bci 10 
     Created vframeArray 0x000000000b402298
DEOPT UNPACKING thread 0x000000000b02c000 vframeArray 0x000000000b402298 mode 2
     {method} 'test' '([B)I' in 'OverflowTest' - iload_1 @ bci 10 sp = 0x0000000040103970

可以看到新的行为是,编译器会生成检查循环条件溢出的代码,当真的发生溢出时会掉进一个uncommon trap(Deoptimization::Reason_loop_limit_check)回到解释器执行。
这样正确性是没问题了,但感觉搞不好会deoptimize掉一堆原本不需要deoptimize的方法。不能换个解决办法么…
huxi 2011-07-08
RednaxelaFX 写道
Bug ID 7052494: Eclipse test fails on JDK 7 b142

I traced it to new code which changes loop check "for(i != lim; i++)" to "for(i < lim; i++)". Such conversion is incorrect when initial value is >= lim (note, such loops are terminated by other checks inside loop's body).
Posted Date : 2011-06-17 02:10:19.0

http://hg.openjdk.java.net/hsx/hotspot-comp/hotspot/rev/aacaff365100
Posted Date : 2011-06-21 05:56:07.0

http://hg.openjdk.java.net/jdk7/hotspot/hotspot/rev/782e2bb60c41
Posted Date : 2011-06-23 23:32:26.0

这个在刚发布的JDK7 RC b147里搞定了。
RednaxelaFX 2011-07-08
huxi 写道
这个在刚发布的JDK7 RC b147里搞定了。

嗯,是撒。你看我在上面回复里就是用JDK7b147的
huxi 2011-07-08
RednaxelaFX 写道
huxi 写道
这个在刚发布的JDK7 RC b147里搞定了。

嗯,是撒。你看我在上面回复里就是用JDK7b147的

got it.
Global site tag (gtag.js) - Google Analytics