[pypy-svn] pypy jit-short_from_state: hg merge post-release-1.5
hakanardo
commits-noreply at bitbucket.org
Mon Apr 25 19:43:52 CEST 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-short_from_state
Changeset: r43607:4b434eb43229
Date: 2011-04-25 16:44 +0200
http://bitbucket.org/pypy/pypy/changeset/4b434eb43229/
Log: hg merge post-release-1.5
diff --git a/pypy/translator/c/node.py b/pypy/translator/c/node.py
--- a/pypy/translator/c/node.py
+++ b/pypy/translator/c/node.py
@@ -11,7 +11,7 @@
from pypy.translator.c.support import c_char_array_constant, barebonearray
from pypy.translator.c.primitive import PrimitiveType, name_signed
from pypy.rlib import exports
-from pypy.rlib.rfloat import isinf, isnan
+from pypy.rlib.rfloat import isfinite
from pypy.rlib.rstackovf import _StackOverflow
from pypy.translator.c import extfunc
from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -793,7 +793,7 @@
node = db.getcontainernode(value._obj)
expr = 'NULL /*%s*/' % node.name
node.where_to_copy_me.append('&%s' % access_expr)
- elif typeOf(value) == Float and (isinf(value) or isnan(value)):
+ elif typeOf(value) == Float and not isfinite(value):
db.late_initializations.append(('%s' % access_expr, db.get(value)))
expr = '0.0 /* patched later by %sinfinity */' % (
'-+'[value > 0])
diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py
--- a/pypy/rlib/rfloat.py
+++ b/pypy/rlib/rfloat.py
@@ -158,12 +158,12 @@
return _formatd(x, code, precision, flags)
def double_to_string(value, tp, precision, flags):
- if isnan(value):
- special = DIST_NAN
+ if isfinite(value):
+ special = DIST_FINITE
elif isinf(value):
special = DIST_INFINITY
- else:
- special = DIST_FINITE
+ else: #isnan(value):
+ special = DIST_NAN
result = formatd(value, tp, precision, flags)
return result, special
@@ -344,7 +344,7 @@
def asinh(x):
"NOT_RPYTHON"
absx = abs(x)
- if isnan(x) or isinf(x):
+ if not isfinite(x):
return x
if absx < _2_to_m28:
return x
@@ -405,3 +405,6 @@
r = math.floor(absx)
return copysign(r, x)
+def isfinite(x):
+ "NOT_RPYTHON"
+ return not isinf(x) and not isnan(x)
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2223,6 +2223,45 @@
return sa
assert self.meta_interp(f, [10]) == f(10)
+ def test_bug688_multiple_immutable_fields(self):
+ myjitdriver = JitDriver(greens=[], reds=['counter','context'])
+
+ class Tag:
+ pass
+ class InnerContext():
+ _immutable_fields_ = ['variables','local_names']
+ def __init__(self, variables):
+ self.variables = variables
+ self.local_names = [0]
+
+ def store(self):
+ self.local_names[0] = 1
+
+ def retrieve(self):
+ variables = hint(self.variables, promote=True)
+ result = self.local_names[0]
+ if result == 0:
+ return -1
+ else:
+ return -1
+ def build():
+ context = InnerContext(Tag())
+
+ context.store()
+
+ counter = 0
+ while True:
+ myjitdriver.jit_merge_point(context=context, counter = counter)
+ context.retrieve()
+ context.retrieve()
+
+ counter += 1
+ if counter > 10:
+ return 7
+ assert self.meta_interp(build, []) == 7
+ self.check_loops(getfield_gc_pure=0)
+ self.check_loops(getfield_gc_pure=2, everywhere=True)
+
class TestOOtype(BasicTests, OOJitMixin):
def test_oohash(self):
diff --git a/pypy/rpython/extfuncregistry.py b/pypy/rpython/extfuncregistry.py
--- a/pypy/rpython/extfuncregistry.py
+++ b/pypy/rpython/extfuncregistry.py
@@ -36,6 +36,9 @@
register_external(rfloat.isnan, [float], bool,
export_name="ll_math.ll_math_isnan", sandboxsafe=True,
llimpl=ll_math.ll_math_isnan)
+register_external(rfloat.isfinite, [float], bool,
+ export_name="ll_math.ll_math_isfinite", sandboxsafe=True,
+ llimpl=ll_math.ll_math_isfinite)
register_external(rfloat.copysign, [float, float], float,
export_name="ll_math.ll_math_copysign", sandboxsafe=True,
llimpl=ll_math.ll_math_copysign)
diff --git a/pypy/translator/c/test/test_genc.py b/pypy/translator/c/test/test_genc.py
--- a/pypy/translator/c/test/test_genc.py
+++ b/pypy/translator/c/test/test_genc.py
@@ -273,7 +273,7 @@
assert res == 1.5
def test_nan_and_special_values():
- from pypy.rlib.rfloat import isnan, isinf, copysign
+ from pypy.rlib.rfloat import isnan, isinf, isfinite, copysign
inf = 1e300 * 1e300
assert isinf(inf)
nan = inf/inf
@@ -283,6 +283,7 @@
(inf, lambda x: isinf(x) and x > 0.0),
(-inf, lambda x: isinf(x) and x < 0.0),
(nan, isnan),
+ (42.0, isfinite),
(0.0, lambda x: not x and copysign(1., x) == 1.),
(-0.0, lambda x: not x and copysign(1., x) == -1.),
]:
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -1,7 +1,7 @@
from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong
from pypy.rlib.rarithmetic import ovfcheck, r_longlong, widen
from pypy.rlib.rarithmetic import most_neg_value_of_same_type
-from pypy.rlib.rfloat import isinf, isnan
+from pypy.rlib.rfloat import isfinite
from pypy.rlib.debug import make_sure_not_resized, check_regular_int
from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.rlib import jit
@@ -173,9 +173,15 @@
def fromfloat(dval):
""" Create a new bigint object from a float """
# This function is not marked as pure because it can raise
+ if isfinite(dval):
+ return rbigint._fromfloat_finite(dval)
+ else:
+ raise OverflowError
+
+ @staticmethod
+ @jit.purefunction
+ def _fromfloat_finite(dval):
sign = 1
- if isinf(dval) or isnan(dval):
- raise OverflowError
if dval < 0.0:
sign = -1
dval = -dval
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -72,7 +72,8 @@
def find_rewritable_bool(self, op, args):
try:
oldopnum = opboolinvers[op.getopnum()]
- targs = [args[0], args[1], ConstInt(oldopnum)]
+ targs = self.optimizer.make_args_key(ResOperation(oldopnum, [args[0], args[1]],
+ None))
if self.try_boolinvers(op, targs):
return True
except KeyError:
@@ -80,7 +81,8 @@
try:
oldopnum = opboolreflex[op.getopnum()] # FIXME: add INT_ADD, INT_MUL
- targs = [args[1], args[0], ConstInt(oldopnum)]
+ targs = self.optimizer.make_args_key(ResOperation(oldopnum, [args[1], args[0]],
+ None))
oldop = self.optimizer.pure_operations.get(targs, None)
if oldop is not None and oldop.getdescr() is op.getdescr():
self.make_equal_to(op.result, self.getvalue(oldop.result))
@@ -90,7 +92,8 @@
try:
oldopnum = opboolinvers[opboolreflex[op.getopnum()]]
- targs = [args[1], args[0], ConstInt(oldopnum)]
+ targs = self.optimizer.make_args_key(ResOperation(oldopnum, [args[1], args[0]],
+ None))
if self.try_boolinvers(op, targs):
return True
except KeyError:
diff --git a/pypy/jit/metainterp/optimizeutil.py b/pypy/jit/metainterp/optimizeutil.py
--- a/pypy/jit/metainterp/optimizeutil.py
+++ b/pypy/jit/metainterp/optimizeutil.py
@@ -99,7 +99,9 @@
make_sure_not_resized(args)
res = 0x345678
for arg in args:
- if isinstance(arg, history.Const):
+ if arg is None:
+ y = 17
+ elif isinstance(arg, history.Const):
y = arg._get_hash_()
else:
y = compute_identity_hash(arg)
diff --git a/pypy/rpython/test/test_rfloat.py b/pypy/rpython/test/test_rfloat.py
--- a/pypy/rpython/test/test_rfloat.py
+++ b/pypy/rpython/test/test_rfloat.py
@@ -157,9 +157,9 @@
self.interpret(fn, [1.0, 2.0, 3.0])
def test_copysign(self):
- import math
+ from pypy.rlib import rfloat
def fn(x, y):
- return math.copysign(x, y)
+ return rfloat.copysign(x, y)
assert self.interpret(fn, [42, -1]) == -42
assert self.interpret(fn, [42, -0.0]) == -42
assert self.interpret(fn, [42, 0.0]) == 42
@@ -172,21 +172,42 @@
assert self.interpret(fn, [0]) == 42.3
def test_isnan(self):
- import math
- def fn(x):
- inf = x * x
- nan = inf / inf
- return math.isnan(nan)
- assert self.interpret(fn, [1e200])
+ from pypy.rlib import rfloat
+ def fn(x, y):
+ n1 = x * x
+ n2 = y * y * y
+ return rfloat.isnan(n1 / n2)
+ assert self.interpret(fn, [1e200, 1e200]) # nan
+ assert not self.interpret(fn, [1e200, 1.0]) # +inf
+ assert not self.interpret(fn, [1e200, -1.0]) # -inf
+ assert not self.interpret(fn, [42.5, 2.3]) # +finite
+ assert not self.interpret(fn, [42.5, -2.3]) # -finite
def test_isinf(self):
- import math
- def fn(x):
- inf = x * x
- return math.isinf(inf)
- assert self.interpret(fn, [1e200])
+ from pypy.rlib import rfloat
+ def fn(x, y):
+ n1 = x * x
+ n2 = y * y * y
+ return rfloat.isinf(n1 / n2)
+ assert self.interpret(fn, [1e200, 1.0]) # +inf
+ assert self.interpret(fn, [1e200, -1.0]) # -inf
+ assert not self.interpret(fn, [1e200, 1e200]) # nan
+ assert not self.interpret(fn, [42.5, 2.3]) # +finite
+ assert not self.interpret(fn, [42.5, -2.3]) # -finite
-
+ def test_isfinite(self):
+ from pypy.rlib import rfloat
+ def fn(x, y):
+ n1 = x * x
+ n2 = y * y * y
+ return rfloat.isfinite(n1 / n2)
+ assert self.interpret(fn, [42.5, 2.3]) # +finite
+ assert self.interpret(fn, [42.5, -2.3]) # -finite
+ assert not self.interpret(fn, [1e200, 1.0]) # +inf
+ assert not self.interpret(fn, [1e200, -1.0]) # -inf
+ assert not self.interpret(fn, [1e200, 1e200]) # nan
+
+
class TestLLtype(BaseTestRfloat, LLRtypeMixin):
def test_hash(self):
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -269,7 +269,7 @@
self.optimizer.pure_operations[key] = op
def has_pure_result(self, opnum, args, descr):
- op = ResOperation(opnum, args, None)
+ op = ResOperation(opnum, args, None, descr)
key = self.optimizer.make_args_key(op)
op = self.optimizer.pure_operations.get(key, None)
if op is None:
@@ -571,7 +571,7 @@
def make_args_key(self, op):
n = op.numargs()
- args = [None] * (n + 1)
+ args = [None] * (n + 2)
for i in range(n):
arg = op.getarg(i)
try:
@@ -582,6 +582,7 @@
arg = value.get_key_box()
args[i] = arg
args[n] = ConstInt(op.getopnum())
+ args[n+1] = op.getdescr()
return args
def optimize_default(self, op):
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -219,6 +219,7 @@
same before and after translation, except for RPython instances on the
lltypesystem.
"""
+ assert x is not None
result = object.__hash__(x)
try:
x.__dict__['__precomputed_identity_hash'] = result
@@ -267,14 +268,15 @@
In RPython, floats cannot be used with ints in dicts, anyway.
"""
from pypy.rlib.rarithmetic import intmask
- from pypy.rlib.rfloat import isinf, isnan
- if isinf(f):
- if f < 0.0:
- return -271828
- else:
- return 314159
- elif isnan(f):
- return 0
+ from pypy.rlib.rfloat import isfinite, isinf
+ if not isfinite(f):
+ if isinf(f):
+ if f < 0.0:
+ return -271828
+ else:
+ return 314159
+ else: #isnan(f):
+ return 0
v, expo = math.frexp(f)
v *= TAKE_NEXT
hipart = int(v)
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -10,7 +10,7 @@
from pypy.objspace.std.longobject import W_LongObject
from pypy.rlib.rarithmetic import ovfcheck_float_to_int, intmask, LONG_BIT
from pypy.rlib.rfloat import (
- isinf, isnan, INFINITY, NAN, copysign, formatd,
+ isinf, isnan, isfinite, INFINITY, NAN, copysign, formatd,
DTSF_ADD_DOT_0, DTSF_STR_PRECISION)
from pypy.rlib.rbigint import rbigint
from pypy.rlib.objectmodel import we_are_translated
@@ -102,7 +102,7 @@
def float_hex__Float(space, w_float):
value = w_float.floatval
- if isinf(value) or isnan(value):
+ if not isfinite(value):
return str__Float(space, w_float)
if value == 0.0:
if copysign(1., value) == -1.:
@@ -136,15 +136,15 @@
def float2string(space, w_float, code, precision):
x = w_float.floatval
# we special-case explicitly inf and nan here
- if isinf(x):
+ if isfinite(x):
+ s = formatd(x, code, precision, DTSF_ADD_DOT_0)
+ elif isinf(x):
if x > 0.0:
s = "inf"
else:
s = "-inf"
- elif isnan(x):
+ else: # isnan(x):
s = "nan"
- else:
- s = formatd(x, code, precision, DTSF_ADD_DOT_0)
return space.wrap(s)
def repr__Float(space, w_float):
@@ -179,7 +179,7 @@
if opname == 'eq' or opname == 'ne':
def do_compare_bigint(f1, b2):
"""f1 is a float. b2 is a bigint."""
- if isinf(f1) or isnan(f1) or math.floor(f1) != f1:
+ if not isfinite(f1) or math.floor(f1) != f1:
return opname == 'ne'
b1 = rbigint.fromfloat(f1)
res = b1.eq(b2)
@@ -189,7 +189,7 @@
else:
def do_compare_bigint(f1, b2):
"""f1 is a float. b2 is a bigint."""
- if isinf(f1) or isnan(f1):
+ if not isfinite(f1):
return op(f1, 0.0)
if opname == 'gt' or opname == 'le':
# 'float > long' <==> 'ceil(float) > long'
@@ -457,8 +457,6 @@
if x == 0.0:
if y < 0.0:
- if isinf(y):
- return space.wrap(INFINITY)
raise OperationError(space.w_ZeroDivisionError,
space.wrap("0.0 cannot be raised to "
"a negative power"))
diff --git a/pypy/rpython/lltypesystem/module/test/test_ll_math.py b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
--- a/pypy/rpython/lltypesystem/module/test/test_ll_math.py
+++ b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
@@ -22,11 +22,60 @@
assert ll_math.ll_math_isnan(nan)
assert not ll_math.ll_math_isnan(inf)
+ def test_isfinite(self):
+ inf = 1e200 * 1e200
+ nan = inf / inf
+ assert ll_math.ll_math_isfinite(0.0)
+ assert ll_math.ll_math_isfinite(-42.0)
+ assert not ll_math.ll_math_isfinite(nan)
+ assert not ll_math.ll_math_isnan(inf)
+ assert not ll_math.ll_math_isnan(-inf)
+
+ def test_compiled_isnan(self):
+ def f(x, y):
+ n1 = normalize(x * x)
+ n2 = normalize(y * y * y)
+ return ll_math.ll_math_isnan(n1 / n2)
+ f = compile(f, [float, float], backendopt=False)
+ assert f(1e200, 1e200) # nan
+ assert not f(1e200, 1.0) # +inf
+ assert not f(1e200, -1.0) # -inf
+ assert not f(42.5, 2.3) # +finite
+ assert not f(42.5, -2.3) # -finite
+
def test_compiled_isinf(self):
- def f(x):
- return ll_math.ll_math_isinf(1. / x)
- f = compile(f, [float], backendopt=False)
- assert f(5.5e-309)
+ def f(x, y):
+ n1 = normalize(x * x)
+ n2 = normalize(y * y * y)
+ return ll_math.ll_math_isinf(n1 / n2)
+ f = compile(f, [float, float], backendopt=False)
+ assert f(1e200, 1.0) # +inf
+ assert f(1e200, -1.0) # -inf
+ assert not f(1e200, 1e200) # nan
+ assert not f(42.5, 2.3) # +finite
+ assert not f(42.5, -2.3) # -finite
+
+ def test_compiled_isfinite(self):
+ def f(x, y):
+ n1 = normalize(x * x)
+ n2 = normalize(y * y * y)
+ return ll_math.ll_math_isfinite(n1 / n2)
+ f = compile(f, [float, float], backendopt=False)
+ assert f(42.5, 2.3) # +finite
+ assert f(42.5, -2.3) # -finite
+ assert not f(1e200, 1.0) # +inf
+ assert not f(1e200, -1.0) # -inf
+ assert not f(1e200, 1e200) # nan
+
+
+from pypy.rpython.lltypesystem import lltype
+_A = lltype.GcArray(lltype.Float)
+def normalize(x):
+ # workaround: force the C compiler to cast to a double
+ a = lltype.malloc(_A, 1)
+ a[0] = x
+ import time; time.time()
+ return a[0]
def make_test_case((fnname, args, expected), dict):
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -8,7 +8,7 @@
from pypy.tool.autopath import pypydir
from pypy.rlib import jit, rposix
from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN
+from pypy.rlib.rfloat import isinf, isnan, isfinite, INFINITY, NAN
if sys.platform == "win32":
eci = ExternalCompilationInfo()
@@ -91,14 +91,20 @@
# Custom implementations
def ll_math_isnan(y):
- # By not calling into the extenal function the JIT can inline this. Floats
- # are awesome.
+ # By not calling into the external function the JIT can inline this.
+ # Floats are awesome.
return y != y
def ll_math_isinf(y):
# Use a bitwise OR so the JIT doesn't produce 2 different guards.
return (y == INFINITY) | (y == -INFINITY)
+def ll_math_isfinite(y):
+ # Use a custom hack that is reasonably well-suited to the JIT.
+ # Floats are awesome (bis).
+ z = 0.0 * y
+ return z == z # i.e.: z is not a NaN
+
ll_math_floor = math_floor
diff --git a/pypy/rlib/rstruct/ieee.py b/pypy/rlib/rstruct/ieee.py
--- a/pypy/rlib/rstruct/ieee.py
+++ b/pypy/rlib/rstruct/ieee.py
@@ -87,12 +87,13 @@
raise ValueError("invalid size value")
sign = rfloat.copysign(1.0, x) < 0.0
- if rfloat.isinf(x):
- mant = r_ulonglong(0)
- exp = MAX_EXP - MIN_EXP + 2
- elif rfloat.isnan(x):
- mant = r_ulonglong(1) << (MANT_DIG-2) # other values possible
- exp = MAX_EXP - MIN_EXP + 2
+ if not rfloat.isfinite(x):
+ if rfloat.isinf(x):
+ mant = r_ulonglong(0)
+ exp = MAX_EXP - MIN_EXP + 2
+ else: # rfloat.isnan(x):
+ mant = r_ulonglong(1) << (MANT_DIG-2) # other values possible
+ exp = MAX_EXP - MIN_EXP + 2
elif x == 0.0:
mant = r_ulonglong(0)
exp = 0
More information about the Pypy-commit
mailing list