Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4787943
Votes 0
Synopsis REGRESSION: Long shift produces incorrect results with -client
Category hotspot:compiler1
Reported Against 1.4.1 , 1.4.0_03
Release Fixed 1.4.0_04, 1.4.1_03(Bug ID:2061997) , 1.4.2(mantis-beta) (Bug ID:2061998)
State 10-Fix Delivered, bug
Priority: 3-Medium
Related Bugs
Submit Date 03-DEC-2002
Description




FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)


FULL OPERATING SYSTEM VERSION :
SunOS lxor 5.8 Generic_108528-17 sun4u sparc SUNW,Ultra-5_10

A DESCRIPTION OF THE PROBLEM :
Shifting a long by a dynamically calculated integer value
produces the wrong answer when run with the java -client
command line option.

REGRESSION.  Last worked in version 1.3

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. javac LongCrash.java
2. java -client LongCrash
3.

EXPECTED VERSUS ACTUAL BEHAVIOR :
When the program works there should be no output (java
-server).

When the program fails (java -client), the output should be
similar to:

ERROR: sent: 80000000000003d7 got: ffffff00000003d7

The value at which the program fails does change, but it
consistently fails; I'm guessing it depends on when a
dynamic optimization occurs for the sizeAdj() method.  In my
environment the failure occurs almost immediately after
running the program.  I ran the working (-server) version
over a weekend and experienced no failures.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
ERROR: sent: 80000000000003d7 got: ffffff00000003d7

This error is printed from within the test program when the arithmetic failure
is detected.  The expected is equal to the sent value.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * This example detects errant arithmetic in the sizeAdj() method.
 * The error occurs on Solaris Sparc JVM 1.4.0 and 1.4.1_01 when
 * running with the java -client command line argument.  This program
 * works as expected on 1.3.1_01.  The J2SE_Solaris_8_Recommended
 * patches were all installed.  This program also works on the 1.4
 * versions when run with the -server command line argument.
 *
 * The failure occurs in the long shifts in the sizeAdj() method.  The
 * error occurs for numbers sligthly larger than MIN_LONG and doesn't
 * always fail on the same number which might be related to how long
 * the program runs before the sizeAdj() method is dynamically
 * optimized.  The error is detected by checking the result of the
 * sizeAdj() method against the input value; they should be identical
 * since the shifts performed in sizeAdj() should always be by 0 since
 * the width argument is set to a constant 64 when sizeAdj() is
 * called.
 *
 * Tinkering with the program has showed that the error doesn't occur
 * when run with -server or if the sizeAdj() local variable "shiftMag"
 * is declared as long (causing the shift amount calculation to
 * produce a long instead of the integer value as coded) or if the
 * "shiftMag" variable declaration is left as an integer but moved
 * after the "ret" variable declaration.  The program will also work
 * if the "shiftMag" variable is removed and replaced with its only
 * value of the "width" variable, or if the shift amount is forced to
 * be a long value by using "64L" in the amount calculation.
 *
 * To reproduce the error:
 *
 * 1. javac LongCrash.java
 * 2. java -client LongCrash
 *
 * The output will be similar to:
 *
 * ERROR: sent: 80000000000003d7 got: ffffff00000003d7
 *
 */
public class LongCrash
{
    public static void main(String[] args)
    {
        while(true)
        {
            for(long i=0x7ffffffffffffff0L; i != 0x80000000000f0000L; i++)
            {
                long answer = 0L;
                
                if((answer = sizeAdj(i,64)) != i)
                {
                    System.out.println("ERROR: sent: " +
                                       Long.toHexString(i) + " got: " +
                                       Long.toHexString(answer));
                    System.exit(1);
                }
            }
        }
    }
    
    private static long sizeAdj (long value, int width)
    {
        // if this variable declaration moves after the next one it
        // works
        // if this variable declaration stays here but is made long it works
        int shiftMag = width;
        
        long ret = value;

        // if the shiftMag variable is replaced with width it works
        // if the constant 64 is replaced with 64L it works
        ret <<= (64 - shiftMag);
        ret >>= (64 - shiftMag);

        return ret;
    }
}

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

CUSTOMER WORKAROUND :
1. Use -server java command line option
2. Force long shifts to be by long types, not integers 
3. Allocate smaller primitive type local variables after long types.

Release Regression From : 1.3.1_06
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 178368) 
======================================================================
Work Around
N/A
Evaluation
Long shifts destroy the count register but the peephole optimizer didn't understand this and so tried to substitute a better register.  The fix is to propagate the destroyed flag through and check it in the LIROptimizer.  The bug has existed since 1.4.0.
  xxxxx@xxxxx   2002-12-03

i've added an alternative fix that would be acceptable on earlier releases.
  xxxxx@xxxxx   2003-01-29
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang