JDK-6914095 : HotSpot should reuse invariant loop parameter
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2010-01-05
  • Updated: 2011-10-11
  • Resolved: 2010-11-09
Description
FULL PRODUCT VERSION :
java version "1.7.0-ea-fastdebug"
Java(TM) SE Runtime Environment (build 1.7.0-ea-fastdebug-b76)
Java HotSpot(TM) Client VM (build 17.0-b05-fastdebug, mixed mode)


FULL OS VERSION :
Windows XP SP-3

EXTRA RELEVANT SYSTEM CONFIGURATION :
using hsdis library
See:
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/branches/j7_EUC_TW/nbproject/configs/C_d_b_c1_f3_shortMap5_PA.properties?rev=895&view=markup

A DESCRIPTION OF THE PROBLEM :
In the for loop in my code I have
    code<(page+1)*PAGE_LENGTH
as loop termination.
Variable page is local and  is not altered in the loop, and PAGE_LENGTH is static final, so the result from "(page+1)*PAGE_LENGTH" should be remembered instead of recalculated each loop.

In disassembly in pc 0x00bc9e1b the result is held in ecx register.
In pc 0x00bc9e2e ecx register is overwritten without saving the result before.


THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run from NetBeans 6.8 using:
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/branches/j7_EUC_TW/nbproject/configs/C_d_b_c1_f3_shortMap5_PA.properties?rev=895&view=markup


EXPECTED VERSUS ACTUAL BEHAVIOR :
Output from disassembly:

  0x00bc9e0a: mov    %ebp,0xc(%esp)
  0x00bc9e0e: imul   $0x5e,%ebp,%ecx    ;*imul
                                        ; - sun.nio.cs.ext.EUC_TW_C_d_b_c1_f3_shortMap4$Encoder::&lt;clinit&gt;@129 (line 329)
  0x00bc9e11: cmp    0x18(%esp),%ebx
  0x00bc9e15: jg     0x00bc9f81         ;*if_icmpgt
                                        ; - sun.nio.cs.ext.EUC_TW_C_d_b_c1_f3_shortMap4$Encoder::&lt;clinit&gt;@139 (line 329)
  0x00bc9e1b: add    $0x5e,%ecx
  0x00bc9e1e: mov    0x24(%esp),%ebp
  0x00bc9e22: cmp    %ecx,%ebp
  0x00bc9e24: jge    0x00bc9f12         ;*if_icmpge
                                        ; - sun.nio.cs.ext.EUC_TW_C_d_b_c1_f3_shortMap4$Encoder::&lt;clinit&gt;@150 (line 330)
  0x00bc9e2a: mov    0x14(%esp),%edi
  0x00bc9e2e: mov    0x10(%edi),%ecx    ; implicit exception: dispatches to 0x00bca2d9

 ...

Complete output here (line 569):
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/branches/j7_EUC_TW/log/C_d_b_c1_f3_shortMap4_PA_3.xml?rev=895&view=markup
REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
In my code I have following snippet:

                for (int code=page*PAGE_LENGTH, i=0; i<=maxCode; page++) {
                    for (; code<(page+1)*PAGE_LENGTH && i<=maxCode; code++, i++) { // TODO: HotSpot bug: "(page+1)*PAGE_LENGTH" should be reused instead of recalculated each loop
                        char c = chars.charAt(i);
                        assert code <= Character.MAX_VALUE;
                        if (c != UNMAPPABLE_DECODING)
                            if ((b2cIsSupp[i] & (1 << p)) == 0)
                                c2b[c2bIndex[c >> 8] + (c&0xff)] = (char)code;
                            else
                                c2bSupp[c2bSuppIndex[c >> 8] + (c&0xff)] = (char)code;
                    }
                    codeOffsets[page] = codeOffset;
                }

Complete source code (line 330):
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/branches/j7_EUC_TW/src/sun/nio/cs/ext/EUC_TW_C_d_b_c1_f3_shortMap4.java?rev=895&view=markup

Complete project:
https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/branches/j7_EUC_TW?rev=895

---------- END SOURCE ----------

Comments
EVALUATION It would be nice if 32bit x86 had more registers. Unfortunately we have to reuse registers otherwise we will get more spills on stack which will cause more performance regression then keeping value in register. And x*c+c is very fast (few cycles) on modern cpus.
11-10-2011