Author: Philip Jenvey <[email protected]>
Branch: py3k
Changeset: r65160:98718a061cac
Date: 2013-07-01 16:34 -0700
http://bitbucket.org/pypy/pypy/changeset/98718a061cac/
Log: merge default
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -132,7 +132,8 @@
_tls.main = gmain
_tls.current = gmain
-def _greenlet_start(greenlet, (args, kwds)):
+def _greenlet_start(greenlet, args):
+ args, kwds = args
_tls.current = greenlet
try:
res = greenlet.run(*args, **kwds)
diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst
--- a/pypy/doc/how-to-contribute.rst
+++ b/pypy/doc/how-to-contribute.rst
@@ -77,3 +77,4 @@
entry point.
.. _`introduction to RPython`: getting-started-dev.html
+.. _`pytest`: http://pytest.org/
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -65,3 +65,8 @@
.. branch: ndarray-view
Add view to ndarray and zeroD arrays, not on dtype scalars yet
+.. branch: identity-set
+Faster sets for objects
+
+.. branch: inline-identityhash
+Inline the fast path of id() and hash()
diff --git a/pypy/module/micronumpy/__init__.py
b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -184,6 +184,7 @@
appleveldefs = {}
interpleveldefs = {
'choose': 'interp_arrayops.choose',
+ 'put': 'interp_arrayops.put',
'repeat': 'interp_arrayops.repeat',
}
submodules = {
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py
b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -13,6 +13,9 @@
def next(self):
self.called_once = True
+ def next_skip_x(self, n):
+ self.called_once = True
+
def getitem(self):
return self.v.get_scalar_value()
diff --git a/pypy/module/micronumpy/interp_arrayops.py
b/pypy/module/micronumpy/interp_arrayops.py
--- a/pypy/module/micronumpy/interp_arrayops.py
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -192,6 +192,61 @@
loop.choose(space, arr, choices, shape, dtype, out, MODES[mode])
return out
+
+@unwrap_spec(mode=str)
+def put(space, w_arr, w_indices, w_values, mode='raise'):
+ from pypy.module.micronumpy import constants
+ from pypy.module.micronumpy.support import int_w
+
+ arr = convert_to_array(space, w_arr)
+
+ if mode not in constants.MODES:
+ raise OperationError(space.w_ValueError,
+ space.wrap("mode %s not known" % (mode,)))
+ if not w_indices:
+ raise OperationError(space.w_ValueError,
+ space.wrap("indice list cannot be empty"))
+ if not w_values:
+ raise OperationError(space.w_ValueError,
+ space.wrap("value list cannot be empty"))
+
+ dtype = arr.get_dtype()
+
+ if space.isinstance_w(w_indices, space.w_list):
+ indices = space.listview(w_indices)
+ else:
+ indices = [w_indices]
+
+ if space.isinstance_w(w_values, space.w_list):
+ values = space.listview(w_values)
+ else:
+ values = [w_values]
+
+ v_idx = 0
+ for idx in indices:
+ index = int_w(space, idx)
+
+ if index < 0 or index >= arr.get_size():
+ if constants.MODES[mode] == constants.MODE_RAISE:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "invalid entry in choice array"))
+ elif constants.MODES[mode] == constants.MODE_WRAP:
+ index = index % arr.get_size()
+ else:
+ assert constants.MODES[mode] == constants.MODE_CLIP
+ if index < 0:
+ index = 0
+ else:
+ index = arr.get_size() - 1
+
+ value = values[v_idx]
+
+ if v_idx + 1 < len(values):
+ v_idx += 1
+
+ arr.setitem(space, [index], dtype.coerce(space, value))
+
+
def diagonal(space, arr, offset, axis1, axis2):
shape = arr.get_shape()
shapelen = len(shape)
diff --git a/pypy/module/micronumpy/interp_numarray.py
b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -550,9 +550,10 @@
raise OperationError(space.w_NotImplementedError, space.wrap(
"ptp (peak to peak) not implemented yet"))
- def descr_put(self, space, w_indices, w_values, w_mode='raise'):
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "put not implemented yet"))
+ @unwrap_spec(mode=str)
+ def descr_put(self, space, w_indices, w_values, mode='raise'):
+ from pypy.module.micronumpy.interp_arrayops import put
+ put(space, self, w_indices, w_values, mode)
def descr_resize(self, space, w_new_shape, w_refcheck=True):
raise OperationError(space.w_NotImplementedError, space.wrap(
@@ -630,7 +631,7 @@
old_itemsize = self.get_dtype().get_size()
new_itemsize = dtype.get_size()
impl = self.implementation
- new_shape = self.get_shape()
+ new_shape = self.get_shape()[:]
dims = len(new_shape)
if dims == 0:
# Cannot resize scalars
@@ -989,6 +990,7 @@
prod = interp2app(W_NDimArray.descr_prod),
max = interp2app(W_NDimArray.descr_max),
min = interp2app(W_NDimArray.descr_min),
+ put = interp2app(W_NDimArray.descr_put),
argmax = interp2app(W_NDimArray.descr_argmax),
argmin = interp2app(W_NDimArray.descr_argmin),
all = interp2app(W_NDimArray.descr_all),
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -37,7 +37,7 @@
we can go faster.
All the calculations happen in next()
-next_skip_x() tries to do the iteration for a number of steps at once,
+next_skip_x(steps) tries to do the iteration for a number of steps at once,
but then we cannot gaurentee that we only overflow one single shape
dimension, perhaps we could overflow times in one big step.
"""
diff --git a/pypy/module/micronumpy/test/test_arrayops.py
b/pypy/module/micronumpy/test/test_arrayops.py
--- a/pypy/module/micronumpy/test/test_arrayops.py
+++ b/pypy/module/micronumpy/test/test_arrayops.py
@@ -132,3 +132,26 @@
x = array([0, 0, 0], dtype='i2')
r = array([2, 1, 0]).choose([a, b, c], out=x)
assert r.dtype == 'i2'
+
+ def test_put_basic(self):
+ from numpypy import arange, array
+ a = arange(5)
+ a.put([0, 2], [-44, -55])
+ assert (a == array([-44, 1, -55, 3, 4])).all()
+ a = arange(5)
+ a.put([3, 4], 9)
+ assert (a == array([0, 1, 2, 9, 9])).all()
+ a = arange(5)
+ a.put(1, [7, 8])
+ assert (a == array([0, 7, 2, 3, 4])).all()
+
+ def test_put_modes(self):
+ from numpypy import array, arange
+ a = arange(5)
+ a.put(22, -5, mode='clip')
+ assert (a == array([0, 1, 2, 3, -5])).all()
+ a = arange(5)
+ a.put(22, -5, mode='wrap')
+ assert (a == array([0, 1, -5, 3, 4])).all()
+ raises(ValueError, "arange(5).put(22, -5, mode='raise')")
+ raises(ValueError, "arange(5).put(22, -5, mode='wrongmode')")
diff --git a/pypy/module/micronumpy/test/test_iter.py
b/pypy/module/micronumpy/test/test_iter.py
--- a/pypy/module/micronumpy/test/test_iter.py
+++ b/pypy/module/micronumpy/test/test_iter.py
@@ -1,4 +1,5 @@
from pypy.module.micronumpy.iter import MultiDimViewIterator
+from pypy.module.micronumpy.arrayimpl.scalar import ScalarIterator
class MockArray(object):
size = 1
@@ -8,7 +9,7 @@
#Let's get started, simple iteration in C order with
#contiguous layout => strides[-1] is 1
start = 0
- shape = [3, 5]
+ shape = [3, 5]
strides = [5, 1]
backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
assert backstrides == [10, 4]
@@ -47,7 +48,7 @@
#iteration in C order with #contiguous layout => strides[-1] is 1
#skip less than the shape
start = 0
- shape = [3, 5]
+ shape = [3, 5]
strides = [5, 1]
backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
assert backstrides == [10, 4]
@@ -89,3 +90,9 @@
assert i.indexes == [0,1]
assert i.offset == 3
assert i.done()
+
+ def test_scalar_iter(self):
+ i = ScalarIterator(MockArray)
+ i.next()
+ i.next_skip_x(3)
+ assert i.done()
diff --git a/pypy/module/micronumpy/test/test_numarray.py
b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1411,16 +1411,17 @@
assert a[3].imag == -10
assert a[2].imag == -5
- def test_ndarray_view(self):
+ def test_view(self):
from numpypy import array, int8, int16, dtype
- x = array([(1, 2)], dtype=[('a', int8), ('b', int8)])
+ x = array((1, 2), dtype=int8)
+ assert x.shape == (2,)
y = x.view(dtype=int16)
- print y,y.shape
+ assert x.shape == (2,)
assert y[0] == 513
assert y.dtype == dtype('int16')
y[0] = 670
- assert x['a'] == -98
- assert x['b'] == 2
+ assert x[0] == -98
+ assert x[1] == 2
f = array([1000, -1234], dtype='i4')
nnp = self.non_native_prefix
d = f.view(dtype=nnp + 'i4')
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py
b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -201,10 +201,27 @@
def main(n):
i = 0
while i < n:
- s = set([1,2,3])
+ s = set([1, 2, 3])
i += 1
log = self.run(main, [1000])
assert log.result == main(1000)
loop, = log.loops_by_filename(self.filepath)
opnames = log.opnames(loop.allops())
assert opnames.count('new_with_vtable') == 0
+
+ def test_specialised_tuple(self):
+ def main(n):
+ import pypyjit
+
+ f = lambda: None
+ tup = (n, n)
+ while n > 0:
+ tup[0] # ID: getitem
+ pypyjit.residual_call(f)
+ n -= 1
+
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ ops = loop.ops_by_id('getitem')
+ assert log.opnames(ops) == []
diff --git a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py
b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py
--- a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py
+++ b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py
@@ -32,14 +32,6 @@
return d
-def test_syslog():
- try:
- import lib_pypy.syslog
- except ImportError:
- py.test.skip('no syslog on this platform')
- d = run('syslog.ctc.py', '_syslog_cache.py')
- assert 'LOG_NOTICE' in d
-
def test_resource():
try:
import lib_pypy.resource
diff --git a/pypy/module/test_lib_pypy/test_grp_extra.py
b/pypy/module/test_lib_pypy/test_grp_extra.py
--- a/pypy/module/test_lib_pypy/test_grp_extra.py
+++ b/pypy/module/test_lib_pypy/test_grp_extra.py
@@ -7,7 +7,7 @@
def test_basic():
g = grp.getgrnam("root")
assert g.gr_gid == 0
- assert g.gr_mem == ['root']
+ assert g.gr_mem == ['root'] or g.gr_mem == []
assert g.gr_name == 'root'
assert isinstance(g.gr_passwd, str) # usually just 'x', don't hope :-)
diff --git a/pypy/module/test_lib_pypy/test_syslog.py
b/pypy/module/test_lib_pypy/test_syslog.py
--- a/pypy/module/test_lib_pypy/test_syslog.py
+++ b/pypy/module/test_lib_pypy/test_syslog.py
@@ -1,8 +1,12 @@
-import py
+import sys, py
try:
from lib_pypy import syslog
except ImportError:
py.test.skip('no syslog on this platform')
+except AssertionError:
+ if '__pypy__' in sys.builtin_module_names:
+ raise
+ py.test.skip('AssertionError during import (wrong cffi version?)')
# XXX very minimal test
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
@@ -26,7 +26,7 @@
def __repr__(self):
"""representation for debugging purposes"""
reprlist = [repr(w_item) for w_item in self.getkeys()]
- return "<%s(%s)>" % (self.__class__.__name__, ', '.join(reprlist))
+ return "<%s(%s)(%s)>" % (self.__class__.__name__, self.strategy, ',
'.join(reprlist))
def from_storage_and_strategy(self, storage, strategy):
obj = self._newobj(self.space, None)
@@ -759,6 +759,8 @@
strategy = self.space.fromcache(StringSetStrategy)
elif type(w_key) is W_UnicodeObject:
strategy = self.space.fromcache(UnicodeSetStrategy)
+ elif self.space.type(w_key).compares_by_identity():
+ strategy = self.space.fromcache(IdentitySetStrategy)
else:
strategy = self.space.fromcache(ObjectSetStrategy)
w_set.strategy = strategy
@@ -918,6 +920,13 @@
def equals(self, w_set, w_other):
if w_set.length() != w_other.length():
return False
+ if w_set.length() == 0:
+ return True
+ # it's possible to have 0-lenght strategy that's not empty
+ if w_set.strategy is w_other.strategy:
+ return self._issubset_unwrapped(w_set, w_other)
+ if not self.may_contain_equal_elements(w_other.strategy):
+ return False
items = self.unerase(w_set.sstorage).keys()
for key in items:
if not w_other.has_key(self.wrap(key)):
@@ -1187,7 +1196,9 @@
def may_contain_equal_elements(self, strategy):
if strategy is self.space.fromcache(IntegerSetStrategy):
return False
- if strategy is self.space.fromcache(EmptySetStrategy):
+ elif strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ elif strategy is self.space.fromcache(IdentitySetStrategy):
return False
return True
@@ -1221,7 +1232,9 @@
def may_contain_equal_elements(self, strategy):
if strategy is self.space.fromcache(IntegerSetStrategy):
return False
- if strategy is self.space.fromcache(EmptySetStrategy):
+ elif strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ elif strategy is self.space.fromcache(IdentitySetStrategy):
return False
return True
@@ -1255,9 +1268,11 @@
def may_contain_equal_elements(self, strategy):
if strategy is self.space.fromcache(UnicodeSetStrategy):
return False
- if strategy is self.space.fromcache(UnicodeSetStrategy):
+ elif strategy is self.space.fromcache(UnicodeSetStrategy):
return False
- if strategy is self.space.fromcache(EmptySetStrategy):
+ elif strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ elif strategy is self.space.fromcache(IdentitySetStrategy):
return False
return True
@@ -1315,6 +1330,41 @@
break
d_obj[w_item] = None
+class IdentitySetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+ erase, unerase = rerased.new_erasing_pair("identityset")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def get_empty_storage(self):
+ return self.erase({})
+
+ def get_empty_dict(self):
+ return {}
+
+ def is_correct_type(self, w_key):
+ w_type = self.space.type(w_key)
+ return w_type.compares_by_identity()
+
+ def may_contain_equal_elements(self, strategy):
+ #empty first, probably more likely
+ if strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ if strategy is self.space.fromcache(IntegerSetStrategy):
+ return False
+ if strategy is self.space.fromcache(StringSetStrategy):
+ return False
+ if strategy is self.space.fromcache(UnicodeSetStrategy):
+ return False
+ return True
+
+ def unwrap(self, w_item):
+ return w_item
+
+ def wrap(self, item):
+ return item
+
+ def iter(self, w_set):
+ return IdentityIteratorImplementation(self.space, self, w_set)
class IteratorImplementation(object):
def __init__(self, space, strategy, implementation):
@@ -1406,6 +1456,17 @@
else:
return None
+class IdentityIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, strategy, w_set):
+ IteratorImplementation.__init__(self, space, strategy, w_set)
+ d = strategy.unerase(w_set.sstorage)
+ self.iterator = d.iterkeys()
+
+ def next_entry(self):
+ for key in self.iterator:
+ return self.space.wrap(key)
+ else:
+ return None
class RDictIteratorImplementation(IteratorImplementation):
def __init__(self, space, strategy, w_set):
@@ -1525,6 +1586,15 @@
w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
return
+ # check for compares by identity
+ for w_item in iterable_w:
+ if not space.type(w_item).compares_by_identity():
+ break
+ else:
+ w_set.strategy = space.fromcache(IdentitySetStrategy)
+ w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
+ return
+
w_set.strategy = space.fromcache(ObjectSetStrategy)
w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
diff --git a/pypy/objspace/std/specialisedtupleobject.py
b/pypy/objspace/std/specialisedtupleobject.py
--- a/pypy/objspace/std/specialisedtupleobject.py
+++ b/pypy/objspace/std/specialisedtupleobject.py
@@ -18,6 +18,8 @@
iter_n = unrolling_iterable(range(typelen))
class cls(W_AbstractTupleObject):
+ _immutable_fields_ = ['value%s' % i for i in iter_n]
+
def __init__(self, space, *values_w):
self.space = space
assert len(values_w) == typelen
diff --git a/pypy/objspace/std/test/test_identityset.py
b/pypy/objspace/std/test/test_identityset.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_identityset.py
@@ -0,0 +1,205 @@
+import py
+
+
+class AppTestIdentitySet(object):
+
+ # needed for compares_by_identity
+ spaceconfig = {"objspace.std.withidentitydict": True}
+
+ def setup_class(cls):
+ from pypy.objspace.std import identitydict
+ if cls.runappdirect:
+ py.test.skip("interp2app doesn't work on appdirect")
+
+ def w_uses_strategy(self, s , obj):
+ import __pypy__
+ return s in __pypy__.internal_repr(obj)
+
+ def test_use_identity_strategy(self):
+
+ class Plain(object):
+ pass
+
+ class CustomEq(object):
+ def __eq__(self, other):
+ return True
+
+ class CustomCmp (object):
+ def __cmp__(self, other):
+ return 0
+
+ class CustomHash(object):
+ def __hash__(self):
+ return 0
+
+ s = set()
+
+ assert not self.uses_strategy('IdentitySetStrategy',s)
+
+ s.add(Plain())
+
+ assert self.uses_strategy('IdentitySetStrategy',s)
+
+ for cls in [CustomEq,CustomCmp,CustomHash]:
+ s = set()
+ s.add(cls())
+ assert not self.uses_strategy('IdentitySetStrategy',s)
+
+
+ def test_use_identity_strategy_list(self):
+
+ class X(object):
+ pass
+
+ assert self.uses_strategy('IdentitySetStrategy',set([X(),X()]))
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),""]))
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),u""]))
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),1]))
+
+ def test_identity_strategy_add(self):
+
+ class X(object):
+ pass
+
+ class NotIdent(object):
+ def __eq__(self,other):
+ pass
+
+ s = set([X(),X()])
+ s.add('foo')
+ assert not self.uses_strategy('IdentitySetStrategy',s)
+ s = set([X(),X()])
+ s.add(NotIdent())
+ assert not self.uses_strategy('IdentitySetStrategy',s)
+
+ def test_identity_strategy_sanity(self):
+
+ class X(object):
+ pass
+
+ class Y(object):
+ pass
+
+ a,b,c,d,e,f = X(),Y(),X(),Y(),X(),Y()
+
+ s = set([a,b]).union(set([c]))
+ assert self.uses_strategy('IdentitySetStrategy',s)
+ assert set([a,b,c]) == s
+ s = set([a,b,c,d,e,f]) - set([d,e,f])
+ assert self.uses_strategy('IdentitySetStrategy',s)
+ assert set([a,b,c]) == s
+
+
+ s = set([a])
+ s.update([b,c])
+
+ assert s == set([a,b,c])
+
+
+ def test_identity_strategy_iterators(self):
+
+ class X(object):
+ pass
+
+ s = set([X() for i in range(10)])
+ counter = 0
+ for item in s:
+ counter += 1
+ assert item in s
+
+ assert counter == 10
+
+
+ def test_identity_strategy_other_cmp(self):
+
+ # test tries to hit positive and negative in
+ # may_contain_equal_elements
+
+ class X(object):
+ pass
+
+ s = set([X() for i in range(10)])
+
+ assert s.intersection(set([1,2,3])) == set()
+ assert s.intersection(set(['a','b','c'])) == set()
+ assert s.intersection(set(['a','b','c'])) == set()
+ assert s.intersection(set([X(),X()])) == set()
+
+ other = set(['a','b','c',s.__iter__().next()])
+ intersect = s.intersection(other)
+ assert len(intersect) == 1
+ assert intersect.__iter__().next() in s
+ assert intersect.__iter__().next() in other
+
+ def test_class_monkey_patch(self):
+
+ class X(object):
+ pass
+
+ s = set()
+
+ s.add(X())
+ assert self.uses_strategy('IdentitySetStrategy',s)
+ X.__eq__ = lambda self,other : None
+ s.add(X())
+ assert not self.uses_strategy('IdentitySetStrategy',s)
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),X()]))
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),""]))
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),u""]))
+ assert not self.uses_strategy('IdentitySetStrategy',set([X(),1]))
+
+ # An interesting case, add an instance, mutate the class,
+ # then add the same instance.
+
+ class X(object):
+ pass
+
+ s = set()
+ inst = X()
+ s.add(inst)
+ X.__eq__ = lambda x,y : x is y
+ s.add(inst)
+
+ assert len(s) == 1
+ assert s.__iter__().next() is inst
+ assert not self.uses_strategy('IdentitySetStrategy',s)
+
+
+ # Add instance, mutate class, check membership of that instance.
+
+ class X(object):
+ pass
+
+
+ inst = X()
+ s = set()
+ s.add(inst)
+ X.__eq__ = lambda x,y : x is y
+ assert inst in s
+
+ # Test Wrong strategy
+ # If the strategy is changed by mutation, but the instance
+ # does not change, then this tests the methods that call
+ # may_contain_equal_elements still function.
+ # i.e. same instance in two sets, one with object strategy, one with
+ # identity strategy.
+
+ class X(object):
+ pass
+
+
+ inst = X()
+ s1 = set()
+ s1.add(inst)
+ assert self.uses_strategy('IdentitySetStrategy',s1)
+ X.__eq__ = lambda x,y : x is y
+ s2 = set()
+ s2.add(inst)
+ assert not self.uses_strategy('IdentitySetStrategy',s2)
+
+ assert s1.intersection(s2) == set([inst])
+ assert (s1 - s2) == set()
+ assert (s2 - s1) == set()
+
+ s1.difference_update(s2)
+ assert s1 == set()
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -57,8 +57,8 @@
from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
from rpython.rlib.rarithmetic import LONG_BIT_SHIFT
from rpython.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
-from rpython.rlib.objectmodel import we_are_translated
-from rpython.tool.sourcetools import func_with_new_name
+from rpython.rlib.objectmodel import specialize
+
#
# Handles the objects in 2 generations:
@@ -1824,6 +1824,48 @@
# ----------
# id() and identityhash() support
+ def _allocate_shadow(self, obj):
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ size = self.get_size(obj)
+ shadowhdr = self._malloc_out_of_nursery(size_gc_header +
+ size)
+ # Initialize the shadow enough to be considered a
+ # valid gc object. If the original object stays
+ # alive at the next minor collection, it will anyway
+ # be copied over the shadow and overwrite the
+ # following fields. But if the object dies, then
+ # the shadow will stay around and only be freed at
+ # the next major collection, at which point we want
+ # it to look valid (but ready to be freed).
+ shadow = shadowhdr + size_gc_header
+ self.header(shadow).tid = self.header(obj).tid
+ typeid = self.get_type_id(obj)
+ if self.is_varsize(typeid):
+ lenofs = self.varsize_offset_to_length(typeid)
+ (shadow + lenofs).signed[0] = (obj + lenofs).signed[0]
+ #
+ self.header(obj).tid |= GCFLAG_HAS_SHADOW
+ self.nursery_objects_shadows.setitem(obj, shadow)
+ return shadow
+
+ def _find_shadow(self, obj):
+ #
+ # The object is not a tagged pointer, and it is still in the
+ # nursery. Find or allocate a "shadow" object, which is
+ # where the object will be moved by the next minor
+ # collection
+ if self.header(obj).tid & GCFLAG_HAS_SHADOW:
+ shadow = self.nursery_objects_shadows.get(obj)
+ ll_assert(shadow != NULL,
+ "GCFLAG_HAS_SHADOW but no shadow found")
+ else:
+ shadow = self._allocate_shadow(obj)
+ #
+ # The answer is the address of the shadow.
+ return shadow
+ _find_shadow._dont_inline_ = True
+
+ @specialize.arg(2)
def id_or_identityhash(self, gcobj, is_hash):
"""Implement the common logic of id() and identityhash()
of an object, given as a GCREF.
@@ -1832,41 +1874,7 @@
#
if self.is_valid_gc_object(obj):
if self.is_in_nursery(obj):
- #
- # The object is not a tagged pointer, and it is still in the
- # nursery. Find or allocate a "shadow" object, which is
- # where the object will be moved by the next minor
- # collection
- if self.header(obj).tid & GCFLAG_HAS_SHADOW:
- shadow = self.nursery_objects_shadows.get(obj)
- ll_assert(shadow != NULL,
- "GCFLAG_HAS_SHADOW but no shadow found")
- else:
- size_gc_header = self.gcheaderbuilder.size_gc_header
- size = self.get_size(obj)
- shadowhdr = self._malloc_out_of_nursery(size_gc_header +
- size)
- # Initialize the shadow enough to be considered a
- # valid gc object. If the original object stays
- # alive at the next minor collection, it will anyway
- # be copied over the shadow and overwrite the
- # following fields. But if the object dies, then
- # the shadow will stay around and only be freed at
- # the next major collection, at which point we want
- # it to look valid (but ready to be freed).
- shadow = shadowhdr + size_gc_header
- self.header(shadow).tid = self.header(obj).tid
- typeid = self.get_type_id(obj)
- if self.is_varsize(typeid):
- lenofs = self.varsize_offset_to_length(typeid)
- (shadow + lenofs).signed[0] = (obj + lenofs).signed[0]
- #
- self.header(obj).tid |= GCFLAG_HAS_SHADOW
- self.nursery_objects_shadows.setitem(obj, shadow)
- #
- # The answer is the address of the shadow.
- obj = shadow
- #
+ obj = self._find_shadow(obj)
elif is_hash:
if self.header(obj).tid & GCFLAG_HAS_SHADOW:
#
@@ -1884,6 +1892,7 @@
if is_hash:
i = mangle_hash(i)
return i
+ id_or_identityhash._always_inline_ = True
def id(self, gcobj):
return self.id_or_identityhash(gcobj, False)
diff --git a/rpython/memory/gctransform/framework.py
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -424,7 +424,7 @@
self.identityhash_ptr = getfn(GCClass.identityhash.im_func,
[s_gc, s_gcref],
annmodel.SomeInteger(),
- minimal_transform=False)
+ minimal_transform=False, inline=True)
if getattr(GCClass, 'obtain_free_space', False):
self.obtainfreespace_ptr = getfn(GCClass.obtain_free_space.im_func,
[s_gc, annmodel.SomeInteger()],
@@ -433,7 +433,7 @@
if GCClass.moving_gc:
self.id_ptr = getfn(GCClass.id.im_func,
[s_gc, s_gcref], annmodel.SomeInteger(),
- inline = False,
+ inline = True,
minimal_transform = False)
else:
self.id_ptr = None
diff --git a/rpython/translator/platform/arm.py
b/rpython/translator/platform/arm.py
--- a/rpython/translator/platform/arm.py
+++ b/rpython/translator/platform/arm.py
@@ -17,6 +17,7 @@
class ARM(Linux):
name = "arm"
+ shared_only = ('-fPIC',)
available_librarydirs = [SB2 + '/lib/arm-linux-gnueabi/',
SB2 + '/lib/arm-linux-gnueabihf/',
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit