[pypy-svn] r44929 - in pypy/dist/pypy/translator/jvm: . src/pypy test

pdg at codespeak.net pdg at codespeak.net
Wed Jul 11 14:36:32 CEST 2007


Author: pdg
Date: Wed Jul 11 14:36:31 2007
New Revision: 44929

Modified:
   pypy/dist/pypy/translator/jvm/generator.py
   pypy/dist/pypy/translator/jvm/opcodes.py
   pypy/dist/pypy/translator/jvm/prebuiltnodes.py
   pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java
   pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java
   pypy/dist/pypy/translator/jvm/test/test_float.py
   pypy/dist/pypy/translator/jvm/test/test_int.py
Log:
translator/jvm - added overflow checking, long casting, new simple opcodes, and a new exception (pdg)

Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py	(original)
+++ pypy/dist/pypy/translator/jvm/generator.py	Wed Jul 11 14:36:31 2007
@@ -52,10 +52,11 @@
 class Opcode(object):
     def __init__(self, jvmstr):
         """
-        flags is a set of flags (see above) that describe opcode
+        flags is a set of flags (see above) that describe opcode #UPDATE
         jvmstr is the name for jasmin printouts
         """
         self.jvmstr = jvmstr
+        self.flags = None #Should flags be added to args?
 
     def __repr__(self):
         return "<Opcode %s:%x>" % (self.jvmstr, self.flags)
@@ -363,9 +364,26 @@
 DOUBLETOSTRINGD =       Method.s(jDoubleClass, 'toString', (jDouble,), jString)
 CHARTOSTRINGC =         Method.s(jCharClass, 'toString', (jChar,), jString)
 MATHIABS =              Method.s(jMath, 'abs', (jInt,), jInt)
+IABSOVF =               Method.s(jPyPy, 'abs_ovf', (jInt,), jInt)
 MATHLABS =              Method.s(jMath, 'abs', (jLong,), jLong)
+LABSOVF =               Method.s(jPyPy, 'abs_ovf', (jLong,), jLong)
 MATHDABS =              Method.s(jMath, 'abs', (jDouble,), jDouble)
+INEGOVF =               Method.s(jPyPy, 'negate_ovf', (jInt,), jInt)
+LNEGOVF =               Method.s(jPyPy, 'negate_ovf', (jInt,), jInt)
+IADDOVF =               Method.s(jPyPy, 'add_ovf', (jInt, jInt), jInt)
+LADDOVF =               Method.s(jPyPy, 'add_ovf', (jLong, jLong), jLong)
+ISUBOVF =               Method.s(jPyPy, 'sub_ovf', (jInt, jInt), jInt)
+LSUBOVF =               Method.s(jPyPy, 'sub_ovf', (jLong, jLong), jLong)
+IMULOVF =               Method.s(jPyPy, 'multiply_ovf', (jInt, jInt), jInt)
+LMULOVF =               Method.s(jPyPy, 'multiply_ovf', (jLong, jLong), jLong)
 MATHFLOOR =             Method.s(jMath, 'floor', (jDouble,), jDouble)
+IFLOORDIVOVF =          Method.s(jPyPy, 'floordiv_ovf', (jInt, jInt), jInt)
+LFLOORDIVOVF =          Method.s(jPyPy, 'floordiv_ovf', (jLong, jLong), jLong)
+IFLOORDIVZEROVF =       Method.s(jPyPy, 'floordiv_zer_ovf', (jInt, jInt), jInt)
+LFLOORDIVZEROVF =       Method.s(jPyPy, 'floordiv_zer_ovf', (jLong, jLong), jLong)
+IREMOVF =               Method.s(jPyPy, 'mod_ovf', (jInt, jInt), jInt)
+LREMOVF =               Method.s(jPyPy, 'mod_ovf', (jLong, jLong), jLong)
+MATHDPOW =              Method.s(jMath, 'pow', (jDouble, jDouble), jDouble)
 PRINTSTREAMPRINTSTR =   Method.v(jPrintStream, 'print', (jString,), jVoid)
 CLASSFORNAME =          Method.s(jClass, 'forName', (jString,), jClass)
 CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
@@ -375,7 +393,7 @@
 PYPYULONGCMP =          Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
 PYPYUINTTODOUBLE =      Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
 PYPYDOUBLETOUINT =      Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
-#PYPYDOUBLETOLONG =      Method.s(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
+PYPYDOUBLETOLONG =      Method.s(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
 PYPYLONGBITWISENEGATE = Method.s(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
 PYPYSTRTOINT =          Method.s(jPyPy, 'str_to_int', (jString,), jInt)
 PYPYSTRTOUINT =         Method.s(jPyPy, 'str_to_uint', (jString,), jInt)

Modified: pypy/dist/pypy/translator/jvm/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/opcodes.py	(original)
+++ pypy/dist/pypy/translator/jvm/opcodes.py	Wed Jul 11 14:36:31 2007
@@ -32,20 +32,8 @@
         _proc(op))]
 
 def _check_ovf(op):
-    # TODO
     return op
     
-def _check_unary_ovf(op):
-    # TODO  We should just use rlib's overflow dtection
-    # Assume LLONG_MIN = (- LLONG_MAX-1)
-#    if op.operand == LLONG_MIN:
-#        return [TranslateException(
-#            jvmtype.jArithmeticException,
-#            'throwOverflowError',
-#            _proc(op))]
-#    else:
-#        return op
-    return op
 
 # This table maps the opcodes to micro-ops for processing them.
 # It is post-processed by _proc.
@@ -96,9 +84,9 @@
 
     'int_is_true':              'not_equals_zero',
     'int_neg':                  jvmgen.INEG,
-    'int_neg_ovf':              None, # How to handle overflow?
+    'int_neg_ovf':              jvmgen.INEGOVF,
     'int_abs':                  'iabs',
-    'int_abs_ovf':              _check_ovf('iabs'),
+    'int_abs_ovf':              jvmgen.IABSOVF,
     'int_invert':               'bitwise_negate',
 
     'int_add':                  jvmgen.IADD,
@@ -118,11 +106,12 @@
     'int_lshift':               jvmgen.ISHL,
     'int_rshift':               jvmgen.ISHR,
     'int_xor':                  jvmgen.IXOR,
-    'int_add_ovf':              _check_ovf(jvmgen.IADD),
-    'int_sub_ovf':              _check_ovf(jvmgen.ISUB),
-    'int_mul_ovf':              _check_ovf(jvmgen.IMUL),
+    'int_add_ovf':              jvmgen.IADDOVF,
+    'int_sub_ovf':              jvmgen.ISUBOVF,
+    'int_mul_ovf':              jvmgen.IMULOVF,
     'int_floordiv_ovf':         jvmgen.IDIV, # these can't overflow!
-    'int_mod_ovf':              jvmgen.IREM,
+    'int_mod_zer':              _check_zer(jvmgen.IREM),
+    'int_mod_ovf':              jvmgen.IREMOVF,
     'int_lt_ovf':               'less_than',
     'int_le_ovf':               'less_equals',
     'int_eq_ovf':               'equals',
@@ -138,7 +127,7 @@
     'int_rshift_ovf':           jvmgen.ISHR, # these can't overflow!
     'int_xor_ovf':              jvmgen.IXOR,
     'int_floordiv_ovf_zer':     _check_zer(jvmgen.IDIV),
-    'int_mod_ovf_zer':          _check_zer(jvmgen.IREM),
+    'int_mod_ovf_zer':          _check_zer(jvmgen.IREMOVF),
 
     'uint_is_true':             'not_equals_zero',
     'uint_invert':              'bitwise_negate',
@@ -171,7 +160,8 @@
     'float_add':                jvmgen.DADD,
     'float_sub':                jvmgen.DSUB,
     'float_mul':                jvmgen.DMUL,
-    'float_truediv':            jvmgen.DDIV, 
+    'float_truediv':            jvmgen.DDIV,
+    'float_pow':                jvmgen.MATHDPOW,
     'float_lt':                 'dbl_less_than',     
     'float_le':                 'dbl_less_equals',   
     'float_eq':                 'dbl_equals',        
@@ -183,8 +173,9 @@
                                  jvmgen.LCONST_0,
                                  'long_not_equals'],
     'llong_neg':                jvmgen.LNEG,
-    'llong_neg_ovf':            _check_ovf(jvmgen.LNEG),
+    'llong_neg_ovf':            jvmgen.LNEGOVF,
     'llong_abs':                jvmgen.MATHLABS,
+    'llong_abs_ovf':            jvmgen.LABSOVF,
     'llong_invert':             jvmgen.PYPYLONGBITWISENEGATE,
 
     'llong_add':                jvmgen.LADD,
@@ -193,7 +184,9 @@
     'llong_div':                jvmgen.LDIV,
     'llong_truediv':            None, # TODO
     'llong_floordiv':           jvmgen.LDIV,
+    'llong_floordiv_zer':       _check_zer(jvmgen.LDIV),
     'llong_mod':                jvmgen.LREM,
+    'llong_mod_zer':            _check_zer(jvmgen.LREM),
     'llong_lt':                 'long_less_than',     
     'llong_le':                 'long_less_equals',   
     'llong_eq':                 'long_equals',        
@@ -205,6 +198,8 @@
     'llong_lshift':             jvmgen.LSHL,
     'llong_rshift':             jvmgen.LSHR,
     'llong_xor':                jvmgen.LXOR,
+    'llong_floordiv_ovf':       jvmgen.LDIV, # these can't overflow!
+    'llong_mod_ovf':            jvmgen.LREMOVF,
 
     'ullong_is_true':           [PushAllArgs,
                                  jvmgen.LCONST_0,
@@ -218,6 +213,7 @@
     'ullong_truediv':           None, # TODO
     'ullong_floordiv':          jvmgen.LDIV, # valid?
     'ullong_mod':               jvmgen.LREM, # valid?
+    'ullong_mod_zer':           _check_zer(jvmgen.LREM),
     'ullong_lt':                'ulong_less_than',     
     'ullong_le':                'ulong_less_equals',   
     'ullong_eq':                'ulong_equals',        
@@ -244,7 +240,7 @@
     'cast_uint_to_float':       jvmgen.PYPYUINTTODOUBLE, 
     'cast_float_to_int':        jvmgen.D2I,
     #'cast_float_to_longlong':   jvmgen.D2L, #PAUL
-    #'cast_float_to_longlong':   jvmgen.PYPYDOUBLETOLONG, #PAUL
+    'cast_float_to_longlong':   jvmgen.PYPYDOUBLETOLONG, #PAUL
     'cast_float_to_uint':       jvmgen.PYPYDOUBLETOUINT,
     'truncate_longlong_to_int': jvmgen.L2I,
     'cast_longlong_to_float':   jvmgen.L2D,
@@ -255,3 +251,4 @@
 for opc, val in _opcodes.items():
     opcodes[opc] = _proc(val)
 del _opcodes
+

Modified: pypy/dist/pypy/translator/jvm/prebuiltnodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/prebuiltnodes.py	(original)
+++ pypy/dist/pypy/translator/jvm/prebuiltnodes.py	Wed Jul 11 14:36:31 2007
@@ -8,6 +8,9 @@
 def throwIndexError():
     raise IndexError
 
+def throwOverflowError():
+    raise OverflowError
+
 # ___________________________________________________________________________
 
 def create_interlink_node(db):

Modified: pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java	(original)
+++ pypy/dist/pypy/translator/jvm/src/pypy/Interlink.java	Wed Jul 11 14:36:31 2007
@@ -12,4 +12,5 @@
 public interface Interlink {
     public void throwZeroDivisionError();
     public void throwIndexError();
-}
\ No newline at end of file
+    public void throwOverflowError();
+}

Modified: pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java	(original)
+++ pypy/dist/pypy/translator/jvm/src/pypy/PyPy.java	Wed Jul 11 14:36:31 2007
@@ -17,6 +17,12 @@
     
     public static Interlink interlink;
 
