JDK-6442508 : Casting yields wrong results
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-06-23
  • Updated: 2010-04-02
  • Resolved: 2006-07-11
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 6
6 b91Fixed
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
any 1.6beta client VM

FULL OS VERSION :
WindowsXP ver 2002 SP2

A DESCRIPTION OF THE PROBLEM :
I am working on a Sega Genesis Emulator and after seeing it fail on any 1.6beta client VM, i made some tests and found the first point, where something is going wrong. I use the following code to sign extend 16bit values in my CPU emulator:

for example:
int EffectiveAddress  =  ((short)(memory.fetchOpWord(PC)&0xFFFF));

At a certain time fetchOpWord returns 0xF62A, for example. In any VM except the 1.6client this leads to EffectiveAddress = 0xFFFFF62A, while in the 1.6clients it becomes EffectiveAddress = 0xF62A.
So it doesnt get sign extended.
This always happens at this point and by the behavior i can see during emulation, i am sure the same happens in other locations as well.

It does not happen using the -Xint option, nor in the server VM.

I suspect the reason is "&0xFFFF" gets executed AFTER the cast, because leaving it out leads to the correct result.


THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: No

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected:
 ((short)(0xF000 & 0xFFFF)) = 0xFFFFF000;

Actual:
 ((short)(0xF000 & 0xFFFF)) = 0xF000;
REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
    void test(){
        int i, ea;
        for(i=0; i<=0xFFFF; i++){
            ea = ((short)(i&0xFFFF));
            System.out.println( Integer.toHexString(i) + " : " + Integer.toHexString(ea) );
        }
    }
---------- END SOURCE ----------

Comments
SUGGESTED FIX http://analemma.sfbay.sun.com/net/prt-archiver.sfbay/data/archived_workspaces/main/c2_baseline/2006/20060626153903.never.sux/workspace/webrevs/webrev-2006.06.26/index.html
27-06-2006

EVALUATION The i2s and i2c cases are swapped in one of the identity tranformations. When anding with a mask that doesn't include the sign bit the sign extending conversions can be elided. Unfortunately the i2s case was allowing the sign bit to get involved so we ended skipping the sign extension when we shouldn't have.
23-06-2006

SUGGESTED FIX *** /tmp/geta26677 Thu Jun 22 18:09:26 2006 --- c1_Canonicalizer.cpp Thu Jun 22 17:19:51 2006 *************** *** 483,490 **** jint mask = op2->y()->type()->as_IntConstant()->value(); switch (x->op()) { case Bytecodes::_i2b: safebits = 0x7f; break; ! case Bytecodes::_i2s: safebits = 0xffff; break; ! case Bytecodes::_i2c: safebits = 0x7fff; break; } if (safebits && (mask & ~safebits) == 0) { set_canonical(x->value()); --- 483,490 ---- jint mask = op2->y()->type()->as_IntConstant()->value(); switch (x->op()) { case Bytecodes::_i2b: safebits = 0x7f; break; ! case Bytecodes::_i2s: safebits = 0x7fff; break; ! case Bytecodes::_i2c: safebits = 0xffff; break; } if (safebits && (mask & ~safebits) == 0) { set_canonical(x->value());
23-06-2006