[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