Author: Philip Jenvey <pjen...@underboss.org> 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 pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit