-
Enhancement
-
Resolution: Unresolved
-
P4
-
6, 9, 10
-
generic
-
generic
A DESCRIPTION OF THE REQUEST :
The following java class creates the following assembler code (i486). The code was obtained with 1.6.0-rc-fastdebug-b90-debug and the following options,
VM option '+PrintCompilation'
VM option '+PrintInlining'
VM option '+PrintOptoAssembly'
JUSTIFICATION :
In a small class like below it's not much but wenn considering a Matrix4f class with 16 members - this creates 15 unneccessarry (and impossible to call) traps.
Which is bad because these get methods are mostly inlined into the caller and causes increased memory footprint (and runtime).
These kind of get(FloatBuffer xxx) methods are always hot methods in a 3d engine.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The CMP EBX, xxx in block B3, B4 and the TEST EBX, EBX in block B5 can never evaluate to true. Thus B7, B8 and B9 can never be called.
In this method this would save 14 bytes (for the checks) and 77 bytes for the traps. This makes 91 bytes or 36% of this method.
ACTUAL -
192 b de.matthiasmann.worldscape.math.Plane::get (34 bytes)
@ 6 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
@ 14 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
@ 22 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
@ 30 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
{method}
- klass: {other class}
- method holder: 'de/matthiasmann/worldscape/math/Plane'
- constants: 0x083ed660{constant pool}
- access: 0x81000001 public
- name: 'get'
- signature: '(Ljava/nio/FloatBuffer;)Ljava/nio/FloatBuffer;'
- max stack: 3
- max locals: 2
- size of params: 2
- method size: 22
- vtable index: 5
- code size: 34
- code start: 0x1046ba38
- code end (excl): 0x1046ba5a
- method data: 0x10524eb0
- checked ex length: 0
- linenumber start: 0x1046ba5a
- localvar length: 2
- localvar start: 0x1046ba5e
#
# java/nio/DirectFloatBufferU * ( de/matthiasmann/worldscape/math/Plane:NotNull *, java/nio/DirectFloatBufferU * )
#
#r000 ecx : parm 0: de/matthiasmann/worldscape/math/Plane:NotNull *
#r005 edx : parm 1: java/nio/DirectFloatBufferU *
# -- Old esp -- Framesize: 80 --
#r045 esp+76: return address
#r044 esp+72: pad2, in_preserve
#r043 esp+68: pad2, in_preserve
#r042 esp+64: pad2, in_preserve
#r061 esp+60: spill
#r060 esp+56: spill
#r059 esp+52: spill
#r058 esp+48: spill
#r057 esp+44: spill
#r056 esp+40: spill
#r055 esp+36: spill
#r054 esp+32: spill
#r053 esp+28: spill
#r052 esp+24: spill
#r051 esp+20: spill
#r050 esp+16: spill
#r049 esp+12: spill
#r048 esp+ 8: spill
#r047 esp+ 4: spill
#r046 esp+ 0: spill
#
000 N121: # B1 <- BLOCK HEAD IS JUNK Freq: 10000
000 CMP EAX,[ECX+4] # Inline cache check
JNE SharedRuntime::handle_ic_miss_stub
NOP
NOP
NOP
000
00c B1: # B11 B2 <- BLOCK HEAD IS JUNK Freq: 10000
00c # stack bang
PUSHL EBP
SUB ESP,72 # Create frame
01a MOVSS XMM1a,[ECX + #20]
01f MOV ESI,EDX
021 MOV EBX,[EDX + #24]
024 NullCheck EDX
024
024 B2: # B10 B3 <- B1 Freq: 9999.99
024 MOV EDI,#464
029 MOV EDI,[EDI + precise klass java/nio/DirectFloatBufferU: 0x35b88978:Constant:exact *]
02f CMP EBX,#3
032 Jle B10 P=0.000000 C=6701.000000
032
038 B3: # B9 B4 <- B2 Freq: 6701
038 MOV EAX.lo,[ESI + #8]
MOV EAX.hi,[ESI + #8]+4
03e MOVSS XMM2a,[ECX + #16]
043 #castL2P of eAX
043 MOVSS [EAX + #12],XMM1a
048 CMP EBX,#2
04b Jle,s B9 P=0.000000 C=6701.000000
04b
04d B4: # B8 B5 <- B3 Freq: 6701
04d MOVSS [EAX + #8],XMM2a
052 MOVSS XMM0a,[ECX + #12]
057 CMP EBX,#1
05a Jle,s B8 P=0.000000 C=6701.000000
05a
05c B5: # B7 B6 <- B4 Freq: 6701
05c MOVSS [EAX + #4],XMM0a
061 MOVSS XMM0a,[ECX + #8]
066 TEST EBX,EBX
068 Jle,s B7 P=0.000000 C=6701.000000
068
06a B6: # N121 <- B5 Freq: 6701
06a MOVSS [EAX],XMM0a
06e MOV EAX,ESI
070 ADD ESP,72 # Destroy frame
POPL EBP
TEST PollPage,EAX ! Poll Safepoint
07a RET
07a
07b B7: # N121 <- B5 Freq: 0.0015
07b MOV ECX,#16
080 MOV EBP,ESI
082 MOVSS [ESP + #0],XMM0a
087 MOV [ESP + #4],EDI
08b CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=EBP L[1]=_ L[2]=esp + #0 STK[0]=esp + #4 STK[1]=EBP
# de.matthiasmann.worldscape.math.Plane::get @ bci:30 L[0]=_ L[1]=_
# ebp=Oop [4]=Oop
090 INT3 ; ShouldNotReachHere
090
091 B8: # N121 <- B4 Freq: 0.0015
091 MOV EBP,ECX
093 MOV [ESP + #0],ESI
096 MOVSS [ESP + #4],XMM0a
09c MOV [ESP + #8],EDI
0a0 MOV ECX,#16
0a5 NOP # Pad for loops and calls
0a6 NOP # Pad for loops and calls
0a7 CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=esp + #0 L[1]=_ L[2]=esp + #4 STK[0]=esp + #8 STK[1]=esp + #0
# de.matthiasmann.worldscape.math.Plane::get @ bci:22 L[0]=EBP L[1]=_
# ebp=Oop [0]=Oop [8]=Oop
0ac INT3 ; ShouldNotReachHere
0ac
0ad B9: # N121 <- B3 Freq: 0.0015
0ad MOV EBP,ECX
0af MOV [ESP + #0],ESI
0b2 MOVSS [ESP + #4],XMM2a
0b8 MOV [ESP + #8],EDI
0bc MOV ECX,#16
0c1 NOP # Pad for loops and calls
0c2 NOP # Pad for loops and calls
0c3 CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=esp + #0 L[1]=_ L[2]=esp + #4 STK[0]=esp + #8 STK[1]=esp + #0
# de.matthiasmann.worldscape.math.Plane::get @ bci:14 L[0]=EBP L[1]=_
# ebp=Oop [0]=Oop [8]=Oop
0c8 INT3 ; ShouldNotReachHere
0c8
0c9 B10: # N121 <- B2 Freq: 0.0015
0c9 MOV EBP,ECX
0cb MOV [ESP + #0],EDX
0ce MOVSS [ESP + #4],XMM1a
0d4 MOV [ESP + #8],EDI
0d8 MOV ECX,#16
0dd NOP # Pad for loops and calls
0de NOP # Pad for loops and calls
0df CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=esp + #0 L[1]=_ L[2]=esp + #4 STK[0]=esp + #8 STK[1]=esp + #0
# de.matthiasmann.worldscape.math.Plane::get @ bci:6 L[0]=EBP L[1]=_
# ebp=Oop [0]=Oop [8]=Oop
0e4 INT3 ; ShouldNotReachHere
0e4
0e5 B11: # N121 <- B1 Freq: 0.0015
0e5 MOV ECX,#-10
0ea MOV EBP,EDX
0ec MOVSS [ESP + #0],XMM1a
0f1 NOP # Pad for loops and calls
0f2 NOP # Pad for loops and calls
0f3 CALL,static wrapper for: uncommon_trap
# de.matthiasmann.worldscape.math.Plane::get @ bci:6 L[0]=_ L[1]=_ STK[0]=EBP STK[1]=#3 STK[2]=esp + #0
# ebp=Oop
0f8 INT3 ; ShouldNotReachHere
0f8
---------- BEGIN SOURCE ----------
public class Plane {
public float nx, ny, nz;
public float d;
public FloatBuffer get(FloatBuffer b) {
return b.put(3, d).put(2, nz).put(1, ny).put(0, nx);
}
}
---------- END SOURCE ----------
A more complete test case, Test.java, is attached.
The following java class creates the following assembler code (i486). The code was obtained with 1.6.0-rc-fastdebug-b90-debug and the following options,
VM option '+PrintCompilation'
VM option '+PrintInlining'
VM option '+PrintOptoAssembly'
JUSTIFICATION :
In a small class like below it's not much but wenn considering a Matrix4f class with 16 members - this creates 15 unneccessarry (and impossible to call) traps.
Which is bad because these get methods are mostly inlined into the caller and causes increased memory footprint (and runtime).
These kind of get(FloatBuffer xxx) methods are always hot methods in a 3d engine.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The CMP EBX, xxx in block B3, B4 and the TEST EBX, EBX in block B5 can never evaluate to true. Thus B7, B8 and B9 can never be called.
In this method this would save 14 bytes (for the checks) and 77 bytes for the traps. This makes 91 bytes or 36% of this method.
ACTUAL -
192 b de.matthiasmann.worldscape.math.Plane::get (34 bytes)
@ 6 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
@ 14 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
@ 22 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
@ 30 java.nio.DirectFloatBufferU::put inline (hot)
@ 6 java.nio.Buffer::checkIndex inline (hot)
@ 9 java.nio.DirectFloatBufferU::ix inline (hot)
Inlining Unsafe.putFloat(JF)V
Inlining intrinsic virtual void sun.misc.Unsafe.putFloat(jlong, jfloat)
{method}
- klass: {other class}
- method holder: 'de/matthiasmann/worldscape/math/Plane'
- constants: 0x083ed660{constant pool}
- access: 0x81000001 public
- name: 'get'
- signature: '(Ljava/nio/FloatBuffer;)Ljava/nio/FloatBuffer;'
- max stack: 3
- max locals: 2
- size of params: 2
- method size: 22
- vtable index: 5
- code size: 34
- code start: 0x1046ba38
- code end (excl): 0x1046ba5a
- method data: 0x10524eb0
- checked ex length: 0
- linenumber start: 0x1046ba5a
- localvar length: 2
- localvar start: 0x1046ba5e
#
# java/nio/DirectFloatBufferU * ( de/matthiasmann/worldscape/math/Plane:NotNull *, java/nio/DirectFloatBufferU * )
#
#r000 ecx : parm 0: de/matthiasmann/worldscape/math/Plane:NotNull *
#r005 edx : parm 1: java/nio/DirectFloatBufferU *
# -- Old esp -- Framesize: 80 --
#r045 esp+76: return address
#r044 esp+72: pad2, in_preserve
#r043 esp+68: pad2, in_preserve
#r042 esp+64: pad2, in_preserve
#r061 esp+60: spill
#r060 esp+56: spill
#r059 esp+52: spill
#r058 esp+48: spill
#r057 esp+44: spill
#r056 esp+40: spill
#r055 esp+36: spill
#r054 esp+32: spill
#r053 esp+28: spill
#r052 esp+24: spill
#r051 esp+20: spill
#r050 esp+16: spill
#r049 esp+12: spill
#r048 esp+ 8: spill
#r047 esp+ 4: spill
#r046 esp+ 0: spill
#
000 N121: # B1 <- BLOCK HEAD IS JUNK Freq: 10000
000 CMP EAX,[ECX+4] # Inline cache check
JNE SharedRuntime::handle_ic_miss_stub
NOP
NOP
NOP
000
00c B1: # B11 B2 <- BLOCK HEAD IS JUNK Freq: 10000
00c # stack bang
PUSHL EBP
SUB ESP,72 # Create frame
01a MOVSS XMM1a,[ECX + #20]
01f MOV ESI,EDX
021 MOV EBX,[EDX + #24]
024 NullCheck EDX
024
024 B2: # B10 B3 <- B1 Freq: 9999.99
024 MOV EDI,#464
029 MOV EDI,[EDI + precise klass java/nio/DirectFloatBufferU: 0x35b88978:Constant:exact *]
02f CMP EBX,#3
032 Jle B10 P=0.000000 C=6701.000000
032
038 B3: # B9 B4 <- B2 Freq: 6701
038 MOV EAX.lo,[ESI + #8]
MOV EAX.hi,[ESI + #8]+4
03e MOVSS XMM2a,[ECX + #16]
043 #castL2P of eAX
043 MOVSS [EAX + #12],XMM1a
048 CMP EBX,#2
04b Jle,s B9 P=0.000000 C=6701.000000
04b
04d B4: # B8 B5 <- B3 Freq: 6701
04d MOVSS [EAX + #8],XMM2a
052 MOVSS XMM0a,[ECX + #12]
057 CMP EBX,#1
05a Jle,s B8 P=0.000000 C=6701.000000
05a
05c B5: # B7 B6 <- B4 Freq: 6701
05c MOVSS [EAX + #4],XMM0a
061 MOVSS XMM0a,[ECX + #8]
066 TEST EBX,EBX
068 Jle,s B7 P=0.000000 C=6701.000000
068
06a B6: # N121 <- B5 Freq: 6701
06a MOVSS [EAX],XMM0a
06e MOV EAX,ESI
070 ADD ESP,72 # Destroy frame
POPL EBP
TEST PollPage,EAX ! Poll Safepoint
07a RET
07a
07b B7: # N121 <- B5 Freq: 0.0015
07b MOV ECX,#16
080 MOV EBP,ESI
082 MOVSS [ESP + #0],XMM0a
087 MOV [ESP + #4],EDI
08b CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=EBP L[1]=_ L[2]=esp + #0 STK[0]=esp + #4 STK[1]=EBP
# de.matthiasmann.worldscape.math.Plane::get @ bci:30 L[0]=_ L[1]=_
# ebp=Oop [4]=Oop
090 INT3 ; ShouldNotReachHere
090
091 B8: # N121 <- B4 Freq: 0.0015
091 MOV EBP,ECX
093 MOV [ESP + #0],ESI
096 MOVSS [ESP + #4],XMM0a
09c MOV [ESP + #8],EDI
0a0 MOV ECX,#16
0a5 NOP # Pad for loops and calls
0a6 NOP # Pad for loops and calls
0a7 CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=esp + #0 L[1]=_ L[2]=esp + #4 STK[0]=esp + #8 STK[1]=esp + #0
# de.matthiasmann.worldscape.math.Plane::get @ bci:22 L[0]=EBP L[1]=_
# ebp=Oop [0]=Oop [8]=Oop
0ac INT3 ; ShouldNotReachHere
0ac
0ad B9: # N121 <- B3 Freq: 0.0015
0ad MOV EBP,ECX
0af MOV [ESP + #0],ESI
0b2 MOVSS [ESP + #4],XMM2a
0b8 MOV [ESP + #8],EDI
0bc MOV ECX,#16
0c1 NOP # Pad for loops and calls
0c2 NOP # Pad for loops and calls
0c3 CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=esp + #0 L[1]=_ L[2]=esp + #4 STK[0]=esp + #8 STK[1]=esp + #0
# de.matthiasmann.worldscape.math.Plane::get @ bci:14 L[0]=EBP L[1]=_
# ebp=Oop [0]=Oop [8]=Oop
0c8 INT3 ; ShouldNotReachHere
0c8
0c9 B10: # N121 <- B2 Freq: 0.0015
0c9 MOV EBP,ECX
0cb MOV [ESP + #0],EDX
0ce MOVSS [ESP + #4],XMM1a
0d4 MOV [ESP + #8],EDI
0d8 MOV ECX,#16
0dd NOP # Pad for loops and calls
0de NOP # Pad for loops and calls
0df CALL,static wrapper for: uncommon_trap
# java.nio.Buffer::checkIndex @ bci:12 L[0]=_ L[1]=_
# java.nio.DirectFloatBufferU::put @ bci:6 L[0]=esp + #0 L[1]=_ L[2]=esp + #4 STK[0]=esp + #8 STK[1]=esp + #0
# de.matthiasmann.worldscape.math.Plane::get @ bci:6 L[0]=EBP L[1]=_
# ebp=Oop [0]=Oop [8]=Oop
0e4 INT3 ; ShouldNotReachHere
0e4
0e5 B11: # N121 <- B1 Freq: 0.0015
0e5 MOV ECX,#-10
0ea MOV EBP,EDX
0ec MOVSS [ESP + #0],XMM1a
0f1 NOP # Pad for loops and calls
0f2 NOP # Pad for loops and calls
0f3 CALL,static wrapper for: uncommon_trap
# de.matthiasmann.worldscape.math.Plane::get @ bci:6 L[0]=_ L[1]=_ STK[0]=EBP STK[1]=#3 STK[2]=esp + #0
# ebp=Oop
0f8 INT3 ; ShouldNotReachHere
0f8
---------- BEGIN SOURCE ----------
public class Plane {
public float nx, ny, nz;
public float d;
public FloatBuffer get(FloatBuffer b) {
return b.put(3, d).put(2, nz).put(1, ny).put(0, nx);
}
}
---------- END SOURCE ----------
A more complete test case, Test.java, is attached.