+    public static final long LONG_MAX = Long.MAX_VALUE;
+    public static final long LONG_MIN = Long.MIN_VALUE;
+    public static final int INT_MAX = Integer.MAX_VALUE;
+    public static final int INT_MIN = Integer.MIN_VALUE;
+
+
     /** 
      * Compares two unsigned integers (value1 and value2) and returns
      * a value greater than, equal to, or less than zero if value 1 is
@@ -116,6 +122,15 @@
         return (hiword << 16) + loword;
     }
 
+    public static long double_to_long(double value)
+    {
+        //if (value <= LONG_MAX)
+        //{
+            return (long)value;
+        //}
+        //TODO: Add some logic here, but I don't think we'll need it
+    }
+
     public static long long_bitwise_negate(long value) {
         return ~value;
     }
@@ -259,6 +274,202 @@
     }
 
     // ----------------------------------------------------------------------
+    // Checked Arithmetic - Overflow protection
+    public static int negate_ovf(int x) 
+    {
+        if (x == INT_MIN)
+        {
+            throwOverflowError();
+        }
+        return -x;
+    }
+
+    public static long negate_ovf(long x) 
+    {
+        if (x == LONG_MIN)
+        {
+            throwOverflowError();
+        }
+        return -x;
+    }
+    
+    public static int abs_ovf(int x) 
+    {
+        if (x == INT_MIN)
+        {
+            throwOverflowError();
+        }
+        return Math.abs(x);
+    }
+
+    public static long abs_ovf(long x) 
+    {
+        if (x == LONG_MIN)
+        {
+            throwOverflowError();
+        }
+        return Math.abs(x);
+    }
+
+    public static int add_ovf(int x, int y) 
+    {
+        int result = x+y;
+        if (!(((result^x) >=0) || ((result^y) >=0)))
+        {
+            throwOverflowError();
+        }
+        return result;
+    }
+
+    public static int subtract_ovf(int x, int y) 
+    {
+        int result = x-y;
+        if (!(((result^x) >=0) || ((result^(~y)) >=0)))
+        {
+            throwOverflowError();
+        }
+        return result;
+    }
+
+    private static boolean int_multiply(int x, int y)
+    {
+        double dprod = (double)x * (double)y;
+        long longprod = x * y;
+        double dlongprod = (double)longprod;
+        double diff = dlongprod - dprod;
+        double absdiff = Math.abs(diff);
+        double absprod = Math.abs(dprod);
+
+        if (dlongprod == dprod) //if diff == 0
+            return true;
+        else if (32.0 * absdiff <= absprod) //if we lost some information, are we at least 5 good bits?
+            return true;
+        else
+            return false;
+    }
+    public static int multiply_ovf(int x, int y) 
+    {
+        if (!(int_multiply(x, y)))
+        {
+            throwOverflowError();
+        }
+        return x * y;
+    }
+
+    public static long add_ovf(long x, long y) 
+    {
+        long result = x+y;
+        if (!(((result^x) >=0) || ((result^y) >=0)))
+        {
+            throwOverflowError();
+        }
+        return result;
+    }
+
+    public static long subtract_ovf(long x, long y) 
+    {
+        long result = x-y;
+        if (!(((result^x) >=0) || ((result^(~y)) >=0)))
+        {
+            throwOverflowError();
+        }
+        return result;
+    }
+
+    private static boolean long_multiply(long x, long y)
+    {
+        double dprod = (double)x * (double)y;
+        long longprod = x * y;
+        double dlongprod = (double)longprod;
+        double diff = dlongprod - dprod;
+        double absdiff = Math.abs(diff);
+        double absprod = Math.abs(dprod);
+
+        if (dlongprod == dprod) //if diff == 0
+            return true;
+        else if (32.0 * absdiff <= absprod) //if we lost some information, are we at least 5 good bits?
+            return true;
+        else
+            return false;
+    }
+    public static long multiply_ovf(long x, long y) 
+    {
+        //if (long_multiply(x, y))
+        //{
+        //    return x * y;
+        //}
+        //else
+        //    throwOverflowError();
+        if (!(long_multiply(x, y)))
+        {
+            throwOverflowError();
+        }
+        return x*y;
+        //else
+        //    throwOverflowError();
+    }
+
+    /* shifting */
+    /* Talk to Niko about how to get a workaround for PY_* functions in Java */
+
+    /* floor division */
+    public static int floordiv_ovf(int x, int y) 
+    {
+        if ((y == -1) && (x == INT_MIN))
+        {
+            throwOverflowError();
+        }
+        return x/y;
+    }
+
+    public static int floordiv_zer_ovf(int x, int y) 
+    {
+        if (y != 0)
+        {
+            return floordiv_ovf(x,y);
+        }
+        else
+            throw new ArithmeticException("Floor Division with integer by 0");
+    }
+
+    public static long floordiv_ovf(long x, long y) 
+    {
+        if ((y == -1) && (x == LONG_MIN))
+        {
+            throwOverflowError();
+        }
+        return x/y;
+    }
+
+    public static long floordiv_zer_ovf(long x, long y)
+    {
+        if (y != 0)
+        {
+            return floordiv_ovf(x,y);
+        }
+        else
+            throw new ArithmeticException("Floor Division with integer by 0");
+    }
+
+    public static int mod_ovf(int x, int y) 
+    {
+        if ((y == -1) && (x == INT_MIN))
+        {
+            throwOverflowError();
+        }
+        return x%y;
+    }
+
+    public static long mod_ovf(long x, long y) 
+    {
+        if ((y == -1) && (x == LONG_MIN))
+        {
+            throwOverflowError();
+        }
+        return x%y;
+    }
+
+    // ----------------------------------------------------------------------
     // String
 
     public static String ll_strconcat(String str1, String str2) {
@@ -419,7 +630,7 @@
     // Helpers
     
     public static byte[] string2bytes(String s) {
-    	return s.getBytes();
+        return s.getBytes();
     }
 
     public static void append(StringBuilder sb, String s) {
@@ -438,7 +649,7 @@
     // OOString support
     
     public static String oostring(int n, int base_) {
-    	// XXX needs special case for unsigned ints
+        // XXX needs special case for unsigned ints
         if (base_ == -1)
             base_ = 10;
         if (n < 0 && base_ != 10)
@@ -598,6 +809,10 @@
         interlink.throwIndexError();
     }
 
+    public static void throwOverflowError() {
+        interlink.throwOverflowError();
+    }
+    
     // ----------------------------------------------------------------------
     // Self Test
 

Modified: pypy/dist/pypy/translator/jvm/test/test_float.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_float.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/test_float.py	Wed Jul 11 14:36:31 2007
@@ -17,19 +17,19 @@
 #            expected = fn(i)
 #            res = self.interpret(fn, [i])
 #            assert res == expected
-            
+    
+    #Works, answer is correct, but not of type r_longlong.
     def test_longlong_conversion(self):
         py.test.skip("JVM backend unknown opcode cast_float_to_longlong")
-        
-    def test_pow(self):
-        py.test.skip("JVM backend unknown opcode float_pow")
-        
+                
     def test_float_constant_conversions(self):
         py.test.skip("JVM backend lacks appropriate percision; 42.000000614400001 == 42.0")
-        
+    
+    #The JVM doesn't even have uints
     def test_from_r_uint(self):
         py.test.skip("JVM backend lacks appropriate percision")
     
+    #The jvm doesn't even have uints
     def test_to_r_uint(self):
         py.test.skip("JVM backend lacks appropriate percision")
-        
\ No newline at end of file
+        

Modified: pypy/dist/pypy/translator/jvm/test/test_int.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_int.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/test_int.py	Wed Jul 11 14:36:31 2007
@@ -18,11 +18,9 @@
 
     def test_rarithmetic(self):
         pass # does this make more sense in jvm
-        
+    
+    #There is an issue that it doesn't correctly call long code over int code
     def test_neg_abs_ovf(self):
         py.test.skip("Unaware how to handle overflow")
-        
-    def test_protected_div_mod(self):
-        py.test.skip("fails because of unusual exception propagation")
 
     div_mod_iteration_count = 20



More information about the Pypy-commit mailing list