[pypy-svn] pypy default: hg merge post-release-1.5
arigo
commits-noreply at bitbucket.org
Sat Apr 30 18:05:09 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r43817:ea4e1fd5b529
Date: 2011-04-30 18:03 +0200
http://bitbucket.org/pypy/pypy/changeset/ea4e1fd5b529/
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/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/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/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -617,7 +617,7 @@
if w_obj.is_cpytype():
Py_DecRef(space, pto.c_tp_dict)
- w_dict = space.newdict(from_strdict_shared=w_obj.dict_w)
+ w_dict = w_obj.getdict(space)
pto.c_tp_dict = make_ref(space, w_dict)
@cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, error=CANNOT_FAIL)
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
@@ -2118,6 +2118,45 @@
res = self.interp_operations(f, [])
assert res
+ 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/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -34,13 +34,7 @@
@staticmethod
def allocate_and_init_instance(space, w_type=None, module=False,
instance=False, classofinstance=None,
- from_strdict_shared=None, strdict=False):
- if from_strdict_shared is not None:
- assert w_type is None
- assert not module and not instance and classofinstance is None
- w_self = StrDictImplementation(space)
- w_self.content = from_strdict_shared
- return w_self
+ strdict=False):
if space.config.objspace.std.withcelldict and module:
from pypy.objspace.std.celldict import ModuleDictImplementation
assert w_type is None
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1086,6 +1086,50 @@
--TICK--
jump(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, i28, i25, i19, i13, p14, p15, descr=<Loop0>)
""")
+
+ def test_mutate_class(self):
+ def fn(n):
+ class A(object):
+ count = 1
+ def __init__(self, a):
+ self.a = a
+ def f(self):
+ return self.count
+ i = 0
+ a = A(1)
+ while i < n:
+ A.count += 1 # ID: mutate
+ i = a.f() # ID: meth1
+ return i
+ #
+ log = self.run(fn, [1000], threshold=10)
+ assert log.result == 1000
+ #
+ # first, we test the entry bridge
+ # -------------------------------
+ entry_bridge, = log.loops_by_filename(self.filepath, is_entry_bridge=True)
+ ops = entry_bridge.ops_by_id('mutate', opcode='LOAD_ATTR')
+ assert log.opnames(ops) == ['guard_value', 'getfield_gc', 'guard_value',
+ 'getfield_gc', 'guard_nonnull_class']
+ # the STORE_ATTR is folded away
+ assert list(entry_bridge.ops_by_id('meth1', opcode='STORE_ATTR')) == []
+ #
+ # then, the actual loop
+ # ----------------------
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match("""
+ i8 = getfield_gc_pure(p5, descr=<SignedFieldDescr .*W_IntObject.inst_intval.*>)
+ i9 = int_lt(i8, i7)
+ guard_true(i9, descr=.*)
+ i11 = int_add(i8, 1)
+ i12 = force_token()
+ --TICK--
+ p20 = new_with_vtable(ConstClass(W_IntObject))
+ setfield_gc(p20, i11, descr=<SignedFieldDescr.*W_IntObject.inst_intval .*>)
+ setfield_gc(ConstPtr(ptr21), p20, descr=<GcPtrFieldDescr .*TypeCell.inst_w_value .*>)
+ jump(p0, p1, p2, p3, p4, p20, p6, i7, descr=<Loop.>)
+ """)
+
def test_intbound_simple(self):
"""
diff --git a/lib-python/modified-2.7/test/test_descr.py b/lib-python/modified-2.7/test/test_descr.py
--- a/lib-python/modified-2.7/test/test_descr.py
+++ b/lib-python/modified-2.7/test/test_descr.py
@@ -3190,7 +3190,8 @@
except TypeError:
pass
else:
- self.fail("%r's __dict__ can be modified" % cls)
+ if test_support.check_impl_detail(pypy=False):
+ self.fail("%r's __dict__ can be modified" % cls)
# Modules also disallow __dict__ assignment
class Module1(types.ModuleType, Base):
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
@@ -220,7 +220,7 @@
self.optimizer.pure_operations[self.optimizer.make_args_key(op)] = 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:
@@ -482,7 +482,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:
@@ -493,6 +493,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/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
@@ -101,14 +101,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/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -54,7 +54,6 @@
from pypy.objspace.std.slicetype import slice_typedef
from pypy.objspace.std.longtype import long_typedef
from pypy.objspace.std.unicodetype import unicode_typedef
- from pypy.objspace.std.dictproxytype import dictproxy_typedef
from pypy.objspace.std.nonetype import none_typedef
from pypy.objspace.std.itertype import iter_typedef
self.pythontypes = [value for key, value in result.__dict__.items()
@@ -123,7 +122,6 @@
iterobject.W_FastTupleIterObject: [],
iterobject.W_ReverseSeqIterObject: [],
unicodeobject.W_UnicodeObject: [],
- dictproxyobject.W_DictProxyObject: [],
dictmultiobject.W_DictViewKeysObject: [],
dictmultiobject.W_DictViewItemsObject: [],
dictmultiobject.W_DictViewValuesObject: [],
diff --git a/pypy/objspace/std/test/test_dictproxy.py b/pypy/objspace/std/test/test_dictproxy.py
--- a/pypy/objspace/std/test/test_dictproxy.py
+++ b/pypy/objspace/std/test/test_dictproxy.py
@@ -1,21 +1,26 @@
-
+from pypy.conftest import gettestobjspace
class AppTestUserObject:
def test_dictproxy(self):
class NotEmpty(object):
a = 1
- assert isinstance(NotEmpty.__dict__, dict) == False
+ NotEmpty.a = 1
+ NotEmpty.a = 1
+ NotEmpty.a = 1
+ NotEmpty.a = 1
assert 'a' in NotEmpty.__dict__
assert 'a' in NotEmpty.__dict__.keys()
assert 'b' not in NotEmpty.__dict__
- assert isinstance(NotEmpty.__dict__.copy(), dict)
- assert NotEmpty.__dict__ == NotEmpty.__dict__.copy()
- try:
- NotEmpty.__dict__['b'] = 1
- except:
- pass
- else:
- raise AssertionError, 'this should not have been writable'
+ NotEmpty.__dict__['b'] = 4
+ assert NotEmpty.b == 4
+ del NotEmpty.__dict__['b']
+ assert NotEmpty.__dict__.get("b") is None
+ raises(TypeError, 'NotEmpty.__dict__[15] = "y"')
+ raises(KeyError, 'del NotEmpty.__dict__[15]')
+ assert NotEmpty.__dict__.setdefault("string", 1) == 1
+ assert NotEmpty.__dict__.setdefault("string", 2) == 1
+ assert NotEmpty.string == 1
+ raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)')
def test_dictproxyeq(self):
class a(object):
@@ -33,7 +38,13 @@
def test_str_repr(self):
class a(object):
pass
- s = repr(a.__dict__)
- assert s.startswith('<dictproxy') and s.endswith('>')
- s = str(a.__dict__)
- assert s.startswith('{') and s.endswith('}')
+ s1 = repr(a.__dict__)
+ s2 = str(a.__dict__)
+ assert s1 == s2
+ assert s1.startswith('{') and s1.endswith('}')
+
+class AppTestUserObjectMethodCache(AppTestUserObject):
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.withmethodcachecounter": True})
+
diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py
--- a/pypy/objspace/std/test/test_setobject.py
+++ b/pypy/objspace/std/test/test_setobject.py
@@ -284,6 +284,18 @@
# All empty frozenset subclass instances should have different ids
assert len(set(map(id, efs))) == len(efs)
+ def test_subclass_union(self):
+ for base in [set, frozenset]:
+ class subset(base):
+ def __init__(self, *args):
+ self.x = args
+ s = subset([2])
+ assert s.x == ([2],)
+ t = s | base([5])
+ # obscure CPython behavior:
+ assert type(t) is subset
+ assert not hasattr(t, 'x')
+
def test_isdisjoint(self):
assert set([1,2,3]).isdisjoint(set([4,5,6]))
assert set([1,2,3]).isdisjoint(frozenset([4,5,6]))
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -787,12 +787,10 @@
def newtuple(self, l):
return tuple(l)
- def newdict(self, module=False, instance=False, classofinstance=None,
- from_strdict_shared=None):
+ def newdict(self, module=False, instance=False, classofinstance=None):
return W_DictMultiObject.allocate_and_init_instance(
self, module=module, instance=instance,
- classofinstance=classofinstance,
- from_strdict_shared=from_strdict_shared)
+ classofinstance=classofinstance)
def finditem_str(self, w_dict, s):
return w_dict.getitem_str(s) # assume it's a multidict
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -408,6 +408,13 @@
guard_op = old_loop.operations[old_index]
assert guard_op.is_guard()
guard_op.jump_target = new_loop
+ # check that the bridge's inputargs are of the correct number and
+ # kind for the guard
+ if guard_op.fail_args is not None:
+ argkinds = [v.concretetype for v in guard_op.fail_args if v]
+ else:
+ argkinds = []
+ assert argkinds == [v.concretetype for v in new_loop.inputargs]
# ------------------------------
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -1,15 +1,88 @@
from pypy.objspace.std.model import registerimplementation, W_Object
from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject, IteratorImplementation
+from pypy.objspace.std.typeobject import unwrap_cell
+from pypy.interpreter.error import OperationError
-def descr_get_dictproxy(space, w_obj):
- return W_DictProxyObject(w_obj.getdict(space))
-class W_DictProxyObject(W_Object):
- from pypy.objspace.std.dictproxytype import dictproxy_typedef as typedef
+class W_DictProxyObject(W_DictMultiObject):
+ def __init__(w_self, space, w_type):
+ W_DictMultiObject.__init__(w_self, space)
+ w_self.w_type = w_type
- def __init__(w_self, w_dict):
- w_self.w_dict = w_dict
+ def impl_getitem(self, w_lookup):
+ space = self.space
+ w_lookup_type = space.type(w_lookup)
+ if space.is_w(w_lookup_type, space.w_str):
+ return self.impl_getitem_str(space.str_w(w_lookup))
+ else:
+ return None
-registerimplementation(W_DictProxyObject)
+ def impl_getitem_str(self, lookup):
+ return self.w_type.getdictvalue(self.space, lookup)
-register_all(vars())
+ def impl_setitem(self, w_key, w_value):
+ space = self.space
+ if space.is_w(space.type(w_key), space.w_str):
+ self.impl_setitem_str(self.space.str_w(w_key), w_value)
+ else:
+ raise OperationError(space.w_TypeError, space.wrap("cannot add non-string keys to dict of a type"))
+
+ def impl_setitem_str(self, name, w_value):
+ self.w_type.setdictvalue(self.space, name, w_value)
+
+ def impl_setdefault(self, w_key, w_default):
+ space = self.space
+ w_result = self.impl_getitem(w_key)
+ if w_result is not None:
+ return w_result
+ self.impl_setitem(w_key, w_default)
+ return w_default
+
+ def impl_delitem(self, w_key):
+ space = self.space
+ w_key_type = space.type(w_key)
+ if space.is_w(w_key_type, space.w_str):
+ if not self.w_type.deldictvalue(space, w_key):
+ raise KeyError
+ else:
+ raise KeyError
+
+ def impl_length(self):
+ return len(self.w_type.dict_w)
+
+ def impl_iter(self):
+ return DictProxyIteratorImplementation(self.space, self)
+
+ def impl_keys(self):
+ space = self.space
+ return [space.wrap(key) for key in self.w_type.dict_w.iterkeys()]
+
+ def impl_values(self):
+ return [unwrap_cell(self.space, w_value) for w_value in self.w_type.dict_w.itervalues()]
+
+ def impl_items(self):
+ space = self.space
+ return [space.newtuple([space.wrap(key), unwrap_cell(self.space, w_value)])
+ for (key, w_value) in self.w_type.dict_w.iteritems()]
+
+ def impl_clear(self):
+ self.w_type.dict_w.clear()
+ self.w_type.mutated()
+
+ def _as_rdict(self):
+ assert 0, "should be unreachable"
+
+ def _clear_fields(self):
+ assert 0, "should be unreachable"
+
+class DictProxyIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, dictimplementation):
+ IteratorImplementation.__init__(self, space, dictimplementation)
+ self.iterator = dictimplementation.w_type.dict_w.iteritems()
+
+ def next_entry(self):
+ for key, w_value in self.iterator:
+ return (self.space.wrap(key), unwrap_cell(self.space, w_value))
+ else:
+ return (None, None)
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -310,7 +310,7 @@
def ne__Set_settypedef(space, w_left, w_other):
rd = make_setdata_from_w_iterable(space, w_other)
- return space.wrap(_is_eq(w_left.setdata, rd))
+ return space.wrap(not _is_eq(w_left.setdata, rd))
ne__Set_frozensettypedef = ne__Set_settypedef
ne__Frozenset_settypedef = ne__Set_settypedef
diff --git a/pypy/objspace/std/dictproxytype.py b/pypy/objspace/std/dictproxytype.py
deleted file mode 100644
--- a/pypy/objspace/std/dictproxytype.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from pypy.interpreter import gateway
-from pypy.interpreter.typedef import GetSetProperty
-from pypy.interpreter.error import OperationError
-from pypy.objspace.std.stdtypedef import StdTypeDef
-
-# ____________________________________________________________
-
-def _proxymethod(name):
- def fget(space, w_obj):
- from pypy.objspace.std.dictproxyobject import W_DictProxyObject
- if not isinstance(w_obj, W_DictProxyObject):
- raise OperationError(space.w_TypeError,
- space.wrap("expected dictproxy"))
- return space.getattr(w_obj.w_dict, space.wrap(name))
- return GetSetProperty(fget)
-
-def _compareproxymethod(opname):
- def compare(space, w_obj1, w_obj2):
- from pypy.objspace.std.dictproxyobject import W_DictProxyObject
- if not isinstance(w_obj1, W_DictProxyObject):
- raise OperationError(space.w_TypeError,
- space.wrap("expected dictproxy"))
- return getattr(space, opname)(w_obj1.w_dict, w_obj2)
- compare.func_name = "dictproxy_compare_%s" % (opname, )
- return gateway.interp2app(compare)
-
-# ____________________________________________________________
-
-dictproxy_typedef = StdTypeDef("dictproxy",
- has_key = _proxymethod('has_key'),
- get = _proxymethod('get'),
- keys = _proxymethod('keys'),
- values = _proxymethod('values'),
- items = _proxymethod('items'),
- iterkeys = _proxymethod('iterkeys'),
- itervalues = _proxymethod('itervalues'),
- iteritems = _proxymethod('iteritems'),
- copy = _proxymethod('copy'),
- __len__ = _proxymethod('__len__'),
- __getitem__ = _proxymethod('__getitem__'),
- __contains__ = _proxymethod('__contains__'),
- __str__ = _proxymethod('__str__'),
- __iter__ = _proxymethod('__iter__'),
- __lt__ = _compareproxymethod('lt'),
- __le__ = _compareproxymethod('le'),
- __eq__ = _compareproxymethod('eq'),
- __ne__ = _compareproxymethod('ne'),
- __gt__ = _compareproxymethod('gt'),
- __ge__ = _compareproxymethod('ge'),
-)
-dictproxy_typedef.registermethods(globals())
diff --git a/pypy/objspace/std/test/test_versionedtype.py b/pypy/objspace/std/test/test_versionedtype.py
--- a/pypy/objspace/std/test/test_versionedtype.py
+++ b/pypy/objspace/std/test/test_versionedtype.py
@@ -189,6 +189,30 @@
assert btag is atag
assert btag is not None
+ def test_version_tag_when_changing_a_lot(self):
+ space = self.space
+ w_x = space.wrap("x")
+ w_A, w_B, w_C = self.get_three_classes()
+ atag = w_A.version_tag()
+ space.setattr(w_A, w_x, space.newint(1))
+ assert w_A.version_tag() is not atag
+ assert space.int_w(space.getattr(w_A, w_x)) == 1
+
+ atag = w_A.version_tag()
+ space.setattr(w_A, w_x, space.newint(2))
+ assert w_A.version_tag() is not atag
+ assert space.int_w(space.getattr(w_A, w_x)) == 2
+
+ atag = w_A.version_tag()
+ space.setattr(w_A, w_x, space.newint(3))
+ assert w_A.version_tag() is atag
+ assert space.int_w(space.getattr(w_A, w_x)) == 3
+
+ space.setattr(w_A, w_x, space.newint(4))
+ assert w_A.version_tag() is atag
+ assert space.int_w(space.getattr(w_A, w_x)) == 4
+
+
class AppTestVersionedType(test_typeobject.AppTestTypeObject):
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withtypeversion": True})
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/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -4,15 +4,25 @@
from pypy.interpreter import gateway
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.typedef import weakref_descr
+from pypy.interpreter.baseobjspace import W_Root
from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member
from pypy.objspace.std.objecttype import object_typedef
-from pypy.objspace.std.dictproxyobject import W_DictProxyObject
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.objectmodel import current_object_addr_as_int, compute_hash
from pypy.rlib.jit import hint, purefunction_promote, we_are_jitted
from pypy.rlib.jit import purefunction, dont_look_inside, unroll_safe
from pypy.rlib.rarithmetic import intmask, r_uint
+class TypeCell(W_Root):
+ def __init__(self, w_value=None):
+ self.w_value = w_value
+
+def unwrap_cell(space, w_value):
+ if (space.config.objspace.std.withtypeversion and
+ isinstance(w_value, TypeCell)):
+ return w_value.w_value
+ return w_value
+
# from compiler/misc.py
MANGLE_LEN = 256 # magic constant from compile.c
@@ -211,6 +221,17 @@
return compute_C3_mro(w_self.space, w_self)
def getdictvalue(w_self, space, attr):
+ if space.config.objspace.std.withtypeversion:
+ version_tag = w_self.version_tag()
+ if version_tag is not None:
+ return unwrap_cell(
+ space,
+ w_self._pure_getdictvalue_no_unwrapping(
+ space, version_tag, attr))
+ w_value = w_self._getdictvalue_no_unwrapping(space, attr)
+ return unwrap_cell(space, w_value)
+
+ def _getdictvalue_no_unwrapping(w_self, space, attr):
w_value = w_self.dict_w.get(attr, None)
if w_self.lazyloaders and w_value is None:
if attr in w_self.lazyloaders:
@@ -225,6 +246,48 @@
return w_value
return w_value
+ @purefunction
+ def _pure_getdictvalue_no_unwrapping(w_self, space, version_tag, attr):
+ return w_self._getdictvalue_no_unwrapping(space, attr)
+
+ def setdictvalue(w_self, space, name, w_value):
+ if (not space.config.objspace.std.mutable_builtintypes
+ and not w_self.is_heaptype()):
+ msg = "can't set attributes on type object '%s'"
+ raise operationerrfmt(space.w_TypeError, msg, w_self.name)
+ if name == "__del__" and name not in w_self.dict_w:
+ msg = "a __del__ method added to an existing type will not be called"
+ space.warn(msg, space.w_RuntimeWarning)
+ if space.config.objspace.std.withtypeversion:
+ version_tag = w_self.version_tag()
+ if version_tag is not None:
+ w_curr = w_self._pure_getdictvalue_no_unwrapping(
+ space, version_tag, name)
+ if w_curr is not None:
+ if isinstance(w_curr, TypeCell):
+ w_curr.w_value = w_value
+ return True
+ w_value = TypeCell(w_value)
+ w_self.mutated()
+ w_self.dict_w[name] = w_value
+ return True
+
+ def deldictvalue(w_self, space, w_key):
+ if w_self.lazyloaders:
+ w_self._freeze_() # force un-lazification
+ key = space.str_w(w_key)
+ if (not space.config.objspace.std.mutable_builtintypes
+ and not w_self.is_heaptype()):
+ msg = "can't delete attributes on type object '%s'"
+ raise operationerrfmt(space.w_TypeError, msg, w_self.name)
+ try:
+ del w_self.dict_w[key]
+ except KeyError:
+ return False
+ else:
+ w_self.mutated()
+ return True
+
def lookup(w_self, name):
# note that this doesn't call __get__ on the result at all
space = w_self.space
@@ -280,7 +343,7 @@
space = w_self.space
for w_class in w_self.mro_w:
assert isinstance(w_class, W_TypeObject)
- w_value = w_class.getdictvalue(space, key)
+ w_value = w_class._getdictvalue_no_unwrapping(space, key)
if w_value is not None:
return w_class, w_value
return None, None
@@ -293,7 +356,8 @@
if version_tag is None:
tup = w_self._lookup_where(name)
return tup
- return w_self._pure_lookup_where_with_method_cache(name, version_tag)
+ w_class, w_value = w_self._pure_lookup_where_with_method_cache(name, version_tag)
+ return w_class, unwrap_cell(space, w_value)
@purefunction
def _pure_lookup_where_with_method_cache(w_self, name, version_tag):
@@ -358,10 +422,10 @@
return False
def getdict(w_self, space): # returning a dict-proxy!
+ from pypy.objspace.std.dictproxyobject import W_DictProxyObject
if w_self.lazyloaders:
w_self._freeze_() # force un-lazification
- newdic = space.newdict(from_strdict_shared=w_self.dict_w)
- return W_DictProxyObject(newdic)
+ return W_DictProxyObject(space, w_self)
def unwrap(w_self, space):
if w_self.instancetypedef.fakedcpytype is not None:
@@ -395,15 +459,15 @@
def get_module(w_self):
space = w_self.space
if w_self.is_heaptype() and '__module__' in w_self.dict_w:
- return w_self.dict_w['__module__']
+ return w_self.getdictvalue(space, '__module__')
else:
# for non-heap types, CPython checks for a module.name in the
# type name. That's a hack, so we're allowed to use a different
# hack...
if ('__module__' in w_self.dict_w and
- space.is_true(space.isinstance(w_self.dict_w['__module__'],
+ space.is_true(space.isinstance(w_self.getdictvalue(space, '__module__'),
space.w_str))):
- return w_self.dict_w['__module__']
+ return w_self.getdictvalue(space, '__module__')
return space.wrap('__builtin__')
def get_module_type_name(w_self):
@@ -800,52 +864,9 @@
"type object '%s' has no attribute '%s'",
w_type.name, name)
-def setattr__Type_ANY_ANY(space, w_type, w_name, w_value):
- # Note. This is exactly the same thing as descroperation.descr__setattr__,
- # but it is needed at bootstrap to avoid a call to w_type.getdict() which
- # would un-lazify the whole type.
- name = space.str_w(w_name)
- w_descr = space.lookup(w_type, name)
- if w_descr is not None:
- if space.is_data_descr(w_descr):
- space.set(w_descr, w_type, w_value)
- return
-
- if (not space.config.objspace.std.mutable_builtintypes
- and not w_type.is_heaptype()):
- msg = "can't set attributes on type object '%s'"
- raise operationerrfmt(space.w_TypeError, msg, w_type.name)
- if name == "__del__" and name not in w_type.dict_w:
- msg = "a __del__ method added to an existing type will not be called"
- space.warn(msg, space.w_RuntimeWarning)
- w_type.mutated()
- w_type.dict_w[name] = w_value
-
def eq__Type_Type(space, w_self, w_other):
return space.is_(w_self, w_other)
-def delattr__Type_ANY(space, w_type, w_name):
- if w_type.lazyloaders:
- w_type._freeze_() # force un-lazification
- name = space.str_w(w_name)
- w_descr = space.lookup(w_type, name)
- if w_descr is not None:
- if space.is_data_descr(w_descr):
- space.delete(w_descr, w_type)
- return
- if (not space.config.objspace.std.mutable_builtintypes
- and not w_type.is_heaptype()):
- msg = "can't delete attributes on type object '%s'"
- raise operationerrfmt(space.w_TypeError, msg, w_type.name)
- try:
- del w_type.dict_w[name]
- except KeyError:
- raise OperationError(space.w_AttributeError, w_name)
- else:
- w_type.mutated()
- return
-
-
# ____________________________________________________________
diff --git a/pypy/objspace/std/test/test_methodcache.py b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -65,7 +65,7 @@
cache_counter = __pypy__.method_cache_counter("f")
# the cache hits come from A.f = ..., which first does a lookup on A as
# well
- assert cache_counter == (9, 11)
+ assert cache_counter == (17, 3)
def test_subclasses(self):
import __pypy__
@@ -148,3 +148,32 @@
assert cache_counter[0] >= 5
assert cache_counter[1] >= 1 # should be (27, 3)
assert sum(cache_counter) == 10
+
+ def test_mutate_class(self):
+ import __pypy__
+ class A(object):
+ x = 1
+ y = 2
+ __pypy__.reset_method_cache_counter()
+ a = A()
+ for i in range(100):
+ assert a.y == 2
+ assert a.x == i + 1
+ A.x += 1
+ cache_counter = __pypy__.method_cache_counter("x")
+ assert cache_counter[0] >= 350
+ assert cache_counter[1] >= 1
+ assert sum(cache_counter) == 400
+
+ __pypy__.reset_method_cache_counter()
+ a = A()
+ for i in range(100):
+ assert a.y == 2
+ setattr(a, "a%s" % i, i)
+ cache_counter = __pypy__.method_cache_counter("x")
+ assert cache_counter[0] == 0 # 0 hits, because all the attributes are new
+
+ def test_get_module_from_namedtuple(self):
+ # this used to crash
+ from collections import namedtuple
+ assert namedtuple("a", "b").__module__
diff --git a/pypy/objspace/std/typetype.py b/pypy/objspace/std/typetype.py
--- a/pypy/objspace/std/typetype.py
+++ b/pypy/objspace/std/typetype.py
@@ -207,38 +207,28 @@
def descr_set__module(space, w_type, w_value):
w_type = _check(space, w_type)
- if not w_type.is_heaptype():
- raise operationerrfmt(space.w_TypeError,
- "can't set %s.__module__",
- w_type.name)
- w_type.mutated()
- w_type.dict_w['__module__'] = w_value
+ w_type.setdictvalue(space, '__module__', w_value)
def descr_get___abstractmethods__(space, w_type):
w_type = _check(space, w_type)
# type itself has an __abstractmethods__ descriptor (this). Don't return it
if not space.is_w(w_type, space.w_type):
- try:
- return w_type.dict_w["__abstractmethods__"]
- except KeyError:
- pass
+ w_result = w_type.getdictvalue(space, "__abstractmethods__")
+ if w_result is not None:
+ return w_result
raise OperationError(space.w_AttributeError,
space.wrap("__abstractmethods__"))
def descr_set___abstractmethods__(space, w_type, w_new):
w_type = _check(space, w_type)
- w_type.dict_w["__abstractmethods__"] = w_new
- w_type.mutated()
+ w_type.setdictvalue(space, "__abstractmethods__", w_new)
w_type.set_abstract(space.is_true(w_new))
def descr_del___abstractmethods__(space, w_type):
w_type = _check(space, w_type)
- try:
- del w_type.dict_w["__abstractmethods__"]
- except KeyError:
+ if not w_type.deldictvalue(space, space.wrap("__abstractmethods__")):
raise OperationError(space.w_AttributeError,
space.wrap("__abstractmethods__"))
- w_type.mutated()
w_type.set_abstract(False)
def descr___subclasses__(space, w_type):
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/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -303,11 +303,10 @@
return W_ListObject(list_w)
def newdict(self, module=False, instance=False, classofinstance=None,
- from_strdict_shared=None, strdict=False):
+ strdict=False):
return W_DictMultiObject.allocate_and_init_instance(
self, module=module, instance=instance,
classofinstance=classofinstance,
- from_strdict_shared=from_strdict_shared,
strdict=strdict)
def newslice(self, w_start, w_end, w_step):
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/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
@@ -59,7 +59,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:
@@ -67,7 +68,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))
@@ -77,7 +79,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/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -111,6 +111,7 @@
del X.__abstractmethods__
X()
raises(AttributeError, getattr, type, "__abstractmethods__")
+ raises(TypeError, "int.__abstractmethods__ = ('abc', )")
def test_call_type(self):
assert type(42) is int
@@ -1015,6 +1016,25 @@
__weakref__ = 42
assert B().__weakref__ == 42
+ def test_change_dict(self):
+ class A(object):
+ pass
+
+ a = A()
+ A.x = 1
+ assert A.__dict__["x"] == 1
+ raises(AttributeError, "del A.__dict__")
+ raises((AttributeError, TypeError), "A.__dict__ = {}")
+
+ def test_mutate_dict(self):
+ class A(object):
+ pass
+
+ a = A()
+ A.x = 1
+ assert A.__dict__["x"] == 1
+ A.__dict__['x'] = 5
+ assert A.x == 5
class AppTestMutableBuiltintypes:
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/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
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):
More information about the Pypy-commit
mailing list